Sleazy Fork is available in English.

1337x - Combined Enhancements 2024

Adds a column with torrent and magnet links, extends titles, adds images, full width site

// ==UserScript==
// @name         1337x - Combined Enhancements 2024
// @namespace    http://tampermonkey.net/
// @version      2024.6
// @description  Adds a column with torrent and magnet links, extends titles, adds images, full width site
// @author       sharmanhall
// @contributor  darkred, NotNeo, barn852, French Bond
// @match        *://*.1337x.to/*
// @match        *://*.1337x.to/torrent/*
// @match        *://*.1337x.to/torrent/*
// @match        *://*.1337x.to/*
// @match        *://*.1337x.ws/torrent/*
// @match        *://*.1337x.eu/torrent/*
// @match        *://*.1337x.eu/*
// @match        *://*.1337x.se/torrent/*
// @match        *://*.1337x.is/*
// @match        *://*.1337x.is/torrent/*
// @match        *://*.1337x.gd/*
// @match        *://*.1337x.gd/torrent/*
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// @license      MIT
// @icon         https://www.google.com/s2/favicons?sz=64&domain=1337x.to
//
//    Thanks to:
//    - French Bond: modified original script taken from https://greasyfork.org/en/scripts/479974-1337x-ux-enhancement
//    - darkred: modified original script taken from https://greasyfork.org/en/scripts/479974-1337x-ux-enhancement
//    - NotNeo: most of the CSS used is taken from this script: https://greasyfork.org/en/scripts/373230-1337x-magnet-torrent-links-everywhere .
//    - barn852 for his contribution here: https://greasyfork.org/en/scripts/420754-1337x-torrent-and-magnet-links/discussions/96026
//
// Official mirrors list: https://1337x.to/about
//
// ==/UserScript==

const VISIBLE_IMAGES = 4; // Number of images to show initially

