def github(update: Update, context: CallbackContext): message = update.message or update.edited_message last = 0 thing_matches = [] things = {} # Due to bug in ptb we need to convert entities of type URL to TEXT_LINK for them to be converted to html for entity in message.entities: if entity.type == MessageEntity.URL: entity.type = MessageEntity.TEXT_LINK entity.url = message.parse_entity(entity) for match in GITHUB_PATTERN.finditer(get_text_not_in_entities(message.text_html)): logging.debug(match.groupdict()) owner, repo, number, sha = [match.groupdict()[x] for x in ('owner', 'repo', 'number', 'sha')] if number or sha: thing_matches.append((owner, repo, number, sha)) for thing_match in thing_matches: last = keep_typing(last, update.effective_chat, ChatAction.TYPING) owner, repo, number, sha = thing_match if number: issue = github_issues.get_issue(int(number), owner, repo) things[issue.url] = github_issues.pretty_format_issue(issue) elif sha: commit = github_issues.get_commit(sha, owner, repo) things[commit.url] = github_issues.pretty_format_commit(commit) if things: reply_or_edit(update, context, '\n'.join([f'<a href="{url}">{name}</a>' for url, name in things.items()]))
def github(update: Update, context: CallbackContext): message = update.message or update.edited_message last = 0 thing_matches = [] things = {} # Due to bug in ptb we need to convert entities of type URL to TEXT_LINK for them to be converted to html for entity in message.entities: if entity.type == MessageEntity.URL: entity.type = MessageEntity.TEXT_LINK entity.url = message.parse_entity(entity) for match in GITHUB_PATTERN.finditer(get_text_not_in_entities(message.text_html)): logging.debug(match.groupdict()) owner, repo, number, sha = [match.groupdict()[x] for x in ('owner', 'repo', 'number', 'sha')] if number or sha: thing_matches.append((owner, repo, number, sha)) for thing_match in thing_matches: last = keep_typing(last, update.effective_chat, ChatAction.TYPING) owner, repo, number, sha = thing_match if number: issue = github_issues.get_issue(int(number), owner, repo) things[issue.url] = github_issues.pretty_format_issue(issue) elif sha: commit = github_issues.get_commit(sha, owner, repo) things[commit.url] = github_issues.pretty_format_commit(commit) if things: reply_or_edit(update, context, '\n'.join([f'[{name}]({url})' for url, name in things.items()]))
def github(bot, update, chat_data): message = update.message or update.edited_message last = 0 things = {} for entity in message.entities: if entity.type == MessageEntity.URL: entity.type = MessageEntity.TEXT_LINK entity.url = message.parse_entity(entity) for match in GITHUB_PATTERN.finditer(get_text_not_in_entities(message.text_html)): last = keep_typing(last, update.effective_chat, ChatAction.TYPING) logging.debug(match.groupdict()) owner, repo, number, sha = [match.groupdict()[x] for x in ('owner', 'repo', 'number', 'sha')] if number: issue = github_issues.get_issue(int(number), owner, repo) things[issue.url] = github_issues.pretty_format_issue(issue) elif sha: commit = github_issues.get_commit(sha, owner, repo) things[commit.url] = github_issues.pretty_format_commit(commit) if things: reply_or_edit(bot, update, chat_data, '\n'.join([f'[{name}]({url})' for url, name in things.items()]))
def inline_github(query): """ Parse query for issues, PRs and commits SHA Returns a list of `articles`. Examples: `#10` - [(title=Replace via GitHub, description=#10: tenth issue title)] `#10 #9` - [(title=Replace via GitHub, description=#10: tenth issue title, #9: ninth issue)] `@d6d0dec6e0e8b647d140dfb74db66ecb1d00a61d` - [(title=Replace via GitHub, description=@d6d0dec: commit title)] `#search` - [(title= 🔍 An issue with search in it's issue, description=#3: that issue), (title= 🔍 Another issue with search in it's issue, description=#2: that issue), ... (3 more)] `#10 #search` - [(title=An issue with search in it's issue, description=#10: tenth issue, #3: that issue), (title=Another issue with search in it's issue, description=#10: tenth issue, #2: that issue), ... (3 more)] `#search #10` - [(title= 🔍 An issue with search in it's issue, description=#3: that issue, #10: tenth issue), (title= 🔍 Another issue with search in it's issue, description=#2: that issue, #10, tenth issue), ... (3 more)] `#search1 #10 #search2` - [(title= 🔍 An issue with search2 in it's issue, description=#3: search1 result, #10: tenth issue, #5: search2 result1), (title= 🔍 Another issue with search2 in it's issue, description=#3: search1 result, #10, tenth issue, #6: search2 result2), ... (3 more)] """ # Issues/PRs/Commits things = OrderedDict() results = [] # Search for Issues, PRs and commits in the query and add them to things for match in GITHUB_PATTERN.finditer(query): owner, repo, number, sha, search_query, full = [ match.groupdict()[x] for x in ('owner', 'repo', 'number', 'sha', 'query', 'full') ] # If it's an issue if number: issue = github_issues.get_issue(int(number), owner, repo) things[full] = issue # If it's a commit elif sha: commit = github_issues.get_commit(sha, owner, repo) things[full] = commit # If it's a search elif search_query: search_results = github_issues.search(search_query) things['#' + search_query] = search_results if not things: # We didn't find anything return [] # Unwrap and collapse things last_search, choices = unwrap(things) # Loop over all the choices we should send to the client # Each choice (things) is a dict of things (issues/PRs/commits) to show in that choice # If not searching there will only be a single choice # If searching we have 5 different possibilities we wanna send for i, things in enumerate(choices): # If we did a search if last_search and last_search[i]: # Show the search title as the title title = '🔍' + github_issues.pretty_format( last_search[i], short_with_title=True, title_max_length=50) else: # Otherwise just use generic title title = 'Resolve via GitHub' # Description is the short formats combined with ', ' description = (', '.join( github_issues.pretty_format(thing, short_with_title=True) for thing in things.values())) # Truncate the description to 100 chars, from the left side. # So the last thing will always be shown. if len(description) > 100: description = '⟻' + description[-99:].partition(',')[2] # The text that will be sent when user clicks the choice/result text = '' pattern = r'|'.join( re.escape(thing) for thing in sorted(things.keys(), key=len, reverse=True)) # Check if there's other stuff than issues/PRs etc. in the query by # removing issues/PRs etc. and seeing if there's anything left if re.sub(pattern, '', query).strip(): # Replace every 'thing' with a link to said thing *all at once* # Needs to all at once because otherwise 'blah/blah#2 #2' # would break would turn into something like # [blah/blah[#2](LinkFor#2)](LinkForblah/blah[#2](LinkFor#2)) # which isn't even valid markdown text = re.sub( pattern, lambda x: f'<a href="{things[x.group(0)].url}">' f'{github_issues.pretty_format(things[x.group(0)], short=True)}</a>', query) # Add full format to bottom of message text += '\n\n' + '\n'.join( f'<a href="{thing.url}">{github_issues.pretty_format(thing)}</a>' for thing in things.values()) results.append( article(title=title, description=description, message_text=text)) return results
def inline_github(query): """ Parse query for issues, PRs and commits SHA Returns a list of `articles`. Examples: `#10` - [(title=Replace via GitHub, description=#10: tenth issue title)] `#10 #9` - [(title=Replace via GitHub, description=#10: tenth issue title, #9: ninth issue)] `@d6d0dec6e0e8b647d140dfb74db66ecb1d00a61d` - [(title=Replace via GitHub, description=@d6d0dec: commit title)] `#search` - [(title= 🔍 An issue with search in it's issue, description=#3: that issue), (title= 🔍 Another issue with search in it's issue, description=#2: that issue), ... (3 more)] `#10 #search` - [(title=An issue with search in it's issue, description=#10: tenth issue, #3: that issue), (title=Another issue with search in it's issue, description=#10: tenth issue, #2: that issue), ... (3 more)] `#search #10` - [(title= 🔍 An issue with search in it's issue, description=#3: that issue, #10: tenth issue), (title= 🔍 Another issue with search in it's issue, description=#2: that issue, #10, tenth issue), ... (3 more)] `#search1 #10 #search2` - [(title= 🔍 An issue with search2 in it's issue, description=#3: search1 result, #10: tenth issue, #5: search2 result1), (title= 🔍 Another issue with search2 in it's issue, description=#3: search1 result, #10, tenth issue, #6: search2 result2), ... (3 more)] """ # Issues/PRs/Commits things = OrderedDict() results = [] # Search for Issues, PRs and commits in the query and add them to things for match in GITHUB_PATTERN.finditer(query): owner, repo, number, sha, search_query, full = [match.groupdict()[x] for x in ('owner', 'repo', 'number', 'sha', 'query', 'full')] # If it's an issue if number: issue = github_issues.get_issue(int(number), owner, repo) things[full] = issue # If it's a commit elif sha: commit = github_issues.get_commit(sha, owner, repo) things[full] = commit # If it's a search elif search_query: search_results = github_issues.search(search_query) things['#' + search_query] = search_results if not things: # We didn't find anything return [] # Unwrap and collapse things last_search, choices = unwrap(things) # Loop over all the choices we should send to the client # Each choice (things) is a dict of things (issues/PRs/commits) to show in that choice # If not searching there will only be a single choice # If searching we have 5 different possibilities we wanna send for i, things in enumerate(choices): # If we did a search if last_search and last_search[i]: # Show the search title as the title title = '🔍' + github_issues.pretty_format(last_search[i], short_with_title=True, title_max_length=50) else: # Otherwise just use generic title title = 'Resolve via GitHub' # Description is the short formats combined with ', ' description = (', '.join(github_issues.pretty_format(thing, short_with_title=True) for thing in things.values())) # Truncate the description to 100 chars, from the left side. # So the last thing will always be shown. if len(description) > 100: description = '⟻' + description[-99:].partition(',')[2] # The text that will be sent when user clicks the choice/result text = '' pattern = r'|'.join(re.escape(thing) for thing in sorted(things.keys(), key=len, reverse=True)) # Check if there's other stuff than issues/PRs etc. in the query by # removing issues/PRs etc. and seeing if there's anything left if re.sub(pattern, '', query).strip(): # Replace every 'thing' with a link to said thing *all at once* # Needs to all at once because otherwise 'blah/blah#2 #2' # would break would turn into something like # [blah/blah[#2](LinkFor#2)](LinkForblah/blah[#2](LinkFor#2)) # which isn't even valid markdown text = re.sub(pattern, lambda x: f'[{github_issues.pretty_format(things[x.group(0)], short=True)}]' f'({things[x.group(0)].url})', query) # Add full format to bottom of message text += '\n\n' + '\n'.join(f'[{github_issues.pretty_format(thing)}]({thing.url})' for thing in things.values()) results.append(article(title=title, description=description, message_text=text)) return results