您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
A fork of Bierdopje AddOn Plus for Seriesfeed
当前为
- // ==UserScript==
- // @name Seriesfeed++
- // @namespace https://greasyfork.org/en/users/22592
- // @description A fork of Bierdopje AddOn Plus for Seriesfeed
- // @include http://seriesfeed.com/*
- // @include http://*.seriesfeed.com/*
- // @version 1.09
- // @grant GM_registerMenuCommand
- // @grant GM_setValue
- // @grant GM_getValue
- // @grant GM_addStyle
- // @require http://code.jquery.com/jquery-1.10.2.js
- // @require http://code.jquery.com/ui/1.11.4/jquery-ui.js
- // @author Mr. Invisible
- // @run-at document-end
- // ==/UserScript==
- /*global GM_getValue,GM_registerMenuCommand,GM_addStyle,GM_info,GM_setValue,$ */
- /**
- Changelog:
- 1.09: Added an exception
- 1.08: Multi-domain
- 1.07: Forgot to turn of debug once again
- 1.06:
- - updated for SeriesFeed 2.0
- - added new provider
- - dialog also closes when middle-clicking
- - re-added functionality to the episode and season pages.
- - added exception for legends of tomorrow
- - added email address for easier communication
- 1.05: Updated for SeriesFeed 1.3
- 1.04: Fixed problem with the visual watchlist & dialog for download now closes after clicking a link.
- 1.03: Updated for SeriesFeed 1.2
- 1.02: Fixed small bug with Chrome-derived browsers
- 1.01: Rewrote script in order to accommodate the SeriesFeed pages
- 1.00: Cloned from the Bierdopje AddOn Plus version 1.101
- **/
- // Create one accessible object. The remainder is hidden for external use.
- var seriesFeedPlusPlus = (function () {
- 'use strict';
- var seriesFeedPlusPlus, configDialog, // Objects
- debug, pageRegexes, currentPage, flags, subProviders, dlProviders, dlFormats, dlSites, languageMap, // Variables
- main, checkPage, injectMenuItem, modifyPage, handleStartPage, injectDefaultTable, createFunctionality,
- createLanguageFlag, parseEpisode, showSubSelectionDialog, handleBroadcastPage, handleWatchlistPage,
- injectTableHeader, showDlSelectionDialog, createDownloadLink, formatToConvention, handleSeasonPage,
- handleEpisodePage; // Methods
- // Initialize objects
- seriesFeedPlusPlus = {};
- configDialog = (function () {
- var instance, configElementName, preferences, mapping, show, close, closeOtherSubConfigs, closeSubConfig,
- openSubConfig, changeConfiguration, saveConfiguration, loadPreferences, getEnabledSubtitleLanguages,
- getConfigValue, getEnabledSubtitleSources, getEnabledDownloadProviders, getEnabledDownloadTypes;
- // Init vars
- configElementName = "configFrame";
- // Preferences with their default values
- preferences = {
- sub_lang_nl: true,
- sub_lang_en: true,
- sub_source_addic7ed: true,
- sub_source_podnapisi: true,
- sub_source_opensubtitles: false,
- sub_source_subtitleseeker: false,
- dl_format_webdl: true,
- dl_format_hdtv: true,
- dl_format_hdtvx264: true,
- dl_source_torrent: false,
- dl_source_nzb: true
- };
- mapping = {
- sub_lang_nl: "Ext.SF.SubLanguage_NL",
- sub_lang_en: "Ext.SF.SubLanguage_US",
- sub_source_addic7ed: "Ext.SF.SubProvider_Addic7ed",
- sub_source_podnapisi: "Ext.SF.SubProvider_PodNapisi",
- sub_source_opensubtitles: "Ext.SF.SubProvider_OpenSubTitles",
- sub_source_subtitleseeker: "Ext.SF.SubProvider_SubtitleSeeker",
- dl_format_webdl: "Ext.SF.MediaFormat_WEB-DL",
- dl_format_hdtv: "Ext.SF.MediaFormat_HDTV",
- dl_format_hdtvx264: "Ext.SF.MediaFormat_HTDV.x264",
- dl_source_torrent: "Ext.SF.DownloadFormat_Torrent",
- dl_source_nzb: "Ext.SF.DownloadFormat_NZB"
- };
- // Initialize functions
- show = function () {
- var css, html, div, subFrames, idx, inputs;
- if (document.getElementById(configElementName)) {
- close();
- return;
- }
- css = ' ' +
- '.h3subframe { margin: 1px 0 0px; padding: 1px 10px; border-bottom: 1px solid #bbb; font-size: 1.5em; font-weight: normal; cursor:pointer; background:#DDDDDD none repeat scroll 0 0; } ' +
- '.h3subframe:hover { background:#C0BEBE none repeat scroll 0 0; } ' +
- '#h3subframetitle { margin: 2px 0 0px; padding: 7px 10px; border-bottom: 1px solid #bbb; font-size: 2.0em; font-weight: normal; } ' +
- '.popup a { color: darkblue; text-decoration: none; } ' +
- '.popup p { padding: 1px 10px; margin: 0px 0; font-family:verdana,geneva,lucida,"lucida grande",arial,helvetica,sans-serif; font-size:10pt; font-size-adjust:none; font-stretch:normal; font-style:normal; font-variant:normal; font-weight:normal; line-height:normal; } ' +
- '.sidebyside { padding: 1px 10px; margin: 0px 0;display:inline-block;width:17em; } ' +
- '.h3subframecontent { max-height:294px; overflow:auto; display: none; padding: 10px 10px; } ' +
- '#showinfo { font-size:14px; } ';
- GM_addStyle(css);
- html =
- '<div id="fade" style="background: #000;height: 100%;opacity: .80;"></div>' +
- '<div style="font-family: verdana; color: black; background: #ddd; padding: 10px 20px; border: 10px solid #fff; float: left; width: 731px; position: absolute; top: 2%; left: 40%; margin: 0 0 0 -292px; border-radius: 10px; z-index: 100;">' +
- ' <div class="popup" style="float: left; width: 100%; background: #fff; margin: 10px 0; padding: 0px 0 0px; border-left: 1px solid #bbb; border-top: 1px solid #bbb; border-right: 1px solid #bbb;">' +
- ' <a href="#" onclick="javascript:return false;">' +
- ' <img id="' + configElementName + '_close" style="border:none; position: absolute; right: -20px; top: -20px;" title="Close" src="data:image/png;base64,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%3D%3D"/>' +
- ' </a>' +
- ' <div id="h3subframetitle"><b>SeriesFeed AddOn - Preferences</b></div>' +
- ' <div id="h3subframe1" class="h3subframe">Media</div>' +
- ' <div class="h3subframecontent">' +
- ' <p id="showinfo">Choose the <b>media formats</b> you need</p><br>' +
- ' <div class="sidebyside"><input type="checkbox" id="dl_format_webdl" /> WEB-DL <font color="gray">(720p & 1080p)</font></div>' +
- ' <div class="sidebyside"><input type="checkbox" id="dl_format_hdtv" /> HDTV <font color="gray">(720p & 1080p)</font></div>' +
- ' <div class="sidebyside"><input type="checkbox" id="dl_format_hdtvx264" /> HDTV_x264 <font color="gray">(MP4)</font></div>' +
- ' <hr/>' +
- ' <p id="showinfo">Choose the <b>type of files</b> you want to download</p><br>' +
- ' <div class="sidebyside"><input type="checkbox" id="dl_source_nzb" /> NZB</div>' +
- ' <div class="sidebyside"><input type="checkbox" id="dl_source_torrent" /> Torrent</div><br>' +
- ' </div>' +
- ' <div id="h3subframe2" class="h3subframe">Subtitles</div>' +
- ' <div class="h3subframecontent">' +
- ' <p id="showinfo">Choose the <b>subtitle sites</b> you want as option</p><br>' +
- ' <p><input type="checkbox" id="sub_source_addic7ed" /> Addic7eD <font color="gray">(preferred)</font></p>' +
- ' <p><input type="checkbox" id="sub_source_podnapisi" /> PodNapisi</p>' +
- ' <p><input type="checkbox" id="sub_source_opensubtitles" /> OpenSubtitles</p>' +
- ' <p><input type="checkbox" id="sub_source_subtitleseeker" /> SubTitleSeeker <font color="gray">(can be unsafe)</font></p>' +
- ' </div>' +
- ' <div id="h3subframe3" class="h3subframe">Languages</div>' +
- ' <div class="h3subframecontent">' +
- ' <p id="showinfo">Choose the <b>subtitle languages</b> you want to find</p><br>' +
- ' <p><input type="checkbox" id="sub_lang_nl" /> Nederlands <img src="' + flags.nl + '"/></p>' +
- ' <p><input type="checkbox" id="sub_lang_en" /> English <img src="' + flags.en + '"/></p>' +
- ' </div>' +
- ' <div id="h3subframe4" class="h3subframe">About</div>' +
- ' <div class="h3subframecontent">' +
- ' <p><b>' + GM_info.script.name + '</b> - version: ' + GM_info.script.version + '</p>' +
- ' <br />' +
- ' <p>' + GM_info.script.description + '</p>' +
- ' <p>Author: Mr. Invisible (mrinvisible@cryptolab.net) - original author: XppX</p>' +
- ' <p>License: GPL</p>' +
- ' </div>' +
- ' </div>' +
- '</div>';
- div = document.createElement("div");
- div.id = configElementName;
- div.setAttribute('style',
- 'visibility: visible;position: fixed;width: 100%;height: 100%;top: 0;left: 0;font-size:12px;' +
- 'z-index:1001;text-align:left;');
- div.innerHTML = html;
- document.body.appendChild(div);
- document.getElementById(configElementName + "_close").addEventListener("click", close, false);
- // Loop through checkboxes to populate them
- inputs = div.getElementsByTagName("input");
- for (idx = 0; idx < inputs.length; idx++) {
- if (inputs[idx].type === "checkbox") {
- if (preferences.hasOwnProperty(inputs[idx].id) && preferences[inputs[idx].id]) {
- inputs[idx].setAttribute("checked", "checked");
- }
- // Add a listener to each checkbox
- inputs[idx].addEventListener("click", changeConfiguration, false);
- }
- }
- // Add event listeners for opening when a click on the head is performed
- subFrames = document.getElementsByClassName("h3subframe");
- for (idx = 0; idx < subFrames.length; idx++) {
- subFrames[idx].addEventListener("click", openSubConfig, false);
- }
- // Unfold the first one
- openSubConfig({
- target: document.getElementById('h3subframe1')
- });
- };
- close = function () {
- var box = document.getElementById(configElementName);
- box.parentNode.removeChild(box);
- window.location.reload(false);
- };
- closeOtherSubConfigs = function (evt) {
- var ignore, subFrames, idx;
- ignore = evt.target || evt.srcElement;
- subFrames = document.getElementsByClassName("h3subframe");
- for (idx = 0; idx < subFrames.length; idx++) {
- if (ignore !== subFrames[idx]) {
- subFrames[idx].nextElementSibling.style.display = "none";
- subFrames[idx].addEventListener("click", openSubConfig, false);
- }
- }
- };
- closeSubConfig = function (e) {
- var evt, target;
- evt = e || window.event;
- target = evt.target || evt.srcElement;
- target.removeEventListener("click", closeSubConfig, false);
- target.nextElementSibling.style.display = "none";
- target.addEventListener("click", openSubConfig, false);
- };
- openSubConfig = function (e) {
- var evt, target;
- evt = e || window.event;
- target = evt.target || evt.srcElement;
- target.removeEventListener("click", openSubConfig, false);
- target.nextElementSibling.style.display = "block";
- closeOtherSubConfigs(evt);
- target.addEventListener("click", closeSubConfig, false);
- };
- changeConfiguration = function (e) {
- if (e.target.tagName.toLowerCase() === 'input') {
- saveConfiguration(e.target.id, e.target.checked);
- }
- };
- saveConfiguration = function (id, value) {
- if (preferences.hasOwnProperty(id)) {
- preferences[id] = value;
- GM_setValue(mapping[id], value);
- }
- };
- loadPreferences = function () {
- var key;
- if (debug) {
- window.console.log("Entering load preferences function");
- }
- if (debug) {
- window.console.log("Preferences (default):");
- window.console.log(preferences);
- }
- for (key in mapping) {
- if (mapping.hasOwnProperty(key) && preferences.hasOwnProperty(key)) {
- preferences[key] = GM_getValue(mapping[key], preferences[key]);
- }
- }
- if (debug) {
- window.console.log("Preferences (loaded):");
- window.console.log(preferences);
- }
- };
- getConfigValue = function (name) {
- if (preferences.hasOwnProperty(name)) {
- return preferences[name];
- }
- return null;
- };
- getEnabledSubtitleLanguages = function () {
- var result = [];
- if (preferences.sub_lang_en) {
- result.push("en");
- }
- if (preferences.sub_lang_nl) {
- result.push("nl");
- }
- return result;
- };
- getEnabledSubtitleSources = function () {
- var result = [];
- if (preferences.sub_source_addic7ed) {
- result.push(subProviders.sub_source_addic7ed);
- }
- if (preferences.sub_source_podnapisi) {
- result.push(subProviders.sub_source_podnapisi);
- }
- if (preferences.sub_source_opensubtitles) {
- result.push(subProviders.sub_source_opensubtitles);
- }
- if (preferences.sub_source_subtitleseeker) {
- result.push(subProviders.sub_source_subtitleseeker);
- }
- return result;
- };
- getEnabledDownloadProviders = function () {
- var result = [];
- if (preferences.dl_source_torrent) {
- result.push(dlProviders.dl_source_torrent);
- }
- if (preferences.dl_source_nzb) {
- result.push(dlProviders.dl_source_nzb);
- }
- return result;
- };
- getEnabledDownloadTypes = function () {
- var result = [];
- if (preferences.dl_format_webdl) {
- result.push(dlFormats.dl_format_webdl);
- }
- if (preferences.dl_format_hdtv) {
- result.push(dlFormats.dl_format_hdtv);
- }
- if (preferences.dl_format_hdtvx264) {
- result.push(dlFormats.dl_format_hdtvx264);
- }
- return result;
- };
- // Initialize object to return and expose appropriate methods
- instance = {};
- instance.show = show;
- instance.loadPreferences = loadPreferences;
- instance.getConfigValue = getConfigValue;
- instance.getEnabledSubtitleLanguages = getEnabledSubtitleLanguages;
- instance.getEnabledSubtitleSources = getEnabledSubtitleSources;
- instance.getEnabledDownloadProviders = getEnabledDownloadProviders;
- instance.getEnabledDownloadTypes = getEnabledDownloadTypes;
- return instance;
- }());
- // Initialize variables
- debug = false;
- // Maps short language keywords to the full English language
- languageMap = {
- "en": "English",
- "nl": "Dutch"
- };
- // Providers, keys of this MUST be equal to the ones in the configDialog.preferences variable
- subProviders = {
- sub_source_addic7ed: {
- title: "Addic7eD",
- createLink: function (showName, showEpisode, language) {
- var showNameConverted, showEpisodeConverted, languageConverted;
- // Convert show name & show episode to appropriate formats
- showNameConverted = this.showConversion(showName);
- showEpisodeConverted = this.episodeConversion(showEpisode);
- languageConverted = this.languageConversion(language);
- return "http://www.addic7ed.com/serie/" + showNameConverted + "/" + showEpisodeConverted.season + "/" +
- showEpisodeConverted.episode + "/" + languageConverted;
- },
- showConversion: function (show) {
- var exceptions;
- show = show.replace(/ /g, "_");
- // Exception map for shows
- exceptions = {
- "The_Flash": "The_Flash_(2014)",
- "Legends_of_Tomorrow": "DC's_Legends_of_Tomorrow",
- "Marvel's_Daredevil": "Daredevil"
- };
- if (exceptions.hasOwnProperty(show)) {
- show = exceptions[show];
- }
- return show;
- },
- episodeConversion: function (episode) { return parseEpisode(episode); },
- languageConversion: function (language) {
- switch (language) {
- case "nl":
- return "17";
- case "en":
- return "1";
- }
- return language;
- }
- },
- sub_source_podnapisi: {
- title: "PodNapisi",
- createLink: function (showName, showEpisode, language) {
- var showNameConverted, showEpisodeConverted, languageConverted;
- // Convert show name & show episode to appropriate formats
- showNameConverted = this.showConversion(showName);
- showEpisodeConverted = this.episodeConversion(showEpisode);
- languageConverted = this.languageConversion(language);
- return "http://www.podnapisi.net/subtitles/search/advanced?keywords=" + showNameConverted + "&seasons="
- + showEpisodeConverted.season + "&episodes=" + showEpisodeConverted.episode + "&language=" +
- languageConverted;
- },
- showConversion: function (show) {
- var exceptions;
- show = show.replace(/ /g, "+");
- // Exception map for shows
- exceptions = {};
- if (exceptions.hasOwnProperty(show)) {
- show = exceptions[show];
- }
- return show;
- },
- episodeConversion: function (episode) { return parseEpisode(episode); },
- languageConversion: function (language) { return language; }
- },
- sub_source_opensubtitles: {
- title: "OpenSubtitles",
- createLink: function (showName, showEpisode, language) {
- var showNameConverted, showEpisodeConverted, languageConverted;
- // Convert show name & show episode to appropriate formats
- showNameConverted = this.showConversion(showName);
- showEpisodeConverted = this.episodeConversion(showEpisode);
- languageConverted = this.languageConversion(language);
- return "http://www.openSubtitles.org/nl/search/searchonlytvseries-on/subformat-srt/sublanguageid-" +
- languageConverted + "/season-" + showEpisodeConverted.season + "/episode-" +
- showEpisodeConverted.episode + "/moviename-" + showNameConverted;
- },
- showConversion: function (show) {
- var exceptions;
- show = show.replace(/ /g, "+");
- // Exception map for shows
- exceptions = {};
- if (exceptions.hasOwnProperty(show)) {
- show = exceptions[show];
- }
- return show;
- },
- episodeConversion: function (episode) { return parseEpisode(episode); },
- languageConversion: function (language) {
- switch (language) {
- case "nl":
- return "dut";
- case "en":
- return "eng";
- }
- }
- },
- sub_source_subtitleseeker: {
- title: "SubTitleSeeker",
- createLink: function (showName, showEpisode, language) {
- var showNameConverted, showEpisodeConverted, convertedLanguage;
- // Convert show name & show episode to appropriate formats
- showNameConverted = this.showConversion(showName);
- showEpisodeConverted = this.episodeConversion(showEpisode);
- convertedLanguage = this.languageConversion(language);
- if (debug) {
- window.console.log("Language is not used for subTitleSeeker: " + convertedLanguage);
- }
- return "http://www.subtitleseeker.com/search/TV_EPISODES/" + showNameConverted + "+S" +
- showEpisodeConverted.season + "E" + showEpisodeConverted.episode;
- },
- showConversion: function (show) {
- var exceptions;
- show = show.replace(/ /g, "+");
- // Exception map for shows
- exceptions = {};
- if (exceptions.hasOwnProperty(show)) {
- show = exceptions[show];
- }
- return show;
- },
- episodeConversion: function (episode) { return parseEpisode(episode); },
- languageConversion: function (language) { return language; }
- }
- };
- dlFormats = {
- dl_format_webdl: "WEB-DL 1080/720p",
- dl_format_hdtv: "HDTV 1080/720p",
- dl_format_hdtvx264: "HDTV-x264 (MP4)"
- };
- dlSites = {
- torrentz: {
- title: "Torrentz",
- createLink: function (showName, showEpisode, quality, dialog) {
- var url, dlAddition;
- // Adjust name & episode for search
- showName = showName.replace(/ /g, "+");
- showEpisode = parseEpisode(showEpisode);
- // Determine addition based on quality
- dlAddition = "";
- switch (quality) {
- case dlFormats.dl_format_webdl:
- dlAddition = "+WEB%20DL";
- break;
- case dlFormats.dl_format_hdtv:
- dlAddition = "+720p+x264";
- break;
- case dlFormats.dl_format_hdtvx264:
- dlAddition = "+HDTV+x264";
- break;
- default:
- window.console.warn("Got an unknown quality type: " + quality);
- }
- url = "https://torrentz.eu/search?f=" + showName + "+" + formatToConvention(showEpisode) + dlAddition;
- return createDownloadLink(this.title, url, dialog);
- }
- },
- kat: {
- title: "KAT",
- createLink: function (showName, showEpisode, quality, dialog) {
- var url, dlAddition;
- // Adjust name & episode for search
- showName = showName.replace(/ /g, "%2B");
- showName = showName.replace(/\(/g, "");
- showEpisode = parseEpisode(showEpisode);
- // Determine addition based on quality
- dlAddition = "";
- switch (quality) {
- case dlFormats.dl_format_webdl:
- dlAddition = "%2BWEB-DL";
- break;
- case dlFormats.dl_format_hdtv:
- dlAddition = "%2B720p%2Bx264";
- break;
- case dlFormats.dl_format_hdtvx264:
- dlAddition = "%2BHDTV.x264";
- break;
- default:
- window.console.warn("Got an unknown quality type: " + quality);
- }
- url = "https://kat.cr/usearch/" + showName + "%2B" + formatToConvention(showEpisode) + dlAddition;
- return createDownloadLink(this.title, url, dialog);
- }
- },
- tpb: {
- title: "TPB",
- createLink: function (showName, showEpisode, quality, dialog) {
- var url, dlAddition;
- // Adjust name & episode for search
- showEpisode = parseEpisode(showEpisode);
- // Determine addition based on quality
- dlAddition = "";
- switch (quality) {
- case dlFormats.dl_format_webdl:
- dlAddition = " WEB-DL";
- break;
- case dlFormats.dl_format_hdtv:
- dlAddition = " 720p x264";
- break;
- case dlFormats.dl_format_hdtvx264:
- dlAddition = " HDTV.x264";
- break;
- default:
- window.console.warn("Got an unknown quality type: " + quality);
- }
- url = "https://thepiratebay.se/search/" + showName + " " + formatToConvention(showEpisode) + dlAddition;
- return createDownloadLink(this.title, url, dialog);
- }
- },
- nzbindex: {
- title: "NZBIndex",
- createLink: function (showName, showEpisode, quality, dialog) {
- var url, dlAddition;
- // Adjust name & episode for search
- showName = showName.replace(/ /g, "+");
- showEpisode = parseEpisode(showEpisode);
- // Determine addition based on quality
- dlAddition = "";
- switch (quality) {
- case dlFormats.dl_format_webdl:
- dlAddition = "+0p++WEB-DL&age=&max=25&sort=agedesc&minsize=600&maxsize=5120&poster=&nfo=&hidespam=1&more=0";
- break;
- case dlFormats.dl_format_hdtv:
- dlAddition = "+0p++x264&age=&max=25&sort=agedesc&minsize=600&maxsize=5120&poster=&nfo=&hidespam=1&more=0";
- break;
- case dlFormats.dl_format_hdtvx264:
- dlAddition = "+HDTV.x264&age=&max=25&sort=agedesc&minsize=150&maxsize=1536&poster=&nfo=&hidespam=1&more=0";
- break;
- default:
- window.console.warn("Got an unknown quality type: " + quality);
- }
- url = "https://www.nzbindex.com/search/?q=" + showName + '+"' + formatToConvention(showEpisode) +
- '"|"' + formatToConvention(showEpisode, "x") + dlAddition;
- return createDownloadLink(this.title, url, dialog);
- }
- },
- nzbclub: {
- title: "NZBClub",
- createLink: function (showName, showEpisode, quality, dialog) {
- var url, dlAddition;
- // Adjust name & episode for search
- showName = showName.replace(/ /g, "+");
- showEpisode = parseEpisode(showEpisode);
- // Determine addition based on quality
- dlAddition = "";
- switch (quality) {
- case dlFormats.dl_format_webdl:
- dlAddition = "+WEB-DL&szs=20&sze=24&st=1&sp=1&sn=1";
- break;
- case dlFormats.dl_format_hdtv:
- dlAddition = "+0p+x264&szs=20&sze=24&st=1&sp=1&sn=1";
- break;
- case dlFormats.dl_format_hdtvx264:
- dlAddition = "+HDTV.x264&sz=16&ez=22&rpp=25&st=1&sp=1&sn=1";
- break;
- default:
- window.console.warn("Got an unknown quality type: " + quality);
- }
- url = "https://www.nzbclub.com/search.aspx?q=" + showName + '+' + formatToConvention(showEpisode) +
- dlAddition;
- return createDownloadLink(this.title, url, dialog);
- }
- },
- binsearch: {
- title: "BinSearch",
- createLink: function (showName, showEpisode, quality, dialog) {
- var url, dlAddition;
- // Adjust name & episode for search
- showName = showName.replace(/ /g, "+");
- showEpisode = parseEpisode(showEpisode);
- // Determine addition based on quality
- dlAddition = "";
- switch (quality) {
- case dlFormats.dl_format_webdl:
- dlAddition = "+WEB-DL&m=&max=25&adv_g=&adv_age=999&adv_sort=date&adv_col=on&minsize=600&maxsize=5120&font=small&postdate=";
- break;
- case dlFormats.dl_format_hdtv:
- dlAddition = "+0p+x264&m=&max=25&adv_g=&adv_age=999&adv_sort=date&adv_col=on&minsize=600&maxsize=5120&font=small&postdate=";
- break;
- case dlFormats.dl_format_hdtvx264:
- dlAddition = "+HDTV.x264&m=&max=25&adv_g=&adv_age=999&adv_sort=date&adv_col=on&minsize=150&maxsize=1024&font=small&postdate=";
- break;
- default:
- window.console.warn("Got an unknown quality type: " + quality);
- }
- url = "https://binsearch.info/index.php?q=" + showName + '+' + formatToConvention(showEpisode) +
- dlAddition;
- return createDownloadLink(this.title, url, dialog);
- }
- }
- };
- dlProviders = {
- dl_source_torrent: {
- title: "Torrent",
- sites: [
- dlSites.torrentz,
- dlSites.kat,
- dlSites.tpb
- ]
- },
- dl_source_nzb: {
- title: "NZB",
- sites: [
- dlSites.nzbindex,
- dlSites.nzbclub,
- dlSites.binsearch
- ]
- }
- };
- // Flags
- flags = {
- "nl": "data:image/gif;base64,R0lGODlhEAALANUAAAABdP7+/jRusgAhj/picxZYp/UAAPLy8vr6+vj4+Pb29v56iVqKw/1da0V7ujpytSpmrusAAGSSx/pCUftUZP11gwAAR/96hgAAWe7v7yFgq0J3tw1Rokt/vAAAPFCCv1SFwS9qrtHR0fk8Tf6CkdXV1ftqevcxQvg3Rz52uPxMWvVWavZabv8VMflXaP5ZZ3eezv6XpC5qsvYsPPv7+/pQX/5/j/htfvlIV/T19fxwgPX19fz8/P0AAPT09P8AACH5BAAAAAAALAAAAAAQAAsAAAaFwJ/w1ysWDUhkJPJbLC6Vis5kIhAaLkqNeWk0XloVbjJCnWa4SCtGsjmltyqBtbpFDoE8j0dDIBIJCjs+OyUZenx+gII+Bzkih3t9f4GDBwc+IgMwDCAfHQ4bDwIhEBAaGxYAEg4pozKnGgUFHBwhHqsMnZ+hrgKkELgAwxjFxRbIHsoeQQA7",
- "en": "data:image/gif;base64,R0lGODlhEAALANUAAGNjtvr6+vb29fHx8fxGRvkQEP15eatjSuNjSjx6+TV0+f2Kd+np6dvb2PxUVPx4YttjSvsrK5q7/PxlZrpjSvw6Oubm5e7u7sljSgR09Z1jSvT080iB+gBMtkF9+vofHwBpu/f39uLi3/syMtVjSqG+/C9y+Ozs7KLA/GNlwPyBbO3t6gNx5QArs/2XhpGRgKysn+z+/rS0qPR0XuXl/P7KwcnJwf39Wzh3+f7+/fv/+vHx7wNv4df+/f3h3GNnxCH5BAAAAAAALAAAAAAQAAsAAAaMwJ/wl0oBjqoHYgmB/HIoXSkgoQYCoawA9kNxOJ5EAmcyTByEiouUmnoEiYspMxhcTreNrR1OKOYgaBUjEQsYAAEJAwonLCIddwwMFj0yABI4fzwgHS2DER8fCwciAQIbG3aRkxYNPi8qNWZoaRGgBbgqGg0BMVqoqTsrNBYiM0sITU0kGBQUBwca0kEAOw=="
- };
- // Page regexes
- pageRegexes = {
- // SeriesFeed homepage
- start: new RegExp("^/$"),
- // Broadcast schedule (format: series/uitzendlijst/[{month}/]* )
- broadcast: new RegExp("^.*/series/uitzendlijst(/[a-z]+)*/$"),
- // Watchlist (format: series/kijklijst/[topshows/|favorieten/]*
- watch: new RegExp("^.*/series/kijklijst/([topshows|favorieten]+/)*$"),
- // Episodes/Seasons (format: series/{name}/afleveringen/[seizoen/{nr}/]* )
- season: new RegExp("^.*/series/(.+)/afleveringen/(seizoen/[0-9]+/)*$"),
- // Episode (format: series/aflevering/{nr}/ )
- episode: new RegExp("^.*/series/aflevering/[0-9]+/?$")
- };
- // Current page
- currentPage = null;
- // Initialize functions
- main = function () {
- if (debug) {
- window.console.log("Entering main function");
- }
- // Load preferences
- configDialog.loadPreferences();
- // Register GreaseMonkey menu entry
- try {
- GM_registerMenuCommand("[SeriesFeed AddOn] Configuratie", configDialog.show, "C");
- } catch (e) {
- window.console.warn("Could not register GM menu handler. This is normal if run outside of GreaseMonkey.", e);
- }
- // Inject config menu item
- injectMenuItem();
- // Check page we're on
- checkPage();
- // If the page is still null at this point, we didn't identify the page.
- if (currentPage === null) {
- window.console.warn("Did not identify a page to run on. Not executing any more page alterations.");
- return;
- }
- // Inject some css
- GM_addStyle('.ui-front { z-index: 1000 !important; }');
- // Modify the page
- modifyPage();
- };
- checkPage = function () {
- var key, found;
- if (debug) {
- window.console.log("Entering checkPage function");
- }
- found = null;
- for (key in pageRegexes) {
- if (pageRegexes.hasOwnProperty(key)) {
- if (debug) {
- window.console.log("Trying to match " + pageRegexes[key] + " to " + window.location.pathname);
- }
- if (pageRegexes[key].exec(window.location.pathname)) {
- if (debug) {
- window.console.log("Match found for " + key);
- }
- found = key;
- break;
- }
- }
- }
- currentPage = found;
- };
- injectMenuItem = function () {
- var idx, links, li, menu, inject, injectLink;
- if (debug) {
- window.console.log("Entering injectMenuItem function");
- }
- // There are no id's used, so we'll hook on to some text contents in the page
- links = document.getElementsByTagName("a");
- for (idx = 0; idx < links.length; idx++) {
- if (links[idx].innerHTML === "Profiel wijzigen") {
- // Might have a match, verify "menu" element above
- li = links[idx].parentNode;
- menu = li.parentNode;
- if (menu.classList.contains("dropdown-menu")) {
- // We can assume safely that we're in a menu. Inject menu item
- inject = document.createElement("li");
- injectLink = document.createElement("a");
- injectLink.innerHTML = "SeriesFeed++ configureren";
- injectLink.addEventListener("click", configDialog.show, false);
- inject.appendChild(injectLink);
- menu.appendChild(inject);
- }
- }
- }
- };
- modifyPage = function () {
- if (debug) {
- window.console.log("Entering modifyPage function");
- }
- // Depending on the type of the page, we need to render differently
- switch (currentPage) {
- case "start":
- handleStartPage();
- break;
- case "broadcast":
- handleBroadcastPage();
- break;
- case "watch":
- handleWatchlistPage();
- break;
- case "season":
- handleSeasonPage();
- break;
- case "episode":
- handleEpisodePage();
- break;
- default:
- window.console.warn("Did not identify a page to run on. Not executing any more page alterations.");
- }
- // Append css for jquery UI
- $("head").append('<link href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css"' +
- 'rel="stylesheet" type="text/css">');
- };
- // Page specific modifications
- handleStartPage = function () {
- if (debug) {
- window.console.log("Entering handleStartPage function");
- }
- // There is one table of interest: latest favourites. As of 1.3 it can be missing if there's no episodes
- injectDefaultTable("favourite_episodes");
- };
- handleBroadcastPage = function () {
- if (debug) {
- window.console.log("Entering handleBroadcastPage function");
- }
- // Single table: broadcasted episodes
- injectDefaultTable("afleveringen");
- };
- handleWatchlistPage = function () {
- if (debug) {
- window.console.log("Entering handleWatchlistPage function");
- }
- // Single table: favourites/popular episodes
- injectDefaultTable("afleveringen");
- };
- handleSeasonPage = function () {
- var table, showName;
- if (debug) {
- window.console.log("Entering handleSeasonPage function");
- }
- // Get show name
- showName = document.getElementById('seriesName').value;
- // Single table: show episodes
- table = $("#afleveringen");
- // Inject element for header
- injectTableHeader("afleveringen");
- // Inject icons in rows
- table.find("tbody tr.light").each(function (idx, elm) {
- var td, cells, showEpisode;
- if (debug) {
- window.console.log("Processing row " + idx);
- }
- td = document.createElement("td");
- cells = elm.getElementsByTagName("td");
- showEpisode = cells[0].firstElementChild.innerHTML;
- td.appendChild(createFunctionality(showName, showEpisode));
- elm.appendChild(td);
- });
- };
- handleEpisodePage = function () {
- var table, row, cell, data, showName, showEpisode;
- if (debug) {
- window.console.log("Entering handleEpisodePage function");
- }
- // Need to inject new row instead of cell
- table = $("#episodeInfo");
- data = table.find("thead th").first().html().trim();
- data = data.match(/([A-Za-z ]*) \([0-9]{4}\) : (.*)/);
- showName = data[1];
- showEpisode = data[2];
- // Inject
- row = document.createElement('tr');
- cell = document.createElement('td');
- cell.innerHTML = 'SeriesFeed++';
- row.appendChild(cell);
- cell = document.createElement('td');
- cell.appendChild(createFunctionality(showName, showEpisode));
- row.appendChild(cell);
- table.find("tbody").append(row);
- };
- // General modification methods
- injectTableHeader = function (tableId) {
- var table, th;
- if (debug) {
- window.console.log("Entering injectTableHeader function");
- }
- table = $("#" + tableId);
- // Inject element for header
- th = document.createElement("th");
- th.innerHTML = "SeriesFeed++";
- table.find("thead tr")[0].appendChild(th);
- };
- injectDefaultTable = function (tableId) {
- var table, colspan, readMore;
- if (debug) {
- window.console.log("Entering injectDefaultTable function");
- }
- table = $("#" + tableId);
- // Check if element actually exists
- if (table.length === 0) {
- if (debug) {
- window.console.log("Did not find a table with the id: " + tableId);
- }
- return;
- }
- // Inject element for header
- injectTableHeader(tableId);
- // Inject icons in rows
- table.find("tbody tr").not('.readMore').each(function (idx, elm) {
- var td, cells, showName, showEpisode;
- if (debug) {
- window.console.log("Processing row" + idx);
- }
- td = document.createElement("td");
- cells = elm.getElementsByTagName("td");
- showName = cells[0].firstElementChild.innerHTML;
- showEpisode = cells[1].firstElementChild.innerHTML;
- td.appendChild(createFunctionality(showName, showEpisode));
- elm.appendChild(td);
- });
- readMore = table.find("tbody tr.readMore td");
- colspan = parseInt(readMore.attr("colspan"), 10);
- readMore.attr('colspan', colspan + 1);
- };
- createFunctionality = function (showName, showEpisode) {
- var span, languages, idx, downloadProviders, downloadTypes, downloadIcon;
- if(debug){
- console.log("Entering createFunctionality with parameters: showName: "+showName+", showEpisode: "+showEpisode)
- }
- span = document.createElement("span");
- // Add language flags
- languages = configDialog.getEnabledSubtitleLanguages();
- for (idx = 0; idx < languages.length; idx++) {
- span.appendChild(createLanguageFlag(languages[idx], showName, showEpisode));
- span.appendChild(document.createTextNode(" "));
- }
- downloadProviders = configDialog.getEnabledDownloadProviders();
- downloadTypes = configDialog.getEnabledDownloadTypes();
- if (downloadProviders.length > 0 && downloadTypes.length > 0) {
- downloadIcon = document.createElement("i");
- downloadIcon.setAttribute('class','fa fa-download');
- downloadIcon.setAttribute('style', 'display:inline-block; font-size: 19px; cursor: pointer;');
- downloadIcon.title = "download episode";
- downloadIcon.addEventListener("click", showDlSelectionDialog);
- span.appendChild(downloadIcon);
- }
- return span;
- };
- createLanguageFlag = function (lang, showName, showEpisode) {
- var result, img, subSources;
- if(debug){
- console.log("Entering createLanguageFlag with parameters: lang: "+lang+", showName: "+showName+", showEpisode: "+showEpisode)
- }
- if (!flags.hasOwnProperty(lang)) {
- throw new Error(lang + "is not a recognized language flag!");
- }
- img = document.createElement("img");
- img.src = flags[lang];
- img.alt = lang + " flag";
- img.title = languageMap[lang] + " subtitles";
- img.setAttribute("data-language", lang);
- img.setAttribute('style', 'height: 16px; vertical-align:top;');
- // If there's just one subtitle source, make it a link, otherwise make it a pop-up menu
- subSources = configDialog.getEnabledSubtitleSources();
- if (subSources.length > 1) {
- img.addEventListener("click", showSubSelectionDialog, false);
- result = img;
- } else {
- result = document.createElement("a");
- result.href = subSources[0].createLink(showName, showEpisode, lang);
- result.target = "_blank";
- result.appendChild(img);
- }
- return result;
- };
- showSubSelectionDialog = function (e) {
- var evt, target, dialog, subSources, row, showName, showEpisode, lang, cells, idx, link, p, thead, data;
- evt = e || window.event;
- target = evt.target || evt.srcElement;
- // Get language
- lang = target.getAttribute("data-language");
- // Get row, so we can extract show name & episode
- row = target.parentNode.parentNode.parentNode;
- cells = row.getElementsByTagName("td");
- if(currentPage === "season"){
- showName = document.getElementById('seriesName').value;
- showEpisode = cells[0].firstElementChild.innerHTML;
- } else if(currentPage === "episode") {
- thead = row.parentNode.previousElementSibling;
- data = thead.firstElementChild.firstElementChild.innerHTML.trim();
- data = data.match(/([A-Za-z ]*) \([0-9]{4}\) : (.*)/);
- showName = data[1];
- showEpisode = data[2];
- } else {
- showName = cells[0].firstElementChild.innerHTML;
- showEpisode = cells[1].firstElementChild.innerHTML;
- }
- // Build dialog
- dialog = document.createElement("div");
- p = document.createElement("p");
- p.innerHTML = "Show: " + showName + "<br/>Episode: " + showEpisode;
- dialog.appendChild(p);
- p = document.createElement("p");
- // Get sub source sites
- subSources = configDialog.getEnabledSubtitleSources();
- for (idx = 0; idx < subSources.length; idx++) {
- link = document.createElement("a");
- link.target = "_blank";
- link.href = subSources[idx].createLink(showName, showEpisode, lang);
- link.innerHTML = subSources[idx].title;
- link.setAttribute("style","text-decoration: underline;");
- link.addEventListener("click", function () {
- $(dialog).dialog("close");
- }, false);
- p.appendChild(link);
- p.appendChild(document.createTextNode(" "));
- }
- dialog.appendChild(p);
- $(dialog).dialog({
- title: "Download " + languageMap[lang] + " subtitles",
- position: { my: "right bottom", at: "top left", of: target }
- });
- };
- showDlSelectionDialog = function (e) {
- var evt, target, dialog, row, cells, showName, showEpisode, p, downloadTypes, downloadProviders, idx, ul, li,
- jdx, kdx, thead, data;
- evt = e || window.event;
- target = evt.target || evt.srcElement;
- // Get row, so we can extract show name & episode
- row = target.parentNode.parentNode.parentNode;
- cells = row.getElementsByTagName("td");
- if(currentPage === "season") {
- showName = document.getElementById('seriesName').value;
- showEpisode = cells[0].firstElementChild.innerHTML;
- } else if(currentPage === "episode") {
- thead = row.parentNode.previousElementSibling;
- data = thead.firstElementChild.firstElementChild.innerHTML.trim();
- data = data.match(/([A-Za-z ]*) \([0-9]{4}\) : (.*)/);
- showName = data[1];
- showEpisode = data[2];
- } else {
- showName = cells[0].firstElementChild.innerHTML;
- showEpisode = cells[1].firstElementChild.innerHTML;
- }
- dialog = document.createElement("div");
- p = document.createElement("p");
- p.innerHTML = "Show: " + showName + "<br/>Episode: " + showEpisode;
- dialog.appendChild(p);
- p = document.createElement("p");
- // Get types & sites
- downloadProviders = configDialog.getEnabledDownloadProviders();
- downloadTypes = configDialog.getEnabledDownloadTypes();
- for (idx = 0; idx < downloadTypes.length; idx++) {
- p = document.createElement("p");
- p.appendChild(document.createTextNode(downloadTypes[idx]));
- dialog.appendChild(p);
- ul = document.createElement("ul");
- for (jdx = 0; jdx < downloadProviders.length; jdx++) {
- li = document.createElement("li");
- li.appendChild(document.createTextNode(downloadProviders[jdx].title + ": "));
- for (kdx = 0; kdx < downloadProviders[jdx].sites.length; kdx++) {
- li.appendChild(downloadProviders[jdx].sites[kdx].createLink(showName, showEpisode, downloadTypes[idx], dialog));
- li.appendChild(document.createTextNode(" "));
- }
- ul.appendChild(li);
- }
- dialog.appendChild(ul);
- }
- $(dialog).dialog({
- title: "Download episode",
- position: { my: "right bottom", at: "top left", of: target }
- });
- };
- parseEpisode = function (showEpisode) {
- var result, regex, match;
- if (debug) {
- window.console.log("Entering parseEpisode function");
- }
- result = {
- season: 0,
- episode: 0,
- title: ""
- };
- regex = new RegExp("S([0-9]+)E([0-9]+) - (.+)");
- // Epected format: SxEy - episode title
- match = regex.exec(showEpisode);
- if (match !== null) {
- result.season = parseInt(match[1], 10);
- result.episode = parseInt(match[2], 10);
- result.title = match[3];
- } else {
- window.console.warn("Could not parse " + showEpisode + " correctly!");
- }
- return result;
- };
- createDownloadLink = function (name, href, dialog) {
- var a, closeDialog;
- closeDialog = function () {
- $(dialog).dialog("close");
- };
- a = document.createElement("a");
- a.href = href;
- a.target = "_blank";
- a.innerHTML = name;
- a.setAttribute("style","text-decoration: underline;");
- //a.addEventListener("click", closeDialog, false);
- a.addEventListener("mouseup", closeDialog, false);
- return a;
- };
- // Helper functions
- formatToConvention = function (episodeData, episodeCharacter) {
- episodeCharacter = episodeCharacter || "E";
- return "S" + ((episodeData.season < 10) ? "0" : "") + episodeData.season + episodeCharacter +
- ((episodeData.episode < 10) ? "0" : "") + episodeData.episode;
- };
- // Expose methods to the outside world
- seriesFeedPlusPlus.main = main;
- return seriesFeedPlusPlus;
- }());
- // Execute main
- try {
- seriesFeedPlusPlus.main();
- } catch (e) {
- console.log(e);
- console.log(e.stack);
- // Display error
- var txt = "An error occurred while executing this script.\n\n";
- txt += "Issue: <<<" + e.message + ">>>\n\n";
- txt += "\nPlease report this back to the author (on the greasyfork website, or by sending me an email at mrinvisible@cryptolab.net) so it can be corrected.\n\n";
- txt += "Click 'OK' to continue.\n\n";
- window.alert(txt);
- }