feat(threads): thread and forum API, admin, schemas and docs (#3251)

This commit is contained in:
Hampus authored and GitHub committed 2026-10-07 15:25:12 +02:00
1 parent 5f4295e399
commit 3f4160b138
495 files changed
+39232 -1215

No files matched your search

@@ -6,6 +6,8 @@ import {Config} from '@app/api/Config';
import type {IChannelRepository} from '@app/api/channel/IChannelRepository';
import type {MessageUpdateRequest} from '@app/api/channel/MessageTypes';
import {createMessageResponseDataService} from '@app/api/channel/services/message/MessageResponseDataService';
import {maskThreadArtifactsFor} from '@app/api/channel/services/message/ThreadMessageResponses';
import {SYSTEM_THREAD_VIEWER, type ThreadViewer} from '@app/api/experiment/ChannelThreadsGate';
import type {IGatewayService} from '@app/api/infrastructure/IGatewayService';
import type {LiveKitWebhookService} from '@app/api/infrastructure/LiveKitWebhookService';
import type {UserCacheService} from '@app/api/infrastructure/UserCacheService';
@@ -36,18 +38,21 @@ type WebhookExecutionResponse = MessageResponse | null;
interface WebhookListGuildParams {
userId: UserID;
viewer: ThreadViewer;
guildId: GuildID;
requestCache: RequestCache;
}
interface WebhookListChannelParams {
userId: UserID;
viewer: ThreadViewer;
channelId: ChannelID;
requestCache: RequestCache;
}
interface WebhookCreateParams {
userId: UserID;
viewer: ThreadViewer;
channelId: ChannelID;
data: WebhookCreateRequest;
requestCache: RequestCache;
@@ -56,6 +61,7 @@ interface WebhookCreateParams {
interface WebhookGetByUserParams {
userId: UserID;
viewer: ThreadViewer;
webhookId: WebhookID;
requestCache: RequestCache;
}
@@ -70,6 +76,7 @@ type WebhookGetParams = WebhookGetByUserParams | WebhookGetByTokenParams;
interface WebhookUpdateByUserParams {
userId: UserID;
viewer: ThreadViewer;
webhookId: WebhookID;
data: WebhookUpdateRequest;
requestCache: RequestCache;
@@ -87,6 +94,7 @@ type WebhookUpdateParams = WebhookUpdateByUserParams | WebhookUpdateByTokenParam
interface WebhookDeleteByUserParams {
userId: UserID;
viewer: ThreadViewer;
webhookId: WebhookID;
auditLogReason?: string | null;
}
@@ -101,6 +109,7 @@ type WebhookDeleteParams = WebhookDeleteByUserParams | WebhookDeleteByTokenParam
interface WebhookExecuteParams {
webhookId: WebhookID;
token: WebhookToken;
threadId?: string;
data: WebhookExecuteMessageData;
wait: boolean;
requestCache: RequestCache;
@@ -109,6 +118,7 @@ interface WebhookExecuteParams {
interface WebhookGetMessageParams {
webhookId: WebhookID;
token: WebhookToken;
threadId?: string;
messageId: MessageID;
requestCache: RequestCache;
}
@@ -116,6 +126,7 @@ interface WebhookGetMessageParams {
interface WebhookEditMessageParams {
webhookId: WebhookID;
token: WebhookToken;
threadId?: string;
messageId: MessageID;
data: MessageUpdateRequest;
requestCache: RequestCache;
@@ -124,6 +135,7 @@ interface WebhookEditMessageParams {
interface WebhookDeleteMessageParams {
webhookId: WebhookID;
token: WebhookToken;
threadId?: string;
messageId: MessageID;
requestCache: RequestCache;
}
@@ -131,6 +143,7 @@ interface WebhookDeleteMessageParams {
interface WebhookExecuteGitHubParams {
webhookId: WebhookID;
token: WebhookToken;
threadId?: string;
event: string;
delivery: string;
data: GitHubWebhook;
@@ -140,6 +153,7 @@ interface WebhookExecuteGitHubParams {
interface WebhookExecuteSlackParams {
webhookId: WebhookID;
token: WebhookToken;
threadId?: string;
data: SlackWebhookRequest;
requestCache: RequestCache;
}
@@ -184,6 +198,7 @@ export class WebhookRequestService {
async listGuildWebhooks(params: WebhookListGuildParams): Promise<Array<WebhookResponse>> {
const webhooks = await this.webhookService.getGuildWebhooks({
userId: params.userId,
viewer: params.viewer,
guildId: params.guildId,
});
return mapWebhooksToResponse({
@@ -197,6 +212,7 @@ export class WebhookRequestService {
async listChannelWebhooks(params: WebhookListChannelParams): Promise<Array<WebhookResponse>> {
const webhooks = await this.webhookService.getChannelWebhooks({
userId: params.userId,
viewer: params.viewer,
channelId: params.channelId,
});
return mapWebhooksToResponse({
@@ -211,6 +227,7 @@ export class WebhookRequestService {
const webhook = await this.webhookService.createWebhook(
{
userId: params.userId,
viewer: params.viewer,
channelId: params.channelId,
data: params.data,
},
@@ -230,7 +247,11 @@ export class WebhookRequestService {
const webhook = await this.webhookService.getWebhookByToken({webhookId: params.webhookId, token: params.token});
return mapWebhookToTokenResponse(webhook);
}
const webhook = await this.webhookService.getWebhook({userId: params.userId, webhookId: params.webhookId});
const webhook = await this.webhookService.getWebhook({
userId: params.userId,
viewer: params.viewer,
webhookId: params.webhookId,
});
return mapWebhookToResponseWithCache({
webhook,
userCacheService: this.userCacheService,
@@ -253,6 +274,7 @@ export class WebhookRequestService {
const webhook = await this.webhookService.updateWebhook(
{
userId: params.userId,
viewer: params.viewer,
webhookId: params.webhookId,
data: params.data,
},
@@ -274,6 +296,7 @@ export class WebhookRequestService {
await this.webhookService.deleteWebhook(
{
userId: params.userId,
viewer: params.viewer,
webhookId: params.webhookId,
},
params.auditLogReason ?? null,
@@ -284,6 +307,7 @@ export class WebhookRequestService {
const message = await this.webhookService.executeWebhook({
webhookId: params.webhookId,
token: params.token,
threadId: params.threadId,
data: params.data,
requestCache: params.requestCache,
});
@@ -297,6 +321,7 @@ export class WebhookRequestService {
const message = await this.webhookService.getWebhookMessage({
webhookId: params.webhookId,
token: params.token,
threadId: params.threadId,
messageId: params.messageId,
});
return this.mapMessageResponse(message, params.requestCache);
@@ -306,6 +331,7 @@ export class WebhookRequestService {
const message = await this.webhookService.editWebhookMessage({
webhookId: params.webhookId,
token: params.token,
threadId: params.threadId,
messageId: params.messageId,
data: params.data,
requestCache: params.requestCache,
@@ -317,6 +343,7 @@ export class WebhookRequestService {
await this.webhookService.deleteWebhookMessage({
webhookId: params.webhookId,
token: params.token,
threadId: params.threadId,
messageId: params.messageId,
requestCache: params.requestCache,
});
@@ -326,6 +353,7 @@ export class WebhookRequestService {
await this.webhookService.executeGitHubWebhook({
webhookId: params.webhookId,
token: params.token,
threadId: params.threadId,
event: params.event,
delivery: params.delivery,
data: params.data,
@@ -346,8 +374,10 @@ export class WebhookRequestService {
await this.webhookService.executeWebhook({
webhookId: params.webhookId,
token: params.token,
threadId: params.threadId,
data: transformSlackWebhookRequest(params.data),
requestCache: params.requestCache,
service: true,
});
}
@@ -381,7 +411,7 @@ export class WebhookRequestService {
private async mapMessageResponse(message: Message, _requestCache: RequestCache): Promise<MessageResponse> {
const channel = await this.channelRepository.findUnique(message.channelId);
return createMessageResponseDataService().buildMessage({
const response = await createMessageResponseDataService().buildMessage({
userId: createUserID(0n),
message,
access: {
@@ -390,5 +420,7 @@ export class WebhookRequestService {
canReadMessageHistory: true,
},
});
const [shaped] = maskThreadArtifactsFor(SYSTEM_THREAD_VIEWER, channel?.guildId ?? null, [response]);
return shaped ?? response;
}
}