export function telegramAttachment(content = {}) { const type = content['@type'] if (type === 'messagePhoto') { const sizes = Array.isArray(content.photo?.sizes) ? content.photo.sizes : [] const file = sizes.at(-1)?.photo return file?.id ? { telegramFileId: Number(file.id), attachmentName: `telegram-photo-${file.id}.jpg`, attachmentMimeType: 'image/jpeg', attachmentSize: Number(file.size || file.expected_size || 0), } : {} } if (type === 'messageDocument') { const document = content.document || {} const file = document.document return file?.id ? { telegramFileId: Number(file.id), attachmentName: document.file_name || `document-${file.id}`, attachmentMimeType: document.mime_type || 'application/octet-stream', attachmentSize: Number(file.size || file.expected_size || 0), } : {} } if (type === 'messageVoiceNote') { const file = content.voice_note?.voice return file?.id ? { telegramFileId: Number(file.id), attachmentName: `voice-${file.id}.ogg`, attachmentMimeType: content.voice_note?.mime_type || 'audio/ogg', attachmentSize: Number(file.size || file.expected_size || 0), duration: Number(content.voice_note?.duration || 0), } : {} } if (type === 'messageAudio') { const audio = content.audio || {} const file = audio.audio return file?.id ? { telegramFileId: Number(file.id), attachmentName: audio.file_name || audio.title || `audio-${file.id}`, attachmentMimeType: audio.mime_type || 'audio/mpeg', attachmentSize: Number(file.size || file.expected_size || 0), duration: Number(audio.duration || 0), } : {} } if (type === 'messageSticker') { const sticker = content.sticker || {} const file = sticker.sticker const format = sticker.format?.['@type'] const extension = format === 'stickerFormatTgs' ? 'tgs' : format === 'stickerFormatWebm' ? 'webm' : 'webp' return file?.id ? { telegramFileId: Number(file.id), attachmentName: `sticker-${file.id}.${extension}`, attachmentMimeType: extension === 'webp' ? 'image/webp' : extension === 'webm' ? 'video/webm' : 'application/x-tgsticker', attachmentSize: Number(file.size || file.expected_size || 0), stickerEmoji: sticker.emoji || '', } : {} } return {} } export const dateKey = (value = Date.now()) => { const date = new Date(value) return Number.isNaN(date.getTime()) ? '' : date.toISOString().slice(0, 10) } export const percent = (numerator, denominator) => denominator ? Math.round((numerator / denominator) * 1000) / 10 : 0 export const countBy = (list, key) => { const counts = new Map() for (const item of list) { const value = typeof key === 'function' ? key(item) : item[key] if (!value) continue counts.set(String(value), (counts.get(String(value)) || 0) + 1) } return counts }