@@ -76,116 +76,6 @@ class Mention:
76
76
next_mention : Mention | None = None
77
77
78
78
79
- @dataclass
80
- class Comment :
81
- body : str
82
- author : str
83
- created_at : datetime
84
- url : str
85
- mentions : list [Mention ]
86
-
87
- @property
88
- def line_count (self ) -> int :
89
- """Number of lines in the comment."""
90
- if not self .body :
91
- return 0
92
- return len (self .body .splitlines ())
93
-
94
- @classmethod
95
- def from_event (cls , event : sansio .Event ) -> Comment :
96
- match event .event :
97
- case "issue_comment" | "pull_request_review_comment" | "commit_comment" :
98
- comment_data = event .data .get ("comment" )
99
- case "pull_request_review" :
100
- comment_data = event .data .get ("review" )
101
- case _:
102
- comment_data = None
103
-
104
- if not comment_data :
105
- raise ValueError (f"Cannot extract comment from event type: { event .event } " )
106
-
107
- created_at_str = comment_data .get ("created_at" , "" )
108
- if created_at_str :
109
- # GitHub timestamps are in ISO format: 2024-01-01T12:00:00Z
110
- created_at_aware = datetime .fromisoformat (
111
- created_at_str .replace ("Z" , "+00:00" )
112
- )
113
- if settings .USE_TZ :
114
- created_at = created_at_aware
115
- else :
116
- created_at = timezone .make_naive (
117
- created_at_aware , timezone .get_default_timezone ()
118
- )
119
- else :
120
- created_at = timezone .now ()
121
-
122
- author = comment_data .get ("user" , {}).get ("login" , "" )
123
- if not author and "sender" in event .data :
124
- author = event .data .get ("sender" , {}).get ("login" , "" )
125
-
126
- return cls (
127
- body = comment_data .get ("body" , "" ),
128
- author = author ,
129
- created_at = created_at ,
130
- url = comment_data .get ("html_url" , "" ),
131
- mentions = [],
132
- )
133
-
134
-
135
- @dataclass
136
- class MentionEvent :
137
- comment : Comment
138
- triggered_by : Mention
139
- scope : MentionScope | None
140
-
141
- @classmethod
142
- def from_event (
143
- cls ,
144
- event : sansio .Event ,
145
- * ,
146
- username : str | re .Pattern [str ] | None = None ,
147
- pattern : str | re .Pattern [str ] | None = None ,
148
- scope : MentionScope | None = None ,
149
- ):
150
- """Generate MentionEvent instances from a GitHub event.
151
-
152
- Yields MentionEvent for each mention that matches the given criteria.
153
- """
154
- # Check scope match first
155
- event_scope = MentionScope .from_event (event )
156
- if scope is not None and event_scope != scope :
157
- return
158
-
159
- # Parse mentions
160
- mentions = parse_mentions_for_username (event , username )
161
- if not mentions :
162
- return
163
-
164
- # Create comment
165
- comment = Comment .from_event (event )
166
- comment .mentions = mentions
167
-
168
- # Yield contexts for matching mentions
169
- for mention in mentions :
170
- # Check pattern match if specified
171
- if pattern is not None :
172
- match = check_pattern_match (mention .text , pattern )
173
- if not match :
174
- continue
175
- mention .match = match
176
-
177
- yield cls (
178
- comment = comment ,
179
- triggered_by = mention ,
180
- scope = event_scope ,
181
- )
182
-
183
-
184
- CODE_BLOCK_PATTERN = re .compile (r"```[\s\S]*?```" , re .MULTILINE )
185
- INLINE_CODE_PATTERN = re .compile (r"`[^`]+`" )
186
- QUOTE_PATTERN = re .compile (r"^\s*>.*$" , re .MULTILINE )
187
-
188
-
189
79
def check_pattern_match (
190
80
text : str , pattern : str | re .Pattern [str ] | None
191
81
) -> re .Match [str ] | None :
@@ -208,6 +98,11 @@ def check_pattern_match(
208
98
return re .match (escaped_pattern , text , re .IGNORECASE )
209
99
210
100
101
+ CODE_BLOCK_PATTERN = re .compile (r"```[\s\S]*?```" , re .MULTILINE )
102
+ INLINE_CODE_PATTERN = re .compile (r"`[^`]+`" )
103
+ QUOTE_PATTERN = re .compile (r"^\s*>.*$" , re .MULTILINE )
104
+
105
+
211
106
def parse_mentions_for_username (
212
107
event : sansio .Event , username_pattern : str | re .Pattern [str ] | None = None
213
108
) -> list [Mention ]:
@@ -299,3 +194,100 @@ def parse_mentions_for_username(
299
194
mention .next_mention = mentions [i + 1 ]
300
195
301
196
return mentions
197
+
198
+
199
+ @dataclass
200
+ class Comment :
201
+ body : str
202
+ author : str
203
+ created_at : datetime
204
+ url : str
205
+ mentions : list [Mention ]
206
+
207
+ @property
208
+ def line_count (self ) -> int :
209
+ """Number of lines in the comment."""
210
+ if not self .body :
211
+ return 0
212
+ return len (self .body .splitlines ())
213
+
214
+ @classmethod
215
+ def from_event (cls , event : sansio .Event ) -> Comment :
216
+ match event .event :
217
+ case "issue_comment" | "pull_request_review_comment" | "commit_comment" :
218
+ comment_data = event .data .get ("comment" )
219
+ case "pull_request_review" :
220
+ comment_data = event .data .get ("review" )
221
+ case _:
222
+ comment_data = None
223
+
224
+ if not comment_data :
225
+ raise ValueError (f"Cannot extract comment from event type: { event .event } " )
226
+
227
+ created_at_str = comment_data .get ("created_at" , "" )
228
+ if created_at_str :
229
+ # GitHub timestamps are in ISO format: 2024-01-01T12:00:00Z
230
+ created_at_aware = datetime .fromisoformat (
231
+ created_at_str .replace ("Z" , "+00:00" )
232
+ )
233
+ if settings .USE_TZ :
234
+ created_at = created_at_aware
235
+ else :
236
+ created_at = timezone .make_naive (
237
+ created_at_aware , timezone .get_default_timezone ()
238
+ )
239
+ else :
240
+ created_at = timezone .now ()
241
+
242
+ author = comment_data .get ("user" , {}).get ("login" , "" )
243
+ if not author and "sender" in event .data :
244
+ author = event .data .get ("sender" , {}).get ("login" , "" )
245
+
246
+ return cls (
247
+ body = comment_data .get ("body" , "" ),
248
+ author = author ,
249
+ created_at = created_at ,
250
+ url = comment_data .get ("html_url" , "" ),
251
+ mentions = [],
252
+ )
253
+
254
+
255
+ @dataclass
256
+ class MentionEvent :
257
+ comment : Comment
258
+ triggered_by : Mention
259
+ scope : MentionScope | None
260
+
261
+ @classmethod
262
+ def from_event (
263
+ cls ,
264
+ event : sansio .Event ,
265
+ * ,
266
+ username : str | re .Pattern [str ] | None = None ,
267
+ pattern : str | re .Pattern [str ] | None = None ,
268
+ scope : MentionScope | None = None ,
269
+ ):
270
+ event_scope = MentionScope .from_event (event )
271
+ if scope is not None and event_scope != scope :
272
+ return
273
+
274
+ mentions = parse_mentions_for_username (event , username )
275
+ if not mentions :
276
+ return
277
+
278
+ comment = Comment .from_event (event )
279
+ comment .mentions = mentions
280
+
281
+ for mention in mentions :
282
+ if pattern is not None :
283
+ match = check_pattern_match (mention .text , pattern )
284
+ if not match :
285
+ continue
286
+ mention .match = match
287
+
288
+ yield cls (
289
+ comment = comment ,
290
+ triggered_by = mention ,
291
+ scope = event_scope ,
292
+ )
293
+
0 commit comments