Oxtorrent/Torrent911

Ajoute filters, Open All, YouTube trailers, et series recherche pour Oxtorrent/Torrent911.

// ==UserScript==
// @name         Oxtorrent/Torrent911
// @namespace    https://greasyfork.org/users/PinkyGreasy
// @version      1.0.1
// @description  Ajoute filters, Open All, YouTube trailers, et series recherche pour Oxtorrent/Torrent911.
// @author       Pinky Greasy
// @license      MIT
// @include      /^https:\/\/(www\.)?(oxtorrent|torrent9|torrent911|t911)\.[a-z]+\/.*(films|series|detail|torrent|recherche).*/
// @grant        none
// ==/UserScript==


(function () {
    'use strict';

    function searchTrailerOnYoutube(title) {
        // Clean up title for search (remove language tags, quality, year)
        let cleanTitle = title
        .replace(/\b(FRENCH|TRUEFRENCH|MULTI|VOSTFR|HDTS|CAM|MD|LD|REPACK|HDRip|WEBRIP)\b/gi, '')
        .replace(/\b(720p|1080p|2160p|4K)\b/gi, '')
        .replace(/\b\d{4}\b/g, '') // remove year
        .replace(/\s+/g, ' ')
        .trim();

        let youtubeUrl = `https://www.youtube.com/results?search_query=${encodeURIComponent(cleanTitle + " trailer")}`;
        window.open(youtubeUrl, '_blank');
    }

    function createOpenAllButton() {
        if (document.querySelector('#openAllBtn')) return; // prevent duplicates

        // Container for button + checkbox
        let container = document.createElement('div');
        container.style.display = 'flex';
        container.style.alignItems = 'center';
        container.style.gap = '10px';
        container.style.margin = '10px 0';
        container.style.justifyContent = 'center';

        // Original button
        let btn = document.createElement('button');
        btn.id = 'openAllBtn';
        btn.innerText = 'Open All';
        btn.style.padding = '10px 15px';
        btn.style.background = '#007bff';
        btn.style.color = '#fff';
        btn.style.border = 'none';
        btn.style.borderRadius = '5px';
        btn.style.cursor = 'pointer';
        btn.style.fontSize = '14px';
        btn.style.boxShadow = '0 2px 5px rgba(0,0,0,0.3)';

        // Create YouTube checkbox
        let label = document.createElement('label');
        label.style.fontSize = '14px';
        label.style.cursor = 'pointer';

        let checkbox = document.createElement('input');
        checkbox.type = 'checkbox';
        checkbox.id = 'youtubeTrailer';
        checkbox.style.marginRight = '5px';

        label.appendChild(checkbox);
        label.appendChild(document.createTextNode('YouTube trailer'));

        container.appendChild(btn);
        container.appendChild(label);

        document.querySelector('#dernierstorrents #trier')?.insertAdjacentElement("afterbegin", container);


        btn.addEventListener('click', function() {
            let links = [...document.querySelectorAll('.listing-torrent > table tr td:first-child a')]
            .filter(link => link.offsetParent !== null);

            let groups = {};
            links.forEach(link => {
                let text = link.innerText.trim();
                let key = text
                .replace(/\b(FRENCH|TRUEFRENCH|MULTI|VOSTFR|HDTS|CAM|MD|LD|REPACK|HDRip|WEBRIP)\b.*$/gi, '')
                .replace(/\b(720p|1080p|2160p|4K)\b.*$/gi, '')
               // .replace(/\b\d{4}\b/g, '') // remove year
                .replace(/\s+/g, ' ')
                .trim()
                .toLowerCase();

                if (!groups[key]) groups[key] = [];
                groups[key].push({ link: link.href, text });
            });

            let selectedItems = [];
            for (let key in groups) {
                let items = groups[key];
                items.sort((a, b) => {
                    let score = (t) => {
                        if (/720p/i.test(t)) return 3;
                        if (/1080p/i.test(t)) return 2;
                        return 1; // fallback
                    };
                    return score(b.text) - score(a.text);
                });
                selectedItems.push(items[0]); // keep the object {link, text}
            }

            console.log(`Opening ${selectedItems.length} unique items`);
            selectedItems.forEach(item => {
                if (checkbox.checked) {
                    searchTrailerOnYoutube(item.text); // Then open trailer tab
                }
                window.open(item.link, '_blank'); // Open torrent link
            });
        });
    }


    function hideOldMovies() {
        let list = document.querySelectorAll('.listing-torrent > table tr td:first-child');
        let re = new RegExp(' (VOSTFR|HDTS|MD|LD|CAM) ');
        const d = new Date();
        if (list.length > 0) {
            list.forEach((el) => {
                const filmName = el.innerText;
                if (re.test(filmName)) {
                    el.closest("tr").remove();
                } else {
                    const year = filmName.trim().substr(-4);
                    if (parseInt(year) <= d.getFullYear() - 3) {
                        el.closest("tr").remove();
                    }
                }
            });
        }
    }

    function openNewBackgroundTab(url) {
        var a = document.createElement("a");
        a.href = url;
        var evt = document.createEvent("MouseEvents");
        evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0,
            true, false, false, false, 0, null);
        a.dispatchEvent(evt);
    }

    function tabifyLinks() {
        let links = document.querySelectorAll('.listing-torrent > table tr td:first-child a');
        links.forEach((el) => {
            el.onclick = function (e) {
                e.preventDefault();
                openNewBackgroundTab(el.href);
            }
        });
    }

    function highlightFrSeries() {
        let list = document.querySelectorAll('.listing-torrent > table tr td:first-child');
        let re = new RegExp(' VOSTFR ', 'i'); console.log(list.length);
        if (list.length > 0) {
            list.forEach((el) => { console.log(el);
                const filmName = el.innerText;
                if (re.test(filmName)) {
                    el.closest("tr").style.opacity = "0.3";
                }
            });
        }
    }

    function copyTextToClipboard(element, text) {
        var textArea = document.createElement('textarea');
        textArea.style.position = 'absolute';
        textArea.style.opacity = '0';
        textArea.value = text;
        document.body.appendChild(textArea);

        var execCopy = e => {
            textArea.select();
            document.execCommand('copy');
            document.body.removeChild(textArea);
        };
        element.addEventListener('mouseup', execCopy, { once: true });
    }

    function downloadifyPoster() {
        let poster = document.querySelector('img.img-rounded');
        let download = document.querySelector('[class^="download"] a[href^="magnet"]')?.href || document.querySelector('#torrentsimage a[href*="magnet:"]')?.href;

        if (poster) {
            poster.style.cursor = "pointer";
            if (download) {
                let magnet = document.querySelector('[class^="download"] img[alt*="magnet"]') || document.querySelector('#torrentsimage a[href*="magnet:"]');
                if (magnet) {
                    poster.onmousedown = e => magnet.closest('a').click();
                }
            } else {
                poster.onmousedown = e => copyTextToClipboard(poster, download);
            }
        }
    }

    function youtubifyTitle() {
        let titles = document.querySelectorAll('.title > a[title]');
        if (titles.length > 0) {
            titles.forEach(titleEl => {
                const name = titleEl.title.replace(/(REPACK|FRENCH|TRUEFRENCH|HDRip).+/, '').trim();
                const searchUrl = "https://www.youtube.com/results?search_query=" + encodeURIComponent(name) + " trailer";
                titleEl.href = searchUrl;
                titleEl.target = '_blank';
            });
        }
    }

    function cleanSerieName(rawName) {
        // Replace dots with spaces
        let name = rawName.replace(/\./g, ' ');

        // Capture everything up to SxxExx
        let match = name.match(/^(.*?\bS\d{2}E)\d{2}/i);
        if (match) {
            return match[1].trim();
        }

        // If no SxxExx found, return cleaned name without extension
        return name.replace(/\.[^.]+$/, '').trim();
    }

    function searchifySerie() {
        const elements = document.querySelectorAll('#torrentsimage .maximums');

        elements.forEach(el => {
            el.style.cursor = "pointer";
            el.addEventListener('click', (e) => {
                e.preventDefault();
                let rawName = el.textContent.trim();
                let cleanedName = cleanSerieName(rawName);
                let searchUrl = `/recherche/${encodeURIComponent(cleanedName)}`;
                window.open(searchUrl, '_blank'); // open in new tab
            });
        });
    }


    setTimeout(() => {
        const page = location.href;
        console.log("Tampermonkey Script Loaded!", page);

        if (page.match(/(torrent|detail)\/[0-9]+/)) { console.log("page");
            downloadifyPoster();
            youtubifyTitle();
            searchifySerie();
        } else if (page.includes("series")) { console.log("series");
            highlightFrSeries();
            tabifyLinks();
        } else if (page.includes("films")) { console.log("films");
            hideOldMovies();
            tabifyLinks();
            createOpenAllButton();
        }
    }, 1000);
})();