Mediux Titlecards Fix

Inserts Season #s into Titlecard YAML and fixes errors where no posters are available

目前为 2024-10-10 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Mediux Titlecards Fix
  3. // @license MIT
  4. // @version 1.0
  5. // @description Inserts Season #s into Titlecard YAML and fixes errors where no posters are available
  6. // @author azuravian
  7. // @require https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
  8. // @match https://mediux.pro/*
  9. // @grant none
  10. // @run-at document-end
  11. // @namespace https://greasyfork.org/users/1025348
  12. // ==/UserScript==
  13.  
  14. waitForKeyElements(
  15. "code.whitespace-pre-wrap",
  16. start);
  17.  
  18. function sleep(ms) {
  19. return new Promise(resolve => setTimeout(resolve, ms));
  20. }
  21.  
  22. function get_posters() {
  23. const regexpost = /posterCheck/g
  24. var scriptlist = document.querySelectorAll('script')
  25. for (let i = scriptlist.length - 1; i >= 0; i--) {
  26. const element = scriptlist[i];
  27. if (regexpost.test(element.textContent)) {
  28. var str1 = element.textContent.replace('self.__next_f.push(', '');
  29. var str1 = str1.substring(0, str1.length - 1);
  30. var jsonString = JSON.parse(str1)[1].split('{"set":')[1];
  31. var fullJson = `{"set":${jsonString}`;
  32. var parsedObject = JSON.parse(fullJson.substring(0, fullJson.length - 2));
  33. return parsedObject.set.files;
  34. }
  35. }
  36. }
  37.  
  38. function color_change(button) {
  39. button.classList.remove('bg-gray-500');
  40. button.classList.add('bg-green-500');
  41.  
  42. // After 2 seconds, change it back to bg-gray-500
  43. setTimeout(() => {
  44. button.classList.remove('bg-green-500');
  45. button.classList.add('bg-gray-500');
  46. }, 2000); // 2000 milliseconds = 2 seconds
  47. }
  48.  
  49. function fix_posters(codeblock) {
  50. const button = document.querySelector('#fpbutton');
  51. var yaml = codeblock.textContent;
  52. var posters = get_posters();
  53. var seasons = posters.filter((poster) => poster.title.includes("Season"));
  54. for (i in seasons) {
  55. var current = seasons.filter((season) => season.title.includes(`Season ${i}`));
  56. yaml = yaml + ` ${i}:\n url_poster: https://api.mediux.pro/assets/${current[0].id}\n`;
  57. }
  58. yaml = yaml.substring(0, yaml.length - 1);
  59. codeblock.innerText = yaml;
  60. navigator.clipboard.writeText(yaml);
  61. color_change(button);
  62. }
  63.  
  64. function fix_cards(codeblock) {
  65. const button = document.querySelector('#fcbutton');
  66. const str = codeblock.innerText;
  67. const regextest = /(seasons:\n)( episodes:)/g;
  68. const regex = /( episodes:)/g;
  69. let counter = 1;
  70. if (regextest.test(str)) {
  71. const modifiedStr = str.replace(regex, (match) => {
  72. const newLine = ` ${counter++}:\n`; // Create the new line with the counter
  73. return `${newLine}${match}`; // Return the new line followed by the match
  74. });
  75. codeblock.innerText = modifiedStr;
  76. navigator.clipboard.writeText(modifiedStr);
  77. color_change(button);
  78. }
  79. }
  80.  
  81. function start() {
  82. const codeblock = document.querySelector('code.whitespace-pre-wrap');
  83. var fpbutton = $('<button id="fpbutton" class="absolute duration-500 top-1 right-1 text-xs py-1 px-2 bg-gray-500 text-white rounded flex items-center justify-center" style="margin-top:30px"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-gallery-horizontal-end w-5 h-5"><path d="M2 7v10"></path><path d="M6 5v14"></path><rect width="12" height="18" x="10" y="3" rx="2"></rect></svg></button>');
  84. // Set the onclick event to call the runner function
  85. fpbutton.on('click', () => fix_posters(codeblock));
  86.  
  87. // Insert the button after the code element with class "whitespace-pre-wrap"
  88. $('.whitespace-pre-wrap').after(fpbutton);
  89.  
  90. var fcbutton = $('<button id="fcbutton" class="absolute duration-500 top-1 right-1 text-xs py-1 px-2 bg-gray-500 text-white rounded flex items-center justify-center" style="margin-top:60px"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-gallery-vertical-end w-5 h-5"><path d="M7 2h10"></path><path d="M5 6h14"></path><rect width="18" height="12" x="3" y="10" rx="2"></rect></svg></button>');
  91. // Set the onclick event to call the runner function
  92. fcbutton.on('click', () => fix_cards(codeblock));
  93.  
  94. // Insert the button after the fpbutton
  95. $('#fpbutton').after(fcbutton);
  96. }
  97.  
  98.  
  99. /*--- waitForKeyElements(): A utility function, for Greasemonkey scripts,
  100. that detects and handles AJAXed content.
  101. Usage example:
  102. waitForKeyElements (
  103. "div.comments"
  104. , commentCallbackFunction
  105. );
  106. //--- Page-specific function to do what we want when the node is found.
  107. function commentCallbackFunction (jNode) {
  108. jNode.text ("This comment changed by waitForKeyElements().");
  109. }
  110. IMPORTANT: This function requires your script to have loaded jQuery.
  111. */
  112. function waitForKeyElements (
  113. selectorTxt, /* Required: The jQuery selector string that
  114. specifies the desired element(s).
  115. */
  116. actionFunction, /* Required: The code to run when elements are
  117. found. It is passed a jNode to the matched
  118. element.
  119. */
  120. bWaitOnce, /* Optional: If false, will continue to scan for
  121. new elements even after the first match is
  122. found.
  123. */
  124. iframeSelector /* Optional: If set, identifies the iframe to
  125. search.
  126. */
  127. ) {
  128. var targetNodes, btargetsFound;
  129.  
  130. if (typeof iframeSelector == "undefined")
  131. targetNodes = jQuery(selectorTxt);
  132. else
  133. targetNodes = jQuery(iframeSelector).contents ()
  134. .find (selectorTxt);
  135.  
  136. if (targetNodes && targetNodes.length > 0) {
  137. btargetsFound = true;
  138. /*--- Found target node(s). Go through each and act if they
  139. are new.
  140. */
  141. targetNodes.each ( function () {
  142. var jThis = jQuery(this);
  143. var alreadyFound = jThis.data ('alreadyFound') || false;
  144.  
  145. if (!alreadyFound) {
  146. //--- Call the payload function.
  147. var cancelFound = actionFunction (jThis);
  148. if (cancelFound)
  149. btargetsFound = false;
  150. else
  151. jThis.data ('alreadyFound', true);
  152. }
  153. } );
  154. }
  155. else {
  156. btargetsFound = false;
  157. }
  158.  
  159. //--- Get the timer-control variable for this selector.
  160. var controlObj = waitForKeyElements.controlObj || {};
  161. var controlKey = selectorTxt.replace (/[^\w]/g, "_");
  162. var timeControl = controlObj [controlKey];
  163.  
  164. //--- Now set or clear the timer as appropriate.
  165. if (btargetsFound && bWaitOnce && timeControl) {
  166. //--- The only condition where we need to clear the timer.
  167. clearInterval (timeControl);
  168. delete controlObj [controlKey]
  169. }
  170. else {
  171. //--- Set a timer, if needed.
  172. if ( ! timeControl) {
  173. timeControl = setInterval ( function () {
  174. waitForKeyElements ( selectorTxt,
  175. actionFunction,
  176. bWaitOnce,
  177. iframeSelector
  178. );
  179. },
  180. 300
  181. );
  182. controlObj [controlKey] = timeControl;
  183. }
  184. }
  185. waitForKeyElements.controlObj = controlObj;
  186. }