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. // @version 3.5.0
  7. // @author layenh
  8. // @icon https://i0.hdslb.com/bfs/activity-plat/static/b9vgSxGaAg.png
  9. // @homepage https://github.com/vruses/get-bili-redeem
  10. // @supportURL https://github.com/vruses/get-bili-redeem/issues
  11. // @require https://update.greasyfork.org/scripts/535838/1588053/NumberInput.js
  12. // @require https://update.greasyfork.org/scripts/535840/1588055/FloatButton.js
  13. // @run-at document-start
  14. // @grant none
  15. // @description 🔥功能介绍:1、支持B站所有激励计划,是否成功取决于b站接口是否更新,与游戏版本无关;2、根据验证码通过情况自适应请求速度
  16. // ==/UserScript==
  17.  
  18. // utils.request(p)=>info,inner
  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", 10000);
  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 temp = this.toString();
  92. temp.indexOf("this.$nextTick(()=>{}),");
  93. temp = temp.replace(
  94. `this.$nextTick(()=>{}),`,
  95. (res) =>
  96. res +
  97. "Object.assign(window,{awardInstance:this}),Object.assign(window,{utils:v}),"
  98. );
  99. // 禁止pub&notify错误页消息
  100. temp = temp.replace(
  101. `setCommonDialog(t){b.commonErrorDialog=t},`,
  102. `setCommonDialog(t){},`
  103. );
  104. // 防止不再弹出验证码
  105. temp = temp.replace(`e.destroy()`, ``);
  106. temp = eval("(" + temp + ")");
  107. return originalCall.apply(temp, args);
  108. }
  109. return originalCall.apply(this, args);
  110. };
  111.  
  112. const originalFetch = window.fetch;
  113.  
  114. window.fetch = function (input, init = {}) {
  115. let url = "";
  116. // 处理 input 可能是字符串或 Request 对象
  117. if (typeof input === "string") {
  118. url = input;
  119. } else if (input instanceof Request) {
  120. url = input.url;
  121. }
  122. if (url.includes("/x/activity_components/mission/receive")) {
  123. return originalFetch
  124. .call(this, input, init)
  125. .then((res) => {
  126. res
  127. .clone()
  128. .json()
  129. .then((res) => {
  130. if (res.code === 202100) {
  131. document.querySelector("a.geetest_close")?.click();
  132. worker.postMessage({ taskName: "receiveTask", time: SlowerTime });
  133. } else {
  134. worker.postMessage({ taskName: "receiveTask", time: ReceiveTime });
  135. }
  136. });
  137. return res;
  138. })
  139. .catch((e) => {
  140. console.log(e);
  141. });
  142. }
  143. return originalFetch.call(this, input, init);
  144. };
  145.  
  146. window.addEventListener("load", function () {
  147. // 插入到页面的一些信息
  148. const totalStockEl = document.createElement("p");
  149. totalStockEl.className = "extra-info";
  150. totalStockEl.textContent = `总剩余量: ${"未获取"}`;
  151. const cdKeyEl = document.createElement("p");
  152. cdKeyEl.className = "extra-info";
  153. cdKeyEl.textContent = `cdKey: ${"未获取"}`;
  154. const awardPreviewEl = document.createElement("div");
  155. awardPreviewEl.className = "award-preview";
  156. awardPreviewEl.append(cdKeyEl, totalStockEl);
  157. // 文字可选中
  158. document.querySelector(".award-wrap").style.userSelect = "text";
  159. document.querySelector(".award-wrap").append(awardPreviewEl);
  160. if (awardInstance.cdKey) {
  161. return;
  162. }
  163. const loopRequest = function () {
  164. return new Promise((res, rej) => {
  165. setTimeout(res, 1000);
  166. })
  167. .then(() => {
  168. awardInstance.handelReceive();
  169. })
  170. .catch((e) => {
  171. console.log(e);
  172. loopRequest();
  173. });
  174. };
  175. loopRequest();
  176. // 定时获取新的信息
  177. setInterval(() => {
  178. worker.postMessage({ taskName: "getInfoTask", time: 0 });
  179. }, 3000);
  180. console.log(awardInstance);
  181. awardInstance.$watch("pageError", function (newVal, oldVal) {
  182. this.pageError = false;
  183. });
  184. awardInstance.$watch("cdKey", function (newVal, oldVal) {
  185. window.fetch = originalFetch;
  186. worker.terminate();
  187. });
  188. worker.addEventListener("message", function (e) {
  189. console.log("post to window: " + e.data);
  190. if (e.data === "receiveTask") {
  191. awardInstance.handelReceive();
  192. } else if (e.data === "getInfoTask") {
  193. utils.getBounsInfo("6ERA4wloghv5rn00").then((res) => {
  194. totalStockEl.textContent = `总剩余量:${res.stock_info.total_stock}%`;
  195. cdKeyEl.textContent = `cdKey${awardInstance.cdKey}`;
  196. });
  197. }
  198. });
  199. });
  200.  
  201. // 在修改间隔后进行存储
  202. // 每次请求发起的间隔
  203. const receiveInput = document.createElement("input-number");
  204. receiveInput.value = ReceiveTime / 1000;
  205. receiveInput._value = receiveInput.value;
  206. Object.defineProperty(receiveInput, "value", {
  207. get() {
  208. return this._value;
  209. },
  210. set(value) {
  211. console.log("receive:" + value);
  212. ReceiveTime = value * 1000;
  213. storage.set("ReceiveTime", value * 1000);
  214. this._value = value;
  215. },
  216. });
  217. // 每次验证使用的时间
  218. const validateInput = document.createElement("input-number");
  219. validateInput.value = SlowerTime / 1000;
  220. validateInput._value = validateInput.value;
  221. Object.defineProperty(validateInput, "value", {
  222. get() {
  223. return this._value;
  224. },
  225. set(value) {
  226. console.log("validate:" + value);
  227. SlowerTime = value * 1000;
  228. storage.set("SlowerTime", value * 1000);
  229. this._value = value;
  230. },
  231. });
  232. // 请求插槽
  233. const intervalFaster = document.createElement("div");
  234. intervalFaster.slot = "interval-faster";
  235. intervalFaster.style.display = "flex";
  236. intervalFaster.style.alignItems = "center";
  237. intervalFaster.innerHTML = `<span style="width: 70px">请求间隔</span>`;
  238. // 验证插槽
  239. const intervalSlower = document.createElement("div");
  240. intervalSlower.slot = "interval-slower";
  241. intervalSlower.style.display = "flex";
  242. intervalSlower.style.alignItems = "center";
  243. intervalSlower.innerHTML = `<span style="width: 70px">验证间隔</span>`;
  244.  
  245. intervalFaster.append(receiveInput);
  246. intervalSlower.append(validateInput);
  247.  
  248. const floatButton = document.createElement("float-button");
  249. floatButton.append(intervalFaster, intervalSlower);
  250. document.documentElement.append(floatButton);