ylMzBetterChat

creates clickable links for urls and players IDs

  1. // ==UserScript==
  2. // @name ylMzBetterChat
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.4
  5. // @description creates clickable links for urls and players IDs
  6. // @author You
  7. // @match https://www.managerzone.com/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=managerzone.com
  9. // @license MIT
  10. // @grant none
  11. // ==/UserScript==
  12. (function() {
  13. 'use strict';
  14. // Initialize processed messages tracking
  15. const processedMessages = new Set();
  16. // Process existing messages on page load
  17. function processExistingMessages() {
  18. $(".messenger-row.buddy, .messenger-row.you").each(function() {
  19. const $this = $(this);
  20. const messageId = $this.attr('id') || $this.index();
  21. if (!processedMessages.has(messageId)) {
  22. processedMessages.add(messageId);
  23. const newHtml = findPlayerId($this.text());
  24. $this.html(newHtml);
  25. }
  26. });
  27. }
  28. // Improved scroll event handler with debounce
  29. let scrollTimeout;
  30. $(".messenger-conversation").on('scroll', function() {
  31. clearTimeout(scrollTimeout);
  32. scrollTimeout = setTimeout(function() {
  33. processExistingMessages();
  34. }, 300); // 300ms debounce
  35. });
  36. // Set up MutationObserver to detect new messages
  37. const chatObserver = new MutationObserver(function(mutations) {
  38. processExistingMessages(); // Process all messages when any change is detected
  39. });
  40. // Start observing the chat container with more comprehensive options
  41. function setupObservers() {
  42. const chatContainers = document.querySelectorAll(".messenger-conversation");
  43. chatContainers.forEach(container => {
  44. if (container) {
  45. chatObserver.observe(container, {
  46. childList: true,
  47. subtree: true,
  48. characterData: true,
  49. attributes: true
  50. });
  51. }
  52. });
  53. }
  54. // Process messages on initial page load and set up observers
  55. $(document).ready(function() {
  56. setTimeout(function() {
  57. processExistingMessages();
  58. setupObservers();
  59. // Add a global click handler to process messages when clicking anywhere in the chat
  60. $(document).on('click', '.messenger-dialog', function() {
  61. setTimeout(processExistingMessages, 100);
  62. });
  63. // Handle AJAX loading specifically
  64. $(document).ajaxComplete(function(event, xhr, settings) {
  65. if (settings.url && settings.url.includes('messenger')) {
  66. setTimeout(processExistingMessages, 300);
  67. }
  68. });
  69. }, 1000);
  70. });
  71.  
  72. function findPlayerId(msg) {
  73. const words = msg.split(/\s+/);
  74. let newMsg = " ";
  75. for (let i = 0; i < words.length; i++) {
  76. let word = words[i].trim();
  77. if (/^\d{9}$/.test(word)) {
  78. word = "<a href='https://www.managerzone.com/?p=players&pid=" + word +"'>" + word + "</a>";
  79. }
  80. // Improved URL detection with regex
  81. else if (/^(https?:\/\/|www\.)[^\s]+\.[^\s]+/.test(word)) {
  82. // Add https:// prefix if missing
  83. const href = word.startsWith('www.') ? 'https://' + word : word;
  84. word = "<a href='" + href + "' target='_blank'>" + word + "</a>";
  85. }
  86. newMsg = newMsg + " " + word;
  87. }
  88. return newMsg;
  89. }
  90. function processLeagueLinks() {
  91. // Define all language variants
  92. const titleVariants = [
  93. "Liga Światowa U18",
  94. "U18 World League",
  95. "Liga Mundial U18",
  96. "Liga Mundial Sub18",
  97. "Liga Mundial Sub-18",
  98. "U18 Dünya Ligi"
  99. ];
  100. // Step 1: Check for h1 with any of the language variants
  101. const h1Elements = Array.from(document.getElementsByTagName('h1'));
  102. const targetH1 = h1Elements.find(h1 =>
  103. titleVariants.some(variant => h1.textContent.trim() === variant)
  104. );
  105. if (!targetH1) {
  106. console.log("Target H1 not found in any language variant");
  107. return;
  108. }
  109. // Check if link already exists next to h1
  110. const nextElement = targetH1.nextElementSibling;
  111. if (nextElement && nextElement.tagName === 'A') {
  112. console.log("Link already exists next to H1");
  113. return;
  114. }
  115. // Step 2: Find link containing specific href pattern
  116. const links = document.getElementsByTagName('a');
  117. const teamLink = Array.from(links).find(link => link.href.includes('?p=team&tid='));
  118. if (!teamLink) {
  119. console.log("Team link not found");
  120. return;
  121. }
  122. // Step 3: Perform AJAX call
  123. fetch(teamLink.href)
  124. .then(response => response.text())
  125. .then(html => {
  126. // Create a temporary DOM parser
  127. const parser = new DOMParser();
  128. const doc = parser.parseFromString(html, 'text/html');
  129. // Step 4: Look for league link specifically in infoAboutTeam div
  130. const infoDiv = doc.getElementById('infoAboutTeam');
  131. if (!infoDiv) {
  132. console.log("Info div not found in AJAX response");
  133. return;
  134. }
  135. const leagueLinks = Array.from(infoDiv.getElementsByTagName('a'));
  136. const leagueLink = leagueLinks.find(link =>
  137. link.href.includes('/?p=league&type=u18_world') ||
  138. link.href.includes('/?p=league&amp;type=u18_world')
  139. );
  140. if (!leagueLink) {
  141. console.log("League link not found in info div");
  142. return;
  143. }
  144. // Step 5: Add new link next to h1
  145. const newLink = document.createElement('a');
  146. newLink.href = leagueLink.href;
  147. newLink.textContent = leagueLink.textContent;
  148. newLink.style.marginLeft = '10px';
  149. targetH1.parentNode.insertBefore(newLink, targetH1.nextSibling);
  150. })
  151. .catch(error => {
  152. console.error("Error during AJAX request:", error);
  153. });
  154. }
  155. // Your code here...
  156. // Control variable to ensure we only process once per tab
  157. let hasProcessed = false;
  158. // Function to handle visibility change
  159. function handleVisibilityChange() {
  160. if (document.visibilityState === 'visible' && !hasProcessed) {
  161. hasProcessed = true;
  162. setTimeout(processLeagueLinks, 6000);
  163. }
  164. }
  165. // Add visibility change listener
  166. document.addEventListener('visibilitychange', handleVisibilityChange);
  167. // Also check initial state in case tab is already active
  168. if (document.visibilityState === 'visible') {
  169. hasProcessed = true;
  170. setTimeout(processLeagueLinks, 500);
  171. }
  172. // Your code here...
  173. })();