Exemplo n.º 1
0
def reply_search(update: Update, context: CallbackContext) -> None:
    message = cast(Message, update.effective_message)
    last = 0.0
    thing_matches: List[Tuple[int, Tuple[str, str, str, str, str]]] = []
    things: List[Tuple[int, BaseEntry]] = []

    no_entity_text = get_text_not_in_entities(message).strip()

    # Parse exact matches for GitHub threads & ptbcontrib things first
    for match in GITHUB_PATTERN.finditer(no_entity_text):
        logging.debug(match.groupdict())
        owner, repo, number, sha, ptbcontrib = [
            cast(str,
                 match.groupdict()[x])
            for x in ("owner", "repo", "number", "sha", "ptbcontrib")
        ]
        if number or sha or ptbcontrib:
            thing_matches.append(
                (match.start(), (owner, repo, number, sha, ptbcontrib)))

    for thing_match in thing_matches:
        last = keep_typing(last, cast(Chat, update.effective_chat),
                           ChatAction.TYPING)
        owner, repo, number, sha, ptbcontrib = thing_match[1]
        if number:
            issue = github_issues.get_issue(int(number), owner, repo)
            if issue is not None:
                things.append((thing_match[0], issue))
        elif sha:
            commit = github_issues.get_commit(sha, owner, repo)
            if commit is not None:
                things.append((thing_match[0], commit))
        elif ptbcontrib:
            contrib = github_issues.ptbcontribs.get(ptbcontrib)
            if contrib:
                things.append((thing_match[0], contrib))

    # Parse fuzzy search next
    if no_entity_text.startswith("!search") or no_entity_text.endswith(
            "!search"):
        for match in ENCLOSED_REGEX.finditer(no_entity_text):
            last = keep_typing(last, cast(Chat, update.effective_chat),
                               ChatAction.TYPING)
            things.append(
                (match.start(), search.search(match.group(0), amount=1)[0]))

        # Sort the things - only necessary if we appended something here
        things.sort(key=lambda thing: thing[0])

    if things:
        reply_or_edit(
            update, context,
            "\n".join(thing[1].html_reply_markup() for thing in things))
Exemplo n.º 2
0
def github(update: Update, context: CallbackContext) -> None:
    message = cast(Message, update.effective_message)
    last = 0.0
    thing_matches = []
    things = {}

    for match in GITHUB_PATTERN.finditer(
            get_text_not_in_entities(message.text_html)):
        logging.debug(match.groupdict())
        owner, repo, number, sha, ptbcontrib = [
            match.groupdict()[x]
            for x in ('owner', 'repo', 'number', 'sha', 'ptbcontrib')
        ]
        if number or sha or ptbcontrib:
            thing_matches.append((owner, repo, number, sha, ptbcontrib))

    for thing_match in thing_matches:
        last = keep_typing(last, cast(Chat, update.effective_chat),
                           ChatAction.TYPING)
        owner, repo, number, sha, ptbcontrib = thing_match
        if number:
            issue = github_issues.get_issue(int(number), owner, repo)
            if issue is not None:
                things[issue.url] = github_issues.pretty_format_issue(issue)
        elif sha:
            commit = github_issues.get_commit(sha, owner, repo)
            if commit is not None:
                things[commit.url] = github_issues.pretty_format_commit(commit)
        elif ptbcontrib:
            contrib = github_issues.ptbcontribs.get(ptbcontrib)
            if contrib:
                things[contrib.url] = f'ptbcontrib/{contrib.name}'

    if things:
        reply_or_edit(
            update,
            context,
            '\n'.join([
                f'<a href="{url}">{name}</a>' for url, name in things.items()
            ]),
        )
Exemplo n.º 3
0
def inline_github(query: str) -> List[InlineQueryResultArticle]:
    """
    Parse query for issues, PRs and commits SHA
    Returns a list of `articles`.

    Examples:
        `ptbcontrib/search` - [(title=🔍 A contrib with search in its description,
                                description=ptbcontrib/that contrib), …]
        `#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: Dict[str, Union[Issue, Commit, List[Issue], PTBContrib,
                            List[PTBContrib]]] = 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, ptbcontrib = [
            match.groupdict()[x] for x in ('owner', 'repo', 'number', 'sha',
                                           'query', 'full', 'ptbcontrib')
        ]
        # If it's an issue
        if number:
            issue = github_issues.get_issue(int(number), owner, repo)
            if issue:
                things[full] = issue
        # If it's a commit
        elif sha:
            commit = github_issues.get_commit(sha, owner, repo)
            if commit:
                things[full] = commit
        # If it's a search
        elif search_query:
            search_results = github_issues.search(search_query)
            things['#' + search_query] = search_results
        elif ptbcontrib:
            contrib = github_issues.ptbcontribs.get(ptbcontrib)
            if contrib is not None:
                things[full] = contrib
            else:
                contrib_search_results = github_issues.search_ptbcontrib(
                    ptbcontrib)
                things[full] = contrib_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 (items) 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, items 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 items.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(items.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="{items[x.group(0)].url}">'  # pylint: disable=W0640
                f'{github_issues.pretty_format(items[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 items.values())

        results.append(
            article(title=title, description=description, message_text=text))

    return results