Greasy Fork 还支持 简体中文。

Twonky host origin fix

Fixes image/link/url references to the local host automatically, allowing you to browse servers normally. Functionality inspired by 'Twonky Viewer' chrome extension developed by

  1. // ==UserScript==
  2. // @name Twonky host origin fix
  3. // @namespace https://greasyfork.org/en/users/1443383
  4. // @version 1.0
  5. // @license MIT
  6. // @description Fixes image/link/url references to the local host automatically, allowing you to browse servers normally. Functionality inspired by 'Twonky Viewer' chrome extension developed by
  7. // @author kryo
  8. // @match *://*:9000/*
  9. // @match *://*:9001/*
  10. // @match *://*:9002/*
  11. // @match *://*:9443/*
  12. // @include *://*:*/*
  13. // @grant none
  14. // @run-at document-start
  15. // ==/UserScript==
  16.  
  17. (function() {
  18. 'use strict';
  19.  
  20. const TWONKY_PORTS = ['9000', '9001', '9002', '9443'];
  21. // Regex to match http(s)://127.0.0.1:PORT/... where PORT is one of the Twonky ports
  22. const urlPattern = new RegExp(`^https?:\/\/127\\.0\\.0\\.1:(${TWONKY_PORTS.join('|')})(\/|$)`);
  23. // Get the correct hostname from the current page URL
  24. const correctHostname = window.location.hostname;
  25.  
  26. // --- Function to fix attributes of a given node ---
  27. function fixNodeAttributes(node) {
  28. // Only process element nodes
  29. if (node.nodeType !== Node.ELEMENT_NODE) {
  30. return;
  31. }
  32.  
  33. // List of attributes that commonly contain URLs
  34. const urlAttributes = ['src', 'href', 'action', 'data-url']; // Add other attributes if needed
  35.  
  36. urlAttributes.forEach(attr => {
  37. if (node.hasAttribute(attr)) {
  38. const originalUrl = node.getAttribute(attr);
  39. if (originalUrl && urlPattern.test(originalUrl)) {
  40. const newUrl = originalUrl.replace('127.0.0.1', correctHostname);
  41. console.log(`Tampermonkey: Fixing URL in ${node.tagName} ${attr}: ${originalUrl} -> ${newUrl}`);
  42. node.setAttribute(attr, newUrl);
  43. // Special handling for anchors to potentially update text content if it mirrors the href
  44. if (node.tagName === 'A' && node.textContent === originalUrl) {
  45. node.textContent = newUrl;
  46. }
  47. }
  48. }
  49. });
  50.  
  51. // Add specific handling for other elements/attributes if necessary
  52. // e.g., <object data="...">, <embed src="...">, background-image styles
  53. if (node.style && node.style.backgroundImage) {
  54. const originalUrl = node.style.backgroundImage;
  55. // Basic check: url("http://127.0.0.1:9000/...")
  56. if (originalUrl.includes('url("') && originalUrl.includes('127.0.0.1:')) {
  57. // More robust regex might be needed here depending on variations
  58. const potentialUrl = originalUrl.substring(originalUrl.indexOf('url("') + 5, originalUrl.lastIndexOf('")'));
  59. if (urlPattern.test(potentialUrl)) {
  60. const newUrl = potentialUrl.replace('127.0.0.1', correctHostname);
  61. console.log(`Tampermonkey: Fixing background-image URL: ${potentialUrl} -> ${newUrl}`);
  62. node.style.backgroundImage = `url("${newUrl}")`;
  63. }
  64. }
  65. }
  66. }
  67.  
  68. // --- Function to recursively scan a node and its children ---
  69. function scanAndFixNodes(node) {
  70. fixNodeAttributes(node);
  71. // Recursively scan child elements
  72. if (node.children) {
  73. for (let i = 0; i < node.children.length; i++) {
  74. scanAndFixNodes(node.children[i]);
  75. }
  76. }
  77. }
  78.  
  79. // --- MutationObserver to watch for dynamically added elements ---
  80. const observer = new MutationObserver(mutations => {
  81. mutations.forEach(mutation => {
  82. // Check added nodes
  83. mutation.addedNodes.forEach(newNode => {
  84. scanAndFixNodes(newNode); // Scan the new node and its children
  85. });
  86.  
  87. // Check if attributes changed (less common for initial load, but good for dynamic updates)
  88. if (mutation.type === 'attributes' && mutation.target) {
  89. fixNodeAttributes(mutation.target);
  90. }
  91. });
  92. });
  93.  
  94. // --- Start observing ---
  95. // We run at document-start, so wait for the documentElement to be available
  96. // and observe it for additions/changes to head and body
  97. const observerConfig = {
  98. childList: true, // Watch for adding/removing child nodes
  99. subtree: true, // Watch descendants as well
  100. attributes: true, // Watch for attribute changes
  101. attributeFilter: ['src', 'href', 'action', 'data-url', 'style'] // Optional: Be specific about watched attributes
  102. };
  103.  
  104. // Function to start the observer once the document element exists
  105. function observeRoot() {
  106. if (document.documentElement) {
  107. console.log('Tampermonkey: Twonky Fixer - Starting MutationObserver.');
  108. observer.observe(document.documentElement, observerConfig);
  109.  
  110. // --- Initial Scan ---
  111. // Perform an initial scan of the document in case elements already exist
  112. // when the script runs (especially important if @run-at is not document-start,
  113. // but good practice anyway).
  114. console.log('Tampermonkey: Twonky Fixer - Performing initial DOM scan.');
  115. scanAndFixNodes(document.documentElement);
  116. } else {
  117. // If documentElement is not yet ready (should be rare with document-start), retry shortly
  118. console.log('Tampermonkey: Twonky Fixer - documentElement not ready, retrying...');
  119. setTimeout(observeRoot, 50);
  120. }
  121. }
  122.  
  123. observeRoot();
  124.  
  125. // Optional: Disconnect observer when page unloads (usually not strictly necessary for userscripts)
  126. // window.addEventListener('unload', () => {
  127. // if (observer) {
  128. // observer.disconnect();
  129. // console.log('Tampermonkey: Twonky Fixer - Disconnected MutationObserver.');
  130. // }
  131. // });
  132.  
  133. })();