Bitcoin Forum
September 17, 2026, 04:58:57 PM *
News: Latest Bitcoin Core release: 31.1 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: [Userscript] A Tool to Save Posts, Organize and Revisit Forum Posts  (Read 325 times)
MisFoxie (OP)
Full Member
***
Offline

Activity: 308
Merit: 130



View Profile
June 28, 2026, 07:08:05 AM
Last edit: July 03, 2026, 03:48:08 AM by MisFoxie
Merited by Mia Chloe (3), joker_josue (1)
 #1

While visiting [Merit] Share your best posts/threads with Fillippone to be merit assessed this thread made by Fillippone I notice an interesting fact. As everyone know Fillippone help users by giving merit to quality posts but the interesting fact is Fillippone gives 1 merit extra in the submitted form which i think to keep track of his activity like mark it as reviewed or maybe I'm wrong. So I made a userscript to help track his activity in that thread without giving extra merits.

What this tool does?
This tool allow users to Save multiple post in a thread, the saved post got highlighted and the recent saved post in a thread can be open through Saved Posts button which located at the right bottom side. It also shows total smerit available to give.

Why people should trust this tool?
  
  • It runs locally in Tampermonkey.
  • Saved posts remain on the user’s own device.
  • It does not use any external server or analytics.
  • It does not collect passwords, cookies, private messages, or personal information.
  • Network access is restricted to Bitcointalk.org only, mainly for checking the logged-in user’s sMerit balance.
  • The entire source code is visible, so users can review it before installation.
  • Users can disable or uninstall it anytime from Tampermonkey.

Some photos for reference:

How to install on desktop

1. Install Tampermonkey extension in your browser.
2. Go to chrome://extensions/ click Details in Tampermonkey> scroll down and Allow User Scripts [on]
3. Go to Greasyfork and click [install this script] then install
6. Open or refresh Bitcointalk.

How to install on Android / phone

You need a browser that supports userscripts. For example:
  • Kiwi Browser + Tampermonkey
  • mises Browser + Tampermonkey
  • Any other Android browser that supports userscript extensions

Script code box
Code:
// ==UserScript==
// @name         Bitcointalk Saved Posts
// @namespace    https://bitcointalk.org/
// @version      1.1.0
// @description  Save Bitcointalk posts locally and automatically show your remaining sMerit.
// @author       Misfoxie
// @match        https://bitcointalk.org/*
// @match        http://bitcointalk.org/*
// @match        https://www.bitcointalk.org/*
// @match        http://www.bitcointalk.org/*
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_xmlhttpRequest
// @connect      bitcointalk.org
// @connect      www.bitcointalk.org
// @run-at       document-end
// ==/UserScript==

