@@ -309,11 +309,51 @@ export function extractLabelData(body: any) {
309309}
310310
311311/**
312- * Infers the entity category from a Confluence webhook payload .
313- * Unlike Jira, Confluence payloads have no `event`/`webhookEvent` field —
314- * we detect the category by which entity key is present in the body .
312+ * Maps trigger IDs to the exact Confluence event strings they accept .
313+ * Admin REST API webhooks include an `event` field (e.g. `"event": "page_created"`).
314+ * Connect app webhooks do NOT — for those we fall back to entity-category matching .
315315 */
316- export function inferConfluenceEntityCategory ( body : Record < string , unknown > ) : string | null {
316+ const TRIGGER_EVENT_MAP : Record < string , string [ ] > = {
317+ confluence_page_created : [ 'page_created' ] ,
318+ confluence_page_updated : [ 'page_updated' ] ,
319+ confluence_page_removed : [ 'page_removed' , 'page_trashed' ] ,
320+ confluence_page_moved : [ 'page_moved' ] ,
321+ confluence_comment_created : [ 'comment_created' ] ,
322+ confluence_comment_removed : [ 'comment_removed' ] ,
323+ confluence_blog_created : [ 'blog_created' ] ,
324+ confluence_blog_updated : [ 'blog_updated' ] ,
325+ confluence_blog_removed : [ 'blog_removed' , 'blog_trashed' ] ,
326+ confluence_attachment_created : [ 'attachment_created' ] ,
327+ confluence_attachment_removed : [ 'attachment_removed' , 'attachment_trashed' ] ,
328+ confluence_space_created : [ 'space_created' ] ,
329+ confluence_space_updated : [ 'space_updated' ] ,
330+ confluence_label_added : [ 'label_added' , 'label_created' ] ,
331+ confluence_label_removed : [ 'label_removed' , 'label_deleted' ] ,
332+ }
333+
334+ const TRIGGER_CATEGORY_MAP : Record < string , string > = {
335+ confluence_page_created : 'page' ,
336+ confluence_page_updated : 'page' ,
337+ confluence_page_removed : 'page' ,
338+ confluence_page_moved : 'page' ,
339+ confluence_comment_created : 'comment' ,
340+ confluence_comment_removed : 'comment' ,
341+ confluence_blog_created : 'blog' ,
342+ confluence_blog_updated : 'blog' ,
343+ confluence_blog_removed : 'blog' ,
344+ confluence_attachment_created : 'attachment' ,
345+ confluence_attachment_removed : 'attachment' ,
346+ confluence_space_created : 'space' ,
347+ confluence_space_updated : 'space' ,
348+ confluence_label_added : 'label' ,
349+ confluence_label_removed : 'label' ,
350+ }
351+
352+ /**
353+ * Infers the entity category from a Confluence webhook payload by checking
354+ * which entity key is present in the body.
355+ */
356+ function inferEntityCategory ( body : Record < string , unknown > ) : string | null {
317357 if ( body . comment ) return 'comment'
318358 if ( body . attachment ) return 'attachment'
319359 if ( body . blog || body . blogpost ) return 'blog'
@@ -323,7 +363,13 @@ export function inferConfluenceEntityCategory(body: Record<string, unknown>): st
323363 return null
324364}
325365
326- /** Checks if a Confluence webhook payload matches a trigger's expected entity category. */
366+ /**
367+ * Checks if a Confluence webhook payload matches a trigger.
368+ *
369+ * Admin REST API webhooks (Settings > Webhooks) include an `event` field
370+ * for exact action-level matching. Connect app webhooks omit it, so we
371+ * fall back to entity-category matching (page vs comment vs blog, etc.).
372+ */
327373export function isConfluencePayloadMatch (
328374 triggerId : string ,
329375 body : Record < string , unknown >
@@ -332,29 +378,15 @@ export function isConfluencePayloadMatch(
332378 return true
333379 }
334380
335- const triggerCategoryMap : Record < string , string > = {
336- confluence_page_created : 'page' ,
337- confluence_page_updated : 'page' ,
338- confluence_page_removed : 'page' ,
339- confluence_page_moved : 'page' ,
340- confluence_comment_created : 'comment' ,
341- confluence_comment_removed : 'comment' ,
342- confluence_blog_created : 'blog' ,
343- confluence_blog_updated : 'blog' ,
344- confluence_blog_removed : 'blog' ,
345- confluence_attachment_created : 'attachment' ,
346- confluence_attachment_removed : 'attachment' ,
347- confluence_space_created : 'space' ,
348- confluence_space_updated : 'space' ,
349- confluence_label_added : 'label' ,
350- confluence_label_removed : 'label' ,
381+ const event = body . event as string | undefined
382+ if ( event ) {
383+ const acceptedEvents = TRIGGER_EVENT_MAP [ triggerId ]
384+ return acceptedEvents ? acceptedEvents . includes ( event ) : false
351385 }
352386
353- const expectedCategory = triggerCategoryMap [ triggerId ]
387+ const expectedCategory = TRIGGER_CATEGORY_MAP [ triggerId ]
354388 if ( ! expectedCategory ) {
355389 return false
356390 }
357-
358- const actualCategory = inferConfluenceEntityCategory ( body )
359- return actualCategory === expectedCategory
391+ return inferEntityCategory ( body ) === expectedCategory
360392}
0 commit comments