- // ==UserScript==
- // @name Torrenter
- // @namespace http://www.google.com/search?q=mabakay
- // @version 2.3.6
- // @description Adds links to torrent sites on popular movie websites.
- // @description:pl Dodaje linki do stron z torrentami na popularnych stronach o filmach.
- // @author mabakay
- // @copyright 2010 - 2024, mabakay
- // @date 28 Oct 2024
- // @license MIT
- // @run-at document-end
- // @icon64URL https://raw.githubusercontent.com/mabakay/torrenter/master/torrenter_64.png
- // @supportURL https://github.com/mabakay/torrenter
- // @match http://www.filmweb.pl/*
- // @match https://www.filmweb.pl/*
- // @match http://release24.pl/*
- // @match https://release24.pl/*
- // @match http://www.imdb.com/*
- // @match https://www.imdb.com/*
- // @match http://www.rottentomatoes.com/*
- // @match https://www.rottentomatoes.com/*
- // @require https://openuserjs.org/src/libs/sizzle/GM_config.min.js
- // @grant GM_getValue
- // @grant GM_setValue
- // @grant GM_registerMenuCommand
- // ==/UserScript==
- "use strict";
- class TorrenterConfigurator {
- get localization() {
- var _a;
- return (_a = TorrenterConfigurator._localization[this._language]) !== null && _a !== void 0 ? _a : TorrenterConfigurator._localization["en"];
- }
- getConfigurationProperty(name, defaultValue) {
- return GM_config.get(name, defaultValue);
- }
- getConfiguration() {
- return {
- engines: [
- "https://thepiratebay10.org/search/{title}[ {year}]/0/7/0",
- "https://torrentgalaxy.to/torrents.php?search={title}[ {year}]&sort=seeders&order=desc",
- "https://1337x.to/sort-search/{title}[ {year}]/seeders/desc/1/",
- "https://torrentz2eu.org/index.html?q={title}[ {year}]",
- "https://yts.mx/browse-movies/{title}[/all/all/0/seeds/{year}/all]",
- "https://eztv.re/search/{title}[ {year}]",
- "https://www.torlock.com/?q={title}[ {year}]&sort=seeds&order=desc",
- "https://www.torrentdownloads.me/search/?new=1&s_cat=0&search={title}[ {year}]",
- "https://www.limetorrents.lol/search/all/{title}[ {year}]/seeds/1/"
- ],
- showEngines: this.getConfigurationProperty("showEngines", true),
- showUserEngines: this.getConfigurationProperty("showUserEngines", false),
- showUserEnginesFirst: this.getConfigurationProperty("showUserEnginesFirst", false),
- userEngines: this.getConfigurationProperty("userEngines", "").split(/\r?\n/).filter((item) => { return !!item; }),
- };
- }
- constructor(changeCallback, onInitCallback) {
- let languages = window.navigator.languages.map(item => item.replace('-', '_'));
- this._language = languages.find(lang => TorrenterConfigurator._localization[lang])
- || languages.find(lang => TorrenterConfigurator._localization[lang.split(/-|_/)[0]])
- || 'en';
- if (!GM_config || !GM_registerMenuCommand) {
- return;
- }
- let gmConfiguration = {
- "id": "mabakay_Torrenter",
- "title": this.localization.settingsTitle,
- "fields": {
- "showEngines": {
- "label": this.localization.showBuildInEngines,
- "type": "checkbox",
- "default": true
- },
- "showUserEngines": {
- "label": this.localization.showUserEngines,
- "type": "checkbox",
- "default": false
- },
- "showUserEnginesFirst": {
- "label": this.localization.showUserEnginesFirst,
- "type": "checkbox",
- "default": false
- },
- "userEngines": {
- "label": this.localization.userEngines,
- "type": "textarea",
- "default": "",
- }
- },
- "events": {
- "init": onInitCallback,
- "open": (document, window, frame) => {
- let userEnginesFiled = document.getElementById("mabakay_Torrenter_field_userEngines");
- userEnginesFiled.setAttribute("cols", "80");
- userEnginesFiled.setAttribute("rows", "10");
- userEnginesFiled.setAttribute("placeholder", this.localization.eg + " https://search-site.com/?title={title}&year={year}&orderby=seeds[&imdbTag={imdb}]");
- let enginesFieldDescription = document.createElement("div");
- enginesFieldDescription.setAttribute("style", "font-size: 12px;margin: 5px 6px;color: gray;");
- enginesFieldDescription.innerHTML = this.localization.addEngineDescription;
- let enginesLabelField = document.getElementById("mabakay_Torrenter_userEngines_field_label");
- enginesLabelField.after(enginesFieldDescription);
- let saveButton = document.getElementById("mabakay_Torrenter_saveBtn");
- saveButton.textContent = this.localization.saveButtonCaption;
- let closeButton = document.getElementById("mabakay_Torrenter_closeBtn");
- closeButton.textContent = this.localization.closeCaptionButton;
- let restToDefaultsLink = document.getElementById("mabakay_Torrenter_resetLink");
- restToDefaultsLink.textContent = this.localization.resetLinkCaption;
- GM_config.frame.setAttribute("style", "inset: 166px auto auto 326px;border: 1px solid rgb(0, 0, 0);height: 440px;margin: 0px;opacity: 1;overflow: auto;padding: 0px;position: fixed;width: 650px;z-index: 9999;display: block;");
- },
- "save": () => {
- GM_config.close();
- if (changeCallback) {
- changeCallback();
- }
- }
- }
- };
- GM_config.init(gmConfiguration);
- GM_registerMenuCommand(this.localization.configureMenuItem, () => { GM_config.open(); });
- }
- }
- TorrenterConfigurator._localization = {
- en: {
- settingsTitle: "Torrenter Script Settings",
- showBuildInEngines: "Show Build-in Engines",
- showUserEngines: "Show User Definied Engines",
- showUserEnginesFirst: "Show User Definied Engines First",
- userEngines: "User Engines",
- eg: "e.g.",
- addEngineDescription: "Type by separating with an enter. Available variables are:</br> {title} - movie title</br> {year} - movie release year</br> {imdb} - position ID in www.imdb.com</br> [] - optional fragment, removed if the internal tag is not found by the site processor",
- saveButtonCaption: "Save",
- closeCaptionButton: "Close",
- resetLinkCaption: "Reset to defaults",
- configureMenuItem: "Configure"
- },
- pl: {
- settingsTitle: "Ustawienia skryptu Torrenter",
- showBuildInEngines: "Pokaż wyszukiwarki wbudowane",
- showUserEngines: "Pokaż wyszukiwarki użytkownika",
- showUserEnginesFirst: "Pokaż wyszukiwarki użytkownika jako pierwsze",
- userEngines: "Wyszukiwarki użytkownika",
- eg: "np.",
- addEngineDescription: "Podaj rozdzielając enterem. Dostępne zmienne to:</br> {title} - tytuł filmu</br> {year} - rok wydania filmu</br> {imdb} - ID pozycji w serwisie www.imdb.com</br> [] - fragment opcjonalny usuwany jeżeli wewnętrzny tag nie zostanie odnaleziony przez parser strony",
- saveButtonCaption: "Zapisz",
- closeCaptionButton: "Anuluj",
- resetLinkCaption: "Przywróć ustawienia domyślne",
- configureMenuItem: "Skonfiguruj"
- },
- pt_PT: {
- settingsTitle: "Definições do script Torrenter",
- showBuildInEngines: "Mostrar motores de pesquisa incorporados",
- showUserEngines: "Mostrar motores de pesquisa definidos pelo utilizador",
- showUserEnginesFirst: "Mostrar primeiro os motores de pesquisa definidos pelo utilizador",
- userEngines: "Motores de pesquisa do utilizador",
- eg: "p. ex.",
- addEngineDescription: "Digite separando com um enter. As variáveis disponíveis são:</br> {title} - título do filme</br> {year} - ano de lançamento do filme</br> {imdb} - ID da posição em www.imdb.com</br> [] - fragmento opcional, removido se a etiqueta interna não for encontrada pelo processador do site",
- saveButtonCaption: "Guardar",
- closeCaptionButton: "Fechar",
- resetLinkCaption: "Repor as predefinições",
- configureMenuItem: "Definições"
- },
- pt_BR: {
- settingsTitle: "Configurações do script Torrenter",
- showBuildInEngines: "Mostrar mecanismos de busca incorporados",
- showUserEngines: "Mostrar mecanismos de busca definidos pelo usuário",
- showUserEnginesFirst: "Mostrar primeiro os mecanismos de busca definidos pelo usuário",
- userEngines: "Mecanismos de busca do usuário",
- eg: "p. ex.",
- addEngineDescription: "Digite separando com um enter. As variáveis disponíveis são:</br> {title} - título do filme</br> {year} - ano de lançamento do filme</br> {imdb} - ID da posição em www.imdb.com</br> [] - fragmento opcional, removido se a tag interna não for encontrada pelo processador do site",
- saveButtonCaption: "Salvar",
- closeCaptionButton: "Fechar",
- resetLinkCaption: "Redefinir para os padrões",
- configureMenuItem: "Configurações"
- }
- };
- class Torrenter {
- apply(config, siteProcessor) {
- let torrenterElements = document.getElementsByClassName("torrenter");
- if (torrenterElements && torrenterElements.length > 0) {
- for (let i = torrenterElements.length - 1; i >= 0; i--) {
- torrenterElements[i].remove();
- }
- }
- setTimeout(() => { siteProcessor((tag, style, itemStyle, args) => { return this.createLinkSpan(config, tag, style, itemStyle, args); }); }, 250);
- }
- static getSiteProcessor(hostName) {
- switch (hostName) {
- case "release24.pl":
- return Torrenter.processRelease24;
- case "www.filmweb.pl":
- return Torrenter.processFilmweb;
- case "www.imdb.com":
- return Torrenter.processImdb;
- case "www.rottentomatoes.com":
- return Torrenter.processRottenTomatoes;
- }
- }
- createLinkSpan(config, tag, style, itemStyle, args) {
- let span = document.createElement(tag);
- span.setAttribute("style", style);
- span.classList.add("torrenter");
- let engines = [];
- if (config.showEngines && config.showUserEngines) {
- if (config.showUserEnginesFirst) {
- engines = config.userEngines.concat(config.engines);
- }
- else {
- engines = config.engines.concat(config.userEngines);
- }
- }
- else if (config.showEngines) {
- engines = config.engines;
- }
- else if (config.showUserEngines) {
- engines = config.userEngines;
- }
- for (let i = 0; i < engines.length; i++) {
- let link = document.createElement("a");
- link.setAttribute("href", Torrenter.format(engines[i], args));
- if (itemStyle) {
- link.setAttribute("style", itemStyle);
- }
- let urlRegex = /(https?:\/\/)(.+?)\//;
- let regexResult = engines[i].match(urlRegex);
- link.innerHTML = Torrenter.getFavIconImg(regexResult[2]);
- link.setAttribute("title", regexResult[2]);
- if (i > 0) {
- let separator = document.createElement("span");
- separator.innerHTML = " | ";
- span.appendChild(separator);
- }
- span.appendChild(link);
- }
- return span;
- }
- static getFavIconImg(url) {
- return '<img src="' + window.location.protocol + '//www.google.com/s2/favicons?domain=' + url + '" width="16px" height="16px">';
- }
- static format(str, args) {
- return str.replace(/(?:\[[^{}]*?)?{(\w+)}(?:[^{}]*?\])?/g, (text, placeholder) => {
- if (text[0] == "[" && text[text.length - 1] == "]") {
- return args.hasOwnProperty(placeholder) && args[placeholder] != null ? text.substring(1, text.length - 1).replace("{" + placeholder + "}", encodeURIComponent(args[placeholder])) : "";
- }
- else {
- return args.hasOwnProperty(placeholder) ? encodeURIComponent(args[placeholder]) : text;
- }
- });
- }
- static processRelease24(createLinkSpan) {
- let titleElement = document.getElementById("mainwindow");
- let loopCount = titleElement.childElementCount;
- for (let i = 1; i < loopCount; i++) {
- let elem = titleElement.children[i];
- if (elem.className === "wpis") {
- let title_regex = /\"(.*)\"\s*(\(([0-9]{4})\))?/;
- let match = elem.children[0].children[0].innerHTML.match(title_regex);
- if (match != null) {
- let title = match[1];
- let year = match.length === 4 && match[3] ? match[3] : null;
- let span = createLinkSpan("span", "margin-left: 1em; font-weight: normal;", "position: relative; top: 5px;", { title, year });
- elem.children[2].children[0].children[0].children[0].children[0].children[1].children[0].children[0].children[0].appendChild(span);
- }
- }
- }
- }
- static processFilmweb(createLinkSpan) {
- let titleElement = document.querySelector(".filmCoverSection__title");
- let title;
- let year;
- if (titleElement) {
- let smallTitleElement = document.querySelector(".filmCoverSection__originalTitle");
- if (smallTitleElement) {
- title = smallTitleElement.textContent;
- }
- else {
- title = titleElement.textContent;
- }
- let yearRegexp = /([0-9]{4})/;
- let match = document.querySelector(".filmCoverSection__year").textContent.match(yearRegexp);
- if (match != null) {
- year = match[1];
- }
- }
- let headerElement = document.querySelector(".filmCoverSection__titleDetails");
- if (headerElement && title) {
- headerElement.insertBefore(createLinkSpan("span", "display: inline-flex;", "position: relative; top: 2px; z-index: 1;", { title, year }), document.querySelector('.preview__content'));
- }
- }
- static processImdb(createLinkSpan) {
- let titleElement = document.querySelector('[data-testid*="hero__pageTitle"]');
- let title;
- let year;
- if (titleElement) {
- let smallTitleElement = titleElement.nextElementSibling;
- if (smallTitleElement && smallTitleElement.textContent && smallTitleElement.textContent.indexOf("Original title:") > -1) {
- title = smallTitleElement.textContent;
- // Remove "Original title" prefix
- let titleRegexp = /Original title: (.*)|.*/;
- let titleMatch = title.match(titleRegexp);
- if (titleMatch != null) {
- title = titleMatch[1];
- }
- }
- else {
- title = titleElement.textContent;
- }
- let yearElement = document.querySelector('[data-testid*="hero__pageTitle"] ~ ul > li');
- if (yearElement) {
- let yearRegexp = /([0-9]{4})/;
- let match = yearElement.textContent.match(yearRegexp);
- if (match != null) {
- year = match[1];
- }
- }
- }
- let headerElement = document.querySelector('[data-testid*="hero__pageTitle"] ~ ul');
- if (headerElement && title) {
- let match = window.location.pathname.match(/\/(tt.*?)(?:\/|\?|$)/i);
- let imdb = match != null ? match[1] : null;
- headerElement.appendChild(createLinkSpan("span", "margin-left: 1em; display: inline-block;", null, { title, year, imdb }));
- }
- }
- static processRottenTomatoes(createLinkSpan) {
- let titleElement = document.querySelector("media-hero rt-text[slot=title]");
- let title;
- let year;
- if (titleElement) {
- title = titleElement.textContent;
- let yearRegexp = /([0-9]{4})/;
- let match = document.querySelectorAll("media-hero rt-text[slot=metadataProp]")[1].textContent.match(yearRegexp);
- if (match != null) {
- year = match[1];
- }
- }
- let headerElement = document.querySelector("media-hero rt-text[slot=title]");
- if (headerElement && title) {
- headerElement.appendChild(createLinkSpan("span", "margin-left: 1em;font-size: 0.5em;position: relative;top: -7px;", "position: relative; top: 2px;", { title, year }));
- }
- }
- }
- let hostName = window.location.hostname;
- let siteProcessor = Torrenter.getSiteProcessor(hostName);
- let applyFunction = (config) => {
- if (siteProcessor) {
- let torrenter = new Torrenter();
- torrenter.apply(config, siteProcessor);
- }
- };
- let configurator = new TorrenterConfigurator(() => applyFunction(configurator.getConfiguration()), () => applyFunction(configurator.getConfiguration()));