Skip to content

Slack Handler Reference

Technical reference for all Slack event handlers, action routers, submission processors, and view builders.

Last Updated: 2026-05-15


Handler Registration

All handlers are registered in src/app.ts:

typescript
// Events
app.event('app_home_opened', handleAppHomeOpenedEvent);

// View Submissions (catches ALL callback_ids)
app.view(/.*/, handleViewSubmission);

// Actions (catches ALL action_ids)
app.action(/.*/, handleActions);

// Shortcuts
app.shortcut('add_to_hub', handleSaveMessageShortcut);
app.shortcut('quick_add_knowledge', handleQuickAddKnowledgeShortcut);

// Error handling
app.error(async (error) => { logger.error('[App] Unhandled error:', error); });

Event Handlers

events.ts

EventHandlerDescription
app_home_openedhandleAppHomeOpenedEvent()Delegates to home/index.ts

The bot currently only subscribes to app_home_opened. URL/file detection events (message.channels, file_shared, reaction_added) are defined in the manifest but the handlers for them are deferred — the current code focuses on the App Home dashboard.

home/index.ts

Entry point that delegates to home/dynamic.ts:

typescript
export async function handleAppHomeOpened(args) → calls handleDynamicAppHome()

home/dynamic.ts

Renders the dynamic App Home tab with three view modes:

ModeConstantWhat it Shows
CategoriesHOME_TAB_MODES.CATEGORIESPaginated category list with overflow menus
Knowledge ItemsHOME_TAB_MODES.KNOWLEDGE_ITEMSAll knowledge items with details
AI SummariesHOME_TAB_MODES.AI_SUMMARIESAI-generated summaries per item

Users switch modes via a dropdown (VIEW_MODE_SELECTOR action). The home tab auto-refreshes after mutations (add knowledge, create category, etc.).


Shortcuts

shortcuts.ts

ShortcutTypeHandlerCallback ID
Add to YapHubMessagehandleSaveMessageShortcut()add_to_hub
Quick Add to YapHubGlobalhandleQuickAddKnowledgeShortcut()quick_add_knowledge

Message Shortcut Flow:

  1. User right-clicks a message > "Add to YapHub"
  2. Extracts message text, timestamps, channel info
  3. Detects URLs in the message text
  4. Opens save_message_modal with pre-filled content

Global Shortcut Flow:

  1. User clicks lightning bolt > "Quick Add to YapHub"
  2. Fetches categories from cache
  3. Opens add_knowledge_modal with empty form

Action Handler

actions.ts — Main Router

Routes all button clicks and menu selections. Uses a switch statement for known action IDs and prefix matching for dynamic actions.

Direct Actions:

Action IDHandlerDescription
add_list_from_homeOpens add_list_modalCreate new category
home_add_knowledgeOpens add_knowledge_modalAdd knowledge from home tab
open_add_modalOpens add_knowledge_modalAdd knowledge (generic)
home_open_digestOpens generate_digest_modalGenerate digest
home_open_distributionOpens distribute_digest_modalDistribute digest
home_open_settingsDelegates to categorySettings.tsCategory digest settings

Prefix-Based Actions:

PrefixHandlerExample
category_overflow_handleCategoryOverflowAction()category_overflow_123

Category Overflow Operations (value format: actionType:categoryId):

Action TypeWhat Happens
add_knowledgeOpens add modal with category pre-selected
digestOpens digest modal with category pre-selected
distributeDelegates to distribution.ts
settingsDelegates to categorySettings.ts
subscribeDelegates to subscription.ts
unsubscribeDelegates to subscription.ts

actions/categorySettings.ts

Handles category-level digest configuration:

  • Opens settings modal for a category
  • Handles category selection within settings
  • Processes digest config updates (enabled, frequency, day, time)

actions/distribution.ts

Handles digest distribution to subscribers:

  • Category selection in distribution modal
  • Digest list loading for a category
  • Distribution confirmation (sends to subscribers)
  • Direct distribution from category overflow menu

actions/subscription.ts

Handles subscribe/unsubscribe from category overflow menus.


Submission Handler

submissions.ts — Main Router

Routes all modal submissions by callback_id (view ID).

Callback IDs (from VIEW_IDS constant):

Callback IDHandlerDescription
add_list_modalInlineCreates a new category via backend API
add_knowledge_modalInlineCreates a new knowledge item
save_message_modalInlineSaves a Slack message as knowledge
generate_digest_modaldigestHandler.tsGenerates AI digest
distribute_digest_modaldistribution.tsConfirms digest distribution
category_settings_modalInlineSaves digest config (via services/categorySettings.ts)
UnknownLogs warning, acksFallback

Common Pattern:

  1. Acknowledge immediately (await ack())
  2. Extract form values from view.state.values using BLOCK_IDS and ACTION_IDS constants
  3. Call backend API via services
  4. Send confirmation DM to user
  5. Refresh App Home tab

submissions/digestHandler.ts