(function () {
  'use strict';

  // Add a column with torrent and magnet links
  function appendColumn() {
    const allTables = document.querySelectorAll('.table-list-wrap');
    const isSeries = window.location.href.includes('/series/');
    const title = 'ml dl';

    allTables.forEach((table) => {
      const headersCellsInitial = table.querySelectorAll(`.table-list > thead > tr:not(.blank) > th:nth-child(1),
                                                          .table-list > tbody > tr:not(.blank) > td:nth-child(1)`);
      headersCellsInitial.forEach((cell, index) => {
        if (index === 0 && !isSeries) {
          cell.insertAdjacentHTML('afterend', `<th>` + title + `</th>`);
        } else {
          cell.insertAdjacentHTML('afterend', `<td>` + title + `</td>`);
        }
      });

      const headersCellsNew = table.querySelectorAll(`.table-list > thead > tr:not(.blank) > th:nth-child(2),
                                                      .table-list > tbody > tr:not(.blank) > td:nth-child(2)`);
      headersCellsNew.forEach((cell, index) => {
        cell.classList.add('coll-1b');
        if (index === 0 && !isSeries) {
          cell.innerHTML = title;
        } else {
          cell.classList.add('dl-buttons');

          let href;
          if (!isSeries){
            href = headersCellsInitial[index].firstElementChild.nextElementSibling.href;
          } else {
            href = headersCellsInitial[index].firstElementChild.href;
          }

          cell.innerHTML =  `<a class="list-button-magnet" data-href=" ${href} "href="javascript:void(0)" title="ml via xhr"><i class="flaticon-magnet"></i></a>`;
          cell.innerHTML += `<a class="list-button-dl" data-href="     ${href} "href="javascript:void(0)" title="dl via xhr"><i class="flaticon-torrent-download"></i></a>`;
        }
      });
    });
  }

  function addClickListeners(links, type){
    links.forEach((link) => {
      link.addEventListener('click', function(){
        let href = this.getAttribute('href');
        if (href === 'javascript:void(0)') {
          let tLink = this.getAttribute('data-href');

          var xhr = new XMLHttpRequest();
          xhr.open('GET', tLink, true);
          xhr.onload = function () {
            let container = document.implementation.createHTMLDocument().documentElement;
            container.innerHTML = xhr.responseText;

            let retrievedLink = (type === 'ml') ? container.querySelector('a[href^="magnet:"]') : container.querySelector('.dropdown-menu > li > a');

            if (retrievedLink) {
              link.setAttribute('href', retrievedLink.href.replace('http:', 'https:'));
              link.click();
            }
          };
          xhr.send();
        }
      }, false);
    });
  }

  function createColumn(){
    appendColumn();
    addClickListeners(document.querySelectorAll('.list-button-magnet'), 'ml' );
    addClickListeners(document.querySelectorAll('.list-button-dl'), 'dl' );
  }

  // List all torrent links on the page
  function listTorrentLinks() {
    return document.querySelectorAll('.table-list a[href^="/torrent/"]');
  }

  // Clean the page title to get the torrent title
  function cleanTitle(title) {
    if (title.startsWith('Download ')) {
      title = title.substring('Download '.length);
    }
    let pipeIndex = title.indexOf(' Torrent |');
    if (pipeIndex !== -1) {
      title = title.substring(0, pipeIndex);
    }
    return title;
  }

  // Modify the H1 content on torrent pages
  function modifyH1ContentOnTorrentPages() {
    if (window.location.pathname.startsWith('/torrent/')) {
      let h1Element = document.querySelector('.box-info-heading h1');
      if (h1Element) {
        h1Element.textContent = cleanTitle(document.title);
      }
    }
  }

// Process the link to update the title and add download buttons and images
function processLink(link) {
  fetchContent(link, (doc) => {
    let torrentLink = doc.querySelector("a[href*='itorrents.org/torrent/']");
    let magnetLink = doc.querySelector("a[href^='magnet:?']");

    updateLinkTitle(link, doc);
    appendImages(link, doc);
    // Pass the links in the correct order
    addDownloadButtons(link, torrentLink, magnetLink);
  });
}



  // Update the link title
  function updateLinkTitle(link, doc) {
    let title = cleanTitle(doc.querySelector('title').innerText);
    link.innerText = title;
  }

// Add download buttons next to the link
function addDownloadButtons(link, torrentLink, magnetLink) {
  let buttonsContainer = document.createElement('div');
  buttonsContainer.style.display = 'flex';
  buttonsContainer.style.alignItems = 'center';
  buttonsContainer.style.gap = '5px';
  buttonsContainer.style.marginTop = '10px';

  // Torrent button
  let torrentButton = document.createElement('a');
  torrentButton.href = torrentLink ? torrentLink.href.replace('http:', 'https:') : '#';
  torrentButton.title = 'Download torrent file';
  torrentButton.innerHTML = '<i id="DLT" class="flaticon-torrent-download" style="color: #89ad19; font-size: 16px"></i>';

  // Magnet button
  let magnetButton = document.createElement('a');
  magnetButton.href = magnetLink ? magnetLink.href : '#';
  magnetButton.title = 'Download via magnet';
  magnetButton.innerHTML = '<i id="DLM" class="flaticon-magnet" style="color: #da3a04; font-size: 16px"></i>';

 buttonsContainer.appendChild(torrentButton);
  buttonsContainer.appendChild(magnetButton);

  link.after(buttonsContainer);
}

// Modify this function to update or replace existing download buttons
  function updateDownloadButtons() {
    document.querySelectorAll('.table-list-wrap .table-list tbody tr').forEach(row => {
      let torrentPageLink = row.querySelector('.coll-1.name a').getAttribute('href');
      let fullTorrentPageLink = `https://1337x.to${torrentPageLink}`;

      fetchContent(fullTorrentPageLink, (doc) => {
        let torrentLink = doc.querySelector("a[href*='itorrents.org/torrent/']");
        let magnetLink = doc.querySelector("a[href^='magnet:?']");

        let dlButtonsCell = row.querySelector('.coll-1b.dl-buttons');
        if (dlButtonsCell) {
          // Check if buttons already exist and update them or create new ones
          updateOrCreateButtons(dlButtonsCell, torrentLink, magnetLink);
        }
      });
    });
  }

  function updateOrCreateButtons(dlButtonsCell, torrentLink, magnetLink) {
    let existingButtons = dlButtonsCell.querySelectorAll('a');
    if (existingButtons.length === 2) {
      // Update existing buttons
      existingButtons[0].href = torrentLink ? torrentLink.href.replace('http:', 'https:') : '#';
      existingButtons[1].href = magnetLink ? magnetLink.href : '#';
    } else {
      // Create new buttons
      dlButtonsCell.innerHTML = createButtonHTML(torrentLink, magnetLink);
    }
  }


// Function to create HTML for download and magnet buttons
function createButtonHTML(torrentLink, magnetLink) {
  let torrentButtonHTML = torrentLink ? `<a href="${torrentLink.href.replace('http:', 'https:')}" title="Download torrent file"><i class="flaticon-torrent-download" style="color: #89ad19; font-size: 16px"></i></a>` : '';
  let magnetButtonHTML = magnetLink ? `<a href="${magnetLink.href}" title="Download via magnet"><i class="flaticon-magnet" style="color: #da3a04; font-size: 16px"></i></a>` : '';
  // Place the torrent button first and the magnet button second
  return `<div style="display: flex; align-items: center; gap: 5px; margin-top: 10px;">${torrentButtonHTML}${magnetButtonHTML}</div>`;
}

// Function to fetch content of a link
function fetchContent(link, onSuccess) {
  GM_xmlhttpRequest({
    method: 'GET',
    url: link,
    onload: function(response) {
      let parser = new DOMParser();
      let doc = parser.parseFromString(response.responseText, 'text/html');
      onSuccess(doc);
    }
  });
}

  // Call the function to update download buttons
  updateDownloadButtons();

  // Append images related to the torrent
// Append images related to the torrent
function appendImages(link, doc) {
  let images = doc.querySelectorAll('#description img');
  if (images.length > 0) {
    let flexContainer = document.createElement('div');
    flexContainer.style.display = 'flex';
    flexContainer.style.flexWrap = 'wrap';
    flexContainer.style.gap = '10px';
    flexContainer.style.marginTop = '10px';

    let clonedImages = []; // Array to store cloned images
    images.forEach((img, index) => {
      let clonedImg = img.cloneNode(true);

      // Use 'data-original' if it exists, else use 'src'
      let imgSrc = img.getAttribute('data-original') || img.src;
      if (imgSrc.includes('https://imgtraffic.com/1s/')) {
        imgSrc = imgSrc.replace('https://imgtraffic.com/1s/', 'https://imgtraffic.com/1/');
      }
      // Check if the src matches the specific pattern and replace 'th.jpg' with '.jpg'
      if (imgSrc.includes('https://pilot007.org/images/')) {
          imgSrc = imgSrc.replace(/.th\.jpg$/, '.jpg');
      }
      // Check if the src matches the specific pattern and replace 'th.jpg' with '.jpg'
      if (imgSrc.includes('https://13xpics.space/images/')) {
          imgSrc = imgSrc.replace(/.th\.jpg$/, '.jpg');
      }
      // Check if the src matches the specific pattern and replace 'th.jpg' with '.jpg'
      if (imgSrc.includes('https://37xpics.space/images/')) {
          imgSrc = imgSrc.replace(/.th\.jpg$/, '.jpg');
      }
        // Check if the src matches the pattern like https://<anything>/images/<anything>.th.jpg and replace '.th.jpg' with '.jpg'
        if (/https?:\/\/.*\/images\/.*\.th\.jpg$/.test(imgSrc)) {
            imgSrc = imgSrc.replace(/\.th\.jpg$/, '.jpg');
        }
      clonedImg.src = imgSrc;
      clonedImg.style.maxHeight = '100px';
      clonedImg.style.setProperty('margin', '0', 'important');
      clonedImg.style.display = index < VISIBLE_IMAGES ? 'block' : 'none';
      flexContainer.appendChild(clonedImg);
      clonedImages.push(clonedImg); // Store the cloned image
    });

    // Add "Show More/Less" button if there are more than VISIBLE_IMAGES images
    if (images.length > VISIBLE_IMAGES) {
      let showMoreButton = document.createElement('button');
      showMoreButton.textContent = 'Show More';

      showMoreButton.onclick = function () {
        // Toggle visibility of additional images
        let isShowingMore = showMoreButton.textContent === 'Show Less';
        clonedImages.forEach((img, index) => {
          if (index >= VISIBLE_IMAGES) {
            img.style.display = isShowingMore ? 'none' : 'block';
          }
        });
        showMoreButton.textContent = isShowingMore ? 'Show More' : 'Show Less';
      };



      clonedImages.forEach((clonedImg) => {
        // Mouseover event to show enlarged image
        clonedImg.addEventListener('mouseover', function () {
          showEnlargedImg(clonedImg.src);
        });

        // Mousemove event to update the position of the enlarged image
        clonedImg.addEventListener('mousemove', updateEnlargedImgPosition);

        // Mouseout event to remove enlarged image
        clonedImg.addEventListener('mouseout', function () {
          removeEnlargedImg();
        });
      });

      flexContainer.appendChild(showMoreButton);
    }

    link.parentNode.insertBefore(flexContainer, link.nextSibling);
  }
}

 // Function to show an enlarged image
  function showEnlargedImg(imgSrc) {
    const enlargedImg = document.createElement('img');
    enlargedImg.src = imgSrc;
    enlargedImg.style.position = 'fixed';
    enlargedImg.style.width = '500px';
    enlargedImg.style.height = '500px';
    enlargedImg.style.pointerEvents = 'none'; // Ignore pointer events
    enlargedImg.id = 'enlargedImg';
    document.body.appendChild(enlargedImg);
  }

  // Function to update the position of the enlarged image
  function updateEnlargedImgPosition(e) {
    const enlargedImg = document.getElementById('enlargedImg');
    if (enlargedImg) {
      const viewportWidth = window.innerWidth;
      const viewportHeight = window.innerHeight;
      const imgWidth = 500; // Width of the enlarged image
      const imgHeight = 500; // Height of the enlarged image
      const offsetX = 10; // Horizontal offset from the cursor
      const offsetY = 10; // Vertical offset from the cursor

      let leftPosition = e.clientX + offsetX;
      let topPosition = e.clientY + offsetY;

      // Adjust position if the image goes out of the viewport
      if (leftPosition + imgWidth > viewportWidth) {
        leftPosition = e.clientX - imgWidth - offsetX;
      }
      if (topPosition + imgHeight > viewportHeight) {
        topPosition = e.clientY - imgHeight - offsetY;
      }

      enlargedImg.style.left = leftPosition + 'px';
      enlargedImg.style.top = topPosition + 'px';
    }
  }

  // Function to remove enlarged image
  function removeEnlargedImg() {
    const enlargedImg = document.getElementById('enlargedImg');
    if (enlargedImg) {
      document.body.removeChild(enlargedImg);
    }
  }



  // Function calls
  createColumn();
  replaceLinkTextWithTitlesAndAppendImages();
  modifyH1ContentOnTorrentPages();

  // Replace the link text with the title and append images
  function replaceLinkTextWithTitlesAndAppendImages() {
    let torrentLinks = listTorrentLinks();
    torrentLinks.forEach(processLink);
  }

  // Inject custom CSS to remove max-width on container
  function injectCustomCSS() {
    GM_addStyle('.container { max-width: none !important; }');
  // Custom CSS
  GM_addStyle(`
    main.container, div.container {
      max-width: 1450px;
    }

    .list-button-magnet > i.flaticon-magnet {
      font-size: 13px;
      color: #da3a04
    }

    .list-button-dl > i.flaticon-torrent-download {
      font-size: 13px;
      color: #89ad19;
    }

    table.table-list td.dl-buttons {
      border-left: 1px solid #f6f6f6;
      border-right: 1px solid #c0c0c0;
      padding-left: 2.5px;
      padding-right: 2.5px;
      text-align: center !important;
      position: relative;
      display: table-cell !important; /* proper height of cell on multiple row torrent name */
      width: 6%;
    }

    td.dl-buttons > a,
    td.dl-buttons > a:hover,
    td.dl-buttons > a:visited,
    td.dl-buttons > a:link,
    td.dl-buttons > a:active {
      color: inherit;
      text-decoration: none;
      cursor: pointer;
      display: inline-block !important;
      margin: 0 2px;
    }

    table.table-list td.coll-1b {
      border-right: 1px solid silver;
    }

    .table-list > thead > tr > th:nth-child(2),
    .table-list > thead > tr > td:nth-child(2) {
      text-align: center;
    }

    .container { max-width: none !important; }
  `);
  }

  injectCustomCSS();
})();