🏠 Home 

CSDN娱乐脚本

修改CSDN博客数据,仅供娱乐使用!


安装此脚本?
  1. // ==UserScript==
  2. // @name CSDN娱乐脚本
  3. // @namespace http://tampermonkey.net/
  4. // @match https://mp.csdn.net/mp_blog/analysis/article/*
  5. // @grant unsafeWindow
  6. // @run-at document-start
  7. // @version 1.0
  8. // @license MIT
  9. // @author Berger
  10. // @require https://registry.npmmirror.com/sweetalert2/10.16.6/files/dist/sweetalert2.min.js
  11. // @require https://registry.npmmirror.com/hotkeys-js/3.13.3/files/dist/hotkeys.min.js
  12. // @resource style https://registry.npmmirror.com/sweetalert2/10.16.6/files/dist/sweetalert2.min.css
  13. // @description 修改CSDN博客数据,仅供娱乐使用!
  14. // @grant GM_registerMenuCommand
  15. // @grant GM_getValue
  16. // @grant GM_setValue
  17. // ==/UserScript==
  18. (function () {
  19. 'use strict';
  20. const utils = {
  21. responseInterceptors(hijackUrl, functions) {
  22. // 保存原始的 open 和 send 方法
  23. const originalOpen = XMLHttpRequest.prototype.open;
  24. const originalSend = XMLHttpRequest.prototype.send;
  25. // 重写 XMLHttpRequest 的 open 方法
  26. XMLHttpRequest.prototype.open = function (method, url, async, user, password) {
  27. // 将请求的 URL 和方法存储在当前实例中
  28. this._url = url;
  29. this._method = method;
  30. // 检查 URL 是否包含要劫持的 URL
  31. if (url.includes(hijackUrl)) {
  32. // 添加状态变化的事件监听器
  33. this.addEventListener('readystatechange', function () {
  34. // 当请求完成时(readyState === 4)
  35. if (this.readyState === 4) {
  36. try {
  37. // 解析响应文本为 JSON 对象
  38. const res = JSON.parse(this.responseText);
  39. // 调用提供的函数进行响应修改
  40. const modifiedResponse = functions(res);
  41. // 使 responseText 属性可写,并进行修改
  42. Object.defineProperty(this, "responseText", {
  43. writable: true,
  44. configurable: true, // 使属性可配置
  45. });
  46. // 将修改后的响应文本赋值给 responseText
  47. this.responseText = modifiedResponse;
  48. } catch (error) {
  49. // 处理 JSON 解析错误
  50. console.error("Error parsing response:", error);
  51. }
  52. }
  53. });
  54. }
  55. // 调用原始的 open 方法
  56. originalOpen.call(this, method, url, async, user, password);
  57. };
  58. // 重写 XMLHttpRequest 的 send 方法
  59. XMLHttpRequest.prototype.send = function (body) {
  60. // 调用原始的 send 方法
  61. originalSend.call(this, body);
  62. };
  63. },
  64. getValue(name) {
  65. return GM_getValue(name);
  66. },
  67. setValue(name, value) {
  68. return GM_setValue(name, value);
  69. },
  70. };
  71. const responseContentModify = {
  72. modifyBlogStatics(response) {
  73. const blogStaticsData = utils.getValue("blogStatics")
  74. if (blogStaticsData.article) {
  75. //文章总数
  76. response['data'][0]['num'] = blogStaticsData.article
  77. }
  78. if (blogStaticsData.fans) {
  79. //粉丝数
  80. response['data'][1]['num'] = blogStaticsData.fans
  81. }
  82. if (blogStaticsData.digg) {
  83. //点赞数
  84. response['data'][2]['num'] = blogStaticsData.digg
  85. }
  86. if (blogStaticsData.comment) {
  87. //评论数
  88. response['data'][3]['num'] = blogStaticsData.comment
  89. }
  90. if (blogStaticsData.view) {
  91. //阅读量
  92. response['data'][4]['num'] = blogStaticsData.view
  93. }
  94. if (blogStaticsData.score) {
  95. //积分
  96. response['data'][5]['num'] = blogStaticsData.score
  97. }
  98. if (blogStaticsData.rank) {
  99. //总排名
  100. response['data'][6]['num'] = blogStaticsData.rank
  101. }
  102. if (blogStaticsData.collect) {
  103. //收藏数
  104. response['data'][7]['num'] = blogStaticsData.collect
  105. }
  106. return response
  107. }
  108. }
  109. function hijackBlogStatics() {
  110. // 博客数据请求接口
  111. const blogStaticsUrl = 'https://bizapi.csdn.net/blog/phoenix/console/v1/data/blog-statistics'
  112. utils.responseInterceptors(blogStaticsUrl, responseContentModify.modifyBlogStatics)
  113. }
  114. function registerMenuCommand() {
  115. GM_registerMenuCommand('⚙️ 配置博客数据', () => {
  116. main.showBlogStaticsSettingBox()
  117. });
  118. }
  119. let main = {
  120. init() {
  121. hijackBlogStatics()
  122. registerMenuCommand()
  123. },
  124. // 博客数据配置
  125. showBlogStaticsSettingBox() {
  126. const blogStaticsData = utils.getValue("blogStatics")
  127. console.log(blogStaticsData)
  128. Swal.fire({
  129. title: '博客数据配置',
  130. html:
  131. '<span>文章总数</span><input id="article" class="swal2-input" placeholder="文章总数" value="' + (blogStaticsData == null || undefined ? '' : blogStaticsData.article) + '">' +
  132. '<span>粉丝数</span><input id="fans" class="swal2-input" placeholder="粉丝数" value="' + (blogStaticsData == null || undefined ? '' : blogStaticsData.fans) + '">' +
  133. '<span>点赞数</span><input id="digg" class="swal2-input" placeholder="点赞数" value="' + (blogStaticsData == null || undefined ? '' : blogStaticsData.digg) + '">' +
  134. '<span>评论数</span><input id="comment" class="swal2-input" placeholder="评论数" value="' + (blogStaticsData == null || undefined ? '' : blogStaticsData.comment) + '">' +
  135. '<span>阅读量</span><input id="view" class="swal2-input" placeholder="阅读量" value="' + (blogStaticsData == null || undefined ? '' : blogStaticsData.view) + '">' +
  136. '<span>积分</span><input id="score" class="swal2-input" placeholder="积分" value="' + (blogStaticsData == null || undefined ? '' : blogStaticsData.score) + '">' +
  137. '<span>总排名</span><input id="rank" class="swal2-input" placeholder="总排名" value="' + (blogStaticsData == null || undefined ? '' : blogStaticsData.rank) + '">' +
  138. '<span>收藏数</span><input id="collect" class="swal2-input" placeholder="收藏数" value="' + (blogStaticsData == null || undefined ? '' : blogStaticsData.collect) + '">',
  139. focusConfirm: false,
  140. showDenyButton: true,
  141. confirmButtonText: '保存数据到本地',
  142. denyButtonText: '清除本地信息',
  143. footer: 'tips:未填写的信息不会被修改',
  144. preConfirm: () => {
  145. const articleNum = Swal.getPopup().querySelector('#article').value;
  146. const fansNum = Swal.getPopup().querySelector('#fans').value;
  147. const diggNum = Swal.getPopup().querySelector('#digg').value;
  148. const commentNum = Swal.getPopup().querySelector('#comment').value;
  149. const viewNum = Swal.getPopup().querySelector('#view').value;
  150. const scoreNum = Swal.getPopup().querySelector('#score').value;
  151. const rankNum = Swal.getPopup().querySelector('#rank').value;
  152. const collectNum = Swal.getPopup().querySelector('#collect').value;
  153. const inputs = [
  154. articleNum,
  155. fansNum,
  156. diggNum,
  157. commentNum,
  158. viewNum,
  159. scoreNum,
  160. rankNum,
  161. collectNum
  162. ];
  163. for (let input of inputs) {
  164. const num = Number(input);
  165. if (!Number.isInteger(num) || num < 0) {
  166. return Swal.fire({
  167. icon: 'error',
  168. title: '输入错误',
  169. text: '数据必须是大于等于的整数',
  170. });
  171. }
  172. }
  173. return {articleNum, fansNum, diggNum, commentNum, viewNum, scoreNum, rankNum, collectNum}
  174. }
  175. }).then((result) => {
  176. const {articleNum, fansNum, diggNum, commentNum, viewNum, scoreNum, rankNum, collectNum} = result.value;
  177. if (result.isConfirmed) {
  178. // 保存信息
  179. const blogStaticsData = {
  180. article: articleNum,
  181. fans: fansNum,
  182. digg: diggNum,
  183. comment: commentNum,
  184. view: viewNum,
  185. score: scoreNum,
  186. rank: rankNum,
  187. collect: collectNum,
  188. }
  189. utils.setValue("blogStatics", blogStaticsData);
  190. // 提示
  191. Swal.fire({
  192. icon: "success",
  193. title: "保存成功!",
  194. showConfirmButton: false,
  195. timer: 1300
  196. }).then(()=>location.reload());
  197. }
  198. if (result.isDenied) {
  199. utils.setValue("blogStatics", null)
  200. Swal.fire({
  201. icon: "success",
  202. title: "博客数据已清除!",
  203. showConfirmButton: false,
  204. timer: 1300
  205. }).then(()=>location.reload());
  206. }
  207. });
  208. },
  209. }
  210. window.addEventListener('DOMContentLoaded', main.init);
  211. })();