Files
kt-financial-system/apps/backend/utils/media-repository.ts
你的用户名 b68511b2e2
Some checks failed
Deploy to Production / Build and Test (push) Successful in 10m51s
Deploy to Production / Deploy to Server (push) Failing after 6m41s
feat: migrate backend storage to postgres
2025-11-06 22:01:50 +08:00

163 lines
3.9 KiB
TypeScript

import { existsSync } from 'node:fs';
import { query } from './db';
interface MediaRow {
id: number;
chat_id: number;
message_id: number;
user_id: number;
username: null | string;
display_name: null | string;
file_type: string;
file_id: string;
file_unique_id: null | string;
caption: null | string;
file_name: null | string;
file_path: string;
file_size: null | number;
mime_type: null | string;
duration: null | number;
width: null | number;
height: null | number;
forwarded_to: null | number;
created_at: string;
updated_at: string;
}
export interface MediaMessage {
id: number;
chatId: number;
messageId: number;
userId: number;
username?: string;
displayName?: string;
fileType: string;
fileId: string;
fileUniqueId?: string;
caption?: string;
fileName?: string;
filePath: string;
fileSize?: number;
mimeType?: string;
duration?: number;
width?: number;
height?: number;
forwardedTo?: number;
createdAt: string;
updatedAt: string;
available: boolean;
downloadUrl: null | string;
}
function mapMediaRow(row: MediaRow): MediaMessage {
const fileExists = existsSync(row.file_path);
return {
id: row.id,
chatId: row.chat_id,
messageId: row.message_id,
userId: row.user_id,
username: row.username ?? undefined,
displayName: row.display_name ?? undefined,
fileType: row.file_type,
fileId: row.file_id,
fileUniqueId: row.file_unique_id ?? undefined,
caption: row.caption ?? undefined,
fileName: row.file_name ?? undefined,
filePath: row.file_path,
fileSize: row.file_size ?? undefined,
mimeType: row.mime_type ?? undefined,
duration: row.duration ?? undefined,
width: row.width ?? undefined,
height: row.height ?? undefined,
forwardedTo: row.forwarded_to ?? undefined,
createdAt: row.created_at,
updatedAt: row.updated_at,
available: fileExists,
downloadUrl: fileExists ? `/finance/media/${row.id}/download` : null,
};
}
export async function fetchMediaMessages(
params: {
fileTypes?: string[];
limit?: number;
} = {},
) {
const whereClauses: string[] = [];
const queryParams: any[] = [];
if (params.fileTypes && params.fileTypes.length > 0) {
const placeholders = params.fileTypes.map((type) => {
queryParams.push(type);
return `$${queryParams.length}`;
});
whereClauses.push(`file_type IN (${placeholders.join(', ')})`);
}
const where =
whereClauses.length > 0 ? `WHERE ${whereClauses.join(' AND ')}` : '';
const limitClause =
params.limit && params.limit > 0 ? `LIMIT ${Number(params.limit)}` : '';
const { rows } = await query<MediaRow>(
`SELECT id,
chat_id,
message_id,
user_id,
username,
display_name,
file_type,
file_id,
file_unique_id,
caption,
file_name,
file_path,
file_size,
mime_type,
duration,
width,
height,
forwarded_to,
created_at,
updated_at
FROM finance_media_messages
${where}
ORDER BY created_at DESC, id DESC
${limitClause}`,
queryParams,
);
return rows.map((row) => mapMediaRow(row));
}
export async function getMediaMessageById(id: number) {
const { rows } = await query<MediaRow>(
`SELECT id,
chat_id,
message_id,
user_id,
username,
display_name,
file_type,
file_id,
file_unique_id,
caption,
file_name,
file_path,
file_size,
mime_type,
duration,
width,
height,
forwarded_to,
created_at,
updated_at
FROM finance_media_messages
WHERE id = $1`,
[id],
);
const row = rows[0];
return row ? mapMediaRow(row) : null;
}