/*
成分姬插件 - YunzaiBot特供版
核心代码思路来自:NoneBot2 成分姬插件 - https://github.com/noneplugin/nonebot-plugin-ddcheck
改编者:Yujio_Nako
若有bug可以在GitHub提请issue:
https://github.com/ldcivan/ddcheck_plugin
*/
import plugin from '../../lib/plugins/plugin.js'
import { segment } from "oicq";
import fetch from "node-fetch"
import schedule from 'node-schedule'
import fs from 'fs'
import cfg from '../../lib/config/config.js'
import lodash from 'lodash'
import common from '../../lib/common/common.js'
import crypto from "crypto"
import QRCode from "qrcode"
var cookie = "" //理论上SESSDATA即可 现在通过命令设置
var ac_time_value = ""
//在这里填写你的自动刷新列表设置↓↓↓↓↓
let rule =`0 58 23 * * ?` //更新的秒,分,时,日,月,星期几;日月/星期几为互斥条件,必须有一组为*
let auto_refresh = true //是否自动更新列表
let auto_check_cookie = true //是否自动检查cookie
let divisor = 100 //切割发送阈值,0则不切割
let masterId = cfg.masterQQ[0] //管理者QQ账号
let announce_limit = 10; //新增或更新时,数量超过该值则不回报详情
let ping_timeout = 1500; //api的ping值测试超时阈值
//v列表接口地址 https://github.com/dd-center/vtbs.moe/blob/master/api.md =>meta-cdn
var api_cdn = "https://api.vtbs.moe/meta/cdn"
let record_num = 0
let refresh_num = 0
let record = []
let refresh = []
const login_check_url = "https://passport.bilibili.com/x/passport-login/web/cookie/info"; //检测是否需要更新cookie
const refresh_csrf_url = "https://www.bilibili.com/correspond/1/"; //获取csrf
const refresh_cookie_url = "https://passport.bilibili.com/x/passport-login/web/cookie/refresh"; //用csrf生成新cookie
const refresh_confirm_url = "https://passport.bilibili.com/x/passport-login/web/confirm/refresh"; //废弃旧cookie
const generate_qr_url= "https://passport.bilibili.com/x/passport-login/web/qrcode/generate"; //申请二维码
const check_qr_url= "https://passport.bilibili.com/x/passport-login/web/qrcode/poll?qrcode_key="; //检查二维码扫描情况
const attention_url = "https://line3-h5-mobile-api.biligame.com/game/center/h5/user/relationship/following_list?vmid=" //B站用户关注表
const archive_url = "http://api.bilibili.com/x/web-interface/card?mid="; //b站用户基本信息
const medal_url = "https://api.live.bilibili.com/xlive/web-ucenter/user/MedalWall?target_id=" //粉丝牌查询接口
const search_url = `https://api.bilibili.com/x/web-interface/wbi/search/type?search_type=bili_user&keyword=` //昵称转uid
const dirpath = "data/cha_chengfen" //本地V列表文件夹
var filename = `vtuber_list.json` //本地V列表文件名
var cookie_filename = `bilibili_cookies.txt`; //b站cookie
var ac_time_value_filename = `ac_time_value.txt`; //b站ac_time_value
if (!fs.existsSync(dirpath)) {//如果文件夹不存在
fs.mkdirSync(dirpath);//创建文件夹
}
if (!fs.existsSync(dirpath + "/" + filename)) {
fs.writeFileSync(dirpath + "/" + filename, JSON.stringify({
}))
}
if (!fs.existsSync(dirpath + "/" + cookie_filename)) {
fs.writeFileSync(dirpath + "/" + cookie_filename, JSON.stringify({
}))
}
if (!fs.existsSync(dirpath + "/" + ac_time_value_filename)) {
fs.writeFileSync(dirpath + "/" + ac_time_value_filename, JSON.stringify({
}))
}
// 读取文件内容并存储到变量 cookie 中
fs.readFile(dirpath + "/" + cookie_filename, 'utf8', async function(err, data) {
if (err) {
await Bot.pickUser(masterId).sendMsg('【查成分】 Cookie 文件读取错误');
console.error(err);
return;
}
if (data === '') {
await Bot.pickUser(masterId).sendMsg('【查成分】您尚未设置Cookie,请使用 #查成分保存ck 来保存');
console.log('文件为空');
} else {
cookie = data;
await Bot.pickUser(masterId).sendMsg('【查成分】 Cookie已设置');
console.log('读取到的 Cookie:', cookie);
}
});
// 读取文件内容并存储到变量 ac_time_value 中
fs.readFile(dirpath + "/" + ac_time_value_filename, 'utf8', async function(err, data) {
if (err) {
await Bot.pickUser(masterId).sendMsg('【查成分】 ac_time_value 文件读取错误');
console.error(err);
return;
}
if (data === '') {
await Bot.pickUser(masterId).sendMsg('【查成分】 您尚未设置ac_time_value,请使用 #查成分保存ac 来保存');
console.log('文件为空');
} else {
ac_time_value = data;
await Bot.pickUser(masterId).sendMsg('【查成分】 ac_time_value已设置');
console.log('读取到的 ac_time_value:', ac_time_value);
}
});
async function sortUrlsByPing(urls) {
const pingResults = await Promise.all(urls.map(async (url) => {
const pingTime = await ping(url);
return { url, pingTime };
}));
pingResults.sort((a, b) => a.pingTime - b.pingTime);
return pingResults
.filter(result => result.pingTime < Infinity) // Filter out unreachable servers
.map(result => result.url);
}
async function ping(url, timeout = ping_timeout) {
const controller = new AbortController();
const signal = controller.signal;
const fetchPromise = fetch(url, { method: 'HEAD', mode: 'no-cors', signal })
.then(() => Date.now() - start)
.catch(() => Infinity); // If fetch fails, consider it as an infinite ping time
const timeoutPromise = new Promise((_, reject) =>
setTimeout(() => {
controller.abort();
reject(new Error('timeout'));
}, timeout)
);
const start = Date.now();
try {
return await Promise.race([fetchPromise, timeoutPromise]);
} catch (error) {
return Infinity; // Consider timeout as an infinite ping time
}
}
async function check_refresh_cookie() {
async function check_cookie() {
let response = await fetch(login_check_url, { "headers": {"cookie": cookie, "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0", "Referer": "https://www.bilibili.com"}, "method": "GET", });
if (response.status>=400&&response.status<500) {
await Bot.pickUser(masterId).sendMsg("检查Cookie状态失败")
return false;
}
let cookie_status = await response.json();
if(cookie_status.code === 0) {
Bot.pickUser(masterId).sendMsg('Cookie状态正常,无需刷新');
return true;
} else {
Bot.pickUser(masterId).sendMsg('Cookie失效,将重新获取Cookie');
return false;
}
}
async function createCorrespondPath() {
const publicKey = await crypto.subtle.importKey(
"jwk",
{
kty: "RSA",
n: "y4HdjgJHBlbaBN04VERG4qNBIFHP6a3GozCl75AihQloSWCXC5HDNgyinEnhaQ_4-gaMud_GF50elYXLlCToR9se9Z8z433U3KjM-3Yx7ptKkmQNAMggQwAVKgq3zYAoidNEWuxpkY_mAitTSRLnsJW-NCTa0bqBFF6Wm1MxgfE",
e: "AQAB",
},
{ name: "RSA-OAEP", hash: "SHA-256" },
true,
["encrypt"],
)
async function getCorrespondPath(timestamp) {
const data = new TextEncoder().encode(`refresh_${timestamp}`);
const encrypted = new Uint8Array(await crypto.subtle.encrypt({ name: "RSA-OAEP" }, publicKey, data))
return encrypted.reduce((str, c) => str + c.toString(16).padStart(2, "0"), "")
}
const ts = Date.now()
return await getCorrespondPath(ts)
}
async function refresh_cookie(refresh_csrf) {
async function getCookieValue(cookieString, key) {
return cookieString
.split('; ')
.reduce((result, item) => {
const [k, v] = item.split('=');
return k === key ? v : result;
}, '');
}
async function refresh_confirm(csrf, refresh_token) {
const data = {
csrf: csrf,
refresh_token: refresh_token
}
let response = await fetch(refresh_confirm_url, { "headers": {'Content-Type': 'application/x-www-form-urlencoded', "cookie": cookie, "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0", "Referer": "https://www.bilibili.com"}, "method": "POST", "body": data.toString() });
let confirm_result = response.json();
if (confirm_result.code === 0) {
return true;
} else {
Bot.pickUser(masterId).sendMsg(`刷新确认异常,错误码${confirm_result.code},错误报${confirm_result.message},参考错误码解释:\n-101:账号未登录\n-111:csrf 校验失败\n-400:请求错误`);
return false;
}
}
let biliJct = await getCookieValue(cookie, 'bili_jct');
const data = new URLSearchParams({
csrf: biliJct,
refresh_csrf: refresh_csrf,
source: 'main_web',
refresh_token: ac_time_value
});
let response = await fetch(refresh_cookie_url, { "headers": {'Content-Type': 'application/x-www-form-urlencoded', "cookie": cookie, "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0", "Referer": "https://www.bilibili.com"}, "method": "POST", "body": data.toString() });
let refresh_result = response.json();
if (refresh_result.code === 0) {
const last_ac_time_value = ac_time_value;
ac_time_value = refresh_result.data.refresh_token;
async function write_ac_time_value(ac_time_value) {
fs.writeFile(dirpath + "/" + ac_time_value_filename, ac_time_value, 'utf8', async function(err) {
if (err) {
console.error(err);
await e.reply('ac_time_value 保存失败');
return;
}
console.log('ac_time_value 已成功保存到文件:', ac_time_value_filename);
await e.reply('ac_time_value 已保存:' + ac_time_value);
});
}
await write_ac_time_value(ac_time_value);
const setCookieHeaders = response.headers.getAll('set-cookie') || [];
// 解析并提取 SESSDATA 和 bili_jct 的值
cookie = "";
setCookieHeaders.forEach(cookieString => {
// 提取键值对(示例使用正则表达式)
const match = cookieString.match(/^(.*?);/); // 提取键值对部分(忽略其他参数)
if (match) {
const [pair] = match;
const [key, value] = pair.split('=');
cookie += `${key}=${value} `;
}
});
async function write_cookies(cookie) {
fs.writeFile(dirpath + "/" + cookie_filename, cookie, 'utf8', async function(err) {
if (err) {
console.error(err);
await e.reply('Cookie 保存失败');
return;
}
console.log('Cookie 已成功保存到文件:', cookie_filename);
await e.reply('Cookie 已保存:' + cookie);
});
}
await write_cookies(cookie);
biliJct = await getCookieValue(cookie, 'bili_jct');
if(await refresh_confirm(biliJct, last_ac_time_value)) {
Bot.pickUser(masterId).sendMsg("Cookie刷新成功");
return true;
} else {
Bot.pickUser(masterId).sendMsg("Cookie刷新确认失败");
return false;
}
} else {
Bot.pickUser(masterId).sendMsg('Cookie刷新请求失败');
return false;
}
}
if (await check_cookie()) {
return true;
}
const full_refresh_csrf_url = refresh_csrf_url + await createCorrespondPath();
let response = await fetch(full_refresh_csrf_url, { "headers": {"cookie": cookie, "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0", "Referer": "https://www.bilibili.com"}, "method": "GET", });
let refresh_result = await response.text();
const regex = /
(.*?)<\/div>/is; // i 表示不区分大小写,s 表示点匹配换行
const match = htmlString.match(regex);
let refresh_csrf;
if (match) {
refresh_csrf = match[1]; // 提取第一个捕获组的内容
}
await refresh_cookie(refresh_csrf);
return true;
}
let refresh_task = schedule.scheduleJob(rule, async (e) => { //定时更新
if(auto_refresh){
const res = await fetch(api_cdn, { "method": "GET" })
let urls = await res.json();
urls = await sortUrlsByPing(urls);
var local_json = JSON.parse(fs.readFileSync(dirpath + "/" + filename, "utf8"));//读取文件
for(var i = 0;i
=400&&response.status<500) {
await e.reply("检查Cookie状态失败")
return false;
}
let cookie_status = await response.json();
if(cookie_status.code === 0) {
e.reply('Cookie状态正常,无需刷新');
return true;
} else {
e.reply('Cookie失效,请重新扫码登陆');
return false;
}
}
async function createCorrespondPath() {
const publicKey = await crypto.subtle.importKey(
"jwk",
{
kty: "RSA",
n: "y4HdjgJHBlbaBN04VERG4qNBIFHP6a3GozCl75AihQloSWCXC5HDNgyinEnhaQ_4-gaMud_GF50elYXLlCToR9se9Z8z433U3KjM-3Yx7ptKkmQNAMggQwAVKgq3zYAoidNEWuxpkY_mAitTSRLnsJW-NCTa0bqBFF6Wm1MxgfE",
e: "AQAB",
},
{ name: "RSA-OAEP", hash: "SHA-256" },
true,
["encrypt"],
)
async function getCorrespondPath(timestamp) {
const data = new TextEncoder().encode(`refresh_${timestamp}`);
const encrypted = new Uint8Array(await crypto.subtle.encrypt({ name: "RSA-OAEP" }, publicKey, data))
return encrypted.reduce((str, c) => str + c.toString(16).padStart(2, "0"), "")
}
const ts = Date.now()
return await getCorrespondPath(ts)
}
async function refresh_cookie(refresh_csrf) {
async function getCookieValue(cookieString, key) {
return cookieString
.split('; ')
.reduce((result, item) => {
const [k, v] = item.split('=');
return k === key ? v : result;
}, '');
}
async function refresh_confirm(csrf, refresh_token) {
const data = {
csrf: csrf,
refresh_token: refresh_token
}
let response = await fetch(refresh_confirm_url, { "headers": {'Content-Type': 'application/x-www-form-urlencoded', "cookie": cookie, "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0", "Referer": "https://www.bilibili.com"}, "method": "POST", "body": data.toString() });
let confirm_result = response.json();
if (confirm_result.code === 0) {
return true;
} else {
e.reply(`刷新确认异常,错误码${confirm_result.code},错误报${confirm_result.message},参考错误码解释:\n-101:账号未登录\n-111:csrf 校验失败\n-400:请求错误`);
return false;
}
}
let biliJct = await getCookieValue(cookie, 'bili_jct');
const data = new URLSearchParams({
csrf: biliJct,
refresh_csrf: refresh_csrf,
source: 'main_web',
refresh_token: ac_time_value
});
let response = await fetch(refresh_cookie_url, { "headers": {'Content-Type': 'application/x-www-form-urlencoded', "cookie": cookie, "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0", "Referer": "https://www.bilibili.com"}, "method": "POST", "body": data.toString() });
let refresh_result = response.json();
if (refresh_result.code === 0) {
const last_ac_time_value = ac_time_value;
ac_time_value = refresh_result.data.refresh_token;
async function write_ac_time_value(ac_time_value) {
fs.writeFile(dirpath + "/" + ac_time_value_filename, ac_time_value, 'utf8', async function(err) {
if (err) {
console.error(err);
await e.reply('ac_time_value 保存失败');
return;
}
console.log('ac_time_value 已成功保存到文件:', ac_time_value_filename);
await e.reply('ac_time_value 已保存:' + ac_time_value);
});
}
await write_ac_time_value(ac_time_value);
const setCookieHeaders = response.headers.getAll('set-cookie') || [];
// 解析并提取 SESSDATA 和 bili_jct 的值
cookie = "";
setCookieHeaders.forEach(cookieString => {
// 提取键值对(示例使用正则表达式)
const match = cookieString.match(/^(.*?);/); // 提取键值对部分(忽略其他参数)
if (match) {
const [pair] = match;
const [key, value] = pair.split('=');
cookie += `${key}=${value} `;
}
});
async function write_cookies(cookie) {
fs.writeFile(dirpath + "/" + cookie_filename, cookie, 'utf8', async function(err) {
if (err) {
console.error(err);
await e.reply('Cookie 保存失败');
return;
}
console.log('Cookie 已成功保存到文件:', cookie_filename);
await e.reply('Cookie 已保存:' + cookie);
});
}
await write_cookies(cookie);
biliJct = await getCookieValue(cookie, 'bili_jct');
if(await refresh_confirm(biliJct, last_ac_time_value)) {
e.reply("Cookie刷新成功");
return true;
} else {
e.reply("Cookie刷新确认失败");
return false;
}
} else {
e.reply('Cookie刷新请求失败');
return false;
}
}
if (await check_cookie()) {
return true;
}
const full_refresh_csrf_url = refresh_csrf_url + await createCorrespondPath();
let response = await fetch(full_refresh_csrf_url, { "headers": {"cookie": cookie, "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0", "Referer": "https://www.bilibili.com"}, "method": "GET", });
let refresh_result = await response.text();
const regex = /(.*?)<\/div>/is; // i 表示不区分大小写,s 表示点匹配换行
const match = refresh_result.match(regex);
let refresh_csrf;
if (match) {
refresh_csrf = match[1]; // 提取第一个捕获组的内容
}
await refresh_cookie(refresh_csrf);
return true;
}
async scan_login(e) {
if (!e.isMaster) {
await e.reply('查成分只允许主人扫码登陆');
return false;
}
if (e.isGroup) {
await e.reply('查成分只允许主人私聊扫码登陆');
return false;
}
async function generate_qr() {
let response = await fetch(generate_qr_url, { "headers": {"cookie": cookie, "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0", "Referer": "https://www.bilibili.com"}, "method": "GET", });
if (response.status>=400&&response.status<500) {
await e.reply("请求二维码失败")
return false;
}
let generate_result = await response.json();
if(generate_result.code === 0) {
return [generate_result.data.url, generate_result.data.qrcode_key];
} else {
e.reply('请求二维码失败,错误码:'+generate_result.code);
return false;
}
}
async function trans_send_qr(url) {
try {
// 生成二维码到文件
await QRCode.toFile(dirpath + '/qrcode.png', url);
await e.reply("本二维码是作查成分插件获取cookie之用,请勿扫描您不信任的二维码,否则后果自负");
await e.reply(segment.image(dirpath + '/qrcode.png'));
return true;
// 或返回 Base64 字符串
// const base64QR = await QRCode.toDataURL(url);
// return { filePath: './qrcode.png', base64QR };
} catch (err) {
e.reply('从'+url+'生成二维码失败:', err);
return false;
}
}
async function wait_login(qrcode_key) {
let wait_result, response;
function wait(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
while (true) {
response = await fetch(check_qr_url+qrcode_key, { "headers": {"cookie": cookie, "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0", "Referer": "https://www.bilibili.com"}, "method": "GET", });
if (response.status>=400&&response.status<500) {
await e.reply("检查扫码状态失败")
return false;
}
let wait_result = await response.json();
if(wait_result.data.code === 86101 || wait_result.data.code === 86090) {
continue;
} else if (wait_result.data.code === 86038) {
e.reply('查成分扫码登陆二维码已失效,请重新获取');
return false;
} else if(wait_result.data.code === 0) {
e.reply('查成分登陆成功');
ac_time_value = wait_result.data.refresh_token;
async function write_ac_time_value(ac_time_value) {
fs.writeFile(dirpath + "/" + ac_time_value_filename, ac_time_value, 'utf8', async function(err) {
if (err) {
console.error(err);
await e.reply('ac_time_value 保存失败');
return;
}
console.log('ac_time_value 已成功保存到文件:', ac_time_value_filename);
await e.reply('ac_time_value 已保存:' + ac_time_value);
});
}
await write_ac_time_value(ac_time_value);
const setCookieHeaders = response.headers.getAll('set-cookie') || [];
// 解析并提取 SESSDATA 和 bili_jct 的值
cookie = "";
setCookieHeaders.forEach(cookieString => {
// 提取键值对(示例使用正则表达式)
const match = cookieString.match(/^(.*?);/); // 提取键值对部分(忽略其他参数)
if (match) {
const [pair] = match;
const [key, value] = pair.split('=');
cookie += `${key}=${value} `;
}
});
async function write_cookies(cookie) {
fs.writeFile(dirpath + "/" + cookie_filename, cookie, 'utf8', async function(err) {
if (err) {
console.error(err);
await e.reply('Cookie 保存失败');
return;
}
console.log('Cookie 已成功保存到文件:', cookie_filename);
await e.reply('Cookie 已保存:' + cookie);
});
}
await write_cookies(cookie);
return true;
}
await wait(1000);
}
}
let generate_qr_data = await generate_qr();
if(!generate_qr_data) {
return false;
}
let [qr_url, qrcode_key] = generate_qr_data;
if(await trans_send_qr(qr_url)) {
if (await wait_login(qrcode_key)) {
return true;
} else {
return false;
}
} else {
return false;
}
}
async name2uid(name) {
//https://api.bilibili.com/x/web-interface/wbi/search/type?page=1&page_size=36&platform=pc&keyword=%E8%8B%A6%E6%80%95creep-II&search_type=bili_user
try {
var response = await fetch((search_url+name), { "headers": {"cookie": cookie, "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0", "Referer": "https://www.bilibili.com"}, "method": "GET" });
} catch (e) {
this.reply("name2uid请求发生异常:" + e + ",可能是Cookie失效导致")
console.log("name2uid请求发生异常:" + e)
let uid_name = {"mid": 0, "name": name}
return uid_name
}
let search_result = await response.json()
if(search_result['code']==0&&typeof(search_result['data']['result'])!='undefined'){
if(search_result['data']['result'].length != 0){
let uid = search_result['data']['result'][0]['mid']
let name = search_result['data']['result'][0]['uname']
let uid_name = {"mid": parseInt(uid), "name": name}
return uid_name
}
else {
this.reply("无法由昵称转为uid:搜索结果为0")
console.log("昵称转uid解析过程发生异常:搜索结果为0")
let uid_name = {"mid": 0, "name": name}
return uid_name
}
}
else {
this.reply("昵称转uid解析过程发生异常,可能是Cookie失效:"+search_url+name+JSON.stringify(search_result))
console.log("昵称转uid解析过程发生异常")
let uid_name = {"mid": 0, "name": name}
return uid_name
}
}
async get_v_list(e) {
const res = await fetch(api_cdn, { "method": "GET" })
let urls = await res.json();
urls = await this.sortUrlsByPing(urls);
var local_json = JSON.parse(fs.readFileSync(dirpath + "/" + filename, "utf8"));//读取文件
for(var i = 0;i=400&&response.status<500) {
await this.reply("404,可能是uid不存在")
return [0,[]];
}
resJson = await response.json();
// await this.reply(attention_url+`${mid}&pn=${page}`+JSON.stringify(resJson));
if(resJson.code!==0){
await this.reply(`获取目标关注列表失败,可能是查无此人或者风控:${resJson.message}`)
return [0,[]];
} else if (resJson.data.list&&JSON.stringify(resJson.data.list) == '[]') {
break;
} else {
attention_list = [...attention_list, ...resJson.data.list];
page++;
}
}
return [resJson.total,attention_list];
}
async get_archive(mid) {
let resJson;
var response = await fetch(archive_url+mid, { "headers": {"cookie": cookie, "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0", "Referer": "https://www.bilibili.com"}, "method": "GET" });
if (response.status>=400&&response.status<500) {
await this.reply("404,可能是uid不存在")
return false;
}
resJson = await response.json();
if(resJson.code!==0){
await this.reply(`获取目标基本信息失败,可能是查无此人:${resJson.message}`)
return false;
} else {
return resJson;
}
}
async get_medal_list(mid) {
var response = await fetch(medal_url+mid, { "headers": {"cookie": cookie, "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0", "Referer": "https://www.bilibili.com"}, "method": "GET" });
if (response.status==404) {
await this.reply("404,可能是uid不存在")
return false
}
var medal_list_raw = await response.json()
var medal_list = {};
if(medal_list_raw.code!==0){
await this.reply(`获取粉丝牌数据错误:${JSON.stringify(medal_list_raw.message)},一般是cookie中的SESSDATA过期导致`)
return medal_list
}
for(var i = 0;i Date.now() - start)
.catch(() => Infinity); // If fetch fails, consider it as an infinite ping time
const timeoutPromise = new Promise((_, reject) =>
setTimeout(() => {
controller.abort();
reject(new Error('timeout'));
}, timeout)
);
const start = Date.now();
try {
return await Promise.race([fetchPromise, timeoutPromise]);
} catch (error) {
return Infinity; // Consider timeout as an infinite ping time
}
}
async sortUrlsByPing(urls) {
const pingResults = await Promise.all(urls.map(async (url) => {
const pingTime = await this.ping(url);
return { url, pingTime };
}));
pingResults.sort((a, b) => a.pingTime - b.pingTime);
return pingResults
.filter(result => result.pingTime < Infinity) // Filter out unreachable servers
.map(result => result.url);
}
async makeForwardMsg (title, base_info, msg) {
let nickname = Bot.nickname
if (this.e.isGroup) {
let info = await Bot.pickMember(this.e.group_id, Bot.uin)
nickname = info.nickname || info.card
}
let userInfo = {
user_id: Bot.uin,
nickname
}
let forwardMsg = [
{
...userInfo,
message: title
},
{
...userInfo,
message: base_info
},
{
...userInfo,
message: msg
}
]
/** 制作转发内容 */
if (this.e.isGroup) {
forwardMsg = await this.e.group.makeForwardMsg(forwardMsg)
} else {
forwardMsg = await this.e.friend.makeForwardMsg(forwardMsg)
}
/** 处理描述 */
forwardMsg.data = JSON.stringify(forwardMsg.data)
forwardMsg.data = forwardMsg.data
.replace(/\n/g, '')
.replace(/(.+?)<\/title>/g, '___')
.replace(/___+/, `${title}`)
forwardMsg.data = JSON.parse(forwardMsg.data)
return forwardMsg
}
async chengfen_help(e){
await this.reply("查成分帮助\n1.发送 #更新v列表 更新主播列表到本地,建议每周至少更新一次\n2.使用 #查成分 目标uid或者昵称全称 获取目标的成分,包括关注的V/游戏官号以及对应的粉丝牌\n3.使用 #查成分登录 来通过哔哩哔哩APP扫描获取cookie;若不能扫描或扫码登陆失败,可使用 #查成分记录ck 保存b站Cookie,并使用 #查成分记录ac 保存b站ac_time_value;要查看你的设置,使用 #查成分查看ck 查看保存的ck,使用 #查成分查看ac 查看保存的ac_time_value,你也可以通过 #查成分检查ck 检查cookie有效性")
}
}