bilibiliHelper.js 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124
  1. /*
  2. 哔哩哔哩每日任务(V1.1)
  3. 更新时间: 2024-04-06
  4. 脚本兼容: QuantumultX, Surge, Loon
  5. 脚本作者: MartinsKing(@ClydeTime)
  6. 软件功能: 登录/观看/分享/投币/直播签到/银瓜子转硬币/大会员积分签到/年度大会员每月B币券+等任务
  7. 注意事项:
  8. 抓取cookie时注意保证账号登录状态;
  9. 账号内须有一定数量的关注数,否则无法完成投币;
  10. 当硬币不足5枚,提示硬币不足,停止投币;
  11. 为保证投币任务成功, 脚本有重试机制(最多重试10次), 以确保任务完成, 前提需要您尽可能多的关注Up主;
  12. 年度大会员每月B币券会在每月1号、15号尝试领取,确保应用正常运行, 以防漏领;
  13. 年度大会员自动充电会在每次领劵之后进行, 默认为自己充电, B币多的用户可自行到boxjs设置,以防误充.
  14. 使用声明: ⚠️此脚本仅供学习与交流,请勿贩卖!⚠️
  15. 脚本参考: Nobyda、Wyatt1026、ABreadTree、chavyleung、SocialSisterYi
  16. ************************
  17. QX, Surge, Loon说明:
  18. ************************
  19. 1.获取cookie
  20. ①后台退出手机B站客户端的情况下, 重新打开APP进入主页
  21. ②通过网址「https://www.bilibili.com」登录,登录后当前网页登录状态失效
  22. 如通知成功获取cookie, 则可以使用此签到脚本.
  23. 脚本将在每天上午7点30执行.
  24. 2.投币设置
  25. 定时任务脚本投币规则为: 随机获取关注列表Up主视频, 默认5视频5硬币, 不点赞.
  26. 用户如需要不投币的版本, 请使用boxjs订阅「https://raw.githubusercontent.com/ClydeTime/BiliBili/main/boxjs/BiliBili.boxjs.json」
  27. 将投币次数置为0, 并保存即可.
  28. /***********************
  29. Surge 脚本配置:
  30. ************************
  31. # B站每日等级任务 「请在模块中添加」
  32. https://raw.githubusercontent.com/ClydeTime/BiliBili/main/modules/BiliBiliDailyBonus.sgmodule
  33. ************************
  34. Loon 远程脚本配置:
  35. ************************
  36. # B站每日等级任务 「请在插件中添加」
  37. https://raw.githubusercontent.com/ClydeTime/BiliBili/main/modules/BiliBiliDailyBonus.plugin
  38. ************************
  39. QuantumultX 远程脚本配置:
  40. ************************
  41. [rewrite local]
  42. # > 哔哩哔哩cookie
  43. ^https?:\/\/app\.bilibili\.com\/x\/resource\/fingerprint\? url script-request-header https://git.jojo21.top/shawenguan/Quantumult-X/raw/master/Scripts/bilibili/bilibiliHelper.js
  44. ^https?:\/\/m.bilibili.com/$ url script-request-header https://git.jojo21.top/shawenguan/Quantumult-X/raw/master/Scripts/bilibili/bilibiliHelper.js
  45. [MITM]
  46. hostname = m.bilibili.com,app.bilibili.com
  47. */
  48. const format = (ts, fmt = 'yyyy-MM-dd HH:mm:ss') => {
  49. return $.time(fmt, ts);
  50. }
  51. const check = key =>
  52. !config.hasOwnProperty(key) ||
  53. !config[key].hasOwnProperty("time") ||
  54. !(config[key]["num"] > 0) ||
  55. format(new Date().toDateString()) > config[key].time
  56. const string2object = cookie => {
  57. let obj = {}
  58. let arr = cookie.split("; ")
  59. arr.forEach(function (val) {
  60. let array = val.split("=")
  61. obj[array[0]] = array[1]
  62. })
  63. return obj
  64. }
  65. const isFlag = exec_times =>
  66. config.user.num === 0 ||
  67. config.watch.num === 0 ||
  68. config.share.num === 0 ||
  69. (config.coins.num < exec_times * 10 && Math.floor(config.user.money) > 5)
  70. const persistentStore = async config => {
  71. if (config.cookie.DedeUserID) {
  72. const url = $request.url
  73. config.key = url.match(/.*access_key=(.*?)&build/)?.[1]
  74. config.cookieStr = `DedeUserID=${config.cookie.DedeUserID}; DedeUserID__ckMd5=${config.cookie.DedeUserID__ckMd5}; SESSDATA=${config.cookie.SESSDATA}; bili_jct=${config.cookie.bili_jct}; sid=${config.cookie.sid}`
  75. if (!config.key) { //网页方式登录
  76. let auth_code = "0", access_key = "0", login_confirm = false
  77. auth_code = await getAuthCode()
  78. if (auth_code !== "0") login_confirm = await loginConfirm(auth_code)
  79. if (login_confirm) access_key = await getAccessKey(auth_code)
  80. if (access_key !== "0") {
  81. config.key = access_key
  82. } else {
  83. $.log("- 获取用户access_key失败!")
  84. $.msg($.name, "🤒获取用户access_key失败!")
  85. }
  86. }
  87. const isFirstInsert = config.FirstInsert
  88. delete config.FirstInsert
  89. $.log($.toStr(config))
  90. const successMessage = $.setItem($.name + "_daily_bonus", $.toStr(config))
  91. ? "🎉cookie存储成功"
  92. : "🤒cookie存储失败"
  93. $.msg($.name, isFirstInsert ? "首次获取cookie" : "检测到cookie已更新", successMessage)
  94. } else {
  95. $.msg($.name, "- 尚未登录, 请登录后重新获取cookie")
  96. }
  97. }
  98. const $ = new Env("bilibili")
  99. const startTime = format()
  100. let cards = []
  101. let config = {
  102. cookie: {},
  103. cookieStr: "",
  104. key: "",
  105. user: {},
  106. watch: {},
  107. share: {},
  108. coins: {},
  109. score: {}
  110. }
  111. let real_times //实际需要投币次数
  112. !(async () => {
  113. if (typeof $request != "undefined") {
  114. $.log("- 正在获取cookie, 请稍后")
  115. await getCookie()
  116. } else {
  117. await signBiliBili()
  118. }
  119. })()
  120. .catch((e) => $.logErr(e))
  121. .finally(() => $.done())
  122. async function getCookie() {
  123. if ("object" === typeof $request) {
  124. let Cookie = $request.headers.cookie || $request.headers.Cookie
  125. if (Cookie) {
  126. config.cookie = string2object(Cookie)
  127. const PStoreConfig = $.getItem($.name + "_daily_bonus", {})
  128. if (PStoreConfig.cookie && PStoreConfig.cookie.bili_jct !== config.cookie.bili_jct) {
  129. if (PStoreConfig.Settings) config.Settings = PStoreConfig.Settings // 同步boxjs数据
  130. config.FirstInsert = false
  131. $.log($.toStr(config))
  132. await persistentStore(config)
  133. } else if (PStoreConfig.cookie) {
  134. $.log("- cookie未失效,无需更新")
  135. } else {
  136. config.FirstInsert = true
  137. await persistentStore(config)
  138. }
  139. } else {
  140. $.msg($.name, "- 尚未登录, 请登录后重新获取cookie")
  141. }
  142. }
  143. }
  144. async function signBiliBili() {
  145. config = $.getItem($.name + "_daily_bonus", {})
  146. if (config.cookie && await me()) {
  147. await queryStatus()
  148. let exec_times = config.Settings?.exec //用户设置投币次数
  149. if (!Boolean(exec_times)) {
  150. exec_times = 5
  151. real_times = 5 - (Number(config.coins.num) / 10)
  152. } else {
  153. exec_times = Number(exec_times)
  154. real_times = Math.max(0, exec_times - (Number(config.coins.num) / 10))
  155. }
  156. let flag = isFlag(exec_times)
  157. if (flag){
  158. await dynamic()
  159. if (cards.length) {
  160. let item = cards[Math.floor(Math.random() * cards.length)]
  161. let card = $.toObj(item.card)
  162. short_link = encodeURIComponent(card?.short_link_v2.replace(/\\\//g, '/'))
  163. await watch(item.desc.rid, item.desc.bvid, card.cid)
  164. await share(item.desc.rid, card.cid, short_link)
  165. } else {
  166. $.log("- 获取视频失败,请重试或寻求帮助")
  167. }
  168. $.log("3️⃣ 投币任务")
  169. if (typeof config.coins.failures !== 'undefined' && config.coins.failures > 0){
  170. config.coins.failures = 0 //重置投币失败次数
  171. }
  172. if (real_times === 0){
  173. $.log(`- 今日已完成 ${config.coins.time}`)
  174. } else {
  175. for (let i = 0; i < real_times; i ++) {
  176. if (Math.floor(config.user.money) <= 5) {
  177. $.log("- 硬币不足,投币失败")
  178. break
  179. } else {
  180. await coin()
  181. $.wait(300) //减少频繁请求概率
  182. }
  183. }
  184. }
  185. $.log("---- 将尝试额外任务")
  186. } else {
  187. $.log("---- 经验值任务均已完成,将尝试额外任务")
  188. }
  189. await liveSign()
  190. await silver2coin()
  191. await vipScoreSign()
  192. if (config.user.vipStatus === 1) {
  193. await vipExtraEx()
  194. await vipScoreGo()
  195. await vipScoreFan()
  196. await vipScoreMovie()
  197. await vipScoreDress()
  198. await vipWatchAccept()
  199. //B币券每月尝试两次领取
  200. let day = $.time('dd')
  201. if (day === '1' || day === '15') {
  202. if (config.user.vipType === 2) {
  203. await vipPrivilege(1)
  204. $.wait(800) //延迟执行,防止领劵延迟
  205. let charge_mid = config.Settings?.charge_mid || config.user.mid //用户设置充电id
  206. let bp_num = config.Settings?.bp_num || 5 //用户设置充电数量
  207. await Charge(charge_mid, bp_num)//充电
  208. for (let i = 2; i <= 7; i++) await vipPrivilege(i)
  209. } else if (config.user.vipType === 1) {
  210. await vipPrivilege(6)
  211. await vipPrivilege(7)
  212. }
  213. }
  214. }
  215. flag = !isFlag(exec_times)
  216. let title = `${$.name} 登录${config.user.num}/观看${config.watch.num}/分享${config.share.num}/投币${config.coins.num / 10}${flag ? "已完成" : "未完成"}`
  217. $.log(`#### ${title}`)
  218. $.log(`- 登录时间: ${config.user.time || "暂无"}`)
  219. $.log(`- 观看时间: ${config.watch.time || "暂无"}`)
  220. $.log(`- 分享时间: ${config.share.time || "暂无"}`)
  221. $.log(`- 投币时间: ${config.coins.time || "暂无"}`)
  222. notice = {
  223. title: `${$.name} [${config.user.uname}]`,
  224. subTitle: `${flag ? "✅任务完成" : "❗️有未完成的任务"}`,
  225. content:
  226. `任务:登录(观看)${check("watch") ? "" : "+10exp"} 分享${check("share") ? "" : "+5exp"} 投币${check("coins") ? "" : "+50exp"}\n` +
  227. `经验:当前${config.user.level_info.current_exp}/下级${config.user.level_info.next_exp}/满级28800\n` +
  228. `等级:当前${config.user.level_info.current_level}级 升满级最快需${Math.ceil((config.user.v6_exp)/65)}天`,
  229. }
  230. $.msg(notice.title, notice.subTitle, notice.content)
  231. } else {
  232. $.msg(`${$.name} 任务失败`,`📅 ${startTime}`, "🤒请更新cookie")
  233. }
  234. }
  235. async function getAuthCode() {
  236. const body = {
  237. appkey: "27eb53fc9058f8c3",
  238. local_id: 0,
  239. ts: $.getTimestamp()
  240. }
  241. const sortedBody = $.queryStr(Object.fromEntries(new Map(Array.from(Object.entries(body)).sort())))
  242. const sign = md5(sortedBody + 'c2ed53a74eeefe3cf99fbd01d8c9c375')
  243. body['sign'] = sign
  244. const myRequest = {
  245. url: "https://passport.bilibili.com/x/passport-tv-login/qrcode/auth_code",
  246. headers: {
  247. "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
  248. },
  249. body: $.queryStr(body)
  250. }
  251. return await $.fetch(myRequest).then(response => {
  252. try {
  253. const body = $.toObj(response.body)
  254. if (body.code === 0 && body.message === "0") {
  255. $.log("- 获取auth_code成功")
  256. return body.data.auth_code
  257. } else {
  258. $.log("- 获取auth_code失败")
  259. return "0"
  260. }
  261. } catch (e) {
  262. $.logErr(e, response)
  263. }
  264. })
  265. }
  266. async function loginConfirm(auth_code) {
  267. const body = {
  268. auth_code,
  269. build: 7082000,
  270. csrf: config.cookie.bili_jct
  271. }
  272. const myRequest = {
  273. url: "https://passport.bilibili.com/x/passport-tv-login/h5/qrcode/confirm",
  274. headers: {
  275. "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
  276. 'cookie': `DedeUserID=${config.cookie.DedeUserID}; SESSDATA=${config.cookie.SESSDATA}`
  277. },
  278. body: $.queryStr(body)
  279. }
  280. return await $.fetch(myRequest).then(response => {
  281. try {
  282. const body = $.toObj(response.body)
  283. if (body.code === 0 && body.message === "0") {
  284. $.log("- 确认登录成功")
  285. return true
  286. } else {
  287. $.log("- 确认登录失败")
  288. return false
  289. }
  290. } catch (e) {
  291. $.logErr(e, response)
  292. }
  293. })
  294. }
  295. async function getAccessKey(auth_code) {
  296. const body = {
  297. appkey: "27eb53fc9058f8c3",
  298. auth_code,
  299. local_id: 0,
  300. ts: $.getTimestamp()
  301. }
  302. const sortedBody = $.queryStr(Object.fromEntries(new Map(Array.from(Object.entries(body)).sort())))
  303. const sign = md5(sortedBody + 'c2ed53a74eeefe3cf99fbd01d8c9c375')
  304. body['sign'] = sign
  305. const myRequest = {
  306. url: "https://passport.bilibili.com/x/passport-tv-login/qrcode/poll",
  307. headers: {
  308. "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
  309. },
  310. body: $.queryStr(body)
  311. }
  312. return await $.fetch(myRequest).then(response => {
  313. try {
  314. const body = $.toObj(response.body)
  315. if (body.code === 0 && body.message === "0") {
  316. $.log("- 获取access_key成功")
  317. return body.data.access_token
  318. } else {
  319. $.log("- 获取access_key失败")
  320. return "0"
  321. }
  322. } catch (e) {
  323. $.logErr(e, response)
  324. }
  325. })
  326. }
  327. async function watch(aid, bvid, cid) {
  328. $.log("1️⃣ 观看(登录)任务")
  329. if (check("watch")) {
  330. $.log(`- 正在观看(登录)(${bvid})`)
  331. const body = {
  332. aid,
  333. cid,
  334. bvid,
  335. mid: config.user.mid,
  336. csrf: config.cookie.bili_jct,
  337. played_time : 1,
  338. real_played_time: 1,
  339. realtime: 1,
  340. start_ts: $.getTimestamp(),
  341. type: 3,
  342. dt: 2,
  343. play_type: 0,
  344. from_spmid: 0,
  345. spmid: 0,
  346. auto_continued_play: 0,
  347. refer_url: "https%3A%2F%2Ft.bilibili.com%2F",
  348. bsource: ""
  349. }
  350. const myRequest = {
  351. url: 'https://api.bilibili.com/x/click-interface/web/heartbeat',
  352. headers: {
  353. "cookie": config.cookieStr,
  354. "referrer": `https://www.bilibili.com/video/${bvid}`
  355. },
  356. body: $.queryStr(body)
  357. }
  358. await $.fetch(myRequest).then(response => {
  359. const body = $.toObj(response.body)
  360. if (body?.code === 0) {
  361. $.log(`- 累计观看(登录)次数 ${(config.watch.num || 0) + 1}`)
  362. config.user.num = (config.user.num || 0) + 1
  363. config.watch.num = (config.watch.num || 0) + 1
  364. $.setItem($.name + "_daily_bonus", $.toStr(config))
  365. } else {
  366. $.log("- 观看失败, 失败原因: " + body?.message)
  367. }
  368. })
  369. } else {
  370. $.log(`- 今日已经观看 ${config.watch.time}`)
  371. }
  372. }
  373. async function share(aid, cid, short_link) {
  374. $.log("2️⃣ 分享任务")
  375. if (check("share")) {
  376. $.log("- 正在分享, aid=" + aid)
  377. const body = {
  378. access_key: config.key.replace(/&actionKey=.*?&appkey=.*$/, ''),
  379. actionKey: 'appkey',
  380. appkey: '27eb53fc9058f8c3',
  381. build: '72700100',
  382. c_locale: 'zh-Hans_CN',
  383. device: 'phone',
  384. disable_rcmd: 0,
  385. link: short_link,
  386. mobi_app: 'iphone',
  387. object_extra_fields: '%7B%7D',
  388. oid: aid,
  389. panel_type: 1,
  390. platform: 'ios',
  391. s_locale:'zh-Hans_CN',
  392. share_channel: 'WEIXIN',
  393. share_id: 'main.ugc-video-detail.0.0.pv',
  394. share_origin: 'vinfo_share',
  395. sid: cid,
  396. spm_id: 'main.ugc-video-detail.0.0',
  397. statistics: '%7B%22appId%22%3A1%2C%22version%22%3A%227.27.0%22%2C%22abtest%22%3A%22%22%2C%22platform%22%3A1%7D',
  398. success: 1,
  399. ts: $.getTimestamp()
  400. }
  401. const sign = md5($.queryStr(body) + 'c2ed53a74eeefe3cf99fbd01d8c9c375')
  402. body['sign'] = sign
  403. const myRequest = {
  404. url: 'https://api.bilibili.com/x/share/finish',
  405. headers: {},
  406. body: $.queryStr(Object.fromEntries(new Map(Array.from(Object.entries(body)).sort())))
  407. }
  408. await $.fetch(myRequest).then(response => {
  409. const body = $.toObj(response.body)
  410. if (body?.code === 0) {
  411. config.share.num = (config.share.num || 0) + 1
  412. $.log("- 分享成功")
  413. $.setItem($.name + "_daily_bonus", $.toStr(config))
  414. } else {
  415. $.log("- 分享失败, 失败原因: " + body?.message)
  416. }
  417. })
  418. } else {
  419. $.log(`- 今日已经分享 ${config.share.time}`)
  420. }
  421. }
  422. async function coin() {
  423. if (config.coins.num >= 50) {
  424. $.log(`- 今日已完成 ${config.coins.time}`)
  425. return
  426. }
  427. let like_uid_list = await getFavUid()
  428. if (like_uid_list && like_uid_list.length > 0) {
  429. let aid = await getFavAid(like_uid_list)
  430. //$.log("即将投币的视频aid: " + aid)
  431. if (aid !== 0) {
  432. const body = {
  433. aid,
  434. multiply: 1,
  435. select_like: 0,
  436. cross_domain: true,
  437. csrf: config.cookie.bili_jct
  438. }
  439. const myRequest = {
  440. url: "https://api.bilibili.com/x/web-interface/coin/add",
  441. headers: {
  442. 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36',
  443. 'accept': 'application/json, text/plain, */*',
  444. 'content-type': 'application/x-www-form-urlencoded',
  445. 'origin': 'https://www.bilibili.com',
  446. 'referer': 'https://www.bilibili.com/video/BV1MT411G7fG?vd_source=1970993e2eff4af7be029aefcfa468b8',
  447. 'cookie': config.cookieStr + ';buvid3=fuckchenruilovelaoliu'
  448. },
  449. body: $.queryStr(body)
  450. }
  451. await $.fetch(myRequest).then(async response => {
  452. try {
  453. const body = $.toObj(response.body)
  454. if (body?.code === 0 && body?.message === "0") {
  455. $.log("- 投币成功")
  456. config.user.money -= 1
  457. config.coins.num += 10
  458. $.setItem($.name + "_daily_bonus", $.toStr(config))
  459. } else {
  460. $.log("- 投币失败,失败原因 " + body.message)
  461. config.coins.failures = (config.coins.failures === 0 || typeof config.coins.failures === 'undefined' ? 1 : config.coins.failures + 1)
  462. $.setItem($.name + "_daily_bonus", $.toStr(config))
  463. if (config.coins.failures < 11) {
  464. $.log("- 正在重试...重试次数 " + (config.coins.failures - 1) + "(超过十次不再重试)")
  465. await coin()
  466. }
  467. }
  468. } catch (e) {
  469. $.logErr(e, response)
  470. }
  471. })
  472. } else {
  473. $.log("获取随机投币视频失败")
  474. }
  475. } else {
  476. $.log("获取随机关注用户列表失败")
  477. }
  478. }
  479. async function getFavUid() {
  480. const myRequest = {
  481. url: `https://api.bilibili.com/x/relation/followings?vmid=${config.cookie.DedeUserID}&ps=10&order_type=attention`,
  482. headers: {
  483. 'cookie': config.cookieStr
  484. }
  485. }
  486. return await $.fetch(myRequest).then(response => {
  487. try {
  488. const body = $.toObj(response.body)
  489. let like_uid_list = new Array()
  490. if (body?.code === 0) {
  491. $.log("- 获取关注列表成功")
  492. let like_list = body?.data?.list
  493. //let $.name_list = new Array()
  494. for (let i = 0; i < like_list.length; i ++) {
  495. //$.name_list[i] = like_list[i].u$.name
  496. like_uid_list[i] = like_list[i].mid
  497. }
  498. return like_uid_list
  499. //$.log($.toStr($.name_list))
  500. } else {
  501. $.log("- 获取关注列表成失败")
  502. $.log("- 失败原因 " + body?.message)
  503. return like_uid_list
  504. }
  505. } catch (e) {
  506. $.logErr(e, response)
  507. }
  508. })
  509. }
  510. async function getFavAid(arr) {
  511. //$.log("- 获取关注列表中的随机视频")
  512. let random_int = Math.floor((Math.random()*arr.length))
  513. let random_mid = arr[random_int]
  514. let wbiSigns = getWbiSigns({mid: random_mid})
  515. const myRequest = {
  516. url: `https://api.bilibili.com/x/space/wbi/arc/search?${wbiSigns}`,
  517. headers: {
  518. 'cookie': config.cookieStr
  519. }
  520. }
  521. return await $.fetch(myRequest).then(response => {
  522. try {
  523. const body = $.toObj(response.body)
  524. if (body?.code === 0) {
  525. $.log("- 获取投币视频成功")
  526. let vlist = body.data?.list?.vlist
  527. let random_v_int = Math.floor((Math.random() * vlist.length))
  528. let aid = vlist[random_v_int]?.aid
  529. $.log("- 作者: " + vlist[random_v_int]['author'] + "; 视频标题: " + vlist[random_v_int]['title'])
  530. return aid
  531. } else {
  532. $.log("- 获取投币视频失败")
  533. $.log("- 失败原因 " + body?.message)
  534. return 0
  535. }
  536. } catch (e) {
  537. $.logErr(e, response)
  538. }
  539. }, reason => {
  540. $.log("- 获取投币视频失败")
  541. $.log("- 失败原因 " + $.toStr(reason))
  542. return 0
  543. })
  544. }
  545. async function silver2coin() {
  546. $.log("#### 银瓜子兑换硬币任务")
  547. const body = {
  548. csrf: config.cookie.bili_jct,
  549. csrf_token: config.cookie.bili_jct
  550. }
  551. const myRequest = {
  552. url: "https://api.live.bilibili.com/xlive/revenue/v1/wallet/silver2coin",
  553. headers: {
  554. 'cookie': config.cookieStr
  555. },
  556. body: $.queryStr(body)
  557. }
  558. await $.fetch(myRequest).then(response => {
  559. try {
  560. let result = $.toObj(response.body)
  561. let title = `${$.name} 银瓜子转硬币`
  562. // 兑换成功
  563. if (result && result.code === 0) {
  564. let subTitle = `- ${result.message}`
  565. let detail = `- 成功兑换: ${result.data.coin} 个硬币\n当前银瓜子: ${result.data.silver} , 当前金瓜子: ${result.data.gold}`
  566. $.log(subTitle)
  567. $.log(detail)
  568. $.msg(title, subTitle, detail)
  569. }
  570. // 兑换中止(重复兑换&银瓜子不足)
  571. else if (result && result.code === 403) {
  572. let subTitle = "- 未成功兑换"
  573. let detail = `- 原因: ${result.message}`
  574. $.log(subTitle)
  575. $.log(detail)
  576. $.msg(title, subTitle, detail)
  577. }
  578. // 兑换失败
  579. else {
  580. let subTitle = "- 兑换失败"
  581. let detail = `- 原因: ${result.message}`
  582. $.log(subTitle)
  583. $.log(detail)
  584. $.msg(title, subTitle, detail)
  585. }
  586. } catch (e) {
  587. $.logErr(e, response)
  588. }
  589. })
  590. }
  591. async function liveSign() {
  592. $.log("#### 直播签到任务")
  593. const myRequest = {
  594. url: "https://api.live.bilibili.com/xlive/web-ucenter/v1/sign/DoSign",
  595. headers: {
  596. 'cookie': config.cookieStr
  597. }
  598. }
  599. await $.fetch(myRequest).then(response => {
  600. try {
  601. let body = $.toObj(response.body)
  602. if (body?.code === 0) {
  603. $.log("- 签到成功")
  604. $.log(`签到奖励:${body.data.text},连续签到${body.data.hadSignDays}天`)
  605. } else if (body && body.code === 1011040){
  606. $.log("- 今日已完成")
  607. } else {
  608. $.log("- 签到失败")
  609. $.log("- 失败原因 " + body?.message)
  610. }
  611. } catch (e) {
  612. $.logErr(e, response)
  613. }
  614. })
  615. }
  616. async function vipScoreSign() {
  617. $.log("#### 大会员大积分签到任务")
  618. if (config.user.vipStatus === 0) {
  619. $.log("- 当前用户非大会员, 无法完成任务")
  620. } else {
  621. if (check("score")) {
  622. const myRequest = {
  623. url: "https://api.bilibili.com/pgc/activity/score/task/sign",
  624. method: "POST",
  625. headers: {
  626. 'Referer': 'https://big.bilibili.com/mobile/bigPoint/task',
  627. 'cookie': config.cookieStr
  628. }
  629. }
  630. await $.fetch(myRequest).then(response => {
  631. try {
  632. const body = $.toObj(response.body)
  633. if (body?.code === 0 && body?.message === "success") {
  634. $.log("- 签到成功")
  635. config.score.time = startTime
  636. config.score.num = 1
  637. $.setItem($.name + "_daily_bonus", $.toStr(config))
  638. } else {
  639. $.log("- 签到失败")
  640. $.log("- 失败原因 " + body?.message)
  641. }
  642. } catch (e) {
  643. $.logErr(e, response)
  644. }
  645. })
  646. } else {
  647. $.log("- 今日已完成")
  648. }
  649. }
  650. }
  651. async function vipExtraEx() {
  652. $.log("#### 大会员每日额外经验值")
  653. const body = {
  654. csrf: config.cookie.bili_jct,
  655. ts: $.getTimestamp(),
  656. buvid: config.cookie.Buvid,
  657. mobi_app: 'iphone',
  658. platform: 'ios',
  659. appkey: '27eb53fc9058f8c3',
  660. access_key: config.key
  661. }
  662. const sortedBody = $.queryStr(Object.fromEntries(new Map(Array.from(Object.entries(body)).sort())))
  663. const sign = md5(sortedBody + 'c2ed53a74eeefe3cf99fbd01d8c9c375')
  664. body['sign'] = sign
  665. const myRequest = {
  666. url: "https://api.bilibili.com/x/vip/experience/add",
  667. headers: {
  668. 'accept': 'application/json, text/plain, */*',
  669. 'app-key': 'iphone'
  670. },
  671. body: $.queryStr(body)
  672. }
  673. await $.fetch(myRequest).then(response => {
  674. try {
  675. const body = $.toObj(response.body)
  676. if (body?.code === 0 && body?.message === "0") {
  677. $.log("- 成功获得10经验值")
  678. } else {
  679. $.log("- 每日额外经验任务失败")
  680. $.log("- 失败原因 " + body?.message)
  681. }
  682. } catch (e) {
  683. $.logErr(e, response)
  684. }
  685. })
  686. }
  687. async function vipScoreGo() {
  688. $.log("#### 大会员浏览会员购10s任务")
  689. const myRequest = {
  690. url: "https://show.bilibili.com/api/activity/fire/common/event/dispatch",
  691. headers: {
  692. 'Content-Type' : 'application/json',
  693. 'Cookie': config.cookieStr
  694. },
  695. body: `{"eventId":"hevent_oy4b7h3epeb"}`
  696. }
  697. await $.fetch(myRequest).then(response => {
  698. try {
  699. const body = $.toObj(response.body)
  700. if (body?.code === 0 && body?.message === "SUCCESS") {
  701. $.log("- 成功获得10点大积分")
  702. } else {
  703. $.log("- 浏览会员购任务失败")
  704. $.log("- 失败原因 " + body?.message)
  705. }
  706. } catch (e) {
  707. $.logErr(e, response)
  708. }
  709. })
  710. }
  711. async function vipScoreFan() {
  712. $.log("#### 大会员浏览追番频道10s任务")
  713. const myRequest = {
  714. url: `https://api.bilibili.com/pgc/activity/deliver/task/complete?access_key=${config.key}&position=jp_channel&sign=768d600feba34e6d1109e4157c0f0c5f&task_sign=557D1ACE13E9E81393259FFB621D6D0E`,
  715. method: "POST",
  716. headers: {}
  717. }
  718. await $.fetch(myRequest).then(response => {
  719. try {
  720. const body = $.toObj(response.body)
  721. if (body?.code === 0 && body?.message === "success") {
  722. $.log("- 成功获得10点大积分")
  723. } else {
  724. $.log("- 浏览追番频道任务失败")
  725. $.log("- 失败原因 " + body?.message)
  726. }
  727. } catch (e) {
  728. $.logErr(e, response)
  729. }
  730. })
  731. }
  732. async function vipScoreMovie() {
  733. $.log("#### 大会员浏览影视频道10s任务")
  734. const myRequest = {
  735. url: `https://api.bilibili.com/pgc/activity/deliver/task/complete?access_key=${config.key}&position=tv_channel&sign=09ece1c295cb86d74778b93c59c0da3a&task_sign=B7DA5FAE25C39F53C62C03076CF2878B`,
  736. method: "POST",
  737. headers: {}
  738. }
  739. await $.fetch(myRequest).then(response => {
  740. try {
  741. const body = $.toObj(response.body)
  742. if (body?.code === 0 && body?.message === "success") {
  743. $.log("- 成功获得10点大积分")
  744. } else {
  745. $.log("- 浏览影视频道任务失败")
  746. $.log("- 失败原因 " + body?.message)
  747. }
  748. } catch (e) {
  749. $.logErr(e, response)
  750. }
  751. })
  752. }
  753. async function vipScoreDress() {
  754. $.log("#### 大会员浏览装扮商城主页任务")
  755. const body = {
  756. csrf: config.cookie.bili_jct,
  757. ts: $.getTimestamp(),
  758. taskCode: 'dress-view',
  759. access_key: config.key
  760. }
  761. const myRequest = {
  762. url: 'https://api.bilibili.com/pgc/activity/score/task/complete/v2',
  763. headers: {},
  764. body: $.queryStr(body)
  765. }
  766. await $.fetch(myRequest).then(response => {
  767. try {
  768. const body = $.toObj(response.body)
  769. if (body?.code === 0 && body?.message === "success") {
  770. $.log("- 成功获得10点大积分")
  771. } else {
  772. $.log("- 浏览装扮商城主页任务失败")
  773. }
  774. } catch (e) {
  775. $.logErr(e, response)
  776. }
  777. })
  778. }
  779. async function vipWatchAccept() {
  780. $.log("#### 接取大会员观看剧集10min任务")
  781. const body = {
  782. csrf: config.cookie.bili_jct,
  783. ts: $.getTimestamp(),
  784. taskCode: 'ogvwatchnew',
  785. mobi_app: 'iphone',
  786. platform: 'ios',
  787. appkey: '27eb53fc9058f8c3',
  788. access_key: config.key
  789. }
  790. const sortedBody = $.queryStr(Object.fromEntries(new Map(Array.from(Object.entries(body)).sort())))
  791. const sign = md5(sortedBody + 'c2ed53a74eeefe3cf99fbd01d8c9c375')
  792. body['sign'] = sign
  793. const myRequest = {
  794. url: 'https://api.bilibili.com/pgc/activity/score/task/receive/v2',
  795. headers: {
  796. 'Content-Type': 'application/x-www-form-urlencoded',
  797. 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_4_1 like Mac OS X) AppleWebKit/615.2.9.10.4 (KHTML, like Gecko) Mobile/20F75 BiliApp/77200100 os/ios model/iPhone 15 Pro Max mobi_app/iphone build/77200100 osVer/17.4.1 network/2 channel/AppStore c_locale/zh-Hans_CN s_locale/zh-Hans_CN disable_rcmd/0',
  798. 'Cookie': `SESSDATA=${config.cookie.SESSDATA}`,
  799. 'Referer': `https://big.bilibili.com/mobile/bigPoint/task`
  800. },
  801. body: $.queryStr(body)
  802. }
  803. await $.fetch(myRequest).then(response => {
  804. try {
  805. const body = $.toObj(response.body)
  806. if (body?.code === 0 && body?.message === "success") {
  807. $.log("- 大会员观看剧集任务接取成功, 需自行观看")
  808. } else {
  809. $.log("- 大会员观看剧集任务接取失败")
  810. $.log("- 失败原因 " + body?.message)
  811. }
  812. } catch (e) {
  813. $.logErr(e, response)
  814. }
  815. })
  816. }
  817. async function vipPrivilege(type) {
  818. $.log("#### 领取大会员月度福利")
  819. const body = {
  820. csrf: config.cookie.bili_jct,
  821. type
  822. }
  823. const myRequest = {
  824. url: 'https://api.bilibili.com/x/vip/privilege/receive',
  825. headers: {
  826. 'Cookie': config.cookieStr
  827. },
  828. body: $.queryStr(body)
  829. }
  830. await $.fetch(myRequest).then(response => {
  831. try {
  832. const body = $.toObj(response.body)
  833. if (body?.code === 0) {
  834. switch (type) {
  835. case 1:
  836. $.log("- 领取年度大会员每月B币券成功")
  837. $.msg("年度大会员月度福利", "B币券", "🎉🎉🎉领取成功")
  838. break
  839. case 2:
  840. $.log("- 领取年度大会员每月会员购优惠券成功")
  841. break
  842. case 3:
  843. $.log("- 领取年度大会员每月漫画福利券成功")
  844. break
  845. case 4:
  846. $.log("- 领取年度大会员每月会员购包邮券成功")
  847. break
  848. case 5:
  849. $.log("- 领取年度大会员每月漫画商城优惠券成功")
  850. break
  851. case 6:
  852. $.log("- 领取大会员每月装扮体验卡成功")
  853. break
  854. case 7:
  855. $.log("- 领取大会员每月课堂优惠券成功")
  856. break
  857. default:
  858. break
  859. }
  860. } else {
  861. $.log("- 领取大会员每月福利失败, 福利编码为" + type)
  862. $.log("- 失败原因 " + body?.message)
  863. if (type === 1) {
  864. $.msg("年度大会员月度福利", "B币券领取失败", "失败原因为: " + body?.message)
  865. }
  866. //其他福利没什么用,失败也无需单独通知
  867. }
  868. } catch (e) {
  869. $.logErr(e, response)
  870. }
  871. })
  872. }
  873. async function Charge(mid, bp_num) {
  874. $.log("#### B币券自动充电")
  875. const body = {
  876. bp_num,
  877. is_bp_remains_prior: true,
  878. up_mid: mid,
  879. otype: 'up',
  880. oid: mid,
  881. csrf: config.cookie.bili_jct
  882. }
  883. const myRequest = {
  884. url: 'https://api.bilibili.com/x/ugcpay/web/v2/trade/elec/pay/quick',
  885. headers: {
  886. 'Cookie': config.cookieStr
  887. },
  888. body: $.queryStr(body)
  889. }
  890. await $.fetch(myRequest).then(response => {
  891. try {
  892. const body = $.toObj(response.body)
  893. if (body?.code === 0) {
  894. if (body?.data?.status === 4) {
  895. if (mid === config.user.mid) {
  896. $.log("- 为自己充电成功")
  897. } else {
  898. $.log(`- 为用户id为${mid}的用户充电成功`)
  899. }
  900. } else if (body?.data?.status === -4) {
  901. $.log("- 充电失败, B币不足")
  902. } else {
  903. $.log("- 充电失败")
  904. $.log("- 失败原因 " + body?.message)
  905. }
  906. } else {
  907. $.log("- 充电失败")
  908. $.log("- 失败原因 " + body?.message)
  909. }
  910. } catch (e) {
  911. $.logErr(e, response)
  912. }
  913. })
  914. }
  915. async function me() {
  916. $.log("#### 用户信息")
  917. const myRequest = {
  918. url: 'https://api.bilibili.com/x/web-interface/nav',
  919. headers: {
  920. "cookie": config.cookieStr
  921. }
  922. }
  923. return await $.fetch(myRequest).then(response => {
  924. try {
  925. const body = $.toObj(response.body)
  926. if (body?.code) {
  927. $.log("- ❌❌获得用户信息失败(请更新cookie)")
  928. $.setItem($.name + "_daily_bonus", null)
  929. return false
  930. } else {
  931. $.log("- 🎉cookie有效任务即将开始🎉")
  932. config.user = body?.data
  933. config.user.num = check("user") ? 1 : (config.user.num || 0) + 1
  934. $.setItem($.name + "_daily_bonus", $.toStr(config))
  935. config.user.mext_exp = config.user.level_info.next_exp - config.user.level_info.current_exp
  936. config.user.next_day = Math.ceil(config.user.mext_exp / 15)
  937. config.user.v6_exp = 28800 - config.user.level_info.current_exp
  938. config.user.v6_day = Math.ceil(config.user.v6_exp / 15)
  939. if (config.user.vipStatus === 1) {
  940. $.log("- 💖尊贵的大会员用户💖")
  941. }
  942. $.log("- 用户名称: " + config.user.uname)
  943. $.log("- 用户ID: " + config.user.mid)
  944. $.log("- 用户硬币: " + Math.floor(config.user.money))
  945. $.log("- 用户B币: " + config.user.wallet.bcoin_balance)
  946. $.log("- 用户等级: " + config.user.level_info.current_level)
  947. $.log(
  948. `- 当前经验: ${config.user.level_info.current_exp}/${config.user.level_info.next_exp}`
  949. )
  950. $.log(`- 升级还需经验: ${config.user.mext_exp}`)
  951. $.log(
  952. `- 距离下级还需: ${config.user.next_day}天(登录 观看 分享)`
  953. )
  954. $.log(
  955. `- 距离满级还需: ${Math.max(0, config.user.v6_day)}天(登录 观看 分享)`
  956. )
  957. $.log(`- 剩余硬币最多可投: ${Math.floor((config.user.money)/5)}天`)
  958. $.log(
  959. "- 距离满级最快还需: " +
  960. Math.max(0, Math.ceil(config.user.v6_exp / 65)) +
  961. "天(日常 + 投币*5)"
  962. )
  963. return true
  964. }
  965. } catch (e) {
  966. $.logErr(e, response)
  967. }
  968. }, reason => {
  969. $.msg($.name, "- 获取用户信息失败", $.toStr(reason))
  970. return false
  971. })
  972. }
  973. async function queryStatus() {
  974. $.log("#### 检查任务进行状况")
  975. const myRequest = {
  976. url: "https://api.bilibili.com/x/member/web/exp/reward",
  977. headers: {
  978. "cookie": config.cookieStr
  979. }
  980. }
  981. await $.fetch(myRequest).then(response => {
  982. try {
  983. const body = $.toObj(response.body)
  984. if (body?.code === 0) {
  985. if (body.data.login) {
  986. $.log("- 今日已登录")
  987. config.user.num = (config.user.num === 0 ? 1 : config.user.num)
  988. if (!config['user'].hasOwnProperty("time")) {
  989. config.user.time = startTime
  990. }
  991. } else {
  992. $.log("! 今日尚未登录")
  993. config.user.num = 0
  994. }
  995. if (body.data.watch){
  996. $.log("- 今日已观看")
  997. config.watch.num = (config.watch.num === 0 || typeof config.watch.num === 'undefined' ? 1 : config.watch.num)
  998. if (!config['watch'].hasOwnProperty("time")) {
  999. config.watch.time = startTime
  1000. }
  1001. } else {
  1002. $.log("! 今日尚未观看")
  1003. config.watch.num = 0
  1004. }
  1005. if (body.data.share){
  1006. $.log("- 今日已分享")
  1007. config.share.num = (config.share.num === 0 || typeof config.share.num === 'undefined' ? 1 : config.share.num)
  1008. if (!config['share'].hasOwnProperty("time")) {
  1009. config.share.time = startTime
  1010. }
  1011. } else {
  1012. $.log("! 今日尚未分享")
  1013. config.share.num = 0
  1014. }
  1015. if (body.data.coins === 50){
  1016. $.log("- 今日已投币")
  1017. if (!config['coins'].hasOwnProperty("time")) {
  1018. config.coins.time = startTime
  1019. } else {
  1020. if (format(new Date().toDateString()) > config.coins.time) {
  1021. config.coins.time = startTime
  1022. }
  1023. }
  1024. } else if ((body.data.coins / 10) >= real_times) {
  1025. config.coins.time = startTime
  1026. $.log("- 已完成用户设置的投币量")
  1027. } else if (config.user.money <= 5) {
  1028. $.log("! 硬币数不足")
  1029. } else {
  1030. $.log("! 今日投币未完成")
  1031. }
  1032. config.coins.num = body.data.coins
  1033. $.setItem($.name + "_daily_bonus", $.toStr(config))
  1034. } else {
  1035. $.log("- 查询失败")
  1036. $.log("- 失败原因 " + body?.message)
  1037. }
  1038. } catch (e) {
  1039. $.logErr(e, response)
  1040. }
  1041. })
  1042. }
  1043. async function dynamic() {
  1044. $.log("#### 获取首页视频")
  1045. const myRequest = {
  1046. url: `https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/dynamic_new?uid=${config.cookie.DedeUserID}&type_list=8&from=&platform=web`,
  1047. headers: {
  1048. "cookie": config.cookieStr
  1049. }
  1050. }
  1051. await $.fetch(myRequest).then(response => {
  1052. try {
  1053. const body = $.toObj(response.body)
  1054. if (body?.data?.cards) {
  1055. cards = body.data.cards
  1056. const { user, watch, share } = config
  1057. user.time = watch.time = share.time = startTime
  1058. $.log("- 获取视频动态成功")
  1059. } else {
  1060. $.log("- 获取视频动态失败")
  1061. }
  1062. } catch (e) {
  1063. $.logErr(e, response)
  1064. }
  1065. })
  1066. }
  1067. // Wbi签名获取
  1068. function getWbiSigns(r){function t(r){let t="";return e.forEach(s=>{t+=r[s]}),t.slice(0,32)}function s(r,s,u){const e=t(s+u),i=parseInt($.startTime/1e3);let n="";r=Object.assign(r,{wts:i}),n=$.queryStr(Object.fromEntries(new Map(Array.from(Object.entries(r)).sort())));const l=md5(n+e);return n+"&w_rid="+l}function u(){return img_url=config.user.wbi_img.img_url,sub_url=config.user.wbi_img.sub_url,{img_key:img_url.substring(img_url.lastIndexOf("/")+1,img_url.length).split(".")[0],sub_key:sub_url.substring(sub_url.lastIndexOf("/")+1,sub_url.length).split(".")[0]}}const e=[46,47,18,2,53,8,23,32,15,50,10,31,58,3,45,35,27,43,5,49,33,9,42,19,29,28,14,39,12,38,41,13,37,48,7,16,24,55,40,61,26,17,0,1,60,51,30,4,22,25,54,21,56,59,6,63,57,62,11,36,20,34,44,52],i=u();return s(r,i.img_key,i.sub_key)}
  1069. // md5(32位)
  1070. function md5(r){function n(r,n){return r<<n|r>>>32-n}function t(r,n){var t,o,e,u,f;return e=2147483648&r,u=2147483648&n,t=1073741824&r,o=1073741824&n,f=(1073741823&r)+(1073741823&n),t&o?2147483648^f^e^u:t|o?1073741824&f?3221225472^f^e^u:1073741824^f^e^u:f^e^u}function o(r,n,t){return r&n|~r&t}function e(r,n,t){return r&t|n&~t}function u(r,n,t){return r^n^t}function f(r,n,t){return n^(r|~t)}function i(r,e,u,f,i,a,c){return r=t(r,t(t(o(e,u,f),i),c)),t(n(r,a),e)}function a(r,o,u,f,i,a,c){return r=t(r,t(t(e(o,u,f),i),c)),t(n(r,a),o)}function c(r,o,e,f,i,a,c){return r=t(r,t(t(u(o,e,f),i),c)),t(n(r,a),o)}function C(r,o,e,u,i,a,c){return r=t(r,t(t(f(o,e,u),i),c)),t(n(r,a),o)}function g(r){for(var n,t=r.length,o=t+8,e=(o-o%64)/64,u=16*(e+1),f=Array(u-1),i=0,a=0;a<t;)n=(a-a%4)/4,i=a%4*8,f[n]=f[n]|r.charCodeAt(a)<<i,a++;return n=(a-a%4)/4,i=a%4*8,f[n]=f[n]|128<<i,f[u-2]=t<<3,f[u-1]=t>>>29,f}function h(r){var n,t,o="",e="";for(t=0;t<=3;t++)n=r>>>8*t&255,e="0"+n.toString(16),o+=e.slice(-2);return o}function d(r){r=r.replace(/\r\n/g,"\n");for(var n="",t=0;t<r.length;t++){var o=r.charCodeAt(t);o<128?n+=String.fromCharCode(o):o>127&&o<2048?(n+=String.fromCharCode(o>>6|192),n+=String.fromCharCode(63&o|128)):(n+=String.fromCharCode(o>>12|224),n+=String.fromCharCode(o>>6&63|128),n+=String.fromCharCode(63&o|128))}return n}var m,S,v,l,A,s,y,p,w,L=Array(),b=7,j=12,k=17,q=22,x=5,z=9,B=14,D=20,E=4,F=11,G=16,H=23,I=6,J=10,K=15,M=21;for(r=d(r),L=g(r),s=1732584193,y=4023233417,p=2562383102,w=271733878,m=0;m<L.length;m+=16)S=s,v=y,l=p,A=w,s=i(s,y,p,w,L[m+0],b,3614090360),w=i(w,s,y,p,L[m+1],j,3905402710),p=i(p,w,s,y,L[m+2],k,606105819),y=i(y,p,w,s,L[m+3],q,3250441966),s=i(s,y,p,w,L[m+4],b,4118548399),w=i(w,s,y,p,L[m+5],j,1200080426),p=i(p,w,s,y,L[m+6],k,2821735955),y=i(y,p,w,s,L[m+7],q,4249261313),s=i(s,y,p,w,L[m+8],b,1770035416),w=i(w,s,y,p,L[m+9],j,2336552879),p=i(p,w,s,y,L[m+10],k,4294925233),y=i(y,p,w,s,L[m+11],q,2304563134),s=i(s,y,p,w,L[m+12],b,1804603682),w=i(w,s,y,p,L[m+13],j,4254626195),p=i(p,w,s,y,L[m+14],k,2792965006),y=i(y,p,w,s,L[m+15],q,1236535329),s=a(s,y,p,w,L[m+1],x,4129170786),w=a(w,s,y,p,L[m+6],z,3225465664),p=a(p,w,s,y,L[m+11],B,643717713),y=a(y,p,w,s,L[m+0],D,3921069994),s=a(s,y,p,w,L[m+5],x,3593408605),w=a(w,s,y,p,L[m+10],z,38016083),p=a(p,w,s,y,L[m+15],B,3634488961),y=a(y,p,w,s,L[m+4],D,3889429448),s=a(s,y,p,w,L[m+9],x,568446438),w=a(w,s,y,p,L[m+14],z,3275163606),p=a(p,w,s,y,L[m+3],B,4107603335),y=a(y,p,w,s,L[m+8],D,1163531501),s=a(s,y,p,w,L[m+13],x,2850285829),w=a(w,s,y,p,L[m+2],z,4243563512),p=a(p,w,s,y,L[m+7],B,1735328473),y=a(y,p,w,s,L[m+12],D,2368359562),s=c(s,y,p,w,L[m+5],E,4294588738),w=c(w,s,y,p,L[m+8],F,2272392833),p=c(p,w,s,y,L[m+11],G,1839030562),y=c(y,p,w,s,L[m+14],H,4259657740),s=c(s,y,p,w,L[m+1],E,2763975236),w=c(w,s,y,p,L[m+4],F,1272893353),p=c(p,w,s,y,L[m+7],G,4139469664),y=c(y,p,w,s,L[m+10],H,3200236656),s=c(s,y,p,w,L[m+13],E,681279174),w=c(w,s,y,p,L[m+0],F,3936430074),p=c(p,w,s,y,L[m+3],G,3572445317),y=c(y,p,w,s,L[m+6],H,76029189),s=c(s,y,p,w,L[m+9],E,3654602809),w=c(w,s,y,p,L[m+12],F,3873151461),p=c(p,w,s,y,L[m+15],G,530742520),y=c(y,p,w,s,L[m+2],H,3299628645),s=C(s,y,p,w,L[m+0],I,4096336452),w=C(w,s,y,p,L[m+7],J,1126891415),p=C(p,w,s,y,L[m+14],K,2878612391),y=C(y,p,w,s,L[m+5],M,4237533241),s=C(s,y,p,w,L[m+12],I,1700485571),w=C(w,s,y,p,L[m+3],J,2399980690),p=C(p,w,s,y,L[m+10],K,4293915773),y=C(y,p,w,s,L[m+1],M,2240044497),s=C(s,y,p,w,L[m+8],I,1873313359),w=C(w,s,y,p,L[m+15],J,4264355552),p=C(p,w,s,y,L[m+6],K,2734768916),y=C(y,p,w,s,L[m+13],M,1309151649),s=C(s,y,p,w,L[m+4],I,4149444226),w=C(w,s,y,p,L[m+11],J,3174756917),p=C(p,w,s,y,L[m+2],K,718787259),y=C(y,p,w,s,L[m+9],M,3951481745),s=t(s,S),y=t(y,v),p=t(p,l),w=t(w,A);return(h(s)+h(y)+h(p)+h(w)).toLowerCase()}
  1071. /***************** Env *****************/
  1072. // prettier-ignore
  1073. // https://github.com/chavyleung/scripts/blob/master/Env.min.js
  1074. function Env(a,b){var c=Math.floor;return new class{constructor(a,b){this.name=a,this.version="1.7.4",this.data=null,this.logs=[],this.isMute=!1,this.isNeedRewrite=!1,this.logSeparator="\n",this.encoding="utf-8",this.startTime=new Date().getTime(),Object.assign(this,b),this.log("",`🔔${this.name}, 开始!`)}platform(){return"undefined"!=typeof $environment&&$environment["surge-version"]?"Surge":"undefined"!=typeof $environment&&$environment["stash-version"]?"Stash":"undefined"==typeof module||!module.exports?"undefined"==typeof $task?"undefined"==typeof $loon?"undefined"==typeof $rocket?"undefined"==typeof Egern?void 0:"Egern":"Shadowrocket":"Loon":"Quantumult X":"Node.js"}isQuanX(){return"Quantumult X"===this.platform()}isSurge(){return"Surge"===this.platform()}isLoon(){return"Loon"===this.platform()}isShadowrocket(){return"Shadowrocket"===this.platform()}isStash(){return"Stash"===this.platform()}isEgern(){return"Egern"===this.platform()}toObj(a,b=null){try{return JSON.parse(a)}catch{return b}}toStr(a,b=null){try{return JSON.stringify(a)}catch{return b}}lodash_get(a={},b="",c=void 0){Array.isArray(b)||(b=this.toPath(b));const d=b.reduce((a,b)=>Object(a)[b],a);return d===void 0?c:d}lodash_set(a={},b="",c){return Array.isArray(b)||(b=this.toPath(b)),b.slice(0,-1).reduce((a,c,d)=>Object(a[c])===a[c]?a[c]:a[c]=/^\d+$/.test(b[d+1])?[]:{},a)[b[b.length-1]]=c,a}toPath(a){return a.replace(/\[(\d+)\]/g,".$1").split(".").filter(Boolean)}getItem(a=new String,b=null){let c=b;switch(a.startsWith("@")){case!0:const{key:b,path:d}=a.match(/^@(?<key>[^.]+)(?:\.(?<path>.*))?$/)?.groups;a=b;let e=this.getItem(a,{});"object"!=typeof e&&(e={}),c=this.lodash_get(e,d);try{c=JSON.parse(c)}catch(a){}break;default:switch(this.platform()){case"Surge":case"Loon":case"Stash":case"Egern":case"Shadowrocket":c=$persistentStore.read(a);break;case"Quantumult X":c=$prefs.valueForKey(a);break;default:c=this.data?.[a]||null}try{c=JSON.parse(c)}catch(a){}}return c??b}setItem(a=new String,b=new String){let c=!1;switch(typeof b){case"object":b=JSON.stringify(b);break;default:b=b+""}switch(a.startsWith("@")){case!0:const{key:d,path:e}=a.match(/^@(?<key>[^.]+)(?:\.(?<path>.*))?$/)?.groups;a=d;let f=this.getItem(a,{});"object"!=typeof f&&(f={}),this.lodash_set(f,e,b),c=this.setItem(a,f);break;default:switch(this.platform()){case"Surge":case"Loon":case"Stash":case"Egern":case"Shadowrocket":c=$persistentStore.write(b,a);break;case"Quantumult X":c=$prefs.setValueForKey(b,a);break;default:c=this.data?.[a]||null}}return c}async fetch(a={},b={}){switch(a.constructor){case Object:a={...a,...b};break;case String:a={url:a,...b}}a.method||(a.method=a.body??a.bodyBytes?"POST":"GET"),delete a.headers?.Host,delete a.headers?.[":authority"],delete a.headers?.["Content-Length"],delete a.headers?.["content-length"];const c=a.method.toLocaleLowerCase();switch(this.platform()){case"Loon":case"Surge":case"Stash":case"Egern":case"Shadowrocket":default:return a.policy&&(this.isLoon()&&(a.node=a.policy),this.isStash()&&this.lodash_set(a,"headers.X-Stash-Selected-Proxy",encodeURI(a.policy))),a.followRedirect&&((this.isSurge()||this.isLoon())&&(a["auto-redirect"]=!1),this.isQuanX()&&(a.opts?a.opts.redirection=!1:a.opts={redirection:!1})),a.bodyBytes&&!a.body&&(a.body=a.bodyBytes,delete a.bodyBytes),await new Promise((b,d)=>{$httpClient[c](a,(c,e,f)=>{c?d(c):(e.ok=/^2\d\d$/.test(e.status),e.statusCode=e.status,f&&(e.body=f,!0==a["binary-mode"]&&(e.bodyBytes=f)),b(e))})});case"Quantumult X":return a.policy&&this.lodash_set(a,"opts.policy",a.policy),"boolean"==typeof a["auto-redirect"]&&this.lodash_set(a,"opts.redirection",a["auto-redirect"]),a.body instanceof ArrayBuffer?(a.bodyBytes=a.body,delete a.body):ArrayBuffer.isView(a.body)?(a.bodyBytes=a.body.buffer.slice(a.body.byteOffset,a.body.byteLength+a.body.byteOffset),delete object.body):a.body&&delete a.bodyBytes,await $task.fetch(a).then(a=>(a.ok=/^2\d\d$/.test(a.statusCode),a.status=a.statusCode,a),a=>Promise.reject(a.error))}}time(a,b=null){const d=b?new Date(b):new Date;let e={"M+":d.getMonth()+1,"d+":d.getDate(),"H+":d.getHours(),"m+":d.getMinutes(),"s+":d.getSeconds(),"q+":c((d.getMonth()+3)/3),S:d.getMilliseconds()};for(let c in /(y+)/.test(a)&&(a=a.replace(RegExp.$1,(d.getFullYear()+"").slice(4-RegExp.$1.length))),e)new RegExp("("+c+")").test(a)&&(a=a.replace(RegExp.$1,1==RegExp.$1.length?e[c]:("00"+e[c]).slice((""+e[c]).length)));return a}getBaseURL(a){return a.replace(/[?#].*$/,"")}isAbsoluteURL(a){return /^[a-z][a-z0-9+.-]*:/.test(a)}getURLParameters(a){return(a.match(/([^?=&]+)(=([^&]*))/g)||[]).reduce((b,a)=>(b[a.slice(0,a.indexOf("="))]=a.slice(a.indexOf("=")+1),b),{})}getTimestamp(a=new Date){return c(a.getTime()/1e3)}queryStr(a){let b=[];for(let c in a)a.hasOwnProperty(c)&&b.push(`${c}=${a[c]}`);let c=b.join("&");return c}queryObj(a){let b={},c=a.split("&");for(let d of c){let a=d.split("="),c=a[0],e=a[1]||"";c&&(b[c]=e)}return b}msg(a=this.name,b="",c="",d){const e=a=>{switch(typeof a){case void 0:return a;case"string":switch(this.platform()){case"Surge":case"Stash":case"Egern":default:return{url:a};case"Loon":case"Shadowrocket":return a;case"Quantumult X":return{"open-url":a}}case"object":switch(this.platform()){case"Surge":case"Stash":case"Egern":case"Shadowrocket":default:{let b=a.url||a.openUrl||a["open-url"];return{url:b}}case"Loon":{let b=a.openUrl||a.url||a["open-url"],c=a.mediaUrl||a["media-url"];return{openUrl:b,mediaUrl:c}}case"Quantumult X":{let b=a["open-url"]||a.url||a.openUrl,c=a["media-url"]||a.mediaUrl,d=a["update-pasteboard"]||a.updatePasteboard;return{"open-url":b,"media-url":c,"update-pasteboard":d}}}default:}};if(!this.isMute)switch(this.platform()){case"Surge":case"Loon":case"Stash":case"Shadowrocket":default:$notification.post(a,b,c,e(d));break;case"Quantumult X":$notify(a,b,c,e(d))}}log(...a){0<a.length&&(this.logs=[...this.logs,...a]),console.log(a.join(this.logSeparator))}logErr(a,b){switch(this.platform()){case"Surge":case"Loon":case"Stash":case"Egern":case"Shadowrocket":case"Quantumult X":default:this.log("",`❗️${this.name}, 错误!`,a,b)}}wait(a){return new Promise(b=>setTimeout(b,a))}done(a={}){const b=new Date().getTime(),c=(b-this.startTime)/1e3;switch(this.log("",`🔔${this.name}, 结束! 🕛 ${c} 秒`),this.platform()){case"Surge":a.policy&&this.lodash_set(a,"headers.X-Surge-Policy",a.policy),$done(a);break;case"Loon":a.policy&&(a.node=a.policy),$done(a);break;case"Stash":a.policy&&this.lodash_set(a,"headers.X-Stash-Selected-Proxy",encodeURI(a.policy)),$done(a);break;case"Egern":$done(a);break;case"Shadowrocket":default:$done(a);break;case"Quantumult X":a.policy&&this.lodash_set(a,"opts.policy",a.policy),delete a["auto-redirect"],delete a["auto-cookie"],delete a["binary-mode"],delete a.charset,delete a.host,delete a.insecure,delete a.method,delete a.opt,delete a.path,delete a.policy,delete a["policy-descriptor"],delete a.scheme,delete a.sessionIndex,delete a.statusCode,delete a.timeout,a.body instanceof ArrayBuffer?(a.bodyBytes=a.body,delete a.body):ArrayBuffer.isView(a.body)?(a.bodyBytes=a.body.buffer.slice(a.body.byteOffset,a.body.byteLength+a.body.byteOffset),delete a.body):a.body&&delete a.bodyBytes,$done(a)}}}(a,b)}