Skip to content

Commit 582ca38

Browse files
committed
Add support for many more entity events.
Full stops were also added to every one, some items were reordered, and entity kinds (e.g. Issue, Pull Request) were lower-cased to match the UI (though as far as I can tell the canonical spelling is upper-case; not sure why the UI differs).
1 parent dba45df commit 582ca38

File tree

1 file changed

+64
-16
lines changed

1 file changed

+64
-16
lines changed

app/components/github_integration/comments/fetching.py

Lines changed: 64 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,18 @@
1414
from app.components.github_integration.mentions.cache import entity_cache
1515
from app.components.github_integration.models import Comment, EntityGist, GitHubUser
1616
from app.setup import gh
17-
from app.utils import TTRCache
17+
from app.utils import TTRCache, escape_special
1818

1919
if TYPE_CHECKING:
2020
import datetime as dt
21-
from collections.abc import AsyncIterator
21+
from collections.abc import AsyncIterator, Callable
2222

23-
from githubkit.versions.latest.models import PullRequestReviewComment
23+
from githubkit.versions.latest.models import (
24+
Issue,
25+
IssueEvent,
26+
IssueEventRename,
27+
PullRequestReviewComment,
28+
)
2429
from pydantic import BaseModel
2530

2631
COMMENT_PATTERN = re.compile(
@@ -36,14 +41,52 @@
3641
"CHANGES_REQUESTED": 0xE74C3C, # red
3742
}
3843
EVENT_COLOR = 0x3498DB # blue
39-
ENTITY_UPDATE_EVENTS = frozenset({"closed", "locked", "merged", "reopened", "unlocked"})
40-
SUPPORTED_EVENTS = {
41-
"assigned": "Assigned `{event.assignee.login}`",
42-
"labeled": "Added the `{event.label.name}` label",
43-
"milestoned": "Added this to the `{event.milestone.title}` milestone",
44-
"review_requested": "Requested review from `{reviewer}`",
45-
"unassigned": "Unassigned `{event.assignee.login}`",
46-
"unlabeled": "Removed the `{event.label.name}` label",
44+
ENTITY_UPDATE_EVENTS = frozenset(
45+
{"closed", "locked", "merged", "reopened", "unlocked", "pinned"}
46+
)
47+
SUPPORTED_EVENTS: dict[str, str | Callable[[IssueEvent], str]] = {
48+
"assigned": "Assigned `{event.assignee.login}`.",
49+
"unassigned": "Unassigned `{event.assignee.login}`.",
50+
"labeled": "Added the `{event.label.name}` label.",
51+
"unlabeled": "Removed the `{event.label.name}` label.",
52+
"milestoned": "Added this to the `{event.milestone.title}` milestone.",
53+
"demilestoned": "Removed this from the `{event.milestone.title}` milestone.",
54+
"convert_to_draft": "Marked this pull request as draft.",
55+
"ready_for_review": "Marked this pull request as ready for review.",
56+
"review_requested": "Requested review from `{reviewer}`.",
57+
"auto_merge_enabled": "Enabled auto-merge.",
58+
"auto_merge_disabled": "Disabled auto-merge.",
59+
"head_ref_deleted": "Deleted the head branch.",
60+
"head_ref_force_pushed": lambda event: (
61+
# HACK: there does not seem to be any easy way to get the HTML URL of the
62+
# repository.
63+
f"Force-pushed the head branch to [`{cast('str', event.commit_id)[:7]}`](<{
64+
cast('Issue', event.issue)
65+
.repository_url.replace('//api.', '//')
66+
.replace('/repos/', '/')
67+
}/commit/{event.commit_id}>)."
68+
),
69+
"automatic_base_change_succeeded": "Base automatically changed.",
70+
"converted_to_discussion": "Converted this issue to a discussion.",
71+
"parent_issue_added": "Added a parent issue.",
72+
"sub_issue_added": "Added a sub-issue.",
73+
"referenced": lambda event: (
74+
f"Referenced this issue in commit [`{cast('str', event.commit_id)[:7]}`]"
75+
# HACK: once again, there does not seem to be any other way. And for
76+
# some reason the HTML URL requires `commit` while the API URL requires
77+
# `commits` (note the `s`)...
78+
f"(<{
79+
cast('str', event.commit_url)
80+
.replace('//api.', '//')
81+
.replace('/repos/', '/')
82+
.replace('commits', 'commit')
83+
}>)."
84+
),
85+
"renamed": lambda event: (
86+
f"Changed the title ~~{
87+
escape_special((rename := cast('IssueEventRename', event.rename)).from_)
88+
}~~ {escape_special(rename.to)}."
89+
),
4790
}
4891

4992

@@ -160,7 +203,7 @@ async def _get_event(entity_gist: EntityGist, comment_id: int) -> Comment:
160203
owner, repo, entity_no = entity_gist
161204
event = (await gh.rest.issues.async_get_event(owner, repo, comment_id)).parsed_data
162205
if event.event not in SUPPORTED_EVENTS.keys() | ENTITY_UPDATE_EVENTS:
163-
body = f":ghost: Unsupported event: `{event.event}`"
206+
body = f":ghost: Unsupported event: `{event.event}`."
164207
elif event.event == "review_requested":
165208
# Special-cased to handle requests for both users and teams
166209
if event.requested_reviewer:
@@ -170,14 +213,19 @@ async def _get_event(entity_gist: EntityGist, comment_id: int) -> Comment:
170213
# Throwing in the org name to make it clear that it's a team
171214
org_name = event.requested_team.html_url.split("/", 5)[4]
172215
reviewer = f"{org_name}/{event.requested_team.name}"
173-
body = SUPPORTED_EVENTS[event.event].format(reviewer=reviewer)
216+
formatter = SUPPORTED_EVENTS[event.event]
217+
assert not callable(formatter)
218+
body = formatter.format(reviewer=reviewer)
174219
elif event.event in ENTITY_UPDATE_EVENTS:
175220
entity = await entity_cache.get(entity_gist)
176-
body = f"{event.event.capitalize()} the {entity.kind}"
221+
body = f"{event.event.capitalize()} the {entity.kind.lower()}."
177222
if event.lock_reason:
178-
body += f"\nReason: `{event.lock_reason or 'unspecified'}`"
223+
body += f"\nReason: `{event.lock_reason}`."
179224
else:
180-
body = SUPPORTED_EVENTS[event.event].format(event=event)
225+
formatter = SUPPORTED_EVENTS[event.event]
226+
body = (
227+
formatter(event) if callable(formatter) else formatter.format(event=event)
228+
)
181229
# The API doesn't return an html_url, gotta construct it manually.
182230
# It's fine to say "issues" here, GitHub will resolve the correct type
183231
url = f"https://github.com/{owner}/{repo}/issues/{entity_no}#event-{comment_id}"

0 commit comments

Comments
 (0)