diff --git a/src/client/OicqClient.ts b/src/client/OicqClient.ts index 04459a9..e9cbfc1 100644 --- a/src/client/OicqClient.ts +++ b/src/client/OicqClient.ts @@ -13,8 +13,8 @@ import { execSync } from 'child_process'; import random from '../utils/random'; import fs from 'fs'; import fsP from 'fs/promises'; -import path from 'path'; import { Config } from 'oicq/lib/client'; +import dataPath from '../helpers/dataPath'; const LOG_LEVEL: LogLevel = 'warn'; @@ -77,8 +77,8 @@ export default class OicqClient extends Client { resolve(client); } - if (!fs.existsSync(`./data/${params.uin}/device-${params.uin}.json`)) { - await fsP.mkdir(`./data/${params.uin}`, { recursive: true }); + if (!fs.existsSync(dataPath(`${params.uin}/device-${params.uin}.json`))) { + await fsP.mkdir(dataPath(params.uin.toString()), { recursive: true }); const device = { product: 'Q2TG', @@ -97,12 +97,12 @@ export default class OicqClient extends Client { imei: random.imei(), }; - await fsP.writeFile(`./data/${params.uin}/device-${params.uin}.json`, JSON.stringify(device, null, 0), 'utf-8'); + await fsP.writeFile(dataPath(`${params.uin}/device-${params.uin}.json`), JSON.stringify(device, null, 0), 'utf-8'); } const client = new this(params.uin, { platform: params.platform, - data_dir: path.resolve('./data'), + data_dir: dataPath(), log_level: LOG_LEVEL, ffmpeg_path: process.env.FFMPEG_PATH, ffprobe_path: process.env.FFPROBE_PATH, diff --git a/src/helpers/convert.ts b/src/helpers/convert.ts new file mode 100644 index 0000000..fc4f236 --- /dev/null +++ b/src/helpers/convert.ts @@ -0,0 +1,42 @@ +import dataPath from './dataPath'; +import fs from 'fs'; +import path from 'path'; +import sharp from 'sharp'; +import { file as createTempFile } from 'tmp-promise'; +import fsP from 'fs/promises'; +import convertWithFfmpeg from '../encoding/convertWithFfmpeg'; +import tgsToGif from '../encoding/tgsToGif'; + +const CACHE_PATH = dataPath('cache'); +fs.mkdirSync(CACHE_PATH, { recursive: true }); + +// 首先查找缓存,要是缓存中没有的话执行第二个参数的方法转换到缓存的文件 +const cachedConvert = async (key: string, convert: (outputPath: string) => Promise) => { + const convertedPath = path.join(CACHE_PATH, key); + if (!fs.existsSync(convertedPath)) { + await convert(convertedPath); + } + return convertedPath; +}; + +export default { + // webp2png,这里 webpData 是方法因为不需要的话就不获取了 + png: (key: string, webpData: () => Promise) => + cachedConvert(key + '.png', async (convertedPath) => { + await sharp(await webpData()).png().toFile(convertedPath); + }), + webm2gif: (key: string, webmData: () => Promise) => + cachedConvert(key + '.gif', async (convertedPath) => { + const temp = await createTempFile(); + await fsP.writeFile(temp.path, await webmData()); + await convertWithFfmpeg(temp.path, convertedPath, 'gif'); + await temp.cleanup(); + }), + tgs2gif: (key: string, tgsData: () => Promise) => + cachedConvert(key + '.gif', async (convertedPath) => { + const tempTgsPath = path.join(CACHE_PATH, key); + await fsP.writeFile(tempTgsPath, await tgsData()); + await tgsToGif(tempTgsPath); + await fsP.rm(tempTgsPath); + }), +}; diff --git a/src/helpers/dataPath.ts b/src/helpers/dataPath.ts new file mode 100644 index 0000000..9fd5ec0 --- /dev/null +++ b/src/helpers/dataPath.ts @@ -0,0 +1,7 @@ +import path from 'path'; + +const DATA_DIR = process.env.DATA_DIR || path.resolve('./data'); + +// Wrap of path.join, add base DATA_DIR +export default (...paths: string[]) => + path.join(DATA_DIR, ...paths); diff --git a/src/index.ts b/src/index.ts index edfd5ea..8c2a855 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,7 +3,6 @@ import Instance from './models/Instance'; import db from './models/db'; (async () => { - process.env.DATA_DIR && process.chdir(process.env.DATA_DIR); configure({ appenders: { console: { type: 'console' }, diff --git a/src/services/ForwardService.ts b/src/services/ForwardService.ts index 2285b36..bf49650 100644 --- a/src/services/ForwardService.ts +++ b/src/services/ForwardService.ts @@ -15,18 +15,15 @@ import { file as createTempFile, FileResult } from 'tmp-promise'; import fsP from 'fs/promises'; import eviltransform from 'eviltransform'; import silk from '../encoding/silk'; -import fs from 'fs'; -import tgsToGif from '../encoding/tgsToGif'; import axios from 'axios'; import { md5Hex } from '../utils/hashing'; import Instance from '../models/Instance'; import { Pair } from '../models/Pair'; -import sharp from 'sharp'; -import convertWithFfmpeg from '../encoding/convertWithFfmpeg'; import OicqClient from '../client/OicqClient'; import lottie from '../constants/lottie'; import _ from 'lodash'; import emoji from '../constants/emoji'; +import convert from '../helpers/convert'; const NOT_CHAINABLE_ELEMENTS = ['flash', 'record', 'video', 'location', 'share', 'json', 'xml', 'poke']; @@ -291,13 +288,7 @@ export default class ForwardService { message.document?.mimeType?.startsWith('image/')) { // 将 webp 转换为 png,防止 macOS 不识别 if (message.document?.mimeType === 'image/webp') { - const convertedPath = path.resolve(path.join('./data/cache/webp', message.document.id.toString(16) + '.png')); - // 先从缓存中找 - if (!fs.existsSync(convertedPath)) { - await fsP.mkdir('./data/cache/webp', { recursive: true }); - const webpData = await message.downloadMedia({}); - await sharp(webpData).png().toFile(convertedPath); - } + const convertedPath = await convert.png(message.document.id.toString(16), () => message.downloadMedia({})); chain.push({ type: 'image', file: convertedPath, @@ -320,15 +311,7 @@ export default class ForwardService { } else if (file.mimeType === 'video/webm' || message.gif) { // 把 webm 转换成 gif - const convertedPath = path.resolve(path.join('./data/cache/webm', message.document.id.toString(16) + '.gif')); - // 先从缓存中找 - if (!fs.existsSync(convertedPath)) { - await fsP.mkdir('./data/cache/webm', { recursive: true }); - const temp = await createTempFile(); - tempFiles.push(temp); - await fsP.writeFile(temp.path, await message.downloadMedia({})); - await convertWithFfmpeg(temp.path, convertedPath, 'gif'); - } + const convertedPath = await convert.webm2gif(message.document.id.toString(16), () => message.downloadMedia({})); chain.push({ type: 'image', file: convertedPath, @@ -345,19 +328,7 @@ export default class ForwardService { } else if (message.sticker) { // 一定是 tgs - let gifPath: string; - const tempTgsPath = path.resolve(path.join('./data/cache/tgs', message.sticker.id.toString(16))); - // 先从缓存中找 - if (fs.existsSync(tempTgsPath + '.gif')) { - gifPath = tempTgsPath + '.gif'; - } - else { - await fsP.mkdir('./data/cache/tgs', { recursive: true }); - await fsP.writeFile(tempTgsPath, await message.downloadMedia({})); - await tgsToGif(tempTgsPath); - await fsP.rm(tempTgsPath); - gifPath = tempTgsPath + '.gif'; - } + const gifPath = await convert.tgs2gif(message.sticker.id.toString(16), () => message.downloadMedia({})); chain.push({ type: 'image', file: gifPath,