在 V2EX 的每个帖子标题旁添加一个“忽略”按钮,单击即可忽略该主题。
当前为
// ==UserScript==
// @name V2EX Ignore
// @license GNU GPLv3
// @namespace https://www.example.com/
// @version 1.9
// @description Adds an "Ignore" button next to each post's title on V2EX that allows you to ignore the topic with a single click.
// @description:zh-CN 在 V2EX 的每个帖子标题旁添加一个“忽略”按钮,单击即可忽略该主题。
// @description:zh-TW 在 V2EX 的每個帖子標題旁添加一個“忽略”按鈕,單擊即可忽略該主題。
// @description:ja 在 V2EX の各投稿タイトルの横に、「無視する」ボタンを追加し、クリックするだけでそのトピックを無視できます。
// @author Arryboom
// @match https://*.v2ex.com/*
// @match https://v2ex.com/*
// @grant GM_xmlhttpRequest
// @run-at document-end
// ==/UserScript==
(function() {
'use strict';
const debug = true;
const debugLog = debug ? console.log.bind(console) : function() {};
debugLog("Ignore plugin running");
// Function to ignore a topic
function ignoreTopic(event) {
event.preventDefault();
const topicLink = event.target.parentNode.querySelector('.item_title a');
if (topicLink) {
const topicUrl = topicLink.href;
const topicId = getTopicIdFromUrl(topicUrl);
if (topicId) {
getOnceValue().then(onceValue => {
const ignoreUrl = `https://${window.location.hostname}/ignore/topic/${topicId}?once=${onceValue}`;
GM_xmlhttpRequest({
method: 'GET',
url: ignoreUrl,
onload: function(response) {
debugLog(`Topic ${topicId} ignored.`);
const post = event.target.closest('.cell.item');
if (post) {
post.remove();
debugLog(`Post ${topicId} removed.`);
showToast(`Topic ${topicId} ignored.`, function() {
window.location.reload();
});
}
},
onerror: function(error) {
debugLog(`Error ignoring topic ${topicId}: ${error}`);
}
});
}).catch(error => {
debugLog(`Error fetching once value: ${error}`);
});
}
}
}
// Function to extract the topic ID from a topic URL
function getTopicIdFromUrl(topicUrl) {
const match = topicUrl.match(/\/t\/(\d+)/);
if (match) {
return match[1];
}
return null;
}
// Function to fetch the current once value from the V2EX server
function getOnceValue() {
return new Promise((resolve, reject) => {
const tops = document.querySelectorAll('a.top');
const top = Array.from(tops).find(a => a.getAttribute('onclick')?.includes('once='));
if (top) {
const onclick = top.getAttribute('onclick');
const match = onclick.match(/\?once=(\d+)/);
if (match) {
const onceValue = match[1].replace(/\D/g, '');
debugLog(`Current once value is ${onceValue}`);
resolve(onceValue);
return;
}
}
const error = new Error('Not logged in.');
error.isAuthenticationError = true;
reject(error);
});
}
// Function to display a toast message
function showToast(message, callback) {
const toast = document.createElement('div');
toast.textContent = message;
toast.style.position = 'fixed';
toast.style.bottom = '20px';
toast.style.right = '20px';
toast.style.padding = '10px';
toast.style.backgroundColor = '#333';
toast.style.color = '#fff';
toast.style.borderRadius = '5px';
document.body.appendChild(toast);
setTimeout(() => {
toast.remove();
if (callback) {
callback();
}
}, 300);
}
// Find all post titles on the page and add an "Ignore" button next to each one
const postTitles = document.querySelectorAll('.cell.item .item_title');
postTitles.forEach(postTitle => {
const ignoreButton = document.createElement('a');
ignoreButton.textContent = 'Ignore';
ignoreButton.href = '#';
ignoreButton.classList.add('tag');
ignoreButton.addEventListener('click', ignoreTopic);
postTitle.parentNode.insertBefore(ignoreButton, postTitle.nextSibling);
});
})();