|
@@ -1,13 +1,4 @@
|
|
"use strict";
|
|
"use strict";
|
|
-var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
|
|
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
|
|
- return new (P || (P = Promise))(function (resolve, reject) {
|
|
|
|
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
|
|
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
|
|
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
|
|
- step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
|
|
- });
|
|
|
|
-};
|
|
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
const util_1 = require("util");
|
|
const util_1 = require("util");
|
|
const axios_1 = require("axios");
|
|
const axios_1 = require("axios");
|
|
@@ -16,9 +7,8 @@ const html_entities_1 = require("html-entities");
|
|
const pngjs_1 = require("pngjs");
|
|
const pngjs_1 = require("pngjs");
|
|
const puppeteer = require("puppeteer");
|
|
const puppeteer = require("puppeteer");
|
|
const sharp = require("sharp");
|
|
const sharp = require("sharp");
|
|
-const gifski_1 = require("./gifski");
|
|
|
|
const loggers_1 = require("./loggers");
|
|
const loggers_1 = require("./loggers");
|
|
-const mirai_1 = require("./mirai");
|
|
|
|
|
|
+const koishi_1 = require("./koishi");
|
|
const utils_1 = require("./utils");
|
|
const utils_1 = require("./utils");
|
|
const xmlEntities = new html_entities_1.XmlEntities();
|
|
const xmlEntities = new html_entities_1.XmlEntities();
|
|
const ZHType = (type) => new class extends String {
|
|
const ZHType = (type) => new class extends String {
|
|
@@ -57,7 +47,7 @@ class Webshot extends CallableInstance {
|
|
this.renderWebshot = (url, height, webshotDelay) => {
|
|
this.renderWebshot = (url, height, webshotDelay) => {
|
|
const jpeg = (data) => data.pipe(sharp()).jpeg({ quality: 90, trellisQuantisation: true });
|
|
const jpeg = (data) => data.pipe(sharp()).jpeg({ quality: 90, trellisQuantisation: true });
|
|
const sharpToBase64 = (pic) => new Promise(resolve => {
|
|
const sharpToBase64 = (pic) => new Promise(resolve => {
|
|
- pic.toBuffer().then(buffer => resolve(`data:image/jpeg;base64,${buffer.toString('base64')}`));
|
|
|
|
|
|
+ pic.toBuffer().then(buffer => resolve(`base64://${buffer.toString('base64')}`));
|
|
});
|
|
});
|
|
const promise = new Promise((resolve, reject) => {
|
|
const promise = new Promise((resolve, reject) => {
|
|
const width = 720;
|
|
const width = 720;
|
|
@@ -216,60 +206,41 @@ class Webshot extends CallableInstance {
|
|
}).catch(error => this.reconnect(error)
|
|
}).catch(error => this.reconnect(error)
|
|
.then(() => this.renderWebshot(url, height, webshotDelay)));
|
|
.then(() => this.renderWebshot(url, height, webshotDelay)));
|
|
};
|
|
};
|
|
- this.fetchMedia = (url) => {
|
|
|
|
- const gif = (data) => {
|
|
|
|
- const matchDims = /\/(\d+)x(\d+)\//.exec(url);
|
|
|
|
- if (matchDims) {
|
|
|
|
- const [width, height] = matchDims.slice(1).map(Number);
|
|
|
|
- const factor = width + height > 1600 ? 0.375 : 0.5;
|
|
|
|
- return gifski_1.default(data, width * factor);
|
|
|
|
|
|
+ this.fetchMedia = (url) => new Promise((resolve, reject) => {
|
|
|
|
+ logger.info(`fetching ${url}`);
|
|
|
|
+ axios_1.default({
|
|
|
|
+ method: 'get',
|
|
|
|
+ url,
|
|
|
|
+ responseType: 'arraybuffer',
|
|
|
|
+ timeout: 150000,
|
|
|
|
+ }).then(res => {
|
|
|
|
+ if (res.status === 200) {
|
|
|
|
+ logger.info(`successfully fetched ${url}`);
|
|
|
|
+ resolve(res.data);
|
|
}
|
|
}
|
|
- return gifski_1.default(data);
|
|
|
|
- };
|
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
|
- logger.info(`fetching ${url}`);
|
|
|
|
- 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}`);
|
|
|
|
|
|
+ else {
|
|
|
|
+ logger.error(`failed to fetch ${url}: ${res.status}`);
|
|
reject();
|
|
reject();
|
|
- });
|
|
|
|
- }).then(data => {
|
|
|
|
- var _a;
|
|
|
|
- return ((ext) => __awaiter(this, void 0, void 0, function* () {
|
|
|
|
- switch (ext) {
|
|
|
|
- case 'jpg':
|
|
|
|
- return { mimetype: 'image/jpeg', data };
|
|
|
|
- case 'png':
|
|
|
|
- return { mimetype: 'image/png', data };
|
|
|
|
- case 'mp4':
|
|
|
|
- try {
|
|
|
|
- return { mimetype: 'image/gif', data: yield gif(data) };
|
|
|
|
- }
|
|
|
|
- catch (err) {
|
|
|
|
- logger.error(err);
|
|
|
|
- throw Error(err);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }))(((_a = (/\?format=([a-z]+)&/.exec(url))) !== null && _a !== void 0 ? _a : (/.*\/.*\.([^?]+)/.exec(url)))[1])
|
|
|
|
- .catch(() => {
|
|
|
|
- logger.warn('unable to find MIME type of fetched media, failing this fetch');
|
|
|
|
- throw Error();
|
|
|
|
- });
|
|
|
|
- }).then(typedData => `data:${typedData.mimetype};base64,${Buffer.from(typedData.data).toString('base64')}`);
|
|
|
|
- };
|
|
|
|
|
|
+ }
|
|
|
|
+ }).catch(err => {
|
|
|
|
+ logger.error(`failed to fetch ${url}: ${err instanceof Error ? err.message : err}`);
|
|
|
|
+ reject();
|
|
|
|
+ });
|
|
|
|
+ }).then(data => {
|
|
|
|
+ var _a;
|
|
|
|
+ return (ext => {
|
|
|
|
+ const base64 = `base64://${Buffer.from(data).toString('base64')}`;
|
|
|
|
+ switch (ext) {
|
|
|
|
+ case 'jpg':
|
|
|
|
+ case 'png':
|
|
|
|
+ return koishi_1.message.image(base64);
|
|
|
|
+ case 'mp4':
|
|
|
|
+ return koishi_1.message.video(base64);
|
|
|
|
+ }
|
|
|
|
+ logger.warn('unable to find MIME type of fetched media, failing this fetch');
|
|
|
|
+ throw Error();
|
|
|
|
+ })(((_a = (/\?format=([a-z]+)&/.exec(url))) !== null && _a !== void 0 ? _a : (/.*\/.*\.([^?]+)/.exec(url)))[1]);
|
|
|
|
+ });
|
|
if (this.mode = mode) {
|
|
if (this.mode = mode) {
|
|
onready();
|
|
onready();
|
|
}
|
|
}
|
|
@@ -277,7 +248,7 @@ class Webshot extends CallableInstance {
|
|
this.connect(onready);
|
|
this.connect(onready);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- webshot(tweets, uploader, callback, webshotDelay) {
|
|
|
|
|
|
+ webshot(tweets, callback, webshotDelay) {
|
|
let promise = new Promise(resolve => {
|
|
let promise = new Promise(resolve => {
|
|
resolve();
|
|
resolve();
|
|
});
|
|
});
|
|
@@ -286,7 +257,7 @@ class Webshot extends CallableInstance {
|
|
logger.info(`working on ${twi.user.screen_name}/${twi.id_str}`);
|
|
logger.info(`working on ${twi.user.screen_name}/${twi.id_str}`);
|
|
});
|
|
});
|
|
const originTwi = twi.retweeted_status || twi;
|
|
const originTwi = twi.retweeted_status || twi;
|
|
- const messageChain = [];
|
|
|
|
|
|
+ let messageChain = '';
|
|
let author = `${twi.user.name} (@${twi.user.screen_name}):\n`;
|
|
let author = `${twi.user.name} (@${twi.user.screen_name}):\n`;
|
|
if (twi.retweeted_status)
|
|
if (twi.retweeted_status)
|
|
author += `RT @${twi.retweeted_status.user.screen_name}: `;
|
|
author += `RT @${twi.retweeted_status.user.screen_name}: `;
|
|
@@ -303,7 +274,7 @@ class Webshot extends CallableInstance {
|
|
});
|
|
});
|
|
}
|
|
}
|
|
if (this.mode > 0)
|
|
if (this.mode > 0)
|
|
- messageChain.push(mirai_1.Message.Plain(author + xmlEntities.decode(text)));
|
|
|
|
|
|
+ messageChain += (author + xmlEntities.decode(text));
|
|
});
|
|
});
|
|
if (this.mode === 0) {
|
|
if (this.mode === 0) {
|
|
const url = `https://mobile.twitter.com/${twi.user.screen_name}/status/${twi.id_str}`;
|
|
const url = `https://mobile.twitter.com/${twi.user.screen_name}/status/${twi.id_str}`;
|
|
@@ -317,12 +288,12 @@ class Webshot extends CallableInstance {
|
|
promise = promise.then(() => this.renderWebshot(url, 1920, webshotDelay))
|
|
promise = promise.then(() => this.renderWebshot(url, 1920, webshotDelay))
|
|
.then(base64url => {
|
|
.then(base64url => {
|
|
if (base64url)
|
|
if (base64url)
|
|
- return uploader(mirai_1.Message.Image('', base64url, url), () => mirai_1.Message.Plain(author + text));
|
|
|
|
- return mirai_1.Message.Plain(author + text);
|
|
|
|
|
|
+ return koishi_1.message.image(base64url);
|
|
|
|
+ return author + text;
|
|
})
|
|
})
|
|
.then(msg => {
|
|
.then(msg => {
|
|
if (msg)
|
|
if (msg)
|
|
- messageChain.push(msg);
|
|
|
|
|
|
+ messageChain += msg;
|
|
});
|
|
});
|
|
}
|
|
}
|
|
if (1 - this.mode % 2)
|
|
if (1 - this.mode % 2)
|
|
@@ -339,14 +310,13 @@ class Webshot extends CallableInstance {
|
|
.sort((var1, var2) => var2.bitrate - var1.bitrate)
|
|
.sort((var1, var2) => var2.bitrate - var1.bitrate)
|
|
.map(variant => variant.url)[0];
|
|
.map(variant => variant.url)[0];
|
|
}
|
|
}
|
|
- const altMessage = mirai_1.Message.Plain(`\n[失败的${typeInZH[media.type].type}:${url}]`);
|
|
|
|
|
|
+ const altMessage = `\n[失败的${typeInZH[media.type].type}:${url}]`;
|
|
return this.fetchMedia(url)
|
|
return this.fetchMedia(url)
|
|
- .then(base64url => uploader(mirai_1.Message.Image('', base64url, media.type === 'photo' ? url : `${url} as gif`), () => altMessage))
|
|
|
|
.catch(error => {
|
|
.catch(error => {
|
|
logger.warn('unable to fetch media, sending plain text instead...');
|
|
logger.warn('unable to fetch media, sending plain text instead...');
|
|
return altMessage;
|
|
return altMessage;
|
|
})
|
|
})
|
|
- .then(msg => { messageChain.push(msg); });
|
|
|
|
|
|
+ .then(msg => { messageChain += msg; });
|
|
}));
|
|
}));
|
|
}
|
|
}
|
|
});
|
|
});
|
|
@@ -357,19 +327,19 @@ class Webshot extends CallableInstance {
|
|
.filter(urlObj => urlObj.indices[0] < originTwi.display_text_range[1])
|
|
.filter(urlObj => urlObj.indices[0] < originTwi.display_text_range[1])
|
|
.map(urlObj => `\n\ud83d\udd17 ${urlObj.expanded_url}`);
|
|
.map(urlObj => `\n\ud83d\udd17 ${urlObj.expanded_url}`);
|
|
if (urls.length) {
|
|
if (urls.length) {
|
|
- messageChain.push(mirai_1.Message.Plain(urls.join('')));
|
|
|
|
|
|
+ messageChain += urls.join('');
|
|
}
|
|
}
|
|
});
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (originTwi.is_quote_status) {
|
|
if (originTwi.is_quote_status) {
|
|
promise = promise.then(() => {
|
|
promise = promise.then(() => {
|
|
- messageChain.push(mirai_1.Message.Plain(`\n回复此命令查看引用的推文:\n/twitter_view ${originTwi.quoted_status_permalink.expanded}`));
|
|
|
|
|
|
+ messageChain += `\n回复此命令查看引用的推文:\n/twitter_view ${originTwi.quoted_status.id_str}`;
|
|
});
|
|
});
|
|
}
|
|
}
|
|
promise.then(() => {
|
|
promise.then(() => {
|
|
logger.info(`done working on ${twi.user.screen_name}/${twi.id_str}, message chain:`);
|
|
logger.info(`done working on ${twi.user.screen_name}/${twi.id_str}, message chain:`);
|
|
- logger.info(JSON.stringify(messageChain));
|
|
|
|
|
|
+ logger.info(JSON.stringify(koishi_1.ellipseBase64InMessage(messageChain)));
|
|
callback(messageChain, xmlEntities.decode(text), author);
|
|
callback(messageChain, xmlEntities.decode(text), author);
|
|
});
|
|
});
|
|
});
|
|
});
|