您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a conversation button to each comment on a MAL profile using async/await and DOMParser to extract numerical user IDs.
- // ==UserScript==
- // @name MAL Conversation Button Adder (Async, DOMParser)
- // @namespace ConversationMAL
- // @version 2
- // @description Adds a conversation button to each comment on a MAL profile using async/await and DOMParser to extract numerical user IDs.
- // @author Indochina
- // @match https://myanimelist.net/profile/*
- // @match https://myanimelist.net/comments.php?id=*
- // @grant none
- // @run-at document-end
- // @license MIT
- // ==/UserScript==
- (async function() {
- 'use strict';
- // --- STEP 1: Extract the Profile Owner’s Numerical ID ---
- // Look for the Report link and extract the "id" parameter.
- const reportLink = document.querySelector('a.header-right[href*="/modules.php?go=report"]');
- let ownerId = null;
- if (reportLink) {
- const match = reportLink.href.match(/id=(\d+)/);
- if (match) {
- ownerId = match[1];
- console.log(`Profile owner ID extracted: ${ownerId}`);
- }
- }
- if (!ownerId) {
- console.error("Could not determine the profile owner's numerical ID from the Report link.");
- return;
- }
- // --- STEP 2: Define a helper to fetch and extract a commenter's numerical ID ---
- // We use a cache to avoid refetching the same profile.
- const userIdCache = {};
- async function getUserId(username) {
- if (userIdCache[username]) return userIdCache[username];
- try {
- // Fetch the commenter's profile page
- const response = await fetch(`https://myanimelist.net/profile/${username}`);
- const text = await response.text();
- // Parse the HTML response to a document
- const parser = new DOMParser();
- const doc = parser.parseFromString(text, 'text/html');
- // Look for the Report link on the fetched profile page.
- // (This should work for profiles that include it.)
- const reportLink = doc.querySelector('a.header-right[href*="/modules.php?go=report"]');
- if (reportLink) {
- const match = reportLink.href.match(/id=(\d+)/);
- if (match) {
- const userId = match[1];
- userIdCache[username] = userId;
- console.log(`Extracted user id for ${username} via report link: ${userId}`);
- return userId;
- }
- }
- // If the Report link wasn't found, log an error.
- console.error(`Could not extract user_id for ${username}`);
- return null;
- } catch (error) {
- console.error(`Error fetching profile for ${username}:`, error);
- return null;
- }
- }
- // --- STEP 3: Process each comment ---
- // We target each comment container. In many MAL pages, the comment content is within a <div class="text"> element.
- const commentDivs = document.querySelectorAll('div.text');
- for (const commentDiv of commentDivs) {
- // Find the comment author’s profile link; usually an <a class="fw-b"> element.
- const profileLink = commentDiv.querySelector('a.fw-b[href*="/profile/"]');
- if (!profileLink) continue;
- // Extract the username from the URL.
- // For example: "https://myanimelist.net/profile/Indochina"
- const urlParts = profileLink.href.split('/profile/');
- if (urlParts.length < 2) continue;
- const username = urlParts[1].split('?')[0];
- console.log(`Processing comment by: ${username}`);
- // Find or create the container for action links.
- let actionsDiv = commentDiv.querySelector('div.postActions');
- if (!actionsDiv) {
- actionsDiv = document.createElement("div");
- actionsDiv.className = "postActions ar mt4";
- actionsDiv.style.clear = "both";
- actionsDiv.style.paddingTop = "10px";
- commentDiv.appendChild(actionsDiv);
- }
- // If a Conversation link already exists, skip this comment.
- if (actionsDiv.querySelector('a.ml8[href*="comtocom.php"]')) {
- console.log(`Conversation link already exists for ${username}`);
- continue;
- }
- // --- STEP 4: Fetch the commenter's numerical ID and create the button ---
- const commenterId = await getUserId(username);
- if (!commenterId) continue;
- // Create the Conversation button.
- // id1 is the profile owner's id and id2 is the commenter's id.
- const convoLink = document.createElement("a");
- convoLink.className = "ml8";
- convoLink.href = `https://myanimelist.net/comtocom.php?id1=${ownerId}&id2=${commenterId}`;
- convoLink.textContent = "Conversation";
- convoLink.style.marginLeft = "10px";
- // Append the button to the actions container.
- actionsDiv.appendChild(convoLink);
- }
- })();