(msg: Api.Message, sourceMsg: Api.Message)
| 201 | return false; |
| 202 | } |
| 203 | |
| 204 | private async convertToSticker(msg: Api.Message, sourceMsg: Api.Message) { |
| 205 | const statusMsg = await msg.edit({ text: "🔄 正在分析媒体文件..." }); |
| 206 | |
| 207 | // 检查文件大小 |
| 208 | const fileSize = this.getFileSize(sourceMsg); |
| 209 | if (fileSize > this.config.maxFileSize * 1024 * 1024) { |
| 210 | throw new Error(`文件过大 (${Math.round(fileSize / 1024 / 1024)}MB),最大支持 ${this.config.maxFileSize}MB`); |
| 211 | } |
| 212 | |
| 213 | // 检查视频时长(如果是视频) |
| 214 | if (sourceMsg.video) { |
| 215 | const duration = this.getVideoDuration(sourceMsg); |
| 216 | if (duration > this.config.maxDuration) { |
| 217 | throw new Error(`视频过长 (${duration}秒),最大支持 ${this.config.maxDuration}秒`); |
| 218 | } |
| 219 | } |
| 220 | |
| 221 | await statusMsg?.edit({ text: "📥 正在下载文件..." }); |
| 222 | |
| 223 | // 下载源文件 |
| 224 | const timestamp = Date.now(); |
| 225 | const inputFile = path.join(this.tempDir, `input_${timestamp}`); |
| 226 | const outputFile = path.join(this.tempDir, `sticker_${timestamp}.webm`); |
| 227 | |
| 228 | try { |
| 229 | await this.client.downloadMedia(sourceMsg.media!, { outputFile: inputFile }); |
| 230 | |
| 231 | await statusMsg?.edit({ text: "🎬 正在转换为贴纸格式..." }); |
| 232 | |
| 233 | // 使用 FFmpeg 转换为贴纸格式 |
| 234 | await this.convertWithFFmpeg(inputFile, outputFile); |
| 235 | |
| 236 | await statusMsg?.edit({ text: "📤 正在发送贴纸..." }); |
| 237 | await this.sendAsSticker(msg, outputFile); |
| 238 | await statusMsg?.edit({ text: "✅ 贴纸转换完成!" }); |
| 239 | |
| 240 | // 延迟删除状态消息 (generation-safe) |
| 241 | const gen1 = getCurrentGeneration(); |
| 242 | const t1 = setTimeout(() => { |
| 243 | pendingTimers.delete(t1); |
| 244 | if (getCurrentGeneration() !== gen1) return; |
| 245 | statusMsg?.delete().catch(() => {}); |
| 246 | }, 2000); |
| 247 | pendingTimers.add(t1); |
| 248 | |
| 249 | } finally { |
| 250 | // 清理临时文件 |
| 251 | this.cleanupFiles([inputFile, outputFile]); |
| 252 | } |
| 253 | } |
| 254 | |
| 255 | private getFileSize(msg: Api.Message): number { |
no test coverage detected