NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Manual (You) // @description Add arbitary posts to reply tracking // @author Marker // @namespace https://gist.github.com/marktaiwan // @license MIT // @version 1.1 // @match https://boards.4chan.org/* // @match https://boards.4channel.org/* // @grant none // @noframes // @require https://openuserjs.org/src/libs/soufianesakhi/node-creation-observer.js // @icon https://s.4cdn.org/image/favicon-ws.ico // ==/UserScript== /* global Main, Parser, NodeCreationObserver */ (function () { 'use strict'; const $ = (selector, parent = document) => parent.querySelector(selector); const $$ = (selector, parent = document) => parent.querySelectorAll(selector); const ADD_STRING = ' [Start tracking]'; const REM_STRING = ' [<b>Tracked</b>]'; function processPost(postEle) { Parser.trackedReplies = Parser.getTrackedReplies(Main.board, Main.tid) ?? {}; const postId = $('.postInfo input[type="checkbox"]', postEle).name; const postNum = $('.postInfo .postNum', postEle); const isOwnPost = Object.keys(Parser.trackedReplies).some(key => key == '>>' + postId); const button = document.createElement('a'); button.style.cursor = 'pointer'; button.innerHTML = isOwnPost ? REM_STRING : ADD_STRING; button.dataset.ownPost = isOwnPost ? '1' : '0'; button.addEventListener('click', handleClick); postNum.after(button); } function handleClick(e) { const button = e.currentTarget; const postEle = button.closest('.postContainer'); const threadId = Main.tid; const postId = $('.postInfo input[type="checkbox"]', postEle).name; if (button.dataset.ownPost == '1') { delete Parser.trackedReplies['>>' + postId]; Parser.saveTrackedReplies(threadId, Parser.trackedReplies); button.innerHTML = ADD_STRING; button.dataset.ownPost = '0'; // Update replied posts by following the backlinks const backlinks = $$('.backlink .quotelink', postEle); for (const backlink of backlinks) { const replyId = backlink.innerText.slice(2); const replyEle = $('#pc' + replyId); const trackedLinks = $$('.postMessage a.ql-tracked', replyEle); for (const link of trackedLinks) { if (link.innerText.endsWith(postId + ' (You)')) { link.classList.remove('ql-tracked'); link.innerText = '>>' + postId; } } } } else { Parser.trackedReplies['>>' + postId] = '1'; Parser.saveTrackedReplies(threadId, Parser.trackedReplies); button.innerHTML = REM_STRING; button.dataset.ownPost = '1'; // Update replied posts by following the backlinks const backlinks = $$('.backlink .quotelink', postEle); for (const backlink of backlinks) { const replyId = backlink.innerText.slice(2); const replyEle = $('#pc' + replyId); parseTrackedReplies(replyEle); } } } function parseTrackedReplies(postEle) { for (const link of $$('.quotelink', postEle)) { if (!Parser.trackedReplies[link.textContent] || link.closest('.backlink')) continue; link.classList.add('ql-tracked'); link.textContent += ' (You)'; Parser.hasYouMarkers = true; } } if (Main.tid) NodeCreationObserver.onCreation('.postContainer', processPost); })();