[bib] RequestUpload

Facilitates uploading and filling requests.

  1. // ==UserScript==
  2. // @name [bib] RequestUpload
  3. // @namespace varb
  4. // @version 0.7
  5. // @description Facilitates uploading and filling requests.
  6. // @include /^https?://bibliotik.org/(request|torrent)s/\d+/
  7. // @include /^https?://bibliotik.org/upload/\w+/
  8. // @require https://cdnjs.cloudflare.com/ajax/libs/q.js/1.1.2/q.min.js
  9. // @require https://code.jquery.com/jquery-2.1.1.min.js
  10. // @require https://gf.qytechs.cn/scripts/7055-odinfo/code/ODInfo.js?version=28946
  11. // @grant GM_setValue
  12. // @grant GM_getValue
  13. // @grant GM_deleteValue
  14. // @grant GM_addStyle
  15. // @grant GM_listValues
  16. // @grant GM_xmlhttpRequest
  17. // @license WTFPL Version 2; http://www.wtfpl.net/txt/copying/
  18. // ==/UserScript==
  19.  
  20. $(function () {
  21.  
  22. var requestpage = {
  23. category: null,
  24. reqid: null,
  25. odid: null,
  26. odformats: null,
  27. metadata: {},
  28. scrapeRequestInfo: function () {
  29. var $reqdetails = $('#requestDetails'),
  30. $tags = $('#details_tags a'),
  31. $authors = $('#creatorlist'),
  32. reqdmatch = $reqdetails.text().match(/(?:(\w+),\s)?(\w+)\scategory/),
  33. isbnmatch = $('#description').text().match(/Overdrive Listing \((\d+)\)/);
  34.  
  35. if (!reqdmatch) {
  36. console.log('requp: cannot establish request category');
  37. return;
  38. }
  39.  
  40. this.reqid = location.pathname.split('/').slice(-1);
  41. this.category = reqdmatch[2];
  42.  
  43. this.metadata.fillform = $('#TorrentIdField').parents('form').find(':hidden').serializeArray();
  44. this.metadata.overdrive = !!$tags.filter(':contains(overdrive)').length;
  45. this.metadata.lang = reqdmatch[1];
  46. this.metadata.title = $('h1').text().match(/\/\s*(.+?)(?:\s\[Retail\]$|$)/)[1];
  47. this.metadata.publishers = $('#published a').list();
  48. this.metadata.tags = $tags.not(':contains(overdrive)').list();
  49. this.metadata.reqformats = $reqdetails.find('strong').text().split('/');
  50. this.metadata.retail = $reqdetails.text().indexOf('Retail') !== -1;
  51. this.metadata.authors = $authors.find('a').list();
  52. this.metadata.isbn = isbnmatch ? isbnmatch[1] : null;
  53. if (this.category === 'Comics') {
  54. this.metadata.artists = $authors.next('#creatorlist').find('a').list();
  55. }
  56.  
  57. return true;
  58. },
  59. fetchODInfo: function () {
  60. var dfr = new $.Deferred(),
  61. odurl = $('a:contains(Overdrive Listing)').attr('href'),
  62. odtasks = [];
  63.  
  64. if (!odurl) {
  65. return dfr.reject('could not find od listing url').promise();
  66. }
  67.  
  68. odtasks.push({attribute: 'tags'});
  69. if (this.metadata.reqformats.length === 1 && this.metadata.isbn) {
  70. odtasks.push({attribute: 'isbnbyformat'});
  71. }
  72. OD_getInfo({
  73. source: odurl,
  74. tasks: odtasks
  75. }).then(function (info) {
  76. dfr.resolve(info);
  77. }, function (err) {
  78. dfr.reject(err);
  79. });
  80.  
  81. return dfr.promise();
  82. },
  83. run: function () {
  84. var that = this;
  85.  
  86. if ($('#filled').length) {
  87. console.log('requp: nothing to do here');
  88. return;
  89. }
  90.  
  91. if (!that.scrapeRequestInfo()) {
  92. console.log('requp: failed to parse the request');
  93. return;
  94. }
  95.  
  96. // link upload page
  97. var upurl = location.origin + '/upload/' + that.category.toLowerCase() + '?reqid=' + that.reqid;
  98. $('<a/>', {id: 'upreq', href: upurl, text: 'Upload Request'})
  99. .appendTo('#sidebar ul:first')
  100. .wrap('<li></li>')
  101. .after('<span></span>')
  102. .on('click', function (e) {
  103. var $that = $(this);
  104.  
  105. if (!that.metadata.overdrive) {
  106. GM_setValue(that.reqid, JSON.stringify(that.metadata));
  107. return;
  108. }
  109.  
  110. console.log('requp: od request');
  111. e.preventDefault();
  112. $that.next().addClass('loading');
  113.  
  114. that.fetchODInfo()
  115. .done(function (info) {
  116. console.log('requp: OD info %o', info);
  117. that.metadata.isbn = that.metadata.isbn
  118. || (that.metadata.reqformats.length === 1
  119. && info.isbnbyformat[that.metadata.reqformats[0].toLowerCase()])
  120. || info.isbnbyformat['epub']
  121. || info.isbnbyformat['pdf'];
  122. GM_setValue(that.reqid, JSON.stringify($.extend({}, that.metadata, info)));
  123. $that.next().removeClass('loading').text('redirecting...');
  124. location.href = $that.attr('href');
  125. })
  126. .fail(function (reason) {
  127. console.error('requp: ' + reason);
  128. if (confirm('Failed to acquire OverDrive listing.\nProceed to upload page?')) {
  129. GM_setValue(that.reqid, JSON.stringify(that.metadata));
  130. location.href = $that.attr('href');
  131. }
  132. $that.next().removeClass('loading');
  133. });
  134. });
  135. }
  136. };
  137.  
  138. var handle = {
  139. requests: function () {
  140. requestpage.run();
  141. },
  142. upload: function () {
  143. var FORMATS = { 'MP3': 1, 'PDF': 2, 'CBR': 3,
  144. 'DJVU': 4, 'CBZ': 5, 'CHM': 6,
  145. 'FLAC': 10, 'SPX': 13, 'TXT': 14,
  146. 'EPUB': 15, 'MOBI': 16, 'M4A': 17,
  147. 'M4B': 18, 'AZW3': 21},
  148. LANGS = { 'English': 1, 'German': 2, 'French': 3, 'Spanish': 4,
  149. 'Italian': 5, 'Latin': 6, 'Japanese': 7, 'Swedish': 8,
  150. 'Norwegian': 9, 'Dutch': 12, 'Russian': 13, 'Portuguese': 14,
  151. 'Danish': 15, 'Korean': 16, 'Chinese': 17, 'Polish': 18,
  152. 'Arabic': 19, 'Irish': 20, 'Greek': 21, 'Turkish': 22,
  153. 'Hungarian': 23, 'Thai': 24, 'Indonesian': 25, 'Bulgarian': 26},
  154. match = location.search.match(/reqid=(\w+)/),
  155. reqid = match && match[1],
  156. req = GM_listValues().indexOf(reqid) !== -1 && JSON.parse(GM_getValue(reqid));
  157.  
  158. if (!req) {
  159. return;
  160. }
  161.  
  162. console.log('requp: filling from request %o', req);
  163. GM_deleteValue(reqid);
  164.  
  165. // populate upload form fields
  166. $('#AuthorsField').val(req.authors.join(', '));
  167. if (req.artists && req.artists.length) {
  168. $('#ArtistsField').val(req.artists.join(', '));
  169. }
  170. $('#TitleField').val(req.title);
  171. $('#IsbnField').val(req.isbn);
  172. $('#PublishersField').val(req.publisher || req.publishers.join(', '));
  173. $('#YearField').val(req.pubyear);
  174. if (req.reqformats.length === 1) {
  175. $('#FormatField').val(FORMATS[req.reqformats[0]]);
  176. }
  177. $('#LanguageField').val(LANGS[req.lang]);
  178. $('#RetailField').prop('checked', req.retail);
  179. $('#TagsField').val(req.tags.join(', '));
  180. $('#ImageField').val(req.coverurl);
  181. $('#DescriptionField').val(req.description);
  182. if (req.isbnbyformat) {
  183. $('#FormatField').on('change', function () {
  184. var format = $(this).find(':selected').text();
  185. $('#IsbnField').val(req.isbnbyformat[format.toLowerCase()] || req.isbn);
  186. });
  187. }
  188.  
  189. // save fill request form again for the torrent page
  190. $('#TitleField').parents('form').on('submit', function (e) {
  191. if (! (this.IsbnField.value && this.FormatField.value !== 'noformat')) {
  192. alert('Either ISBN or Format is empty.');
  193. return;
  194. }
  195.  
  196. var key = this.IsbnField.value + $(this.FormatField).find(':selected').text();
  197. GM_setValue(key, JSON.stringify({ id: reqid, fillform: req.fillform }));
  198. });
  199. },
  200. torrents: function () {
  201. var match = $('#details_content_info').text().match(/^\s*(\w+).+?\((\d+)\)/),
  202. key = match && match[2] + match[1], // isbn + format
  203. req = GM_listValues().indexOf(key) !== -1 && JSON.parse(GM_getValue(key)),
  204. torrid = location.pathname.split('/').slice(-1);
  205.  
  206. if (!req) {
  207. return;
  208. }
  209.  
  210. GM_deleteValue(key);
  211.  
  212. req.fillform.push({name: 'TorrentIdField', value: torrid});
  213. console.log('requp: associated request identified %o', req);
  214.  
  215. // add fill request link
  216. $('<a/>', {href: '/requests/' + req.id, text: 'Fill Request', id: 'fillreq'})
  217. .appendTo('#sidebar ul')
  218. .wrap('<li></li>')
  219. .after('<span></span>')
  220. .on('click', function (e) {
  221. var $that = $(this);
  222.  
  223. e.preventDefault();
  224.  
  225. $that.next().addClass('loading').text('');
  226.  
  227. $.post(this.href, $.param(req.fillform)).done(function () {
  228. location.href = this.url;
  229. $that.next().removeClass('loading').text('redirecting...');
  230. }).fail(function (xhr) {
  231. $that.next().removeClass('loading').text(xhr.status + ' ' + xhr.statusText);
  232. console.error('requp: failed to fill request');
  233. });
  234. });
  235. }
  236. };
  237.  
  238. return function () {
  239. var page = location.pathname.split('/')[1];
  240.  
  241. console.log('requp: initialized');
  242.  
  243. if (handle[page]) {
  244. handle[page]();
  245. } else {
  246. console.log('requp: unhandled page ' + page);
  247. }
  248. };
  249.  
  250. }());
  251.  
  252. GM_addStyle('#fillreq+span,#upreq+span{margin-left:10px;font-size:0.8em;}.loading{height:12px;width'
  253. +':12px;background-repeat:no-repeat;display:inline-block;background-image:url(data:image/gif;base64'
  254. +',R0lGODlhDAAMAIQAAAQCBIyKjERCRCQiJNze3BQSFPTy9DQ2NHx+fBwaHPz6/AwKDJyanExOTOzq7Dw+PAQGBCwqLOTi5BQW'
  255. +'FPT29Dw6PBweHPz+/JyenFRWVP///wAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCAAaACwAAAAADAAMA'
  256. +'AAFQ6CmKcxTTA+jiJpzAHB8OBr1xnhFMXgPYA9fg0DICAo+msZgQeIgFNElEuwhVoGUD2Cx/BQ3X2Xl8s1YpMdkIsCsNCEAIf'
  257. +'kECQgAEwAsAAAAAAwADACEBAIElJKUPDo85OLkHB4cZGZkFBIUREJE/Pr8nJqc7OrsHBocPD48NDY0bGpsFBYUREZEnJ6c7O7'
  258. +'s////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUDgNCEJYzxMgoiT0gBw3CjjG98CEtw8UPY3EzD2MPAg'
  259. +'A0kBgOINRIjHIcGjiQgRhA1WWAVyrS3gJLCOSg9pVhQCACH5BAkIABIALAAAAAAMAAwAhAQCBJSWlDQ2NOzq7ERGRAwODMzKz'
  260. +'Dw+PJyenPz6/BQWFAQGBJyanDw6PExOTBQSFERCRPz+/P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
  261. +'AAAAVCoCQlwfEoB5OI0iAAcCwM4xvfDXnvAHPwNxMwpngMYajYwWD4wSCMGK21gCESr8JqVADkWq+AKACYsRIMiMMBuYpCACH'
  262. +'5BAkIABUALAAAAAAMAAwAhAQCBIyOjDw6POTi5BweHGRmZPz6/BQSFExKTOzq7JyanERCRBwaHDw+POTm5DQ2NGxqbPz+/BQW'
  263. +'FOzu7JyenP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVCYFUZSnNIjWKIVfIAcPwk4xvfAnnvQMnfpl9McgAUJ'
  264. +'oPFDiVZVRy7hYIREU12FMMjEDEUcCsXoyijiQyUhUSyyIpCACH5BAkIABQALAAAAAAMAAwAhAQCBJSSlDQ2NMzKzBQSFERCRO'
  265. +'zq7JyanAwODDw+PBwaHPz6/AQGBJSWlDw6PMzOzBQWFExKTJyenPz+/P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
  266. +'AAAAAAAVAIEUtTUJAybGIlCEAcCwY4xvfDgkgzB0ficbCkPABEhHWwAhJipY+VGBY9BUOOyNMsrAZcy2vjCZaACGQAlcUAgAh'
  267. +'+QQJCAAUACwAAAAADAAMAIQEAgSUkpQ8Ojzk4uQcHhxkZmT08vQUEhREQkScmpzs6uwcGhw8Pjzk5uQ0NjRsamz8+vwUFhRER'
  268. +'kScnpz///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFQiBFQQlzREwCiZTiEBEgA44yOsFYzIAABQSWgQcoRV'
  269. +'aUAdEEKCgGEmLkQJQyqjxEAjubQBxcH6UBJtZYJEYkgvCKQgAh+QQJCAAYACwAAAAADAAMAIQEAgSEgoQ0NjTc3twUEhT08vR'
  270. +'MTkwMCgycmpw8Pjzs6uwcGhz8+vwEBgSEhoQ8Ojzk4uQUFhRUUlQMDgycnpxEQkTs7uz8/vz///8AAAAAAAAAAAAAAAAAAAAA'
  271. +'AAAAAAAFRSCGMUgiCAnCiJgiAAHDOICgjO+xjhPwkABAwyKyHIKlIMAwgBiUCYJyqoxIqdNIAjutILhKCuPF/bXIUxuLlIhEK'
  272. +'mJRCAAh+QQJCAASACwAAAAADAAMAIQEAgSUlpQ8Ojzk4uQkIiRsamwUEhREQkT8+vycnpzs6uwcGhycmpw8Pjw0NjQUFhRERk'
  273. +'Ts7uz///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFQqAkIUFjPA2DiJLiADDwEI4yvnGxBgIZwzb'
  274. +'RItH4AQYixONgMB4GioKsafyhqr8DAxtLIHDVXgscq7EQjMZj6RWFAAA7);}');

QingJ © 2025

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