Files
arestools/src/core/media.js
T

61 lines
2.4 KiB
JavaScript
Raw Normal View History

import { mkdirSync } from 'node:fs';
import { readFile, writeFile } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
import { config, mediaPath } from '../config.js';
import { encrypt } from './crypto.js';
import { logger } from './logger.js';
/** Определяем тип медиа по объекту сообщения GramJS. */
export function detectMedia(message) {
if (!message?.media) return null;
if (message.photo) return 'photo';
if (message.video) return 'video';
if (message.voice) return 'voice';
if (message.videoNote) return 'video_note';
if (message.gif) return 'gif';
if (message.audio) return 'audio';
if (message.sticker) return 'sticker';
if (message.document) return 'document';
return 'media';
}
/**
* Одноразовые медиа помечены ttlSeconds на самом медиа. Такие файлы Telegram
* стирает у клиента после просмотра — их важно скачать в момент прихода.
*/
export function isOneTime(message) {
const media = message?.media;
const ttl = media?.ttlSeconds ?? media?.photo?.ttlSeconds ?? media?.document?.ttlSeconds;
return Boolean(ttl);
}
/**
* Скачивает медиа сообщения, шифрует и кладёт на диск. Возвращает
* { kind, path } либо null. Имя файла не раскрывает содержимого.
*/
export async function downloadEncrypted(client, message, tag = 'm') {
const kind = detectMedia(message);
if (!kind) return null;
try {
const buffer = await client.downloadMedia(message, {});
if (!buffer || !buffer.length) return { kind, path: null };
mkdirSync(mediaPath(), { recursive: true });
const name = `${tag}_${message.id ?? 'x'}_${buffer.length}.enc`;
const full = fileURLToPath(new URL(name, config.mediaDir));
await writeFile(full, encrypt(buffer));
logger.debug(`media: сохранено ${kind} -> ${name} (${buffer.length} б)`);
return { kind, path: name };
} catch (err) {
logger.warn(`media: не удалось скачать ${kind}:`, err.message);
return { kind, path: null };
}
}
/** Читает зашифрованный медиа-файл с диска по имени (как хранится в БД). */
export function readMedia(name) {
return readFile(fileURLToPath(new URL(name, config.mediaDir)));
}