From b8b38bb1f746bad8248933d228a0269849c843a0 Mon Sep 17 00:00:00 2001 From: Rohitt Vashishtha Date: Sun, 11 Jun 2017 12:19:01 +0530 Subject: [PATCH] bots: Fix github details bot. --- bots/github_detail/__init__.py | 0 bots/github_detail/github_detail.md | 28 ---------- bots/github_detail/github_detail.py | 83 +++++++++++------------------ bots/github_detail/readme.md | 22 ++++++++ 4 files changed, 52 insertions(+), 81 deletions(-) create mode 100644 bots/github_detail/__init__.py delete mode 100644 bots/github_detail/github_detail.md create mode 100644 bots/github_detail/readme.md diff --git a/bots/github_detail/__init__.py b/bots/github_detail/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bots/github_detail/github_detail.md b/bots/github_detail/github_detail.md deleted file mode 100644 index 840052e..0000000 --- a/bots/github_detail/github_detail.md +++ /dev/null @@ -1,28 +0,0 @@ -# GitHub detail bot -This bot links and details issues and pull requests. -To use it username mention the bot then type an id: -Ids can be specified in three different forms: -- Id only: `#2000` -- Repository and id: `zulip#2000` -- Owner, repository and id `zulip/zulip#2000` - -Both the username mention and the id can occur at any time in the message. You -can also mention multiple ids in a single message. - -The bot *requires* a default owner and repository to be configured. -The configuration file should be located at `~/.contrib_bots/github_detail.ini`. -It should look like this: -```ini -[GitHub] -owner = -repo = -``` -If you don't want a default repository you can define one that doesn't exist, the bot -will fail silently. - -The bot won't reply to any other bots to avoid infinite loops. - -Zulip also has a realm feature which will show information about linked sites. -Because of this the bot escapes it's links. Once issue -[#2968](https://github.com/zulip/zulip/issues/2968) is resolved this can be -changed. diff --git a/bots/github_detail/github_detail.py b/bots/github_detail/github_detail.py index 8bc0fcc..c6e29c2 100644 --- a/bots/github_detail/github_detail.py +++ b/bots/github_detail/github_detail.py @@ -12,72 +12,50 @@ class GithubHandler(object): referenced in the chat. ''' - CONFIG_PATH = os.path.expanduser('~/.contrib_bots/github_detail.ini') GITHUB_ISSUE_URL_TEMPLATE = 'https://api.github.com/repos/{owner}/{repo}/issues/{id}' - GITHUB_PULL_URL_TEMPLATE = 'https://api.github.com/repos/{owner}/{repo}/pulls/{id}' HANDLE_MESSAGE_REGEX = re.compile("(?:([\w-]+)\/)?([\w-]+)?#(\d+)") - MAX_LENGTH_OF_MESSAGE = 200 - def __init__(self): - config = six.moves.configparser.ConfigParser() - with open(self.CONFIG_PATH) as config_file: - config.readfp(config_file) - if config.get('GitHub', 'owner'): - self.owner = config.get('GitHub', 'owner') - else: - # Allowing undefined default repos would require multiple triage_message regexs. - # It's simpler to require them to be defined. - sys.exit('Default owner not defined') - - if config.get('GitHub', 'repo'): - self.repo = config.get('GitHub', 'repo') - else: - sys.exit('Default repo not defined') + def initialize(self, bot_handler): + self.config_info = bot_handler.get_config_info('github_detail', optional=True) + self.owner = self.config_info.get("owner", False) + self.repo = self.config_info.get("repo", False) def usage(self): # type: () -> None return ("This plugin displays details on github issues and pull requests. " "To reference an issue or pull request usename mention the bot then " "anytime in the message type its id, for example:\n" - "@**Github detail** #3212 zulip/#3212 zulip/zulip#3212\n" + "@**Github detail** #3212 zulip#3212 zulip/zulip#3212\n" "The default owner is {} and the default repo is {}.".format(self.owner, self.repo)) - def triage_message(self, message, client): - # type: () -> bool - # Check the message contains a username mention, an issue idi - # or 'help', and that we're not replying to another bot. - regex = "(?:@(?:\*\*){}).+?(?:#\d+)|(?:help)".format(re.escape(client.full_name)) - return re.search(regex, message['content']) and not message['sender_email'].endswith('-bot@zulip.com') - def format_message(self, details): # type: (Dict[Text, Union[Text, int, bool]]) -> Text number = details['number'] title = details['title'] link = details['html_url'] - # Truncate if longer than 200 characters. - ellipsis = '...' + author = details['user']['login'] + owner = details['owner'] + repo = details['repo'] - if len(details['body']) > self.MAX_LENGTH_OF_MESSAGE + len(ellipsis): - description = "{}{}".format(details['body'][:self.MAX_LENGTH_OF_MESSAGE], ellipsis) - else: - description = details['body'] + description = details['body'] status = details['state'].title() - return '**[{id} | {title}]({link})** - **{status}**\n```quote\n{description}\n```'\ - .format(id=number, title=title, link=link, status=status, description=description) + message_string = ('**[{owner}/{repo}#{id}]'.format(owner=owner, repo=repo, id=number), + '({link}) - {title}**\n'.format(title=title, link=link), + 'Created by **[{author}](https://github.com/{author})**\n'.format(author=author), + 'Status - **{status}**\n```quote\n{description}\n```'.format(status=status, description=description)) + return ''.join(message_string) def get_details_from_github(self, owner, repo, number): # type: (Text, Text, Text) -> Dict[Text, Union[Text, Int, Bool]] # Gets the details of an issues or pull request - # Try to get an issue, try to get a pull if that fails try: r = requests.get( self.GITHUB_ISSUE_URL_TEMPLATE.format(owner=owner, repo=repo, id=number)) except requests.exceptions.RequestException as e: logging.exception(e) return - if r.status_code == 404: try: r = requests.get( @@ -85,10 +63,8 @@ class GithubHandler(object): except requests.exceptions.RequestException as e: logging.exception(e) return - if r.status_code != requests.codes.ok: return - return r.json() def get_owner_and_repo(self, issue_pr): @@ -100,11 +76,11 @@ class GithubHandler(object): repo = self.repo return (owner, repo) - def handle_message(self, message, client, state_handler): + def handle_message(self, message, bot_handler, state_handler): # type: () -> None # Send help message - if message['content'] == '@**{}** help'.format(client.full_name): - client.send_message(dict( + if message['content'] == '@**{}** help'.format(bot_handler.full_name): + bot_handler.send_message(dict( type='stream', to=message['display_recipient'], subject=message['subject'], @@ -114,22 +90,23 @@ class GithubHandler(object): # Capture owner, repo, id issue_prs = re.finditer( self.HANDLE_MESSAGE_REGEX, message['content']) - bot_messages = [] for issue_pr in issue_prs: owner, repo = self.get_owner_and_repo(issue_pr) - details = self.get_details_from_github(owner, repo, issue_pr.group(3)) - if details is not None: - bot_messages.append(self.format_message(details)) + if owner and repo: + details = self.get_details_from_github(owner, repo, issue_pr.group(3)) + if details is not None: + details['owner'] = owner + details['repo'] = repo + bot_messages.append(self.format_message(details)) + else: + bot_messages.append("Failed to find issue/pr: {owner}/{repo}#{id}" + .format(owner=owner, repo=repo, id=issue_pr.group(3))) else: - bot_messages.append("Failed to find issue/pr: {owner}/{repo}#{id}".format(owner=owner, repo=repo, id=issue_pr.group(3))) + bot_messages.append("Failed to detect owner and repository name.") + if len(bot_messages) == 0: + bot_messages.append("Failed to find any issue or PR.") bot_message = '\n'.join(bot_messages) - - client.send_message(dict( - type='stream', - to=message['display_recipient'], - subject=message['subject'], - content=bot_message, - )) + bot_handler.send_reply(message, bot_message) handler_class = GithubHandler diff --git a/bots/github_detail/readme.md b/bots/github_detail/readme.md new file mode 100644 index 0000000..35a7897 --- /dev/null +++ b/bots/github_detail/readme.md @@ -0,0 +1,22 @@ +# GitHub detail bot + +This bot links and details issues and pull requests. +To use it @-mention the bot then type an id: +Ids can be specified in three different forms: +- Id only: `#2000` +- Repository and id: `zulip#2000` +- Owner, repository and id `zulip/zulip#2000` + +The id can occur at any time in the message. You +can also mention multiple ids in a single message. For example: + +`@**GitHub Detail Bot** find me #5176 and zulip/zulip#4534 .` + +You can configure a default owner and repository. +The configuration file should be located at `api/bots/github_detail/github_detail.conf`. +It should look like this: +```ini +[github_detail] +owner = +repo = +```