(function () {
    'use strict';

    const STORAGE_KEY = 'btt_saved_posts_v1';
    const POST_SELECTOR = '.subject[id^="subject_"]';
    const SMERIT_CACHE_KEY = 'btt_remaining_smerit_cache';
    const SMERIT_CACHE_TIME_KEY = 'btt_remaining_smerit_cache_time';
    const SMERIT_CACHE_DURATION = 5 * 60 * 1000;

    const css = `
        #bttsp-launcher { position:fixed; right:18px; bottom:18px; z-index:99998; border:0; border-radius:999px; background:#263b55; color:#fff; padding:11px 15px; box-shadow:0 4px 18px #0005; cursor:pointer; font:600 13px Arial,sans-serif; }
        #bttsp-launcher:hover { background:#345273; }
        #bttsp-panel { position:fixed; right:18px; bottom:68px; z-index:99999; width:min(390px,calc(100vw - 28px)); max-height:min(650px,calc(100vh - 90px)); display:none; flex-direction:column; overflow:hidden; border:1px solid #8da0b4; border-radius:10px; background:#f5f7fa; color:#1d2936; box-shadow:0 10px 36px #0007; font:13px Arial,sans-serif; text-align:left; }
        #bttsp-panel.bttsp-open { display:flex; }
        .bttsp-head { display:flex; align-items:center; justify-content:space-between; padding:13px 14px; background:#263b55; color:#fff; }
        .bttsp-head strong { font-size:15px; }
        .bttsp-close { border:0; background:transparent; color:#fff; font-size:22px; line-height:18px; cursor:pointer; }
        #bttsp-list { overflow:auto; padding:8px; }
        .bttsp-empty { padding:28px 15px; color:#627181; text-align:center; line-height:1.5; }
        .bttsp-thread { margin-bottom:8px; overflow:hidden; border:1px solid #c8d1db; border-radius:7px; background:#fff; }
        .bttsp-thread summary { position:relative; display:grid; grid-template-columns:minmax(0,1fr) auto; gap:8px; align-items:center; padding:10px 11px; cursor:pointer; list-style:none; }
        .bttsp-thread summary::-webkit-details-marker { display:none; }
        .bttsp-summary-text { min-width:0; }
        .bttsp-title { display:block; overflow:hidden; color:#203f64; font-weight:700; text-overflow:ellipsis; white-space:nowrap; }
        .bttsp-preview { display:block; margin-top:5px; overflow:hidden; color:#596978; font-size:12px; text-overflow:ellipsis; white-space:nowrap; }
        .bttsp-meta { display:block; margin-top:5px; color:#8995a1; font-size:11px; }
        .bttsp-open-latest { display:inline-block; align-self:center; border:1px solid #315a83; border-radius:5px; background:#345f89; color:#fff !important; padding:7px 10px; font-weight:700; text-decoration:none !important; white-space:nowrap; }
        .bttsp-open-latest:hover { background:#264b70; }
        .bttsp-posts { border-top:1px solid #dce2e8; }
        .bttsp-item { display:grid; grid-template-columns:1fr auto; gap:8px; padding:9px 11px; border-bottom:1px solid #edf0f3; }
        .bttsp-item:last-child { border-bottom:0; }
        .bttsp-link { min-width:0; color:#294f79; text-decoration:none; }
        .bttsp-link:hover { text-decoration:underline; }
        .bttsp-link span { display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
        .bttsp-link small { display:block; margin-top:3px; color:#7a8793; }
        .bttsp-delete { align-self:center; border:0; border-radius:4px; background:#eceff2; color:#8b3030; padding:4px 7px; cursor:pointer; }
        .bttsp-save { position:relative !important; top:2px !important; margin-left:7px !important; border:1px solid #526b85 !important; border-radius:4px !important; background:#edf2f6 !important; color:#27435f !important; padding:3px 7px !important; cursor:pointer !important; font:bold 11px Arial,sans-serif !important; vertical-align:middle !important; }
        .bttsp-save:hover { background:#dce7ef !important; }
        .bttsp-save.bttsp-is-saved { border-color:#a56d08 !important; background:#ffe7a8 !important; color:#634200 !important; }
        .bttsp-smerit { display:inline-block; margin-left:7px; border:1px solid #9abe92; border-radius:11px; background:#dcebd8; color:#17601d; padding:3px 9px; font:bold 12px Arial,sans-serif; line-height:1.25; vertical-align:middle; white-space:nowrap; }
        .bttsp-smerit.bttsp-smerit-error { background:#eee; color:#777; }
        .bttsp-saved-row { box-shadow:inset 5px 0 #e0a11d !important; }
        .bttsp-saved-cell { background-image:linear-gradient(90deg,rgba(255,224,132,.30),rgba(255,255,255,0) 55%) !important; }
        .bttsp-saved-cell, .bttsp-saved-cell * { color:#71869a !important; }
        .bttsp-saved-cell a, .bttsp-saved-cell a * { color:#4f789f !important; }
        .bttsp-saved-row .bttsp-poster-text { color:#71869a !important; }
        .bttsp-saved-row .poster_info a .bttsp-poster-text { color:#4f789f !important; }
        .bttsp-saved-cell .bttsp-save { border-color:#a56d08 !important; background:#ffe7a8 !important; color:#634200 !important; opacity:1 !important; }
        .bttsp-saved-cell .bttsp-smerit { border-color:#9abe92 !important; background:#dcebd8 !important; color:#17601d !important; opacity:1 !important; }
        .bttsp-saved-cell .bttsp-saved-label { background:#e0a11d !important; color:#302000 !important; }
        .bttsp-saved-label { display:inline-block; margin-left:7px; border-radius:10px; background:#e0a11d; color:#302000; padding:2px 7px; font:bold 10px Arial,sans-serif; vertical-align:middle; }
        #bttsp-toast { position:fixed; left:50%; bottom:24px; z-index:100000; transform:translateX(-50%); border-radius:6px; background:#182536; color:#fff; padding:9px 14px; box-shadow:0 3px 12px #0006; font:13px Arial,sans-serif; opacity:0; pointer-events:none; transition:opacity .2s; }
        #bttsp-toast.bttsp-show { opacity:1; }
        @media (max-width:600px) { #bttsp-launcher { right:10px; bottom:10px; } #bttsp-panel { right:7px; bottom:58px; } }
    `;

    let saved = loadSaved();
    let toastTimer;

    function loadSaved() {
        const value = GM_getValue(STORAGE_KEY, []);
        if (!Array.isArray(value)) return [];
        return value.filter(item => item && item.postId && item.topicId && item.url);
    }

    function persist() {
        GM_setValue(STORAGE_KEY, saved);
    }

    function getCachedSmerit() {
        const value = localStorage.getItem(SMERIT_CACHE_KEY);
        const time = Number(localStorage.getItem(SMERIT_CACHE_TIME_KEY));
        if (value === null || !time || Date.now() - time > SMERIT_CACHE_DURATION) return null;
        return value;
    }

    function cacheSmerit(value) {
        localStorage.setItem(SMERIT_CACHE_KEY, String(value));
        localStorage.setItem(SMERIT_CACHE_TIME_KEY, String(Date.now()));
    }

    function findMeritLinks() {
        return [...document.querySelectorAll('a[href*="action=merit"]')];
    }

    function extractSmerit(html) {
        const doc = new DOMParser().parseFromString(html, 'text/html');
        const text = (doc.body ? doc.body.textContent : html).replace(/\s+/g, ' ').trim();
        const patterns = [
            /You have\s+(\d+)\s+sendable merits?/i,
            /You have\s+(\d+)\s+sMerits?/i,
            /You have\s+(\d+)\s+available merits?/i,
            /You can send\s+(\d+)\s+merits?/i,
            /sendable merits?\s*[:\-]?\s*(\d+)/i,
            /sMerits?\s*[:\-]?\s*(\d+)/i
        ];
        for (const pattern of patterns) {
            const match = text.match(pattern);
            if (match) return match[1];
        }
        return null;
    }

    function showSmerit(value, failed = false) {
        findMeritLinks().forEach(link => {
            let badge = link.parentElement && link.parentElement.querySelector(`.bttsp-smerit[data-for="${link.href}"]`);
            if (!badge) {
                badge = el('span', 'bttsp-smerit');
                badge.dataset.for = link.href;
                link.insertAdjacentElement('afterend', badge);
            }
            badge.textContent = `sMerit: ${value}`;
            badge.classList.toggle('bttsp-smerit-error', failed);
            badge.title = failed ? 'Could not read the current sMerit balance' : 'Remaining sendable merit (cached for five minutes)';
        });
    }

    function initSmerit() {
        const meritLinks = findMeritLinks();
        if (!meritLinks.length) return;

        const cached = getCachedSmerit();
        if (cached !== null) {
            showSmerit(cached);
            return;
        }

        GM_xmlhttpRequest({
            method: 'GET',
            url: meritLinks[0].href,
            headers: { Accept: 'text/html' },
            onload(response) {
                const value = extractSmerit(response.responseText || '');
                if (value !== null) {
                    cacheSmerit(value);
                    showSmerit(value);
                } else {
                    showSmerit('?', true);
                    console.warn('[Bitcointalk Saved Posts] Could not detect remaining sMerit.');
                }
            },
            onerror() {
                showSmerit('?', true);
                console.warn('[Bitcointalk Saved Posts] Failed to load the Merit page.');
            }
        });
    }

    function normalizeText(value, maxLength) {
        const text = String(value || '').replace(/\s+/g, ' ').trim();
        return text.length > maxLength ? `${text.slice(0, maxLength - 1).trimEnd()}\u2026` : text;
    }

    function parseTopicId(url) {
        const match = String(url).match(/[?;&]topic=(\d+)/i);
        return match ? match[1] : '';
    }

    function getPostData(subject) {
        const postId = subject.id.replace('subject_', '');
        const contentCell = subject.closest('.td_headerandpost') || subject.closest('td');
        const postTable = contentCell && contentCell.closest('table');
        const permalink = (contentCell && contentCell.querySelector(`a[href*="#msg${postId}"]`)) || subject.querySelector('a');
        const postBody = contentCell && contentCell.querySelector('.post');
        const authorLink = postTable && postTable.querySelector('.poster_info a[href*="action=profile"]');
        const numberLink = contentCell && contentCell.querySelector('.message_number');
        const topicId = parseTopicId(permalink ? permalink.href : location.href);
        if (!postId || !topicId || !permalink) return null;

        return {
            postId,
            topicId,
            threadTitle: normalizeText((subject.querySelector('a') || subject).textContent.replace(/^Re:\s*/i, ''), 180) || `Topic ${topicId}`,
            postTitle: normalizeText((subject.querySelector('a') || subject).textContent, 180),
            author: normalizeText(authorLink && authorLink.textContent, 80) || 'Unknown member',
            postNumber: normalizeText(numberLink && numberLink.textContent, 20) || `#${postId}`,
            snippet: normalizeText(postBody && postBody.textContent, 240) || 'Saved Bitcointalk post',
            url: new URL(permalink.href, location.href).href,
            savedAt: Date.now()
        };
    }

    function findSaved(postId) {
        return saved.find(item => item.postId === String(postId));
    }

    function savePost(data) {
        if (findSaved(data.postId)) {
            saved = saved.filter(item => item.postId !== data.postId);
            showToast('Post removed from saved posts');
        } else {
            saved.push(data);
            showToast('Post saved on this device');
        }
        persist();
        decoratePosts();
        renderPanel();
    }

    function preparePosterText(postTable) {
        const poster = postTable && postTable.querySelector('.poster_info');
        if (!poster || poster.dataset.bttspTextPrepared) return;
        poster.dataset.bttspTextPrepared = '1';

        const walker = document.createTreeWalker(poster, NodeFilter.SHOW_TEXT);
        const textNodes = [];
        while (walker.nextNode()) {
            if (walker.currentNode.nodeValue.trim()) textNodes.push(walker.currentNode);
        }
        textNodes.forEach(textNode => {
            const wrapper = el('span', 'bttsp-poster-text');
            textNode.parentNode.insertBefore(wrapper, textNode);
            wrapper.appendChild(textNode);
        });
    }

    function removePost(postId) {
        saved = saved.filter(item => item.postId !== String(postId));
        persist();
        decoratePosts();
        renderPanel();
        showToast('Saved post removed');
    }

    function decoratePosts() {
        document.querySelectorAll(POST_SELECTOR).forEach(subject => {
            const data = getPostData(subject);
            if (!data) return;
            const contentCell = subject.closest('.td_headerandpost') || subject.closest('td');
            const postTable = contentCell && contentCell.closest('table');
            const buttonArea = contentCell && contentCell.querySelector('.td_buttons > div, .td_buttons');
            if (!buttonArea) return;
            preparePosterText(postTable);

            let button = buttonArea.querySelector(`.bttsp-save[data-post-id="${data.postId}"]`);
            if (!button) {
                button = document.createElement('button');
                button.type = 'button';
                button.className = 'bttsp-save';
                button.dataset.postId = data.postId;
                button.addEventListener('click', event => {
                    event.preventDefault();
                    event.stopPropagation();
                    savePost(getPostData(subject));
                });
                buttonArea.appendChild(button);
            }

            const isSaved = Boolean(findSaved(data.postId));
            button.textContent = isSaved ? '\u2605 Saved' : '\u2606 Save';
            button.title = isSaved ? 'Remove this saved post' : 'Save this post locally';
            button.classList.toggle('bttsp-is-saved', isSaved);
            if (postTable) postTable.classList.toggle('bttsp-saved-row', isSaved);
            if (contentCell) contentCell.classList.toggle('bttsp-saved-cell', isSaved);

            let label = subject.querySelector('.bttsp-saved-label');
            if (isSaved && !label) {
                label = document.createElement('span');
                label.className = 'bttsp-saved-label';
                label.textContent = 'SAVED';
                subject.appendChild(label);
            } else if (!isSaved && label) {
                label.remove();
            }
        });
    }

    function groupByThread() {
        const groups = new Map();
        saved.forEach(post => {
            if (!groups.has(post.topicId)) groups.set(post.topicId, []);
            groups.get(post.topicId).push(post);
        });
        return [...groups.values()]
            .map(posts => posts.sort((a, b) => b.savedAt - a.savedAt))
            .sort((a, b) => b[0].savedAt - a[0].savedAt);
    }

    function formatDate(timestamp) {
        try { return new Date(timestamp).toLocaleString([], { dateStyle: 'medium', timeStyle: 'short' }); }
        catch (_) { return new Date(timestamp).toLocaleString(); }
    }

    function el(tag, className, text) {
        const node = document.createElement(tag);
        if (className) node.className = className;
        if (text !== undefined) node.textContent = text;
        return node;
    }

    function renderPanel() {
        const list = document.getElementById('bttsp-list');
        if (!list) return;
        list.replaceChildren();

        const groups = groupByThread();
        if (!groups.length) {
            list.appendChild(el('div', 'bttsp-empty', 'No saved posts yet. Open a thread and use the \u2606 Save button beside a post.'));
            return;
        }

        groups.forEach(posts => {
            const latest = posts[0];
            const details = el('details', 'bttsp-thread');
            const summary = document.createElement('summary');
            const summaryText = el('span', 'bttsp-summary-text');
            summaryText.appendChild(el('span', 'bttsp-title', latest.threadTitle));
            summaryText.appendChild(el('span', 'bttsp-preview', latest.snippet));
            summaryText.appendChild(el('span', 'bttsp-meta', `${posts.length} saved post${posts.length === 1 ? '' : 's'} \u00b7 latest ${formatDate(latest.savedAt)}`));
            const openLatest = el('a', 'bttsp-open-latest', 'Open');
            openLatest.href = latest.url;
            openLatest.title = `Open the most recently saved post (${latest.postNumber})`;
            openLatest.addEventListener('click', event => event.stopPropagation());
            summary.append(summaryText, openLatest);
            details.appendChild(summary);

            const postList = el('div', 'bttsp-posts');
            posts.forEach(post => {
                const item = el('div', 'bttsp-item');
                const link = el('a', 'bttsp-link');
                link.href = post.url;
                link.title = post.snippet;
                link.appendChild(el('span', '', `${post.postNumber} \u2014 ${post.snippet}`));
                link.appendChild(el('small', '', `${post.author} \u00b7 ${formatDate(post.savedAt)}`));
                const remove = el('button', 'bttsp-delete', '\u2715');
                remove.type = 'button';
                remove.title = 'Remove saved post';
                remove.addEventListener('click', event => {
                    event.preventDefault();
                    event.stopPropagation();
                    removePost(post.postId);
                });
                item.append(link, remove);
                postList.appendChild(item);
            });
            details.appendChild(postList);
            list.appendChild(details);
        });
    }

    function showToast(message) {
        const toast = document.getElementById('bttsp-toast');
        if (!toast) return;
        toast.textContent = message;
        toast.classList.add('bttsp-show');
        clearTimeout(toastTimer);
        toastTimer = setTimeout(() => toast.classList.remove('bttsp-show'), 1800);
    }

    function buildUi() {
        const style = document.createElement('style');
        style.textContent = css;

        const launcher = el('button', '', 'Saved posts');
        launcher.id = 'bttsp-launcher';
        launcher.type = 'button';

        const panel = el('aside');
        panel.id = 'bttsp-panel';
        panel.setAttribute('aria-label', 'Saved Bitcointalk posts');
        const head = el('div', 'bttsp-head');
        head.appendChild(el('strong', '', 'Saved threads'));
        const close = el('button', 'bttsp-close', '\u00d7');
        close.type = 'button';
        close.title = 'Close';
        head.appendChild(close);
        const list = el('div');
        list.id = 'bttsp-list';
        panel.append(head, list);

        const toast = el('div');
        toast.id = 'bttsp-toast';
        document.head.appendChild(style);
        document.body.append(launcher, panel, toast);

        launcher.addEventListener('click', () => panel.classList.toggle('bttsp-open'));
        close.addEventListener('click', () => panel.classList.remove('bttsp-open'));
        document.addEventListener('keydown', event => {
            if (event.key === 'Escape') panel.classList.remove('bttsp-open');
        });
    }

    buildUi();
    decoratePosts();
    renderPanel();
    initSmerit();
})();

