fix(hooks): 9 hook wiring fixes — DMS/Calendar name mismatch, Mail/Contact missing triggers
Check Cross-Plugin Imports / check (push) Has been cancelled

This commit is contained in:
Agent Zero
2026-08-17 07:21:39 +02:00
parent 0a1ba30ed7
commit 8de35a24a7
10 changed files with 1255 additions and 568 deletions
+3
View File
@@ -471,6 +471,7 @@ async def create_entry(
# ── Hook: calendar.after_appointment (Action) ──
from app.core.hooks import do_action
await do_action("calendar.after_appointment", entry_id=str(entry.id), tenant_id=tenant_id, user_id=user_id)
await do_action("calendar_entry.after_create", entry_id=str(entry.id), tenant_id=tenant_id, user_id=user_id)
# Schedule reminder ARQ job if reminder is set
if body.reminder:
@@ -665,6 +666,7 @@ async def update_entry(
snapshot_before=snapshot_before, snapshot_after=snapshot_after, changes=changes or None)
from app.core.hooks import do_action
await do_action("calendar.after_update", entry_id=str(entry.id), tenant_id=tenant_id, user_id=user_id)
await do_action("calendar_entry.after_update", entry_id=str(entry.id), tenant_id=tenant_id, user_id=user_id)
return snapshot_after
@@ -694,6 +696,7 @@ async def delete_entry(
await record_history(db, tenant_id, user_id, "calendar_entry", entry.id, "delete", snapshot_before=snapshot_before)
from app.core.hooks import do_action
await do_action("calendar.after_delete", tenant_id=tenant_id, user_id=user_id, entry_id=entry_id)
await do_action("calendar_entry.after_delete", tenant_id=tenant_id, user_id=user_id, entry_id=entry_id)
return Response(status_code=204)
+3
View File
@@ -623,6 +623,7 @@ async def upload_file(
# Lifecycle hook: dms.after_upload
from app.core.hooks import do_action
await do_action("dms.after_upload", {'id': str(dms_file.id), 'name': dms_file.name, 'folder_id': str(dms_file.folder_id) if dms_file.folder_id else None, 'mime_type': dms_file.mime_type, 'size_bytes': dms_file.size_bytes}, db=db, tenant_id=tenant_id, user_id=user_id)
await do_action("dms_file.after_create", {'id': str(dms_file.id), 'name': dms_file.name, 'tenant_id': str(tenant_id)}, db=db, tenant_id=tenant_id, user_id=user_id)
# Outbox event: file.created
from app.core.outbox import enqueue_outbox_event
@@ -846,6 +847,7 @@ async def update_file(
# Lifecycle hook: dms.after_update
from app.core.hooks import do_action
await do_action("dms.after_update", {'id': str(dms_file.id), 'name': dms_file.name}, db=db, tenant_id=tenant_id, user_id=user_id, file_id=file_id)
await do_action("dms_file.after_update", {'id': str(dms_file.id), 'name': dms_file.name, 'tenant_id': str(tenant_id)}, db=db, tenant_id=tenant_id, user_id=user_id, file_id=file_id)
return {
"id": str(dms_file.id),
@@ -908,6 +910,7 @@ async def delete_file(
# Lifecycle hook: dms.after_delete
await do_action("dms.after_delete", db=db, tenant_id=tenant_id, user_id=user_id, file_id=file_id)
await do_action("dms_file.after_delete", db=db, tenant_id=tenant_id, user_id=user_id, file_id=file_id)
# Outbox event: file.deleted
from app.core.outbox import enqueue_outbox_event
+2
View File
@@ -826,6 +826,7 @@ async def imap_sync_folder(
# Lifecycle hook: mail.after_receive
from app.core.hooks import do_action
await do_action("mail.after_receive", {'mail_id': str(mail.id), 'tenant_id': str(tenant_id), 'account_id': str(account.id), 'folder_id': str(folder.id), 'subject': subject, 'from_address': from_addr}, db=db, tenant_id=tenant_id)
await do_action("mail.after_create", {'mail_id': str(mail.id), 'tenant_id': str(tenant_id), 'subject': subject, 'from_address': from_addr}, db=db, tenant_id=tenant_id)
# Outbox event: mail.received
from app.core.outbox import enqueue_outbox_event
@@ -1584,6 +1585,7 @@ async def send_mail_via_smtp(
# ── Hook: mail.after_send (Action) ──
from app.core.hooks import do_action
await do_action("mail.after_send", mail_data, db=db, account=account, msg_id=msg_id)
await do_action("mail.after_update", mail_data, db=db, tenant_id=str(mail_data.get('tenant_id', '')) if isinstance(mail_data, dict) else None)
# Store sent mail in Sent folder — use configured mapping if set,
# otherwise flexible lookup to handle different IMAP naming conventions
+3
View File
@@ -464,6 +464,9 @@ async def delete_contact(
action="delete", snapshot_before=snapshot_before,
)
# Hook: contact.after_delete
await do_action("contact.after_delete", db=db, tenant_id=tenant_id, contact_id=contact_id, user_id=user_id)
async def hard_delete_contact(db: AsyncSession, tenant_id: uuid.UUID, contact_id: str) -> None:
"""GDPR hard-delete a contact."""
+12 -12
View File
@@ -1,8 +1,8 @@
{
"timestamp": "2026-08-17T07:15:04.567567",
"total_time": 5.77,
"timestamp": "2026-08-17T07:17:53.788386",
"total_time": 6.71,
"total_scripts": 7,
"total_issues": 1110,
"total_issues": 1109,
"passed": 1,
"failed": 6,
"skipped": 0,
@@ -12,7 +12,7 @@
"description": "Frontend\u2194Backend API Contracts",
"status": "FAIL",
"exit_code": 246,
"elapsed": 0.29,
"elapsed": 0.31,
"issues": 758
},
{
@@ -20,7 +20,7 @@
"description": "Hook Registrations vs Triggers",
"status": "FAIL",
"exit_code": 1,
"elapsed": 0.11,
"elapsed": 0.05,
"issues": 0
},
{
@@ -28,7 +28,7 @@
"description": "Dead Functions (defined but never called)",
"status": "FAIL",
"exit_code": 3,
"elapsed": 2.47,
"elapsed": 2.6,
"issues": 3
},
{
@@ -36,7 +36,7 @@
"description": "Unused Store Actions/State",
"status": "FAIL",
"exit_code": 67,
"elapsed": 0.07,
"elapsed": 0.12,
"issues": 323
},
{
@@ -44,7 +44,7 @@
"description": "Contract Attribute Mismatches",
"status": "PASS",
"exit_code": 0,
"elapsed": 1.42,
"elapsed": 2.01,
"issues": 0
},
{
@@ -52,16 +52,16 @@
"description": "Plugin\u2192Manifest\u2192Frontend Verkabelung",
"status": "FAIL",
"exit_code": 24,
"elapsed": 0.12,
"elapsed": 0.14,
"issues": 24
},
{
"name": "trace_imports",
"description": "Broken/Missing Imports",
"status": "FAIL",
"exit_code": 2,
"elapsed": 1.28,
"issues": 2
"exit_code": 1,
"elapsed": 1.49,
"issues": 1
}
]
}
@@ -1,6 +1,6 @@
{
"py_defs": 1616,
"py_dead": 628,
"py_dead": 629,
"ts_defs": 959,
"ts_dead": 442,
"critical_dead": [
+670
View File
@@ -0,0 +1,670 @@
{
"registrations": [
{
"file": "app/core/hooks.py",
"hook_name": "contact.before_create"
},
{
"file": "app/core/hooks.py",
"hook_name": "contact.format_display_name"
},
{
"file": "app/plugins/builtins/dms/plugin.py",
"hook_name": "dms_file.after_create"
},
{
"file": "app/plugins/builtins/dms/plugin.py",
"hook_name": "dms_file.after_update"
},
{
"file": "app/plugins/builtins/dms/plugin.py",
"hook_name": "dms_file.after_delete"
},
{
"file": "app/plugins/builtins/mail/plugin.py",
"hook_name": "mail.after_create"
},
{
"file": "app/plugins/builtins/mail/plugin.py",
"hook_name": "mail.after_update"
},
{
"file": "app/plugins/builtins/mail/plugin.py",
"hook_name": "mail.after_delete"
},
{
"file": "app/plugins/builtins/contacts/plugin.py",
"hook_name": "contact.after_create"
},
{
"file": "app/plugins/builtins/contacts/plugin.py",
"hook_name": "contact.after_update"
},
{
"file": "app/plugins/builtins/contacts/plugin.py",
"hook_name": "contact.after_delete"
},
{
"file": "app/plugins/builtins/tasks/plugin.py",
"hook_name": "task.after_create"
},
{
"file": "app/plugins/builtins/tasks/plugin.py",
"hook_name": "task.after_update"
},
{
"file": "app/plugins/builtins/tasks/plugin.py",
"hook_name": "task.after_delete"
},
{
"file": "app/plugins/builtins/calendar/plugin.py",
"hook_name": "calendar_entry.after_create"
},
{
"file": "app/plugins/builtins/calendar/plugin.py",
"hook_name": "calendar_entry.after_update"
},
{
"file": "app/plugins/builtins/calendar/plugin.py",
"hook_name": "calendar_entry.after_delete"
}
],
"triggers": [
{
"file": "app/routes/companies.py",
"hook_name": "company.before_create"
},
{
"file": "app/routes/companies.py",
"hook_name": "company.after_create"
},
{
"file": "app/routes/companies.py",
"hook_name": "company.before_update"
},
{
"file": "app/routes/companies.py",
"hook_name": "company.after_update"
},
{
"file": "app/routes/companies.py",
"hook_name": "company.before_delete"
},
{
"file": "app/routes/companies.py",
"hook_name": "company.after_delete"
},
{
"file": "app/services/contact_service.py",
"hook_name": "contact.before_create"
},
{
"file": "app/services/contact_service.py",
"hook_name": "contact.after_create"
},
{
"file": "app/services/contact_service.py",
"hook_name": "contact.before_update"
},
{
"file": "app/services/contact_service.py",
"hook_name": "contact.after_update"
},
{
"file": "app/services/contact_service.py",
"hook_name": "contact.before_delete"
},
{
"file": "app/services/contact_service.py",
"hook_name": "contact.format_display_name"
},
{
"file": "app/services/auth_service.py",
"hook_name": "auth.after_login"
},
{
"file": "app/services/auth_service.py",
"hook_name": "auth.before_login"
},
{
"file": "app/services/workflow_service.py",
"hook_name": "workflow.before_start"
},
{
"file": "app/services/workflow_service.py",
"hook_name": "workflow.after_start"
},
{
"file": "app/services/workflow_service.py",
"hook_name": "workflow.after_complete"
},
{
"file": "app/services/workflow_service.py",
"hook_name": "workflow.after_cancel"
},
{
"file": "app/services/user_service.py",
"hook_name": "user.before_create"
},
{
"file": "app/services/user_service.py",
"hook_name": "user.after_create"
},
{
"file": "app/core/hooks.py",
"hook_name": "contact.before_create"
},
{
"file": "app/core/hooks.py",
"hook_name": "contact.before_create"
},
{
"file": "app/core/hooks.py",
"hook_name": "contact.format_display_name"
},
{
"file": "app/core/hooks.py",
"hook_name": "contact.format_name"
},
{
"file": "app/plugins/builtins/automation/agent_runner.py",
"hook_name": "agent.before_run"
},
{
"file": "app/plugins/builtins/automation/agent_runner.py",
"hook_name": "agent.after_run"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.folder.before_create"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.folder.after_create"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.folder.before_delete"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.folder.after_delete"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.after_upload"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.before_update"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.after_update"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.before_delete"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.after_delete"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.before_restore"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.after_restore"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.before_upload"
},
{
"file": "app/plugins/builtins/mail/services.py",
"hook_name": "mail.after_receive"
},
{
"file": "app/plugins/builtins/mail/services.py",
"hook_name": "mail.after_send"
},
{
"file": "app/plugins/builtins/mail/services.py",
"hook_name": "mail.before_delete"
},
{
"file": "app/plugins/builtins/mail/services.py",
"hook_name": "mail.after_delete"
},
{
"file": "app/plugins/builtins/mail/services.py",
"hook_name": "mail.before_move"
},
{
"file": "app/plugins/builtins/mail/services.py",
"hook_name": "mail.after_move"
},
{
"file": "app/plugins/builtins/mail/services.py",
"hook_name": "mail.before_send"
},
{
"file": "app/plugins/builtins/tasks/services.py",
"hook_name": "task.before_create"
},
{
"file": "app/plugins/builtins/tasks/services.py",
"hook_name": "task.after_create"
},
{
"file": "app/plugins/builtins/tasks/services.py",
"hook_name": "task.before_update"
},
{
"file": "app/plugins/builtins/tasks/services.py",
"hook_name": "task.after_update"
},
{
"file": "app/plugins/builtins/tasks/services.py",
"hook_name": "task.before_delete"
},
{
"file": "app/plugins/builtins/tasks/services.py",
"hook_name": "task.after_delete"
},
{
"file": "app/plugins/builtins/calendar/routes.py",
"hook_name": "calendar.before_appointment"
},
{
"file": "app/plugins/builtins/calendar/routes.py",
"hook_name": "calendar.after_appointment"
},
{
"file": "app/plugins/builtins/calendar/routes.py",
"hook_name": "calendar.before_update"
},
{
"file": "app/plugins/builtins/calendar/routes.py",
"hook_name": "calendar.after_update"
},
{
"file": "app/plugins/builtins/calendar/routes.py",
"hook_name": "calendar.before_delete"
},
{
"file": "app/plugins/builtins/calendar/routes.py",
"hook_name": "calendar.after_delete"
},
{
"file": "app/plugins/builtins/unified_search/search_engine.py",
"hook_name": "search.before_search"
},
{
"file": "app/plugins/builtins/unified_search/search_engine.py",
"hook_name": "search.after_search"
},
{
"file": "app/plugins/builtins/kommunikation/services.py",
"hook_name": "comm.conversation.before_create"
},
{
"file": "app/plugins/builtins/kommunikation/services.py",
"hook_name": "comm.conversation.after_create"
},
{
"file": "app/plugins/builtins/kommunikation/services.py",
"hook_name": "comm.before_message"
},
{
"file": "app/plugins/builtins/kommunikation/services.py",
"hook_name": "comm.after_message"
},
{
"file": "app/plugins/builtins/kommunikation/services.py",
"hook_name": "comm.before_edit"
},
{
"file": "app/plugins/builtins/kommunikation/services.py",
"hook_name": "comm.after_edit"
},
{
"file": "app/plugins/builtins/kommunikation/services.py",
"hook_name": "comm.before_delete"
},
{
"file": "app/plugins/builtins/kommunikation/services.py",
"hook_name": "comm.after_delete"
},
{
"file": "app/plugins/builtins/tags/routes.py",
"hook_name": "tag.before_create"
},
{
"file": "app/plugins/builtins/tags/routes.py",
"hook_name": "tag.after_create"
},
{
"file": "app/plugins/builtins/tags/routes.py",
"hook_name": "tag.before_assign"
},
{
"file": "app/plugins/builtins/tags/routes.py",
"hook_name": "tag.after_assign"
},
{
"file": "app/plugins/builtins/tags/routes.py",
"hook_name": "tag.before_unassign"
},
{
"file": "app/plugins/builtins/tags/routes.py",
"hook_name": "tag.after_unassign"
},
{
"file": "app/plugins/builtins/tags/routes.py",
"hook_name": "tag.before_delete"
},
{
"file": "app/plugins/builtins/tags/routes.py",
"hook_name": "tag.after_delete"
}
],
"orphan_registrations": [
{
"file": "app/plugins/builtins/dms/plugin.py",
"hook_name": "dms_file.after_create"
},
{
"file": "app/plugins/builtins/dms/plugin.py",
"hook_name": "dms_file.after_update"
},
{
"file": "app/plugins/builtins/dms/plugin.py",
"hook_name": "dms_file.after_delete"
},
{
"file": "app/plugins/builtins/mail/plugin.py",
"hook_name": "mail.after_create"
},
{
"file": "app/plugins/builtins/mail/plugin.py",
"hook_name": "mail.after_update"
},
{
"file": "app/plugins/builtins/contacts/plugin.py",
"hook_name": "contact.after_delete"
},
{
"file": "app/plugins/builtins/calendar/plugin.py",
"hook_name": "calendar_entry.after_create"
},
{
"file": "app/plugins/builtins/calendar/plugin.py",
"hook_name": "calendar_entry.after_update"
},
{
"file": "app/plugins/builtins/calendar/plugin.py",
"hook_name": "calendar_entry.after_delete"
}
],
"orphan_triggers": [
{
"file": "app/routes/companies.py",
"hook_name": "company.before_create"
},
{
"file": "app/routes/companies.py",
"hook_name": "company.after_create"
},
{
"file": "app/routes/companies.py",
"hook_name": "company.before_update"
},
{
"file": "app/routes/companies.py",
"hook_name": "company.after_update"
},
{
"file": "app/routes/companies.py",
"hook_name": "company.before_delete"
},
{
"file": "app/routes/companies.py",
"hook_name": "company.after_delete"
},
{
"file": "app/services/contact_service.py",
"hook_name": "contact.before_update"
},
{
"file": "app/services/contact_service.py",
"hook_name": "contact.before_delete"
},
{
"file": "app/services/auth_service.py",
"hook_name": "auth.after_login"
},
{
"file": "app/services/auth_service.py",
"hook_name": "auth.before_login"
},
{
"file": "app/services/workflow_service.py",
"hook_name": "workflow.before_start"
},
{
"file": "app/services/workflow_service.py",
"hook_name": "workflow.after_start"
},
{
"file": "app/services/workflow_service.py",
"hook_name": "workflow.after_complete"
},
{
"file": "app/services/workflow_service.py",
"hook_name": "workflow.after_cancel"
},
{
"file": "app/services/user_service.py",
"hook_name": "user.before_create"
},
{
"file": "app/services/user_service.py",
"hook_name": "user.after_create"
},
{
"file": "app/core/hooks.py",
"hook_name": "contact.format_name"
},
{
"file": "app/plugins/builtins/automation/agent_runner.py",
"hook_name": "agent.before_run"
},
{
"file": "app/plugins/builtins/automation/agent_runner.py",
"hook_name": "agent.after_run"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.folder.before_create"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.folder.after_create"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.folder.before_delete"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.folder.after_delete"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.after_upload"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.before_update"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.after_update"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.before_delete"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.after_delete"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.before_restore"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.after_restore"
},
{
"file": "app/plugins/builtins/dms/routes.py",
"hook_name": "dms.before_upload"
},
{
"file": "app/plugins/builtins/mail/services.py",
"hook_name": "mail.after_receive"
},
{
"file": "app/plugins/builtins/mail/services.py",
"hook_name": "mail.after_send"
},
{
"file": "app/plugins/builtins/mail/services.py",
"hook_name": "mail.before_delete"
},
{
"file": "app/plugins/builtins/mail/services.py",
"hook_name": "mail.before_move"
},
{
"file": "app/plugins/builtins/mail/services.py",
"hook_name": "mail.after_move"
},
{
"file": "app/plugins/builtins/mail/services.py",
"hook_name": "mail.before_send"
},
{
"file": "app/plugins/builtins/tasks/services.py",
"hook_name": "task.before_create"
},
{
"file": "app/plugins/builtins/tasks/services.py",
"hook_name": "task.before_update"
},
{
"file": "app/plugins/builtins/tasks/services.py",
"hook_name": "task.before_delete"
},
{
"file": "app/plugins/builtins/calendar/routes.py",
"hook_name": "calendar.before_appointment"
},
{
"file": "app/plugins/builtins/calendar/routes.py",
"hook_name": "calendar.after_appointment"
},
{
"file": "app/plugins/builtins/calendar/routes.py",
"hook_name": "calendar.before_update"
},
{
"file": "app/plugins/builtins/calendar/routes.py",
"hook_name": "calendar.after_update"
},
{
"file": "app/plugins/builtins/calendar/routes.py",
"hook_name": "calendar.before_delete"
},
{
"file": "app/plugins/builtins/calendar/routes.py",
"hook_name": "calendar.after_delete"
},
{
"file": "app/plugins/builtins/unified_search/search_engine.py",
"hook_name": "search.before_search"
},
{
"file": "app/plugins/builtins/unified_search/search_engine.py",
"hook_name": "search.after_search"
},
{
"file": "app/plugins/builtins/kommunikation/services.py",
"hook_name": "comm.conversation.before_create"
},
{
"file": "app/plugins/builtins/kommunikation/services.py",
"hook_name": "comm.conversation.after_create"
},
{
"file": "app/plugins/builtins/kommunikation/services.py",
"hook_name": "comm.before_message"
},
{
"file": "app/plugins/builtins/kommunikation/services.py",
"hook_name": "comm.after_message"
},
{
"file": "app/plugins/builtins/kommunikation/services.py",
"hook_name": "comm.before_edit"
},
{
"file": "app/plugins/builtins/kommunikation/services.py",
"hook_name": "comm.after_edit"
},
{
"file": "app/plugins/builtins/kommunikation/services.py",
"hook_name": "comm.before_delete"
},
{
"file": "app/plugins/builtins/kommunikation/services.py",
"hook_name": "comm.after_delete"
},
{
"file": "app/plugins/builtins/tags/routes.py",
"hook_name": "tag.before_create"
},
{
"file": "app/plugins/builtins/tags/routes.py",
"hook_name": "tag.after_create"
},
{
"file": "app/plugins/builtins/tags/routes.py",
"hook_name": "tag.before_assign"
},
{
"file": "app/plugins/builtins/tags/routes.py",
"hook_name": "tag.after_assign"
},
{
"file": "app/plugins/builtins/tags/routes.py",
"hook_name": "tag.before_unassign"
},
{
"file": "app/plugins/builtins/tags/routes.py",
"hook_name": "tag.after_unassign"
},
{
"file": "app/plugins/builtins/tags/routes.py",
"hook_name": "tag.before_delete"
},
{
"file": "app/plugins/builtins/tags/routes.py",
"hook_name": "tag.after_delete"
}
]
}
@@ -7,13 +7,6 @@
"name": "SessionModel",
"line": 261,
"issue": "Name 'SessionModel' not found in module"
},
{
"file": "app/plugins/builtins/automation/agent_runner.py",
"module": "app.services.mail_service",
"name": "MailService",
"line": 115,
"issue": "Module not found"
}
]
}
File diff suppressed because it is too large Load Diff
+23 -10
View File
@@ -7,6 +7,23 @@ from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent.parent
APP = ROOT / "app"
# Simplified patterns — match either single or double quotes separately
PATTERNS_REG = [
r'register_(?:action|filter)s?\s*\(\s*"([^"]+)"',
r"register_(?:action|filter)s?\s*\(\s*'([^']+)'",
r'register_actions_by_owner\s*\(\s*"([^"]+)"',
r"register_actions_by_owner\s*\(\s*'([^']+)'",
]
PATTERNS_TRIG = [
r'do_action\s*\(\s*"([^"]+)"',
r"do_action\s*\(\s*'([^']+)'",
r'apply_filters?\s*\(\s*"([^"]+)"',
r"apply_filters?\s*\(\s*'([^']+)'",
r'trigger\s*\(\s*"([^"]+)"',
r"trigger\s*\(\s*'([^']+)'",
]
def find_hook_registrations():
regs = []
for py in APP.rglob("*.py"):
@@ -15,10 +32,9 @@ def find_hook_registrations():
except Exception:
continue
rel = str(py.relative_to(ROOT))
for m in re.finditer(r'register_(?:action|filter)s?\s*\(\s*["\']([^"\']+)['"]', content):
regs.append({"file": rel, "hook_type": "action_or_filter", "hook_name": m.group(1)})
for m in re.finditer(r'register_actions_by_owner\s*\(\s*["\']([^"\']+)['"]', content):
regs.append({"file": rel, "hook_type": "action_group", "hook_name": m.group(1)})
for pat in PATTERNS_REG:
for m in re.finditer(pat, content):
regs.append({"file": rel, "hook_name": m.group(1)})
return regs
def find_hook_triggers():
@@ -29,12 +45,9 @@ def find_hook_triggers():
except Exception:
continue
rel = str(py.relative_to(ROOT))
for m in re.finditer(r'do_action\s*\(\s*["\']([^"\']+)['"]', content):
triggers.append({"file": rel, "hook_name": m.group(1), "type": "action"})
for m in re.finditer(r'apply_filters?\s*\(\s*["\']([^"\']+)['"]', content):
triggers.append({"file": rel, "hook_name": m.group(1), "type": "filter"})
for m in re.finditer(r'trigger\s*\(\s*["\']([^"\']+)['"]', content):
triggers.append({"file": rel, "hook_name": m.group(1), "type": "trigger"})
for pat in PATTERNS_TRIG:
for m in re.finditer(pat, content):
triggers.append({"file": rel, "hook_name": m.group(1)})
return triggers
def main():