Scan messages for donations and mark posts
当前为
// ==UserScript==
// @name Boosty Message Scanner
// @version 1.7
// @description Scan messages for donations and mark posts
// @match https://boosty.to/*
// @namespace http://tampermonkey.net/
// ==/UserScript==
(function() {
'use strict';
// Function to scan messages and save donation links
function scanMessages() {
const messageElements = document.querySelectorAll('[class*="DialogueMessageWrapper_message_"] [class*="DonationMessageInfo_root_"]');
let existingLinks = JSON.parse(localStorage.getItem('donationLinks')) || [];
const newLinks = [];
messageElements.forEach(element => {
const linkElement = element.querySelector('[class*="DonationMessageInfo_link_"]');
if (linkElement) {
const href = linkElement.href;
const postId = href.split('/').pop().split('?')[0]; // Ensure no query parameters are included
if (!existingLinks.includes(postId) && !newLinks.includes(postId)) {
newLinks.push(postId);
}
}
});
existingLinks = [...new Set([...existingLinks, ...newLinks])];
localStorage.setItem('donationLinks', JSON.stringify(existingLinks));
showAlert(newLinks, existingLinks);
}
// Function to add the scan button
function addScanButton() {
const container = document.querySelector('[class*="Publisher_actionsContainer_"] [class*="Publisher_actionsLeft_"]');
if (container && !document.querySelector('.scanMessagesButton')) {
const scanButton = document.createElement('button');
scanButton.innerText = 'Scan Messages';
scanButton.className = 'scanMessagesButton';
scanButton.style.marginLeft = '10px';
scanButton.onclick = scanMessages;
container.appendChild(scanButton);
}
}
// Function to mark posts with donations
function markPosts() {
const links = JSON.parse(localStorage.getItem('donationLinks')) || [];
// Mark posts in BasePostHeader_root_
const postsBase = document.querySelectorAll('[class*="BasePostHeader_root_"] [class*="CreatedAt_headerLink_"]');
postsBase.forEach(post => {
const href = post.href || post.getAttribute('href');
const postId = href ? href.split('/').pop().split('?')[0] : null; // Ensure no query parameters are included
if (postId && links.includes(postId)) {
const postHeader = post.closest('[class*="BasePostHeader_root_"]');
if (postHeader && !postHeader.querySelector('.markedPost')) {
const mark = document.createElement('span');
mark.innerText = '☻';
mark.className = 'markedPost';
postHeader.querySelector('[class*="BasePostHeader_headerLeftBlock_"]').appendChild(mark);
}
}
});
// Mark posts in PostHeaderWithAuthor_root_
const postsAuthor = document.querySelectorAll('[class*="PostHeaderWithAuthor_root_"] [class*="CreatedAt_headerLink_"]');
postsAuthor.forEach(post => {
const href = post.href || post.getAttribute('href');
const postId = href ? href.split('/').pop().split('?')[0] : null; // Ensure no query parameters are included
if (postId && links.includes(postId)) {
const postHeader = post.closest('[class*="PostHeaderWithAuthor_root_"]');
if (postHeader && !postHeader.querySelector('.markedPost')) {
const mark = document.createElement('span');
mark.innerText = '☻';
mark.className = 'markedPost';
postHeader.querySelector('[class*="PostHeaderWithAuthor_headerLeftBlock_"]').appendChild(mark);
}
}
});
}
// Function to show alert with buttons
function showAlert(newLinks, existingLinks) {
const alertDiv = document.createElement('div');
alertDiv.className = 'customAlert';
alertDiv.style.position = 'fixed';
alertDiv.style.top = '50%';
alertDiv.style.left = '50%';
alertDiv.style.transform = 'translate(-50%, -50%)';
alertDiv.style.backgroundColor = '#fff';
alertDiv.style.padding = '20px';
alertDiv.style.boxShadow = '0px 0px 10px rgba(0,0,0,0.5)';
alertDiv.style.zIndex = '10000';
const message = document.createElement('p');
message.innerText = `Found ${newLinks.length} new donation links. Total: ${existingLinks.length}`;
alertDiv.appendChild(message);
const newLinksButton = document.createElement('button');
newLinksButton.innerText = 'View New Links';
newLinksButton.onclick = () => {
showNewLinks(newLinks);
};
alertDiv.appendChild(newLinksButton);
const totalLinksButton = document.createElement('button');
totalLinksButton.innerText = 'Edit Total Links';
totalLinksButton.onclick = () => {
showTotalLinks(existingLinks);
};
alertDiv.appendChild(totalLinksButton);
const okButton = document.createElement('button');
okButton.innerText = 'OK';
okButton.onclick = () => {
document.body.removeChild(alertDiv);
};
alertDiv.appendChild(okButton);
document.body.appendChild(alertDiv);
}
// Function to show new links
function showNewLinks(newLinks) {
const newLinksDiv = document.createElement('div');
newLinksDiv.className = 'customNewLinks';
newLinksDiv.style.position = 'fixed';
newLinksDiv.style.top = '50%';
newLinksDiv.style.left = '50%';
newLinksDiv.style.transform = 'translate(-50%, -50%)';
newLinksDiv.style.backgroundColor = '#fff';
newLinksDiv.style.padding = '20px';
newLinksDiv.style.boxShadow = '0px 0px 10px rgba(0,0,0,0.5)';
newLinksDiv.style.zIndex = '10000';
newLinksDiv.style.maxHeight = '80%';
newLinksDiv.style.overflowY = 'auto';
const title = document.createElement('h3');
title.innerText = 'New Donation Links';
newLinksDiv.appendChild(title);
const list = document.createElement('ul');
newLinks.forEach(link => {
const listItem = document.createElement('li');
listItem.innerText = link;
list.appendChild(listItem);
});
newLinksDiv.appendChild(list);
const closeButton = document.createElement('button');
closeButton.innerText = 'Close';
closeButton.onclick = () => {
document.body.removeChild(newLinksDiv);
};
newLinksDiv.appendChild(closeButton);
document.body.appendChild(newLinksDiv);
}
// Function to show and edit total links
function showTotalLinks(existingLinks) {
const totalLinksDiv = document.createElement('div');
totalLinksDiv.className = 'customTotalLinks';
totalLinksDiv.style.position = 'fixed';
totalLinksDiv.style.top = '50%';
totalLinksDiv.style.left = '50%';
totalLinksDiv.style.transform = 'translate(-50%, -50%)';
totalLinksDiv.style.backgroundColor = '#fff';
totalLinksDiv.style.padding = '20px';
totalLinksDiv.style.boxShadow = '0px 0px 10px rgba(0,0,0,0.5)';
totalLinksDiv.style.zIndex = '10000';
totalLinksDiv.style.maxHeight = '80%';
totalLinksDiv.style.overflowY = 'auto';
const title = document.createElement('h3');
title.innerText = 'Edit Total Donation Links';
totalLinksDiv.appendChild(title);
const textArea = document.createElement('textarea');
textArea.value = JSON.stringify(existingLinks, null, 2);
textArea.style.width = '100%';
textArea.style.height = '200px';
totalLinksDiv.appendChild(textArea);
const saveButton = document.createElement('button');
saveButton.innerText = 'Save';
saveButton.onclick = () => {
try {
const newTotal = JSON.parse(textArea.value);
if (Array.isArray(newTotal)) {
localStorage.setItem('donationLinks', JSON.stringify(newTotal));
alert('Total Donation Links updated successfully.');
} else {
alert('Invalid format. Please enter a valid JSON array.');
}
} catch (e) {
alert('Invalid format. Please enter a valid JSON array.');
}
};
totalLinksDiv.appendChild(saveButton);
const closeButton = document.createElement('button');
closeButton.innerText = 'Close';
closeButton.onclick = () => {
document.body.removeChild(totalLinksDiv);
};
totalLinksDiv.appendChild(closeButton);
document.body.appendChild(totalLinksDiv);
}
// Initialize script
function init() {
if (location.pathname.includes('/app/messages')) {
addScanButton();
}
markPosts();
}
// Run script on page load and on AJAX content load
document.addEventListener('DOMContentLoaded', init);
const observer = new MutationObserver(init);
observer.observe(document.body, { childList: true, subtree: true });
})();