ModrinthHelper

自动获取你的follow列表,并更改搜索页面follow的图标

  1. // ==UserScript==
  2. // @name ModrinthHelper
  3. // @namespace http://suzunemaiki.moe/
  4. // @version 0.3
  5. // @description 自动获取你的follow列表,并更改搜索页面follow的图标
  6. // @author SuzuneMaiki
  7. // @match http*://modrinth.com/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=modrinth.com
  9. // @grant none
  10. // @license MIT
  11. // ==/UserScript==
  12.  
  13. (async function () {
  14. 'use strict';
  15. let authorization = getCookie('auth-token');
  16. let divWarning = document.createElement('div');
  17. var listFollow = await getFollow();
  18. divWarning.setAttribute('style', 'width:200px;height:100px;position:fixed;top:5px;right:5px;text-align:center;');
  19. document.body.appendChild(divWarning);
  20. const config = {
  21. childList: true,
  22. attributes: true
  23. };
  24. if (!authorization) {
  25. warning('请先登录');
  26. } else {
  27. changeIcon();
  28. const observer = new MutationObserver(() => {
  29. changeIcon();
  30. });
  31. observer.observe(document.getElementsByClassName('normal-page__content')[0], config);
  32. }
  33. //
  34. async function sendRequest(type, url, state) {
  35. return new Promise(function (resolve, reject) {
  36. let request = new XMLHttpRequest();
  37. request.open(type, url, true);
  38. request.setRequestHeader('Authorization', authorization);
  39. request.send('');
  40. request.onreadystatechange = function () {
  41. if (request.readyState == 4) {
  42. if (request.status == state) {
  43. if (request.responseText != '') {
  44. resolve(JSON.parse(request.responseText));
  45. }
  46. else resolve({});
  47. } else {
  48. warning(request.responseText + '\n' + url);
  49. }
  50. }
  51. };
  52. });
  53. }
  54. function getCookie(key) {
  55. var reg = new RegExp(key + '=([^;]*)'); // 正则表达式
  56. var arr = document.cookie.match(reg); // 获取正则匹配后的值
  57. if (!arr) return null;
  58. return arr[1]; // 转码并返回值
  59. }
  60. //
  61. async function follow(project) {
  62. let callback = await sendRequest("POST", 'https://api.modrinth.com/v2/project/' + project + '/follow', 204);
  63. await getFollow();
  64. changeIcon();
  65. warning('关注成功');
  66. }
  67. //
  68. async function unfollow(project) {
  69. let callback = await sendRequest("DELETE", 'https://api.modrinth.com/v2/project/' + project + '/follow', 204);
  70. await getFollow();
  71. changeIcon();
  72. warning('取消成功');
  73. }
  74. //
  75. async function getFollow() {
  76. let user = await sendRequest('GET', 'https://api.modrinth.com/v2/user', 200);
  77. let uid = user.id;
  78. let arrayFollow = await sendRequest("GET", 'https://api.modrinth.com/v2/user/' + uid + '/follows', 200);
  79. let oList = {};
  80. for (let i = 0; i < arrayFollow.length; i++) {
  81. let slug = arrayFollow[i].slug;
  82. oList[slug] = arrayFollow[i];
  83. }
  84. listFollow = oList;
  85. warning('获取列表成功');
  86. return oList;
  87. }
  88. //
  89. function changeIcon() {
  90. if (!listFollow) { }
  91. let arrayNodes = document.getElementsByClassName('project-card');
  92. for (let i = 0; i < arrayNodes.length; i++) {
  93. let node = arrayNodes[i];
  94. let nodeTitle = node.getElementsByClassName('title')[0].childNodes[0];
  95. let slug = nodeTitle.href.split('mod/')[1];
  96. let boolFind = listFollow[slug];
  97. let favourite = node.childNodes[5].childNodes[1];
  98. let icon = document.createElement('a');
  99. if (boolFind) {
  100. icon.innerHTML = '❤️';
  101. icon.onclick = function () {
  102. unfollow(slug);
  103. };
  104. } else {
  105. icon.innerHTML = '🤍';
  106. icon.onclick = function () {
  107. follow(slug);
  108. };
  109. }
  110. let replaced = favourite.childNodes[0];
  111. favourite.replaceChild(icon, replaced);
  112. }
  113. warning('替换成功');
  114. }
  115. function warning(info) {
  116. let nodeWarning = document.createElement('div');
  117. nodeWarning.setAttribute('style', 'width:200px;height:100px;background-color:rgba(255,255,255,0.5);text-align:center;font-size:12px');
  118. nodeWarning.innerHTML = info + '<p>3秒后自动关闭,或点击关闭此提示</p>';
  119. nodeWarning.setAttribute('onclick', 'this.remove()');
  120. //想看log取消注释下面这行
  121. //divWarning.appendChild(nodeWarning);
  122. setTimeout(function (object) {
  123. object.remove();
  124. }, 3000, nodeWarning);
  125. //
  126. }
  127. })();