Plex to Simkl Button

Adds a button to open the current movie or show on Simkl

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})();
Plex to Simkl Button | Robomonkey