Nostr - SSTP over HTTP で喋らせるボタンを生やすやつ

  • /*
     * @title Nostr - SSTP over HTTP で喋らせるボタンを生やすやつ
     * @description nostter に SSTP over HTTP で喋らせるボタンを生やす
     * @include https://nostter.app/*
     * @require 
     */
    
    (function() {
        'use strict';
    
        const tag = (name, props = {}, children = []) => {
            const e = Object.assign(document.createElement(name), props);
            if (typeof props.style === "object") Object.assign(e.style, props.style);
            (children.forEach ? children : [children]).forEach(c => e.appendChild(c));
            return e;
        };
    
        const postData = async (url = '', data = '') => {
            const param = {
                method: 'POST',
                headers: {
                    'Content-Type': 'text/plain',
                    'Origin': sspServerURL,
                },
                body: data,
            };
            try {
                const response = await fetch(url, param);
                return response.text();
            } catch (error) {
                return '';
            }
        };
        const sspServerURL = 'http://localhost:9801';
        const sendSSTP = async (script, type, content, name, display_name, picture) => {
            const protocol_version = 'Nostr/0.3';
            const mes = [
                'NOTIFY SSTP/1.1',
                'Charset: UTF-8',
                'SecurityLevel: external',
                'Sender: ぶらうざのゆーざーすくりぷと',
                'Event: OnNostr',
                `Reference0: ${protocol_version}`,
                `Reference1: ${type}`,
                `Reference2: ${content}`,
                `Reference3: ${name}`,
                `Reference4: ${display_name}`,
                `Reference5: ${picture}`,
                'Option: notranslate,nobreak',
                `Script: ${script}`,
                '',
                '',
            ].join('\n');
            const res = await postData(sspServerURL + '/api/sstp/v1', mes);
        };
    
        const onClick = async e => {
            let root;
            let avatar_url;
            let name;
            let display_name;
            let acct;
            let body;
            switch (document.domain) {
                //nostter
                case 'nostter.app':
                    root = e.target.closest('main div > article');
                    avatar_url = root.querySelector('div > a > img.picture').src;
                    name = root.querySelector('.name').textContent.trim().replace('@', '');
                    display_name = root.querySelector('.display_name').textContent.trim();
                    acct = root.querySelector('.name').textContent.trim();
                    body = root.querySelector('.content').textContent.trim().replace(/\n/g, "\\n");
                    break;
                default:
                    break;
            }
    
            let script = "";
            script += `\\![set,balloonwait,0]\\0\\_l[@4,]${display_name}\\n\\_l[@36,]${acct}\\_l[0,36]`;
            script += `\\![set,balloonwait]${body}`;
            script += "\\e";
    
            sendSSTP(script, 'note', body, name, display_name, avatar_url);
            
        };
    
        new MutationObserver(() => {
            let q;
            switch (document.domain) {
                //nostter
                case 'nostter.app':
                    q = '.action-menu:not(.__ukabutton)';
                    break;
                default:
                    break;
            }
            let timeoutID;
            for (const el of document.querySelectorAll(q)) {
                el.classList.add('__ukabutton');
                const e = tag('button', {
                    className: 'icon-button',
                    style: "width: 18px; height: 18px; background: no-repeat center/18px url(https://ukadon.shillest.net/favicon.ico); opacity: 0.5;",
                    onclick: onClick
                });
                el.append(e);
                if (timeoutID) {
                    clearTimeout(timeoutID);
                }
                timeoutID = setTimeout(() => { e.dispatchEvent(new PointerEvent('click')); }, 100);
            }
        }).observe(document.body, {childList: 1, subtree:1});
    })();
    
  • Permalink
    このページへの個別リンクです。
    RAW
    書かれたコードへの直接のリンクです。
    Packed
    文字列が圧縮された書かれたコードへのリンクです。
    Userscript
    Greasemonkey 等で利用する場合の .user.js へのリンクです。
    Loader
    @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
    Metadata
    コード中にコメントで @xxx と書かれたメタデータの JSON です。

History

  1. 2024/06/08 21:50:09 - 06/08