rush4award

🔥功能介绍:1、支持B站所有激励计划,是否成功取决于b站接口是否更新,与游戏版本无关;2、根据验证码通过情况自适应请求速度

  1. // ==UserScript==
  2. // @name rush4award
  3. // @namespace vurses
  4. // @license Mit
  5. // @match https://www.bilibili.com/blackboard/new-award-exchange.html?task_id=*
  6. // @match https://www.bilibili.com/blackboard/era/award-exchange.html?task_id=*
  7. // @version 3.8.0
  8. // @author layenh
  9. // @icon https://i0.hdslb.com/bfs/activity-plat/static/b9vgSxGaAg.png
  10. // @homepage https://github.com/vruses/get-bili-redeem
  11. // @supportURL https://github.com/vruses/get-bili-redeem/issues
  12. // @require https://update.gf.qytechs.cn/scripts/535838/1588053/NumberInput.js
  13. // @require https://update.gf.qytechs.cn/scripts/535840/1588055/FloatButton.js
  14. // @run-at document-start
  15. // @grant none
  16. // @description 🔥功能介绍:1、支持B站所有激励计划,是否成功取决于b站接口是否更新,与游戏版本无关;2、根据验证码通过情况自适应请求速度
  17. // ==/UserScript==
  18.  
  19. const storage = {
  20. set(key, value) {
  21. try {
  22. const data = JSON.stringify(value);
  23. localStorage.setItem(key, data);
  24. } catch (e) {
  25. console.error("Storage Set Error:", e);
  26. }
  27. },
  28.  
  29. get(key, defaultValue = null) {
  30. try {
  31. const data = localStorage.getItem(key);
  32. return data !== null ? JSON.parse(data) : defaultValue;
  33. } catch (e) {
  34. console.error("Storage Get Error:", e);
  35. return defaultValue;
  36. }
  37. },
  38. };
  39.  
  40. let ReceiveTime = storage.get("ReceiveTime", 1000);
  41. let SlowerTime = storage.get("SlowerTime", 3000);
  42.  
  43. const workerJs = function () {
  44. class TimerManager {
  45. constructor() {
  46. this.timers = new Map();
  47. }
  48. set(key, callback, delay) {
  49. this.clean(key);
  50. const id = setTimeout(() => {
  51. callback();
  52. }, delay);
  53. this.timers.set(key, id);
  54. }
  55. clean(key) {
  56. if (this.timers.has(key)) {
  57. clearTimeout(this.timers.get(key));
  58. this.timers.delete(key);
  59. }
  60. }
  61. cleanAll() {
  62. for (let id of this.timers.values()) {
  63. clearTimeout(id);
  64. }
  65. this.timers.clear();
  66. }
  67. has(key) {
  68. return this.timers.has(key);
  69. }
  70. }
  71. const manager = new TimerManager();
  72. // 根据taskName设置定时
  73. self.addEventListener("message", function (e) {
  74. manager.set(
  75. e.data.taskName,
  76. () => self.postMessage(e.data.taskName),
  77. e.data.time
  78. );
  79. });
  80. };
  81.  
  82. workerJs.toString();
  83. const blob = new Blob([`(${workerJs})()`], { type: "application/javascript" });
  84. const url = URL.createObjectURL(blob);
  85. const worker = new Worker(url);
  86.  
  87. const originalCall = Function.prototype.call;
  88.  
  89. Function.prototype.call = function (...args) {
  90. if (this.name === "fb94") {
  91. let funcStr = this.toString();
  92. const oldIndex = funcStr.indexOf("this.$nextTick(()=>{}),");
  93. // const newIndex = funcStr.indexOf("this.$nextTick((function(){})),");
  94. if (oldIndex !== -1) {
  95. funcStr.indexOf("this.$nextTick(()=>{}),");
  96. funcStr = funcStr.replace(
  97. `this.$nextTick(()=>{}),`,
  98. (res) =>
  99. res +
  100. "Object.assign(window,{awardInstance:this}),Object.assign(window,{utils:v}),"
  101. );
  102. // 禁止pub&notify错误页消息
  103. funcStr = funcStr.replace(
  104. `setCommonDialog(t){b.commonErrorDialog=t},`,
  105. `setCommonDialog(t){},`
  106. );
  107. // 防止不再弹出验证码
  108. funcStr = funcStr.replace(`e.destroy()`, ``);
  109. funcStr = eval("(" + funcStr + ")");
  110. } else {
  111. // 新版页面patch
  112. // 定位目标函数,获取被压缩的函数名(A-Z)
  113. const target1 = "(this.taskKey)";
  114. const index1 = funcStr.indexOf(target1);
  115. // 用于暴露获取奖励信息的函数
  116. const infoFuncName = funcStr.charAt(index1 - 1);
  117.  
  118. const target2 = "(this.actId).then";
  119. const index2 = funcStr.indexOf(target2);
  120. // 用于暴露获取奖励cdk的函数
  121. const historyFuncName = funcStr.charAt(index2 - 1);
  122.  
  123. // 动态注入函数名
  124. funcStr = funcStr.replace(
  125. `this.$nextTick((function(){})),`,
  126. (res) =>
  127. res +
  128. `Object.assign(window,{awardInstance:this}),Object.assign(window,{utils:{getBounsInfo:${infoFuncName},getBounsHistory:${historyFuncName}}}),`
  129. );
  130. // 禁止pub&notify错误页消息
  131. funcStr = funcStr.replace(`I.commonErrorDialog=t`, ``);
  132. funcStr = eval("(" + funcStr + ")");
  133. }
  134.  
  135. return originalCall.apply(funcStr, args);
  136. }
  137. return originalCall.apply(this, args);
  138. };
  139.  
  140. const originalFetch = window.fetch;
  141.  
  142. window.fetch = function (input, init = {}) {
  143. let url = "";
  144. // 处理 input 可能是字符串或 Request 对象
  145. if (typeof input === "string") {
  146. url = input;
  147. } else if (input instanceof Request) {
  148. url = input.url;
  149. }
  150. if (url.includes("/x/activity_components/mission/receive")) {
  151. return originalFetch
  152. .call(this, input, init)
  153. .then((res) => {
  154. res
  155. .clone()
  156. .json()
  157. .then((res) => {
  158. if (res.code === 202100) {
  159. // 由于移除了验证码机制,这部分逻辑可能会在未来移除
  160. document.querySelector("a.geetest_close")?.click();
  161. worker.postMessage({ taskName: "receiveTask", time: SlowerTime });
  162. } else {
  163. worker.postMessage({
  164. taskName: "receiveTask",
  165. time: ReceiveTime,
  166. });
  167. }
  168. });
  169. return res;
  170. })
  171. .catch((e) => {
  172. console.log(e);
  173. });
  174. }
  175. return originalFetch.call(this, input, init);
  176. };
  177.  
  178. window.addEventListener("load", function () {
  179. // 插入到页面的一些信息
  180. const totalStockEl = document.createElement("p");
  181. totalStockEl.className = "extra-info";
  182. totalStockEl.textContent = `总剩余量: ${"未获取"}`;
  183. const cdKeyEl = document.createElement("p");
  184. cdKeyEl.className = "extra-info";
  185. cdKeyEl.textContent = `cdKey: ${"未获取"}`;
  186. const awardPreviewEl = document.createElement("div");
  187. awardPreviewEl.className = "award-preview";
  188. awardPreviewEl.append(cdKeyEl, totalStockEl);
  189. // 文字可选中
  190. document.querySelector(".award-wrap").style.userSelect = "text";
  191. document.querySelector(".award-wrap").append(awardPreviewEl);
  192. if (awardInstance?.cdKey) {
  193. return;
  194. }
  195. const loopRequest = function () {
  196. return new Promise((res, rej) => {
  197. setTimeout(res, 1000);
  198. })
  199. .then(() => {
  200. awardInstance.handelReceive("user");
  201. })
  202. .catch((e) => {
  203. console.log(e);
  204. loopRequest();
  205. });
  206. };
  207. loopRequest();
  208. // 定时获取新的信息
  209. setInterval(() => {
  210. worker.postMessage({ taskName: "getInfoTask", time: 0 });
  211. }, SlowerTime);
  212. console.log(awardInstance);
  213. awardInstance.$watch("pageError", function (newVal, oldVal) {
  214. this.pageError = false;
  215. });
  216. awardInstance.$watch("cdKey", function (newVal, oldVal) {
  217. window.fetch = originalFetch;
  218. worker.terminate();
  219. });
  220. worker.addEventListener("message", function (e) {
  221. if (e.data === "receiveTask") {
  222. awardInstance.handelReceive("user");
  223. } else if (e.data === "getInfoTask") {
  224. // 更新显示信息
  225. utils.getBounsHistory(awardInstance.actId).then((res) => {
  226. // 根据活动id取出对应兑换码
  227. const id = awardInstance.awardInfo.award_inner_id || 0;
  228. const i = res?.list?.find((t) => t.award_id === id);
  229. awardInstance.cdKey = i?.extra_info?.cdkey_content || "";
  230. });
  231. utils.getBounsInfo(awardInstance.taskId).then((res) => {
  232. totalStockEl.textContent = `总剩余量:${res.stock_info.total_stock}%`;
  233. cdKeyEl.textContent = `cdKey${awardInstance.cdKey}`;
  234. });
  235. }
  236. });
  237. });
  238.  
  239. // 在修改间隔后进行存储
  240. // 每次请求发起的间隔
  241. const receiveInput = document.createElement("input-number");
  242. receiveInput.value = ReceiveTime / 1000;
  243. receiveInput._value = receiveInput.value;
  244. Object.defineProperty(receiveInput, "value", {
  245. get() {
  246. return this._value;
  247. },
  248. set(value) {
  249. console.log("receive:" + value);
  250. ReceiveTime = value * 1000;
  251. storage.set("ReceiveTime", value * 1000);
  252. this._value = value;
  253. },
  254. });
  255. // 每次验证使用的时间
  256. const validateInput = document.createElement("input-number");
  257. validateInput.value = SlowerTime / 1000;
  258. validateInput._value = validateInput.value;
  259. Object.defineProperty(validateInput, "value", {
  260. get() {
  261. return this._value;
  262. },
  263. set(value) {
  264. console.log("validate:" + value);
  265. SlowerTime = value * 1000;
  266. storage.set("SlowerTime", value * 1000);
  267. this._value = value;
  268. },
  269. });
  270. // 请求插槽
  271. const intervalFaster = document.createElement("div");
  272. intervalFaster.slot = "interval-faster";
  273. intervalFaster.style.display = "flex";
  274. intervalFaster.style.alignItems = "center";
  275. intervalFaster.innerHTML = `<span style="width: 70px">请求间隔</span>`;
  276. // 验证插槽
  277. const intervalSlower = document.createElement("div");
  278. intervalSlower.slot = "interval-slower";
  279. intervalSlower.style.display = "flex";
  280. intervalSlower.style.alignItems = "center";
  281. intervalSlower.innerHTML = `<span style="width: 70px">信息同步</span>`;
  282.  
  283. intervalFaster.append(receiveInput);
  284. intervalSlower.append(validateInput);
  285.  
  286. const floatButton = document.createElement("float-button");
  287. floatButton.append(intervalFaster, intervalSlower);
  288. document.documentElement.append(floatButton);

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址