Well, this tool can also be helpful for those who want to track thread and quickly access them. Just two click and it will lead you to your favorite thread.

dkbit98
Legendary
*
Offline

Activity: 3080
Merit: 8860



View Profile WWW
June 29, 2026, 02:46:18 PM
 #2

This can be useful tool but for saving posts I want to read later, but I don't think you should mix it with sMerits thing.
I also don't like position of Saved posts button, on the right bottom side, and I think it would work better on top of the page or added in forum menu.

▄▄██████▄░░░▄██████▄▄
██▀▀░░░░░░░░░░░░░▀▀██
▄▄██████▄▄██████▄▄
▄████▀▀▀▀█████▀▀▀▀████▄
▄███░░░▄▄░░░░░░▄▄░░░███▄
▄▄▄███░░░░██░░░░░░░██░░░░███▄▄▄
████████░░░░██░░░░░░░██░░░░████████
██████████░░░▀▀░░░░░░▀▀░░░██████████
████▀▀██████▄▄▄▄█████▄▄▄▄██████▀▀████
▀███▄░░▀▀███████████████████▀▀░░▄███▀
▀████▄▄░░░░▀▀▀▀▀▀▀▀▀▀▀▀▀░░░░▄▄████▀
▀███████▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄███████▀
▀▀█████████████████████▀▀
  
