Links to titles - MAL

Shows entry and topic titles instead of full link urls.

安装此脚本?
作者推荐脚本

您可能也喜欢Quotes Filter - MAL

安装此脚本
  1. // ==UserScript==
  2. // @name Links to titles - MAL
  3. // @namespace https://gf.qytechs.cn/en/users/670188-hacker09?sort=daily_installs
  4. // @version 9
  5. // @description Shows entry and topic titles instead of full link urls.
  6. // @author hacker09
  7. // @match https://myanimelist.net/news/*
  8. // @match https://myanimelist.net/people/*
  9. // @match https://myanimelist.net/profile/*
  10. // @match https://myanimelist.net/clubs.php*
  11. // @match https://myanimelist.net/myblog.php*
  12. // @match https://myanimelist.net/forum/?topicid=*
  13. // @match https://myanimelist.net/comments.php?id*
  14. // @match https://myanimelist.net/stacks/add?type=*
  15. // @match https://myanimelist.net/comtocom.php?id1=*
  16. // @match https://myanimelist.net/mymessages.php?go=*
  17. // @match https://myanimelist.net/myrecommendations.php*
  18. // @match https://myanimelist.net/clubs.php?id=*&action=view&t=comments&show=*
  19. // @icon https://t3.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http://myanimelist.net&size=64
  20. // @connect api.myanimelist.net
  21. // @grant GM.xmlHttpRequest
  22. // @run-at document-end
  23. // ==/UserScript==
  24.  
  25. (function() {
  26. 'use strict';
  27. document.onkeyup = async function() { //Detect when the user is writting
  28. if (document.activeElement.value !== undefined && document.activeElement.value.match(`jpe?g|png|gif|youtu.?be`) !== null) //If the focused element is not = undefined and contains an image/YT text
  29. { //Starts the if condition
  30. document.activeElement.value = document.activeElement.value.replaceAll(/(?<!\[img])(https:\/\/\S+\.(?:jpe?g|png|gif))(?!\[\/img])/gm, '[img]$1[/img]'); //For every image url BBCodefy the url
  31. document.activeElement.value = document.activeElement.value.replaceAll(/(?:https:\/\/\S+\/|https:\/\/\S+\/watch\?v=)([\w-]{11})(?=\W)(\?\w+=\d+(&[^\s?"]+)?|&\w=\w+)?/gm, '[yt]$1[/yt]'); //For every YT url BBCodefy the url
  32. } //Finishes the if condition
  33.  
  34. if (document.activeElement.value !== undefined && document.activeElement.value.match(`myanimelist.net/(anime|manga|forum)/`) !== null) //If the focused element is not = undefined and contains an entry/forum text
  35. { //Starts the if condition
  36. document.activeElement.value = document.activeElement.value.replaceAll(/(https:\/\/myanimelist\.net\/(?:anime|manga)\/\d+)\/(?!.*?\/)([^/\s?]+)\S*/gm, '[url=$1]$2[/url]'); //For each entry with title and no subpage BBCodefy the url
  37. document.activeElement.value = document.activeElement.value.replaceAll(/(?<!\[[^\[\]]*)(https:\/\/myanimelist\.net\/(?:anime|manga)\/\d+\/)([^\s/]+?)(?:__[^\s/]*)?\b(?:\/(\w+))?/gm, '[url=$1$2/$3]$2 ($3)[/url]'); //For each entry with title and subpage BBCodefy the url
  38. document.activeElement.value = document.activeElement.value.replaceAll(/(?<=\][^\[]*)_/gm, ' '); //For each entry replace _ with spaces for the title
  39.  
  40. [...document.activeElement.value.matchAll(/(https:\/\/myanimelist\.net\/(anime|manga)\/(\d+))(?![^\[]*\])/gm)].forEach(async function(el) { //For each entry without any titles
  41. const EntryTitle = await new Promise((resolve) => GM.xmlHttpRequest({ //Starts the xmlHttpRequest
  42. responseType: 'json',
  43. url: `https://api.myanimelist.net/v2/${el[2]}/${el[3]}?fields=title`,
  44. headers: {
  45. "x-mal-client-id": "8ef0267fd86a187d479e6fcd7e1bb42a"
  46. },
  47. onload: r => resolve(r.response.title)
  48. })); //Finishes the xmlHttpRequest
  49. document.activeElement.value = document.activeElement.value.replaceAll(new RegExp(`(${el[0]})(?![^\[]*\])`, 'gm'), `[url=$1]${EntryTitle}[/url]`); //BBCodefy the url
  50. }); //Finishes the for each condition
  51.  
  52. [...document.activeElement.value.matchAll(/(https:\/\/myanimelist\.net\/forum\/\?topicid=(\d+))(?:&show=)?(\d+)?(?:#msg(\d+))?(?![^\[]*\])/gm)].forEach(async function(el, index) { //For each forum link
  53. var PostId = ''; //Creates a new global variable
  54. const Set = el[3] !== undefined ? el[3] : 0; //Get the offset
  55. const Topic = await new Promise((resolve) => GM.xmlHttpRequest({ //Starts the xmlHttpRequest
  56. responseType: 'json',
  57. url: `https://api.myanimelist.net/v2/forum/topic/${el[2]}?offset=${Set}&limit=100`,
  58. headers: {
  59. "x-mal-client-id": "8ef0267fd86a187d479e6fcd7e1bb42a"
  60. },
  61. onload: r => resolve(r.response)
  62. })); //Finishes the xmlHttpRequest
  63. Topic.data.posts.forEach(Mid => Mid.id === parseInt(el[0].match(/\d+/g).pop()) ? PostId = ` (#${Mid.number})` : ''); //Get the post ID
  64. document.activeElement.value = document.activeElement.value.replaceAll(new RegExp(`(${el[0].replace('?','\\?')})(?![^\[]*\])`, 'gm'), `[url=$1]${Topic.data.title}${PostId}[/url]`); //BBCodefy the url
  65. }); //Finishes the for each condition
  66. } //Finishes the if condition
  67. }; //Finishes the onkeyup event listener
  68.  
  69. const ParsedURLsList = []; //Creates a array to later add all non-dup mal links on the page
  70. [...document.querySelectorAll('a')].filter(a => a.innerText.match(`myanimelist.net/(anime|manga|forum)/`)).forEach(async function(el, index) { //For each entry/forum url on the page
  71. if (!ParsedURLsList.includes(el.href)) { //If the url isn't already on the array
  72. ParsedURLsList.push(el.href); //Add the url on the array
  73.  
  74. if (el.href.match(/(?<=\d+\/)[^\/".]+/) !== null && el.href.match(`/forum/`) === null) //If the link already has the entry name on it
  75. { //Starts the if condition
  76. [...document.querySelectorAll('a')].filter(a => a.innerText.match(new RegExp('^' + el.innerText.replace('?', '\\?') + '$'))).forEach(a => a.innerText = `${a.innerText.match(/(?<=\d+\/)[^\/."?]+/)[0].replaceAll('_', ' ')}${a.innerText.match(/(?<=\d+\/)[^\/."?]+[\/]?(\w+)?/)[1] !== undefined ? ` (${a.innerText.match(/(?<=\d+\/)[^\/."?]+[\/]?(\w+)?/)[1]})` : ''}`); //BBCodefy the url
  77. } //Finishes the if condition
  78.  
  79. if (el.href.match(/(?<=\d+\/)[^\/".]+/) === null && el.href.match(`/forum/`) === null) //If the link doesn't have the entry name on it
  80. { //Starts the if condition
  81. const EntryTitle = await new Promise((resolve) => GM.xmlHttpRequest({ //Starts the xmlHttpRequest
  82. responseType: 'json',
  83. url: `https://api.myanimelist.net/v2/${el.href.split('/')[3]}/${el.href.match(/\d+/)[0]}?fields=title`,
  84. headers: {
  85. "x-mal-client-id": "8ef0267fd86a187d479e6fcd7e1bb42a"
  86. },
  87. onload: r => resolve(r.response.title)
  88. })); //Finishes the xmlHttpRequest
  89. [...document.querySelectorAll('a')].filter(a => a.href.match(new RegExp('^' + el.innerText + '$'))).forEach(a => a.innerText = EntryTitle); //BBCodefy the url
  90. } //Finishes the if condition
  91.  
  92. if (el.href.match(`/forum/`) !== null) //If it's a forum link
  93. { //Starts the if condition
  94. var PostId = ''; //Creates a new global variable
  95. const Set = el.href.match(/show=(\d+)/) !== null ? el.href.match(/show=(\d+)/)[1] : 0; //Gets the offset
  96. const Topic = await new Promise((resolve) => GM.xmlHttpRequest({ //Starts the xmlHttpRequest
  97. responseType: 'json',
  98. url: `https://api.myanimelist.net/v2/forum/topic/${el.href.match(/\d+/)[0]}?offset=${Set}&limit=100`,
  99. headers: {
  100. "x-mal-client-id": "8ef0267fd86a187d479e6fcd7e1bb42a"
  101. },
  102. onload: r => resolve(r.response)
  103. })); //Finishes the xmlHttpRequest
  104. Topic.data.posts.forEach(Mid => Mid.id === parseInt(el.href.match(/\d+/g).pop()) ? PostId = ` (#${Mid.number})` : ''); //Get the post ID
  105. [...document.querySelectorAll('a')].filter(a => a.href.replaceAll('?', '').match(new RegExp('^' + el.innerText.replaceAll('?', '') + '$'))).forEach(a => a.innerText = Topic.data.title + PostId); //BBCodefy the url
  106. } //Finishes the if condition
  107. } //Finishes the if condition
  108. }); //Finishes the for each condition
  109. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址