Enhancement Userscript for LIHKG

An Enhancement Userscript for LIHKG

  1. // ==UserScript==
  2. // @name Enhancement Userscript for LIHKG
  3. // @version 0.6.3
  4. // @description An Enhancement Userscript for LIHKG
  5. // @include /https?\:\/\/lihkg\.com/
  6. // @icon https://www.google.com/s2/favicons?domain=lihkg.com
  7. // @grant GM_addStyle
  8. // @license MIT
  9. // @namespace https://gf.qytechs.cn/users/371179
  10. // ==/UserScript==
  11. (function() {
  12. 'use strict';
  13.  
  14. GM_addStyle([
  15.  
  16. `
  17. /*
  18. html.skip-drag-upload .EGBBkGyEbfIEpHMLTW84H{
  19. display:none !important;
  20. }
  21. */
  22.  
  23. /* main textarea */
  24. ._2ME7dqW8n0YSe687nDnGvI ._3ILx6bqxXMKzVd1P5DRS9F{
  25. padding-bottom: 40px;
  26. }
  27.  
  28.  
  29. /* div 放開圖片即可上載*/
  30. .EGBBkGyEbfIEpHMLTW84H{
  31. opacity: 1 !important;
  32. pointer-events: all !important;
  33. left: 5%;
  34. right: 5%;
  35. top: calc(100% - 35px);
  36. bottom: 0;
  37. width: auto;
  38. height: auto;
  39. }
  40.  
  41. /* div Preview ~ div + div 放開圖片即可上載*/
  42. ._1TdM0E7HcWQwmxXpfa6yJg ~ ._2ME7dqW8n0YSe687nDnGvI .EGBBkGyEbfIEpHMLTW84H{
  43. visibility: collapse;
  44. }
  45.  
  46. `,
  47.  
  48. // css fix for thread posts positioning
  49. `
  50. body ._21IQKhlBjN2jlHS_TVgI3l:after {left:0.4rem}
  51. body ._21IQKhlBjN2jlHS_TVgI3l .vv9keWAXpwoonDah6rSIU ._3D2lzCKDMcdgEkexZrTSUh{margin-left: -6px;width: 16px;}
  52. `,
  53.  
  54. // css fix for like and dislike due to js hack of like count and dislike count (reply posts)
  55. `
  56. body label[for*="-dislike-like"] {display:inline-block !important;}
  57. body label[for*="-like-like"] {display:inline-block !important;}
  58. body ._3ExaynSI6tUp5h1U50MHtI ._3imUf8qB9LmLpk_t5PjDm4>div:first-child+div:last-child {margin-left:-6px;}
  59. `,
  60.  
  61. // css fix for like and dislike due to js hack of like count and dislike count (main thread)
  62. // empty full space char for maintaining padding when the count is not yet shown
  63. `
  64. span[data-tip="正評"]:not([data-score])::after{
  65. content: " ";
  66. font-size: .6rem;
  67. font-weight: 400;
  68. margin-top: .3rem;
  69. }
  70. span[data-tip="負評"]:not([data-score])::after{
  71. content: " ";
  72. font-size: .6rem;
  73. font-weight: 400;
  74. margin-top: .3rem;
  75. }
  76. span[data-tip="正評"],span[data-tip="負評"]{
  77. padding-top:0px !important;
  78. }
  79. `,
  80.  
  81. // kiwi browser css fix
  82. `
  83. @supports not (padding-bottom: env(safe-area-inset-bottom)){
  84. ._3dwGLtjqTgI2gc9wpc7FuT {
  85. padding: 1rem .6rem calc(1rem + 0px) calc(.7rem + 0px);
  86. }
  87. }
  88. `,
  89.  
  90. // po reply - userselect for icons
  91. `
  92. html body ._1Ku9qL4qhkBDwAgVLYcQdi[class], html body ._1Ku9qL4qhkBDwAgVLYcQdi[class]:hover {
  93. user-select:none !important;
  94. }
  95. `
  96. ].map(x => x.trim()).join('\n'))
  97.  
  98.  
  99. let isNumCheck = function(n) {
  100. return n > 0 || n < 0 || n === 0
  101. }
  102. let postDetails = {}
  103. let threadDetails = {}
  104. let pendingRefreshThread = false;
  105.  
  106. let testBlockElm = function(elm) {
  107. if (elm && elm.nodeType == 1) {
  108. switch (elm.tagName) {
  109. case 'DIV':
  110. case 'P':
  111. case 'BLOCKQUOTE':
  112. return true;
  113.  
  114. default:
  115. return false;
  116.  
  117. }
  118.  
  119. }
  120. }
  121.  
  122.  
  123. document.cssAll = function() {
  124. return [...document.querySelectorAll.apply(this, arguments)]
  125. }
  126.  
  127. function urlConvert(url) {
  128. let src = url.replace(/\w+\:\/\//, '')
  129. let replacements = [...src.matchAll(/[\w\.]+/g)].filter((t) => /\./.test(t))
  130. if (replacements.length > 1) {
  131. replacements.length--;
  132.  
  133. }
  134. replacements.forEach((s) => {
  135. src = src.replace(s, '')
  136. })
  137.  
  138. src = src.replace(/\/+/g, '/')
  139.  
  140. return src;
  141.  
  142. }
  143.  
  144. let emoji = {};
  145. setTimeout(function() {
  146. console.log(emoji)
  147. }, 1500)
  148.  
  149. setInterval(() => {
  150.  
  151. document.cssAll('img[src*="lihkg.com"][alt]:not([title])').forEach(function(imgElm) {
  152. let src = imgElm.getAttribute('src');
  153. let erc = urlConvert(src)
  154. let imgAlt = imgElm.getAttribute('alt') || "";
  155. if (/^[\x20-\x7E]+$/.test(imgAlt) && /\W/.test(imgAlt)) {
  156. emoji[erc] = imgAlt.trim()
  157. }
  158.  
  159. imgElm.setAttribute('title', imgAlt)
  160.  
  161. })
  162.  
  163.  
  164. document.cssAll('a[href*="profile/"]:not([href*="//"]):not([title])').forEach(function(aElm) {
  165. aElm.setAttribute('title', aElm.getAttribute('href'))
  166. })
  167.  
  168. document.cssAll('[data-ic~="hkgmoji"]:not([title])>img[src*="lihkg.com"]:not([alt])').forEach(function(imgElm) {
  169. let src = imgElm.getAttribute('src');
  170. let erc = urlConvert(src)
  171. let text = emoji[erc] ? emoji[erc] : "[img]" + erc + "[/img]"
  172. imgElm.parentNode.setAttribute('title', text)
  173. imgElm.setAttribute('alt', text)
  174.  
  175.  
  176. })
  177.  
  178.  
  179.  
  180. document.cssAll('img[src]:not([alt]),img[src][alt=""]').forEach((el) => {
  181.  
  182. if (el.getAttribute('alt') || el.getAttribute('title')) return;
  183.  
  184. let text = '';
  185. if (el.tagName.toLowerCase() == 'img' && el.getAttribute('data-original')) {
  186. text = '[img]' + el.getAttribute('data-original') + '[/img]';
  187. } else if (el.tagName.toLowerCase() == 'img' && el.getAttribute('src')) {
  188. text = '[img]' + el.getAttribute('src') + '[/img]';
  189. }
  190. if (text) el.setAttribute('alt', text)
  191. if (text) el.setAttribute('title', text)
  192.  
  193. })
  194.  
  195.  
  196.  
  197.  
  198. document.cssAll('[data-post-id]:not([hacked])').forEach((el) => {
  199.  
  200. el.setAttribute('hacked', 'true');
  201. let post_id = el.getAttribute('data-post-id');
  202. if (!post_id) return;
  203.  
  204. //console.log(post_id, postDetails)
  205. let post_detail = postDetails[post_id]
  206. if (post_detail) {
  207. // console.log(55,post_detail)
  208.  
  209. }
  210.  
  211. })
  212.  
  213.  
  214.  
  215. }, 33)
  216.  
  217.  
  218.  
  219. function refreshingThreadEvent(thread_id) {
  220.  
  221.  
  222. console.log("refreshingThreadEvent", threadDetails[thread_id])
  223. if (thread_id && threadDetails[thread_id]) {
  224.  
  225.  
  226. document.cssAll('span[data-tip="正評"]').forEach((elm) => {
  227.  
  228. elm.setAttribute('data-score', threadDetails[thread_id]["like_count"]);
  229. elm.style.paddingTop = '0px';
  230. })
  231.  
  232.  
  233. document.cssAll('span[data-tip="負評"]').forEach((elm) => {
  234.  
  235. elm.setAttribute('data-score', threadDetails[thread_id]["dislike_count"]);
  236. elm.style.paddingTop = '0px';
  237. })
  238.  
  239.  
  240.  
  241. }
  242.  
  243.  
  244. }
  245.  
  246.  
  247. let cid_refreshingThread = 0;
  248.  
  249. function refreshingThreadRunning() {
  250.  
  251. if (!cid_refreshingThread) return;
  252.  
  253.  
  254. let titlespan = document.cssAll('a[href^="/category/"]+span');
  255. if (titlespan.length == 1) {
  256. let titlespanElm = titlespan[0]
  257.  
  258. if (!titlespanElm.querySelector('noscript')) {
  259. titlespanElm.appendChild(document.createElement('noscript'))
  260.  
  261.  
  262. if (pendingRefreshThread) {
  263.  
  264. let thread_id = pendingRefreshThread === true ? (/thread\/(\d+)\//.exec(location + "") || [null, null])[1] : pendingRefreshThread
  265.  
  266. pendingRefreshThread = false;
  267. clearInterval(cid_refreshingThread);
  268. cid_refreshingThread = 0;
  269. refreshingThreadEvent(thread_id)
  270.  
  271.  
  272. }
  273.  
  274.  
  275. }
  276. }
  277.  
  278. }
  279.  
  280.  
  281.  
  282.  
  283. let makePlain = false;
  284.  
  285.  
  286. document.addEventListener("dragstart", function(evt) {
  287. console.log(evt.target)
  288. if(!evt || !evt.target) return;
  289.  
  290. let type = 0
  291. if(evt.target.nodeType!==1 && evt.target.parentElement/* && evt.target.parentElement.closest('[data-post-id]')*/){
  292. type=1;
  293. }
  294.  
  295. if(evt.target.nodeType ===1){
  296. if(!evt.target.matches('img[alt][src][title]'))return;
  297. let alt = evt.target.getAttribute('alt')+'';
  298. if(!alt)return;
  299. if(/https?\:\/\//.test(alt))return;
  300. if(/^[a-zA-Z0-9]+$/.test(alt))return;
  301. if(/[\u0100-\uFFFF]/.test(alt))return;
  302. type = 2;
  303.  
  304. console.log(alt)
  305.  
  306. evt.dataTransfer.setData('text/plain', alt);
  307.  
  308. evt.stopPropagation()
  309. evt.stopImmediatePropagation();
  310.  
  311. }
  312. if(type>0){
  313. evt.dropEffect='copy';
  314. evt.effectAllowed = "all";
  315.  
  316. document.documentElement.classList.add('skip-drag-upload')
  317. }
  318. }, true);
  319.  
  320.  
  321.  
  322. function makeRangeFromXY(evt){
  323.  
  324. let range=null;
  325. if (document.caretRangeFromPoint) { // Chrome
  326. range=document.caretRangeFromPoint(evt.clientX,evt.clientY);
  327. }
  328. else if (evt.rangeParent) { // Firefox
  329. range=document.createRange(); range.setStart(evt.rangeParent,evt.rangeOffset);
  330. }
  331. return range;
  332. }
  333. document.addEventListener("drop", function(evt) {
  334.  
  335. if(!evt || !evt.target)return;
  336.  
  337. let node = evt.target;
  338.  
  339. if(node.nodeType!==1 && node.parentNode && node.parentNode.nodeType===1) node= node.parentNode;
  340.  
  341. if(node.nodeType===1 &&node.closest('div.ProseMirror[contenteditable]')){
  342. evt.preventDefault();
  343. let range = makeRangeFromXY(evt)
  344. var sel = window.getSelection();
  345. sel.removeAllRanges(); sel.addRange(range);
  346.  
  347. let p = sel.anchorNode
  348. while(p&&p.parentNode){
  349. if(p.nodeType===1&&p.matches('div.ProseMirror[contenteditable]')){
  350. p.focus();
  351. p.classList.add('ProseMirror-focused');
  352. break;
  353. }
  354. p=p.parentNode;
  355. }
  356.  
  357. range.collapse(true);
  358.  
  359. let text = evt.dataTransfer.getData('text/plain')
  360. document.execCommand('insertHTML',false,text);
  361.  
  362. //sel.removeAllRanges();
  363.  
  364. let mRange = window.getSelection().getRangeAt(0);
  365.  
  366. mRange.setStart(mRange.endContainer,mRange.endOffset-text.length);
  367. mRange.setEnd(mRange.endContainer,mRange.endOffset);
  368.  
  369. // nRange.collapse(true);
  370. // sel.addRange(nRange)
  371.  
  372.  
  373. }
  374.  
  375. document.documentElement.classList.remove('skip-drag-upload')
  376.  
  377. },true)
  378.  
  379.  
  380. document.addEventListener("dragend", function(evt) {
  381.  
  382. document.documentElement.classList.remove('skip-drag-upload')
  383.  
  384. let p = document.querySelector('div.EGBBkGyEbfIEpHMLTW84H[style]')
  385. if(p){
  386. p.style.opacity='0';
  387. p.style.pointerEvents='none';
  388. }
  389.  
  390. },true)
  391.  
  392. /*
  393. document.addEventListener("dragover", function(evt) {
  394. if(!evt || !evt.target)return;
  395. try{
  396.  
  397. if(!evt.target.matches('[contenteditable], textarea, div.EGBBkGyEbfIEpHMLTW84H, div._1xaNo-2jhq5KooKoBBRKwe '))return;
  398. }catch(e){return;}
  399. console.log(evt)
  400. evt.stopPropagation();
  401. }, true);
  402. */
  403.  
  404.  
  405. let injection = function() {
  406.  
  407.  
  408. function extractRawURL(thumbnailURL) {
  409.  
  410. let u = [...thumbnailURL.matchAll(/[\?\&]\w+\=([\x21-\x25\x27-\x3E\x40-\x7E]+)/g)].map(d => d[1])
  411. if (u.length) {
  412. let uMaxT = Math.max(...u.map(t => t.length))
  413. let u0 = u.filter(t => t.length == uMaxT)[0]
  414.  
  415. if (u0) {
  416.  
  417. let v0 = null
  418. try {
  419. v0 = decodeURIComponent(u0)
  420. } catch (e) {}
  421. //console.log(v0,u0)
  422. if (v0) {
  423. return v0
  424. }
  425.  
  426. }
  427. }
  428. return null
  429. }
  430.  
  431. if (!JSON._parse && JSON.parse) {
  432. JSON._parse = JSON.parse
  433. JSON.parse = function(text, r) {
  434. /*
  435. if (text && typeof text == "string" && text.indexOf('display_vote') > 0) {
  436. text = text.replace(/([\'\"])display_vote[\'\"]\s*:\s*false/gi, '$1display_vote$1:true')
  437. }
  438. */
  439. let res = JSON._parse.apply(this, arguments)
  440.  
  441. let contentFix = (resObj) => {
  442. if(!resObj || typeof resObj!='object')return;
  443. for (let k in resObj) {
  444. if (typeof resObj[k] == 'object') contentFix(resObj[k]);
  445. else if (k=='display_vote' && resObj[k]===false){
  446. resObj[k]=true;
  447. }
  448. else if (k == 'msg' && typeof resObj[k] == 'string') {
  449.  
  450. let msg = resObj[k];
  451. let replace = false;
  452. let bmsg=msg
  453. msg = msg.replace(/(\<img\s+src\=\")(https?\:\/\/i\.lih\.kg\/thumbnail\?[^\"]+)(\"[^\>]+\>)/g, function(s, a, b, c) {
  454.  
  455. let v0 = extractRawURL(b)
  456. if (v0) {
  457. replace = true;
  458. return s.replace(b,v0).replace(b,v0).replace(b,v0)
  459.  
  460. /*
  461. console.log(v0, b)
  462.  
  463. let v1 = '<img src="' + v0 + '" data-thumbnail-src="' + b + '" />';
  464.  
  465. return v1
  466. */
  467. }
  468.  
  469. return a + b + c
  470.  
  471. })
  472.  
  473. msg = msg.replace(
  474.  
  475. /<a\s+href=\"(https\:\/\/i\.lih\.kg\/thumbnail\?u=[^\?\s\x00-\x20\x7F-\xFF\"]+)\"[^<>]+>\1<\/a>/g,
  476. function(_, a) {
  477.  
  478. let b = extractRawURL(a)
  479. if (b) {
  480. replace = true
  481. return _.replace(a,b).replace(a,b)
  482. /*
  483. let a01 = encodeURIComponent(a)
  484. let a02 = a01.replace(/\%26amp\%3B/gi, '%26')
  485. let b01 = encodeURIComponent(b)
  486. let c = _.replace(a, b).replace(a, b).replace(a02, b01).replace(a01, b01)
  487.  
  488. return c*/
  489. }
  490. return _
  491. })
  492.  
  493.  
  494. if (replace) {
  495. console.log(333,bmsg,msg)
  496. resObj[k] = msg;
  497.  
  498. }
  499. }
  500. }
  501. }
  502.  
  503. contentFix(res)
  504.  
  505. return res;
  506. }
  507. }
  508.  
  509. let api_callback = "uleccyqjstui"
  510.  
  511. ;
  512. ((xmlhr, xmlhr_pt) => {
  513. if (!xmlhr_pt._open) {
  514. xmlhr_pt._open = xmlhr_pt.open;
  515.  
  516.  
  517. xmlhr_pt.open = function() {
  518. // console.log('xmlhr_open', arguments)
  519. if (/https?\:\/\/[\x20-2E\x30-5B\x5D-\x7E]*lihkg\.com\/[\x20-\x7E]*api[\x20-\x7E]+/.test(arguments[1])) {
  520. this._url = arguments[1];
  521.  
  522. console.log('_url', this._url)
  523. }
  524. this._open.apply(this, arguments)
  525. }
  526. }
  527.  
  528.  
  529.  
  530. if (!xmlhr_pt._send) {
  531. xmlhr_pt._send = xmlhr_pt.send;
  532.  
  533.  
  534. xmlhr_pt.send = function() {
  535. if (this._url) {
  536. this.addEventListener('load', function() {
  537. let resText = this.responseText;
  538. let jsonObj = null;
  539. if (resText && typeof resText == 'string') {
  540. try {
  541. jsonObj = JSON.parse(resText);
  542. } catch (e) {}
  543. }
  544.  
  545. if (jsonObj) {
  546. //like_count
  547.  
  548. let code_num = 0;
  549.  
  550. if (jsonObj.success == 1 && jsonObj.response && jsonObj.response.item_data && jsonObj.response.item_data.length >= 1 && jsonObj.response.item_data[0]["post_id"]) {
  551. code_num |= 16;
  552. }
  553. if (jsonObj.success == 1 && jsonObj.response && jsonObj.response.thread_id) {
  554. code_num |= 8;
  555. }
  556. // console.log('code', code_num);
  557. let event = new CustomEvent(api_callback, {
  558. detail: {
  559. code: code_num,
  560. responseJSON: jsonObj
  561. }
  562. });
  563. document.dispatchEvent(event);
  564.  
  565.  
  566.  
  567. //console.log(jsonObj)
  568. }
  569.  
  570. })
  571. }
  572. // console.log('xmlhr_send', arguments)
  573. this._send.apply(this, arguments)
  574. }
  575. }
  576.  
  577.  
  578. })(XMLHttpRequest, XMLHttpRequest.prototype)
  579.  
  580. }
  581.  
  582. let jsscript = document.createElement('script');
  583. jsscript.type = 'text/javascript';
  584. jsscript.innerHTML = '(' + injection + ')()';
  585. document.documentElement.appendChild(jsscript)
  586.  
  587. let api_callback = "uleccyqjstui"
  588. //data-post-id="5226a9cb7b395fbc182d183a6ee9b35c8adfd2fe"
  589. document.addEventListener(api_callback, function(e) {
  590. if (!e || !e.detail) return;
  591. console.log("API_CALLBACK", e.detail)
  592. let jsonObj;
  593. let code_num = e.detail.code
  594. switch (true) {
  595.  
  596. case (code_num & 8) == 8: //main thread
  597.  
  598. case (code_num & 16) == 16: //posts
  599.  
  600.  
  601. jsonObj = e.detail.responseJSON;
  602.  
  603.  
  604. if (jsonObj.success == 1 && jsonObj.response && jsonObj.response.item_data && jsonObj.response.item_data.length >= 1 && jsonObj.response.item_data[0]["post_id"]) {
  605. let reply_post_fx = (reply_item) => {
  606. if ('dislike_count' in reply_item && 'like_count' in reply_item && reply_item["post_id"]) {
  607.  
  608. let like_count = +reply_item['like_count']
  609. let dislike_count = +reply_item['dislike_count']
  610. let post_id = reply_item['post_id']
  611.  
  612. if (isNumCheck(like_count) && isNumCheck(dislike_count) && post_id) {
  613. postDetails[post_id] = {
  614. 'like_count': like_count,
  615. 'dislike_count': dislike_count
  616. }
  617. }
  618.  
  619. }
  620. };
  621. jsonObj.response.item_data.forEach(reply_post_fx)
  622. if (jsonObj.response.pinned_post && jsonObj.response.pinned_post["post_id"]) reply_post_fx(jsonObj.response.pinned_post)
  623.  
  624. }
  625.  
  626.  
  627.  
  628. if (jsonObj.success == 1 && jsonObj.response && jsonObj.response.thread_id) {
  629. let thread_fx = (thread_item) => {
  630. if ('like_count' in thread_item && 'dislike_count' in thread_item && thread_item["thread_id"]) {
  631.  
  632. let like_count = +thread_item['like_count']
  633. let dislike_count = +thread_item['dislike_count']
  634. let thread_id = thread_item['thread_id']
  635.  
  636. if (isNumCheck(like_count) && isNumCheck(dislike_count) && thread_id) {
  637. threadDetails[thread_id] = {
  638. 'like_count': like_count,
  639. 'dislike_count': dislike_count
  640. }
  641. pendingRefreshThread = thread_id;
  642. if (!cid_refreshingThread) cid_refreshingThread = setInterval(refreshingThreadRunning, 1);
  643. }
  644.  
  645. }
  646. };
  647. thread_fx(jsonObj.response)
  648. //console.log(99, threadDetails)
  649.  
  650. }
  651.  
  652. //console.log(jsonObj)
  653. break;
  654.  
  655.  
  656. default:
  657. }
  658.  
  659. });
  660.  
  661. const makePopup=(obj)=>{
  662. const {header, content1,content2, placeholder, remarks, btn1, btn2, closeFn, btn1Fn, btn2Fn}=obj;
  663.  
  664. let mcontent2=content2?`<br>${content2}<br>`:'';
  665.  
  666. let df = document.createElement('div');
  667.  
  668.  
  669. df.innerHTML=
  670. `
  671. <div class="_34dVbr5A8khk2N65H9Nl-j ">
  672. <div class="_27su4Zj_qATokwVdWIbEWB ">
  673. <div class="_1nqRVNQ2PyO3vnAwZIISAJ ">
  674. <div class="_2b5VMoBy8yIXlX-wC8v57F">${header}</div>
  675. <div class="_10tWW0o-L-5oSH8lCBl9ai"><i class="i-close"></i></div>
  676. </div>
  677. <div class="_27SmIe4FGDNnK7apcCB3W7">
  678. <div class="_3dbMg7zkkTIVJ5VZ3ygu4-">
  679. <div style="text-align: center; width: 240px;"><span>${content1}</span>${mcontent2}
  680. <div><input type="text" placeholder="${placeholder}" class=" _2SVsmVSmKfAWFlZGk_5_L8" value=""
  681. style="margin: 0.5rem 0px 0px;"><span
  682. style="font-size: 0.8rem; color: rgb(136, 136, 136);">${remarks}</span></div>
  683. </div>
  684. </div>
  685. </div>
  686. <div class="_2c5AwJ_0ePFIYub8OFE97J _2F7zIQl_1y5nHpDllTwX17"><a href="#">${btn1}</a><a
  687. href="#">${btn2}</a></div>
  688. </div>
  689. </div>
  690. `
  691. df.querySelector('._10tWW0o-L-5oSH8lCBl9ai').addEventListener('click', closeFn)
  692. let btnFns = [btn1Fn, btn2Fn];
  693. for(const [idx,a] of [...df.querySelectorAll('a[href*="#"]')].entries()) a.addEventListener('click', btnFns[idx])
  694. return df.querySelector('div');
  695.  
  696. }
  697.  
  698.  
  699. document.addEventListener('keyup',function(evt){
  700.  
  701. if(evt.code=='KeyB'){
  702.  
  703. let memberID = getSelection()+""
  704.  
  705. let m = null
  706. if(m=/\s*\#(\d+)\s*/.exec(memberID)){
  707.  
  708.  
  709.  
  710. let mPopup = makePopup({header:'Block', content1:`Memeber ID:${m[1]}`,content2:'', placeholder:'Type the Reason Here', remarks:'Please be careful', btn1:'Cancel', btn2:'Block',
  711. closeFn:function(){
  712. mPopup.remove()
  713. },
  714. btn1Fn:function(){
  715. mPopup.remove()
  716. },
  717. btn2Fn:function(){
  718. let reason = mPopup.querySelector('input[type="text"]').value || '';
  719.  
  720. fetch(`https://lihkg.com/api_v2/user/${m[1]}/block?reason=${reason}`)
  721. .then(response => response.json())
  722. .then(data => {
  723. if(data&& 'success' in data) alert( data.success?'成功':'失敗');
  724. console.log(data)
  725. });
  726.  
  727. mPopup.remove()
  728. },
  729.  
  730. })
  731. document.querySelector('body').appendChild(mPopup)
  732.  
  733. }
  734.  
  735.  
  736.  
  737.  
  738. }else if(evt.code=='KeyU'){
  739.  
  740. let memberID = getSelection()+""
  741.  
  742. let m = null
  743. if(m=/\s*\#(\d+)\s*/.exec(memberID)){
  744. fetch(`https://lihkg.com/api_v2/user/${m[1]}/unblock`)
  745. .then(response => response.json())
  746. .then(data => {
  747. if(data&& 'success' in data) alert( data.success?'成功':'失敗');
  748. console.log(data)
  749. });
  750. }
  751.  
  752.  
  753.  
  754.  
  755.  
  756. }
  757.  
  758. })
  759.  
  760.  
  761. // Your code here...
  762. })();

QingJ © 2025

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