OrangeFren
  
██
██
██
██
██
██
██
██
██
██
██
  
▄▄█████▄▄
▄████▀▀▀████▄
███▀░░░░░░░▀███
███▀░░░▄█░░░░▀███
███░░░░░░░░░░███
███▄░░░▄█▄░░░▄███
███▄░░░░░░░▄███
▀████▄▄▄████▀
█████████
▐█████████▌
██████████
▐████▌▐████▌
▀▀▀█░░░█▀▀▀
 
Mia Chloe
Legendary
*
Offline

Activity: 1204
Merit: 2292


Contact me for your designs...


View Profile
July 02, 2026, 03:17:05 PM
 #3

~snip
First up thumbs up for the effort you actually put into making this tool. For someone like me who likes to surf alot before eventually posting it could definitely come in handy for me to save a couple of posts for later when i can read more interesting ones and also distribute some merits too.

You should consider adding a couple of previews to the thread to make things a little easier. Nevertheless i haven't tried the tool yet so i probably would come back with a couple of suggestions as updates later on if necessary.

MisFoxie (OP)
Full Member
***
Offline

Activity: 308
Merit: 130



View Profile
July 02, 2026, 04:04:36 PM
Merited by fillippone (3)
 #4

even if I haven’t used that userscript.
The problem is not exactly knowing which post to merit, but having the right amount of merits to spread between those!
This can be useful tool but for saving posts I want to read later, but I don't think you should mix it with sMerits thing.
it could definitely come in handy for me to save a couple of posts for later when i can read more interesting ones and also distribute some merits too.
Thanks you all for your reply,,

