Vendetta Script

Скрипт с возможностью добавления и редактирования ответов прямо в браузере

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

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

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         Vendetta Script
// @namespace    https://forum.blackrussia.online/
// @version      3.0
// @description  Скрипт с возможностью добавления и редактирования ответов прямо в браузере
// @author       Arseny_Vendetta
// @match        https://forum.blackrussia.online/threads/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    const defaultButtons = [
        { title: 'Одобрено', content: '[CENTER]Ваше обращение одобрено.[/CENTER]', prefix: 9, status: false },
        { title: 'Отказано', content: '[CENTER]В обращении отказано.[/CENTER]', prefix: 4, status: false },
    ];

    let customButtons = JSON.parse(localStorage.getItem('my_custom_responses')) || defaultButtons;

    $(document).ready(() => {
        if (!window.Handlebars) {
            $('body').append('<script src="https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.js"></script>');
        }

        addControlButtons();
    });

    function addControlButtons() {
        $('.button--icon--reply').after(
            `<button type="button" class="button--cta button rippleButton" id="selectAnswer" style="margin-left: 5px; border-radius: 13px;">ОТВЕТЫ</button>`
        );

        $('#selectAnswer').click(() => {
            showMainModal();
        });
    }

    function showMainModal() {
        const buttonsHtml = customButtons.map((btn, i) => `
            <div style="display: flex; align-items: center; margin: 5px; width: 100%;">
                <button id="run-ans-${i}" class="button--primary button" style="flex-grow: 1; margin-right: 5px;">${btn.title}</button>
                <button id="edit-ans-${i}" class="button--primary button" style="background: #2196F3; min-width: 40px;">📝</button>
                <button id="del-ans-${i}" class="button--primary button" style="background: #f44336; min-width: 40px;">×</button>
            </div>
        `).join('');

        const fullHtml = `
            <div id="tech-modal-content" style="max-height: 400px; overflow-y: auto;">
                <button id="add-new-btn" class="button--primary button" style="width: 100%; background: #23b04a; margin-bottom: 15px;">➕ Добавить новый шаблон</button>
                ${buttonsHtml}
            </div>
        `;

        XF.alert(fullHtml, null, 'УПРАВЛЕНИЕ ШАБЛОНАМИ');

        customButtons.forEach((btn, i) => {
            $(`#run-ans-${i}`).click(() => pasteContent(i));
            $(`#edit-ans-${i}`).click(() => showEditModal(i));
            $(`#del-ans-${i}`).click(() => { if(confirm('Удалить?')) deleteAnswer(i); });
        });

        $('#add-new-btn').click(() => showEditModal(null));
    }

    function showEditModal(index) {
        const isNew = index === null;
        const btn = isNew ? { title: '', content: '' } : customButtons[index];

        const editHtml = `
            <div style="display: flex; flex-direction: column; gap: 10px;">
                <input type="text" id="edit-title" placeholder="Название кнопки" value="${btn.title}" style="padding: 8px; border-radius: 4px; border: 1px solid #ccc;">
                <textarea id="edit-content" placeholder="Текст ответа (BB-коды)" style="height: 150px; padding: 8px; border-radius: 4px; border: 1px solid #ccc;">${btn.content}</textarea>
                <button id="save-answer" class="button--primary button" style="background: #23b04a;">Сохранить</button>
            </div>
        `;

        XF.alert(editHtml, null, isNew ? 'НОВЫЙ ШАБЛОН' : 'РЕДАКТИРОВАНИЕ');

        $('#save-answer').click(() => {
            const newBtn = {
                title: $('#edit-title').val(),
                content: $('#edit-content').val(),
                prefix: btn.prefix || 0,
                status: btn.status || false
            };

            if (isNew) customButtons.push(newBtn);
            else customButtons[index] = newBtn;

            saveAndReload();
        });
    }

    function deleteAnswer(index) {
        customButtons.splice(index, 1);
        saveAndReload();
    }

    function saveAndReload() {
        localStorage.setItem('my_custom_responses', JSON.stringify(customButtons));
        location.reload();
    }

    function pasteContent(id) {
        const threadData = getThreadData();
        const template = Handlebars.compile(customButtons[id].content);
        
        $('span.fr-placeholder').empty();
        $('div.fr-element.fr-view p').html(template(threadData));
        $('a.overlay-titleCloser').trigger('click');
    }

    function getThreadData() {
        const authorID = $('a.username')[0].attributes['data-user-id'].nodeValue;
        const authorName = $('a.username').html();
        const hours = new Date().getHours();
        return {
            user: { id: authorID, name: authorName, mention: `[USER=${authorID}]${authorName}[/USER]` },
            greeting: () => 4 < hours && hours <= 11 ? 'Доброе утро' : 11 < hours && hours <= 15 ? 'Добрый день' : 15 < hours && hours <= 21 ? 'Добрый вечер' : 'Доброй ночи',
        };
    }
})();