Handles the heavy digest generation work:

  • validateDigestSubmission(view) — validates form, returns errors or null
  • handleDigestSubmission(view, userId, client) — async digest generation
  • Runs in background (not awaited in the router) to avoid Slack's 3-second timeout
  • Errors are caught and sent to the user as DMs

submissions/api/sendDigest.ts

Express API handler for POST /api/slack/send-digest. Called by the Symfony backend to deliver digests via DM. Requires Bearer token auth matching BACKEND_API_TOKEN.


View Builders

All modals are built in src/views/modals/ using Slack Block Kit. Builders are pure functions that return view objects.

Knowledge Modals

BuilderFileModal
buildAddKnowledgeModal()views/modals/knowledge/addKnowledge.tsadd_knowledge_modal
buildSaveMessageModal()views/modals/knowledge/saveMessage.tssave_message_modal

Add Knowledge Modal Fields:

  • Title (title_block / title_input)
  • Content (content_block / content_input)
  • Category (list_block / list_select)
  • URL (url_block / url_input)
  • Tags (tags_block / tags_input)

Category Modals

BuilderFileModal
buildAddListModal()views/modals/categories/addList.tsadd_list_modal
Category settingsviews/modals/categories/categorySettings.tscategory_settings_modal

Add List Modal Fields:

  • Name (name_block / name_input)
  • Description (description_block / description_input)
  • Icon (icon_block / icon_input)

Digest Modals

BuilderFileModal
buildGenerateDigestModal()views/modals/digest/generateDigest.tsgenerate_digest_modal
buildDistributionModal()views/modals/digest/distributeDigest.tsdistribute_digest_modal

Home Tab

BuilderFile
Dynamic home tabviews/home/dynamicHomeTab.ts
Category listviews/home/categoriesView.ts

Home tab supports three modes via HOME_TAB_MODES: categories, knowledge items, AI summaries.


Services

All services in src/services/ communicate with the Symfony backend via HTTP using a shared Axios client (utils/api.ts).

ServiceFileBackend Endpoints
categories.tslistCategories(), addCategory()/api/categories
knowledge.tsaddKnowledge(), listKnowledge()/api/knowledge
digest.tsgenerateDigest(), distributeDigest(), getDigestsByCategory()/api/digests/generate, /api/digests/{id}/distribute, /api/digests/category/{categoryId}
subscriptions.tsgetUserSubscriptions(), subscribeUserToCategory(), unsubscribeUserFromCategory()/api/subscriptions/user/{userId}, /api/subscriptions/subscribe, /api/subscriptions/unsubscribe
categorySettings.tsgetDigestConfig(), updateDigestConfig()/api/categories/{id}/settings/digest

All requests include Authorization: Bearer $BACKEND_API_TOKEN header.


Constants Reference

All IDs are centralized in src/constants/ to prevent magic strings.

Action IDs (action_ids.ts)

ConstantValueUsed In
HOME_ADD_KNOWLEDGEhome_add_knowledgeAdd knowledge button on home tab
ADD_LIST_FROM_HOMEadd_list_from_homeCreate category button
HOME_OPEN_DIGESThome_open_digestOpen digest modal
HOME_OPEN_DISTRIBUTIONhome_open_distributionOpen distribution modal
HOME_OPEN_SETTINGShome_open_settingsOpen category settings
VIEW_MODE_SELECTORview_mode_selectorHome tab mode dropdown

View IDs / Modal Callback IDs (view_ids.ts)

ConstantValue
ADD_KNOWLEDGEadd_knowledge_modal
SAVE_MESSAGEsave_message_modal
ADD_LISTadd_list_modal
GENERATE_DIGESTgenerate_digest_modal
DISTRIBUTE_DIGESTdistribute_digest_modal
CATEGORY_SETTINGScategory_settings_modal

Action Prefixes (action_ids.ts)

ConstantPrefixPurpose
CATEGORY_OVERFLOWcategory_overflow_Category overflow menus
SETTINGS_OPEN_DIGESTsettings_open_digest:Quick-open digest from settings
SETTINGS_OPEN_DISTRIBUTIONsettings_open_distribution:Quick-open distribution from settings

Error Handling

Pattern

All handlers follow the same error pattern:

typescript
try {
  // handler logic
} catch (error) {
  logger.error(`[Handler] Error:`, error);
  // User-facing error as DM
  await client.chat.postMessage({
    channel: body.user.id,
    text: '❌ Er is een fout opgetreden. Probeer het opnieuw.',
  });
}

API Error Extraction

The getApiErrorMessage() helper in submissions.ts extracts human-readable messages from backend errors:

  • data.message — standard backend errors
  • data.detail — Symfony validation errors
  • data.violations — constraint violations (joined)

Acknowledgment

  • All actions and submissions are acknowledged immediately
  • Digest generation is acked first, then runs in background
  • Validation errors use ack({ response_action: 'errors', errors: {...} })

Testing

See Slack Bot Testing for the full test suite reference.

bash
cd slack
npm test                # Run all tests
npm run test:watch      # Watch mode
npm run test:coverage   # Coverage report