Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions apps/api/src/handlers/account-link-help.test.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions apps/api/src/handlers/account-link-help.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { getDeploymentAccountLinkHelpText } from '@roomote/db/server';

import { apiLogger } from '../logging.js';

export async function appendAccountLinkHelpText(
baseMessage: string,
): Promise<string> {
try {
const helpText = await getDeploymentAccountLinkHelpText();
return helpText ? `${baseMessage} ${helpText}` : baseMessage;
} catch (error) {
apiLogger.warn(
`[account-link] Failed to load deployment help text: ${error instanceof Error ? error.message : String(error)}`,
);
return baseMessage;
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/api/src/handlers/ado/handleComment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ export async function handleAdoComment(
const body =
targetsResult.status === 'error' &&
targetsResult.code === 'account_link_required'
? buildSourceControlAccountLinkRequiredMessage('ado')
? await buildSourceControlAccountLinkRequiredMessage('ado')
: buildReviewerGateMissComment();

await postMentionResponseComment({
Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/handlers/ado/handleWorkItemComment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ export async function handleAdoWorkItemComment(
await postWorkItemMentionResponseComment({
project: projectName,
workItemId,
body: buildSourceControlAccountLinkRequiredMessage('ado'),
body: await buildSourceControlAccountLinkRequiredMessage('ado'),
});

return { status: 'ok', message: 'account_link_required' };
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/api/src/handlers/bitbucket/handleComment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ export async function handleBitbucketComment(
await postMentionResponseComment({
...mentionResponseTarget,
body: requiresAccountLink
? buildSourceControlAccountLinkRequiredMessage('bitbucket')
? await buildSourceControlAccountLinkRequiredMessage('bitbucket')
: requiresEnvironment
? buildSourceControlEnvironmentRequiredMessage('bitbucket')
: buildReviewerGateMissComment(),
Expand Down
28 changes: 25 additions & 3 deletions apps/api/src/handlers/discord/__tests__/account-link.test.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions apps/api/src/handlers/discord/__tests__/index.test.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 18 additions & 11 deletions apps/api/src/handlers/discord/account-link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Env } from '@roomote/env';
import { getRedis } from '@roomote/redis';

import { apiLogger } from '../../logging.js';
import { appendAccountLinkHelpText } from '../account-link-help.js';
import { replyToDiscordEvent } from './replies.js';
import type { DiscordChannelContext } from './task-launch.js';

Expand All @@ -34,17 +35,21 @@ export function buildDiscordAccountLinkFallbackInstruction(): string {
return `Generate a code under ${formatDiscordLinkedAccountsPath()}, then ${DISCORD_LINK_CODE_INSTRUCTION}.`;
}

export function buildDiscordLinkRequiredMessage(): string {
return `Link your Discord account to Roomote before starting tasks. ${buildDiscordAccountLinkFallbackInstruction()}`;
export async function buildDiscordLinkRequiredMessage(): Promise<string> {
return appendAccountLinkHelpText(
`Link your Discord account to Roomote before starting tasks. ${buildDiscordAccountLinkFallbackInstruction()}`,
);
}

export function buildDiscordChannelAutoStartLinkMessage(
export async function buildDiscordChannelAutoStartLinkMessage(
channelName: string,
): string {
return [
`Roomote watches **#${channelName}** and starts a task for each new message, but your Discord account is not linked to a Roomote account yet, so your message did not start one.`,
`Generate a code under ${formatDiscordLinkedAccountsPath()} in Roomote, then reply here with \`/link code:<code>\`.`,
].join('\n\n');
): Promise<string> {
return appendAccountLinkHelpText(
[
`Roomote watches **#${channelName}** and starts a task for each new message, but your Discord account is not linked to a Roomote account yet, so your message did not start one.`,
`Generate a code under ${formatDiscordLinkedAccountsPath()} in Roomote, then reply here with \`/link code:<code>\`.`,
].join('\n\n'),
);
}

// One link DM per user per day across every entry path (mentions, slash
Expand Down Expand Up @@ -243,7 +248,7 @@ export async function promptDiscordAccountLink(input: {
applicationId: input.applicationId,
channel: input.channel,
...(input.interaction ? { interaction: input.interaction } : {}),
text: buildDiscordLinkRequiredMessage(),
text: await buildDiscordLinkRequiredMessage(),
...(input.replyToMessageId
? { replyToMessageId: input.replyToMessageId }
: {}),
Expand Down Expand Up @@ -296,7 +301,7 @@ export async function promptDiscordAccountLink(input: {
);
await input.provider.postMessage({
channelId: dmChannel.id,
text: buildDiscordLinkRequiredMessage(),
text: await buildDiscordLinkRequiredMessage(),
});
dmPromptSent = true;
if (slot === 'claimed') {
Expand Down Expand Up @@ -332,7 +337,9 @@ export async function promptDiscordAccountLink(input: {
text: buildAccountLinkThreadReplyText({
dmPromptSent,
accountLabel: DISCORD_ACCOUNT_LABEL,
fallbackInstruction: buildDiscordAccountLinkFallbackInstruction(),
fallbackInstruction: await appendAccountLinkHelpText(
buildDiscordAccountLinkFallbackInstruction(),
),
}),
...(input.replyToMessageId
? { replyToMessageId: input.replyToMessageId }
Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/handlers/discord/channel-auto-start.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ async function sendLinkNudgeBestEffort(input: {
);
await input.provider.postMessage({
channelId: dmChannel.id,
text: buildDiscordChannelAutoStartLinkMessage(input.channelName),
text: await buildDiscordChannelAutoStartLinkMessage(input.channelName),
});
await markAccountLinkDmSent(input.discordUserId);
} catch (error) {
Expand Down
4 changes: 2 additions & 2 deletions apps/api/src/handlers/gitea/handleComment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ async function handleGiteaIssueComment({
body:
targetsResult.status === 'error' &&
targetsResult.code === 'account_link_required'
? buildSourceControlAccountLinkRequiredMessage('gitea')
? await buildSourceControlAccountLinkRequiredMessage('gitea')
: buildIssueGateMissComment(),
});

Expand Down Expand Up @@ -465,7 +465,7 @@ async function handleGiteaPullRequestComment({
body:
targetsResult.status === 'error' &&
targetsResult.code === 'account_link_required'
? buildSourceControlAccountLinkRequiredMessage('gitea')
? await buildSourceControlAccountLinkRequiredMessage('gitea')
: targetsResult.status === 'error' &&
targetsResult.message.includes('no environment mapping')
? buildSourceControlEnvironmentRequiredMessage('gitea')
Expand Down
4 changes: 2 additions & 2 deletions apps/api/src/handlers/github/handleGitHubIssueComment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ export async function handleGitHubIssueComment(
...replyTarget,
body:
commenterGate.code === 'account_link_required'
? buildSourceControlAccountLinkRequiredMessage('github')
? await buildSourceControlAccountLinkRequiredMessage('github')
: buildGateMissComment(),
});

Expand All @@ -198,7 +198,7 @@ export async function handleGitHubIssueComment(
if (!target?.properties.userId) {
await postIssueComment({
...replyTarget,
body: buildSourceControlAccountLinkRequiredMessage('github'),
body: await buildSourceControlAccountLinkRequiredMessage('github'),
});

return { status: 'ok', message: 'account_link_required' };
Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/handlers/github/handlePrComment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1195,7 +1195,7 @@ export async function handlePrComment(
target: mentionResponseTarget,
body:
reviewerGate.code === 'account_link_required'
? buildSourceControlAccountLinkRequiredMessage('github')
? await buildSourceControlAccountLinkRequiredMessage('github')
: buildReviewerGateMissComment(),
});

Expand Down
4 changes: 2 additions & 2 deletions apps/api/src/handlers/gitlab/handleNote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ async function handleGitLabIssueNote({
body:
targetsResult.status === 'error' &&
targetsResult.code === 'account_link_required'
? buildSourceControlAccountLinkRequiredMessage('gitlab')
? await buildSourceControlAccountLinkRequiredMessage('gitlab')
: buildIssueGateMissNote(),
});

Expand Down Expand Up @@ -383,7 +383,7 @@ async function handleGitLabMergeRequestNote({
body:
targetsResult.status === 'error' &&
targetsResult.code === 'account_link_required'
? buildSourceControlAccountLinkRequiredMessage('gitlab')
? await buildSourceControlAccountLinkRequiredMessage('gitlab')
: buildReviewerGateMissNote(),
});

Expand Down
32 changes: 32 additions & 0 deletions apps/api/src/handlers/source-control-account-linking.test.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading