Sleazy Fork is available in English.

Sadpanda torrent inline

Inlines torrent into to gallery view in sadpanda & regular panda, and adds a hotkey to download the most popular torrent.

  1. // ==UserScript==
  2. // @name Sadpanda torrent inline
  3. // @namespace exh
  4. // @description Inlines torrent into to gallery view in sadpanda & regular panda, and adds a hotkey to download the most popular torrent.
  5. // @include http://exhentai.org/g/*
  6. // @include https://exhentai.org/g/*
  7. // @include http://g.e-hentai.org/g/*
  8. // @include https://g.e-hentai.org/g/*
  9. // @version 1
  10. // @grant none
  11. // @require https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js
  12. // ==/UserScript==
  13.  
  14.  
  15. var link = getTorrentLink();
  16. loadTorrentHtml(link);
  17.  
  18.  
  19.  
  20. function getTorrentLink() {
  21. var EXTRACT_URL_REGEX = /http.*\.php\?[a-zA-Z0-9&=]*/
  22. var linkElm = $('.gm a:contains("Torrent")')
  23. var link = linkElm.attr('onclick').match(EXTRACT_URL_REGEX);
  24. return link;
  25. }
  26.  
  27. function loadTorrentHtml(link) {
  28. $.get(link,null,function(a,b,c) {
  29. var data = extractTorrentInfoFromResp(a);
  30. data = $('<div></div>').append(data);
  31. data.addClass('gm');
  32. data.addClass('torrent-info');
  33. data.css('background','inherit');
  34. addHotkeys(data);
  35. var target = $('.gm').first();
  36. target.after(data);
  37. //document.body.insertBefore(data[0],document.body.firstChild);
  38. })
  39. }
  40.  
  41. function addHotkeys(data) {
  42. var items = data.find('form');
  43. var maxDownloads = 0;
  44. var activeTorrent = null;
  45. var activeTorrentInfo = null;
  46. for (var i = 0; i < items.length; i++) {
  47. var tInfo = getTorrentInfo($(items[i]));
  48. if (tInfo.downloads > maxDownloads) {
  49. maxDownloads = tInfo.downloads;
  50. activeTorrent = $(items[i]);
  51. activeTorrentInfo = tInfo;
  52. }
  53. }
  54. if (activeTorrent) {
  55. addHotkey(activeTorrent);
  56. }
  57. }
  58.  
  59. function addHotkey(item) {
  60. var cell = item.find('tr').first().find('td')[2];
  61. cell = $(cell);
  62. cell.css('font-weight','bold');
  63. cell.css('color','red');
  64. cell.css('font-size','125%');
  65. cell.text("Press space to download");
  66. var linkElm = item.find('a');
  67. shortcut.add('space', function() {
  68. linkElm[0].click();
  69. });
  70. }
  71.  
  72. function getTorrentInfo(item) {
  73. var seedsElm = item.find('span:Contains("Seeds")');
  74. var peersElm = item.find('span:Contains("Peers")');
  75. var downloadsElm = item.find('span:Contains("Downloads")');
  76. var sizeElm = item.find('span:Contains("Size")');
  77. var postedElm = item.find('span:Contains("Posted")');
  78. return {
  79. seeds: getInfo(seedsElm),
  80. peers: getInfo(peersElm),
  81. downloads: getInfo(downloadsElm),
  82. size: getInfo(sizeElm),
  83. posted: getInfo(postedElm)
  84. }
  85. }
  86.  
  87. function getInfo(elm) {
  88. return parseInt(getTextComponent(elm.parent()))
  89. }
  90. function getTextComponent(elm) {
  91. return elm.clone() //clone the element
  92. .children() //select all the children
  93. .remove() //remove all the children
  94. .end() //again go back to selected element
  95. .text();
  96. }
  97.  
  98. function extractTorrentInfoFromResp(resp) {
  99. var res = $(resp).find('#torrentinfo form');
  100. res.splice(res.length-1,1);
  101. return res;
  102. }
  103.  
  104. function writeInfo(info) {
  105. var d = $('<div>' + info + '</div>')
  106. document.body.insertBefore(d[0],document.body.firstChild);
  107. }
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116. /**
  117. * http://www.openjs.com/scripts/events/keyboard_shortcuts/
  118. * Version : 2.01.B
  119. * By Binny V A
  120. * License : BSD
  121. */
  122. shortcut = {
  123. 'all_shortcuts':{},//All the shortcuts are stored in this array
  124. 'add': function(shortcut_combination,callback,opt) {
  125. //Provide a set of default options
  126. var default_options = {
  127. 'type':'keydown',
  128. 'propagate':false,
  129. 'disable_in_input':false,
  130. 'target':document,
  131. 'keycode':false
  132. }
  133. if(!opt) opt = default_options;
  134. else {
  135. for(var dfo in default_options) {
  136. if(typeof opt[dfo] == 'undefined') opt[dfo] = default_options[dfo];
  137. }
  138. }
  139.  
  140. var ele = opt.target;
  141. if(typeof opt.target == 'string') ele = document.getElementById(opt.target);
  142. var ths = this;
  143. shortcut_combination = shortcut_combination.toLowerCase();
  144.  
  145. //The function to be called at keypress
  146. var func = function(e) {
  147. e = e || window.event;
  148. if(opt['disable_in_input']) { //Don't enable shortcut keys in Input, Textarea fields
  149. var element;
  150. if(e.target) element=e.target;
  151. else if(e.srcElement) element=e.srcElement;
  152. if(element.nodeType==3) element=element.parentNode;
  153.  
  154. if(element.tagName == 'INPUT' || element.tagName == 'TEXTAREA') return;
  155. }
  156. //Find Which key is pressed
  157. if (e.keyCode) code = e.keyCode;
  158. else if (e.which) code = e.which;
  159. var character = String.fromCharCode(code).toLowerCase();
  160. if(code == 188) character=","; //If the user presses , when the type is onkeydown
  161. if(code == 190) character="."; //If the user presses , when the type is onkeydown
  162.  
  163. var keys = shortcut_combination.split("+");
  164. //Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked
  165. var kp = 0;
  166. //Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken
  167. var shift_nums = {
  168. "`":"~",
  169. "1":"!",
  170. "2":"@",
  171. "3":"#",
  172. "4":"$",
  173. "5":"%",
  174. "6":"^",
  175. "7":"&",
  176. "8":"*",
  177. "9":"(",
  178. "0":")",
  179. "-":"_",
  180. "=":"+",
  181. ";":":",
  182. "'":"\"",
  183. ",":"<",
  184. ".":">",
  185. "/":"?",
  186. "\\":"|"
  187. }
  188. //Special Keys - and their codes
  189. var special_keys = {
  190. 'esc':27,
  191. 'escape':27,
  192. 'tab':9,
  193. 'space':32,
  194. 'return':13,
  195. 'enter':13,
  196. 'backspace':8,
  197. 'scrolllock':145,
  198. 'scroll_lock':145,
  199. 'scroll':145,
  200. 'capslock':20,
  201. 'caps_lock':20,
  202. 'caps':20,
  203. 'numlock':144,
  204. 'num_lock':144,
  205. 'num':144,
  206. 'pause':19,
  207. 'break':19,
  208. 'insert':45,
  209. 'home':36,
  210. 'delete':46,
  211. 'end':35,
  212. 'pageup':33,
  213. 'page_up':33,
  214. 'pu':33,
  215. 'pagedown':34,
  216. 'page_down':34,
  217. 'pd':34,
  218. 'left':37,
  219. 'up':38,
  220. 'right':39,
  221. 'down':40,
  222. 'f1':112,
  223. 'f2':113,
  224. 'f3':114,
  225. 'f4':115,
  226. 'f5':116,
  227. 'f6':117,
  228. 'f7':118,
  229. 'f8':119,
  230. 'f9':120,
  231. 'f10':121,
  232. 'f11':122,
  233. 'f12':123
  234. }
  235. var modifiers = {
  236. shift: { wanted:false, pressed:false},
  237. ctrl : { wanted:false, pressed:false},
  238. alt : { wanted:false, pressed:false},
  239. meta : { wanted:false, pressed:false} //Meta is Mac specific
  240. };
  241. if(e.ctrlKey) modifiers.ctrl.pressed = true;
  242. if(e.shiftKey) modifiers.shift.pressed = true;
  243. if(e.altKey) modifiers.alt.pressed = true;
  244. if(e.metaKey) modifiers.meta.pressed = true;
  245. for(var i=0; k=keys[i],i<keys.length; i++) {
  246. //Modifiers
  247. if(k == 'ctrl' || k == 'control') {
  248. kp++;
  249. modifiers.ctrl.wanted = true;
  250.  
  251. } else if(k == 'shift') {
  252. kp++;
  253. modifiers.shift.wanted = true;
  254.  
  255. } else if(k == 'alt') {
  256. kp++;
  257. modifiers.alt.wanted = true;
  258. } else if(k == 'meta') {
  259. kp++;
  260. modifiers.meta.wanted = true;
  261. } else if(k.length > 1) { //If it is a special key
  262. if(special_keys[k] == code) kp++;
  263. } else if(opt['keycode']) {
  264. if(opt['keycode'] == code) kp++;
  265.  
  266. } else { //The special keys did not match
  267. if(character == k) kp++;
  268. else {
  269. if(shift_nums[character] && e.shiftKey) { //Stupid Shift key bug created by using lowercase
  270. character = shift_nums[character];
  271. if(character == k) kp++;
  272. }
  273. }
  274. }
  275. }
  276. if(kp == keys.length &&
  277. modifiers.ctrl.pressed == modifiers.ctrl.wanted &&
  278. modifiers.shift.pressed == modifiers.shift.wanted &&
  279. modifiers.alt.pressed == modifiers.alt.wanted &&
  280. modifiers.meta.pressed == modifiers.meta.wanted) {
  281. callback(e);
  282. if(!opt['propagate']) { //Stop the event
  283. //e.cancelBubble is supported by IE - this will kill the bubbling process.
  284. e.cancelBubble = true;
  285. e.returnValue = false;
  286. //e.stopPropagation works in Firefox.
  287. if (e.stopPropagation) {
  288. e.stopPropagation();
  289. e.preventDefault();
  290. }
  291. return false;
  292. }
  293. }
  294. }
  295. this.all_shortcuts[shortcut_combination] = {
  296. 'callback':func,
  297. 'target':ele,
  298. 'event': opt['type']
  299. };
  300. //Attach the function with the event
  301. if(ele.addEventListener) ele.addEventListener(opt['type'], func, false);
  302. else if(ele.attachEvent) ele.attachEvent('on'+opt['type'], func);
  303. else ele['on'+opt['type']] = func;
  304. },
  305.  
  306. //Remove the shortcut - just specify the shortcut and I will remove the binding
  307. 'remove':function(shortcut_combination) {
  308. shortcut_combination = shortcut_combination.toLowerCase();
  309. var binding = this.all_shortcuts[shortcut_combination];
  310. delete(this.all_shortcuts[shortcut_combination])
  311. if(!binding) return;
  312. var type = binding['event'];
  313. var ele = binding['target'];
  314. var callback = binding['callback'];
  315.  
  316. if(ele.detachEvent) ele.detachEvent('on'+type, callback);
  317. else if(ele.removeEventListener) ele.removeEventListener(type, callback, false);
  318. else ele['on'+type] = false;
  319. }
  320. }