futaba reverse res search

被引用レスをポップアップ表示・自分の書き込みへのレスを通知しちゃう

目前为 2022-11-23 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name futaba reverse res search
  3. // @namespace https://github.com/himuro-majika
  4. // @version 1.0.2
  5. // @description 被引用レスをポップアップ表示・自分の書き込みへのレスを通知しちゃう
  6. // @author himuro_majika
  7. // @license MIT
  8. // @match *://*.2chan.net/*/res/*
  9. // @icon https://www.google.com/s2/favicons?sz=64&domain=2chan.net
  10. // @grant GM_getValue
  11. // @grant GM_setValue
  12. // @grant GM_listValues
  13. // @grant GM_deleteValue
  14. // @grant GM_notification
  15. // ==/UserScript==
  16.  
  17. (() => {
  18. 'use strict';
  19.  
  20. // ====オプション====
  21. const USE_NOTIFICATION = true; //自分の書き込みに新着レスが有ったときに通知を表示する(true/false)
  22. const NOTIFICATION_TIMEOUT = 5000; //通知の表示時間(ms)
  23. const MAX_COMMENT_HISTORY_THREAD = 100; //最大レス履歴保存数(スレ)
  24. const MARKER_CHAR = "★"; //自分の書き込みに付けるマーカーの文字(任意:絵文字も可)
  25. // ================
  26.  
  27. const script_title = "GM_FRRS";
  28. let qtlist = [];
  29. let popupOpenTimer;
  30. let popupCloseTimer;
  31. let url;
  32. let isPosted = false;
  33. let commentHistoryList;
  34. const startTime = new Date().getTime(); //count parsing time
  35. init();
  36.  
  37. function init() {
  38. url = getUrl();
  39. checkLoading();
  40. makeSelfCommentPicker();
  41. observeInserted();
  42. setOnSubmitEvent();
  43. }
  44.  
  45. function initParse() {
  46. searchSelfComment();
  47. searchQuotedRes();
  48. addCounter();
  49. console.log(script_title + ' - Parsing: ' + ((new Date()).getTime() - startTime) + 'msec'); //log parsing time
  50. }
  51.  
  52. function getUrl() {
  53. return location.href.match(/^.+:\/\/(.+)/)[1];
  54. }
  55.  
  56. function checkLoading() {
  57. let loadingTimer = setInterval(() => {
  58. if (!document.getElementById("futakuro-loading")) {
  59. initParse();
  60. clearInterval(loadingTimer);
  61. }
  62. }, 100)
  63. }
  64.  
  65. function getThreImgSrc() {
  66. let threimg = document.querySelector("#master img");
  67. if (!threimg) threimg = document.querySelector(".thre > a > img");
  68. return threimg.src
  69. }
  70.  
  71. function getQuotedRes() {
  72. return document.querySelectorAll(".thre td blockquote font[color='#789922']");
  73. }
  74.  
  75. function searchQuotedRes(quote) {
  76. if (arguments.length == 0) {
  77. quote = getQuotedRes();
  78. }
  79. let bqs = document.querySelectorAll(".thre blockquote");
  80. quote.forEach(item => {
  81. let qtnum = getResNoFromTdChild(item.parentNode);
  82. let qtsrcnum = _searchQtSrc(item, qtnum, bqs);
  83. let qtitemindex = qtlist.findIndex(item => item.qtsrcnum == qtsrcnum);
  84.  
  85. if (qtitemindex !== -1 && qtlist[qtitemindex].qtres.findIndex(item => item == qtnum) !== -1) return
  86.  
  87. if (qtitemindex !== -1) {
  88. qtlist[qtitemindex].qtres.push(qtnum);
  89. } else {
  90. let qtres = [];
  91. qtres.push(qtnum);
  92. let objqt = {
  93. "qtsrcnum": qtsrcnum,
  94. "qtres": qtres
  95. }
  96. qtlist.push(objqt)
  97. }
  98. if (commentHistoryList && commentHistoryList.length > 0) {
  99. commentHistoryList.forEach(com => {
  100. if (com.resno == qtsrcnum) {
  101. highlightResponse(item);
  102. if (arguments.length > 0) {
  103. let text = "";
  104. item.parentNode.childNodes.forEach(node => {
  105. if (node.nodeName == "#text") {
  106. text += node.textContent + "\n";
  107. }
  108. });
  109. showNotification(text);
  110. }
  111. }
  112. })
  113. }
  114. });
  115. }
  116.  
  117. function _searchQtSrc(qt, qtnum, bqs) {
  118. let qtText = qt.innerText.substr(1).trim();
  119. let qtsrcnum = "0";
  120.  
  121. // レスナンバー(No.)
  122. // /^ *(No)?\.?[0-9]+ *$/
  123. let matchResNo = qtText.match(/^\s*No\.(\d+)\s*$/);
  124. if (matchResNo && document.getElementById("delcheck" + matchResNo[1])) {
  125. qtsrcnum = matchResNo[1];
  126. return qtsrcnum;
  127. }
  128.  
  129. // 画像ファイル名
  130. // /^[0-9]+\.(jpg|png|gif|webm|mp4|webp)$/
  131. let matchFileName = qtText.match(/^\s*(\d+\.(jpg|png|gif|webm|mp4|webp))\s*$/);
  132. if (matchFileName) {
  133. let matchFileEle = document.querySelector('.thre a[href$="' + matchFileName[1] + '"]');
  134. if (matchFileEle) {
  135. qtsrcnum = getResNoFromTdChild(matchFileEle);
  136. return qtsrcnum;
  137. }
  138. }
  139.  
  140. // レス本文
  141. if (qtText.substr(0,1) == ">") return qtsrcnum;
  142. const qtresnum = parseInt(qt.parentNode.parentNode.querySelector(".rsc").textContent);
  143. for (let i = qtresnum - 1; i > 0; i--) {
  144. let t = "";
  145. bqs[i].childNodes.forEach(node => {
  146. if (node.nodeName == "#text") {
  147. t += node.textContent;
  148. }
  149. });
  150. if (t.indexOf(qtText) >= 0) {
  151. qtsrcnum = getResNoFromTdChild(bqs[i].parentNode);
  152. if (qtsrcnum == qtnum) qtsrcnum = "0";
  153. break;
  154. }
  155. }
  156.  
  157. return qtsrcnum;
  158. }
  159.  
  160. // 被引用数の表示
  161. function addCounter() {
  162. let existedCounter = document.querySelectorAll("." + script_title + "_Counter");
  163. existedCounter.forEach(item => {
  164. item.remove();
  165. })
  166. let cno = document.querySelectorAll(".cno");
  167. cno.forEach(no => {
  168. let num = no.textContent.match(/\d+$/);
  169. let qtindex = qtlist.findIndex(item => item.qtsrcnum == num);
  170. if (qtindex == -1) return;
  171. let qtcount = qtlist[qtindex].qtres.length;
  172. const counter = document.createElement("a");
  173.  
  174. counter.innerText = qtcount + "レス";
  175. counter.classList.add(script_title + "_Counter");
  176. counter.style.color = "#117743";
  177. counter.style.marginLeft = "0.5em";
  178. counter.setAttribute(script_title + "_num", num);
  179.  
  180.  
  181. counter.addEventListener("mouseenter", popupQuoteRes);
  182. counter.addEventListener("mouseleave", removePopup);
  183. no.parentNode.insertBefore(counter, no);
  184. });
  185. }
  186.  
  187. // 被引用レスのポップアップ
  188. function popupQuoteRes(e) {
  189. if (!this.closest("." + script_title + "_popup")) {
  190. removePopupAll();
  191. }
  192. clearTimeout(popupCloseTimer);
  193. clearTimeout(popupOpenTimer);
  194. popupOpenTimer = setTimeout(() => {
  195. let srcnum = this.getAttribute(script_title + "_num");
  196. let qtitem = qtlist.find(item => item.qtsrcnum == srcnum);
  197. let qtres = qtitem.qtres;
  198. let resListContainer = makePopupContainer();
  199.  
  200. let xpos = this.getBoundingClientRect().left + window.scrollX - 20;
  201. let ypos = this.getBoundingClientRect().bottom + window.scrollY;
  202. resListContainer.style.top = ypos.toString() + "px";
  203. if (xpos + 500 > window.innerWidth) {
  204. resListContainer.style.right = "20px";
  205. } else {
  206. resListContainer.style.left = xpos.toString() + "px";
  207. }
  208.  
  209. let resListTable = setPopupContent(qtres);
  210.  
  211. resListContainer.appendChild(resListTable);
  212. document.querySelector("div.thre").appendChild(resListContainer);
  213. }, 200);
  214. }
  215.  
  216. function setPopupContent(resnolist) {
  217. if (resnolist.length == 0) {
  218. let noEle = document.createElement("div");
  219. noEle.textContent = "該当レスがありません。";
  220. return noEle;
  221. }
  222. let resListTable = document.createElement("table");
  223. let resListTbody = document.createElement("tbody");
  224.  
  225. resnolist.forEach(res => {
  226. let td = document.getElementById("delcheck" + res).parentNode.cloneNode(true);
  227. let rsc = td.querySelector(".rsc");
  228. rsc.classList.add("qtjmp");
  229. let jumpid = rsc.id;
  230. rsc.removeAttribute("id");
  231. rsc.addEventListener("click", () => {
  232. let jumptarget = document.getElementById(jumpid).parentNode;
  233. window.scroll(0, jumptarget.getBoundingClientRect().top + window.pageYOffset);
  234. removePopup();
  235. });
  236.  
  237. const counter = td.querySelector("." + script_title + "_Counter");
  238. if (counter) {
  239. counter.addEventListener("mouseenter", popupQuoteRes);
  240. counter.addEventListener("mouseleave", removePopup);
  241. }
  242.  
  243. const futakuro_resno = td.querySelector(".res_no");
  244. if (futakuro_resno) futakuro_resno.style.display = "none";
  245.  
  246. if (checkAkahukuEnabled()) {
  247. // resListContainer.setAttribute("__akahuku_reply_popup_index", resno);
  248. let gtdiv = document.createElement("div");
  249. gtdiv.classList.add("akahuku_popup_content_blockquote");
  250. let bq = td.querySelector("blockquote");
  251. gtdiv.innerHTML = bq.innerHTML;
  252. bq.remove();
  253. td.appendChild(gtdiv);
  254. }
  255. let resListTr = document.createElement("tr");
  256. resListTr.appendChild(td);
  257. resListTbody.appendChild(resListTr);
  258. })
  259. resListTable.appendChild(resListTbody);
  260.  
  261. return resListTable;
  262. }
  263.  
  264. function makePopupContainer() {
  265. let container = document.createElement("div");
  266. container.classList.add(script_title + "_popup");
  267. if (checkAkahukuEnabled()) {
  268. container.classList.add("akahuku_reply_popup");
  269. } else {
  270. container.style.backgroundColor = "#F0E0D6";
  271. container.style.boxShadow = "1px 1px 3px 1px #777";
  272. container.style.borderRadius = "5px";
  273. container.style.fontSize = "0.85em";
  274. }
  275. container.style.position = "absolute";
  276. container.style.zIndex = 302;
  277. container.addEventListener("mouseenter", () => {
  278. clearTimeout(popupCloseTimer);
  279. });
  280. container.addEventListener("mouseleave", removePopup);
  281. return container;
  282. }
  283.  
  284. function removePopup(souceEl) {
  285. clearTimeout(popupCloseTimer);
  286. clearTimeout(popupOpenTimer);
  287. if (!souceEl) return;
  288. if (!souceEl.relatedTarget) return;
  289. if (souceEl.srcElement.className == "GM_FRRS_Counter" &&
  290. souceEl.relatedTarget.closest(".GM_FRRS_popup")) return;
  291. if (souceEl.srcElement.classList.contains("GM_FRRS_popup") &&
  292. souceEl.relatedTarget.closest(".GM_FRRS_popup")) {
  293. removeForwardPopupSibling(souceEl.relatedTarget.closest(".GM_FRRS_popup"));
  294. return;
  295. }
  296. popupCloseTimer = setTimeout(() => {
  297. removePopupAll();
  298. }, 500);
  299. }
  300.  
  301. function removePopupAll() {
  302. let popup = document.querySelectorAll("." + script_title + "_popup");
  303. if (!popup) return;
  304. popup.forEach(p => {
  305. p.remove();
  306. })
  307. }
  308.  
  309. function removeForwardPopupSibling(ele) {
  310. if (!ele.nextElementSibling) return;
  311. let nextsibling = ele.nextElementSibling;
  312. if (nextsibling.classList.contains("GM_FRRS_popup")) {
  313. nextsibling.remove();
  314. } else {
  315. return;
  316. }
  317. removeForwardPopupSibling(ele);
  318. }
  319.  
  320. // 続きを読むで挿入される要素を監視
  321. function observeInserted() {
  322. let target = document.querySelector(".thre");
  323. if (!target) return;
  324. let observer = new MutationObserver((mutations) => {
  325. mutations.forEach(mutation => {
  326. if (!mutation.addedNodes.length) return;
  327. if (mutation.addedNodes[0].className == script_title + "_popup") return;
  328. if (mutation.addedNodes[0].querySelector(".rtd")) {
  329. refreshCounter(mutation.addedNodes);
  330. }
  331. });
  332. if (isPosted) {
  333. isPosted = false;
  334. selfComment(mutations);
  335. }
  336. });
  337. observer.observe(target, {
  338. childList: true
  339. });
  340. }
  341.  
  342. function refreshCounter(nodes) {
  343. let qt = nodes[0].querySelectorAll(".thre td blockquote font[color='#789922']");
  344. if (!qt.length) return;
  345. searchQuotedRes(qt);
  346. addCounter();
  347. }
  348.  
  349. // レス投稿時のイベント設定
  350. function setOnSubmitEvent() {
  351. let formEle = document.getElementById("fm");
  352.  
  353. formEle.addEventListener("submit", () => {
  354. onCommentSend();
  355. });
  356. let button = formEle.querySelector("input[type='submit'");
  357. if (button) {
  358. button.addEventListener("click", () => {
  359. onCommentSend();
  360. });
  361. }
  362. }
  363.  
  364. function onCommentSend() {
  365. if (isPosted) return;
  366. isPosted = true;
  367. let textbody = document.getElementById("ftxa").value.trim();
  368. storeCommentHistory(textbody);
  369. }
  370.  
  371. // 書き込み履歴の保存
  372. function storeCommentHistory(commentText) {
  373. if (typeof(commentText) !== "string") return;
  374.  
  375. commentHistoryList = getCommentHistory();
  376.  
  377. let comment = {
  378. "comment": commentText,
  379. "resno": ""
  380. }
  381. if (!commentHistoryList) {
  382. commentHistoryList = [];
  383. }
  384. commentHistoryList.push(comment);
  385. setCommentHistory(commentHistoryList);
  386. console.log(commentHistoryList);
  387. setTimeout(() => {
  388. expireCommentHistory();
  389. }, 5000);
  390. }
  391.  
  392. function getCommentHistory() {
  393. let commentHistory = getValue(url);
  394. return commentHistory;
  395. }
  396.  
  397. function setCommentHistory(commenthistory) {
  398. setValue(url, commenthistory);
  399. return;
  400. }
  401.  
  402. function searchSelfComment() {
  403. let listUpdatedFlag = false;
  404. commentHistoryList = getCommentHistory();
  405. if (!commentHistoryList) return;
  406. commentHistoryList.forEach(element => {
  407. let elresno = element.resno;
  408. if (elresno !== "") {
  409. let sd = document.getElementById("sd" + elresno);
  410. if (!sd) return;
  411. highlightOwnRes(sd);
  412. }
  413. let comment = element.comment;
  414. if (elresno == "" && comment) {
  415. console.log(comment);
  416. let bq = document.querySelectorAll(".thre .rtd blockquote");
  417. bq.forEach(item => {
  418. let bqtext = item.innerText;
  419. if (comment == bqtext) {
  420. let bqresno = getResNoFromTdChild(item);
  421. let itemsd = document.getElementById("sd" + bqresno);
  422. if (!itemsd) return;
  423. highlightOwnRes(itemsd);
  424. element.resno = bqresno;
  425. listUpdatedFlag = true;
  426. // console.log(bqresno);
  427. }
  428. })
  429. }
  430. });
  431. if (listUpdatedFlag) {
  432. setCommentHistory(commentHistoryList);
  433. }
  434. // console.log(qtlist);
  435. }
  436.  
  437. function selfComment(mutations) {
  438. commentHistoryList = getCommentHistory();
  439. if (!commentHistoryList) return;
  440. if (commentHistoryList[commentHistoryList.length - 1].resno !== "") return;
  441. let latestStoredComment = commentHistoryList[commentHistoryList.length - 1].comment;
  442. let hitres;
  443. mutations.forEach(mutation => {
  444. if (mutation.addedNodes.length && mutation.addedNodes[0].querySelector(".rtd")) {
  445. let table = mutation.addedNodes[0];
  446. let bq = table.querySelector("blockquote");
  447. if (!bq) return;
  448. let bqtext = bq.innerText;
  449. if (latestStoredComment === "") {
  450. if (bqtext !== "キタ━━━(゚∀゚)━━━!!" &&
  451. bqtext !== "キタ━━━━━━(゚∀゚)━━━━━━ !!!!!" &&
  452. bqtext !== "本文無し") {
  453. return;
  454. }
  455. } else if (bqtext !== latestStoredComment) {
  456. return;
  457. }
  458. commentHistoryList[commentHistoryList.length - 1].resno = getResNoFromTdChild(bq);
  459. hitres = table;
  460. }
  461. });
  462. if (!hitres) return;
  463. // console.log(hitres);
  464. setCommentHistory(commentHistoryList);
  465. let sd = hitres.querySelector(".sod");
  466. highlightOwnRes(sd);
  467. // console.log(commentHistoryList);
  468. }
  469.  
  470. function highlightOwnRes(node) {
  471. if (node.parentNode.querySelector("." + script_title + "_own_res")) return;
  472. let marker = document.createElement("span");
  473.  
  474. marker.innerText = MARKER_CHAR;
  475. marker.classList.add(script_title + "_own_res");
  476. // marker.style.fontWeight = "bold";
  477. marker.style.color = "#117743";
  478. marker.style.cursor = "pointer";
  479. marker.addEventListener("click", () => {
  480. let selfResList = document.querySelectorAll("." + script_title + "_own_res");
  481. popupSelfCommentList(selfResList);
  482. });
  483. let rsc = node.parentNode.querySelector(".rsc");
  484. let futakuroResNo = node.parentNode.querySelector(".res_no");
  485. if (futakuroResNo) {
  486. rsc = futakuroResNo;
  487. }
  488. rsc.style.color = "#1b54ff";
  489. rsc.style.fontWeight = "bold";
  490. rsc.style.fontSize = "smaller";
  491. rsc.style.cursor = "pointer";
  492. rsc.addEventListener("click", () => {
  493. let selfResList = document.querySelectorAll("." + script_title + "_own_res");
  494. popupSelfCommentList(selfResList);
  495. });
  496. node.parentNode.insertBefore(marker, node.previousSibling);
  497. }
  498.  
  499. // 自分の書き込みへのレスをハイライト
  500. function highlightResponse(bq) {
  501. bq.parentNode.classList.add(script_title + "_response");
  502. let rsc = bq.parentNode.parentNode.querySelector(".rsc");
  503. let futakuroResNo = bq.parentNode.parentNode.querySelector(".res_no");
  504. if (futakuroResNo) {
  505. rsc = futakuroResNo;
  506. }
  507. rsc.style.color = "#ff0078";
  508. rsc.style.fontWeight = "bold";
  509. rsc.style.fontSize = "smaller";
  510. rsc.style.cursor = "pointer";
  511. rsc.addEventListener("click", () => {
  512. let selfResList = document.querySelectorAll("." + script_title + "_response");
  513. document.getElementById(script_title + "_new_comment").style.color = "#0040ee";
  514. popupSelfCommentList(selfResList);
  515. });
  516. }
  517.  
  518. // 自分の書き込み一覧ポップアップ
  519. function makeSelfCommentPicker() {
  520. let commentPickerContainer = document.createElement("div");
  521. commentPickerContainer.id = script_title + "_comment_picker_container";
  522. commentPickerContainer.style.fontSize = "9pt";
  523.  
  524. let commentPicker = document.createElement("a");
  525. commentPicker.id = script_title + "_self_comment_picker";
  526. commentPicker.textContent = "📑[自分の書き込み]";
  527. commentPicker.style.color = "#0040ee";
  528. commentPicker.style.cursor = "pointer";
  529. commentPicker.addEventListener("click", () => {
  530. let selfResList = document.querySelectorAll("." + script_title + "_own_res");
  531. popupSelfCommentList(selfResList);
  532. });
  533. let newComment = document.createElement("a");
  534. newComment.id = script_title + "_new_comment";
  535. newComment.textContent = "[書き込みへのレス]";
  536. newComment.style.cursor = "pointer";
  537. newComment.style.color = "#0040ee";
  538. newComment.addEventListener("click", () => {
  539. let selfResList = document.querySelectorAll("." + script_title + "_response");
  540. document.getElementById(script_title + "_new_comment").style.color = "#0040ee";
  541. popupSelfCommentList(selfResList);
  542. });
  543. commentPickerContainer.appendChild(commentPicker);
  544. commentPickerContainer.appendChild(newComment);
  545.  
  546. let pwd = document.getElementById("usercounter");
  547. pwd.parentNode.insertBefore(commentPickerContainer, pwd);
  548. }
  549.  
  550. function popupSelfCommentList(selfResList) {
  551. let popup = document.getElementById(script_title + "_own_res_popup");
  552. if (popup) {
  553. popup.remove();
  554. return;
  555. }
  556. let container = makeSelfCommentListContainer();
  557. let selfResNoList = [];
  558. selfResList.forEach(res => {
  559. selfResNoList.push(getResNoFromTdChild(res));
  560. });
  561. let qttable = setPopupContent(selfResNoList);
  562. container.appendChild(qttable);
  563. document.querySelector("html body").appendChild(container);
  564. }
  565.  
  566. function makeSelfCommentListContainer() {
  567. let container = document.createElement("div");
  568. container.id = script_title + "_own_res_popup";
  569. if (checkAkahukuEnabled()) {
  570. container.classList.add("akahuku_reply_popup");
  571. } else {
  572. container.style.boxShadow = "1px 1px 3px 1px #777";
  573. container.style.borderRadius = "5px";
  574. container.style.fontSize = "0.85em";
  575. }
  576. container.style.position = "fixed";
  577. container.style.right = "10px";
  578. container.style.bottom = "400px";
  579. container.style.zIndex = "301";
  580. container.style.overflowY = "scroll";
  581. container.style.maxHeight = "65vh";
  582. container.style.maxWidth = "65em";
  583.  
  584. return container;
  585. }
  586.  
  587. function showNotification(text) {
  588. const newRes = document.getElementById(script_title + "_new_comment");
  589. newRes.style.display = "";
  590. newRes.style.color = "#F00";
  591.  
  592. if (!USE_NOTIFICATION) return;
  593.  
  594. GM_notification({
  595. title: "書き込みに新しいレスがあります",
  596. image: getThreImgSrc(),
  597. text: text,
  598. timeout: NOTIFICATION_TIMEOUT,
  599. onclick: () =>{
  600. // console.log("notification clicked");
  601. }
  602. });
  603. }
  604.  
  605. function getResNoFromTdChild(ele) {
  606. let cno = ele.parentNode.querySelector(".cno");
  607. let resno = cno.textContent.replace("No.", "");
  608. return resno;
  609. }
  610.  
  611. function checkAkahukuEnabled() {
  612. return document.getElementById("akahuku_postform") != null
  613. }
  614.  
  615. function checkFutakuroEnabled() {
  616. return document.getElementById("postform") != null;
  617. }
  618.  
  619. function expireCommentHistory() {
  620. const historyList = getListValues();
  621. // console.log(historyList);
  622. if (historyList.length > MAX_COMMENT_HISTORY_THREAD) {
  623. for (let i = 0; i < historyList.length - MAX_COMMENT_HISTORY_THREAD; i++) {
  624. deleteValue(historyList[i]);
  625. console.log(script_title + " expire comment history: " + historyList[i]);
  626. }
  627. }
  628. }
  629.  
  630. function getValue(name) {
  631. if (!name) return;
  632. try {
  633. let val = GM_getValue(name);
  634. if (!val) return 0;
  635. // console.log(val);
  636. return val;
  637. } catch(e) {
  638. console.log(e);
  639. return 0;
  640. }
  641. }
  642.  
  643. function setValue(name, val) {
  644. if (!name || !val) return;
  645. try {
  646. GM_setValue(name, val);
  647. } catch(e) {
  648. console.log(e);
  649. return;
  650. }
  651. }
  652.  
  653. function getListValues() {
  654. try {
  655. const gmlistvalues = GM_listValues();
  656. if (!gmlistvalues) return;
  657. return gmlistvalues;
  658. } catch (e) {
  659. console.log(e);
  660. return;
  661. }
  662. }
  663.  
  664. function deleteValue(name) {
  665. if (!name) return;
  666. try {
  667. GM_deleteValue(name);
  668. return;
  669. } catch (e) {
  670. console.log(e);
  671. return 0;
  672. }
  673. }
  674. })();