|
2 | 2 |
|
3 | 3 | import datetime as dt
|
4 | 4 | import re
|
| 5 | +from functools import partial |
5 | 6 | from typing import TYPE_CHECKING, Any, Protocol, cast, final, override
|
6 | 7 |
|
7 | 8 | from discord.ext import commands
|
|
15 | 16 |
|
16 | 17 | if TYPE_CHECKING:
|
17 | 18 | from githubkit.typing import Missing
|
| 19 | + from githubkit.versions.latest.models import RepositoryWebhooks |
18 | 20 | from monalisten import Monalisten, events
|
19 | 21 |
|
20 | 22 | from app.bot import EmojiName, GhosttyBot
|
21 | 23 |
|
22 |
| -CONVERTED_DISCUSSION_HEADER = re.compile( |
23 |
| - r"\s*### Discussed in https://github.com/.*?/discussions/(?P<discussion_number>\d+)" |
24 |
| - r"\s*<div type='discussions-op-text'>" |
25 |
| - r"\s*<sup>(?P<subtext>.+?)</sup>", |
26 |
| - re.MULTILINE, |
| 24 | + |
| 25 | +GITHUB_DISCUSSION_URL = re.compile( |
| 26 | + # Ignore if already inside a link block |
| 27 | + r"(?<!\()" |
| 28 | + r"https://github.com/" |
| 29 | + r"(?P<owner>\b[a-zA-Z0-9\-]+/)" |
| 30 | + r"(?P<repo>\b[a-zA-Z0-9\-\._]+)" |
| 31 | + r"(?P<sep>/(?:issues|pull|discussions)/)" |
| 32 | + r"(?P<number>\d+)" |
| 33 | + r"(?!\))" |
| 34 | +) # fmt: skip |
| 35 | +SUP_HTML = re.compile(r"\s*<sup>(.+?)</sup>\s*$") |
| 36 | +DISUCSSION_DIV_TAG = re.compile( |
| 37 | + r"\s*<div type='discussions-op-text'>((?:.|\s)*?)\s*</div>\s*", |
| 38 | + flags=re.MULTILINE, |
27 | 39 | )
|
28 | 40 |
|
29 | 41 |
|
30 |
| -def reformat_converted_discussion_header(body: str | None, repo_url: str) -> str | None: |
31 |
| - if body is None or not (match := CONVERTED_DISCUSSION_HEADER.match(body)): |
32 |
| - return body |
| 42 | +def shorten_same_repo_links( |
| 43 | + origin_repo: RepositoryWebhooks, matchobj: re.Match[str] |
| 44 | +) -> str: |
| 45 | + if ( |
| 46 | + matchobj.group("owner") == origin_repo.owner.name |
| 47 | + and matchobj.group("repo") == origin_repo.name |
| 48 | + ): |
| 49 | + # Only short hand if link comes from same repo |
| 50 | + return f"[#{matchobj.group('number')}]({matchobj.group()})" |
| 51 | + return matchobj.group() |
33 | 52 |
|
34 |
| - d, subtext = match["discussion_number"], match["subtext"] |
35 |
| - new_heading = f"### Discussed in [#{d}]({repo_url}/discussions/{d})\n-# {subtext}\n" |
36 | 53 |
|
37 |
| - _, end = match.span() |
38 |
| - return new_heading + "".join(body[end:].lstrip().rsplit("</div>", maxsplit=1)) |
| 54 | +def reformat_converted_discussion_header( |
| 55 | + body: str | None, repo: RepositoryWebhooks |
| 56 | +) -> str | None: |
| 57 | + if not body: |
| 58 | + return body |
| 59 | + body = SUP_HTML.sub(r"-# \g<1>", body) |
| 60 | + body = DISUCSSION_DIV_TAG.sub(r"\g<1>", body) |
| 61 | + body = GITHUB_DISCUSSION_URL.sub(partial(shorten_same_repo_links, repo), body) |
| 62 | + return body # noqa: RET504 |
39 | 63 |
|
40 | 64 |
|
41 | 65 | class IssueLike(Protocol):
|
@@ -81,9 +105,7 @@ def register_hooks(bot: GhosttyBot, webhook: Monalisten) -> None: # noqa: PLR09
|
81 | 105 | @webhook.event.issues.opened
|
82 | 106 | async def _(event: events.IssuesOpened) -> None:
|
83 | 107 | issue = event.issue
|
84 |
| - body = reformat_converted_discussion_header( |
85 |
| - issue.body, event.repository.html_url |
86 |
| - ) |
| 108 | + body = reformat_converted_discussion_header(issue.body, event.repository) |
87 | 109 | await send_embed(
|
88 | 110 | bot,
|
89 | 111 | event.sender,
|
|
0 commit comments