yz-yuki-plugin 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/LICENSE +21 -0
- package/README.md +195 -0
- package/defaultConfig/bilibili/config.yaml +41 -0
- package/defaultConfig/bilibili/push.yaml +0 -0
- package/defaultConfig/help/help.yaml +86 -0
- package/defaultConfig/weibo/config.yaml +41 -0
- package/defaultConfig/weibo/push.yaml +0 -0
- package/lib/apps/bilibili.js +402 -0
- package/lib/apps/help.js +37 -0
- package/lib/apps/index.js +4 -0
- package/lib/apps/version.js +34 -0
- package/lib/apps/weibo.js +252 -0
- package/lib/components/dynamic/Account.js +26 -0
- package/lib/components/dynamic/Content.js +118 -0
- package/lib/components/dynamic/Footer.js +36 -0
- package/lib/components/dynamic/ForwardContent.js +15 -0
- package/lib/components/dynamic/LogoText.js +10 -0
- package/lib/components/dynamic/MainPage.js +22 -0
- package/lib/components/help/Help.js +33 -0
- package/lib/components/index.js +6 -0
- package/lib/components/loginQrcode/Page.js +21 -0
- package/lib/components/version/Version.js +27 -0
- package/lib/index.js +29 -0
- package/lib/models/bilibili/bilibili.api.js +49 -0
- package/lib/models/bilibili/bilibili.get.web.data.js +80 -0
- package/lib/models/bilibili/bilibili.models.js +484 -0
- package/lib/models/bilibili/bilibili.query.js +393 -0
- package/lib/models/bilibili/bilibili.task.js +256 -0
- package/lib/models/bilibili/bilibili.wbi.js +49 -0
- package/lib/models/help/help.js +20 -0
- package/lib/models/version/version.js +62 -0
- package/lib/models/weibo/weibo.api.js +19 -0
- package/lib/models/weibo/weibo.get.web.data.js +55 -0
- package/lib/models/weibo/weibo.query.js +323 -0
- package/lib/models/weibo/weibo.task.js +215 -0
- package/lib/types/apps/bilibili.d.ts +6 -0
- package/lib/types/apps/help.d.ts +6 -0
- package/lib/types/apps/index.d.ts +4 -0
- package/lib/types/apps/version.d.ts +6 -0
- package/lib/types/apps/weibo.d.ts +6 -0
- package/lib/types/components/dynamic/Account.d.ts +13 -0
- package/lib/types/components/dynamic/Content.d.ts +12 -0
- package/lib/types/components/dynamic/Footer.d.ts +11 -0
- package/lib/types/components/dynamic/ForwardContent.d.ts +6 -0
- package/lib/types/components/dynamic/LogoText.d.ts +9 -0
- package/lib/types/components/dynamic/MainPage.d.ts +34 -0
- package/lib/types/components/help/Help.d.ts +12 -0
- package/lib/types/components/index.d.ts +5 -0
- package/lib/types/components/loginQrcode/Page.d.ts +7 -0
- package/lib/types/components/version/Version.d.ts +8 -0
- package/lib/types/index.d.ts +5 -0
- package/lib/types/models/bilibili/bilibili.api.d.ts +47 -0
- package/lib/types/models/bilibili/bilibili.buid.fp.d.ts +2 -0
- package/lib/types/models/bilibili/bilibili.get.web.data.d.ts +6 -0
- package/lib/types/models/bilibili/bilibili.models.d.ts +20 -0
- package/lib/types/models/bilibili/bilibili.query.d.ts +13 -0
- package/lib/types/models/bilibili/bilibili.task.d.ts +18 -0
- package/lib/types/models/bilibili/bilibili.wbi.d.ts +5 -0
- package/lib/types/models/help/help.d.ts +8 -0
- package/lib/types/models/version/version.d.ts +7 -0
- package/lib/types/models/weibo/weibo.api.d.ts +17 -0
- package/lib/types/models/weibo/weibo.get.web.data.d.ts +8 -0
- package/lib/types/models/weibo/weibo.query.d.ts +18 -0
- package/lib/types/models/weibo/weibo.task.d.ts +17 -0
- package/lib/types/utils/config.d.ts +21 -0
- package/lib/types/utils/image.d.ts +10 -0
- package/lib/types/utils/paths.d.ts +10 -0
- package/lib/types/utils/puppeteer.render.d.ts +23 -0
- package/lib/utils/config.js +108 -0
- package/lib/utils/image.js +26 -0
- package/lib/utils/paths.js +18 -0
- package/lib/utils/puppeteer.render.js +102 -0
- package/package.json +106 -0
- package/public/output.css +1 -0
- package/resources/css/dynamic/Account.css +68 -0
- package/resources/css/dynamic/Content.box.grid.4.css +4 -0
- package/resources/css/dynamic/Content.box.grid.9.css +4 -0
- package/resources/css/dynamic/Content.css +87 -0
- package/resources/css/dynamic/Footer.css +44 -0
- package/resources/css/dynamic/ForwardContent.css +11 -0
- package/resources/css/dynamic/LogoText.css +15 -0
- package/resources/css/dynamic/MainPage.css +93 -0
- package/resources/css/help/help.css +182 -0
- package/resources/css/loginQrcode/Page.css +55 -0
- package/resources/css/version/version.css +116 -0
- package/resources/fonts/iconfont.16acc2.ttf +0 -0
- package/resources/img/background/Girl.png +0 -0
- package/resources/img/icon/dynamic/bili-rich-text-module-goods-taobao.svg +1 -0
- package/resources/img/icon/dynamic/bili-rich-text-module-lottery.svg +1 -0
- package/resources/img/icon/dynamic/bilibili.svg +6 -0
- package/resources/img/icon/dynamic/weibo.svg +43 -0
- package/resources/img/icon/puplic/archaic_stone.png +0 -0
- package/resources/img/icon/puplic/condessence_crystal.png +0 -0
- package/resources/img/icon/puplic/delightful_encounter.png +0 -0
- package/resources/img/icon/puplic/diagram.png +0 -0
- package/resources/img/icon/puplic/essence_of_pure_sacred_dewdrop.png +0 -0
- package/resources/img/icon/puplic/everamber.png +0 -0
- package/resources/img/icon/puplic/flower_1.png +0 -0
- package/resources/img/icon/puplic/flower_2.png +0 -0
- package/resources/img/icon/puplic/kamera.png +0 -0
- package/resources/img/icon/puplic/lumidouce_bell.png +0 -0
- package/resources/img/icon/puplic/mora.png +0 -0
- package/resources/img/icon/puplic/pluie_lotus.png +0 -0
- package/resources/img/icon/puplic/restaurant_smoothie.png +0 -0
- package/resources/img/icon/puplic/romaritime_flower.png +0 -0
- package/resources/img/icon/puplic/shell.png +0 -0
- package/resources/img/icon/puplic/spring_of_pure_sacred_dewdrop.png +0 -0
- package/resources/img/icon/puplic/surging_sacred_chalice.png +0 -0
- package/resources/img/icon/puplic/tourbillon_device.png +0 -0
- package/resources/img/icon/puplic/unfading_silky_grace.png +0 -0
- package/resources/img/icon/puplic/wisdom.png +0 -0
- package/resources/img/icon/puplic/wondrous_lovely_flower.png +0 -0
- package/resources/img/icon/puplic//345/262/251/347/245/236/347/236/263/345/205/261/351/270/243/347/237/263.png +0 -0
- package/resources/img/icon/puplic//346/260/264/347/245/236/347/236/263/345/205/261/351/270/243/347/237/263.png +0 -0
- package/resources/img/icon/puplic//350/215/211/347/245/236/347/236/263/345/205/261/351/270/243/347/237/263.png +0 -0
- package/resources/img/icon/puplic//351/222/223/351/261/274.png +0 -0
- package/resources/img/icon/puplic//351/233/267/347/245/236/347/236/263/345/205/261/351/270/243/347/237/263.png +0 -0
- package/resources/img/icon/puplic//351/243/216/347/245/236/347/236/263/345/205/261/351/270/243/347/237/263.png +0 -0
- package/resources/img/icon/puplic//351/243/216/350/275/246.png +0 -0
- package/resources/img/readme/girl.png +0 -0
- package/resources/img/readme/min-Girl.png +0 -0
- package/resources/img/readme/mini-help.jpg +0 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import md5 from 'md5';
|
|
2
|
+
|
|
3
|
+
const mixinKeyEncTab = [
|
|
4
|
+
46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49,
|
|
5
|
+
33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40,
|
|
6
|
+
61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11,
|
|
7
|
+
36, 20, 34, 44, 52
|
|
8
|
+
];
|
|
9
|
+
const getMixinKey = (orig) => mixinKeyEncTab
|
|
10
|
+
.map((n) => orig[n])
|
|
11
|
+
.join("")
|
|
12
|
+
.slice(0, 32);
|
|
13
|
+
function encWbi(params, img_key, sub_key) {
|
|
14
|
+
const mixin_key = getMixinKey(img_key + sub_key), curr_time = Math.round(Date.now() / 1000), chr_filter = /[!'()*]/g;
|
|
15
|
+
Object.assign(params, { wts: curr_time });
|
|
16
|
+
const query = Object.keys(params)
|
|
17
|
+
.sort()
|
|
18
|
+
.map((key) => {
|
|
19
|
+
const value = params[key].toString().replace(chr_filter, "");
|
|
20
|
+
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
|
|
21
|
+
})
|
|
22
|
+
.join("&");
|
|
23
|
+
const wbi_sign = md5(query + mixin_key);
|
|
24
|
+
return {
|
|
25
|
+
query: query,
|
|
26
|
+
w_rid: wbi_sign,
|
|
27
|
+
time_stamp: curr_time
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
async function getWbiKeys(headers, cookie) {
|
|
31
|
+
const res = await fetch('https://api.bilibili.com/x/web-interface/nav', {
|
|
32
|
+
headers: {
|
|
33
|
+
Cookie: cookie,
|
|
34
|
+
'User-Agent': headers['User-Agent'],
|
|
35
|
+
Referer: 'https://www.bilibili.com/'
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
const { data: { wbi_img: { img_url, sub_url }, }, } = (await res.json());
|
|
39
|
+
return {
|
|
40
|
+
img_key: img_url.slice(img_url.lastIndexOf('/') + 1, img_url.lastIndexOf('.')),
|
|
41
|
+
sub_key: sub_url.slice(sub_url.lastIndexOf('/') + 1, sub_url.lastIndexOf('.'))
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
async function getWbiSign(params, headers, cookie) {
|
|
45
|
+
const { img_key, sub_key } = await getWbiKeys(headers, cookie);
|
|
46
|
+
return encWbi(params, img_key, sub_key);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export { getWbiSign };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import Config from '../../utils/config.js';
|
|
2
|
+
|
|
3
|
+
class Help {
|
|
4
|
+
e;
|
|
5
|
+
model;
|
|
6
|
+
constructor(e) {
|
|
7
|
+
this.model = "help";
|
|
8
|
+
this.e = e;
|
|
9
|
+
}
|
|
10
|
+
static async get(e) {
|
|
11
|
+
let helpData = new Help(e);
|
|
12
|
+
return await helpData.getData();
|
|
13
|
+
}
|
|
14
|
+
async getData() {
|
|
15
|
+
let helpData = Config.getDefaultConfig("help", "help");
|
|
16
|
+
return helpData;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { Help as default };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import fs__default from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { _paths } from '../../utils/paths.js';
|
|
4
|
+
|
|
5
|
+
class VersionData {
|
|
6
|
+
model;
|
|
7
|
+
cache;
|
|
8
|
+
versionPath;
|
|
9
|
+
constructor() {
|
|
10
|
+
this.model = 'versionData';
|
|
11
|
+
this.cache = {};
|
|
12
|
+
this.versionPath = path.resolve(_paths.pluginPath, 'CHANGELOG.md');
|
|
13
|
+
}
|
|
14
|
+
async getChangelogContent() {
|
|
15
|
+
let key = this.model;
|
|
16
|
+
if (this.cache[key])
|
|
17
|
+
return this.cache[key];
|
|
18
|
+
let content = fs__default.readFileSync(this.versionPath, 'utf8');
|
|
19
|
+
let lines = content.split('\n');
|
|
20
|
+
let result = [];
|
|
21
|
+
let currentVersion = null;
|
|
22
|
+
let currentData = [];
|
|
23
|
+
lines.forEach((line) => {
|
|
24
|
+
line = line.trim();
|
|
25
|
+
if (line.startsWith('# ')) {
|
|
26
|
+
if (currentVersion) {
|
|
27
|
+
result.push({
|
|
28
|
+
version: currentVersion,
|
|
29
|
+
data: currentData
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
currentVersion = line.slice(2).trim();
|
|
33
|
+
currentData = [];
|
|
34
|
+
}
|
|
35
|
+
else if (line.startsWith('* ')) {
|
|
36
|
+
currentData.push(line.slice(2).trim());
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
if (currentVersion) {
|
|
40
|
+
result.push({
|
|
41
|
+
version: currentVersion,
|
|
42
|
+
data: currentData
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
result.sort((a, b) => {
|
|
46
|
+
let aParts = a.version.split('.').map(Number);
|
|
47
|
+
let bParts = b.version.split('.').map(Number);
|
|
48
|
+
for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
|
|
49
|
+
let aPart = aParts[i] || 0;
|
|
50
|
+
let bPart = bParts[i] || 0;
|
|
51
|
+
if (aPart !== bPart) {
|
|
52
|
+
return bPart - aPart;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return 0;
|
|
56
|
+
});
|
|
57
|
+
this.cache[key] = result.slice(0, 5);
|
|
58
|
+
return this.cache[key];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export { VersionData as default };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class WeiboApi {
|
|
2
|
+
static WEIBO_API = {
|
|
3
|
+
weiboGetIndex: 'https://m.weibo.cn/api/container/getIndex',
|
|
4
|
+
weiboAjaxSearch: 'https://weibo.com/ajax/side/search',
|
|
5
|
+
};
|
|
6
|
+
static WEIBO_HEADERS = {
|
|
7
|
+
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
|
|
8
|
+
'Accept-language': 'zh-CN,zh;q=0.9',
|
|
9
|
+
'Authority': 'm.weibo.cn',
|
|
10
|
+
'Cache-control': 'max-age=0',
|
|
11
|
+
'Sec-fetch-dest': 'empty',
|
|
12
|
+
'Sec-fetch-mode': 'same-origin',
|
|
13
|
+
'Sec-fetch-site': 'same-origin',
|
|
14
|
+
'Upgrade-insecure-requests': '1',
|
|
15
|
+
'User-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:127.0) Gecko/20100101 Firefox/127.0',
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { WeiboApi };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import { Bot } from 'yunzai';
|
|
3
|
+
import { WeiboApi } from './weibo.api.js';
|
|
4
|
+
import { WeiboQuery } from './weibo.query.js';
|
|
5
|
+
|
|
6
|
+
class WeiboGetWebData {
|
|
7
|
+
e;
|
|
8
|
+
constructor(e) {
|
|
9
|
+
}
|
|
10
|
+
async getBloggerInfo(target) {
|
|
11
|
+
const param = { containerid: '100505' + target };
|
|
12
|
+
const url = new URL(WeiboApi.WEIBO_API.weiboGetIndex);
|
|
13
|
+
url.search = new URLSearchParams(param).toString();
|
|
14
|
+
const resp = await axios.get(url.toString(), {
|
|
15
|
+
timeout: 10000,
|
|
16
|
+
headers: { 'accept': '*/*', 'Content-Type': 'application/json', 'referer': 'https://m.weibo.cn' },
|
|
17
|
+
});
|
|
18
|
+
return resp;
|
|
19
|
+
}
|
|
20
|
+
async searchBloggerInfo(keyword) {
|
|
21
|
+
const url = WeiboApi.WEIBO_API.weiboAjaxSearch;
|
|
22
|
+
const params = {
|
|
23
|
+
q: keyword,
|
|
24
|
+
};
|
|
25
|
+
const resp = await axios.get(url, {
|
|
26
|
+
params,
|
|
27
|
+
timeout: 10000,
|
|
28
|
+
headers: { 'accept': '*/*', 'Content-Type': 'application/json', 'referer': 'https://s.weibo.com' },
|
|
29
|
+
});
|
|
30
|
+
return resp;
|
|
31
|
+
}
|
|
32
|
+
async getBloggerDynamicList(target) {
|
|
33
|
+
const params = { containerid: '107603' + target };
|
|
34
|
+
const url = new URL(WeiboApi.WEIBO_API.weiboGetIndex);
|
|
35
|
+
url.search = new URLSearchParams(params).toString();
|
|
36
|
+
await new Promise((resolve) => setTimeout(resolve, Math.floor(Math.random() * (6500 - 1000 + 1) + 1000)));
|
|
37
|
+
try {
|
|
38
|
+
const response = await axios.get(url.toString(), {
|
|
39
|
+
timeout: 15000,
|
|
40
|
+
headers: { 'accept': '*/*', 'Content-Type': 'application/json', 'referer': 'https://m.weibo.cn' },
|
|
41
|
+
});
|
|
42
|
+
const { ok, data, msg } = response.data;
|
|
43
|
+
if (!ok && msg !== '这里还没有内容') {
|
|
44
|
+
throw new Error(response.config.url);
|
|
45
|
+
}
|
|
46
|
+
return data.cards.filter(WeiboQuery.filterCardTypeCustom);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
(logger ?? Bot.logger)?.mark('微博推送:Error fetching sub list:', error);
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { WeiboGetWebData };
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import moment from 'moment';
|
|
2
|
+
import fetch from 'node-fetch';
|
|
3
|
+
import { WeiboApi } from './weibo.api.js';
|
|
4
|
+
import { Bot, Segment } from 'yunzai';
|
|
5
|
+
import { JSDOM } from 'jsdom';
|
|
6
|
+
|
|
7
|
+
class WeiboQuery {
|
|
8
|
+
static getDynamicId(post) {
|
|
9
|
+
return post?.mblog?.mid || post?.mblog?.id;
|
|
10
|
+
}
|
|
11
|
+
static filterCardTypeCustom(raw_post) {
|
|
12
|
+
return raw_post.card_type === 9;
|
|
13
|
+
}
|
|
14
|
+
static getDynamicCreatetDate(raw_post) {
|
|
15
|
+
const created_time = Date.parse(raw_post?.mblog?.created_at || raw_post?.created_at);
|
|
16
|
+
return created_time;
|
|
17
|
+
}
|
|
18
|
+
static MakeCategory(raw_post) {
|
|
19
|
+
if (raw_post?.mblog?.retweeted_status) {
|
|
20
|
+
return "DYNAMIC_TYPE_FORWARD";
|
|
21
|
+
}
|
|
22
|
+
else if (raw_post?.mblog?.page_info && raw_post?.mblog?.page_info?.type === 'video') {
|
|
23
|
+
return "DYNAMIC_TYPE_AV";
|
|
24
|
+
}
|
|
25
|
+
else if (raw_post?.mblog?.pics) {
|
|
26
|
+
return "DYNAMIC_TYPE_DRAW";
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
return "DYNAMIC_TYPE_ARTICLE";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
static filterText(raw_text) {
|
|
33
|
+
const text = raw_text.replace(/<br \/>/g, '\n');
|
|
34
|
+
const dom = new JSDOM(text);
|
|
35
|
+
return dom.window.document.body.textContent || '';
|
|
36
|
+
}
|
|
37
|
+
static async formatDynamicData(raw_post) {
|
|
38
|
+
let info = raw_post?.mblog || raw_post;
|
|
39
|
+
let retweeted = info && info?.retweeted_status ? true : false;
|
|
40
|
+
let pic_num = retweeted ? info?.retweeted_status?.pic_num : info?.pic_num;
|
|
41
|
+
let type = this.MakeCategory(raw_post);
|
|
42
|
+
if (info?.isLongText || pic_num > 9) {
|
|
43
|
+
const res = await fetch(`https://m.weibo.cn/detail/${info.mid}`, { headers: WeiboApi.WEIBO_HEADERS });
|
|
44
|
+
try {
|
|
45
|
+
const text = await res.text();
|
|
46
|
+
const match = text.match(/"status": ([\s\S]+),\s+"call"/);
|
|
47
|
+
if (match) {
|
|
48
|
+
const full_json_text = match[1];
|
|
49
|
+
info = JSON.parse(full_json_text);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
logger?.error(`优纪插件:微博 detail message error(https://m.weibo.cn/detail/${info?.mid})`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const face_url = info?.user?.profile_image_url;
|
|
57
|
+
const nick_name = info?.user?.screen_name;
|
|
58
|
+
let created_time = this.getDynamicCreatetDate(raw_post);
|
|
59
|
+
let detail_url = `https://weibo.com/${info?.user?.id}/${info?.bid}`;
|
|
60
|
+
let pics = [];
|
|
61
|
+
let formatData = { data: {} };
|
|
62
|
+
formatData.data.face = face_url;
|
|
63
|
+
formatData.data.name = nick_name;
|
|
64
|
+
formatData.data.pendant = '';
|
|
65
|
+
formatData.data.created = moment().format("YYYY年MM月DD日 HH:mm:ss");
|
|
66
|
+
formatData.data.type = type;
|
|
67
|
+
switch (type) {
|
|
68
|
+
case "DYNAMIC_TYPE_AV":
|
|
69
|
+
formatData.data.title = info?.page_info?.title || "";
|
|
70
|
+
formatData.data.content = this.parseRichTextNodes(info?.text);
|
|
71
|
+
formatData.data.url = detail_url;
|
|
72
|
+
formatData.data.pubTs = moment(created_time).format("YYYY年MM月DD日 HH:mm:ss");
|
|
73
|
+
formatData.data.category = "视频动态";
|
|
74
|
+
formatData.data.pics = info?.page_info?.page_pic?.url ? [{ url: info.page_info.page_pic.url }] : [];
|
|
75
|
+
break;
|
|
76
|
+
case "DYNAMIC_TYPE_DRAW":
|
|
77
|
+
let raw_pics_list = retweeted ? info?.retweeted_status?.pics || [] : info?.pics || [];
|
|
78
|
+
pics = raw_pics_list.map((img) => { return { url: img?.large?.url, width: Number(img?.large?.geo?.width), height: Number(img?.large?.geo?.height) }; }) || [];
|
|
79
|
+
formatData.data.title = "";
|
|
80
|
+
formatData.data.content = this.parseRichTextNodes(info?.text);
|
|
81
|
+
formatData.data.url = detail_url;
|
|
82
|
+
formatData.data.pubTs = moment(created_time).format("YYYY年MM月DD日 HH:mm:ss");
|
|
83
|
+
formatData.data.pics = pics;
|
|
84
|
+
formatData.data.category = "图文动态";
|
|
85
|
+
break;
|
|
86
|
+
case "DYNAMIC_TYPE_ARTICLE":
|
|
87
|
+
let raw_pics_list_article = retweeted ? info?.retweeted_status?.pics || [] : info?.pics || [];
|
|
88
|
+
pics = raw_pics_list_article.map((img) => { return { url: img?.large?.url, width: Number(img?.large?.geo?.width), height: Number(img?.large?.geo?.height) }; }) || [];
|
|
89
|
+
formatData.data.title = "";
|
|
90
|
+
formatData.data.content = this.parseRichTextNodes(info?.text);
|
|
91
|
+
formatData.data.url = detail_url;
|
|
92
|
+
formatData.data.pubTs = moment(created_time).format("YYYY年MM月DD日 HH:mm:ss");
|
|
93
|
+
formatData.data.pics = pics;
|
|
94
|
+
formatData.data.category = "文章动态";
|
|
95
|
+
break;
|
|
96
|
+
case "DYNAMIC_TYPE_FORWARD":
|
|
97
|
+
formatData.data.title = "";
|
|
98
|
+
formatData.data.content = this.parseRichTextNodes(info?.text);
|
|
99
|
+
formatData.data.pubTs = moment(created_time).format("YYYY年MM月DD日 HH:mm:ss");
|
|
100
|
+
formatData.data.url = detail_url;
|
|
101
|
+
formatData.data.pics = [];
|
|
102
|
+
let origin_post_info = info?.retweeted_status;
|
|
103
|
+
formatData.data.orig = await this.formatDynamicData(origin_post_info);
|
|
104
|
+
formatData.data.category = "转发动态";
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
...formatData,
|
|
109
|
+
uid: info?.id,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
;
|
|
113
|
+
static parseRichTextNodes = (nodes) => {
|
|
114
|
+
if (typeof nodes === 'string') {
|
|
115
|
+
let parsedContent = nodes.replace(/\n/g, '<br>');
|
|
116
|
+
parsedContent = parsedContent.replace(/<a/g, () => {
|
|
117
|
+
const randomKey = Math.random().toString(36).substring(7);
|
|
118
|
+
return `<a key="${randomKey}"`;
|
|
119
|
+
});
|
|
120
|
+
parsedContent = parsedContent.replace(/class="url-icon"/g, () => {
|
|
121
|
+
const randomKey = Math.random().toString(36).substring(7);
|
|
122
|
+
return `class="url-icon ${randomKey}"`;
|
|
123
|
+
});
|
|
124
|
+
parsedContent = parsedContent.replace(/<img/g, () => {
|
|
125
|
+
const randomKey = Math.random().toString(36).substring(7);
|
|
126
|
+
return `<img key="${randomKey}"`;
|
|
127
|
+
});
|
|
128
|
+
return parsedContent;
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
return nodes;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
static async formatTextDynamicData(upName, raw_post, isForward, setData) {
|
|
135
|
+
let msg = [], raw_pics_list, pic_urls, pics;
|
|
136
|
+
let info = raw_post?.mblog || raw_post;
|
|
137
|
+
let retweeted = info && info.retweeted_status ? true : false;
|
|
138
|
+
let pic_num = retweeted ? info?.retweeted_status?.pic_num : info?.pic_num;
|
|
139
|
+
let type = this.MakeCategory(raw_post);
|
|
140
|
+
if (info?.isLongText || pic_num > 9) {
|
|
141
|
+
const res = await fetch(`https://m.weibo.cn/detail/${info.mid}`, { headers: WeiboApi.WEIBO_HEADERS });
|
|
142
|
+
try {
|
|
143
|
+
const text = await res.text();
|
|
144
|
+
const match = text.match(/"status": ([\s\S]+),\s+"call"/);
|
|
145
|
+
if (match) {
|
|
146
|
+
const full_json_text = match[1];
|
|
147
|
+
info = JSON.parse(full_json_text);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
(logger ?? Bot.logger)?.mark(`优纪插件:获取微博动态全文出错:https://m.weibo.cn/detail/${info?.mid}`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
let created_time = this.getDynamicCreatetDate(raw_post);
|
|
155
|
+
let detail_url = `https://weibo.com/${info?.user?.id}/${info?.bid}`;
|
|
156
|
+
let title = `微博【${upName}】动态推送:\n`;
|
|
157
|
+
const dynamicPicCountLimit = setData.pushPicCountLimit || 3;
|
|
158
|
+
switch (type) {
|
|
159
|
+
case "DYNAMIC_TYPE_AV":
|
|
160
|
+
if (!info)
|
|
161
|
+
return;
|
|
162
|
+
let cover_img_url = info?.page_info?.page_pic?.url;
|
|
163
|
+
let cover_img = Segment.image(cover_img_url, false, 15000, { referer: "https://weibo.com", });
|
|
164
|
+
title = `微博【${upName}】视频动态推送:\n`;
|
|
165
|
+
msg = [
|
|
166
|
+
title,
|
|
167
|
+
`-----------------------------\n`,
|
|
168
|
+
`标题:${info?.page_info?.title || ""}\n`,
|
|
169
|
+
`${this.filterText(info?.text)}\n`,
|
|
170
|
+
`链接:${detail_url}\n`,
|
|
171
|
+
`时间:${created_time
|
|
172
|
+
? moment(created_time).format("YYYY年MM月DD日 HH:mm:ss")
|
|
173
|
+
: ""}\n`,
|
|
174
|
+
cover_img,
|
|
175
|
+
];
|
|
176
|
+
return msg;
|
|
177
|
+
case "DYNAMIC_TYPE_DRAW":
|
|
178
|
+
raw_pics_list = retweeted ? info?.retweeted_status?.pics || [] : info?.pics || [];
|
|
179
|
+
if (!info && !raw_pics_list)
|
|
180
|
+
return;
|
|
181
|
+
if (raw_pics_list.length > dynamicPicCountLimit)
|
|
182
|
+
raw_pics_list.length = dynamicPicCountLimit;
|
|
183
|
+
pic_urls = raw_pics_list.map((img) => img?.large?.url);
|
|
184
|
+
pics = [];
|
|
185
|
+
for (let pic_url of pic_urls) {
|
|
186
|
+
const temp = Segment.image(pic_url, false, 15000, { referer: "https://weibo.com", });
|
|
187
|
+
pics.push(temp);
|
|
188
|
+
}
|
|
189
|
+
title = `微博【${upName}】图文动态推送:\n`;
|
|
190
|
+
msg = [
|
|
191
|
+
title,
|
|
192
|
+
`-----------------------------\n`,
|
|
193
|
+
`${this.dynamicContentLimit(this.filterText(info?.text), setData)}\n`,
|
|
194
|
+
`链接:${detail_url}\n`,
|
|
195
|
+
`时间:${created_time
|
|
196
|
+
? moment(created_time).format("YYYY年MM月DD日 HH:mm:ss")
|
|
197
|
+
: ""}\n`,
|
|
198
|
+
...pics,
|
|
199
|
+
];
|
|
200
|
+
return msg;
|
|
201
|
+
case "DYNAMIC_TYPE_ARTICLE":
|
|
202
|
+
if (!info)
|
|
203
|
+
return;
|
|
204
|
+
raw_pics_list = retweeted ? info?.retweeted_status?.pics || [] : info?.pics || [];
|
|
205
|
+
if (raw_pics_list.length > dynamicPicCountLimit)
|
|
206
|
+
raw_pics_list.length = dynamicPicCountLimit;
|
|
207
|
+
pic_urls = raw_pics_list.map(img => img?.large?.url);
|
|
208
|
+
pics = [];
|
|
209
|
+
for (const pic_url of pic_urls) {
|
|
210
|
+
const temp = Segment.image(pic_url, false, 15000, { referer: "https://weibo.com", });
|
|
211
|
+
pics.push(temp);
|
|
212
|
+
}
|
|
213
|
+
title = `微博【${upName}】文章动态推送:\n`;
|
|
214
|
+
msg = [
|
|
215
|
+
title,
|
|
216
|
+
`-----------------------------\n`,
|
|
217
|
+
`正文:${this.dynamicContentLimit(this.filterText(info?.text), setData)}\n`,
|
|
218
|
+
`链接:${detail_url}\n`,
|
|
219
|
+
`时间:${created_time
|
|
220
|
+
? moment(created_time).format("YYYY年MM月DD日 HH:mm:ss")
|
|
221
|
+
: ""}\n`,
|
|
222
|
+
...pics,
|
|
223
|
+
];
|
|
224
|
+
return msg;
|
|
225
|
+
case "DYNAMIC_TYPE_FORWARD":
|
|
226
|
+
if (!info)
|
|
227
|
+
return;
|
|
228
|
+
if (!info?.retweeted_status)
|
|
229
|
+
return;
|
|
230
|
+
const origin_post_info = info?.retweeted_status;
|
|
231
|
+
isForward = true;
|
|
232
|
+
let orig = await this.formatTextDynamicData(upName, origin_post_info, isForward, setData);
|
|
233
|
+
if (orig && orig.length) {
|
|
234
|
+
orig = orig.slice(2);
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
title = `微博【${upName}】转发动态推送:\n`;
|
|
240
|
+
msg = [
|
|
241
|
+
title,
|
|
242
|
+
`-----------------------------\n`,
|
|
243
|
+
`${this.dynamicContentLimit(this.filterText(info?.text), setData)}\n`,
|
|
244
|
+
`链接:${detail_url}\n`,
|
|
245
|
+
`时间:${created_time
|
|
246
|
+
? moment(created_time).format("YYYY年MM月DD日 HH:mm:ss")
|
|
247
|
+
: ""}\n`,
|
|
248
|
+
"\n---以下为转发内容---\n",
|
|
249
|
+
...orig,
|
|
250
|
+
];
|
|
251
|
+
return msg;
|
|
252
|
+
default:
|
|
253
|
+
logger?.mark(`未处理的微博推送【${upName}】:${type}`);
|
|
254
|
+
return "continue";
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
static dynamicContentLimit(content, setData) {
|
|
258
|
+
const lines = content.split("\n");
|
|
259
|
+
const lengthLimit = setData.pushContentLenLimit || 100;
|
|
260
|
+
const lineLimit = setData.pushContentLineLimit || 5;
|
|
261
|
+
if (lines.length > lineLimit) {
|
|
262
|
+
lines.length = lineLimit;
|
|
263
|
+
}
|
|
264
|
+
let totalLength = 0;
|
|
265
|
+
for (let i = 0; i < lines.length; i++) {
|
|
266
|
+
const remainingLength = lengthLimit - totalLength;
|
|
267
|
+
if (totalLength >= lengthLimit) {
|
|
268
|
+
lines.splice(i--, 1);
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
if (lines[i].length > remainingLength) {
|
|
272
|
+
lines[i] = lines[i].slice(0, remainingLength) + "...";
|
|
273
|
+
totalLength = lengthLimit;
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
totalLength += lines[i].length;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return lines.join("\n");
|
|
280
|
+
}
|
|
281
|
+
static formatUrl(url) {
|
|
282
|
+
return 0 == url.indexOf('//') ? `https:${url}` : url;
|
|
283
|
+
}
|
|
284
|
+
static typeHandle(up, msg, type) {
|
|
285
|
+
const typeMap = {
|
|
286
|
+
"直播": "DYNAMIC_TYPE_LIVE_RCMD",
|
|
287
|
+
"转发": "DYNAMIC_TYPE_FORWARD",
|
|
288
|
+
"文章": "DYNAMIC_TYPE_ARTICLE",
|
|
289
|
+
"图文": ["DYNAMIC_TYPE_DRAW", "DYNAMIC_TYPE_WORD"],
|
|
290
|
+
"视频": "DYNAMIC_TYPE_AV"
|
|
291
|
+
};
|
|
292
|
+
let newType = new Set(up.type || []);
|
|
293
|
+
const handleType = (action) => {
|
|
294
|
+
let isHandled = false;
|
|
295
|
+
for (const [key, value] of Object.entries(typeMap)) {
|
|
296
|
+
if (msg.indexOf(key) !== -1) {
|
|
297
|
+
if (Array.isArray(value)) {
|
|
298
|
+
value.forEach(v => action === "add" ? newType.add(v) : newType.delete(v));
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
action === "add" ? newType.add(value) : newType.delete(value);
|
|
302
|
+
}
|
|
303
|
+
isHandled = true;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return isHandled;
|
|
307
|
+
};
|
|
308
|
+
if (type === "add") {
|
|
309
|
+
handleType("add");
|
|
310
|
+
}
|
|
311
|
+
else if (type === "del") {
|
|
312
|
+
if (!newType.size) {
|
|
313
|
+
newType = new Set(Object.values(typeMap).flat());
|
|
314
|
+
}
|
|
315
|
+
if (!handleType("delete")) {
|
|
316
|
+
newType.clear();
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return Array.from(newType);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
export { WeiboQuery };
|