Now that I think about it, I believe most people have misunderstood the actual purpose of this tool. It isn't designed to help users find and save good posts to merit later. Instead, it simply lets you save posts within a thread so they can be marked as "read." That way, you can easily skip those posts the next time you visit the same thread and focus only on the new ones. Maybe the smerit thing confused everyone.
As everyone know Fillippone help users by giving merit to quality posts but the interesting fact is Fillippone gives 1 merit extra in the submitted form which i think to keep track of his activity like mark it as reviewed or maybe I'm wrong. So I made a userscript to help track his activity in that thread without giving extra merits.




First up thumbs up for the effort you actually put into making this tool. For someone like me who likes to surf alot before eventually posting it could definitely come in handy for me to save a couple of posts for later when i can read more interesting ones and also distribute some merits too.

You should consider adding a couple of previews to the thread to make things a little easier. Nevertheless i haven't tried the tool yet so i probably would come back with a couple of suggestions as updates later on if necessary.
I'm eagerly waiting for your review. I will gladly make any modifications you need in this tool based on your feedback, especially to suit your preference.

GhostOfBitcoin
Member
**
Offline

Activity: 97
Merit: 49

Need A Campaign Manager? Contact TG: @GOB_CEO


View Profile WWW
July 02, 2026, 05:04:00 PM
 #5

