您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Facilitates uploading and filling requests.
当前为
// ==UserScript== // @name [bib] RequestUpload // @namespace varb // @version 0.6.4 // @description Facilitates uploading and filling requests. // @include /^https?://bibliotik.org/(request|torrent)s/\d+/ // @include /^https?://bibliotik.org/upload/\w+/ // @require https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_addStyle // @grant GM_listValues // @grant GM_xmlhttpRequest // @license WTFPL Version 2; http://www.wtfpl.net/txt/copying/ // ==/UserScript== // helpers (function () { // retrieve an array of text contents from the set of matched elements $.fn.list = function () { return $.map(this, function (e) { return e.textContent; }); }; // flatten a set of matched elements wrapping content in bbcode entities $.fn.toBBCode = function () { var nodes = this.get(), frag = document.createDocumentFragment(); for (var i = 0; i < nodes.length; i++) { frag.appendChild(nodes[i].cloneNode(true)); } return stripNode(frag); }; var entityFor = { P: function (s) { return '\n' + s + '\n'; }, BR: function () { return '\n'; }, I: function (s) { return '[i]' + s + '[/i]'; }, EM: function (s) { return this.I(s); }, B: function (s) { return '[b]' + s + '[/b]'; }, STRONG: function (s) { return this.B(s); }, UL: function (s) { return '\n[ul]' + s + '[/ul]\n'; }, OL: function (s) { return '\n[ol]' + s + '[/ol]\n'; }, LI: function (s) { return '[*]' + s + '\n'; }, A: function (s, n) { return '[url=' + n.href + ']' + s + '[/url]'; } }; function stripNode(node) { var result = '', parent = node; if (node.nodeType === 3) { return node.textContent; } if (node.nodeType !== 1 && node.nodeType !== 11) { return ''; } node = node.firstChild; while (node) { result += stripNode(node); node = node.nextSibling; } return entityFor[parent.nodeName] ? entityFor[parent.nodeName](result, parent) : result; } })(); $(function () { var requestpage = { category: null, reqid: null, odid: null, odformats: null, metadata: {}, scrapeRequestInfo: function () { var $reqdetails = $('#requestDetails'), $tags = $('#details_tags a'), $authors = $('#creatorlist'), reqdmatch = $reqdetails.text().match(/(?:(\w+),\s)?(\w+)\scategory/), isbnmatch = $('#description').text().match(/Overdrive Listing \((\d+)\)/); if (!reqdmatch) { console.log('requp: cannot establish request category'); return; } this.reqid = location.pathname.split('/').slice(-1); this.category = reqdmatch[2]; this.metadata.fillform = $('#TorrentIdField').parents('form').find(':hidden').serializeArray(); this.metadata.overdrive = !!$tags.filter(':contains(overdrive)').length; this.metadata.lang = reqdmatch[1]; this.metadata.title = $('h1').text().match(/\/\s*(.+?)(?:\s\[Retail\]$|$)/)[1]; this.metadata.publishers = $('#published a').list(); this.metadata.tags = $tags.not(':contains(overdrive)').list(); this.metadata.format = $reqdetails.find('strong').text().split('/'); this.metadata.retail = $reqdetails.text().indexOf('Retail') !== -1; this.metadata.authors = $authors.find('a').list(); this.metadata.isbn = isbnmatch ? isbnmatch[1] : null; if (this.category === 'Comics') { this.metadata.artists = $authors.next('#creatorlist').find('a').list(); } return true; }, fetchODListing: function () { var dfr = new $.Deferred(), odurl = $('a:contains(Overdrive Listing)').attr('href'); if (!odurl) { return dfr.reject('could not find od listing url').promise(); } GM_xmlhttpRequest({ method: 'GET', url: odurl, onload: function (res) { dfr.resolve(res.responseText); }, onerror: function (res) { dfr.reject('failed fetching od listing: ' + res.status + ' ' + res.statusText); } }); return dfr.promise(); }, parseODListing: function (page) { var dfr = new $.Deferred(), suffix = [null, 'st', 'nd', 'rd'], $page = $(page), $meta = $('.meta-accordion', $page), subtitle, authors, ed; try { // <head> may be stipped by some browsers this.odid = page.match(/meta.+?od:id.+?content=\"([-\w]+)\"/)[1]; this.odformats = $meta.find('span:contains(Format)').next().text(); subtitle = $('h2.subtitle', $page).contents()[0]; subtitle = subtitle && subtitle.textContent.trim(); this.metadata.title = $('h1.title', $page).text().trim() + (subtitle ? ': ' + subtitle : ''); this.metadata.pubyear = $meta.find('dt:contains(Publication Date)').next().text(); // ignore extraneous elements in description $('.description', $page).children().remove('.tags, .meta').andSelf() .find('span:contains(»)').next().andSelf().remove(); this.metadata.desc = $('.description', $page).toBBCode().trim(); authors = $meta.find('span:contains(Creators)').next().find('dd').list(); if (authors.length) { this.metadata.authors = authors; } ed = $meta.find('dt:contains(Edition)').next().text(); if (ed) { ed += (ed.search(/([^1]|\b)[123]$/) !== -1) ? suffix[ed.substr(-1)] : 'th'; this.metadata.title += ' (' + ed + ' Edition)'; } } catch (e) { return dfr.reject('failed parsing od listing: ' + e.name + ', ' + e.message).promise(); } return dfr.resolve().promise(); }, updateISBN: function () { var dfr = new $.Deferred(), that = this, requests = [], formatcodes = {WMA: 25, MP3: 425, EPUB: 410, PDF: 50, Kindle: 420}, format, requested; // look up isbn when one isn't available or when multiple formats are requested if (this.metadata.isbn && this.metadata.format.length === 1) { return dfr.resolve().promise(); } for (format in formatcodes) { // skip if not requested or unavailable requested = (format === 'Kindle') ? $(this.metadata.format).is(['MOBI', 'AZW3']) : $(this.metadata.format).is([format]); if (requested && this.odformats.indexOf(format) !== -1) { requests.push(isbnRequest(this.odid, format, formatcodes[format])); } } $.when.apply($, requests).done(function (/* {format:'', isbn:''}|null, ... */) { that.metadata.formatisbn = {}; for (var i = 0; i < arguments.length; i++) { if (arguments[i]) { that.metadata.formatisbn[arguments[i].format] = arguments[i].isbn; } } // for other formats that.metadata.isbn = that.metadata.isbn || that.metadata.formatisbn.EPUB || that.metadata.formatisbn.PDF; dfr.resolve(); }).fail(function (reason) { // no need to propagate the error console.error('requp: ' + reason); dfr.resolve(); }); return dfr.promise(); function isbnRequest(odid, format, code) { var dfr = new $.Deferred(); GM_xmlhttpRequest({ method: 'GET', url: '//www.contentreserve.com/TitleInfo.asp?ID={'+odid+'}&Format='+code, onload: function (res) { var $page = $(res.responseText, null), isbn = $('td:contains(ISBN):last', $page).next().text().trim(); dfr.resolve(isbn ? {format: format, isbn: isbn} : null); }, onerror: function (res) { dfr.reject('failed looking up isbn: ' + res.status + ' ' + res.statusText); } }); return dfr.promise(); } }, run: function () { var that = this; if ($('#filled').length) { console.log('requp: nothing to do here'); return; } if (!that.scrapeRequestInfo()) { return; } // link upload page var upurl = location.origin + '/upload/' + that.category.toLowerCase() + '?reqid=' + that.reqid; $('<a/>', {id: 'upreq', href: upurl, text: 'Upload Request'}) .appendTo('#sidebar ul:first') .wrap('<li></li>') .after('<span></span>') .on('click', function (e) { var $that = $(this); if (!that.metadata.overdrive) { GM_setValue(that.reqid, JSON.stringify(that.metadata)); return; } e.preventDefault(); $that.next().addClass('loading'); that.fetchODListing() .then(function (page) { return that.parseODListing(page); }) .then(function () { return that.updateISBN(); }) .done(function () { GM_setValue(that.reqid, JSON.stringify(that.metadata)); location.href = $that.attr('href'); $that.next().removeClass('loading').text('redirecting...'); }) .fail(function (reason) { console.error('requp: ' + reason); if (confirm('Failed to acquire OverDrive listing.\nProceed to upload page?')) { location.href = $that.attr('href'); } $that.next().removeClass('loading'); }); }); } }; var handle = { requests: function () { requestpage.run(); }, upload: function () { var FORMATS = { 'MP3': 1, 'PDF': 2, 'CBR': 3, 'DJVU': 4, 'CBZ': 5, 'CHM': 6, 'FLAC': 10, 'SPX': 13, 'TXT': 14, 'EPUB': 15, 'MOBI': 16, 'M4A': 17, 'M4B': 18, 'AZW3': 21}, LANGS = { 'English': 1, 'German': 2, 'French': 3, 'Spanish': 4, 'Italian': 5, 'Latin': 6, 'Japanese': 7, 'Swedish': 8, 'Norwegian': 9, 'Dutch': 12, 'Russian': 13, 'Portuguese': 14, 'Danish': 15, 'Korean': 16, 'Chinese': 17, 'Polish': 18, 'Arabic': 19, 'Irish': 20, 'Greek': 21, 'Turkish': 22, 'Hungarian': 23, 'Thai': 24, 'Indonesian': 25, 'Bulgarian': 26}, match = location.search.match(/reqid=(\w+)/), reqid = match && match[1] req = GM_listValues().indexOf(reqid) !== -1 && JSON.parse(GM_getValue(reqid)); if (!req) { console.log('requp: no request data found'); return; } GM_deleteValue(reqid); // populate upload form fields $('#TitleField').val(req.title); $('#TagsField').val(req.tags.join(', ')); $('#AuthorsField').val(req.authors.join(', ')); if (req.artists && req.artists.length) { $('#ArtistsField').val(req.artists.join(', ')); } if (req.format.length === 1) { $('#FormatField').val(FORMATS[req.format[0]]); } $('#PublishersField').val(req.publishers.join(', ')); $('#LanguageField').val(LANGS[req.lang]); $('#RetailField').prop('checked', req.retail); $('#IsbnField').val(req.isbn); $('#DescriptionField').val(req.desc); $('#YearField').val(req.pubyear); if (req.formatisbn) { $('#FormatField').on('change', function () { var format = $(this).find(':selected').text(); $('#IsbnField').val(req.formatisbn[format] || req.isbn); }); } // save fill request form again for the torrent page $('#TitleField').parents('form').on('submit', function (e) { if (! (this.IsbnField.value && this.FormatField.value !== 'noformat')) { alert('Either ISBN or Format is empty.'); return; } var key = this.IsbnField.value + $(this.FormatField).find(':selected').text(); GM_setValue(key, JSON.stringify({ id: reqid, fillform: req.fillform })); }); }, torrents: function () { var match = $('#details_content_info').text().match(/^\s*(\w+).+?\((\d+)\)/), key = match && match[2] + match[1], // isbn + format req = GM_listValues().indexOf(key) !== -1 && JSON.parse(GM_getValue(key)), torrid = location.pathname.split('/').slice(-1); if (!req) { console.log('requp: no fill request form'); return; } GM_deleteValue(key); req.fillform.push({name: 'TorrentIdField', value: torrid}); // add fill request link $('<a/>', {href: '/requests/' + req.id, text: 'Fill Request', id: 'fillreq'}) .appendTo('#sidebar ul') .wrap('<li></li>') .after('<span></span>') .on('click', function (e) { var $that = $(this); e.preventDefault(); $that.next().addClass('loading').text(''); $.post(this.href, $.param(req.fillform)).done(function () { location.href = this.url; $that.next().removeClass('loading').text('redirecting...'); }).fail(function (xhr) { $that.next().removeClass('loading').text(xhr.status + ' ' + xhr.statusText); console.error('requp: failed to fill request'); }); }); } }; return function () { var page = location.pathname.split('/')[1]; console.log('requp: initialized'); if (handle[page]) { handle[page](); } else { console.log('requp: unhandled page ' + page); } }; }()); GM_addStyle('#fillreq+span,#upreq+span{margin-left:10px;font-size:0.8em;}.loading{height:12px;width\ :12px;background-repeat:no-repeat;display:inline-block;background-image:url(data:image/gif;base64,R\ 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\ 7EQjMZj6RWFAAA7);}');