koishi-plugin-weibo-post-monitor 0.0.10 → 1.0.1-beta.0
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/lib/index.d.ts +4 -12
- package/lib/index.js +349 -180
- package/lib/services/config.d.ts +10 -0
- package/lib/services/constant.d.ts +1 -0
- package/lib/services/cookie.d.ts +6 -0
- package/lib/services/message.d.ts +2 -0
- package/lib/services/utils.d.ts +3 -0
- package/lib/services/weibo.d.ts +1 -0
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -1,13 +1,5 @@
|
|
|
1
|
-
import { Context
|
|
1
|
+
import { Context } from 'koishi';
|
|
2
|
+
import { Config, type Config as ConfigType } from './services/config';
|
|
2
3
|
export declare const name = "weibo-post-monitor";
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
plantform: string;
|
|
6
|
-
waitMinutes: number;
|
|
7
|
-
sendINFO: any;
|
|
8
|
-
is_using_cookie: boolean;
|
|
9
|
-
manual_cookie: string;
|
|
10
|
-
}
|
|
11
|
-
export declare const Config: Schema<Config>;
|
|
12
|
-
export declare function to<T, U = Error>(promise: Promise<T>, errorExt?: object): Promise<[U, undefined] | [null, T]>;
|
|
13
|
-
export declare function apply(ctx: Context, config: Config): void;
|
|
4
|
+
export { Config };
|
|
5
|
+
export declare function apply(ctx: Context, config: ConfigType): void;
|
package/lib/index.js
CHANGED
|
@@ -32,23 +32,12 @@ var src_exports = {};
|
|
|
32
32
|
__export(src_exports, {
|
|
33
33
|
Config: () => Config,
|
|
34
34
|
apply: () => apply,
|
|
35
|
-
name: () => name
|
|
36
|
-
to: () => to
|
|
35
|
+
name: () => name
|
|
37
36
|
});
|
|
38
37
|
module.exports = __toCommonJS(src_exports);
|
|
38
|
+
|
|
39
|
+
// src/services/config.ts
|
|
39
40
|
var import_koishi = require("koishi");
|
|
40
|
-
var import_https = __toESM(require("https"));
|
|
41
|
-
var import_axios = __toESM(require("axios"));
|
|
42
|
-
var name = "weibo-post-monitor";
|
|
43
|
-
var auto_cookie = null;
|
|
44
|
-
var now_user_agent = null;
|
|
45
|
-
var user_agent_list = [
|
|
46
|
-
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36",
|
|
47
|
-
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.5993.90 Safari/537.36",
|
|
48
|
-
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.6045.105 Safari/537.36",
|
|
49
|
-
"Mozilla/5.0 (Windows NT 11.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.71 Safari/537.36",
|
|
50
|
-
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.5845.187 Safari/537.36"
|
|
51
|
-
];
|
|
52
41
|
var Config = import_koishi.Schema.object({
|
|
53
42
|
account: import_koishi.Schema.string().description("账号(qq号)"),
|
|
54
43
|
plantform: import_koishi.Schema.string().default("onebot").description("账号平台"),
|
|
@@ -64,139 +53,137 @@ var Config = import_koishi.Schema.object({
|
|
|
64
53
|
sendAll: import_koishi.Schema.boolean().default(false).description("@全体成员")
|
|
65
54
|
})).description("监听&发送配置")
|
|
66
55
|
});
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
56
|
+
|
|
57
|
+
// src/services/constant.ts
|
|
58
|
+
var USER_AGENT_LIST = [
|
|
59
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36",
|
|
60
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.5993.90 Safari/537.36",
|
|
61
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.6045.105 Safari/537.36",
|
|
62
|
+
"Mozilla/5.0 (Windows NT 11.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.71 Safari/537.36",
|
|
63
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.5845.187 Safari/537.36",
|
|
64
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.7267.799 Safari/537.36 Edge/13.10586",
|
|
65
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.4907.884 Safari/537.36 Edge/13.10586",
|
|
66
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.6562.41 Safari/537.36 Edge/13.10586",
|
|
67
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2276.302 Safari/537.36 Edge/13.10586",
|
|
68
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.5174.848 Safari/537.36 Edge/13.10586",
|
|
69
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.4662.897 Safari/537.36 Edge/13.10586",
|
|
70
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.8759.750 Safari/537.36 Edge/13.10586",
|
|
71
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.9383.882 Safari/537.36 Edge/13.10586",
|
|
72
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.7253.966 Safari/537.36 Edge/13.10586",
|
|
73
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.3909.697 Safari/537.36 Edge/13.10586",
|
|
74
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.6167.85 Safari/537.36",
|
|
75
|
+
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.130 Safari/537.36",
|
|
76
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.6045.199 Safari/537.36",
|
|
77
|
+
"Mozilla/5.0 (Windows NT 11.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.6167.139 Safari/537.36",
|
|
78
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.5993.118 Safari/537.36",
|
|
79
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.5938.149 Safari/537.36",
|
|
80
|
+
"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.5845.140 Safari/537.36"
|
|
81
|
+
];
|
|
82
|
+
|
|
83
|
+
// src/services/cookie.ts
|
|
84
|
+
var import_axios = __toESM(require("axios"));
|
|
85
|
+
var auto_cookie = null;
|
|
86
|
+
var now_user_agent = null;
|
|
87
|
+
function setCookie(cookie) {
|
|
88
|
+
auto_cookie = cookie;
|
|
75
89
|
}
|
|
76
|
-
__name(
|
|
77
|
-
function
|
|
78
|
-
|
|
79
|
-
account: config.account,
|
|
80
|
-
plantform: config.plantform,
|
|
81
|
-
waitMinutes: config.waitMinutes,
|
|
82
|
-
is_using_cookie: config.is_using_cookie
|
|
83
|
-
};
|
|
84
|
-
auto_cookie = config.manual_cookie;
|
|
85
|
-
now_user_agent = user_agent_list[0];
|
|
86
|
-
ctx.setInterval(async () => {
|
|
87
|
-
for (const singleConfig of config.sendINFO) {
|
|
88
|
-
const params = { ...commonConfig, ...singleConfig };
|
|
89
|
-
getWeiboAndSendMessageToGroup(ctx, params);
|
|
90
|
-
}
|
|
91
|
-
}, config.waitMinutes > 0 ? config.waitMinutes * 60 * 1e3 : 6e4);
|
|
90
|
+
__name(setCookie, "setCookie");
|
|
91
|
+
function getCookie() {
|
|
92
|
+
return auto_cookie;
|
|
92
93
|
}
|
|
93
|
-
__name(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}, "getWeiboAndSendMessageToGroup");
|
|
113
|
-
var getLastPost = /* @__PURE__ */ __name((params, weiboList) => {
|
|
114
|
-
for (const wb_element of weiboList) {
|
|
115
|
-
const result = getMessage(params, wb_element);
|
|
116
|
-
if (!result) {
|
|
117
|
-
continue;
|
|
118
|
-
}
|
|
119
|
-
if (result.islast) {
|
|
120
|
-
return result.post;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
return null;
|
|
124
|
-
}, "getLastPost");
|
|
125
|
-
var getMessage = /* @__PURE__ */ __name((params, wbPost) => {
|
|
126
|
-
if (!wbPost) {
|
|
127
|
-
return null;
|
|
128
|
-
}
|
|
129
|
-
const { created_at, user } = wbPost;
|
|
130
|
-
const time = parseDateString(created_at);
|
|
131
|
-
const lastCheckTime = Date.now() - (params.waitMinutes > 0 ? params.waitMinutes * 60 * 1e3 : 6e4);
|
|
132
|
-
if (time.getTime() < lastCheckTime) {
|
|
133
|
-
return null;
|
|
134
|
-
}
|
|
135
|
-
const screenName = user?.screen_name || "";
|
|
136
|
-
let weiboType = -1;
|
|
137
|
-
if ("page_info" in wbPost) {
|
|
138
|
-
weiboType = 0;
|
|
139
|
-
}
|
|
140
|
-
if ("pic_infos" in wbPost) {
|
|
141
|
-
weiboType = 2;
|
|
142
|
-
}
|
|
143
|
-
if ("topic_struct" in wbPost || "retweeted_status" in wbPost) {
|
|
144
|
-
weiboType = 1;
|
|
94
|
+
__name(getCookie, "getCookie");
|
|
95
|
+
function setUserAgent(userAgent) {
|
|
96
|
+
now_user_agent = userAgent;
|
|
97
|
+
}
|
|
98
|
+
__name(setUserAgent, "setUserAgent");
|
|
99
|
+
function getUserAgent() {
|
|
100
|
+
return now_user_agent;
|
|
101
|
+
}
|
|
102
|
+
__name(getUserAgent, "getUserAgent");
|
|
103
|
+
function getRandomUserAgent() {
|
|
104
|
+
return USER_AGENT_LIST[Math.floor(Math.random() * USER_AGENT_LIST.length)];
|
|
105
|
+
}
|
|
106
|
+
__name(getRandomUserAgent, "getRandomUserAgent");
|
|
107
|
+
var mergeCookies = /* @__PURE__ */ __name((cookies) => {
|
|
108
|
+
return cookies.map((c) => c.split(";")[0]).join("; ");
|
|
109
|
+
}, "mergeCookies");
|
|
110
|
+
async function fetchCookie() {
|
|
111
|
+
if (!now_user_agent) {
|
|
112
|
+
now_user_agent = USER_AGENT_LIST[0];
|
|
145
113
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
114
|
+
const commonHeaders = {
|
|
115
|
+
"user-agent": now_user_agent,
|
|
116
|
+
"accept": "*/*",
|
|
117
|
+
"origin": "https://passport.weibo.com",
|
|
118
|
+
"referer": "https://passport.weibo.com/visitor/visitor"
|
|
119
|
+
};
|
|
120
|
+
let allCookies = [];
|
|
121
|
+
const step1Response = await import_axios.default.post("https://passport.weibo.com/visitor/genvisitor2", "cb=visitor_gray_callback&ver=20250916&request_id=fb15e537349aef3542ed130a47d48eb8&tid=&from=weibo&webdriver=false&rid=01by624JxwbmsPak-53wiC9LGhR6I&return_url=https://weibo.com/", {
|
|
122
|
+
headers: {
|
|
123
|
+
...commonHeaders,
|
|
124
|
+
"content-type": "application/x-www-form-urlencoded"
|
|
125
|
+
},
|
|
126
|
+
responseType: "text"
|
|
127
|
+
});
|
|
128
|
+
const step1SetCookies = step1Response.headers["set-cookie"] || [];
|
|
129
|
+
allCookies.push(...step1SetCookies);
|
|
130
|
+
const step1Body = step1Response.data;
|
|
131
|
+
let visitorId = "";
|
|
132
|
+
try {
|
|
133
|
+
const jsonMatch = step1Body.match(/visitor_gray_callback\s*\(\s*({[\s\S]*})\s*\)/);
|
|
134
|
+
if (!jsonMatch || !jsonMatch[1]) {
|
|
135
|
+
throw new Error("无法从响应中提取 JSON 对象");
|
|
157
136
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if (
|
|
161
|
-
|
|
137
|
+
const step1Data = JSON.parse(jsonMatch[1]);
|
|
138
|
+
visitorId = step1Data?.data?.tid || "";
|
|
139
|
+
if (!visitorId) {
|
|
140
|
+
throw new Error("未获取到 visitor id,响应数据: " + JSON.stringify(step1Data));
|
|
162
141
|
}
|
|
142
|
+
} catch (error) {
|
|
143
|
+
throw new Error("解析 genvisitor2 响应失败: " + error.message + ", 响应体: " + step1Body);
|
|
163
144
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
var
|
|
145
|
+
const step2Response = await import_axios.default.get(`https://passport.weibo.com/visitor/visitor?a=incarnate&t=${encodeURIComponent(visitorId)}`, {
|
|
146
|
+
headers: {
|
|
147
|
+
...commonHeaders,
|
|
148
|
+
"cookie": mergeCookies(allCookies)
|
|
149
|
+
},
|
|
150
|
+
responseType: "text"
|
|
151
|
+
});
|
|
152
|
+
const step2SetCookies = step2Response.headers["set-cookie"] || [];
|
|
153
|
+
allCookies.push(...step2SetCookies);
|
|
154
|
+
return mergeCookies(allCookies);
|
|
155
|
+
}
|
|
156
|
+
__name(fetchCookie, "fetchCookie");
|
|
157
|
+
|
|
158
|
+
// src/services/message.ts
|
|
159
|
+
var import_koishi2 = require("koishi");
|
|
160
|
+
|
|
161
|
+
// src/services/weibo.ts
|
|
162
|
+
var import_https = __toESM(require("https"));
|
|
163
|
+
async function getWeibo(config, callback, retry = false) {
|
|
182
164
|
const { weiboUID, is_using_cookie } = config;
|
|
183
165
|
if (!weiboUID) {
|
|
184
166
|
return;
|
|
185
167
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
168
|
+
let auto_cookie2 = getCookie();
|
|
169
|
+
let now_user_agent2 = getUserAgent();
|
|
170
|
+
if (!is_using_cookie && !auto_cookie2) {
|
|
171
|
+
const randomUserAgent = getRandomUserAgent();
|
|
172
|
+
setUserAgent(randomUserAgent);
|
|
173
|
+
now_user_agent2 = randomUserAgent;
|
|
174
|
+
auto_cookie2 = await fetchCookie();
|
|
175
|
+
setCookie(auto_cookie2);
|
|
189
176
|
}
|
|
190
|
-
if (!
|
|
177
|
+
if (!auto_cookie2) {
|
|
191
178
|
throw new Error("Cookie config is null, please check the config");
|
|
192
179
|
}
|
|
193
180
|
const headers = {
|
|
194
181
|
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
|
|
195
182
|
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
|
|
196
183
|
"cache-control": "no-cache",
|
|
197
|
-
"cookie":
|
|
184
|
+
"cookie": auto_cookie2,
|
|
198
185
|
"referer": "https://www.weibo.com/u/" + weiboUID,
|
|
199
|
-
"user-agent":
|
|
186
|
+
"user-agent": now_user_agent2 || ""
|
|
200
187
|
};
|
|
201
188
|
const options = {
|
|
202
189
|
hostname: "www.weibo.com",
|
|
@@ -218,8 +205,10 @@ var getWeibo = /* @__PURE__ */ __name(async (config, callback, retry = false) =>
|
|
|
218
205
|
} catch (error) {
|
|
219
206
|
if (!retry && !is_using_cookie) {
|
|
220
207
|
try {
|
|
221
|
-
|
|
222
|
-
|
|
208
|
+
const randomUserAgent = getRandomUserAgent();
|
|
209
|
+
setUserAgent(randomUserAgent);
|
|
210
|
+
const newCookie = await fetchCookie();
|
|
211
|
+
setCookie(newCookie);
|
|
223
212
|
const retryResult = await getWeibo(config, callback, true);
|
|
224
213
|
resolve(retryResult);
|
|
225
214
|
} catch (retryError) {
|
|
@@ -235,8 +224,21 @@ var getWeibo = /* @__PURE__ */ __name(async (config, callback, retry = false) =>
|
|
|
235
224
|
});
|
|
236
225
|
});
|
|
237
226
|
});
|
|
238
|
-
}
|
|
239
|
-
|
|
227
|
+
}
|
|
228
|
+
__name(getWeibo, "getWeibo");
|
|
229
|
+
|
|
230
|
+
// src/services/utils.ts
|
|
231
|
+
function to(promise, errorExt) {
|
|
232
|
+
return promise.then((data) => [null, data]).catch((err) => {
|
|
233
|
+
if (errorExt) {
|
|
234
|
+
const parsedError = Object.assign({}, err, errorExt);
|
|
235
|
+
return [parsedError, void 0];
|
|
236
|
+
}
|
|
237
|
+
return [err, void 0];
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
__name(to, "to");
|
|
241
|
+
function parseDateString(dateString) {
|
|
240
242
|
const regex = /(\w+) (\w+) (\d+) (\d+):(\d+):(\d+) ([+-]\d{4}) (\d{4})/;
|
|
241
243
|
const match = dateString.match(regex);
|
|
242
244
|
if (!match) {
|
|
@@ -257,14 +259,22 @@ var parseDateString = /* @__PURE__ */ __name((dateString) => {
|
|
|
257
259
|
Nov: 10,
|
|
258
260
|
Dec: 11
|
|
259
261
|
};
|
|
260
|
-
const date = new Date(Date.UTC(
|
|
262
|
+
const date = new Date(Date.UTC(
|
|
263
|
+
parseInt(year, 10),
|
|
264
|
+
monthMap[month],
|
|
265
|
+
parseInt(day, 10),
|
|
266
|
+
parseInt(hour, 10),
|
|
267
|
+
parseInt(minute, 10),
|
|
268
|
+
parseInt(second, 10)
|
|
269
|
+
));
|
|
261
270
|
const timezoneOffsetHours = parseInt(timezone.slice(0, 3), 10);
|
|
262
271
|
const timezoneOffsetMinutes = parseInt(timezone.slice(0, 1) + timezone.slice(3), 10);
|
|
263
272
|
const timezoneOffset = timezoneOffsetHours * 60 + timezoneOffsetMinutes;
|
|
264
273
|
date.setUTCMinutes(date.getUTCMinutes() - timezoneOffset);
|
|
265
274
|
return date;
|
|
266
|
-
}
|
|
267
|
-
|
|
275
|
+
}
|
|
276
|
+
__name(parseDateString, "parseDateString");
|
|
277
|
+
function checkWords(params, message) {
|
|
268
278
|
if (message == null)
|
|
269
279
|
return false;
|
|
270
280
|
let keywordsList = params.keywords?.split(";") || [];
|
|
@@ -294,57 +304,216 @@ var checkWords = /* @__PURE__ */ __name((params, message) => {
|
|
|
294
304
|
}
|
|
295
305
|
}
|
|
296
306
|
return true;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
var
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
const
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
307
|
+
}
|
|
308
|
+
__name(checkWords, "checkWords");
|
|
309
|
+
|
|
310
|
+
// src/services/message.ts
|
|
311
|
+
var import_axios2 = __toESM(require("axios"));
|
|
312
|
+
var import_vm = require("vm");
|
|
313
|
+
async function getWeiboAndSendMessageToGroup(ctx, params) {
|
|
314
|
+
const [err, res] = await to(getWeibo(params));
|
|
315
|
+
if (err) {
|
|
316
|
+
ctx.logger.error(err);
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
const data = res.data || {};
|
|
320
|
+
const weiboList = data.list || [];
|
|
321
|
+
const result = await getLastPost(params, weiboList);
|
|
322
|
+
if (!result) {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
let message = result;
|
|
326
|
+
if (params.sendAll) {
|
|
327
|
+
message = import_koishi2.h.at("all") + " " + message;
|
|
328
|
+
}
|
|
329
|
+
ctx.bots[`${params.plantform}:${params.account}`].sendMessage(params.groupID, message);
|
|
330
|
+
console.log(message);
|
|
331
|
+
}
|
|
332
|
+
__name(getWeiboAndSendMessageToGroup, "getWeiboAndSendMessageToGroup");
|
|
333
|
+
async function getLastPost(params, weiboList) {
|
|
334
|
+
for (const wb_element of weiboList) {
|
|
335
|
+
const result = await getMessage(params, wb_element);
|
|
336
|
+
if (!result) {
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
if (result.islast) {
|
|
340
|
+
return result.post;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
__name(getLastPost, "getLastPost");
|
|
346
|
+
async function getMessage(params, wbPost) {
|
|
347
|
+
if (!wbPost) {
|
|
348
|
+
return null;
|
|
349
|
+
}
|
|
350
|
+
const { created_at, user } = wbPost;
|
|
351
|
+
const time = parseDateString(created_at);
|
|
352
|
+
const lastCheckTime = Date.now() - (params.waitMinutes > 0 ? params.waitMinutes * 60 * 1e3 : 6e4);
|
|
353
|
+
const screenName = user?.screen_name || "";
|
|
354
|
+
let weiboType = -1;
|
|
355
|
+
if ("page_info" in wbPost) {
|
|
356
|
+
weiboType = 0;
|
|
357
|
+
}
|
|
358
|
+
if ("pic_infos" in wbPost) {
|
|
359
|
+
weiboType = 2;
|
|
360
|
+
}
|
|
361
|
+
if ("topic_struct" in wbPost || "retweeted_status" in wbPost) {
|
|
362
|
+
weiboType = 1;
|
|
363
|
+
}
|
|
364
|
+
let message_text = "";
|
|
365
|
+
let tempMessage = "";
|
|
366
|
+
if (!checkWords(params, wbPost?.text_raw)) {
|
|
367
|
+
return null;
|
|
368
|
+
}
|
|
369
|
+
if (weiboType == 0) {
|
|
370
|
+
const pageInfo = wbPost?.page_info;
|
|
371
|
+
if (!pageInfo) {
|
|
372
|
+
return null;
|
|
373
|
+
}
|
|
374
|
+
const objType = pageInfo?.object_type || "";
|
|
375
|
+
if (objType == "video") {
|
|
376
|
+
const text = wbPost?.text_raw || "";
|
|
377
|
+
const video = pageInfo?.media_info?.h5_url || "";
|
|
378
|
+
tempMessage += screenName + " 发布了微博:\n{temp_text}\n" + video || "";
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
if (weiboType == 1) {
|
|
382
|
+
if (params.forward) {
|
|
383
|
+
tempMessage += screenName + " 转发了微博:\n{temp_text}" || "";
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
if (weiboType == 2) {
|
|
387
|
+
const text = wbPost?.text_raw || "";
|
|
388
|
+
const picIds = wbPost?.pic_ids || [];
|
|
389
|
+
const picInfos = wbPost?.pic_infos || {};
|
|
390
|
+
const firstPicUrl = picInfos?.[picIds[0]]?.large?.url || "";
|
|
391
|
+
const picture = import_koishi2.h.image(firstPicUrl);
|
|
392
|
+
tempMessage += screenName + " 发布了微博:\n{temp_text}\n" + picture || "";
|
|
393
|
+
}
|
|
394
|
+
const mid = wbPost?.mid || "";
|
|
395
|
+
const url = `https://m.weibo.cn/status/${mid}`;
|
|
396
|
+
const detailMessage = await getDetailMessage(url);
|
|
397
|
+
if (detailMessage) {
|
|
398
|
+
message_text = detailMessage;
|
|
399
|
+
}
|
|
400
|
+
const urlMessage = `
|
|
401
|
+
微博链接:${url}`;
|
|
402
|
+
if (!checkWords(params, message_text)) {
|
|
403
|
+
return null;
|
|
404
|
+
}
|
|
405
|
+
let message = tempMessage.replace("{temp_text}", message_text);
|
|
406
|
+
const wbpost = message ? message + urlMessage : screenName + " 发布了微博:\n" + wbPost?.text_raw + urlMessage || "";
|
|
407
|
+
return { post: wbpost, islast: true };
|
|
408
|
+
}
|
|
409
|
+
__name(getMessage, "getMessage");
|
|
410
|
+
function stripHtmlTags(html) {
|
|
411
|
+
if (!html) return "";
|
|
412
|
+
let text = html;
|
|
413
|
+
text = text.replace(/<br\s*\/?>/gi, "\n");
|
|
414
|
+
text = text.replace(/<span\s+class=['"]surl-text['"][^>]*>([^<]*)<\/span>/gi, "$1");
|
|
415
|
+
text = text.replace(/<img[^>]*>/gi, "");
|
|
416
|
+
let lastText = "";
|
|
417
|
+
let iterations = 0;
|
|
418
|
+
while (text !== lastText && iterations < 10) {
|
|
419
|
+
lastText = text;
|
|
420
|
+
text = text.replace(/<a[^>]*>([^<]*(?:<[^>]*>[^<]*<\/[^>]*>[^<]*)*)<\/a>/gi, "$1");
|
|
421
|
+
iterations++;
|
|
422
|
+
}
|
|
423
|
+
text = text.replace(/<[^>]+>/g, "");
|
|
424
|
+
text = text.replace(/ /g, " ");
|
|
425
|
+
text = text.replace(/</g, "<");
|
|
426
|
+
text = text.replace(/>/g, ">");
|
|
427
|
+
text = text.replace(/"/g, '"');
|
|
428
|
+
text = text.replace(/'/g, "'");
|
|
429
|
+
text = text.replace(/'/g, "'");
|
|
430
|
+
text = text.replace(/&/g, "&");
|
|
431
|
+
text = text.replace(/[ \t]+/g, " ");
|
|
432
|
+
text = text.replace(/\n[ \t]+/g, "\n");
|
|
433
|
+
text = text.replace(/[ \t]+\n/g, "\n");
|
|
434
|
+
text = text.replace(/\n{3,}/g, "\n\n");
|
|
435
|
+
text = text.trim();
|
|
436
|
+
return text;
|
|
437
|
+
}
|
|
438
|
+
__name(stripHtmlTags, "stripHtmlTags");
|
|
439
|
+
async function getDetailMessage(wb_url) {
|
|
320
440
|
try {
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
|
|
441
|
+
const cookie = getCookie();
|
|
442
|
+
const userAgent = getUserAgent();
|
|
443
|
+
if (!cookie) {
|
|
444
|
+
return null;
|
|
324
445
|
}
|
|
325
|
-
const
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
446
|
+
const headers = {
|
|
447
|
+
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
|
|
448
|
+
"accept-language": "zh-CN,zh;q=0.9",
|
|
449
|
+
"user-agent": userAgent || "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
|
|
450
|
+
"cookie": cookie
|
|
451
|
+
};
|
|
452
|
+
const response = await import_axios2.default.get(wb_url, {
|
|
453
|
+
headers,
|
|
454
|
+
responseType: "text",
|
|
455
|
+
timeout: 1e4
|
|
456
|
+
});
|
|
457
|
+
const html = response.data;
|
|
458
|
+
const startMarker = "var $render_data = ";
|
|
459
|
+
const startIndex = html.indexOf(startMarker);
|
|
460
|
+
if (startIndex === -1) {
|
|
461
|
+
return null;
|
|
462
|
+
}
|
|
463
|
+
const scriptEndIndex = html.indexOf("</script>", startIndex);
|
|
464
|
+
const nextVarIndex = html.indexOf("\n var ", startIndex + startMarker.length);
|
|
465
|
+
let codeEndIndex = html.length;
|
|
466
|
+
if (scriptEndIndex !== -1 && scriptEndIndex < codeEndIndex) {
|
|
467
|
+
codeEndIndex = scriptEndIndex;
|
|
468
|
+
}
|
|
469
|
+
if (nextVarIndex !== -1 && nextVarIndex < codeEndIndex) {
|
|
470
|
+
codeEndIndex = nextVarIndex;
|
|
471
|
+
}
|
|
472
|
+
let code = html.substring(startIndex, codeEndIndex).trim();
|
|
473
|
+
if (!code.endsWith(";")) {
|
|
474
|
+
const lastSemicolon = code.lastIndexOf(";");
|
|
475
|
+
if (lastSemicolon !== -1) {
|
|
476
|
+
code = code.substring(0, lastSemicolon + 1);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
const context = (0, import_vm.createContext)({});
|
|
480
|
+
(0, import_vm.runInContext)(code, context);
|
|
481
|
+
const renderData = context.$render_data;
|
|
482
|
+
if (!renderData || !renderData.status || !renderData.status.text) {
|
|
483
|
+
return null;
|
|
329
484
|
}
|
|
485
|
+
const htmlText = renderData.status.text;
|
|
486
|
+
const plainText = stripHtmlTags(htmlText);
|
|
487
|
+
return plainText;
|
|
330
488
|
} catch (error) {
|
|
331
|
-
|
|
489
|
+
console.error("获取微博详情失败:", error);
|
|
490
|
+
return null;
|
|
332
491
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
492
|
+
}
|
|
493
|
+
__name(getDetailMessage, "getDetailMessage");
|
|
494
|
+
|
|
495
|
+
// src/index.ts
|
|
496
|
+
var name = "weibo-post-monitor";
|
|
497
|
+
function apply(ctx, config) {
|
|
498
|
+
const commonConfig = {
|
|
499
|
+
account: config.account,
|
|
500
|
+
plantform: config.plantform,
|
|
501
|
+
waitMinutes: config.waitMinutes,
|
|
502
|
+
is_using_cookie: config.is_using_cookie
|
|
503
|
+
};
|
|
504
|
+
setCookie(config.manual_cookie);
|
|
505
|
+
setUserAgent(USER_AGENT_LIST[0]);
|
|
506
|
+
ctx.setInterval(async () => {
|
|
507
|
+
for (const singleConfig of config.sendINFO) {
|
|
508
|
+
const params = { ...commonConfig, ...singleConfig };
|
|
509
|
+
getWeiboAndSendMessageToGroup(ctx, params);
|
|
510
|
+
}
|
|
511
|
+
}, config.waitMinutes > 0 ? config.waitMinutes * 60 * 1e3 : 6e4);
|
|
512
|
+
}
|
|
513
|
+
__name(apply, "apply");
|
|
344
514
|
// Annotate the CommonJS export names for ESM import in node:
|
|
345
515
|
0 && (module.exports = {
|
|
346
516
|
Config,
|
|
347
517
|
apply,
|
|
348
|
-
name
|
|
349
|
-
to
|
|
518
|
+
name
|
|
350
519
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const USER_AGENT_LIST: string[];
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function setCookie(cookie: string | null): void;
|
|
2
|
+
export declare function getCookie(): string | null;
|
|
3
|
+
export declare function setUserAgent(userAgent: string | null): void;
|
|
4
|
+
export declare function getUserAgent(): string | null;
|
|
5
|
+
export declare function getRandomUserAgent(): string;
|
|
6
|
+
export declare function fetchCookie(): Promise<string>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getWeibo(config: any, callback?: any, retry?: boolean): Promise<any>;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koishi-plugin-weibo-post-monitor",
|
|
3
3
|
"description": "微博帖子更新推送插件,用于获取指定微博用户的最新帖子推送到指定群聊,参考代码https://github.com/moehuhu/weibo-monitor",
|
|
4
|
-
"version": "0.0
|
|
4
|
+
"version": "1.0.1-beta.0",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "lib/index.d.ts",
|
|
7
7
|
"files": [
|