Skip to content

Commit 2c91983

Browse files
committed
check bot in channel
1 parent 9745490 commit 2c91983

3 files changed

Lines changed: 38 additions & 5 deletions

File tree

src/backend/src/integrations/slack.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,23 @@ export const getChannelName = async (channelId: string) => {
271271
}
272272
};
273273

274+
/**
275+
* Checks whether the bot is a member of the given channel
276+
* @param channelId the id of the slack channel
277+
* @returns true if the bot is a member of the channel, false otherwise
278+
*/
279+
export const checkBotInChannel = async (channelId: string): Promise<boolean> => {
280+
const client = getSlackClient();
281+
if (!client) return false;
282+
283+
try {
284+
const channelRes = await client.conversations.info({ channel: channelId });
285+
return channelRes.channel?.is_member ?? false;
286+
} catch (error) {
287+
return false;
288+
}
289+
};
290+
274291
/**
275292
* Given a slack user id, prood.uces the name of the channel
276293
* @param userId the id of the slack user

src/backend/src/services/attendance.services.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
meetingAttendanceTransformer,
1111
meetingAttendanceWithAttendeesTransformer
1212
} from '../transformers/attendance.transformer.js';
13-
import { editMessage, getChannelName, replyToMessageInThread, sendMessage } from '../integrations/slack.js';
13+
import { checkBotInChannel, editMessage, getChannelName, replyToMessageInThread, sendMessage } from '../integrations/slack.js';
1414
import { userHasPermission } from '../utils/users.utils.js';
1515

1616
export default class AttendanceService {
@@ -215,6 +215,7 @@ export default class AttendanceService {
215215
}
216216

217217
const channelName = await getChannelName(team.slackId);
218-
return { channelName, valid: !!channelName };
218+
const botInChannel = channelName ? await checkBotInChannel(team.slackId) : false;
219+
return { channelName, valid: !!channelName && botInChannel };
219220
}
220221
}

src/backend/tests/unit/attendance.test.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ import { AccessDeniedException, HttpException, NotFoundException } from '../../s
55
import { batmanAppAdmin, supermanAdmin, greenlanternHead, wonderwomanGuest, member } from '../test-data/users.test-data.js';
66
import { createTestOrganization, createTestTeam, createTestTeamType, createTestUser, resetUsers } from '../test-utils.js';
77
import prisma from '../../src/prisma/prisma.js';
8-
import { sendMessage, editMessage, replyToMessageInThread, getChannelName } from '../../src/integrations/slack.js';
8+
import { sendMessage, editMessage, replyToMessageInThread, getChannelName, checkBotInChannel } from '../../src/integrations/slack.js';
99
import { Mock } from 'vitest';
1010

1111
vi.mock('../../src/integrations/slack.js', () => ({
1212
sendMessage: vi.fn(),
1313
editMessage: vi.fn(),
1414
replyToMessageInThread: vi.fn(),
15-
getChannelName: vi.fn()
15+
getChannelName: vi.fn(),
16+
checkBotInChannel: vi.fn()
1617
}));
1718

1819
// Creates a second test org with distinct credentials (since createTestOrganization uses a hardcoded empty email)
@@ -531,11 +532,25 @@ describe('Attendance Tests', () => {
531532
expect(result.channelName).toBeUndefined();
532533
});
533534

534-
it('returns valid: true with channel name if Slack channel is found', async () => {
535+
it('returns valid: false if Slack channel is found but bot is not a member', async () => {
535536
const head = await createTestUser(greenlanternHead, orgId);
536537
const team = await createTeamInOrg(head.userId, orgId);
537538

538539
(getChannelName as Mock).mockResolvedValue('ner-software');
540+
(checkBotInChannel as Mock).mockResolvedValue(false);
541+
542+
const result = await AttendanceService.checkTeamChannel(team.teamId, organization);
543+
544+
expect(result.valid).toBe(false);
545+
expect(result.channelName).toBe('ner-software');
546+
});
547+
548+
it('returns valid: true with channel name if Slack channel is found and bot is a member', async () => {
549+
const head = await createTestUser(greenlanternHead, orgId);
550+
const team = await createTeamInOrg(head.userId, orgId);
551+
552+
(getChannelName as Mock).mockResolvedValue('ner-software');
553+
(checkBotInChannel as Mock).mockResolvedValue(true);
539554

540555
const result = await AttendanceService.checkTeamChannel(team.teamId, organization);
541556

0 commit comments

Comments
 (0)