SemenChecker

Checks posts on unique ips.

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

You will need to install an extension such as Tampermonkey to install this script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

// ==UserScript==
// @name         SemenChecker
// @namespace    http://tampermonkey.net/
// @version      1.3.1
// @description  Checks posts on unique ips.
// @author       You
// @match        https://2ch.hk/*/*/*.html
// @icon         https://www.google.com/s2/favicons?sz=64&domain=2ch.hk
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_listValues
// @grant        GM_deleteValue
// @license MIT
// ==/UserScript==

const MAX_ALLOWED_STORE_TIME_IN_DAYS = 2; // Через сколько дней (с последнего посещения определенного треда на момент активации скрипта) удалится информация о треде.
const HIGHLIGHT_COLOR = 'lightgreen'; // Цвет подсветки нового поста.

const url = document.baseURI.replace('.html', '.json');
const current_thread = document.baseURI.split('#')[0].split('/').slice(3).join('/');

let last_modified;
let initial_poster_count

let unhighlighted_ids = [];
let highlighted_ids = [];

(async () => {
    const initial_response = await fetch(url);
    const initial_json = await initial_response.json();
    last_modified = initial_response.headers.get('Last-Modified');
    initial_poster_count = +initial_json.unique_posters;
    main();
})();


async function parse_json(url) {
    const response = await fetch(url, {
        headers: {
            'If-Modified-Since': last_modified
        }
    });
    if (!response.ok) {
        return false;
    }
    last_modified = response.headers.get('Last-Modified')
    return await response.json();
}

function get_json(url) {
    parse_json(url).then(json => {
        if (!json) {return;}
        const last_post = +json.posts_count;
        unique_checker(
            {
                related_poster_count: +json.unique_posters,
                last_post_id: +json.threads[0].posts[last_post].num
            }
        );
    });
}

function get_int_daytime() {
    return new Date().getTime() / 1000 / 3600 / 24;
}

function unique_checker(poster) {
    if (poster.related_poster_count > initial_poster_count) {
        initial_poster_count = poster.related_poster_count;
        const last_element_id = 'post-' + poster.last_post_id;
        unhighlighted_ids.push(last_element_id);
    }
    //console.log('initial poster count = ' + initial_poster_count);
    //console.log('unhighlighted ids = ' + unhighlighted_ids.length);
    //console.log('GM:');
    //console.log(GM_getValue(current_thread));
}

function inner_highlighter() {
    const uids = [...unhighlighted_ids];
    if (!uids.length) {return;}
    for (let i = 0; i < uids.length; i++) {
        const unhighlighted_post = document.getElementById(unhighlighted_ids[0]);
        if (unhighlighted_post) {
            highlighted_ids.push(unhighlighted_ids.shift());
            highlight_element(unhighlighted_post);
        }
    }
    GM_setValue(current_thread, {
        ids: highlighted_ids,
        date: get_int_daytime()
    });
}

function outer_highlighter(mutationsList) {
    for (let mutation of mutationsList) {
        [...mutation.target.children].slice(-1).forEach((post) => {
            if (highlighted_ids.includes(post.id.replace('-body', ''))) {
                highlight_element(post);
            }
        });
    }
}

function highlight_element(post) {
    let identification_element = document.createElement('span');
    identification_element.style.color = HIGHLIGHT_COLOR;
    identification_element.innerHTML = '[NEW IP]';
    identification_element.className = "new_ip";
    let insert_area = post.getElementsByClassName("post__details")[0];
    if (insert_area.getElementsByClassName(identification_element.className)[0] === undefined) {
        insert_area.appendChild(identification_element);
    }
}

function on_load() {
    const stored_data = GM_getValue(current_thread);
    if (!stored_data) {return;}
    stored_data.ids.forEach((item) => {
        let element = document.getElementById(item);
        if (element) {
            highlight_element(element);
            highlighted_ids.push(item);
        }
    });
    GM_setValue(current_thread, {
        ids: highlighted_ids,
        date: get_int_daytime()
    });
}

function main() {
    'use strict';

    on_load();
    //console.log(GM_listValues());
    GM_listValues().forEach((item) => {
        const stored_data = GM_getValue(item);
        //console.log(stored_data);
        if (Math.abs(get_int_daytime() - stored_data.date) >= MAX_ALLOWED_STORE_TIME_IN_DAYS) {
            GM_deleteValue(item);
        }
    });

    const inner_post_area = document.getElementsByClassName('thread')[0];
    const inner_observer = new MutationObserver(inner_highlighter);
    inner_observer.observe(inner_post_area, {childList: true});

    const outer_post_area = inner_post_area.parentElement;
    const outer_observer = new MutationObserver(outer_highlighter);
    outer_observer.observe(outer_post_area, {childList: true});

    setInterval(() => {get_json(url)}, 500);
    document.getElementsByClassName('de-thr-updater')[0].addEventListener("click", inner_highlighter)
}