bots: Fix github details bot.
ADD
bots/github_detail/__init__.py
bots/github_detail/__init__.py
DELETE
bots/github_detail/github_detail.md
-# 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 = <repository_owner>
-repo = <repository>
-```
-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.

MODIFY
bots/github_detail/github_detail.py
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']
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)
+ 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)))
+ 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 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

ADD
bots/github_detail/readme.md
+# 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 = <repository owner>
+repo = <repository name>
+```

bots: Fix github details bot.