@MisFoxie Thank you for sharing the script. After reviewing the entire code, I found it to be quite clear and practical. I particularly liked the features that allow saved posts to be displayed separately, group posts from the same thread together, and show sMerit. The UI is also user-friendly for the average user.

I feel the script could be improved by addressing a few points.

One issue is that the entire list is currently being regenerated every time a 'Save' or 'Remove' action occurs. If there are many saved posts, this could lead to unnecessary processing. Updating only the specific post that has changed would achieve the same result.

Another point to consider is the sMerit cache. If the 5-minute cache is active after Merit has been sent, the displayed figure might temporarily reflect the old balance. Refreshing or clearing the cache after sending Merit ensures the information remains accurate.

un_rank
Legendary
*
Offline

Activity: 1582
Merit: 1115



View Profile WWW
July 02, 2026, 07:44:55 PM
Last edit: July 09, 2026, 08:56:16 PM by un_rank
 #6

...the interesting fact is Fillippone gives 1 merit extra in the submitted form which i think to keep track of his activity like mark it as reviewed or maybe I'm wrong. So I made a userscript to help track his activity in that thread without giving extra merits.
If that's indeed the case, the users getting the extra merits will not be excited you created a script tht deprives them of that  Wink

This is not a bad script but I think it needs more use cases to encourage people to try it out. It could serve as a page bookmark to remind people where they stopped reading in a thread. I'm a part of a couple of pools and discussions there are easy to lose track of, soneunf like this can help with that.

