feat: add announcement channels, publishing and following (#3090)

This commit is contained in:
Hampus authored and GitHub committed 2026-10-01 16:57:21 +02:00
1 parent 376afd2ad6
commit 7e4d5137f8
381 files changed
+45650 -14076

No files matched your search

@@ -15,6 +15,8 @@ import {MessageEmbedAttachmentResolver} from '@app/api/channel/services/message/
import {
assertAttachmentFileSizesWithinLimit,
collectMessageAttachments,
isCrosspostCopy,
keepOwnedEmbedAttachments,
} from '@app/api/channel/services/message/MessageHelpers';
import {MessageStickerService} from '@app/api/channel/services/message/MessageStickerService';
import {getContentMessage} from '@app/api/content_i18n/ContentI18n';
@@ -111,6 +113,9 @@ interface CreateMessageParams {
};
allowEmbeds?: boolean;
dmNsfwContext?: DmNsfwContext;
processedEmbeds?: Array<MessageEmbed>;
processedStickerItems?: Array<MessageStickerItem>;
skipDeferredEmbeds?: boolean;
}
export class MessagePersistenceService {
@@ -190,8 +195,12 @@ export class MessagePersistenceService {
const allowEmbeds = params.allowEmbeds ?? true;
let initialEmbeds: Array<MessageEmbed> | null = null;
let hasUncachedUrls = false;
const referencedFilenames = this.embedAttachmentResolver.collectReferencedAttachmentFilenames(params.embeds);
if (allowEmbeds) {
const referencedFilenames = params.processedEmbeds
? new Set<string>()
: this.embedAttachmentResolver.collectReferencedAttachmentFilenames(params.embeds);
if (params.processedEmbeds) {
initialEmbeds = params.processedEmbeds.length > 0 ? params.processedEmbeds : null;
} else if (allowEmbeds) {
const resolvedEmbeds = this.embedAttachmentResolver.resolveEmbedAttachmentUrls({
embeds: params.embeds,
attachments: processedAttachments.map(mapAttachmentForEmbedResolution),
@@ -299,6 +308,9 @@ export class MessagePersistenceService {
params: CreateMessageParams,
authorId: UserID | null,
): Promise<Array<MessageStickerItem>> {
if (params.processedStickerItems) {
return params.processedStickerItems;
}
if (!params.stickerIds || params.stickerIds.length === 0) {
return [];
}
@@ -320,7 +332,7 @@ export class MessagePersistenceService {
}): Promise<() => Promise<void>> {
const {message, params, authorId, allowEmbeds, hasUncachedUrls, isNSFWAllowed} = context;
const operations: Array<Promise<unknown>> = [];
const trackedAttachments = collectMessageAttachments(message);
const trackedAttachments = isCrosspostCopy(message) ? [] : collectMessageAttachments(message);
if (trackedAttachments.length > 0) {
const uploadedAt = snowflakeToDate(params.messageId);
const decayPayloads = trackedAttachments.map((att) => ({
@@ -334,7 +346,7 @@ export class MessagePersistenceService {
operations.push(this.attachmentDecayService.upsertMany(decayPayloads));
}
let enqueueDeferredEmbeds: () => Promise<void> = () => Promise.resolve();
if (allowEmbeds && hasUncachedUrls) {
if (allowEmbeds && hasUncachedUrls && !params.skipDeferredEmbeds) {
enqueueDeferredEmbeds = () =>
this.embedService.enqueueUrlEmbedExtraction(
params.channelId,
@@ -524,6 +536,7 @@ export class MessagePersistenceService {
isBugHunterBot: params.isBugHunterBot,
});
if (embedsExplicitlyProvided) {
keepOwnedEmbedAttachments(message, initialEmbeds);
updatedRowData.embeds = initialEmbeds;
} else {
const preservedEmbeds = message.embeds