@@ -120,11 +120,15 @@ def get_repository(self): # pragma: no cover
120120class GithubProjectV2Item (GithubWebhook ):
121121 # NOTE: This might be something for pydantic schemas in the future
122122
123+ @property
123124 def sender (self ):
124125 sender = self .get_sender ()
125126
126127 return f"[@{ sender .login } ]({ sender .html_url } )"
127128
129+ def get_sender (self ) -> GithubSender :
130+ return GithubSender .model_validate (self .content ["sender" ])
131+
128132 def github_object (self ) -> GithubDraftIssue | GithubIssue :
129133 content = self .extra ["content" ]
130134 typename = content .pop ("__typename" )
@@ -143,41 +147,40 @@ def get_repository(self):
143147 # Not relevant at the moment
144148 return ...
145149
146- def get_sender (self ) -> GithubSender :
147- return GithubSender .model_validate (self .content ["sender" ])
148-
149150 def changes (self ) -> dict :
150- if "changes" in self .content :
151- fv = self .content ["changes" ]["field_value" ]
152- field_name = fv ["field_name" ]
153- field_type = fv ["field_type" ]
154-
155- if field_type == "date" :
156- changed_from = (
157- fv ["from" ].split ("T" )[0 ] if fv ["from" ] is not None else "None"
158- )
159- changed_to = fv ["to" ].split ("T" )[0 ] if fv ["to" ] is not None else "None"
160-
161- elif field_type == "single_select" :
162- changed_from = fv ["from" ]["name" ] if fv ["from" ] is not None else "None"
163- changed_to = fv ["to" ]["name" ] if fv ["to" ] is not None else "None"
164-
165- else :
166- changed_from = "None"
167- changed_to = "None"
168-
169- return {
170- "field" : field_name ,
171- "from" : changed_from ,
172- "to" : changed_to ,
173- }
174151
175- return {}
152+ # Early return! \o/
153+ if "changes" not in self .content :
154+ # Fallback because some webhooks just don't have changes.
155+ return {}
156+
157+ fv = self .content ["changes" ]["field_value" ]
158+ field_name = fv ["field_name" ]
159+ field_type = fv ["field_type" ]
160+
161+ if field_type == "date" :
162+ changed_from = (
163+ fv ["from" ].split ("T" )[0 ] if fv ["from" ] is not None else "None"
164+ )
165+ changed_to = fv ["to" ].split ("T" )[0 ] if fv ["to" ] is not None else "None"
166+
167+ elif field_type == "single_select" :
168+ changed_from = fv ["from" ]["name" ] if fv ["from" ] is not None else "None"
169+ changed_to = fv ["to" ]["name" ] if fv ["to" ] is not None else "None"
170+
171+ else :
172+ changed_from = "None"
173+ changed_to = "None"
174+
175+ return {
176+ "field" : field_name ,
177+ "from" : changed_from ,
178+ "to" : changed_to ,
179+ }
176180
177181 def as_discord_message (self ) -> str :
178182 message = "{sender} {action} {details}" .format
179183
180- sender = self .sender ()
181184 changes = self .changes ()
182185
183186 if changes :
@@ -190,7 +193,7 @@ def as_discord_message(self) -> str:
190193
191194 return message (
192195 ** {
193- "sender" : sender ,
196+ "sender" : self . sender ,
194197 "action" : self .action ,
195198 "details" : details ,
196199 }
@@ -214,6 +217,11 @@ def prep_github_webhook(wh: Webhook):
214217 raise ValueError (f"Event `{ event } ` not supported" )
215218
216219
220+ class GithubAPIError (Exception ):
221+ """Custom exception for GithubAPI Errors"""
222+ pass
223+
224+
217225# Should we have a separate GithubClient that encapsulates this?
218226# Or at least a function that runs the request.
219227def fetch_github_project_item (item_id : str ) -> dict [str , Any ]:
@@ -227,7 +235,7 @@ def fetch_github_project_item(item_id: str) -> dict[str, Any]:
227235 if response .status_code == 200 :
228236 return response .json ()["data" ]["node" ]
229237 else :
230- raise Exception (f"GitHub API error: { response .status_code } - { response .text } " )
238+ raise GithubAPIError (f"GitHub API error: { response .status_code } - { response .text } " )
231239
232240
233241def parse_github_webhook (wh : Webhook ):
0 commit comments