refactor: remove dead code (#3337)

This commit is contained in:
Hampus authored and GitHub committed 2026-10-09 01:41:26 +02:00
1 parent a19002652b
commit 93d1f8af46
1527 files changed
+21170 -73846

No files matched your search

@@ -135,62 +135,6 @@ export class AvatarService {
return storedHash;
}
async uploadAvatarToPath(params: {
bucket: string;
keyPath: string;
errorPath: string;
previousKey?: string | null;
base64Image?: string | null;
}): Promise<string | null> {
const {bucket, keyPath, errorPath, previousKey, base64Image} = params;
const stripAnimationPrefix = (key: string) => (key.startsWith('a_') ? key.substring(2) : key);
if (!base64Image) {
if (previousKey) {
await this.storageService.deleteObject(bucket, `${keyPath}/${stripAnimationPrefix(previousKey)}`);
}
return null;
}
const base64Data = base64Image.includes(',') ? base64Image.split(',')[1] : base64Image;
const imageBuffer = new Uint8Array(Buffer.from(base64Data, 'base64'));
const maxAvatarSize = this.resolveSizeLimit('avatar_max_size', AVATAR_MAX_SIZE);
if (imageBuffer.length > maxAvatarSize) {
throw InputValidationError.fromCode(errorPath, ValidationErrorCodes.IMAGE_SIZE_EXCEEDS_LIMIT, {
maxSize: maxAvatarSize,
});
}
const metadata = this.requireAllowedMetadata({
metadata: await this.mediaService.getMetadata({
type: 'base64',
base64: base64Data,
version: 2,
nsfw: 'allow',
}),
kind: 'avatar',
errorPath,
});
const imageHash = crypto.createHash('md5').update(Buffer.from(imageBuffer)).digest('hex');
const imageHashShort = imageHash.slice(0, 8);
const isAnimatedAvatar = metadata.animated ?? false;
const storedHash = isAnimatedAvatar ? `a_${imageHashShort}` : imageHashShort;
if (bannedAvatarHashCache.contains(imageHashShort)) {
throw new ContentBlockedError();
}
await this.scanAndBlockBannedSha({
imageBuffer,
resourceType: 'other',
});
const uploadBuffer = await this.stripImageMetadata(imageBuffer, metadata.format);
await this.storageService.uploadObject({
bucket,
key: `${keyPath}/${imageHashShort}`,
body: uploadBuffer,
});
if (previousKey && stripAnimationPrefix(previousKey) !== imageHashShort) {
await this.storageService.deleteObject(bucket, `${keyPath}/${stripAnimationPrefix(previousKey)}`);
}
return storedHash;
}
async processEmoji(params: {errorPath: string; base64Image: string; guildFeatures: Iterable<string>}): Promise<{
imageBuffer: Uint8Array;
animated: boolean;
@@ -56,17 +56,6 @@ class ContentModerationService {
}
}
scanHostname(host: string, ctx: ModerationContext): void {
if (!host) return;
if (urlBlocklistCache.isHostnameBanned(host)) {
Logger.warn(
{surface: ctx.surface, userId: ctx.userId?.toString(), host},
'content_moderation.block hostname match',
);
throw new ContentBlockedError();
}
}
scanFileBuffer(buffer: Buffer | Uint8Array, ctx: ModerationContext): string {
const sha = createHash('sha256').update(buffer).digest('hex');
this.scanSha256(sha, ctx);
@@ -26,10 +26,6 @@ export class DisabledVirusScanService implements IVirusScanService {
};
}
async isVirusHashCached(fileHash: string): Promise<boolean> {
return this.cachedVirusHashes.has(fileHash);
}
async cacheVirusHash(fileHash: string): Promise<void> {
this.cachedVirusHashes.add(fileHash);
}
@@ -3,8 +3,6 @@
import {stripOwnAttachmentSignature} from '@app/api/attachment/AttachmentUrls';
import type {ChannelID, MessageID} from '@app/api/BrandedTypes';
import type {RichEmbedMediaWithMetadata} from '@app/api/channel/EmbedTypes';
import type {IChannelRepository} from '@app/api/channel/IChannelRepository';
import {nextVersion} from '@app/api/database/CassandraTypes';
import type {MessageEmbed, MessageEmbedChild} from '@app/api/database/types/MessageTypes';
import {
type IMediaService,
@@ -35,15 +33,6 @@ import type {
} from '@fluxer/schema/src/domains/message/MessageRequestSchemas';
import type {IWorkerService} from '@pkgs/worker/src/contracts/IWorkerService';
interface CreateEmbedsParams {
channelId: ChannelID;
messageId: MessageID;
content: string | null;
customEmbeds?: Array<RichEmbedRequest>;
guildId: bigint | null;
nsfwMode: MediaProxyNsfwMode;
}
interface ProcessedUrlEmbeds {
embeds: Array<Embed>;
cacheTtlSeconds: number | null;
@@ -68,20 +57,11 @@ export class EmbedService {
private readonly MAX_EMBED_CHARACTERS_BUG_HUNTER = 12000;
constructor(
private channelRepository: IChannelRepository,
private unfurlerService: IUnfurlerService,
private mediaService: IMediaService,
private workerService: IWorkerService<WorkerTaskName>,
) {}
async createAndSaveEmbeds(params: CreateEmbedsParams): Promise<Array<MessageEmbed> | null> {
if (params.customEmbeds?.length) {
return await this.processCustomEmbeds(params);
} else {
return await this.processUrlEmbeds(params);
}
}
async getInitialEmbeds(params: {
content: string | null;
customEmbeds?: Array<RichEmbedRequest>;
@@ -116,14 +96,6 @@ export class EmbedService {
await this.enqueue(channelId, messageId, guildId, nsfwMode, options);
}
async processUrl(
url: string,
nsfwMode: MediaProxyNsfwMode = 'block',
options: UnfurlOptions = {},
): Promise<Array<Embed>> {
return (await this.processUrlWithCachePolicy(url, nsfwMode, options)).embeds;
}
async processUrlWithCachePolicy(
url: string,
nsfwMode: MediaProxyNsfwMode = 'block',
@@ -190,39 +162,6 @@ export class EmbedService {
return false;
}
private async processCustomEmbeds({
channelId,
messageId,
customEmbeds,
nsfwMode,
}: CreateEmbedsParams): Promise<Array<MessageEmbed> | null> {
if (!customEmbeds?.length) return null;
this.validateEmbedSize(customEmbeds);
const embeds = await Promise.all(customEmbeds.map((embed) => this.createEmbed(embed, nsfwMode)));
await this.updateMessageEmbeds(channelId, messageId, embeds);
return embeds.map((embed) => embed.toMessageEmbed());
}
private async processUrlEmbeds({
channelId,
messageId,
content,
guildId,
nsfwMode,
}: CreateEmbedsParams): Promise<Array<MessageEmbed> | null> {
if (!content) {
await this.updateMessageEmbeds(channelId, messageId, []);
return null;
}
const urls = UnfurlerUtils.extractURLs(content);
if (!urls.length) {
await this.updateMessageEmbeds(channelId, messageId, []);
return null;
}
await this.enqueue(channelId, messageId, guildId, nsfwMode, {content});
return null;
}
private mapResponseEmbed(embed: MessageEmbedResponse): MessageEmbed {
return {
...this.mapResponseEmbedChild(embed),
@@ -529,16 +468,4 @@ export class EmbedService {
);
}
}
private async updateMessageEmbeds(channelId: ChannelID, messageId: MessageID, embeds: Array<Embed>): Promise<void> {
const currentMessage = await this.channelRepository.getMessage(channelId, messageId);
if (!currentMessage) return;
const currentRow = currentMessage.toRow();
const updatedData = {
...currentRow,
embeds: embeds.length > 0 ? embeds.map((embed) => embed.toMessageEmbed()) : null,
version: nextVersion(currentRow.version),
};
await this.channelRepository.upsertMessage(updatedData, currentRow);
}
}
@@ -37,7 +37,7 @@ export function callCallerRpcParams(caller: CallCaller | undefined): Record<stri
return {caller_id: caller.id, caller_name: caller.name, caller_avatar: caller.avatar};
}
export interface GatewayGuildMemoryStatsEntry {
interface GatewayGuildMemoryStatsEntry {
node_id: string;
guild_id: string | null;
guild_name: string;
@@ -52,13 +52,13 @@ export interface GatewayGuildMemoryStats {
guilds: Array<GatewayGuildMemoryStatsEntry>;
}
export interface GatewayNodeMemoryStats {
interface GatewayNodeMemoryStats {
total: string;
processes: string;
system: string;
}
export interface GatewayNodeStatsEntry {
interface GatewayNodeStatsEntry {
node_id: string;
status: string;
sessions: number;
@@ -91,12 +91,12 @@ export interface GatewayNodeStats {
nodes: Array<GatewayNodeStatsEntry>;
}
export interface GatewayVoiceStateRegionCount {
interface GatewayVoiceStateRegionCount {
region_id: string;
voice_state_count: number;
}
export interface GatewayVoiceStateServerCount {
interface GatewayVoiceStateServerCount {
server_id: string;
voice_state_count: number;
}
@@ -71,14 +71,14 @@ interface ListParticipantsParams {
serverId: string;
}
export interface ListParticipantsSuccess {
interface ListParticipantsSuccess {
status: 'ok';
participants: Array<{
identity: string;
}>;
}
export interface ListParticipantsError {
interface ListParticipantsError {
status: 'error';
errorCode: string;
retryable: boolean;
@@ -16,21 +16,21 @@ interface MediaProxyMetadataPolicy {
nsfw: MediaProxyNsfwMode;
}
export type MediaProxyMetadataExternalRequest = {
type MediaProxyMetadataExternalRequest = {
type: 'external';
url: string;
with_base64?: boolean;
} & MediaProxyMetadataPolicy;
export type MediaProxyMetadataUploadRequest = {
type MediaProxyMetadataUploadRequest = {
type: 'upload';
upload_filename: string;
filename?: string;
} & MediaProxyMetadataPolicy;
export type MediaProxyMetadataBase64Request = {
type MediaProxyMetadataBase64Request = {
type: 'base64';
base64: string;
} & MediaProxyMetadataPolicy;
export type MediaProxyMetadataS3Request = {
type MediaProxyMetadataS3Request = {
type: 's3';
bucket: string;
key: string;
@@ -72,7 +72,7 @@ export type MediaProxyFrameRequest =
key: string;
};
export interface MediaProxyFrameData {
interface MediaProxyFrameData {
timestamp: number;
mime_type: string;
base64: string;
@@ -230,15 +230,6 @@ export class KVAccountDeletionQueueService {
}
}
async getStateVersion(): Promise<number | null> {
try {
return parseStoredTimestamp(await this.kvClient.get(STATE_VERSION_KEY), 'Deletion queue state version');
} catch (error) {
Logger.error({error}, 'Failed to get state version');
throw error;
}
}
private getSecondaryKey(userId: UserID): string {
return `deletion_queue_by_user:${userId.toString()}`;
}
@@ -1,9 +1,6 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {
buildProcessedMediaObject,
stripNonJpegImageMetadataForUpload,
} from '@app/api/infrastructure/StorageObjectHelpers';
import {stripNonJpegImageMetadataForUpload} from '@app/api/infrastructure/StorageObjectHelpers';
import {describe, expect, it} from 'vitest';
const PNG_SIGNATURE = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
@@ -118,9 +115,3 @@ describe('stripNonJpegImageMetadataForUpload for WebP', () => {
expect(stripped.body).toEqual(webp([riffChunk('VP8X', expectedVp8x), riffChunk('ANIM', new Uint8Array(6)), anmf]));
});
});
describe('buildProcessedMediaObject', () => {
it('leaves non-media objects for plain copy', async () => {
await expect(buildProcessedMediaObject(textBytes('plain text'), 'text/plain')).resolves.toBeNull();
});
});
@@ -20,15 +20,6 @@ interface ProcessedMediaFile {
height?: number;
}
interface ProcessedMediaObject {
body: Uint8Array;
contentType: string;
contentHash: string;
contentLength: number;
width?: number;
height?: number;
}
interface StrippedMediaBuffer {
body: Uint8Array;
contentType: string;
@@ -36,65 +27,6 @@ interface StrippedMediaBuffer {
height?: number;
}
function processedMediaObject(
body: Uint8Array,
contentType: string,
dimensions?: {width: number; height: number},
): ProcessedMediaObject {
return {
body,
contentType,
contentHash: createHash('sha256').update(body).digest('hex'),
contentLength: body.length,
...dimensions,
};
}
async function processJpegData(sourceData: Uint8Array, contentType: string): Promise<ProcessedMediaObject> {
const inputPath = temporaryFile({extension: 'jpg'});
const outputPath = temporaryFile({extension: 'jpg'});
try {
await fs.promises.writeFile(inputPath, sourceData);
const metadata = await sharp(sourceData).metadata();
const needsRotation = metadata.orientation != null && metadata.orientation > 1;
let preserveIcc = true;
if (needsRotation) {
const sourceQuality = await getJpegQualityEstimate(inputPath);
const chromaSubsampling = metadata.chromaSubsampling === '4:4:4' ? '4:4:4' : '4:2:0';
const processedBuffer = await sharp(sourceData)
.rotate()
.jpeg({quality: sourceQuality ?? 95, chromaSubsampling})
.toBuffer();
await fs.promises.writeFile(outputPath, processedBuffer);
preserveIcc = metadata.space !== 'cmyk';
} else {
await fs.promises.copyFile(inputPath, outputPath);
}
await stripJpegMetadata(outputPath, inputPath, {preserveIcc, rotated: needsRotation});
const finalBuffer = await fs.promises.readFile(outputPath);
const dimensions =
metadata.width && metadata.height
? metadata.orientation != null && metadata.orientation >= 5 && metadata.orientation <= 8
? {width: metadata.height, height: metadata.width}
: {width: metadata.width, height: metadata.height}
: undefined;
const processed = processedMediaObject(new Uint8Array(finalBuffer), contentType, dimensions);
const cleanupErrors = await cleanupTempFiles([inputPath, outputPath]);
if (cleanupErrors.length > 0) {
throw new Error(
`Failed to cleanup temporary files: ${cleanupErrors.map((e) => e.path).join(', ')}. This may indicate disk space or permission issues.`,
);
}
return processed;
} catch (error) {
const cleanupErrors = await cleanupTempFiles([inputPath, outputPath]);
if (cleanupErrors.length > 0) {
Logger.error({cleanupErrors, originalError: error}, 'Failed to cleanup temp files after operation failure');
}
throw error;
}
}
function normalizeContentType(contentType: string): string {
return contentType.split(';', 1)[0]?.trim().toLowerCase() || 'application/octet-stream';
}
@@ -107,24 +39,6 @@ function isJpegContentType(contentType: string): boolean {
return contentType.includes('jpeg') || contentType.includes('jpg');
}
function contentTypeToMediaExtension(contentType: string): string {
if (contentType.includes('mp4') || contentType.includes('mpeg4')) return 'mp4';
if (contentType.includes('webm')) return 'webm';
if (contentType.includes('quicktime')) return 'mov';
if (contentType.includes('x-matroska')) return 'mkv';
if (contentType.includes('avi')) return 'avi';
if (contentType.includes('flv')) return 'flv';
if (contentType.includes('mp2t')) return 'ts';
if (contentType.includes('mpeg')) return contentType.startsWith('audio/') ? 'mp3' : 'mpeg';
if (contentType.includes('x-ms-wmv')) return 'wmv';
if (contentType.includes('wav')) return 'wav';
if (contentType.includes('flac')) return 'flac';
if (contentType.includes('aac')) return 'aac';
if (contentType.includes('aiff')) return 'aiff';
if (contentType.includes('ogg')) return 'ogg';
return 'mp4';
}
function imageContentTypeForSharpFormat(format: string | undefined, fallback: string): string {
switch (format) {
case 'png':
@@ -314,53 +228,6 @@ async function stripMetadataWithExiftool(data: Uint8Array, extension: string): P
}
}
async function stripMediaMetadata(data: Uint8Array, contentType: string): Promise<StrippedMediaBuffer | null> {
const normalizedContentType = normalizeContentType(contentType);
if (!isMediaContentType(normalizedContentType)) return null;
if (isJpegContentType(normalizedContentType)) {
const processed = await processJpegData(data, normalizedContentType);
return {
body: processed.body,
contentType: processed.contentType,
...(processed.width && processed.height ? {width: processed.width, height: processed.height} : {}),
};
}
if (normalizedContentType.startsWith('image/')) {
return stripNonJpegImageMetadataForUpload(data, normalizedContentType);
}
if (normalizedContentType.startsWith('video/') || normalizedContentType.startsWith('audio/')) {
return {
body: await stripVideoMetadata(data, normalizedContentType),
contentType: normalizedContentType,
};
}
return null;
}
export async function buildProcessedMediaObject(
data: Uint8Array,
contentType: string,
): Promise<ProcessedMediaObject | null> {
const stripped = await stripMediaMetadata(data, contentType);
if (!stripped) return null;
const dimensions = stripped.width && stripped.height ? {width: stripped.width, height: stripped.height} : undefined;
return processedMediaObject(stripped.body, stripped.contentType, dimensions);
}
async function stripVideoMetadata(data: Uint8Array, contentType: string): Promise<Uint8Array> {
const ext = contentTypeToMediaExtension(contentType);
const inputPath = temporaryFile({extension: ext});
const outputPath = temporaryFile({extension: ext});
try {
await fs.promises.writeFile(inputPath, data);
await stripVideoMetadataInPlace(inputPath, outputPath);
const result = await fs.promises.readFile(outputPath);
return new Uint8Array(result);
} finally {
await cleanupTempFiles([inputPath, outputPath]);
}
}
async function stripVideoMetadataInPlace(inputPath: string, outputPath: string): Promise<void> {
await execFilePromise('ffmpeg', [
'-hide_banner',
@@ -25,7 +25,6 @@ import {
GetObjectCommand,
type GetObjectCommandOutput,
HeadObjectCommand,
type HeadObjectCommandOutput,
ListObjectsV2Command,
ListPartsCommand,
PutObjectCommand,
@@ -676,10 +675,6 @@ export class StorageService implements IStorageService {
return this.client.send(new GetObjectCommand({Bucket: params.bucket, Key: params.key}));
}
async headObject(params: {bucket: string; key: string}): Promise<HeadObjectCommandOutput> {
return this.client.send(new HeadObjectCommand({Bucket: params.bucket, Key: params.key}));
}
async listObjects(params: {bucket: string; prefix: string; maxObjects?: number}): Promise<
ReadonlyArray<{
key: string;
@@ -322,7 +322,7 @@ export async function shutdownActivityEvents(timeoutMs = 2000): Promise<void> {
stopActivityEvents();
}
export function stopActivityEvents(): void {
function stopActivityEvents(): void {
runtime?.stop();
runtime = null;
}
@@ -31,7 +31,7 @@ export function setActivityProcessChannel(channel: Channel): void {
processChannel = channel;
}
export function activityMetaFromContext(ctx: Context<HonoEnv>): ActivityRequestContext {
function activityMetaFromContext(ctx: Context<HonoEnv>): ActivityRequestContext {
const origin = ctx.req.header('origin');
const ua = ctx.req.header('user-agent');
const acceptLanguage = ctx.req.header('accept-language');
@@ -4,10 +4,10 @@ import type {EventKind} from '@app/api/infrastructure/activity/Contract.generate
import type {IKVProvider} from '@pkgs/kv_client/src/IKVProvider';
export const ACTIVITY_SPOOL_KEY = 'activity:spool';
export const ACTIVITY_SPOOL_SIGNAL_CAP = 200_000;
const ACTIVITY_SPOOL_SIGNAL_CAP = 200_000;
export const ACTIVITY_SPOOL_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
const DRAIN_BATCH = 200;
export const DRAIN_BUDGET_MS = 15_000;
const DRAIN_BUDGET_MS = 15_000;
export interface ActivitySpoolEntry {
kind: EventKind;
@@ -24,7 +24,7 @@ function isSharedListName(name: string): name is SharedListName {
return (SHARED_LISTS as ReadonlyArray<string>).includes(name);
}
export function parseSharedList(value: string): ReadonlySet<string> {
function parseSharedList(value: string): ReadonlySet<string> {
const entries = new Set<string>();
for (const line of value.split('\n')) {
const entry = line.trim().toLowerCase();
@@ -52,7 +52,7 @@ export function isBlockedEmailDomain(domain: string | null | undefined): boolean
return !!tld && sharedListHas('email_tld_blocked', tld);
}
export function sharedListSizes(): Record<SharedListName, number | null> {
function sharedListSizes(): Record<SharedListName, number | null> {
const sizes = {} as Record<SharedListName, number | null>;
for (const name of SHARED_LISTS) {
sizes[name] = lists.get(name)?.size ?? null;