E-Hentai/ExHentai Torrents History Tagger

记录EXHT BT下载历史

  1. // ==UserScript==
  2. // @name E-Hentai/ExHentai Torrents History Tagger
  3. // @namespace pikashi@gmail.com
  4. // @version 0.2.3
  5. // @description 记录EXHT BT下载历史
  6. // @author pks
  7. // @match https://e-hentai.org/*
  8. // @match https://exhentai.org/*
  9. // @exclude https://exhentai.org/g/*
  10. // @exclude https://e-hentai.org/g/*
  11. // @require http://code.jquery.com/jquery-1.11.0.min.js
  12. // @grant GM_setValue
  13. // @grant GM_getValue
  14. // @icon https://e-hentai.org/favicon.ico
  15. // ==/UserScript==
  16.  
  17. let patterns = [
  18.  
  19. // 以下为匹配规则列表,各自对应的下载历史单独保存互不干涉,除非name相同(name相同的规则将会合并)
  20. // regex:必须,为路径匹配正则表达式
  21. // priority:必须,数值越小优先级越高;取值范围为小于9999的正整数,不同条目的priority数值不能相同
  22. // quota:可选,默认值200,全局匹配默认值5000,可按自己需要修改;历史条目数量上限值;如果超出上限值的新的下载历史加入,会自动删除最旧(GID最老的)的下载历史;
  23. // checkDefault:可选,默认值false,仅在非默认规则中使用;如果设为true则此规则工作时也会检查全局匹配列表,且创建新下载时会向全局列表提交下载历史
  24. { regex: /\/tag\/tankoubon\b(\/\d+)?/, name: 'tankoubon', priority:1, quota: 300, checkDefault:true },
  25. { regex: /\bf_search=anthology\b/, name: 'anthology', priority:2 },
  26. { regex: /.*/, name: 'default', priority:9999 }// 此行为全局匹配,请勿修改priority值,如果只想使用全局匹配,请把上面的其他规则都删除
  27.  
  28. ],
  29.  
  30. count = 200, // 保存上限默认值(不包括全局匹配)
  31. checkDefault = false,
  32. defaultQuota = 5000, // 全局历史条目上限单独设定
  33.  
  34. $ = jQuery
  35. ;
  36.  
  37. (function() {
  38. 'use strict';
  39.  
  40. var css = `
  41. #tipEle {
  42. padding:5px;
  43. position: fixed;
  44. right: 10px;
  45. bottom: 10px;
  46. z-index: 50;
  47. background:
  48. green;text-align:
  49. left;font-size: 14px;
  50. max-width: 320px;
  51. }
  52.  
  53. #tipEle .highlight {
  54. color:yellow;
  55. }
  56.  
  57. #tipEle:hover {
  58. opacity: 0.5;
  59. }
  60.  
  61. .gl1t.downloaded {
  62. opacity: 0.9;
  63. border-radius: 5px;
  64. position:relative;
  65. }
  66.  
  67. .gl1t.downloaded > a > div::before {
  68. content: "✔";
  69. color: greenyellow;
  70. font-size: 2.4rem;
  71. display: inline-block;
  72. position: absolute;
  73. bottom: 18px;
  74. left: 3px;
  75. z-index: 50;
  76. }
  77. `,
  78. head = document.head || document.getElementsByTagName('head')[0],
  79. style = document.createElement('style');
  80.  
  81. style.type = 'text/css';
  82. if (style.styleSheet){
  83. style.styleSheet.cssText = css;
  84. } else {
  85. style.appendChild(document.createTextNode(css));
  86. }
  87.  
  88. head.appendChild(style);
  89.  
  90. // Your code here...
  91. $(function() {
  92. let mode = '',list = [];
  93.  
  94. function createTip() {
  95. if (GM_getValue(mode + 'LastDownload')) {
  96. let tipEle = document.createElement('p');
  97. tipEle.innerHTML = `上次下载:<br>${GM_getValue(mode + 'LastDownload')}`;
  98. tipEle.id = 'tipEle';
  99. if (document.querySelector('#tipEle')) document.querySelector('#tipEle').remove();
  100. document.body.appendChild(tipEle);
  101. }
  102. }
  103.  
  104. function getGID(url) {
  105. return url.match(/g\/(\d+)\//i)[1];
  106. }
  107.  
  108. function getPath(url) {
  109. return new URL(url).pathname;
  110. }
  111.  
  112. for (let pattern of patterns.sort((a,b)=>(a.priority - b.priority))) {
  113. if (pattern.regex.test(window.location.href)) {
  114. mode = pattern.name.toLowerCase();
  115. if (!!pattern.quota && pattern.name !== 'default') { count = pattern.quota; }
  116. if (!!pattern.checkDefault && pattern.name !== 'default') { checkDefault = true; }
  117. break;
  118. }
  119. }
  120. console.log('mode is ' + mode + ', quota limit is ' + count + ', checkDefault status is ' + checkDefault);
  121.  
  122.  
  123. if (mode !== '') {
  124.  
  125. const historyVar = mode + 'LastDownloads';
  126.  
  127. let last200Downloads = [];
  128. let defaultLastDownloads = [];
  129. if (checkDefault && mode !== 'default') {
  130. defaultLastDownloads = JSON.parse(GM_getValue('defaultLastDownloads'));
  131. }
  132.  
  133. if (GM_getValue(historyVar)) {
  134. last200Downloads = JSON.parse(GM_getValue(historyVar));
  135. }
  136.  
  137. $('.gl1t').each((_,e) => {
  138. let id = getGID($(e).find('a')[0].href);
  139. // console.log(id);
  140. for (const gid of last200Downloads) {
  141. if (gid === id) {
  142. // console.log(`find match ${gid}`)
  143. $(e).addClass('downloaded');
  144. }
  145. }
  146. });
  147.  
  148. $('div.itg.gld').on('click', 'a.torrentLink', e => {
  149. // console.log(last200Downloads);
  150.  
  151. let url = $(e.target).closest('.gl3t').find('a').first()[0].href;
  152. let gid = getGID(url);
  153. let path = getPath(url);
  154. let date = $(e.target).closest('.gl1t').find('.cs.ct3').next().text();
  155. let title = $(e.target).closest('.gl3t').find('a img')[0].title;
  156.  
  157. let text = `标题:<span class="highlight">${title}</span><br>日期:<span class="highlight">${date}</span><br>URL:<span class="highlight">${url}</span>`;
  158. let dateRaw = new Date(date).valueOf();
  159. list.push({date: dateRaw, text: text});
  160. list.sort((a, b) => {
  161. return b.date - a.date;
  162. });
  163.  
  164. console.log('torrent downloading');
  165.  
  166. // console.log('mode is ' + mode);
  167. // console.info(list);
  168.  
  169. GM_setValue(mode + 'LastDownload', list[0].text);
  170.  
  171. if (last200Downloads.indexOf(gid) === -1 || (defaultLastDownloads.indexOf(gid) === -1 && checkDefault)) {
  172. if (last200Downloads.length >= count) last200Downloads.pop();
  173. last200Downloads.unshift(gid);
  174. GM_setValue(historyVar, JSON.stringify(last200Downloads.sort().reverse()));
  175.  
  176. if (checkDefault && mode !== 'default') {
  177. if (defaultLastDownloads.length >= defaultQuota) defaultLastDownloads.pop();
  178. defaultLastDownloads.unshift(gid);
  179. GM_setValue('defaultLastDownloads', JSON.stringify(defaultLastDownloads.sort().reverse()));
  180. }
  181. $(e.target).closest('.gl1t').addClass('downloaded');
  182. }
  183.  
  184.  
  185. // createTip();
  186.  
  187. });
  188.  
  189. // createTip();
  190. }
  191. });
  192. })();