Skip to content

Commit

Permalink
feat: notify admins when a thread has 100 messages 🚨 (#605)
Browse files Browse the repository at this point in the history
  • Loading branch information
ciaracade authored Dec 7, 2024
1 parent 4ab0538 commit ee5e738
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 6 deletions.
1 change: 1 addition & 0 deletions apps/api/src/routers/slack.router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ slackEventRouter.post('/slack/events', async (req: RawBodyRequest, res) => {
hasFile: !!event.files && !!event.files.length,
id: event.ts!,
isBot: !!event.app_id || !!event.bot_id,
replyCount: event.message?.reply_count,
text: event.text!,
threadId:
event.ts && event.thread_ts && event.ts !== event.thread_ts
Expand Down
5 changes: 5 additions & 0 deletions apps/api/src/routers/slack.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,17 @@ type SlackMessageDeletedEvent = {

/**
* @see https://api.slack.com/events/message
* @see https://api.slack.com/events/message/message_replied
*/
type SlackMessageSentEvent = {
app_id?: string;
bot_id?: string;
channel: string;
files?: unknown[];
message?: {
// Only present if the message is a reply.
reply_count?: number;
};
subtype: undefined;
text: string;
thread_ts: string | undefined;
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/infrastructure/bull/bull.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,7 @@ export const SlackBullJob = z.discriminatedUnion('name', [
}).extend({
hasFile: z.boolean().optional(),
isBot: z.boolean().optional(),
replyCount: z.number().int().optional(),
}),
}),
z.object({
Expand Down
39 changes: 33 additions & 6 deletions packages/core/src/modules/slack/use-cases/add-slack-message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import { type GetBullJobData } from '@/infrastructure/bull/bull.types';
import { job } from '@/infrastructure/bull/use-cases/job';
import { redis } from '@/infrastructure/redis';
import { isFeatureFlagEnabled } from '@/modules/feature-flag/queries/is-feature-flag-enabled';
import { slack } from '@/modules/slack/instances';
import { ErrorWithContext } from '@/shared/errors';
import { retryWithBackoff } from '@/shared/utils/core.utils';
import { getSlackMessage } from '../services/slack-message.service';

export async function addSlackMessage(
data: GetBullJobData<'slack.message.add'>
) {
type AddSlackMessageInput = GetBullJobData<'slack.message.add'>;

export async function addSlackMessage(data: AddSlackMessageInput) {
await ensureThreadExistsIfNecessary(data);

const student = await db
Expand Down Expand Up @@ -53,6 +54,14 @@ export async function addSlackMessage(
threadId: data.threadId || data.id,
});

if (data.replyCount === 100) {
// We don't need to await this since it's not a critical path.
notifyBusySlackThread({
channelId: data.channelId,
id: data.id,
});
}

// We'll do some additional checks for top-level threads...
if (!data.threadId) {
const [
Expand Down Expand Up @@ -111,9 +120,7 @@ export async function addSlackMessage(
}
}

async function ensureThreadExistsIfNecessary(
data: GetBullJobData<'slack.message.add'>
) {
async function ensureThreadExistsIfNecessary(data: AddSlackMessageInput) {
// Don't need to bother if there is no thread.
if (!data.threadId) {
return;
Expand Down Expand Up @@ -174,3 +181,23 @@ async function ensureThreadExistsIfNecessary(
}
);
}

/**
* Sends a notification to the internal team when a thread gets over 100
* replies. The motivation is that some threads can get a little too spicy
* and we want to moderate them quickly in case of abuse.
*/
async function notifyBusySlackThread({
channelId,
id,
}: Pick<AddSlackMessageInput, 'channelId' | 'id'>) {
const { permalink } = await slack.chat.getPermalink({
channel: channelId,
message_ts: id,
});

job('notification.slack.send', {
message: `🚨 Heads up! This <${permalink}|thread> has over 💯 replies!`,
workspace: 'internal',
});
}

0 comments on commit ee5e738

Please sign in to comment.