down2transmission

Add a button in some private tracker site to support adding torrent to Transmission. Current support CCF and TTG.

当前为 2017-03-25 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name down2transmission
  3. // @namespace https://github.com/coderant/
  4. // @version 0.0.2
  5. // @description Add a button in some private tracker site to support adding torrent to Transmission. Current support CCF and TTG.
  6. // @supportURL https://github.com/coderant/down2transmission
  7. // @author Muffin_C
  8. // @match *://ccfbits.org/*
  9. // @match *://totheglory.im/*
  10. // @require https://code.jquery.com/jquery-3.2.1.min.js
  11. // @run-at document-end
  12. // @grant GM_xmlhttpRequest
  13. // ==/UserScript==
  14.  
  15. // Edit these before use.
  16. // http://192.168.1.1 for local access, input ddns for external access.
  17. // NO trailing slash(/).
  18. var transmission_url = "http://your.url.here";
  19.  
  20. // value of "rpc-port" in settings.json .
  21. var transmission_port = "9091";
  22.  
  23. // value of "rpc-url" in settings.json .
  24. var transmission_rpc_bind_address = "/transmission/";
  25.  
  26. // Authentication;
  27. var username = "your_username";
  28. var pw = "your_password";
  29.  
  30. // DO NOT EDIT BELOW.
  31. var rpc_url = transmission_url + ":" + transmission_port + transmission_rpc_bind_address + "rpc";
  32. console.log("Constructed url:" + rpc_url);
  33.  
  34. (function () {
  35. 'use strict';
  36. var site = window.location.href;
  37. var reCCF = /ccf/i;
  38. var reTTG = /totheglory/i;
  39. var baseURL = document.location.origin;
  40. var target;
  41. var buttonCSS = {
  42. 'background-color': '#B6B6B6',
  43. '-moz-border-radius': '2px',
  44. '-webkit-border-radius': '2px',
  45. 'border-radius': '2px',
  46. 'display': 'inline-block',
  47. 'cursor': 'pointer',
  48. 'color': '#000000',
  49. 'font-family': 'Verdana',
  50. 'font-size': '12px',
  51. 'padding': '2px 5px',
  52. 'text-decoration': 'none'
  53. };
  54.  
  55. if (reCCF.test(site)) {
  56. if (site.includes("browse")) {
  57. target = $('table[border=1][cellpadding=5]>>> td:nth-child(2):not([class])');
  58. target.each(function (i) {
  59. var pageURL = baseURL + "/" + $(this).find("a[title][href]").attr("href");
  60. var el = $('<a>', {id: "transmission_main_" + i, rel: pageURL, text: "Transmission"});
  61. el.css(buttonCSS);
  62. $(this).append(el);
  63. el.after($('<a>', {id: "transmission_main_" + i + "_result", text: "", style: "padding-left:5px"}));
  64. });
  65. }
  66. if (site.includes("details")) {
  67. target = $('a[class="index"][href*=".torrent"]');
  68. var ccfTorrentUrl = baseURL + "/" + target.attr("href");
  69. var ccfDetailInsert = $('<a>', {id: "transmission_detail", rel: ccfTorrentUrl, text: "Transmission"});
  70. ccfDetailInsert.css(buttonCSS);
  71. target.after(ccfDetailInsert);
  72. ccfDetailInsert.after($('<a>', {id: "transmission_detail_result", text: "", style: "padding-left:5px"}));
  73. target.after("<br>");
  74. }
  75. }
  76.  
  77. if (reTTG.test(site)) {
  78. if (site.includes("browse")) {
  79. target = $('tr[id]> td:nth-child(2)');
  80. target.each(function (i) {
  81. var page = $(this).find("a[href]").attr("href");
  82. var el = $('<a>', {id: "transmission_main_" + i, rel: baseURL + page, text: "Transmission"});
  83. el.css(buttonCSS);
  84. $(this).append(el);
  85. el.after($('<a>', {id: "transmission_main_" + i + "_result", text: "", style: "padding-left:5px"}));
  86. });
  87. }
  88. if (site.includes("/t/")) {
  89. target = $('a[class="index"][href*=".zip"]');
  90. var ttgTorrentUrl = baseURL + "/" + $('a[class="index"][href*=".torrent"]').attr("href");
  91. var ttgDetailInsert = $('<a>', {id: "transmission_detail", rel: ttgTorrentUrl, text: "Transmission"});
  92. ttgDetailInsert.css(buttonCSS);
  93. target.after(ttgDetailInsert);
  94. ttgDetailInsert.after($('<a>', {id: "transmission_detail_result", text: "", style: "padding-left:5px"}));
  95. target.after("<br>");
  96. }
  97. }
  98.  
  99. $('[id^=transmission]:not([id*=result]').click(function () {
  100. var torrentPage = $(this).attr('rel');
  101. var id = $(this).attr('id');
  102. var resultText = $("#" + id + "_result");
  103. resultText.text("Submitting to Transmission...");
  104. console.log(id + " is clicked");
  105. if (id.includes("main")) {
  106. GM_xmlhttpRequest({
  107. method: "GET",
  108. url: torrentPage,
  109. onload: function (response) {
  110. // console.log("Start fetching torrent details");
  111. var torrentURL = baseURL + "/" + $(response.responseText).find('a[href*=".torrent"]').attr('href');
  112. // console.log("Extracted torrent url: " + torrentURL);
  113. var request = {
  114. arguments: {cookies: getCookie(), filename: torrentURL},
  115. method: "torrent-add",
  116. tag: 80
  117. };
  118. console.log("Clicked:" + id);
  119. addTorrent($("#" + id), $("#" + id + "_result"), request);
  120. }
  121. });
  122. }
  123. if (id.includes("detail")) {
  124. var torrentURL = baseURL + "/" + $('a[class="index"][href*=".torrent"]').attr('href');
  125. var request = {arguments: {cookies: getCookie(), filename: torrentURL}, method: "torrent-add", tag: 80};
  126. addTorrent($("#" + id), resultText, request);
  127. }
  128. });
  129. })();
  130.  
  131. function addTorrent(button, result, request, sessionId, tries) {
  132. if (!tries) {
  133. tries = 0;
  134. }
  135. if (tries === 3) {
  136. alert("p2transmission: Too many Error 409: Conflict.\nCheck your transmission installation");
  137. return;
  138. }
  139. console.log("sending torrent with sessionid: (" + sessionId);
  140. console.log("sending: " + JSON.stringify(request));
  141. GM_xmlhttpRequest({
  142. method: "POST",
  143. user: username,
  144. password: pw,
  145. url: rpc_url,
  146. data: JSON.stringify(request),
  147. headers: {
  148. "X-Transmission-Session-Id": sessionId
  149. },
  150. onload: function (response) {
  151. console.log([
  152. response.status,
  153. response.statusText,
  154. response.responseText
  155. ].join("\n"));
  156. var resultText;
  157. var success = false;
  158. var unclickable = false;
  159. var error = false;
  160. switch (response.status) {
  161. case 200: // status OK
  162. var rpcResponse = response.responseText;
  163. var rpcJSON = JSON.parse(rpcResponse);
  164. if (rpcJSON.result.toLowerCase() === "success") {
  165. if ("torrent-duplicate" in rpcJSON.arguments) {
  166. resultText = "Already added: " + rpcJSON['arguments']['torrent-duplicate'].name;
  167. } else {
  168. resultText = "Added: " + rpcJSON['arguments']['torrent-added'].name;
  169. }
  170. success = true;
  171. } else {
  172. resultText = 'ERROR: ' + rpcJSON.result;
  173. error = true;
  174. }
  175. unclickable = true;
  176. break;
  177. case 401:
  178. resultText = "Your username/password is not correct.";
  179. error = true;
  180. break;
  181. case 409:
  182. var headers = response.responseHeaders.split("\n");
  183. for (var i in headers) {
  184. var header = headers[i].split(":");
  185. if (header[0] == "X-Transmission-Session-Id") {
  186. sessionId = header[1].trim();
  187. console.log("Got new Session ID: (" + sessionId);
  188. addTorrent(button, result, request, sessionId, tries + 1);
  189. }
  190. }
  191. break;
  192. default:
  193. resultText = "Unknown Transmission Response";
  194. error = true;
  195. alert("Unknown Transmission Response: " + response.status + " " + response.statusText);
  196. }
  197. console.log(resultText);
  198. result.text(resultText);
  199. if (unclickable) {
  200. button.unbind('click');
  201. button.css("cursor", "default");
  202. }
  203. if (success) {
  204. button.css("background-color", "#8FFFA6");
  205. }
  206. if (error) {
  207. button.css("background-color", "#FFBAC2");
  208. }
  209. }
  210. });
  211. }
  212.  
  213. function getCookie() {
  214. // from https://github.com/bulljit/Transmission-Add-Torrent-Bookmarkelet Thanks guys.
  215. var sCookie = "";
  216. var aCookie = document.cookie.split(/;[\s\xA0]*/);
  217. if (aCookie !== "") {
  218. for (var i = 0; i < aCookie.length; i++) {
  219. if (aCookie[i].search(/(^__utm|^__qc)/) == -1) {
  220. sCookie = sCookie + aCookie[i] + '; ';
  221. }
  222. }
  223. }
  224. sCookie = sCookie.replace(/;\s+$/, "");
  225. return sCookie;
  226. }