Yuba Fix

可使处于被关闭状态的斗鱼鱼吧的大多数功能暂时恢复正常使用,需要借用状态正常的鱼吧的UI。

  1. // ==UserScript==
  2. // @name Yuba Fix
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.2
  5. // @description 可使处于被关闭状态的斗鱼鱼吧的大多数功能暂时恢复正常使用,需要借用状态正常的鱼吧的UI。
  6. // @match *://yuba.douyu.com/discussion/13062*
  7. // @match *://yuba.douyu.com/discussion/5496243*
  8. // @grant none
  9. // @run-at document-start
  10. // @license MIT
  11. // ==/UserScript==
  12.  
  13. (async function () {
  14. 'use strict';
  15.  
  16. var css = '.banner__AyafQ{background-color:#FFFFFF !important;object-fit:contain;}';
  17. css += '.groupname__BUzOM{color:#515151 !important;text-shadow:0 0 0px #ffffff !important;}';
  18. css += '.groupdesc__b8-53{color:#515151 !important;text-shadow:0 0 0px #ffffff !important;}';
  19.  
  20. const OLD_GROUP_ID = '13062';
  21. const FAKE_GROUP_ID = '5496243';
  22. const FAKE_API_URL = `https://yuba.douyu.com/wbapi/web/group/head?group_id=${FAKE_GROUP_ID}`;
  23. const PUBLISH_API_URL = 'https://yuba.douyu.com/wgapi/yubanc/api/feed/publish';
  24. const FAKE_RESPONSE = {
  25. "data": {
  26. "group_id": 13062,
  27. "group_name": "玩机器丶Machine",
  28. "avatar": "https://apic.douyucdn.cn/upload/avatar_v3/201905/badbf01f7ab943358bf78bcd9245305f_big.jpg",
  29. "describe": "玩机器丶Machine的个人鱼吧",
  30. "post_num": 6657,
  31. "fans_num": 6657,
  32. "anchor_id": 5448527,
  33. "unread": 0,
  34. "is_follow": 1,
  35. "group_level": 3,
  36. "group_exp": 20,
  37. "level_status": 0,
  38. "level_medal": "https://img.douyucdn.cn/data/yuba/admin/2018/10/16/201810161200503920739346639.png?i=2326458f9353bc988e1a27c68175065282",
  39. "level_medal_new": "https://img.douyucdn.cn/data/yuba/weibo/2018/09/20/201809201549507007262123703.png",
  40. "next_level_exp": 30,
  41. "banner": "https://c-yuba.douyucdn.cn/yubavod/b/peApOkzz5mdl/7ced121e3251a680dfdf402305fd349c.jpg", //鱼吧banner背景图
  42. "group_title": "鱼塘司机",
  43. "is_signed": 0,
  44. "fid": 525,
  45. "f_name": "PC游戏",
  46. "f_describe": "斗鱼PC游戏版块",
  47. "f_avatar": "https://apic.douyucdn.cn/upload/avatar_v3/201905/badbf01f7ab943358bf78bcd9245305f_big.jpg",
  48. "manager_type": 0,
  49. "group_type": 2,
  50. "group_new_type": 2,
  51. "has_starwall": 0,
  52. "rank": 137,
  53. "has_user_rank": 1,
  54. "has_user_rank_reward": 1,
  55. "safe_anchor_id": "W67QgJNpzd0O",
  56. "has_game_comment": 0,
  57. "has_information": 0,
  58. "digest_tags": [],
  59. "cate2_info": { "c_template": 0 },
  60. "news_sw": 0,
  61. "hot_sort": false,
  62. "hor_cover": "",
  63. "game_id": 0
  64. },
  65. "message": "",
  66. "status_code": 200
  67. };
  68.  
  69. const redirectRegex = new RegExp(`^/discussion/${FAKE_GROUP_ID}/posts(?:[/?#]|$)`);
  70. const redirectRegex2 = new RegExp(`^/discussion/${FAKE_GROUP_ID}/highlight(?:[/?#]|$)`);
  71.  
  72. if (redirectRegex.test(window.location.pathname + window.location.search)) {
  73. const query = window.location.search || '';
  74. const hash = window.location.hash || '';
  75. window.location.href = `/discussion/${OLD_GROUP_ID}/posts${query}${hash}`;
  76. }
  77. if (redirectRegex2.test(window.location.pathname + window.location.search)) {
  78. const query = window.location.search || '';
  79. const hash = window.location.hash || '';
  80. window.location.href = `/discussion/${OLD_GROUP_ID}/highlight${query}${hash}`;
  81. }
  82.  
  83. function titlechange() {
  84. document.title = '玩机器丶Machine的鱼吧';
  85. }
  86.  
  87. const originalFetch = window.fetch;
  88. window.fetch = async function (...args) {
  89. let [input, init = {}] = args;
  90.  
  91. if (typeof input === 'string') {
  92. input = input.replace(`=${OLD_GROUP_ID}`, `=${FAKE_GROUP_ID}`);
  93. if (input.includes(FAKE_API_URL)) {
  94. return new Response(JSON.stringify(FAKE_RESPONSE), {
  95. status: 200,
  96. headers: { 'Content-Type': 'application/json' }
  97. });
  98. }
  99. titlechange();
  100. if (input.includes(PUBLISH_API_URL) &&
  101. init.method?.toUpperCase() === 'POST' &&
  102. init.headers?.['Content-Type']?.includes('application/x-www-form-urlencoded') &&
  103. typeof init.body === 'string') {
  104. init.body = init.body.replace(`group_id=${OLD_GROUP_ID}`, `group_id=${FAKE_GROUP_ID}`);
  105. }
  106. }
  107.  
  108. return originalFetch.call(this, input, init);
  109. };
  110.  
  111. const originalXHROpen = XMLHttpRequest.prototype.open;
  112. const originalXHRSend = XMLHttpRequest.prototype.send;
  113.  
  114. XMLHttpRequest.prototype.open = function (method, url) {
  115. this._method = method;
  116. this._originalUrl = url;
  117. this._isTarget = url.includes(FAKE_API_URL);
  118. const newUrl = url.replace(`=${OLD_GROUP_ID}`, `=${FAKE_GROUP_ID}`);
  119. return originalXHROpen.call(this, method, newUrl);
  120. };
  121.  
  122. XMLHttpRequest.prototype.send = async function (body) {
  123. if (this._isTarget) {
  124. this.addEventListener('readystatechange', async function () {
  125. if (this.readyState === 4) {
  126. Object.defineProperty(this, 'responseText', {
  127. get: () => JSON.stringify(FAKE_RESPONSE)
  128. });
  129. Object.defineProperty(this, 'response', {
  130. get: () => JSON.stringify(FAKE_RESPONSE)
  131. });
  132. }
  133. });
  134. if (this._isPublish && this._method.toUpperCase() === 'POST' && typeof body === 'string') {
  135. body = body.replace(`group_id=${OLD_GROUP_ID}`, `group_id=${FAKE_GROUP_ID}`);
  136. }
  137. await new Promise(resolve => setTimeout(resolve, 0));
  138. }
  139. return originalXHRSend.call(this, body);
  140. };
  141.  
  142. // 修改banner
  143. function loadStyle(css) {
  144. const style = document.createElement('style');
  145. style.type = 'text/css';
  146. style.rel = 'stylesheet';
  147. style.appendChild(document.createTextNode(css));
  148. document.head.appendChild(style);
  149. }
  150.  
  151. loadStyle(css);
  152.  
  153. // window.addEventListener('load', () => {
  154. // setTimeout(() => {
  155. // titlechange();
  156. // }, 1500);
  157. // });
  158.  
  159. })();