ModrinthHelper

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

目前為 2024-07-01 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         ModrinthHelper
// @namespace    http://suzunemaiki.moe/
// @version      0.2
// @description  自动获取你的follow列表,并更改搜索页面follow的图标
// @author       SuzuneMaiki
// @match        http*://modrinth.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=modrinth.com
// @grant        none
// @license      MIT
// ==/UserScript==

/*
Follow:
POST /v2/project/P7dR8mSH/follow HTTP/2
Host: api.modrinth.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:127.0) Gecko/20100101 Firefox/127.0
Accept:
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br, zstd
Referer: https://modrinth.com/
Authorization: mra_U6dlSKbCjskh8IW16o6TOOQg7yZdBWpPVOOpDzIjAnPvrIEo3Kw6UUSx418t
Origin: https://modrinth.com
Connection: keep-alive
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Priority: u=4
Content-Length: 0
TE: trailers

Unfollow:
DELETE /v2/project/P7dR8mSH/follow HTTP/2
Host: api.modrinth.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:127.0) Gecko/20100101 Firefox/127.0
Accept:
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br, zstd
Referer: https://modrinth.com/
Authorization: mra_U6dlSKbCjskh8IW16o6TOOQg7yZdBWpPVOOpDzIjAnPvrIEo3Kw6UUSx418t
Origin: https://modrinth.com
Connection: keep-alive
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Priority: u=4
TE: trailers

Follow list
https://api.modrinth.com/v2/user/gE2LkmfG/follows
GET /v2/user/gE2LkmfG/follows HTTP/2
Host: api.modrinth.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:127.0) Gecko/20100101 Firefox/127.0
Accept:
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br, zstd
Referer: https://modrinth.com/
Authorization: mra_U6dlSKbCjskh8IW16o6TOOQg7yZdBWpPVOOpDzIjAnPvrIEo3Kw6UUSx418t
Origin: https://modrinth.com
Connection: keep-alive
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Priority: u=4
TE: trailers
*/

(async function () {
    'use strict';
    let authorization = getCookie('auth-token');
    if (!authorization) {
    } else {
        warning('info');
        document.addEventListener('click', function () {
            changeIcon();
        }, false);
    }
    //
    async function sendRequest(type, url, state) {
        return new Promise(function (resolve, reject) {
            let request = new XMLHttpRequest();
            request.open(type, url, true);
            request.setRequestHeader('Authorization', authorization);
            request.send('');
            request.onreadystatechange = function () {
                if (request.readyState == 4) {
                    if (request.status == state) {
                        if (request.responseText != '') {
                            resolve(JSON.parse(request.responseText));
                        }
                        else resolve({});
                    } else {
                        console.log(request.responseText + '\n' + url);
                    }
                }
            };
        });
    }
    function getCookie(key) {
        var reg = new RegExp(key + '=([^;]*)'); // 正则表达式
        var arr = document.cookie.match(reg); // 获取正则匹配后的值
        if (!arr) return null;
        return arr[1]; // 转码并返回值
    }
    //
    async function follow(project) {
        let callback = await sendRequest("POST", 'https://api.modrinth.com/v2/project/' + project + '/follow', 204);
        changeIcon();
    }
    //
    async function unfollow(project) {
        let callback = await sendRequest("DELETE", 'https://api.modrinth.com/v2/project/' + project + '/follow', 204);
        changeIcon();
    }
    //
    async function getFollow() {
        let user = await sendRequest('GET', 'https://api.modrinth.com/v2/user', 200);
        let uid = user.id;
        let arrayFollow = await sendRequest("GET", 'https://api.modrinth.com/v2/user/' + uid + '/follows', 200);
        let oList = {};
        for (let i = 0; i < arrayFollow.length; i++) {
            let slug = arrayFollow[i].slug;
            oList[slug] = arrayFollow[i];
        }
        return oList;
    }
    //
    async function changeIcon() {
        let listFollow = await getFollow();
        let arrayNodes = document.getElementsByClassName('project-card');
        for (let i = 0; i < arrayNodes.length; i++) {
            let node = arrayNodes[i];
            let nodeTitle = node.getElementsByClassName('title')[0].childNodes[0];
            let slug = nodeTitle.href.split('mod/')[1];
            let boolFind = listFollow[slug];
            let favourite = node.childNodes[5].childNodes[1];
            let icon = document.createElement('a');
            if (boolFind) {
                icon.innerHTML = '❤️';
                icon.onclick = function () { unfollow(slug); };
            } else {
                icon.innerHTML = '🤍';
                icon.onclick = function () { follow(slug); };
            }
            let replaced = favourite.childNodes[0];
            favourite.replaceChild(icon, replaced);
        }
    }
    function warning(info) {
        let nodeWarning = document.createElement('div');
        nodeWarning.setAttribute('style', 'width:200px;height:100px;position:fixed;top:5px;right:5px;background-color:rgba(255,255,255,0.5);');
        nodeWarning.innerHTML = info;
        document.body.appendChild(nodeWarning);
    }
})();