- Jay -


 BetBolt.com  
███████████████████████
███████████████████████
███████████████████████
██████████████████████
█████████████████████
██████████████████████
██████████████████████
███████████████████
██████████████████████
███████████████████████
███████████████████████
███████████████████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
🗲
███    ███████████████████████████████████████

CRYPTO'S MOST REWARDING CASINO

███████████████████████████████████████    ███
██████▄██████▄▄
███▄██████████████▄▄
▄███████████████████
█████████████████████
▀███████
████████████████▄
█████████████████████████
███▀███████████████████▀
█████████████████████▀▀
██████▀███████████▀▀
███████████████▀▀
█████████▀█▀▀
    PLAY NOW   



███▄▄▄▄███
████████████
███████████▀
████████▄
█████████▄
█████▀█████▄
▀██████▀█████
██████████▀██▀
fillippone
Legendary
*
Online Online

Activity: 3024
Merit: 21486


Duelbits.com - Rewarding, beyond limits.


View Profile WWW
July 03, 2026, 05:44:09 AM
Merited by Charcol (1), MisFoxie (1)
 #7

even if I haven’t used that userscript.
The problem is not exactly knowing which post to merit, but having the right amount of merits to spread between those!
This can be useful tool but for saving posts I want to read later, but I don't think you should mix it with sMerits thing.
it could definitely come in handy for me to save a couple of posts for later when i can read more interesting ones and also distribute some merits too.
Thanks you all for your reply,,

Now that I think about it, I believe most people have misunderstood the actual purpose of this tool. It isn't designed to help users find and save good posts to merit later. Instead, it simply lets you save posts within a thread so they can be marked as "read." That way, you can easily skip those posts the next time you visit the same thread and focus only on the new ones. Maybe the smerit thing confused everyone.


As you know I have a userscript slightly modifying the forum skin.
You gave me an idea.
I could implement a light shade on the forum up to the last loaded post. Say I read a thread and last loaded post is 100. When I come back to it, every post up to 100 are shaded, so that I know that was the last post present last time I visited it!
This could be a nice way of doing things.


Charcol
Sr. Member
****
Online Online

Activity: 350
Merit: 253



View Profile
July 03, 2026, 06:20:04 AM
 #8

I could implement a light shade on the forum up to the last loaded post. Say I read a thread and last loaded post is 100. When I come back to it, every post up to 100 are shaded, so that I know that was the last post present last time I visited it!
This could be a nice way of doing things.
Great...
I really like your idea, at least I think it's better than the "save post" idea. And I mostly discuss in mega threads where there are 3-4 posts every hour or sometimes more. It bothers me to remember where I was reading in those threads. If you can implement the idea you shared, it would be great for many. However, it would probably be better to make the shadow of the read part lighter. So that it is not difficult to read old posts at some point. Although I have the utmost confidence in the projects you have created. I hope this will be as good as the last time.

