( userId: string, message: SlackBlockMessage )
| 363 | * Send a direct message to a user |
| 364 | */ |
| 365 | export async function sendDirectMessage( |
| 366 | userId: string, |
| 367 | message: SlackBlockMessage |
| 368 | ): Promise<{ ok: boolean; ts?: string; error?: string }> { |
| 369 | try { |
| 370 | // First, open a DM channel with the user |
| 371 | const imResponse = await slackPostRequest<{ channel: { id: string } }>('conversations.open', { |
| 372 | users: userId, |
| 373 | }); |
| 374 | |
| 375 | const channelId = imResponse.channel.id; |
| 376 | |
| 377 | // Send the message |
| 378 | const messageResponse = await slackPostRequest<{ ts: string }>('chat.postMessage', { |
| 379 | channel: channelId, |
| 380 | text: message.text, |
| 381 | blocks: message.blocks, |
| 382 | }); |
| 383 | |
| 384 | logger.info({ userId, ts: messageResponse.ts }, 'Sent Slack DM'); |
| 385 | return { ok: true, ts: messageResponse.ts }; |
| 386 | } catch (error) { |
| 387 | const errorMessage = error instanceof Error ? error.message : 'Unknown error'; |
| 388 | logger.error({ error, userId }, 'Failed to send Slack DM'); |
| 389 | return { ok: false, error: errorMessage }; |
| 390 | } |
| 391 | } |
| 392 | |
| 393 | /** |
| 394 | * Privacy state of a configured Slack channel at send time. Distinguishes |
no outgoing calls
no test coverage detected