"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = require("fs"); const axios_1 = require("axios"); const CallableInstance = require("callable-instance"); const html_entities_1 = require("html-entities"); const temp = require("temp"); const loggers_1 = require("./loggers"); const koishi_1 = require("./koishi"); const xmlEntities = new html_entities_1.XmlEntities(); const ZHType = (type) => new class extends String { constructor() { super(...arguments); this.type = super.toString(); this.toString = () => `[${super.toString()}]`; } }(type); const typeInZH = { photo: ZHType('图片'), video: ZHType('视频'), }; const logger = (0, loggers_1.getLogger)('webshot'); class Webshot extends CallableInstance { constructor(_wsUrl, _mode, onready) { super('webshot'); this.fetchMedia = (url) => new Promise((resolve, reject) => { logger.info(`fetching ${url}`); (0, axios_1.default)({ method: 'get', url, responseType: 'arraybuffer', timeout: 150000, }).then(res => { if (res.status === 200) { logger.info(`successfully fetched ${url}`); resolve(res.data); } else { logger.error(`failed to fetch ${url}: ${res.status}`); reject(); } }).catch(err => { logger.error(`failed to fetch ${url}: ${err instanceof Error ? err.message : err}`); reject(); }); }).then(data => (ext => { const mediaTempFilePath = temp.path({ suffix: `.${ext}` }); (0, fs_1.writeFileSync)(mediaTempFilePath, Buffer.from(data)); const path = `file://${mediaTempFilePath}`; switch (ext) { case 'jpg': case 'png': return koishi_1.Message.Image(path); case 'mp4': return koishi_1.Message.Video(path); } logger.warn('unable to find MIME type of fetched media, failing this fetch'); throw Error(); })(/\/.+\.(?:.*?(?<=[?&])stp=dst-(jpg)|(.+?)\?)/.exec(url).filter(g => g)[1])); this.fetchBestCandidate = ({ image_versions2, video_versions }) => { const candidates = video_versions || image_versions2.candidates; const url = candidates .sort((var1, var2) => var2.width + ((var2 === null || var2 === void 0 ? void 0 : var2.type) || 0) - var1.width - ((var1 === null || var1 === void 0 ? void 0 : var1.type) || 0)) .map(variant => variant.url)[0]; const altMessage = `\n[失败的${typeInZH[video_versions ? 'video' : 'photo'].type}:${url}]`; return this.fetchMedia(url) .catch(error => { logger.warn('unable to fetch media, sending plain text instead...'); return altMessage; }); }; onready(); } webshot(mediaItems, callback, webshotDelay) { const promises = mediaItems.map(item => { let promise = Promise.resolve(); logger.info(`working on ${item.user.username}/${item.code}`); let messageChain = ''; const author = `${item.user.full_name} (@${item.user.username}):\n`; const date = `${new Date(item.taken_at * 1000)}\n`; messageChain += author + date; promise = promise.then(() => this.fetchBestCandidate(item)) .then(msg => { messageChain += msg; }); return promise.then(() => { logger.info(`done working on ${item.user.username}/${item.code}, message chain:`); logger.info(JSON.stringify(koishi_1.Message.ellipseBase64(messageChain))); callback(messageChain, xmlEntities.decode(item.caption), author); }); }); return Promise.all(promises).then(); } } exports.default = Webshot;