R


▀▀▀▀▀▀▀██████▄▄
████████████████
▀▀▀▀█████▀▀▀█████
████████▌███▐████
▄▄▄▄█████▄▄▄█████
████████████████
▄▄▄▄▄▄▄██████▀▀
LLBIT|
4,000+ GAMES
███████████████████
██████████▀▄▀▀▀████
████████▀▄▀██░░░███
██████▀▄███▄▀█▄▄▄██
███▀▀▀▀▀▀█▀▀▀▀▀▀███
██░░░░░░░░█░░░░░░██
██▄░░░░░░░█░░░░░▄██
███▄░░░░▄█▄▄▄▄▄████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
█████████
▀████████
░░▀██████
░░░░▀████
░░░░░░███
▄░░░░░███
▀█▄▄▄████
░░▀▀█████
▀▀▀▀▀▀▀▀▀
█████████
░░░▀▀████
██▄▄▀░███
█░░█▄░░██
░████▀▀██
█░░█▀░░██
██▀▀▄░███
░░░▄▄████
▀▀▀▀▀▀▀▀▀
|||
▄▄████▄▄
▀█▀
▄▀▀▄▀█▀
▄░░▄█░██░█▄░░▄
█░▄█░▀█▄▄█▀░█▄░█
▀▄░███▄▄▄▄███░▄▀
▀▀█░░░▄▄▄▄░░░█▀▀
░░██████░░█
█░░░░▀▀░░░░█
▀▄▀▄▀▄▀▄▀▄
▄░█████▀▀█████░▄
▄███████░██░███████▄
▀▀██████▄▄██████▀▀
▀▀████████▀▀
.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
░▀▄░▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄░▄▀
███▀▄▀█████████████████▀▄▀
█████▀▄░▄▄▄▄▄███░▄▄▄▄▄▄▀
███████▀▄▀██████░█▄▄▄▄▄▄▄▄
█████████▀▄▄░███▄▄▄▄▄▄░▄▀
███████████░███████▀▄▀
███████████░██▀▄▄▄▄▀
███████████░▀▄▀
████████████▄▀
███████████
▄▄███████▄▄
▄████▀▀▀▀▀▀▀████▄
▄███▀▄▄███████▄▄▀███▄
▄██▀▄█▀▀▀█████▀▀▀█▄▀██▄
▄██▀▄███░░░▀████░███▄▀██▄
███░████░░░░░▀██░████░███
███░████░█▄░░░░▀░████░███
███░████░███▄░░░░████░███
▀██▄▀███░█████▄░░███▀▄██▀
▀██▄▀█▄▄▄██████▄██▀▄██▀
▀███▄▀▀███████▀▀▄███▀
▀████▄▄▄▄▄▄▄████▀
▀▀███████▀▀
OFFICIAL PARTNERSHIP
SOUTHAMPTON FC
FAZE CLAN
SSC NAPOLI
MisFoxie (OP)
Full Member
***
Offline

Activity: 308
Merit: 130



View Profile
July 03, 2026, 07:01:18 AM
 #9

As you know I have a userscript slightly modifying the forum skin.
You gave me an idea.
I could implement a light shade on the forum up to the last loaded post. Say I read a thread and last loaded post is 100. When I come back to it, every post up to 100 are shaded, so that I know that was the last post present last time I visited it!
This could be a nice way of doing things.
You can definitely do that and looking at your userscript I think you can design it better than me. So let me give you another idea it may become only helpful to you:- when you save or lock a post in a thread the userscript will shows list of posts made after that saved post by that user if they made any.. I noticed many user post form even though their old form isn't reviewed.


fillippone
Legendary
*
Online Online

Activity: 3024
Merit: 21486


Duelbits.com - Rewarding, beyond limits.


View Profile WWW
July 04, 2026, 09:25:00 AM
 #10

Hello,
I implemented something inspired by you in my userscript: i hope you find it interesting:

[Userscript] Bitcointalk Modern Theme - Yet another Bitcointalk Skin

Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!