Skip to content

Instantly share code, notes, and snippets.

@Xorboo
Created July 25, 2025 06:22
Show Gist options
  • Select an option

  • Save Xorboo/4bb4b9a33fd3379ccf8cdc57ad2fa6c5 to your computer and use it in GitHub Desktop.

Select an option

Save Xorboo/4bb4b9a33fd3379ccf8cdc57ad2fa6c5 to your computer and use it in GitHub Desktop.
Trakt.tv torrent icon
// ==UserScript==
// @name Trakt.tv quick torrent search
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Quickly open torrent search for the episode. Only tested on [Progress] tab.
// @author Xorboo
// @match https://trakt.tv/*
// @match https://www.trakt.tv/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
function createCustomURL(showName, season, episode) {
const cleanShowName = showName.toLowerCase()
.replace(/[^a-z0-9\s]/g, '')
.replace(/\s+/g, '+')
.trim();
const seasonPadded = season.toString().padStart(2, '0');
const episodePadded = episode.toString().padStart(2, '0');
return `https://1337x.to/search/${cleanShowName}+s${seasonPadded}e${episodePadded}/1/`;
}
function extractEpisodeInfo(episodePanel) {
try {
const showNameElement = episodePanel.querySelector('.titles-link h5');
if (!showNameElement) return null;
const showName = showNameElement.textContent.trim();
const episodeTitleElement = episodePanel.querySelector('.main-title-sxe');
if (!episodeTitleElement) return null;
const episodeText = episodeTitleElement.textContent.trim();
const match = episodeText.match(/(\d+)x(\d+)/);
if (!match) return null;
const season = parseInt(match[1]);
const episode = parseInt(match[2]);
return {
showName,
season,
episode
};
} catch (error) {
console.error('Error extracting episode info:', error);
return null;
}
}
function addCustomButton(episodePanel) {
if (episodePanel.querySelector('.custom-url-button')) {
return;
}
const episodeInfo = extractEpisodeInfo(episodePanel);
if (!episodeInfo) return;
const customURL = createCustomURL(episodeInfo.showName, episodeInfo.season, episodeInfo.episode);
const actionsContainer = episodePanel.querySelector('.quick-icons .actions');
if (!actionsContainer) return;
const customButton = document.createElement('a');
customButton.className = 'custom-url-button';
customButton.href = customURL;
customButton.target = '_blank';
customButton.title = `Hehe >:3`;
customButton.style.cssText = `
position: relative;
display: inline-block;
width: 35px;
height: 40px;
cursor: pointer;
`;
const buttonBase = document.createElement('div');
buttonBase.className = 'base';
buttonBase.style.cssText = `
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
transition: all 0.5s ease;
`;
const buttonIcon = document.createElement('div');
buttonIcon.innerHTML = '▼';
buttonIcon.style.cssText = `
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #aa3333;
font-size: 22px;
z-index: 1;
`;
customButton.addEventListener('mouseenter', function() {
buttonBase.style.background = '#aa3333ff';
buttonIcon.style.color = '#ffffff';
});
customButton.addEventListener('mouseleave', function() {
buttonBase.style.background = '#00000000';
buttonIcon.style.color = '#aa3333';
});
customButton.appendChild(buttonBase);
customButton.appendChild(buttonIcon);
actionsContainer.appendChild(customButton);
}
function processEpisodePanels() {
const progressWrapper = document.getElementById('progress-wrapper');
if (!progressWrapper) return;
const episodePanels = progressWrapper.querySelectorAll('[data-type="episode"]');
episodePanels.forEach(panel => {
addCustomButton(panel);
});
}
function init() {
processEpisodePanels();
const observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.addedNodes.length > 0) {
mutation.addedNodes.forEach(function(node) {
if (node.nodeType === 1) {
if (node.matches && node.matches('[data-type="episode"]')) {
addCustomButton(node);
} else if (node.querySelectorAll) {
const newEpisodePanels = node.querySelectorAll('[data-type="episode"]');
newEpisodePanels.forEach(panel => {
addCustomButton(panel);
});
}
}
});
}
});
});
const progressWrapper = document.getElementById('progress-wrapper');
if (progressWrapper) {
observer.observe(progressWrapper, {
childList: true,
subtree: true
});
}
observer.observe(document.body, {
childList: true,
subtree: true
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
setTimeout(init, 1000);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment