您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add Letterboxd link to its corresponding Plex film's page
当前为
- // ==UserScript==
- // @name Plex Letterboxd links
- // @namespace http://tampermonkey.net/
- // @description Add Letterboxd link to its corresponding Plex film's page
- // @author CarnivalHipster
- // @match https://app.plex.tv/*
- // @icon https://www.google.com/s2/favicons?sz=64&domain=plex.tv
- // @license MIT
- // @grant GM_xmlhttpRequest
- // @version 1.1
- // ==/UserScript==
- (function() {
- 'use strict';
- const letterboxdImg = 'https://www.google.com/s2/favicons?sz=64&domain=letterboxd.com';
- var lastTitle = undefined;
- var lastYear = undefined;
- //Function Definitions
- function extractData() {
- const titleElement = document.querySelector('h1[data-testid="metadata-title"]');
- const yearElement = document.querySelector('span[data-testid="metadata-line1"]');
- if (titleElement) {
- const title = titleElement.textContent.trim() || titleElement.innerText.trim();
- if (title !== lastTitle) {
- lastTitle = title;
- console.log('The title is:', lastTitle);
- }
- } else {
- lastTitle = ''; // Reset if no title is found
- }
- if (yearElement) {
- const text = yearElement.textContent.trim() || yearElement.innerText.trim();
- const match = text.match(/\b\d{4}\b/);
- if (match && match[0] !== lastYear) {
- lastYear = match[0];
- console.log('The year is:', lastYear);
- }
- } else {
- lastYear = ''; // Reset if no year is found
- }
- }
- function checkLink(url) {
- return new Promise((resolve, reject) => {
- GM.xmlHttpRequest({
- method: 'HEAD',
- url: url,
- onload: function(response) {
- if (response.status >= 200 && response.status < 300) {
- resolve({url: url, status: response.status, accessible: true});
- } else {
- resolve({url: url, status: response.status, accessible: false});
- }
- },
- onerror: function() {
- reject(new Error(url + ' could not be reached or is blocked by CORS policy.'));
- }
- });
- });
- }
- function updateOrCreateLetterboxdIcon(link) {
- const existingIcon = document.querySelector('.letterboxd-icon');
- const metadataElement = document.querySelector('div[data-testid="metadata-children"]');
- if (existingIcon) {
- existingIcon.href = link;
- } else if (metadataElement) {
- const icon = document.createElement('img');
- icon.src = letterboxdImg;
- icon.alt = 'Letterboxd Icon';
- icon.classList.add('letterboxd-icon');
- icon.style.cssText = 'width: 24px; height: 24px; cursor: pointer;';
- const linkElement = document.createElement('a');
- linkElement.href = link;
- //linkElement.target = '_blank'; // Open in a new tab
- linkElement.appendChild(icon);
- metadataElement.insertAdjacentElement('afterend', linkElement);
- }
- }
- function buildDefaultLetterboxdUrl(title, year) {
- const titleSlug = title.trim().toLowerCase()
- .replace(/&/g, 'and')
- .replace(/[^\w\s-]/g, '')
- .replace(/\s+/g, '-');
- const letterboxdBaseUrl = 'https://letterboxd.com/film/';
- return `${letterboxdBaseUrl}${titleSlug}-${year}/`;
- }
- function removeYearFromUrl(url) {
- const yearPattern = /-\d{4}(?=\/$)/;
- return url.replace(yearPattern, '');
- }
- function replaceFilmWithDirector(url) {
- return url.replace('film','director');
- }
- function buildLetterboxdUrl(title, year) {
- let defaultUrl = buildDefaultLetterboxdUrl(title, year);
- return checkLink(defaultUrl).then(result => {
- if (result.accessible) {
- console.log(result.url, 'is accessible, status:', result.status);
- return result.url;
- } else {
- console.log(result.url, 'is not accessible, status:', result.status);
- let yearRemovedUrl = removeYearFromUrl(result.url);
- console.log('Trying URL without year:', yearRemovedUrl);
- return checkLink(yearRemovedUrl).then(yearRemovedResult => {
- if (yearRemovedResult.accessible) {
- console.log(yearRemovedUrl, 'is accessible, status:', yearRemovedResult.status);
- return yearRemovedUrl;
- } else {
- console.log(yearRemovedUrl, 'is not accessible, status:', yearRemovedResult.status);
- let directorUrl = replaceFilmWithDirector(yearRemovedUrl);
- console.log('Trying director URL:', directorUrl);
- return directorUrl;
- }
- });
- }
- }).catch(error => {
- console.error('Error after checking both film and year:', error.message);
- let newUrl = removeYearFromUrl(defaultUrl);
- return newUrl;
- });
- }
- // Main
- if(document.readyState === 'complete' || document.readyState === 'loaded' || document.readyState === 'interactive') {
- main();
- } else {
- document.addEventListener('DOMContentLoaded', main);
- }
- function main() {
- function observerCallback(mutationsList, observer) {
- extractData();
- if (lastTitle && lastYear) {
- buildLetterboxdUrl(lastTitle, lastYear).then(url => {
- updateOrCreateLetterboxdIcon(url);
- }).catch(error => {
- console.error('Error building Letterboxd URL:', error);
- });
- } else {
- console.log('Title or year not found, not updating Letterboxd icon.');
- }
- }
- const observer = new MutationObserver(observerCallback);
- observer.observe(document.body, {
- childList: true,
- characterData: true,
- subtree: true
- });
- }
- })();