Sleazy Fork is available in English.

福利吧论坛 - 好孩子看得见

好孩子才看得见,论坛小助手

  1. // ==UserScript==
  2. // @name 福利吧论坛 - 好孩子看得见
  3. // @name:zh-TW 福利吧論壇 - 好孩子看得見
  4. // @namespace https://greasyfork.org/zh-CN/users/193133-pana
  5. // @homepage https://greasyfork.org/zh-CN/users/193133-pana
  6. // @version 9.4.3
  7. // @description 好孩子才看得见,论坛小助手
  8. // @description:zh-TW 好孩子才看得見,論壇小助手
  9. // @author pana
  10. // @include /www.wnflb\d*.com/
  11. // @require https://cdn.bootcss.com/crypto-js/4.0.0/core.min.js
  12. // @require https://cdn.bootcss.com/crypto-js/4.0.0/enc-base64.min.js
  13. // @require https://gcore.jsdelivr.net/npm/arrive@2.4.1/minified/arrive.min.js
  14. // @require https://greasyfork.org/scripts/403716-gm-config-cn/code/GM_config_CN.js
  15. // @connect pan.baidu.com
  16. // @connect keyfc.net
  17. // @grant GM_info
  18. // @grant GM_setClipboard
  19. // @grant GM_getValue
  20. // @grant GM_setValue
  21. // @grant GM_registerMenuCommand
  22. // @grant GM_xmlhttpRequest
  23. // @grant GM_addStyle
  24. // @run-at document-start
  25. // @noframes
  26. // @license GNU General Public License v3.0 or later
  27. // @note 注意: 9.0.0 以前的版本的配置不兼容新版本,若之前改动过默认设置,请升级后重新设置一遍
  28. // ==/UserScript==
  29.  
  30. (function () {
  31. 'use strict';
  32. if (typeof GM_config == 'undefined') {
  33. console.error('福利吧论坛 - 好孩子看得见:\nGM_config 库文件加载失败,脚本无法正常工作,请尝试刷新网页以重新加载。');
  34. } else if (typeof document.arrive == 'undefined') {
  35. console.error('福利吧论坛 - 好孩子看得见:\narrive 库文件加载失败,脚本可能无法正常工作,请尝试刷新网页以重新加载。');
  36. } else if (typeof CryptoJS == 'undefined') {
  37. console.warn('福利吧论坛 - 好孩子看得见:\nCryptoJS 库文件加载失败,BASE64 编解码功能无法使用。');
  38. } else {
  39. console.debug('福利吧论坛 - 好孩子看得见:\n脚本工作环境正常。');
  40. }
  41. const icon = {
  42. settings: 'url(https://cdn.jsdelivr.net/gh/LightAPIs/PicGoImg@master/img/settings.svg)',
  43. codeGray: 'url(https://cdn.jsdelivr.net/gh/LightAPIs/PicGoImg@master/img/code_gray.svg)',
  44. codeBlue: 'url(https://cdn.jsdelivr.net/gh/LightAPIs/PicGoImg@master/img/code_blue.svg)',
  45. modeNight: 'url(https://cdn.jsdelivr.net/gh/LightAPIs/PicGoImg@master/img/mode_night.svg)',
  46. modeDay: 'url(https://cdn.jsdelivr.net/gh/LightAPIs/PicGoImg@master/img/mode_day.svg)',
  47. signatureAdd: 'url(https://cdn.jsdelivr.net/gh/LightAPIs/PicGoImg@master/img/signature_add.svg)',
  48. signatureMinus: 'url(https://cdn.jsdelivr.net/gh/LightAPIs/PicGoImg@master/img/signature_minus.svg)',
  49. collapsedYes: 'static/image/common/collapsed_yes.gif',
  50. collapsedNo: 'static/image/common/collapsed_no.gif',
  51. };
  52. const style = {
  53. settings: `
  54. #myGoodBoyConfig input, #myGoodBoyConfig button {
  55. cursor: pointer;
  56. }
  57. #myGoodBoyConfig .reset_holder {
  58. float: left;
  59. position: relative;
  60. bottom: -3vh;
  61. }
  62. #myGoodBoyConfig .section_header a {
  63. color: #F5F9FB;
  64. text-decoration: none;
  65. }
  66. `,
  67. codePanel: `
  68. #myCodePanel input, #myCodePanel button {
  69. cursor: pointer;
  70. }
  71. #myCodePanel_bjxEncodeBtn_var, #myCodePanel_bjxDecodeBtn_var,
  72. #myCodePanel_coreValuesEncodeBtn_var, #myCodePanel_coreValuesDecodeBtn_var,
  73. #myCodePanel_yflcEncodeBtn_var, #myCodePanel_yflcDecodeBtn_var,
  74. #myCodePanel_base64EncodeBtn_var, #myCodePanel_base64DecodeBtn_var,
  75. #myCodePanel_baiduQueryBtn_var {
  76. display: inline;
  77. }
  78. #myCodePanel {
  79. width: 600px !important;
  80. height: 430px !important;
  81. }
  82. #myCodePanel .reset_holder {
  83. float: left;
  84. position: relative;
  85. bottom: -1vh;
  86. }
  87. #myCodePanel .nav-tabs {
  88. text-align: center;
  89. }
  90. #myCodePanel .nav-tabs > div {
  91. padding: 5px 20px;
  92. }
  93. #myCodePanel #myCodePanel_saveBtn {
  94. display: none;
  95. }
  96. #myCodePanel #myCodePanel_resetLink {
  97. text-decoration: underline;
  98. }
  99. #myCodePanel textarea {
  100. width: 96%;
  101. }
  102. `,
  103. night: `
  104. html, body, .bm, .bdl, .bdl dt, .bdl dd.bdl_a a, .tb .a a, .pn, .fl .bm_h, .ct2_a, .ct3_a, .t_table, table.plhin {
  105. background-color: #282A36 !important;
  106. background-blend-mode: multiply;
  107. }
  108. .bdl dl.a, .tl .th, .tl .ts th, .tl .ts td, .pg a, .pg strong, .pgb a, .pg label, .bml .bm_h, #scrolltop a, .bmn, .bm_h, td.pls, .ad td.plc, div.exfm, .tb a, .tb_h, .ttp li.a a, div.uo a, input#addsubmit_btn, #gh .bm .bm_h, .jump_bdl li, .newthread tr th, .newthread tr td, .tl .threadpre td, .tl .threadpre:hover td, .nfl .f_c, #myCodePanel {
  109. background-color: #282A36 !important;
  110. }
  111. #nv, .card_gender_0, .card .o a, .tbn li.a, #p_btn a, #p_btn i {
  112. background: #40444D !important;
  113. }
  114. #toptb, .tedt .bar, .edt .bar, .edt .bbar, #post_extra_tb label.a, #extcreditmenu.a, #g_upmine.a, .tl #forumnewshow, .jump_bdl .a a, .jump_bdl .a a:hover, .psth, .pl .quote, .pm_tac, .pm .c, .pml .hover, #uhd, #flw_header .bar, .ttp a, .ttp strong, .bmw .bm_h, .GzList ul li a, .m_c, .m_c .o, .dt th, .section_header_holder p, #fx_checkin_menu,#fx_checkin_menub, .pl .blockcode ol li:hover {
  115. background-color: #40444D !important;
  116. }
  117. #nv li a:hover, #nv li.hover a, #nv li.hover a:hover, #nv > a {
  118. background: #1A1A1A !important;
  119. background-blend-mode: multiply;
  120. }
  121. .p_pop, .p_pof, .sllt, .tl #forumnewshow a:hover, #autopbn:hover, .pgbtn a:hover, #hiddenpoststip {
  122. background-color: #1A1A1A !important;
  123. }
  124. #threadlist > div > table > tbody > tr:hover > *, #threadlist > div > form > table > tbody > tr:not(.threadpre):hover > *, div.tl > form > table > tbody > tr:hover > * {
  125. background-color: #1A1A1A !important;
  126. }
  127. .p_pop a:hover {
  128. background: #3D3D3D !important;
  129. }
  130. a, #um, #um a, body, input, button, select, textarea, .xi2, .xi2 a, .pg a, .pg strong, .pgb a, .pg label, .jump_bdl a, div#forum_rules_37 font {
  131. color: #C0C0C0 !important;
  132. }
  133. .tps a, .chart em {
  134. color: #666 !important;
  135. }
  136. .GzList ul li a {
  137. color: #000 !important !important;
  138. }
  139. .tedt .pt, .px, .pt, .ps, select, input,
  140. #myCodePanel textarea, #myCodePanel button
  141. {
  142. background-color: #38383D !important;
  143. }
  144. .pl .blockcode {
  145. background: #38383D !important;
  146. }
  147. ul.cl.nav li a, ul.cl.nav li a:hover {
  148. background-repeat: no-repeat !important;
  149. background-position: 50% 5px !important;
  150. }
  151. #fastpostsmilie_88_td, #fx_checkin_topb, #hd h2 a,#newspecial, #newspecialtmp, #post_reply, #post_replytmp, .ico_fall, .ico_increase, .o img, fieldset legend, div.ac1 {
  152. mix-blend-mode: multiply;
  153. }
  154. .p_pop a, .tl #forumnewshow a {
  155. filter: brightness(.7);
  156. }
  157. #category_36 tbody td p>a, .bm_c tbody h2>a, .common font, .fl .bm_h h2 a, .tl th a, .xw0.xi1, .y.xg1 font {
  158. mix-blend-mode: color-dodge;
  159. }
  160. .ignore_notice {
  161. right: -3px !important;
  162. top: -53px !important;
  163. }
  164. .tps a:hover {
  165. background-color: #C0C0C0 !important;
  166. }
  167. `,
  168. basic: `
  169. .my_good_boy_div_float {
  170. position: absolute;
  171. max-width: 430px;
  172. padding-left: 20px;
  173. padding-right: 10px;
  174. margin-left: 962px;
  175. margin-top: -170px;
  176. border: 2px solid #CDCDCD;
  177. border-radius: 8px;
  178. }
  179. .my_good_boy_div_basic {
  180. margin-top: 10px;
  181. }
  182. .my_good_boy_p {
  183. color: red;
  184. font-size: 15px;
  185. }
  186. .my_good_boy_p_float {
  187. margin-left: 0px !important;
  188. }
  189. .my_good_boy_li {
  190. list-style-type: disc;
  191. white-space: nowrap;
  192. }
  193. .my_good_boy_a {
  194. display: inline;
  195. font-size: 15px;
  196. white-space: nowrap;
  197. }
  198. .my_good_boy_a_copy {
  199. display: inline-block;
  200. font-size: 15px;
  201. margin-left: 20px;
  202. text-decoration: underline;
  203. }
  204. .a_copy_completed {
  205. color: #F60 !important;
  206. }
  207. .link_faild {
  208. color: #999 !important;
  209. text-decoration: line-through !important;
  210. }
  211. .show_more_link {
  212. text-decoration: underline;
  213. }
  214. #settingsIcon {
  215. display: block;
  216. float: right;
  217. cursor: pointer;
  218. margin-top: 5px;
  219. width: 23px;
  220. height: 18px;
  221. background-image: ${icon.settings};
  222. background-repeat: no-repeat;
  223. background-size: 16px auto;
  224. background-position: center;
  225. }
  226. .expand_box {
  227. bottom: 0px;
  228. height: 60px;
  229. position: fixed;
  230. right: -6vw;
  231. transition: 0.5s;
  232. width: 12vw;
  233. z-index: 999;
  234. }
  235. .expand_box_h {
  236. bottom: 0px;
  237. height: 120px;
  238. position: fixed;
  239. right: -6vw;
  240. transition: 0.5s;
  241. width: 12vw;
  242. z-index: 999;
  243. }
  244. .show_expand_box {
  245. right: 0;
  246. width: 6vw;
  247. }
  248. #myCodeSpan {
  249. background-image: ${icon.codeGray};
  250. background-repeat: no-repeat;
  251. background-size: 32px auto;
  252. background-position: center;
  253. background-color: #787878;
  254. border-radius: 19px;
  255. border: 1px solid #787878;
  256. bottom: 10px;
  257. color: #FFF;
  258. cursor: pointer;
  259. display: block;
  260. font-size: 13px;
  261. height: 38px;
  262. line-height: 38px;
  263. position: absolute;
  264. right: 1vw;
  265. text-align: center;
  266. width: 38px;
  267. z-index: 999;
  268. }
  269. #myCodeSpan:hover {
  270. box-shadow: 0 0 5px green;
  271. background-image: ${icon.codeBlue};
  272. }
  273. #myNightSpan {
  274. background-repeat: no-repeat;
  275. background-size: 32px auto;
  276. background-position: center;
  277. background-color: #00A1D6;
  278. border-radius: 19px;
  279. border: 1px solid #00A1D6;
  280. bottom: 10px;
  281. color: #FFF;
  282. cursor: pointer;
  283. display: block;
  284. font-size: 13px;
  285. height: 38px;
  286. line-height: 38px;
  287. position: absolute;
  288. right: 1vw;
  289. text-align: center;
  290. width: 38px;
  291. z-index: 999;
  292. }
  293. #myNightSpan_2 {
  294. background-repeat: no-repeat;
  295. background-size: 32px auto;
  296. background-position: center;
  297. background-color: #00A1D6;
  298. border-radius: 19px;
  299. border: 1px solid #00A1D6;
  300. bottom: 60px;
  301. color: #FFF;
  302. cursor: pointer;
  303. display: block;
  304. font-size: 13px;
  305. height: 38px;
  306. line-height: 38px;
  307. position: absolute;
  308. right: 1vw;
  309. text-align: center;
  310. width: 38px;
  311. z-index: 999;
  312. }
  313. #myNightSpan:hover, #myNightSpan_2:hover {
  314. box-shadow: 0 0 5px green;
  315. }
  316. .collapsed_hide {
  317. display: none;
  318. }
  319. .signature_switch_div {
  320. width: 16px;
  321. height: 16px;
  322. display: block;
  323. position: relative;
  324. top: -5px;
  325. cursor: pointer;
  326. background-image: ${icon.signatureMinus};
  327. background-size: 16px auto;
  328. background-repeat: no-repeat;
  329. background-position: center;
  330. }
  331. .signature_switch_close {
  332. background-image: ${icon.signatureAdd};
  333. }
  334. .signature_hide {
  335. display: none;
  336. }
  337. `,
  338. };
  339. const reg = {
  340. url: /^[\S\s]*?(magnet:\?xt=urn:btih:(?:[a-z0-9]{40}|[a-z0-9]{32})|ftp:\/\/\S*|ed2k:\/\/\S*|thunder:\/\/\S*|flashget:\/\/\S*|qqdl:\/\/\S*|xfplay:\/\/\S*|https?:\/\/[\w零一二三四五六七八九壹贰叁肆伍陆柒捌玖-]*\.?[\w零一二三四五六七八九壹贰叁肆伍陆柒捌玖-]+\.+\w+\S*)/i,
  341. download: /^[\S\s]*?(magnet:\?xt=urn:btih:(?:[a-z0-9]{40}|[a-z0-9]{32})|ed2k:\/\/\S*|thunder:\/\/\S*)/i,
  342. www: /^[\S\s]*?(www\.[\w-]+\.[a-z]+[\w#=%+?/-]*)/i,
  343. baidupan: /^https?:\/\/pan\.baidu\.com\/s(?:hare)?\/[\w=?&-]+$/i,
  344. baidupanIncludeCode: /^https?:\/\/pan\.baidu\.com\/s(?:hare)?\/[\w=?#&-]+$/i,
  345. code: /(?:提取)+[^a-z0-9解压]*([a-z0-9]{4})[^a-z0-9]*/i,
  346. baidupanCode: /^(?:(?:下载)?链接\S+\s+)?(?:[^解压]+\s+)?[^a-z0-9解压]*([a-z0-9]{4})[^a-z0-9]*(?:app)?[^a-z0-9]*$/i,
  347. singleCharCode: /^[a-z0-9]$/i,
  348. missingHeaderBaidupan: /^[\S\s]*?[^/\w-]?((?<!xunlei\.com\/)s(?:hare)?\/[\w=?-]{10,50})/i,
  349. missingHeaderBaidupanTest: /^([\w=?-]{15,50})\s+[a-z0-9]{4}$/i,
  350. pan: /^[\S\s]*?(pan\.(?:baidu|xunlei|lanzou)\.com\/?s?(?:hare)?\/[\w=?&-]+)/i,
  351. hash: /(?:[^a-z0-9]|^)([a-z0-9]{40}|[a-z0-9]{32})(?:&dn=.*|[^a-z0-9]|$)/i,
  352. md5: /(?:md5[^a-z0-9]+|sha1[^a-z0-9]+)/i,
  353. core: /^.*?((?:富强|民主|文明|和谐|自由|平等|公正|法治|爱国|敬业|诚信|友善){10,}).*?$/i,
  354. baijia:
  355. /^.*?([赵钱孙李周吴郑王冯陈褚卫蒋沈韩杨朱秦尤许何吕施张孔曹严华金魏陶姜戚谢邹喻福水窦章云苏潘葛奚范彭郎鲁韦昌马苗凤花方俞任袁柳唐罗薛伍余米贝姚孟顾尹江钟]{10,}).*?$/i,
  356. foyu: /^.*?((?:佛曰:|如是我闻:)\S{10,}).*?$/i,
  357. prefixLinkMagnet: /^https?:\/\/www\.wnflb\d*\.com\/magnet:\?xt=.*$/i,
  358. prefixLinkMagnetReplace: /^https?:\/\/www\.wnflb\d*\.com\//i,
  359. prefixCode: /^https?:\/\/www\.wnflb\d*\.com\/(\w+-\w+$|chrome-extension:\/\/)/i,
  360. prefixHash: /^https?:\/\/www\.wnflb\d*\.com\/([a-z0-9]{40}|[a-z0-9]{32})$/i,
  361. prefixUrl: /^https?:\/\/www\.wnflb\d*\.com\/(www\..*$|.*\.(?:com|net|cn|org|site|info|edu|gov)$)/i,
  362. redircdn: /^https?:\/\/to\.redircdn\.com\/\?(.*)&z$/i,
  363. prefixReplace: /^https?:\/\/www\.wnflb\d*\.com\//i,
  364. baseImage: /^https?:\/\/(data:)/i,
  365. };
  366. const filterReg = [
  367. /^https?:\/\/pan\.baidu\.com\/(?:s|share|mbox)?\/[\w#?%=/&-]*[^\w#?%=/&-]+/i,
  368. /^https?:\/\/www\.52pojie\.cn\/?#?$/i,
  369. /^https?:\/\/www\.52pojie\.cn\/(?:forum|home|misc)\.php\?/i,
  370. /^https?:\/\/www\.52pojie\.cn\/(?:forum|thread)-\d+-\d+(?:-\d+)?\.html$/i,
  371. /^https?:\/\/www\.wnflb\d*\.com\/?$/i,
  372. /^https?:\/\/www\.wnflb\d*\.com\/(?:home|forum)\.php\?/i,
  373. /^https?:\/\/www\.wnflb\d*\.com\/(?:thread|forum)-\d+-\d+(?:-\d+)?\.html$/i,
  374. /^https?:\/\/www\.imdb\.com\/title\//i,
  375. /^https?:\/\/movie\.douban\.com\/(?:subject|celebrity)/i,
  376. /^https?:\/\/photo\.weibo\.com\//i,
  377. /^https?:\/\/s\.weibo\.com\/weibo\?q=/i,
  378. /^https?:\/\/baike\.(?:so|baidu|sogou)\.com/i,
  379. /^https?:\/\/app\.bilibili\.com/i,
  380. /^https?:\/\/bbs\.zhiyoo\.com\/(?:forum|gforum)-\d+-\d+\.html/i,
  381. /^https?:\/\/www\.3dmgame\.com\/tag\//i,
  382. /^https?:\/\/www\.3dmgame\.com\/games\/[^/]*\/?$/i,
  383. /^https?:\/\/www\.tv432\.com\/search\.php\?searchword=/i,
  384. /^https?:\/\/www\.viidii\.info\/\?/i,
  385. /^https?:\/\/www\.daybox\.net\/image\//i,
  386. /^https?:\/\/www\.yidianzixun\.com\/channel\//i,
  387. /^https?:\/\/[\w-]*\.?sina\.com\.cn\/?/i,
  388. /^https?:\/\/(?:www|post)\.smzdm\.com\/(?:fenlei|p)\//i,
  389. /^https?:\/\/laod\.cn\/tag\//i,
  390. /^https?:\/\/www\.smmimg\.com\/i\//i,
  391. ];
  392. const coreValues = '富强民主文明和谐自由平等公正法治爱国敬业诚信友善';
  393. const baijiaValues = {
  394. 赵: '0',
  395. 钱: '1',
  396. 孙: '2',
  397. 李: '3',
  398. 周: '4',
  399. 吴: '5',
  400. 郑: '6',
  401. 王: '7',
  402. 冯: '8',
  403. 陈: '9',
  404. 褚: 'a',
  405. 卫: 'b',
  406. 蒋: 'c',
  407. 沈: 'd',
  408. 韩: 'e',
  409. 杨: 'f',
  410. 朱: 'g',
  411. 秦: 'h',
  412. 尤: 'i',
  413. 许: 'j',
  414. 何: 'k',
  415. 吕: 'l',
  416. 施: 'm',
  417. 张: 'n',
  418. 孔: 'o',
  419. 曹: 'p',
  420. 严: 'q',
  421. 华: 'r',
  422. 金: 's',
  423. 魏: 't',
  424. 陶: 'u',
  425. 姜: 'v',
  426. 戚: 'w',
  427. 谢: 'x',
  428. 邹: 'y',
  429. 喻: 'z',
  430. 福: 'A',
  431. 水: 'B',
  432. 窦: 'C',
  433. 章: 'D',
  434. 云: 'E',
  435. 苏: 'F',
  436. 潘: 'G',
  437. 葛: 'H',
  438. 奚: 'I',
  439. 范: 'J',
  440. 彭: 'K',
  441. 郎: 'L',
  442. 鲁: 'M',
  443. 韦: 'N',
  444. 昌: 'O',
  445. 马: 'P',
  446. 苗: 'Q',
  447. 凤: 'R',
  448. 花: 'S',
  449. 方: 'T',
  450. 俞: 'U',
  451. 任: 'V',
  452. 袁: 'W',
  453. 柳: 'X',
  454. 唐: 'Y',
  455. 罗: 'Z',
  456. 薛: '.',
  457. 伍: '-',
  458. 余: '_',
  459. 米: '+',
  460. 贝: '=',
  461. 姚: '/',
  462. 孟: '?',
  463. 顾: '#',
  464. 尹: '%',
  465. 江: '&',
  466. 钟: '*',
  467. 高: ':',
  468. 田: '|',
  469. };
  470. const status = {
  471. nightEnable: GM_config.getValue('nightEnable', false),
  472. collapsedGwwzEnable: GM_config.getValue('collapsedGwwzEnable', false),
  473. accessNum: GM_config.getValue('accessNumber', 90),
  474. nightStyleDom: null,
  475. checkDate: GM_config.getValue('checkDate', '2000-1-1'),
  476. oldUrl: location.href,
  477. timer1: null,
  478. timer2: null,
  479. timer3: null,
  480. timer4: null,
  481. };
  482. class Good_Boy {
  483. constructor(config, linkArray = []) {
  484. this.config = config;
  485. this.floatEnable = this.isMobilePage() ? false : config.get('displayPosition') == '右侧';
  486. this.linkArray = linkArray;
  487. this.totalCount = linkArray.length;
  488. this.currentCount = 0;
  489. this.showMoreStatus = false;
  490. this.insertUlStatus = false;
  491. this.ulNode = document.createElement('ul');
  492. }
  493. insertLinkItem(linkArray = []) {
  494. this.linkArray = this.linkArray.concat(linkArray);
  495. this.totalCount = this.linkArray.length;
  496. if (this.currentCount < this.config.get('maxLinkNumber') || this.config.get('maxLinkNumber') < 0) {
  497. for (; this.currentCount < this.totalCount && this.currentCount != this.config.get('maxLinkNumber'); this.currentCount++) {
  498. const tempA = this.createLink(this.linkArray[this.currentCount]);
  499. tempA && this.ulNode.appendChild(tempA);
  500. }
  501. }
  502. if (this.config.get('maxLinkNumber') > -1 && this.totalCount > this.config.get('maxLinkNumber')) {
  503. this.ulNode.getElementsByTagName('p')[0].textContent =
  504. '[共提取到 ' + this.totalCount + ' 个链接,仅显示前 ' + this.config.get('maxLinkNumber') + ' 个]:';
  505. if (!this.showMoreStatus) {
  506. this.ulNode.appendChild(this.showMoreLink());
  507. this.showMoreStatus = true;
  508. }
  509. } else {
  510. this.ulNode.getElementsByTagName('p')[0].textContent = '[共提取到 ' + this.totalCount + ' 个链接]:';
  511. }
  512. }
  513. isMobilePage() {
  514. return /android|webos|iphone|ipod|blackberry/i.test(navigator.userAgent);
  515. }
  516. getCutLinkText(linkText) {
  517. if (this.isMobilePage()) {
  518. return linkText.length >= 35 ? linkText.slice(0, 15) + ' ... ' + linkText.slice(-10) : linkText;
  519. } else if (this.floatEnable) {
  520. return linkText.length >= 50 ? linkText.slice(0, 25) + ' ... ' + linkText.slice(-15) : linkText;
  521. }
  522. return linkText.length >= 80 ? linkText.slice(0, 45) + ' ... ' + linkText.slice(-25) : linkText;
  523. }
  524. managePrefixCode(inputLink) {
  525. const { prefixCode, prefixHash, prefixReplace, prefixUrl, redircdn } = reg;
  526. if (prefixCode.test(inputLink)) {
  527. return inputLink.replace(prefixReplace, '');
  528. } else if (prefixHash.test(inputLink)) {
  529. return inputLink.replace(prefixReplace, 'magnet:?xt=urn:btih:');
  530. } else if (prefixUrl.test(inputLink)) {
  531. return inputLink.replace(prefixReplace, 'http://');
  532. } else if (redircdn.test(inputLink)) {
  533. return inputLink.replace(redircdn, '$1').replace('______', '.');
  534. }
  535. return inputLink;
  536. }
  537. createLink(linkHref) {
  538. const { baidupanIncludeCode } = reg;
  539. if (linkHref.length > 2000) {
  540. return null;
  541. }
  542. const linkLi = document.createElement('li');
  543. linkLi.className = 'my_good_boy_li';
  544. const linkA = document.createElement('a');
  545. linkA.title = '点击访问';
  546. linkHref = this.managePrefixCode(linkHref);
  547. linkA.className = 'my_good_boy_a';
  548. linkA.href = encodeURI(linkHref);
  549. linkA.target = '_blank';
  550. linkA.textContent = this.getCutLinkText(linkHref);
  551. linkA.style.color = this.config.get('linkColor');
  552. linkLi.appendChild(linkA);
  553. if (this.config.get('copyEnable')) {
  554. const copyA = document.createElement('a');
  555. copyA.className = 'my_good_boy_a_copy';
  556. copyA.title = '复制链接';
  557. copyA.href = 'javascript:;';
  558. copyA.target = '_self';
  559. copyA.textContent = '复制';
  560. copyA.style.color = this.config.get('linkColor');
  561. copyA.addEventListener('click', function () {
  562. GM_setClipboard(linkHref, 'text');
  563. this.classList.add('a_copy_completed');
  564. this.title = '复制成功';
  565. status.timer1 && clearTimeout(status.timer1);
  566. status.timer1 = setTimeout(() => {
  567. this.classList.remove('a_copy_completed');
  568. this.title = '复制链接';
  569. }, 2000);
  570. });
  571. linkLi.appendChild(copyA);
  572. if (baidupanIncludeCode.test(linkHref) && /(?:#|\?pwd=)[a-z0-9]{4}$/i.test(linkHref)) {
  573. const codeValue = /#([a-z0-9]{4})$/i.exec(linkHref)[1];
  574. const codeCopyA = document.createElement('a');
  575. codeCopyA.className = 'my_good_boy_a_copy';
  576. codeCopyA.title = '复制提取码';
  577. codeCopyA.href = 'javascript:;';
  578. codeCopyA.target = '_self';
  579. codeCopyA.textContent = '复制提取码';
  580. codeCopyA.style.color = this.config.get('linkColor');
  581. codeCopyA.addEventListener('click', function () {
  582. GM_setClipboard(codeValue, 'text');
  583. this.classList.add('a_copy_completed');
  584. this.title = '复制成功';
  585. status.timer2 && clearTimeout(status.timer2);
  586. status.timer2 = setTimeout(() => {
  587. this.classList.remove('a_copy_completed');
  588. this.title = '复制提取码';
  589. }, 2000);
  590. });
  591. linkLi.appendChild(codeCopyA);
  592. }
  593. }
  594. this.config.get('checkEnable') && baidupanIncludeCode.test(linkHref) && this.checkBaidupan(linkHref, linkA);
  595. return linkLi;
  596. }
  597. showMoreLink() {
  598. const linkLi = document.createElement('li');
  599. linkLi.className = 'my_good_boy_li';
  600. const linkA = document.createElement('a');
  601. linkA.className = 'my_good_boy_a show_more_link';
  602. linkA.href = 'javascript:;';
  603. linkA.title = '显示全部提取链接';
  604. linkA.textContent = '显示全部';
  605. linkA.target = '_self';
  606. linkA.style.color = this.config.get('linkColor');
  607. linkA.addEventListener(
  608. 'click',
  609. () => {
  610. this.ulNode.removeChild(linkLi);
  611. for (; this.currentCount < this.totalCount; this.currentCount++) {
  612. const tempA = this.createLink(this.linkArray[this.currentCount]);
  613. tempA && this.ulNode.appendChild(tempA);
  614. }
  615. this.ulNode.getElementsByTagName('p')[0].textContent = '[共提取到 ' + this.totalCount + ' 个链接]:';
  616. this.showMoreStatus = false;
  617. },
  618. false
  619. );
  620. linkLi.appendChild(linkA);
  621. return linkLi;
  622. }
  623. createGoodBoyFrame(container, linkArray = []) {
  624. if (this.insertUlStatus) {
  625. this.insertLinkItem(linkArray);
  626. } else {
  627. const goodBoyDiv = document.createElement('div');
  628. goodBoyDiv.className = this.floatEnable ? 'my_good_boy_div_float' : 'my_good_boy_div_basic';
  629. const goodBoyP = document.createElement('p');
  630. goodBoyP.className = this.floatEnable ? 'my_good_boy_p my_good_boy_p_float' : 'my_good_boy_p';
  631. this.ulNode.appendChild(goodBoyP);
  632. this.insertLinkItem(linkArray);
  633. goodBoyDiv.appendChild(this.ulNode);
  634. container.appendChild(goodBoyDiv);
  635. this.insertUlStatus = true;
  636. }
  637. }
  638. createGoodBoyElement(container, linkObj, textObj, nodeTextArray) {
  639. const backLinkArray = this.autoEvent(
  640. container,
  641. linkObj.linkObjArray,
  642. linkObj.baiduObjArray,
  643. linkObj.linksArray,
  644. textObj.hideTextArray,
  645. textObj.showTextArray,
  646. nodeTextArray
  647. );
  648. backLinkArray.length > 0 && this.createGoodBoyFrame(container, backLinkArray);
  649. }
  650. managePrefix(inputLinkArray) {
  651. const { prefixLinkMagnet, prefixLinkMagnetReplace } = reg;
  652. const returnLinkArray = [];
  653. inputLinkArray.forEach(item => {
  654. returnLinkArray.push(prefixLinkMagnet.test(item) ? item.replace(prefixLinkMagnetReplace, '') : item);
  655. });
  656. return returnLinkArray;
  657. }
  658. pickUpMagnet(item) {
  659. const { url, download, hash, md5 } = reg;
  660. let tempLink = '';
  661. const item1 = item.replace(/[^a-z0-9:=?/\\.&%|-]/gi, '');
  662. if (download.test(item1)) {
  663. tempLink = download.exec(item1)[1];
  664. } else {
  665. const item2 = item.replace(/[^a-z0-9:=?/\\.,,。|\s+-]/gi, '');
  666. if (!md5.test(item2) && hash.test(item2) && !url.test(item2)) {
  667. const tempHash = hash.exec(item2)[1];
  668. if (!/^(?:[a-z]+|[0-9]+)$/i.test(tempHash)) {
  669. tempLink = 'magnet:?xt=urn:btih:' + tempHash;
  670. }
  671. }
  672. }
  673. return tempLink;
  674. }
  675. manageText(textArray) {
  676. const { url, download, www, missingHeaderBaidupan, missingHeaderBaidupanTest, pan, hash, md5 } = reg;
  677. const tempArray = [];
  678. textArray.forEach(item => {
  679. let tempLink = '';
  680. if (pan.test(item)) {
  681. tempLink = 'https://' + pan.exec(item)[1];
  682. } else if (/magnet:|ed2k:|thunder:/i.test(item)) {
  683. if (download.test(item)) {
  684. tempLink = download.exec(item)[1];
  685. }
  686. } else if (url.test(item)) {
  687. tempLink = url.exec(item)[1];
  688. } else if (www.test(item)) {
  689. tempLink = 'http://' + www.exec(item)[1];
  690. } else if (missingHeaderBaidupan.test(item)) {
  691. const linkMissValue = missingHeaderBaidupan.exec(item)[1];
  692. tempLink = /^\//i.test(linkMissValue) ? 'https://pan.baidu.com' + linkMissValue : 'https://pan.baidu.com/' + linkMissValue;
  693. } else if (missingHeaderBaidupanTest.test(item)) {
  694. tempLink = 'https://pan.baidu.com/s/' + missingHeaderBaidupanTest.exec(item)[1];
  695. } else if (!md5.test(item) && hash.test(item)) {
  696. tempLink = 'magnet:?xt=urn:btih:' + hash.exec(item)[1];
  697. } else if (item.length > 32) {
  698. tempLink = this.pickUpMagnet(item);
  699. }
  700. filterLink(tempLink) && tempArray.push(tempLink);
  701. });
  702. return this.managePrefix(tempArray);
  703. }
  704. decodeLink(inputLinkArray) {
  705. const { url } = reg;
  706. inputLinkArray.forEach((item, index) => {
  707. if (url.test(item)) {
  708. inputLinkArray[index] = decodeURI(item);
  709. }
  710. });
  711. return inputLinkArray;
  712. }
  713. pickUpBaidupanCode(textArray) {
  714. const { code, baidupanCode, singleCharCode } = reg;
  715. const codeArray = [];
  716. const charArray = [];
  717. textArray.forEach(item => {
  718. let tempValue = '';
  719. if (code.test(item)) {
  720. tempValue = code.exec(item)[1];
  721. } else if (baidupanCode.test(item)) {
  722. tempValue = baidupanCode.exec(item)[1];
  723. } else if (singleCharCode.test(item)) {
  724. charArray.push(item);
  725. }
  726. if (tempValue && !/\d{4}/i.test(tempValue) && codeArray.indexOf(tempValue) === -1) {
  727. codeArray.push(tempValue);
  728. }
  729. });
  730. while (charArray.length > 0 && charArray.length % 4 === 0) {
  731. const tempCode = charArray.splice(0, 4);
  732. const charValue = tempCode.join('');
  733. if (!/\d{4}/i.test(charValue) && codeArray.indexOf(charValue) === -1) {
  734. codeArray.push(charValue);
  735. }
  736. }
  737. return codeArray;
  738. }
  739. manageRepeatArray(inputLinkArray) {
  740. const outputLinkArray = [];
  741. for (let i = 0, l = inputLinkArray.length; i < l; i++) {
  742. for (let j = i + 1; j < l; j++) {
  743. if (getPureLink(inputLinkArray[i]) === getPureLink(inputLinkArray[j])) {
  744. ++i;
  745. j = i;
  746. }
  747. }
  748. outputLinkArray.push(inputLinkArray[i]);
  749. }
  750. return outputLinkArray;
  751. }
  752. splitWrap(textArray) {
  753. let tempArray = [];
  754. textArray.forEach(text => {
  755. if (text) {
  756. tempArray = tempArray.concat(text.split('\n').filter(v => v));
  757. }
  758. });
  759. return tempArray;
  760. }
  761. autoEvent(container, linkObjArray, baiduObjArray, _linksArray, hideTextArray, showTextArray, nodeTextArray) {
  762. const { url, baidupan, hash, md5 } = reg;
  763. const linkArray = [];
  764. const linkTextArray = [];
  765. linkObjArray.forEach(item => {
  766. linkArray.push(item.eleValue);
  767. linkTextArray.push(item.eleContainer);
  768. });
  769. if (hideTextArray.length > 0) {
  770. hideTextArray = this.splitWrap(hideTextArray);
  771. }
  772. if (showTextArray.length > 0) {
  773. showTextArray = this.splitWrap(showTextArray);
  774. }
  775. if (nodeTextArray.length > 0) {
  776. nodeTextArray = this.splitWrap(nodeTextArray);
  777. }
  778. const concatTextArray = this.manageRepeatArray(this.decodeLink(hideTextArray));
  779. let concatLinkArray = this.manageRepeatArray(this.decodeLink(this.manageText(linkArray.concat(concatTextArray))));
  780. const generalTextArray = showTextArray.concat(nodeTextArray.concat(linkTextArray));
  781. const indexA = [];
  782. const codeB = this.pickUpBaidupanCode(concatTextArray);
  783. let codeC = [];
  784. if (codeB.length > 0) {
  785. for (let j = 0; j < concatLinkArray.length; j++) {
  786. if (baidupan.test(concatLinkArray[j])) {
  787. indexA.push(j);
  788. }
  789. }
  790. if (codeB.length === indexA.length) {
  791. for (let k = 0; k < indexA.length; k++) {
  792. if (!/\?pwd=/.test(concatLinkArray[indexA[k]])) {
  793. concatLinkArray[indexA[k]] += '?pwd=' + codeB[k];
  794. }
  795. }
  796. } else if (codeB.length === baiduObjArray.length) {
  797. for (let l = 0; l < baiduObjArray.length; l++) {
  798. if (!/\?pwd=/.test(baiduObjArray[l].ele.href)) {
  799. baiduObjArray[l].ele.textContent = baiduObjArray[l].eleContainer + '?pwd=' + codeB[l];
  800. baiduObjArray[l].ele.href = baiduObjArray[l].eleValue + '?pwd=' + codeB[l];
  801. }
  802. }
  803. }
  804. } else {
  805. codeC = this.pickUpBaidupanCode(generalTextArray);
  806. if (codeC.length > 0) {
  807. for (let j = 0; j < concatLinkArray.length; j++) {
  808. if (baidupan.test(concatLinkArray[j])) {
  809. indexA.push(j);
  810. }
  811. }
  812. if (codeC.length === indexA.length) {
  813. for (let k = 0; k < indexA.length; k++) {
  814. concatLinkArray[indexA[k]] += '?pwd=' + codeC[k];
  815. }
  816. } else if (codeC.length === baiduObjArray.length) {
  817. for (let l = 0; l < baiduObjArray.length; l++) {
  818. baiduObjArray[l].ele.textContent = baiduObjArray[l].eleContainer + '?pwd=' + codeC[l];
  819. baiduObjArray[l].ele.href = baiduObjArray[l].eleValue + '?pwd=' + codeC[l];
  820. }
  821. }
  822. }
  823. }
  824. let hashArray = [];
  825. generalTextArray.forEach(item => {
  826. if (!url.test(item)) {
  827. if (!md5.test(item) && hash.test(item)) {
  828. hashArray.push('magnet:?xt=urn:btih:' + hash.exec(item)[1]);
  829. } else if (item.length > 32) {
  830. let temp_link = this.pickUpMagnet(item);
  831. temp_link && hashArray.push(temp_link);
  832. }
  833. }
  834. });
  835. hashArray = this.decodeLink(hashArray);
  836. concatLinkArray = this.manageRepeatArray(concatLinkArray.concat(hashArray));
  837. if (this.config.get('checkEnable')) {
  838. for (let p of baiduObjArray) {
  839. this.checkBaidupan(p.eleValue, p.ele);
  840. }
  841. }
  842. const hideCodeTextArray = this.decodeCoreValues(container, hideTextArray.concat(generalTextArray));
  843. if (hideCodeTextArray.length > 0) {
  844. hideCodeTextArray.forEach((item, index) => {
  845. if (!url.test(item)) {
  846. if (!md5.test(item) && hash.test(item)) {
  847. hideCodeTextArray[index] = 'magnet:?xt=urn:btih:' + hash.exec(item)[1];
  848. } else if (item.length > 32) {
  849. const tempLink = this.pickUpMagnet(item);
  850. if (tempLink) {
  851. hideCodeTextArray[index] = tempLink;
  852. }
  853. }
  854. }
  855. });
  856. concatLinkArray = this.manageRepeatArray(concatLinkArray.concat(hideCodeTextArray));
  857. }
  858. concatLinkArray = concatLinkArray
  859. .map(item => {
  860. if (generalTextArray.includes(item)) {
  861. return null;
  862. }
  863. return item;
  864. })
  865. .filter(v => v);
  866. return concatLinkArray;
  867. }
  868. foyuPromise(encoded) {
  869. return new Promise(function (resolve, _reject) {
  870. GM_xmlhttpRequest({
  871. method: 'POST',
  872. url: 'https://keyfc.net/bbs/tools/tudou.aspx',
  873. data: 'orignalMsg=' + encoded.replace(/\s/g, '') + '&action=Decode',
  874. headers: {
  875. 'Content-Type': 'application/x-www-form-urlencoded',
  876. },
  877. onload: function (res) {
  878. if (res.status == 200 && res.readyState == 4) {
  879. resolve(res.responseText.replace(/^<BUDDHIST><Message><!\[CDATA\[|\]\]><\/Message><\/BUDDHIST>$/g, ''));
  880. } else {
  881. console.warn('福利吧论坛 - 好孩子看得见:\n自动解码出错!');
  882. resolve('');
  883. }
  884. },
  885. onerror: function () {
  886. console.error('福利吧论坛 - 好孩子看得见:\n网络链接出错!');
  887. resolve('');
  888. },
  889. });
  890. });
  891. }
  892. async foyuDecode(container, encoded) {
  893. await this.foyuPromise(encoded).then(data => {
  894. data && this.createGoodBoyFrame(container, [data]);
  895. });
  896. }
  897. decodeCoreValues(container, textArray) {
  898. const { core, baijia, foyu } = reg;
  899. const decodeArray = [];
  900. textArray.forEach(item => {
  901. if (core.test(item)) {
  902. decodeArray.push(coreValuesDecode(core.exec(item)[1]));
  903. } else if (baijia.test(item)) {
  904. decodeArray.push(baijiaDecode(baijia.exec(item)[1]));
  905. } else if (foyu.test(item)) {
  906. this.foyuDecode(container, foyu.exec(item)[1]);
  907. }
  908. });
  909. return decodeArray;
  910. }
  911. checkBaidupan(linkValue, linkDom) {
  912. GM_xmlhttpRequest({
  913. method: 'GET',
  914. url: linkValue,
  915. headers: {
  916. 'Content-Type': 'application/x-www-form-urlencoded',
  917. },
  918. onload: function (res) {
  919. if (
  920. res.responseText.indexOf('此链接分享内容可能因为涉及侵权') !== -1 ||
  921. res.responseText.indexOf('你所访问的页面不存在了') !== -1 ||
  922. res.responseText.indexOf('分享的文件已经被取消了') !== -1
  923. ) {
  924. linkDom.classList.add('link_faild');
  925. linkDom.title = '链接资源已经失效!';
  926. } else {
  927. linkDom.title = '链接资源正常。';
  928. }
  929. },
  930. onerror: function () {
  931. console.wran('福利吧论坛 - 好孩子看得见:\n网络连接失败。\n', linkValue);
  932. },
  933. });
  934. }
  935. }
  936. function randBin() {
  937. return Math.random() >= 0.5;
  938. }
  939. function str2Utf8(str) {
  940. const notEncoded = /[A-Za-z0-9\-_.!~*'()]/g;
  941. const str1 = str.replace(notEncoded, c => c.codePointAt(0).toString(16));
  942. const str2 = encodeURIComponent(str1);
  943. const concated = str2.replace(/%/g, '').toUpperCase();
  944. return concated;
  945. }
  946. function hex2Duo(hexs) {
  947. const duo = [];
  948. for (let c of hexs) {
  949. const n = Number.parseInt(c, 16);
  950. if (n < 10) {
  951. duo.push(n);
  952. } else {
  953. if (randBin()) {
  954. duo.push(10);
  955. duo.push(n - 10);
  956. } else {
  957. duo.push(11);
  958. duo.push(n - 6);
  959. }
  960. }
  961. }
  962. return duo;
  963. }
  964. function utf82Str(utfs) {
  965. const l = utfs.length;
  966. const splited = [];
  967. for (let i = 0; i < l; i++) {
  968. if ((i & 1) === 0) {
  969. splited.push('%');
  970. }
  971. splited.push(utfs[i]);
  972. }
  973. return decodeURIComponent(splited.join(''));
  974. }
  975. function duo2Hex(duo) {
  976. const hex = [];
  977. const l = duo.length;
  978. let i = 0;
  979. while (i < l) {
  980. if (duo[i] < 10) {
  981. hex.push(duo[i]);
  982. } else {
  983. if (duo[i] === 10) {
  984. i++;
  985. hex.push(duo[i] + 10);
  986. } else {
  987. i++;
  988. hex.push(duo[i] + 6);
  989. }
  990. }
  991. i++;
  992. }
  993. return hex.map(v => v.toString(16).toUpperCase()).join('');
  994. }
  995. function duo2Values(duo) {
  996. return duo.map(d => coreValues[2 * d] + coreValues[2 * d + 1]).join('');
  997. }
  998. function coreValuesEncode(str) {
  999. return duo2Values(hex2Duo(str2Utf8(str)));
  1000. }
  1001. function coreValuesDecode(encoded) {
  1002. const duo = [];
  1003. for (let c of encoded) {
  1004. let i = coreValues.indexOf(c);
  1005. if (i === -1) {
  1006. continue;
  1007. } else if (i & 1) {
  1008. continue;
  1009. } else {
  1010. duo.push(i >> 1);
  1011. }
  1012. }
  1013. const hexs = duo2Hex(duo);
  1014. let str;
  1015. try {
  1016. str = utf82Str(hexs);
  1017. } catch (e) {
  1018. throw e;
  1019. }
  1020. return str;
  1021. }
  1022. function isFloat(str) {
  1023. return str == '右侧';
  1024. }
  1025. function baijiaEncode(str) {
  1026. str = str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
  1027. const v = str.replace(/magnet:\?xt=urn:btih:/, '');
  1028. const strc = v.split('');
  1029. let a = '';
  1030. for (let item of strc) {
  1031. for (let key in baijiaValues) {
  1032. if (baijiaValues[key] === item) {
  1033. a += key;
  1034. break;
  1035. }
  1036. }
  1037. }
  1038. return a;
  1039. }
  1040. function baijiaDecode(encoded) {
  1041. const charArray = encoded.split('');
  1042. let str = '';
  1043. for (let item of charArray) {
  1044. if (baijiaValues[item]) {
  1045. str += baijiaValues[item];
  1046. }
  1047. }
  1048. if (/^https?\/\//i.test(str)) {
  1049. return str.replace(/^(https?)/, '$1' + ':');
  1050. } else if (/^(https?:\/\/|ed2k:\/\/)/.test(str)) {
  1051. return str;
  1052. } else {
  1053. return 'magnet:?xt=urn:btih:' + str;
  1054. }
  1055. }
  1056. function convertChineseNumber(textString) {
  1057. return textString.replace(/[零一二三四五六七八九壹贰叁肆伍陆柒捌玖]/gi, arg0 => {
  1058. let index = '零一二三四五六七八九'.indexOf(arg0);
  1059. if (index === -1) {
  1060. index = '壹贰叁肆伍陆柒捌玖'.indexOf(arg0) + 1;
  1061. }
  1062. return index;
  1063. });
  1064. }
  1065. function filterLink(inputLink) {
  1066. let status = true;
  1067. if (inputLink) {
  1068. for (let i in filterReg) {
  1069. if (filterReg[i].test(inputLink)) {
  1070. status = false;
  1071. break;
  1072. }
  1073. }
  1074. } else {
  1075. status = false;
  1076. }
  1077. return status;
  1078. }
  1079. function getPureLink(inputLink, depthBoolean) {
  1080. const { baidupanIncludeCode } = reg;
  1081. let outputLink = inputLink;
  1082. if (depthBoolean) {
  1083. if (baidupanIncludeCode.test(outputLink)) {
  1084. if (/#[a-z0-9]{4}$/i.test(outputLink)) {
  1085. outputLink = outputLink.replace(/#[a-z0-9]{4}$/i, '');
  1086. }
  1087. } else if (/^https?:\/\/www\.bilibili\.com\/video\/av\d+\?from=search/i.test(outputLink)) {
  1088. outputLink = outputLink.replace(/\?from=search.*/, '');
  1089. }
  1090. }
  1091. let returnLink = outputLink
  1092. .replace(/(^(?:\s+)?(?:\[url\])?(?:\s+)?(?:https?:\/\/)?|(?:\/+)?(?:\s+)?(?:\[\/url\])?$|%C2%A0$)/gi, '')
  1093. .replace(/%C2%A0/gi, '%20');
  1094. try {
  1095. returnLink = decodeURI(returnLink);
  1096. } catch (e) {
  1097. console.warn('福利吧论坛 - 好孩子看得见:\n出现编码转换错误。', outputLink);
  1098. console.warn(e);
  1099. returnLink = outputLink
  1100. .replace(/(^(?:\s+)?(?:\[url\])?(?:\s+)?(?:https?:\/\/)?|(?:\/+)?(?:\s+)?(?:\[\/url\])?$|%C2%A0$)/gi, '')
  1101. .replace(/%C2%A0/gi, '%20');
  1102. }
  1103. return returnLink;
  1104. }
  1105. function contrastTextAndLink(textValue, linkValue) {
  1106. let sta = true;
  1107. textValue = getPureLink(textValue, true);
  1108. linkValue = getPureLink(linkValue, true);
  1109. if (/\s...\s/i.test(textValue)) {
  1110. sta = false;
  1111. } else if (textValue === linkValue) {
  1112. sta = false;
  1113. }
  1114. return sta;
  1115. }
  1116. function findLink(container) {
  1117. const { baidupan } = reg;
  1118. const linkA = container.getElementsByTagName('a');
  1119. const tempObj = {
  1120. linkObjArray: [],
  1121. baiduObjArray: [],
  1122. linksArray: [],
  1123. };
  1124. const tempBaiduArray = [];
  1125. for (let i = 0; i < linkA.length; i++) {
  1126. if (linkA[i].closest('div.aimg_tip')) {
  1127. continue;
  1128. }
  1129. const tempLink = linkA[i].href;
  1130. if (filterLink(tempLink)) {
  1131. const tempImg = linkA[i].querySelectorAll('img');
  1132. if (tempImg.length === 0 || (tempImg.length > 0 && tempImg[0].src !== tempLink && tempImg[0].getAttribute('file') !== tempLink)) {
  1133. const tempText = linkA[i].innerText.replace(/^\s+|\s+$/gi, '');
  1134. if (contrastTextAndLink(tempText, tempLink)) {
  1135. const linkObj = {
  1136. eleValue: tempLink,
  1137. eleContainer: tempText,
  1138. ele: linkA[i],
  1139. };
  1140. tempObj.linkObjArray.push(linkObj);
  1141. } else if (baidupan.test(tempLink)) {
  1142. const baiduObj = {
  1143. eleValue: tempLink,
  1144. eleContainer: tempText,
  1145. ele: linkA[i],
  1146. };
  1147. if (tempBaiduArray.indexOf(tempLink) === -1) {
  1148. tempBaiduArray.push(tempLink);
  1149. tempObj.baiduObjArray.push(baiduObj);
  1150. }
  1151. }
  1152. }
  1153. tempObj.linksArray.indexOf(tempLink) === -1 && tempObj.linksArray.push(tempLink);
  1154. }
  1155. }
  1156. return tempObj;
  1157. }
  1158. function judgeColor(rgbColorValue) {
  1159. if (/rgb\(/i.test(rgbColorValue)) {
  1160. const rgbValue = rgbColorValue.replace('rgb(', '').replace(')', '');
  1161. const rgbValueArray = rgbValue.split(',');
  1162. const grayLevel = rgbValueArray[0] * 0.299 + rgbValueArray[1] * 0.587 + rgbValueArray[2] * 0.114;
  1163. return grayLevel > 192;
  1164. } else if (/rgba\(/i.test(rgbColorValue)) {
  1165. const rgbaValue = rgbColorValue.replace('rgba(', '').replace(')', '');
  1166. const rgbaValueArray = rgbaValue.split(',');
  1167. if (rgbaValueArray[3] <= 0.2) {
  1168. return true;
  1169. } else {
  1170. const grayLevel2 = rgbaValueArray[0] * 0.299 + rgbaValueArray[1] * 0.587 + rgbaValueArray[2] * 0.114;
  1171. return grayLevel2 > 192;
  1172. }
  1173. }
  1174. return false;
  1175. }
  1176. function rgb2Rgba(colorString) {
  1177. const colorValue = colorString.match(/\d+/g);
  1178. if (colorValue.length === 3) {
  1179. return 'rgba(' + colorValue[0] + ', ' + colorValue[1] + ', ' + colorValue[2] + ', 1)';
  1180. }
  1181. return colorString;
  1182. }
  1183. function display_Text(container, newTextColor, newTextBackgroundColor) {
  1184. const { url } = reg;
  1185. const textFont = container.getElementsByTagName('font');
  1186. const tempObj = {
  1187. hideTextArray: [],
  1188. showTextArray: [],
  1189. };
  1190. for (let i = 0; i < textFont.length; i++) {
  1191. if (textFont[i].closest('.quote') || textFont[i].getElementsByClassName('aimg_tip').length !== 0) {
  1192. continue;
  1193. }
  1194. const tempText = textFont[i].innerText.replace(/^\s+|\s+$/gi, '');
  1195. if (!/^\s*$/i.test(tempText)) {
  1196. const textColor = window.getComputedStyle(textFont[i]).color;
  1197. const textBackgroundColor = window.getComputedStyle(textFont[i]).backgroundColor;
  1198. if (judgeColor(textColor) && judgeColor(textBackgroundColor)) {
  1199. textFont[i].style.color = newTextColor;
  1200. tempObj.hideTextArray.push(tempText);
  1201. } else if (rgb2Rgba(textBackgroundColor) === rgb2Rgba(textColor)) {
  1202. textFont[i].style.backgroundColor = newTextBackgroundColor;
  1203. textFont[i].style.color = newTextColor;
  1204. tempObj.hideTextArray.push(tempText);
  1205. } else if (!judgeColor(textBackgroundColor) && !judgeColor(textColor)) {
  1206. textFont[i].style.backgroundColor = newTextBackgroundColor;
  1207. textFont[i].style.color = newTextColor;
  1208. tempObj.hideTextArray.push(tempText);
  1209. } else if (textFont[i].childNodes.length === 1 && textFont[i].childNodes[0].nodeType === 3) {
  1210. if (GM_config.get('extractEnable')) {
  1211. if (url.test(tempText)) {
  1212. textFont[i].innerHTML = textFont[i].innerHTML.replace(url, (_arg0, arg1) => {
  1213. return (
  1214. '<a href="' + convertChineseNumber(arg1) + '" title="点击访问" target="_blank">' + convertChineseNumber(arg1) + '</a>'
  1215. );
  1216. });
  1217. }
  1218. }
  1219. !tempObj.showTextArray.includes(tempText) && tempObj.showTextArray.push(tempText);
  1220. } else if (textFont[i].childNodes.length > 1) {
  1221. const tFont = textFont[i].childNodes;
  1222. for (let child_index in tFont) {
  1223. analysisText(tFont[child_index]);
  1224. }
  1225. !tempObj.showTextArray.includes(tempText) && tempObj.showTextArray.push(tempText);
  1226. }
  1227. }
  1228. }
  1229. const tempTable = container.getElementsByTagName('table');
  1230. for (let j = 0; j < tempTable.length; j++) {
  1231. if (!judgeColor(tempTable[j].style.backgroundColor) && !judgeColor(tempTable[j].style.color)) {
  1232. tempTable[j].style.backgroundColor = newTextBackgroundColor;
  1233. } else if (judgeColor(tempTable[j].style.color) && judgeColor(tempTable[j].style.backgroundColor)) {
  1234. tempTable[j].style.color = newTextColor;
  1235. }
  1236. }
  1237. return tempObj;
  1238. }
  1239. function text2A(node) {
  1240. const { url } = reg;
  1241. const tempSpan = document.createElement('span');
  1242. tempSpan.innerHTML = node.nodeValue.replace(url, (arg0, arg1) => {
  1243. if (arg1.length > 2000) {
  1244. return arg0;
  1245. }
  1246. return arg0.replace(
  1247. arg1,
  1248. '<a href="' + convertChineseNumber(arg1) + '" title="点击访问" target="_blank">' + convertChineseNumber(arg1) + '</a>'
  1249. );
  1250. });
  1251. node.parentNode.replaceChild(tempSpan, node);
  1252. }
  1253. function analysisText(domPoint) {
  1254. const { url } = reg;
  1255. const nodeList = domPoint.childNodes;
  1256. const nodeTextArray = [];
  1257. for (let i in nodeList) {
  1258. if (nodeList[i].nodeType === 3) {
  1259. const tempText = nodeList[i].nodeValue.replace(/^\s+|\s+$/gi, '');
  1260. if (!/^\s*$/i.test(tempText)) {
  1261. if (GM_config.get('extractEnable')) {
  1262. if (url.test(tempText)) {
  1263. text2A(nodeList[i]);
  1264. }
  1265. }
  1266. nodeTextArray.push(tempText);
  1267. }
  1268. } else if (
  1269. nodeList[i].nodeType === 1 &&
  1270. !nodeList[i].className.includes('quote') &&
  1271. !nodeList[i].className.includes('pstatus') &&
  1272. !nodeList[i].className.includes('aimg_tip') &&
  1273. !nodeList[i].className.includes('blockcode') &&
  1274. nodeList[i].nodeName !== 'FONT' &&
  1275. nodeList[i].nodeName !== 'A' &&
  1276. nodeList[i].nodeName !== 'SCRIPT' &&
  1277. nodeList[i].childNodes.length > 0
  1278. ) {
  1279. const recursiveArray = analysisText(nodeList[i]);
  1280. for (let j in recursiveArray) {
  1281. nodeTextArray.push(recursiveArray[j]);
  1282. }
  1283. }
  1284. }
  1285. return nodeTextArray;
  1286. }
  1287. function isMobilePage() {
  1288. return /android|webos|iphone|ipod|blackberry/i.test(navigator.userAgent);
  1289. }
  1290. function getNowDate() {
  1291. const now = new Date();
  1292. return now.getFullYear() + '-' + (now.getMonth() + 1) + '-' + now.getDate();
  1293. }
  1294. function timeAddZero(value) {
  1295. return value < 10 ? '0' + value : value;
  1296. }
  1297. function getUpdateTime(unixTime) {
  1298. if (unixTime) {
  1299. const tempTime = new Date(unixTime);
  1300. return (
  1301. ' (更新时间: ' +
  1302. tempTime.getFullYear() +
  1303. '-' +
  1304. timeAddZero(tempTime.getMonth() + 1) +
  1305. '-' +
  1306. timeAddZero(tempTime.getDate()) +
  1307. ' ' +
  1308. timeAddZero(tempTime.getHours()) +
  1309. ':' +
  1310. timeAddZero(tempTime.getMinutes()) +
  1311. ':' +
  1312. timeAddZero(tempTime.getSeconds()) +
  1313. ')'
  1314. );
  1315. }
  1316. return '';
  1317. }
  1318. function highlightPost() {
  1319. try {
  1320. let userAccessNum = 90;
  1321. let upmimeNum = document.getElementById('g_upmine').textContent;
  1322. upmimeNum = /LV\.(-?[0-9])/.exec(upmimeNum)[1];
  1323. if (upmimeNum == -1) {
  1324. userAccessNum = 0;
  1325. } else if (upmimeNum == 0) {
  1326. userAccessNum = 5;
  1327. } else if (upmimeNum >= 1 && upmimeNum <= 8) {
  1328. userAccessNum = upmimeNum * 10;
  1329. }
  1330. if (status.accessNum != userAccessNum) {
  1331. status.accessNum = userAccessNum;
  1332. GM_config.setValue('accessNumber', status.accessNum);
  1333. }
  1334. } catch (e) {
  1335. console.warn('福利吧论坛 - 好孩子看得见:\n识别用户阅读权限出错,将使用存储中记录的用户阅读权限。');
  1336. }
  1337. console.debug('福利吧论坛 - 好孩子看得见:\n用户阅读权限:', status.accessNum);
  1338. document.arrive('div#threadlist form table tbody', { onceOnly: true }, function () {
  1339. let item = this.querySelectorAll('.common, .new, .lock')[0];
  1340. if (item) {
  1341. let readNum = item.querySelector('.xw1');
  1342. let tempStatus = true;
  1343. if (readNum) {
  1344. readNum = Number(readNum.textContent);
  1345. if (readNum > 90) {
  1346. item
  1347. .querySelector('.xst')
  1348. .setAttribute('style', 'color: #999; font-weight: bold; text-decoration-line: line-through; text-decoration-color: #000000;');
  1349. tempStatus = false;
  1350. } else if (readNum > status.accessNum) {
  1351. item.querySelector('.xst').setAttribute('style', 'color: #999; font-weight: bold;');
  1352. tempStatus = false;
  1353. }
  1354. }
  1355. if (tempStatus && item.querySelector('.xst').style.fontWeight === '700') {
  1356. tempStatus = false;
  1357. }
  1358. if (tempStatus) {
  1359. let agreeNum = 0;
  1360. const fontEle = item.querySelectorAll('font');
  1361. for (let j = 0; j < fontEle.length; j++) {
  1362. let fontNum = fontEle[j].textContent;
  1363. if (fontNum) {
  1364. fontNum = Number(fontNum.replace('+', ''));
  1365. if (fontNum > agreeNum) {
  1366. agreeNum = fontNum;
  1367. }
  1368. }
  1369. }
  1370. if (agreeNum > 0) {
  1371. if (agreeNum >= GM_config.get('agreeThreshold')) {
  1372. item.querySelector('.xst').setAttribute('style', 'font-weight: bold; color: ' + GM_config.get('agreeColor') + ';');
  1373. tempStatus = false;
  1374. }
  1375. }
  1376. }
  1377. if (tempStatus) {
  1378. let replyNum = item.parentNode.querySelector('td.num a').textContent;
  1379. if (replyNum) {
  1380. replyNum = Number(replyNum);
  1381. if (replyNum >= GM_config.get('replyTHreshold')) {
  1382. item.querySelector('.xst').setAttribute('style', 'font-weight: bold; color: ' + GM_config.get('replyColor') + ';');
  1383. }
  1384. }
  1385. }
  1386. }
  1387. });
  1388. }
  1389. function createSettingsIcon() {
  1390. const iconSpan = document.createElement('span');
  1391. iconSpan.id = 'settingsIcon';
  1392. iconSpan.title = '打开好孩子看得见设置';
  1393. iconSpan.addEventListener('click', () => {
  1394. GM_config.open();
  1395. });
  1396. return iconSpan;
  1397. }
  1398. function operateCode(inputId, outputId, callback, waitStr = '') {
  1399. const str = document.getElementById(inputId).value;
  1400. if (str) {
  1401. document.getElementById(outputId).value = waitStr;
  1402. const result = callback(str, outputId);
  1403. if (result) {
  1404. document.getElementById(outputId).value = result;
  1405. }
  1406. }
  1407. }
  1408. function copyCode(copyBtn, resultId) {
  1409. const copyStr = document.getElementById(resultId).value;
  1410. if (copyStr) {
  1411. GM_setClipboard(copyStr, 'text');
  1412. copyBtn.title = '复制成功';
  1413. copyBtn.classList.add('a_copy_completed');
  1414. status.timer3 && clearTimeout(status.timer3);
  1415. status.timer3 = setTimeout(() => {
  1416. copyBtn.classList.remove('a_copy_completed');
  1417. copyBtn.title = '将输出的结果复制到剪贴板中';
  1418. }, 2000);
  1419. }
  1420. }
  1421. function createSwitchSpan(keyValue, domArray) {
  1422. const switchSpan = document.createElement('span');
  1423. switchSpan.className = 'o';
  1424. const switchImg = document.createElement('img');
  1425. switchImg.id = keyValue + '_user_img';
  1426. switchImg.title = '收起/展开';
  1427. switchImg.alt = '收起/展开';
  1428. if (status[keyValue]) {
  1429. domArray.forEach(function (item) {
  1430. item.classList.add('collapsed_hide');
  1431. });
  1432. switchImg.src = icon.collapsedYes;
  1433. } else {
  1434. switchImg.src = icon.collapsedNo;
  1435. }
  1436. switchImg.addEventListener('click', () => {
  1437. if (status[keyValue]) {
  1438. domArray.forEach(item => {
  1439. item.classList.remove('collapsed_hide');
  1440. });
  1441. switchImg.src = icon.collapsedNo;
  1442. status[keyValue] = false;
  1443. } else {
  1444. domArray.forEach(item => {
  1445. item.classList.add('collapsed_hide');
  1446. });
  1447. switchImg.src = icon.collapsedYes;
  1448. status[keyValue] = true;
  1449. }
  1450. GM_config.setValue(keyValue, status[keyValue]);
  1451. });
  1452. switchSpan.appendChild(switchImg);
  1453. return switchSpan;
  1454. }
  1455. function createSignatureSwitch(signature, switchStatus = true) {
  1456. const switchDiv = document.createElement('div');
  1457. switchDiv.className = 'signature_switch_div';
  1458. if (switchStatus) {
  1459. switchDiv.title = '收起';
  1460. } else {
  1461. switchDiv.title = '展开';
  1462. switchDiv.classList.add('signature_switch_close');
  1463. signature.classList.add('signature_hide');
  1464. }
  1465. switchDiv.addEventListener(
  1466. 'click',
  1467. () => {
  1468. if (switchStatus) {
  1469. switchStatus = false;
  1470. switchDiv.title = '展开';
  1471. switchDiv.classList.add('signature_switch_close');
  1472. signature.classList.add('signature_hide');
  1473. } else {
  1474. switchStatus = true;
  1475. switchDiv.title = '收起';
  1476. switchDiv.classList.remove('signature_switch_close');
  1477. signature.classList.remove('signature_hide');
  1478. }
  1479. },
  1480. false
  1481. );
  1482. return switchDiv;
  1483. }
  1484. function mobileInit() {
  1485. const { checkDate, oldUrl } = status;
  1486. if (GM_config.get('highlightEnable')) {
  1487. if (oldUrl.indexOf('mod=forumdisplay') !== -1 || /forum-\d+-\d+\.html/i.test(oldUrl)) {
  1488. document.body.arrive('.threadlist li', { fireOnAttributesModification: true, existing: true }, function () {
  1489. let replyNum = this.querySelector('span.num.icon.iconfont').textContent;
  1490. if (replyNum) {
  1491. replyNum = Number(/\d+/.exec(replyNum)[0]);
  1492. if (replyNum >= GM_config.get('replyTHreshold')) {
  1493. this.querySelector('div.thread-item-sub').setAttribute(
  1494. 'style',
  1495. 'font-weight: bold; color: ' + GM_config.get('replyColor') + ';'
  1496. );
  1497. }
  1498. }
  1499. });
  1500. }
  1501. }
  1502. if (oldUrl.indexOf('mod=viewthread') !== -1 || /thread-\d+-\d+(?:-\d+)?\.html/i.test(oldUrl)) {
  1503. const phoneBackgroundColor = window.getComputedStyle(document.body).backgroundColor;
  1504. const messageDom = document.querySelectorAll('.message');
  1505. for (let messageEle of messageDom) {
  1506. const textObj = display_Text(messageEle, GM_config.get('textColor'), phoneBackgroundColor);
  1507. const textArray = analysisText(messageEle);
  1508. const linkObj = findLink(messageEle);
  1509. const goodBoyObj = new Good_Boy(GM_config);
  1510. goodBoyObj.createGoodBoyElement(messageEle, linkObj, textObj, textArray);
  1511. }
  1512. }
  1513. if (GM_config.get('autoCheckInEnable')) {
  1514. document.body.arrive('.bg > a', { onceOnly: true, existing: true }, function (item) {
  1515. if (item.textContent === '签到领奖') {
  1516. const nowDate = getNowDate();
  1517. if (nowDate !== checkDate) {
  1518. GM_config.setValue('checkEnable', nowDate);
  1519. setTimeout(() => {
  1520. item.click();
  1521. }, 2000);
  1522. console.info('福利吧论坛 - 好孩子看得见:\n完成自动签到。');
  1523. }
  1524. }
  1525. });
  1526. }
  1527. }
  1528. function pcInit() {
  1529. const { baseImage } = reg;
  1530. const { oldUrl } = status;
  1531. if (oldUrl.indexOf('mod=forumdisplay') !== -1 || /forum-\d+-\d+\.html/i.test(oldUrl)) {
  1532. if (oldUrl.indexOf('fid=37') !== -1 || /forum-37-/i.test(oldUrl)) {
  1533. document.arrive('div.bm_h.cl', { fireOnAttributesModification: true, onceOnly: true, existing: true }, function () {
  1534. if (this.querySelectorAll('span.y').length === 0) {
  1535. const themeArray = [];
  1536. themeArray.push(this.nextElementSibling);
  1537. this.insertBefore(createSwitchSpan('collapsedGwwzEnable', themeArray), this.childNodes[0]);
  1538. }
  1539. });
  1540. }
  1541. GM_config.get('highlightEnable') && highlightPost();
  1542. if (GM_config.get('visitedEnable')) {
  1543. const visitedStyle = '.tl th a.s.xst:visited, .tl td.fn a:visited { color: ' + GM_config.get('visitedColor') + ' !important; }';
  1544. GM_addStyle(visitedStyle);
  1545. console.debug('福利吧论坛 - 好孩子看得见:\n完成注入自定义己访问帖子的样式。');
  1546. }
  1547. }
  1548. if (oldUrl.indexOf('mod=viewthread') !== -1 || /thread-\d+-\d+(?:-\d+)?\.html/i.test(oldUrl)) {
  1549. document.addEventListener(
  1550. 'DOMContentLoaded',
  1551. () => {
  1552. const tFImg = document.querySelectorAll('td.t_f img');
  1553. for (let imgEle of tFImg) {
  1554. let baseSrc = imgEle.getAttribute('file');
  1555. if (baseImage.test(baseSrc)) {
  1556. baseSrc = baseSrc.replace(baseImage, '$1');
  1557. imgEle.setAttribute('file', baseSrc);
  1558. imgEle.src = baseSrc;
  1559. }
  1560. }
  1561. const zoomImg = document.querySelectorAll('.t_f img.zoom');
  1562. for (let zoomEle of zoomImg) {
  1563. zoomEle.removeAttribute('height');
  1564. }
  1565. const htmlBackgroundColor = window.getComputedStyle(document.body).backgroundColor;
  1566. const tFDom = document.querySelectorAll('td.t_f');
  1567. for (let domEle of tFDom) {
  1568. const goodBoyObj = new Good_Boy(GM_config);
  1569. if (isFloat(GM_config.get('displayPosition'))) {
  1570. const favatarBtn = domEle.closest('table.plhin').querySelector('div.favatar');
  1571. const textObj = display_Text(domEle, GM_config.get('textColor'), htmlBackgroundColor);
  1572. const textArray = analysisText(domEle);
  1573. const linkObj = findLink(domEle);
  1574. goodBoyObj.createGoodBoyElement(favatarBtn, linkObj, textObj, textArray);
  1575. } else {
  1576. const mainBtn = domEle.closest('div.pcb').querySelector('div.t_fsz') || domEle.closest('div.pcb').querySelector('div.pcbs');
  1577. const textObj = display_Text(domEle, GM_config.get('textColor'), htmlBackgroundColor);
  1578. const textArray = analysisText(domEle);
  1579. const linkObj = findLink(domEle);
  1580. goodBoyObj.createGoodBoyElement(mainBtn, linkObj, textObj, textArray);
  1581. }
  1582. }
  1583. const signA = document.querySelectorAll('div.sign a');
  1584. for (let signEle of signA) {
  1585. if (/member\.php\?mod=logging&action=logout/i.test(signEle.href)) {
  1586. signEle.style.display = 'none';
  1587. }
  1588. }
  1589. if (GM_config.get('signatureEnable')) {
  1590. const sign = document.querySelectorAll('div.sign');
  1591. const signStatus = GM_config.get('signatureSwitch') == '展开';
  1592. for (let signItem of sign) {
  1593. signItem.insertAdjacentElement('beforebegin', createSignatureSwitch(signItem, signStatus));
  1594. }
  1595. }
  1596. },
  1597. false
  1598. );
  1599. }
  1600. if (GM_config.get('autoCheckInEnable')) {
  1601. document.arrive('#fx_checkin_topb', { fireOnAttributesModification: true, onceOnly: true, existing: true }, function () {
  1602. if (this.getElementsByTagName('img')[0].alt !== '已签到') {
  1603. if (typeof fx_checkin === 'function') {
  1604. this.click();
  1605. } else {
  1606. setTimeout(() => {
  1607. this.click();
  1608. }, 2000);
  1609. }
  1610. console.info('福利吧论坛 - 好孩子看得见:\n自动签到完成。');
  1611. }
  1612. });
  1613. }
  1614. if (GM_config.get('codeEnable') || GM_config.get('nightBtnEnable')) {
  1615. document.addEventListener('DOMContentLoaded', function () {
  1616. const expandBox = document.createElement('div');
  1617. expandBox.className = 'expand_box';
  1618. if (GM_config.get('codeEnable') && GM_config.get('nightBtnEnable')) {
  1619. expandBox.className = 'expand_box_h';
  1620. }
  1621. expandBox.onmouseenter = function () {
  1622. this.classList.add('show_expand_box');
  1623. };
  1624. expandBox.onmouseleave = function () {
  1625. this.classList.remove('show_expand_box');
  1626. };
  1627. if (GM_config.get('codeEnable')) {
  1628. const codeFrame = document.createElement('div');
  1629. document.body.appendChild(codeFrame);
  1630. const codePanel = new GM_configStruct({
  1631. id: 'myCodePanel',
  1632. title: '编解码工具',
  1633. isTabs: true,
  1634. skin: 'tab',
  1635. frame: codeFrame,
  1636. css: style.codePanel,
  1637. fields: {
  1638. bjxInput: {
  1639. label: '输入:',
  1640. section: [
  1641. '百家姓',
  1642. GM_config.create('a', {
  1643. textContent: '百家姓编码原示例地址',
  1644. title: '点击跳转到百家姓编码示例',
  1645. target: '_blank',
  1646. href: 'https://fulibus.net/anhao.html',
  1647. }),
  1648. ],
  1649. type: 'textarea',
  1650. labelPos: 'above',
  1651. placeholder: '请输入内容',
  1652. default: '',
  1653. save: false,
  1654. },
  1655. bjxEncodeBtn: {
  1656. label: '编码 >>>',
  1657. title: '使用"百家姓"进行编码',
  1658. type: 'button',
  1659. click: () => {
  1660. operateCode('myCodePanel_field_bjxInput', 'myCodePanel_field_bjxOutput', baijiaEncode, '编码中...');
  1661. },
  1662. },
  1663. bjxDecodeBtn: {
  1664. label: '解码 >>>',
  1665. title: '对"百家姓"的编码进行解码',
  1666. type: 'button',
  1667. click: () => {
  1668. operateCode('myCodePanel_field_bjxInput', 'myCodePanel_field_bjxOutput', baijiaDecode, '解码中...');
  1669. },
  1670. },
  1671. bjxOutput: {
  1672. label: '输出:',
  1673. type: 'textarea',
  1674. labelPos: 'above',
  1675. placeholder: '此处显示结果',
  1676. default: '',
  1677. save: false,
  1678. },
  1679. bjxCopyBtn: {
  1680. label: '复制结果',
  1681. title: '将输出的结果复制到剪贴板中',
  1682. type: 'button',
  1683. click: function () {
  1684. copyCode(this, 'myCodePanel_field_bjxOutput');
  1685. },
  1686. },
  1687. coreValuesInput: {
  1688. label: '输入:',
  1689. section: [
  1690. '社会主义核心价值观',
  1691. GM_config.create('a', {
  1692. textContent: '社会主义核心价值观编码项目地址',
  1693. title: '点击跳转到社会主义核心价值观编码项目',
  1694. target: '_blank',
  1695. href: 'https://github.com/sym233/core-values-encoder',
  1696. }),
  1697. ],
  1698. type: 'textarea',
  1699. labelPos: 'above',
  1700. placeholder: '请输入内容',
  1701. default: '',
  1702. save: false,
  1703. },
  1704. coreValuesEncodeBtn: {
  1705. label: '编码 >>>',
  1706. title: '使用"社会主义核心价值观"进行编码',
  1707. type: 'button',
  1708. click: () => {
  1709. operateCode('myCodePanel_field_coreValuesInput', 'myCodePanel_field_coreValuesOutput', coreValuesEncode, '编码中...');
  1710. },
  1711. },
  1712. coreValuesDecodeBtn: {
  1713. label: '解码 >>>',
  1714. title: '对"社会主义核心价值观"的编码进行解码',
  1715. type: 'button',
  1716. click: () => {
  1717. operateCode('myCodePanel_field_coreValuesInput', 'myCodePanel_field_coreValuesOutput', coreValuesDecode, '解码中...');
  1718. },
  1719. },
  1720. coreValuesOutput: {
  1721. label: '输出:',
  1722. type: 'textarea',
  1723. labelPos: 'above',
  1724. placeholder: '此处显示结果',
  1725. default: '',
  1726. save: false,
  1727. },
  1728. coreValuesCopyBtn: {
  1729. label: '复制结果',
  1730. title: '将输出的结果复制到剪贴板中',
  1731. type: 'button',
  1732. click: function () {
  1733. copyCode(this, 'myCodePanel_field_coreValuesOutput');
  1734. },
  1735. },
  1736. yflcInput: {
  1737. label: '输入:',
  1738. section: [
  1739. '与佛论禅',
  1740. GM_config.create('a', {
  1741. textContent: '与佛论禅编码原工具地址',
  1742. title: '点击跳转到与佛论禅编码工具',
  1743. target: '_blank',
  1744. href: 'http://keyfc.net/bbs/tools/tudoucode.aspx',
  1745. }),
  1746. ],
  1747. type: 'textarea',
  1748. labelPos: 'above',
  1749. placeholder: '请输入内容',
  1750. default: '',
  1751. save: false,
  1752. },
  1753. yflcEncodeBtn: {
  1754. label: '编码 >>>',
  1755. title: '使用"与佛论禅"进行编码',
  1756. type: 'button',
  1757. click: () => {
  1758. operateCode(
  1759. 'myCodePanel_field_yflcInput',
  1760. 'myCodePanel_field_yflcOutput',
  1761. (str, result_id) => {
  1762. GM_xmlhttpRequest({
  1763. method: 'POST',
  1764. url: 'https://keyfc.net/bbs/tools/tudou.aspx',
  1765. data: 'orignalMsg=' + encodeURIComponent(str) + '&action=Encode',
  1766. headers: {
  1767. 'Content-Type': 'application/x-www-form-urlencoded',
  1768. },
  1769. onload: res => {
  1770. if (res.status == 200 && res.readyState == 4) {
  1771. document.getElementById(result_id).value = res.responseText.replace(
  1772. /^<BUDDHIST><Message><!\[CDATA\[|\]\]><\/Message><\/BUDDHIST>$/g,
  1773. ''
  1774. );
  1775. } else {
  1776. document.getElementById(result_id).value = '编码出现错误!';
  1777. }
  1778. },
  1779. onerror: () => {
  1780. document.getElementById(result_id).value = '网络连接出错!';
  1781. },
  1782. });
  1783. return false;
  1784. },
  1785. '联网进行编码中...'
  1786. );
  1787. },
  1788. },
  1789. yflcDecodeBtn: {
  1790. label: '解码 >>>',
  1791. title: '对"与佛论禅"的编码进行解码',
  1792. type: 'button',
  1793. click: () => {
  1794. operateCode(
  1795. 'myCodePanel_field_yflcInput',
  1796. 'myCodePanel_field_yflcOutput',
  1797. (str, result_id) => {
  1798. GM_xmlhttpRequest({
  1799. method: 'POST',
  1800. url: 'https://keyfc.net/bbs/tools/tudou.aspx',
  1801. data: 'orignalMsg=' + str.replace(/\s/g, '') + '&action=Decode',
  1802. headers: {
  1803. 'Content-Type': 'application/x-www-form-urlencoded',
  1804. },
  1805. onload: res => {
  1806. if (res.status == 200 && res.readyState == 4) {
  1807. document.getElementById(result_id).value = res.responseText.replace(
  1808. /^<BUDDHIST><Message><!\[CDATA\[|\]\]><\/Message><\/BUDDHIST>$/g,
  1809. ''
  1810. );
  1811. } else {
  1812. document.getElementById(result_id).value = '解码出现错误!';
  1813. }
  1814. },
  1815. onerror: () => {
  1816. document.getElementById(result_id).value = '网络连接出错!';
  1817. },
  1818. });
  1819. return false;
  1820. },
  1821. '联网进行解码中...'
  1822. );
  1823. },
  1824. },
  1825. yflcOutput: {
  1826. label: '输出:',
  1827. type: 'textarea',
  1828. labelPos: 'above',
  1829. placeholder: '此处显示结果',
  1830. default: '',
  1831. save: false,
  1832. },
  1833. yflcCopyBtn: {
  1834. label: '复制结果',
  1835. title: '将输出的结果复制到剪贴板中',
  1836. type: 'button',
  1837. click: function () {
  1838. copyCode(this, 'myCodePanel_field_yflcOutput');
  1839. },
  1840. },
  1841. base64Input: {
  1842. label: '输入:',
  1843. section: [
  1844. 'BASE64',
  1845. GM_config.create('a', {
  1846. textContent: 'crypto-js 项目地址',
  1847. title: '点击跳转到 crypto-js 项目',
  1848. target: '_blank',
  1849. href: 'https://github.com/brix/crypto-js',
  1850. }),
  1851. ],
  1852. type: 'textarea',
  1853. labelPos: 'above',
  1854. placeholder: '请输入内容',
  1855. default: '',
  1856. save: false,
  1857. },
  1858. base64EncodeBtn: {
  1859. label: '编码 >>>',
  1860. title: '使用"BASE64"进行编码',
  1861. type: 'button',
  1862. click: () => {
  1863. operateCode(
  1864. 'myCodePanel_field_base64Input',
  1865. 'myCodePanel_field_base64Output',
  1866. str => {
  1867. if (typeof CryptoJS == 'undefined') {
  1868. return 'crypto-js 库文件不存在!';
  1869. } else {
  1870. str = CryptoJS.enc.Utf8.parse(str);
  1871. return CryptoJS.enc.Base64.stringify(str);
  1872. }
  1873. },
  1874. '编码中...'
  1875. );
  1876. },
  1877. },
  1878. base64DecodeBtn: {
  1879. label: '解码 >>>',
  1880. title: '对"BASE64"的编码进行解码',
  1881. type: 'button',
  1882. click: () => {
  1883. operateCode(
  1884. 'myCodePanel_field_base64Input',
  1885. 'myCodePanel_field_base64Output',
  1886. str => {
  1887. if (typeof CryptoJS == 'undefined') {
  1888. return 'crypto-js 库文件不存在!';
  1889. } else {
  1890. let words = CryptoJS.enc.Base64.parse(str);
  1891. return words.toString(CryptoJS.enc.Utf8);
  1892. }
  1893. },
  1894. '解码中...'
  1895. );
  1896. },
  1897. },
  1898. base64Output: {
  1899. label: '输出:',
  1900. type: 'textarea',
  1901. labelPos: 'above',
  1902. placeholder: '此处显示结果',
  1903. default: '',
  1904. save: false,
  1905. },
  1906. base64CopyBtn: {
  1907. label: '复制结果',
  1908. title: '将输出的结果复制到剪贴板中',
  1909. type: 'button',
  1910. click: function () {
  1911. copyCode(this, 'myCodePanel_field_base64Output');
  1912. },
  1913. },
  1914. },
  1915. events: {
  1916. open: function (doc) {
  1917. let config = this;
  1918. doc.getElementById(config.id + '_closeBtn').title = '关闭面板';
  1919. doc.getElementById(config.id + '_resetLink').textContent = '清空内容';
  1920. doc.getElementById(config.id + '_resetLink').title = '清空所有内容';
  1921. },
  1922. },
  1923. });
  1924. const codeSpan = document.createElement('span');
  1925. codeSpan.id = 'myCodeSpan';
  1926. codeSpan.title = '打开编解码工具';
  1927. codeSpan.addEventListener(
  1928. 'click',
  1929. () => {
  1930. codePanel.open();
  1931. },
  1932. false
  1933. );
  1934. expandBox.appendChild(codeSpan);
  1935. }
  1936. if (GM_config.get('nightBtnEnable')) {
  1937. const nightBtnSpan = document.createElement('span');
  1938. nightBtnSpan.id = 'myNightSpan';
  1939. if (GM_config.get('codeEnable')) {
  1940. nightBtnSpan.id = 'myNightSpan_2';
  1941. }
  1942. if (status.nightEnable) {
  1943. nightBtnSpan.style.backgroundImage = icon.modeNight;
  1944. nightBtnSpan.title = '切换到日间模式';
  1945. } else {
  1946. nightBtnSpan.style.backgroundImage = icon.modeDay;
  1947. nightBtnSpan.title = '切换到夜间模式';
  1948. }
  1949. nightBtnSpan.addEventListener(
  1950. 'click',
  1951. () => {
  1952. if (status.nightEnable) {
  1953. status.nightStyleDom && status.nightStyleDom.parentNode.removeChild(status.nightStyleDom);
  1954. status.nightEnable = false;
  1955. GM_config.setValue('nightEnable', status.nightEnable);
  1956. nightBtnSpan.title = '切换到夜间模式';
  1957. nightBtnSpan.style.backgroundImage = icon.modeDay;
  1958. } else {
  1959. status.nightStyleDom = GM_addStyle(style.night);
  1960. status.nightEnable = true;
  1961. GM_config.setValue('nightEnable', status.nightEnable);
  1962. nightBtnSpan.title = '切换到日间模式';
  1963. nightBtnSpan.style.backgroundImage = icon.modeNight;
  1964. }
  1965. },
  1966. false
  1967. );
  1968. expandBox.appendChild(nightBtnSpan);
  1969. }
  1970. document.body.appendChild(expandBox);
  1971. });
  1972. }
  1973. document.arrive('#sslct', { fireOnAttributesModification: true, onceOnly: true, existing: true }, item => {
  1974. item.after(createSettingsIcon());
  1975. });
  1976. }
  1977. function aInit() {
  1978. try {
  1979. GM_registerMenuCommand('好孩子看得见 - 设置', () => {
  1980. GM_config.open();
  1981. });
  1982. } catch (e) {
  1983. console.error('福利吧论坛 - 好孩子看得见:\n在扩展中注册菜单项出错!');
  1984. console.error(e);
  1985. }
  1986. GM_addStyle(style.basic);
  1987. if (isMobilePage()) {
  1988. console.info('福利吧论坛 - 好孩子看得见:\n当前页面为移动端页面。');
  1989. document.addEventListener('DOMContentLoaded', () => {
  1990. mobileInit();
  1991. });
  1992. } else {
  1993. if (document.head) {
  1994. if (document.head.querySelector('title')) {
  1995. if (status.nightEnable) {
  1996. status.nightStyleDom = GM_addStyle(style.night);
  1997. }
  1998. pcInit();
  1999. } else {
  2000. document.addEventListener('DOMContentLoaded', function () {
  2001. console.warn('福利吧论坛 - 好孩子看得见:\n网页加载失败。即将自动刷新重载。');
  2002. status.timer4 && clearTimeout(status.timer4);
  2003. status.timer4 = setTimeout(() => {
  2004. location.reload();
  2005. }, 2000);
  2006. });
  2007. }
  2008. } else {
  2009. if (status.nightEnable) {
  2010. status.nightStyleDom = GM_addStyle(style.night);
  2011. }
  2012. pcInit();
  2013. }
  2014. }
  2015. }
  2016. GM_config.init({
  2017. id: 'myGoodBoyConfig',
  2018. title: GM_config.create('a', {
  2019. textContent: '好孩子看得见-设置 ver.' + GM_info.script.version,
  2020. title: '点击跳转到脚本页面' + getUpdateTime(GM_info.script.lastModified),
  2021. target: '_blank',
  2022. href: 'https://sleazyfork.org/zh-CN/scripts/381494',
  2023. }),
  2024. skin: 'tab',
  2025. css: style.settings,
  2026. frameStyle: {
  2027. width: '400px',
  2028. height: '720px',
  2029. },
  2030. fields: {
  2031. autoCheckInEnable: {
  2032. label: '自动签到',
  2033. title: '进入论坛后自动点击签到按钮',
  2034. labelPos: 'right',
  2035. type: 'checkbox',
  2036. default: true,
  2037. section: GM_config.create('a', {
  2038. textContent: '作者: pana',
  2039. title: '点击反馈问题',
  2040. target: '_blank',
  2041. href: location.origin + '/home.php?mod=spacecp&ac=pm&op=showmsg&touid=8548',
  2042. }),
  2043. },
  2044. nightBtnEnable: {
  2045. label: '显示切换夜间模式的悬浮按钮',
  2046. title: '将鼠标移至网页右下角弹出 (仅支持电脑端页面)',
  2047. labelPos: 'right',
  2048. type: 'checkbox',
  2049. default: false,
  2050. },
  2051. codeEnable: {
  2052. label: '显示编解码工具的悬浮按钮',
  2053. title: '将鼠标移至网页右下角弹出 (仅支持电脑端页面)',
  2054. labelPos: 'right',
  2055. type: 'checkbox',
  2056. default: false,
  2057. },
  2058. copyEnable: {
  2059. label: '显示复制按钮',
  2060. title: '在所提取链接后显示复制按钮',
  2061. labelPos: 'right',
  2062. type: 'checkbox',
  2063. default: true,
  2064. },
  2065. extractEnable: {
  2066. label: '识别文字中的网址并转换为超链接',
  2067. title: '将帖子中网址文字转换为可点击访问的超链接',
  2068. labelPos: 'right',
  2069. type: 'checkbox',
  2070. default: true,
  2071. },
  2072. checkEnable: {
  2073. label: '自动检测百度网盘链接有效性',
  2074. title: '检测并标记出已经失效的百度网盘链接',
  2075. labelPos: 'right',
  2076. type: 'checkbox',
  2077. default: false,
  2078. },
  2079. displayPosition: {
  2080. label: '自定义提取链接的显示位置: ',
  2081. title: '指定所提取链接的显示位置 (仅支持电脑端页面)',
  2082. labelPos: 'left',
  2083. type: 'select',
  2084. options: ['底部', '右侧'],
  2085. default: '底部',
  2086. },
  2087. maxLinkNumber: {
  2088. label: '所提取链接的最大显示数量: ',
  2089. title: '每个楼层所提取链接的默认最大显示数量值 (-1 表示无限制)',
  2090. labelPos: 'left',
  2091. type: 'int',
  2092. size: 18,
  2093. default: 5,
  2094. },
  2095. linkColor: {
  2096. label: '自定义提取链接的文字颜色: ',
  2097. title: '设定所提取链接显示的文字颜色',
  2098. labelPos: 'left',
  2099. type: 'text',
  2100. size: 18,
  2101. default: '#369',
  2102. },
  2103. textColor: {
  2104. label: '自定义隐藏文字的高亮颜色: ',
  2105. title: '设定将隐藏文字高亮的颜色',
  2106. labelPos: 'left',
  2107. type: 'text',
  2108. size: 18,
  2109. default: '#FF33CC',
  2110. },
  2111. signatureEnable: {
  2112. label: '显示签名档折叠图标',
  2113. title: '在签名档的左上方显示一个折叠图标',
  2114. labelPos: 'right',
  2115. type: 'checkbox',
  2116. default: true,
  2117. line: 'start',
  2118. },
  2119. signatureSwitch: {
  2120. label: '签名档的默认折叠状态: ',
  2121. title: '自定义签名档默认的折叠状态',
  2122. labelPos: 'left',
  2123. type: 'select',
  2124. options: ['展开', '收起'],
  2125. default: '展开',
  2126. line: 'end',
  2127. },
  2128. highlightEnable: {
  2129. label: '启用热帖高亮功能',
  2130. title: '在帖子列表页面开启热帖高亮 (移动端页面只支持回复高亮)',
  2131. labelPos: 'right',
  2132. type: 'checkbox',
  2133. default: true,
  2134. line: 'start',
  2135. },
  2136. agreeThreshold: {
  2137. label: '按分享值高亮的阈值: ',
  2138. title: '分享值>=阈值时高亮',
  2139. labelPos: 'left',
  2140. type: 'unsigned int',
  2141. size: 18,
  2142. default: 20,
  2143. },
  2144. agreeColor: {
  2145. label: '按分享值高亮的颜色: ',
  2146. title: '优化级高',
  2147. labelPos: 'left',
  2148. type: 'text',
  2149. size: 18,
  2150. default: '#EE1B2E',
  2151. },
  2152. replyTHreshold: {
  2153. label: '按回复数高亮的阈值: ',
  2154. title: '回复数>=阈值时高亮',
  2155. labelPos: 'left',
  2156. type: 'unsigned int',
  2157. size: 18,
  2158. default: 50,
  2159. },
  2160. replyColor: {
  2161. label: '按回复数高亮的颜色: ',
  2162. title: '优化级低',
  2163. labelPos: 'left',
  2164. type: 'text',
  2165. size: 18,
  2166. default: '#2B65B7',
  2167. line: 'end',
  2168. },
  2169. visitedEnable: {
  2170. label: '标记已打开过的帖子',
  2171. title: '允许将已打开过的帖子设置成自定义的颜色',
  2172. labelPos: 'right',
  2173. type: 'checkbox',
  2174. default: false,
  2175. line: 'start',
  2176. },
  2177. visitedColor: {
  2178. label: '自定义已打开过的帖子的颜色',
  2179. title: '优先级最高',
  2180. labelPos: 'left',
  2181. type: 'text',
  2182. size: 18,
  2183. default: '#666',
  2184. line: 'end',
  2185. },
  2186. },
  2187. events: {
  2188. init: () => {
  2189. console.debug('福利吧论坛 - 好孩子看得见:\n配置信息读取完成。');
  2190. aInit();
  2191. },
  2192. save: () => {
  2193. location.reload();
  2194. },
  2195. },
  2196. });
  2197. })();