Size
4.8 KB
Version
1.1.3
Created
Jan 29, 2026
Updated
1 day ago
1// ==UserScript==
2// @name Plex to Simkl Button
3// @description Adds a button to open the current movie or show on Simkl
4// @version 1.1.3
5// @match https://*.app.plex.tv/*
6// @icon https://app.plex.tv/desktop/favicon.ico
7// @grant GM.openInTab
8// ==/UserScript==
9(function() {
10 'use strict';
11
12 console.log('Plex to Simkl extension loaded');
13
14 // Function to get the current media title from the page
15 function getMediaTitle() {
16 const titleElement = document.querySelector('[data-testid="metadata-title"]');
17 if (titleElement) {
18 return titleElement.textContent.trim();
19 }
20 return null;
21 }
22
23 // Function to create and add the Simkl button
24 function addSimklButton() {
25 // Check if button already exists
26 if (document.querySelector('#simkl-button')) {
27 console.log('Simkl button already exists');
28 return;
29 }
30
31 // Find the action buttons container
32 const buttonsContainer = document.querySelector('[data-testid="preplay-removeFromWatchlist"]')?.parentElement;
33
34 if (!buttonsContainer) {
35 console.log('Buttons container not found, will retry...');
36 return false;
37 }
38
39 console.log('Creating Simkl button');
40
41 // Create the Simkl button matching Plex's button style
42 const simklButton = document.createElement('button');
43 simklButton.id = 'simkl-button';
44 simklButton.className = '_1v4h9jl0 _76v8d62 _76v8d61 _76v8d6a tvbry60 _76v8d6g _76v8d65 _1v25wbq1g _1v25wbq18';
45 simklButton.setAttribute('data-state', 'closed');
46 simklButton.setAttribute('aria-label', 'Open in Simkl');
47 simklButton.setAttribute('role', 'button');
48 simklButton.setAttribute('type', 'button');
49 simklButton.style.backgroundColor = '#1a1a1a';
50 simklButton.style.border = '1px solid #333';
51 simklButton.style.cursor = 'pointer';
52
53 // Create button content
54 const buttonContent = document.createElement('div');
55 buttonContent.className = '_1h4p3k00 _1v25wbq8 _1v25wbq1w _1v25wbqg _1v25wbq1g _1v25wbq1c _1v25wbq14 _1v25wbq3g _1v25wbq2g';
56
57 // Add Simkl logo as image
58 buttonContent.innerHTML = `
59 <img src="https://simkl.com/favicon.ico" width="24" height="24" style="display: block;" alt="Simkl">
60 `;
61
62 simklButton.appendChild(buttonContent);
63
64 // Add click event to open Simkl search
65 simklButton.addEventListener('click', async () => {
66 const title = getMediaTitle();
67 if (title) {
68 console.log('Opening Simkl for:', title);
69 const searchUrl = `https://simkl.com/search/?q=${encodeURIComponent(title)}`;
70 await GM.openInTab(searchUrl, false);
71 } else {
72 console.error('Could not get media title');
73 }
74 });
75
76 // Add hover effect
77 simklButton.addEventListener('mouseenter', () => {
78 simklButton.style.backgroundColor = '#2a2a2a';
79 });
80
81 simklButton.addEventListener('mouseleave', () => {
82 simklButton.style.backgroundColor = '#1a1a1a';
83 });
84
85 // Insert the button into the container
86 buttonsContainer.appendChild(simklButton);
87 console.log('Simkl button added successfully');
88 return true;
89 }
90
91 // Function to wait for and add the button with retries
92 function waitAndAddButton() {
93 let attempts = 0;
94 const maxAttempts = 20;
95 const interval = setInterval(() => {
96 attempts++;
97 const success = addSimklButton();
98 if (success) {
99 clearInterval(interval);
100 } else if (attempts >= maxAttempts) {
101 console.error('Failed to add Simkl button after', maxAttempts, 'attempts');
102 clearInterval(interval);
103 }
104 }, 500);
105 }
106
107 // Function to initialize the extension
108 function init() {
109 console.log('Initializing Plex to Simkl extension');
110
111 // Wait for the page to load
112 if (document.readyState === 'loading') {
113 document.addEventListener('DOMContentLoaded', () => {
114 waitAndAddButton();
115 });
116 } else {
117 waitAndAddButton();
118 }
119
120 // Watch for URL changes (Plex is a single-page app)
121 let lastUrl = location.href;
122 new MutationObserver(() => {
123 const currentUrl = location.href;
124 if (currentUrl !== lastUrl) {
125 lastUrl = currentUrl;
126 console.log('URL changed, re-adding Simkl button');
127 setTimeout(waitAndAddButton, 1000);
128 }
129 }).observe(document.body, { childList: true, subtree: true });
130 }
131
132 // Start the extension
133 init();
134})();