@@ -745,6 +745,27 @@ async def handle_notification(client: httpx.AsyncClient, note: Dict):
745745 pass
746746 return
747747
748+ # 检查通知类型 - 只处理 issue 和 pull_request 类型
749+ # GitHub 通知的 subject.type 可以是: "Issue", "PullRequest", "Commit", "Discussion" 等
750+ # 但 issue 关闭等事件也会触发通知,我们需要检查 URL 中是否包含事件信息
751+ subject_type = note .get ("subject" , {}).get ("type" )
752+ logger .info (f"Notification subject type: { subject_type } " )
753+
754+ # 检查 URL 中是否包含事件类型(如 /issues/123 可能是 issue 关闭事件)
755+ # 我们需要确保只处理真正包含 @mention 的内容,而不是所有相关事件
756+ # 例如:issue 被关闭时,如果之前被 @mention 过,也会触发通知
757+ # 但这种通知不应该触发 workflow,因为没有新的 @mention
758+ if subject_type and subject_type not in ["Issue" , "PullRequest" , "Commit" , "Discussion" ]:
759+ logger .info (f"Ignoring notification with unsupported subject type: { subject_type } " )
760+ try :
761+ await client .patch (
762+ f"{ REST_API } /notifications/threads/{ thread_id } " ,
763+ headers = {"Authorization" : f"token { BOT_TOKEN } " }
764+ )
765+ except :
766+ pass
767+ return
768+
748769 # 1. 获取资源详情
749770 resource_data = await fetch_resource_details (client , raw_url )
750771 if not resource_data :
@@ -882,6 +903,37 @@ async def handle_notification(client: httpx.AsyncClient, note: Dict):
882903 pass
883904 return
884905
906+ # 5. 验证触发节点的时间戳 - 防止处理旧事件
907+ # 检查触发节点的创建时间是否在通知的更新时间之前(说明是旧的 @mention)
908+ # 这可以防止 issue 关闭等事件触发 workflow(这些事件会发送通知,但没有新的 @mention)
909+ notification_updated_at = note .get ("updated_at" )
910+ if notification_updated_at and trigger_node .created_at :
911+ try :
912+ # 解析时间戳(ISO 8601 格式)
913+ note_time = datetime .fromisoformat (notification_updated_at .replace ("Z" , "+00:00" ))
914+ trigger_time = datetime .fromisoformat (trigger_node .created_at .replace ("Z" , "+00:00" ))
915+
916+ # 如果触发节点的创建时间比通知更新时间早很多(超过 1 分钟)
917+ # 说明这不是新的 @mention,而是旧事件的后续通知(如 issue 关闭)
918+ time_diff = (note_time - trigger_time ).total_seconds ()
919+ if time_diff > 60 : # 超过 1 分钟
920+ logger .warning (f"Trigger node is too old (created { time_diff :.0f} s before notification update). This might be an event notification (e.g., issue closed) rather than a new @mention." )
921+ logger .warning (f"Notification updated_at: { notification_updated_at } , Trigger created_at: { trigger_node .created_at } " )
922+ # 标记为已读但不触发 workflow
923+ try :
924+ await client .patch (
925+ f"{ REST_API } /notifications/threads/{ thread_id } " ,
926+ headers = {"Authorization" : f"token { BOT_TOKEN } " }
927+ )
928+ except :
929+ pass
930+ return
931+ else :
932+ logger .info (f"Trigger node time check passed (time diff: { time_diff :.0f} s)" )
933+ except Exception as e :
934+ logger .warning (f"Could not parse timestamps for validation: { e } " )
935+ # 继续处理,但记录警告
936+
885937 # 验证触发消息是否存在
886938 if not trigger_node .body or not trigger_node .body .strip ():
887939 logger .error (f"Trigger node { trigger_node .id } has empty body. Cannot proceed with workflow." )
@@ -899,7 +951,7 @@ async def handle_notification(client: httpx.AsyncClient, note: Dict):
899951 pass
900952 return
901953
902- # 5 . 构建完整上下文(使用修复后的build_rich_context)
954+ # 6 . 构建完整上下文(使用修复后的build_rich_context)
903955 context = build_rich_context (resource_data , timeline_items , trigger_node , raw_url , thread_id )
904956
905957 # 6. 获取diff内容(根据触发类型决定)
0 commit comments