Open in Miru

Adds a link to open an anime in Miru, if you have MAL-Sync installed then it will be at the bottom of the Quicklinks.

  1. // ==UserScript==
  2. // @name Open in Miru
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.2.1
  5. // @description Adds a link to open an anime in Miru, if you have MAL-Sync installed then it will be at the bottom of the Quicklinks.
  6. // @author WhiteTapeti
  7. // @match https://anilist.co/*
  8. // @match https://myanimelist.net/*
  9. // @icon https://miru.watch/logo_filled.png
  10. // @require https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js
  11. // @require https://openuserjs.org/src/libs/sizzle/GM_config.js
  12. // @grant GM_getValue
  13. // @grant GM_setValue
  14. // @grant GM.getValue
  15. // @grant GM.setValue
  16. // @grant GM_addStyle
  17. // @grant GM_registerMenuCommand
  18. // @grant GM_xmlhttpRequest
  19. // ==/UserScript==
  20.  
  21. var anilistURL = "https://anilist.co/anime/"
  22.  
  23. GM_xmlhttpRequest({
  24. method: "POST",
  25. url: "https://graphql.anilist.co",
  26. data: JSON.stringify({
  27. query: `query($id:Int,$type:MediaType){
  28. Media(idMal:$id,type:$type){
  29. siteUrl
  30. }
  31. }`,
  32. variables: {
  33. "id": window.location.pathname.split("/")[2],
  34. "type": window.location.pathname.split("/")[1].toUpperCase()
  35. }
  36. }),
  37. headers: {
  38. "Content-Type": "application/json"
  39. },
  40. onload: function(response) {
  41. anilistURL=JSON.parse(response.responseText)["data"]["Media"]["siteUrl"]
  42. }
  43. });
  44.  
  45. var quicklinkPosition = '';
  46.  
  47. async function quicklinkSettings() {
  48. let MiruQuicklinkConfigFrame = document.createElement('div');
  49. document.body.appendChild(MiruQuicklinkConfigFrame);
  50.  
  51. let gmc = new GM_config({
  52. 'id': 'MiruLinkConfig', // The id used for this instance of GM_config
  53. 'title': 'Miru Quicklink Settings', // Panel Title
  54. 'fields': // Fields object
  55. {
  56. 'Name': // This is the id of the field
  57. {
  58. 'label': 'Quicklink Position (only changes the position if Mal-Sync is installed)', // Appears next to field
  59. 'type': 'select', // Makes this setting a dropdown
  60. 'options': ['Bottom', 'Top'], // Possible choices
  61. 'default': 'Bottom' // Default value if user doesn't change it
  62. }
  63. },
  64. 'events': {
  65. 'init': function() { // runs after initialization completes
  66. },
  67.  
  68. 'save': function() { // runs after values are saved
  69. // log the saved value of the Name field
  70. this.log(this.get('Name'));
  71. quicklinkPosition = this.get('Name');
  72. if (window.location.href.indexOf('https://anilist.co/anime/') == 0 || window.location.href.indexOf('https://myanimelist.net/anime/') == 0) {
  73. setTimeout(function() {
  74. if (document.body.contains(document.getElementById("MiruLinks")) == true) {
  75. document.getElementById("MiruLinks").remove();
  76. }
  77. }, 1500);
  78. }
  79.  
  80. }
  81. },
  82. 'css': '#MiruLinkConfig *{font-family:arial,tahoma,myriad pro,sans-serif;color-scheme:dark!important}#MiruLinkConfig{background:#fff}#MiruLinkConfig .field_label{font-size:large;font-weight:700;margin-right:6px}a#MiruLinkConfig_resetLink{text-decoration:underline}#MiruLinkConfig .block{display:block}#MiruLinkConfig .saveclose_buttons{margin:16px 10px 10px;padding:2px 12px}#MiruLinkConfig .reset,#MiruLinkConfig_buttons_holder{color:#000;text-align:right}#MiruLinkConfig .config_header{font-size:20pt;margin:0}#MiruLinkConfig .reset{font-size:9pt}#MiruLinkConfig .center{text-align:center}#MiruLinkConfig .section_header_holder{margin-top:8px}#MiruLinkConfig .config_var{margin:0 0 4px}/*! CSS Used from: Embedded ; media=screen *//*! CSS Used from: Embedded ; media=screen */@media screen{:root{neutral-background:#131516;neutral-text:#d8d4cf;selection-background:#004daa;selection-text:#e8e6e3}div#MiruLinkConfig{border-color:#736b5e;color:#e8e6e3}::placeholder{color:#b2aba1;opacity:.5!important}::-webkit-scrollbar{background-color:#202324;color:#aba499}::-webkit-scrollbar-thumb{background-color:#454a4d}::-webkit-scrollbar-thumb:hover{background-color:#575e62}::-webkit-scrollbar-thumb:active{background-color:#484e51}::-webkit-scrollbar-corner{background-color:#181a1b}::selection{background-color:#004daa!important;color:#e8e6e3!important}#MiruLinkConfig{background-image:initial;background-color:#151f2e}#MiruLinkConfig .reset,#MiruLinkConfig_buttons_holder{color:#e8e6e3}button#MiruLinkConfig_closeBtn,button#MiruLinkConfig_saveBtn{background-color:#3db4f2}}',
  83. 'frame': MiruQuicklinkConfigFrame
  84. });
  85.  
  86. await gmc.initialized;
  87. quicklinkPosition = gmc.get('Name');
  88.  
  89.  
  90. GM_registerMenuCommand('Configure Miru Quicklink', () => {
  91. gmc.open()
  92. });
  93.  
  94. console.log('Saved position is ' + quicklinkPosition);
  95.  
  96. var functionIsRunning = false;
  97.  
  98. document.body.onload = function() {
  99. if (window.location.href.indexOf('https://anilist.co/anime/') == 0 || window.location.href.indexOf('https://myanimelist.net/anime/') == 0) {
  100. setTimeout(function() {
  101. if (document.body.contains(document.getElementById("MiruLinks")) == false) {
  102. if (!functionIsRunning) {
  103. functionIsRunning = true;
  104. console.log('dsa');
  105. if (quicklinkPosition == 'Bottom') {
  106. if (window.location.href.indexOf('https://anilist.co/anime/') == 0) {
  107. $(`<div style="background: rgb(var(--color-foreground)); border-radius: 3px; display: block; padding: 8px 12px; width: 100%; margin-bottom: 16px; margin-top: 16px; font-size: 1.2rem; position: relative; word-break: break-all;" class="mal_links" id="MiruLinks"> <img width="16" height="16" src="https://miru.watch/logo_filled.png"> <span style="font-weight: 500; line-height: 16px; vertical-align: middle;">Miru</span> <div style="margin-top: 5px;" class="miru_links"> <a href="miru://anime/` + document.location.href.split('/')[4] + `" target="miruOpen"> ` + document.getElementsByClassName('content')[0].childNodes[0].innerText + ` </a> </div></div><iframe href="about:blank" onload="browser.history.deleteAll();" name="miruOpen" style="visibility:hidden;position:absolute" width="0px" height="0px"></iframe>`).insertBefore(".data");
  108. } else if (window.location.href.indexOf('https://myanimelist.net/anime/') == 0) {
  109. $(`<div style="background: rgb(var(--color-foreground)); border-radius: 3px; display: block; width: 100%; margin-bottom: 16px; margin-top: 16px; position: relative; word-break: break-all;" class="mal_links" id="MiruLinks"> <h2 style="/* font-weight: 500; *//* line-height: 16;/* vertical-align: middle; */iddle;"><img width="16" height="16" src="https://miru.watch/logo_filled.png">Miru</h2> <div style="margin-top: 5px;" class="miru_links"> <a href="miru://anime/` + anilistURL.split('/')[4] + `" target="_blank"> ` + document.getElementsByClassName('title-english title-inherit')[0].innerText + ` </a> </div></div><iframe href="about:blank" onload="browser.history.deleteAll();" name="miruOpen" style="visibility:hidden;position:absolute" width="0px" height="0px"></iframe>`).insertBefore("h2:contains('Information')");
  110. }
  111. } else {
  112. if (window.location.href.indexOf('https://anilist.co/anime/') == 0) {
  113. $(`<div style="background: rgb(var(--color-foreground)); border-radius: 3px; display: block; padding: 8px 12px; width: 100%; margin-bottom: 16px; margin-top: 16px; font-size: 1.2rem; position: relative; word-break: break-all;" class="mal_links" id="MiruLinks"> <img width="16" height="16" src="https://miru.watch/logo_filled.png"> <span style="font-weight: 500; line-height: 16px; vertical-align: middle;">Miru</span> <div style="margin-top: 5px;" class="miru_links"> <a href="miru://anime/` + document.location.href.split('/')[4] + `" target="miruOpen"> ` + document.getElementsByClassName('content')[0].childNodes[0].innerText + ` </a> </div></div><iframe href="about:blank" onload="browser.history.deleteAll();" name="miruOpen" style="visibility:hidden;position:absolute" width="0px" height="0px"></iframe>`).insertAfter(".rankings");
  114. } else if (window.location.href.indexOf('https://myanimelist.net/anime/') == 0) {
  115. $(`<div style="background: rgb(var(--color-foreground)); border-radius: 3px; display: block; width: 100%; margin-bottom: 16px; margin-top: 16px; position: relative; word-break: break-all;" class="mal_links" id="MiruLinks"> <h2 style="/* font-weight: 500; *//* line-height: 16;/* vertical-align: middle; */iddle;"><img width="16" height="16" src="https://miru.watch/logo_filled.png">Miru</h2> <div style="margin-top: 5px;" class="miru_links"> <a href="miru://anime/` + anilistURL.split('/')[4] + `" target="_blank"> ` + document.getElementsByClassName('title-english title-inherit')[0].innerText + ` </a> </div></div><iframe href="about:blank" onload="browser.history.deleteAll();" name="miruOpen" style="visibility:hidden;position:absolute" width="0px" height="0px"></iframe>`).insertAfter(".viewOpEdMore.js-anime-toggle-alternative-title-button");
  116. }
  117. }
  118. functionIsRunning = false;
  119.  
  120. }
  121. }
  122. }, 1500);
  123. }
  124. }
  125.  
  126. window.addEventListener('popstate', (event) => {
  127. if (window.location.href.indexOf('https://anilist.co/anime/') == 0 || window.location.href.indexOf('https://myanimelist.net/anime/') == 0) {
  128. setTimeout(function() {
  129. if (document.body.contains(document.getElementById("MiruLinks")) == false) {
  130. if (!functionIsRunning) {
  131. functionIsRunning = true;
  132. console.log('dsa');
  133. if (quicklinkPosition == 'Bottom') {
  134. if (window.location.href.indexOf('https://anilist.co/anime/') == 0) {
  135. $(`<div style="background: rgb(var(--color-foreground)); border-radius: 3px; display: block; padding: 8px 12px; width: 100%; margin-bottom: 16px; margin-top: 16px; font-size: 1.2rem; position: relative; word-break: break-all;" class="mal_links" id="MiruLinks"> <img width="16" height="16" src="https://miru.watch/logo_filled.png"> <span style="font-weight: 500; line-height: 16px; vertical-align: middle;">Miru</span> <div style="margin-top: 5px;" class="miru_links"> <a href="miru://anime/` + document.location.href.split('/')[4] + `" target="miruOpen"> ` + document.getElementsByClassName('content')[0].childNodes[0].innerText + ` </a> </div></div><iframe href="about:blank" onload="browser.history.deleteAll();" name="miruOpen" style="visibility:hidden;position:absolute" width="0px" height="0px"></iframe>`).insertBefore(".data");
  136. } else if (window.location.href.indexOf('https://myanimelist.net/anime/') == 0) {
  137. $(`<div style="background: rgb(var(--color-foreground)); border-radius: 3px; display: block; width: 100%; margin-bottom: 16px; margin-top: 16px; position: relative; word-break: break-all;" class="mal_links" id="MiruLinks"> <h2 style="/* font-weight: 500; *//* line-height: 16;/* vertical-align: middle; */iddle;"><img width="16" height="16" src="https://miru.watch/logo_filled.png">Miru</h2> <div style="margin-top: 5px;" class="miru_links"> <a href="miru://anime/` + anilistURL.split('/')[4] + `" target="_blank"> ` + document.getElementsByClassName('title-english title-inherit')[0].innerText + ` </a> </div></div><iframe href="about:blank" onload="browser.history.deleteAll();" name="miruOpen" style="visibility:hidden;position:absolute" width="0px" height="0px"></iframe>`).insertBefore("h2:contains('Information')");
  138. }
  139. } else {
  140. if (window.location.href.indexOf('https://anilist.co/anime/') == 0) {
  141. $(`<div style="background: rgb(var(--color-foreground)); border-radius: 3px; display: block; padding: 8px 12px; width: 100%; margin-bottom: 16px; margin-top: 16px; font-size: 1.2rem; position: relative; word-break: break-all;" class="mal_links" id="MiruLinks"> <img width="16" height="16" src="https://miru.watch/logo_filled.png"> <span style="font-weight: 500; line-height: 16px; vertical-align: middle;">Miru</span> <div style="margin-top: 5px;" class="miru_links"> <a href="miru://anime/` + document.location.href.split('/')[4] + `" target="miruOpen"> ` + document.getElementsByClassName('content')[0].childNodes[0].innerText + ` </a> </div></div><iframe href="about:blank" onload="browser.history.deleteAll();" name="miruOpen" style="visibility:hidden;position:absolute" width="0px" height="0px"></iframe>`).insertAfter(".rankings");
  142. } else if (window.location.href.indexOf('https://myanimelist.net/anime/') == 0) {
  143. $(`<div style="background: rgb(var(--color-foreground)); border-radius: 3px; display: block; width: 100%; margin-bottom: 16px; margin-top: 16px; position: relative; word-break: break-all;" class="mal_links" id="MiruLinks"> <h2 style="/* font-weight: 500; *//* line-height: 16;/* vertical-align: middle; */iddle;"><img width="16" height="16" src="https://miru.watch/logo_filled.png">Miru</h2> <div style="margin-top: 5px;" class="miru_links"> <a href="miru://anime/` + anilistURL.split('/')[4] + `" target="_blank"> ` + document.getElementsByClassName('title-english title-inherit')[0].innerText + ` </a> </div></div><iframe href="about:blank" onload="browser.history.deleteAll();" name="miruOpen" style="visibility:hidden;position:absolute" width="0px" height="0px"></iframe>`).insertAfter(".viewOpEdMore.js-anime-toggle-alternative-title-button");
  144. }
  145. }
  146. functionIsRunning = false;
  147.  
  148. }
  149. }
  150. }, 1500);
  151. }
  152. });
  153.  
  154. window.addEventListener('locationchange', function() {
  155. if (window.location.href.indexOf('https://anilist.co/anime/') == 0 || window.location.href.indexOf('https://myanimelist.net/anime/') == 0) {
  156. setTimeout(function() {
  157. if (document.body.contains(document.getElementById("MiruLinks")) == false) {
  158. if (!functionIsRunning) {
  159. functionIsRunning = true;
  160. console.log('dsa');
  161. if (quicklinkPosition == 'Bottom') {
  162. if (window.location.href.indexOf('https://anilist.co/anime/') == 0) {
  163. $(`<div style="background: rgb(var(--color-foreground)); border-radius: 3px; display: block; padding: 8px 12px; width: 100%; margin-bottom: 16px; margin-top: 16px; font-size: 1.2rem; position: relative; word-break: break-all;" class="mal_links" id="MiruLinks"> <img width="16" height="16" src="https://miru.watch/logo_filled.png"> <span style="font-weight: 500; line-height: 16px; vertical-align: middle;">Miru</span> <div style="margin-top: 5px;" class="miru_links"> <a href="miru://anime/` + document.location.href.split('/')[4] + `" target="miruOpen"> ` + document.getElementsByClassName('content')[0].childNodes[0].innerText + ` </a> </div></div><iframe href="about:blank" onload="browser.history.deleteAll();" name="miruOpen" style="visibility:hidden;position:absolute" width="0px" height="0px"></iframe>`).insertBefore(".data");
  164. } else if (window.location.href.indexOf('https://myanimelist.net/anime/') == 0) {
  165. $(`<div style="background: rgb(var(--color-foreground)); border-radius: 3px; display: block; width: 100%; margin-bottom: 16px; margin-top: 16px; position: relative; word-break: break-all;" class="mal_links" id="MiruLinks"> <h2 style="/* font-weight: 500; *//* line-height: 16;/* vertical-align: middle; */iddle;"><img width="16" height="16" src="https://miru.watch/logo_filled.png">Miru</h2> <div style="margin-top: 5px;" class="miru_links"> <a href="miru://anime/` + anilistURL.split('/')[4] + `" target="_blank"> ` + document.getElementsByClassName('title-english title-inherit')[0].innerText + ` </a> </div></div><iframe href="about:blank" onload="browser.history.deleteAll();" name="miruOpen" style="visibility:hidden;position:absolute" width="0px" height="0px"></iframe>`).insertBefore("h2:contains('Information')");
  166. }
  167. } else {
  168. if (window.location.href.indexOf('https://anilist.co/anime/') == 0) {
  169. $(`<div style="background: rgb(var(--color-foreground)); border-radius: 3px; display: block; padding: 8px 12px; width: 100%; margin-bottom: 16px; margin-top: 16px; font-size: 1.2rem; position: relative; word-break: break-all;" class="mal_links" id="MiruLinks"> <img width="16" height="16" src="https://miru.watch/logo_filled.png"> <span style="font-weight: 500; line-height: 16px; vertical-align: middle;">Miru</span> <div style="margin-top: 5px;" class="miru_links"> <a href="miru://anime/` + document.location.href.split('/')[4] + `" target="miruOpen"> ` + document.getElementsByClassName('content')[0].childNodes[0].innerText + ` </a> </div></div><iframe href="about:blank" onload="browser.history.deleteAll();" name="miruOpen" style="visibility:hidden;position:absolute" width="0px" height="0px"></iframe>`).insertAfter(".rankings");
  170. } else if (window.location.href.indexOf('https://myanimelist.net/anime/') == 0) {
  171. $(`<div style="background: rgb(var(--color-foreground)); border-radius: 3px; display: block; width: 100%; margin-bottom: 16px; margin-top: 16px; position: relative; word-break: break-all;" class="mal_links" id="MiruLinks"> <h2 style="/* font-weight: 500; *//* line-height: 16;/* vertical-align: middle; */iddle;"><img width="16" height="16" src="https://miru.watch/logo_filled.png">Miru</h2> <div style="margin-top: 5px;" class="miru_links"> <a href="miru://anime/` + anilistURL.split('/')[4] + `" target="_blank"> ` + document.getElementsByClassName('title-english title-inherit')[0].innerText + ` </a> </div></div><iframe href="about:blank" onload="browser.history.deleteAll();" name="miruOpen" style="visibility:hidden;position:absolute" width="0px" height="0px"></iframe>`).insertAfter(".viewOpEdMore.js-anime-toggle-alternative-title-button");
  172. }
  173. }
  174. functionIsRunning = false;
  175.  
  176. }
  177. }
  178. }, 1500);
  179. }
  180. });
  181.  
  182. $(document).click(function() {
  183. if (window.location.href.indexOf('https://anilist.co/anime/') == 0 || window.location.href.indexOf('https://myanimelist.net/anime/') == 0) {
  184. setTimeout(function() {
  185. if (document.body.contains(document.getElementById("MiruLinks")) == false) {
  186. if (!functionIsRunning) {
  187. functionIsRunning = true;
  188. console.log('dsa');
  189. if (quicklinkPosition == 'Bottom') {
  190. if (window.location.href.indexOf('https://anilist.co/anime/') == 0) {
  191. $(`<div style="background: rgb(var(--color-foreground)); border-radius: 3px; display: block; padding: 8px 12px; width: 100%; margin-bottom: 16px; margin-top: 16px; font-size: 1.2rem; position: relative; word-break: break-all;" class="mal_links" id="MiruLinks"> <img width="16" height="16" src="https://miru.watch/logo_filled.png"> <span style="font-weight: 500; line-height: 16px; vertical-align: middle;">Miru</span> <div style="margin-top: 5px;" class="miru_links"> <a href="miru://anime/` + document.location.href.split('/')[4] + `" target="miruOpen"> ` + document.getElementsByClassName('content')[0].childNodes[0].innerText + ` </a> </div></div><iframe href="about:blank" onload="browser.history.deleteAll();" name="miruOpen" style="visibility:hidden;position:absolute" width="0px" height="0px"></iframe>`).insertBefore(".data");
  192. } else if (window.location.href.indexOf('https://myanimelist.net/anime/') == 0) {
  193. $(`<div style="background: rgb(var(--color-foreground)); border-radius: 3px; display: block; width: 100%; margin-bottom: 16px; margin-top: 16px; position: relative; word-break: break-all;" class="mal_links" id="MiruLinks"> <h2 style="/* font-weight: 500; *//* line-height: 16;/* vertical-align: middle; */iddle;"><img width="16" height="16" src="https://miru.watch/logo_filled.png">Miru</h2> <div style="margin-top: 5px;" class="miru_links"> <a href="miru://anime/` + anilistURL.split('/')[4] + `" target="_blank"> ` + document.getElementsByClassName('title-english title-inherit')[0].innerText + ` </a> </div></div><iframe href="about:blank" onload="browser.history.deleteAll();" name="miruOpen" style="visibility:hidden;position:absolute" width="0px" height="0px"></iframe>`).insertBefore("h2:contains('Information')");
  194. }
  195. } else {
  196. if (window.location.href.indexOf('https://anilist.co/anime/') == 0) {
  197. $(`<div style="background: rgb(var(--color-foreground)); border-radius: 3px; display: block; padding: 8px 12px; width: 100%; margin-bottom: 16px; margin-top: 16px; font-size: 1.2rem; position: relative; word-break: break-all;" class="mal_links" id="MiruLinks"> <img width="16" height="16" src="https://miru.watch/logo_filled.png"> <span style="font-weight: 500; line-height: 16px; vertical-align: middle;">Miru</span> <div style="margin-top: 5px;" class="miru_links"> <a href="miru://anime/` + document.location.href.split('/')[4] + `" target="miruOpen"> ` + document.getElementsByClassName('content')[0].childNodes[0].innerText + ` </a> </div></div><iframe href="about:blank" onload="browser.history.deleteAll();" name="miruOpen" style="visibility:hidden;position:absolute" width="0px" height="0px"></iframe>`).insertAfter(".rankings");
  198. } else if (window.location.href.indexOf('https://myanimelist.net/anime/') == 0) {
  199. $(`<div style="background: rgb(var(--color-foreground)); border-radius: 3px; display: block; width: 100%; margin-bottom: 16px; margin-top: 16px; position: relative; word-break: break-all;" class="mal_links" id="MiruLinks"> <h2 style="/* font-weight: 500; *//* line-height: 16;/* vertical-align: middle; */iddle;"><img width="16" height="16" src="https://miru.watch/logo_filled.png">Miru</h2> <div style="margin-top: 5px;" class="miru_links"> <a href="miru://anime/` + anilistURL.split('/')[4] + `" target="_blank"> ` + document.getElementsByClassName('title-english title-inherit')[0].innerText + ` </a> </div></div><iframe href="about:blank" onload="browser.history.deleteAll();" name="miruOpen" style="visibility:hidden;position:absolute" width="0px" height="0px"></iframe>`).insertAfter(".viewOpEdMore.js-anime-toggle-alternative-title-button");
  200. }
  201. }
  202. functionIsRunning = false;
  203.  
  204. }
  205. }
  206. }, 1500);
  207. }
  208. });
  209. }
  210. quicklinkSettings();