Discord DM Sender with Input Box

Send DM messages via Discord API

目前为 2024-12-23 提交的版本。查看 最新版本

// ==UserScript==
// @name         Discord DM Sender with Input Box
// @namespace    http://tampermonkey.net/
// @version      1.5
// @description  Send DM messages via Discord API
// @author       Your Name
// @match        https://discord.com/*
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// @license      You can modify as long as you credit me
// ==/UserScript==

(function() {
    'use strict';

    let channelId = ''; // 初期チャンネルIDを削除

    const initialWidth = '280px';
    const initialHeight = '400px';

    const container = document.createElement('div');
    container.style.position = 'fixed';
    container.style.bottom = '10px';
    container.style.left = '10px';
    container.style.backgroundColor = '#2f3136';
    container.style.color = '#ffffff';
    container.style.padding = '10px';
    container.style.borderRadius = '5px';
    container.style.zIndex = '1000';
    container.style.width = initialWidth;
    container.style.height = initialHeight;
    document.body.appendChild(container);

    makeElementDraggable(container);

    const tokenBox = document.createElement('textarea');
    tokenBox.placeholder = 'Enter your token';
    tokenBox.style.width = '100%';
    tokenBox.style.height = '40px';
    tokenBox.style.resize = 'none';
    tokenBox.style.backgroundColor = '#000000';
    tokenBox.style.color = '#00FF00';
    container.appendChild(tokenBox);

    const inputBox = document.createElement('textarea');
    inputBox.placeholder = 'Enter your secret message to aarr';
    inputBox.style.width = '100%';
    inputBox.style.height = '100px';
    inputBox.style.resize = 'none';
    inputBox.style.backgroundColor = '#000000';
    inputBox.style.color = '#00FF00';
    container.appendChild(inputBox);

    const channelBox1 = document.createElement('textarea');
    channelBox1.placeholder = '荒らし雑談のBOTのDMチャンネルIDを入力';
    channelBox1.style.width = '100%';
    channelBox1.style.height = '40px';
    channelBox1.style.resize = 'none';
    channelBox1.style.backgroundColor = '#000000';
    channelBox1.style.color = '#00FF00';
    container.appendChild(channelBox1);

    const channelBox2 = document.createElement('textarea');
    channelBox2.placeholder = '情勢雑談のBOTのDMチャンネルIDを入力';
    channelBox2.style.width = '100%';
    channelBox2.style.height = '40px';
    channelBox2.style.resize = 'none';
    channelBox2.style.backgroundColor = '#000000';
    channelBox2.style.color = '#00FF00';
    container.appendChild(channelBox2);

    const channelBox3 = document.createElement('textarea');
    channelBox3.placeholder = '依頼支部のBOTのDMチャンネルIDを入力';
    channelBox3.style.width = '100%';
    channelBox3.style.height = '40px';
    channelBox3.style.resize = 'none';
    channelBox3.style.backgroundColor = '#000000';
    channelBox3.style.color = '#00FF00';
    container.appendChild(channelBox3);

    const button = document.createElement('button');
    button.innerText = 'Send DM';
    button.style.marginTop = '10px';
    button.style.width = '100%';
    button.style.backgroundColor = '#575757';
    button.style.color = '#ffffff';
    button.style.border = 'none';
    button.style.borderRadius = '3px';
    button.style.cursor = 'pointer';
    container.appendChild(button);

    const buttonContainer = document.createElement('div');
    buttonContainer.style.marginTop = '10px';
    buttonContainer.style.display = 'flex';
    buttonContainer.style.justifyContent = 'space-between';

    const channelButton1 = document.createElement('button');
    channelButton1.innerText = '1荒らし雑談';
    channelButton1.style.width = '30%';
    channelButton1.style.backgroundColor = '#575757';
    channelButton1.style.color = '#ffffff';
    channelButton1.style.border = 'none';
    channelButton1.style.borderRadius = '3px';
    channelButton1.style.cursor = 'pointer';
    channelButton1.addEventListener('click', () => {
        channelId = channelBox1.value.trim();
        updateButtonStyles(channelButton1);
    });

    const channelButton2 = document.createElement('button');
    channelButton2.innerText = '2情勢雑談';
    channelButton2.style.width = '30%';
    channelButton2.style.backgroundColor = '#575757';
    channelButton2.style.color = '#ffffff';
    channelButton2.style.border = 'none';
    channelButton2.style.borderRadius = '3px';
    channelButton2.style.cursor = 'pointer';
    channelButton2.addEventListener('click', () => {
        channelId = channelBox2.value.trim();
        updateButtonStyles(channelButton2);
    });

    const channelButton3 = document.createElement('button');
    channelButton3.innerText = '3依頼版';
    channelButton3.style.width = '30%';
    channelButton3.style.backgroundColor = '#575757';
    channelButton3.style.color = '#ffffff';
    channelButton3.style.border = 'none';
    channelButton3.style.borderRadius = '3px';
    channelButton3.style.cursor = 'pointer';
    channelButton3.addEventListener('click', () => {
        channelId = channelBox3.value.trim();
        updateButtonStyles(channelButton3);
    });

    buttonContainer.appendChild(channelButton1);
    buttonContainer.appendChild(channelButton2);
    buttonContainer.appendChild(channelButton3);
    container.appendChild(buttonContainer);

    function updateButtonStyles(activeButton) {
        [channelButton1, channelButton2, channelButton3].forEach(button => {
            if (button === activeButton) {
                button.style.backgroundColor = '#047500';
            } else {
                button.style.backgroundColor = '#575757';
            }
        });
    }

    inputBox.value = GM_getValue('inputBoxValue', '');
    tokenBox.value = GM_getValue('tokenBoxValue', '');

    async function sendDM() {
        const token = tokenBox.value.trim();
        if (!token) {
            alert('Token is required');
            return;
        }

        const message = inputBox.value.trim();
        if (!message) {
            alert('Message cannot be empty');
            return;
        }

        tokenBox.style.display = 'none';
        GM_setValue('tokenBoxValue', token);

        const success = await sendMessage(channelId, message, token);
        if (success) {
            inputBox.value = '';
            GM_setValue('inputBoxValue', '');
        } else {
            alert('Failed to send message');
        }
    }

    button.addEventListener('click', sendDM);

    inputBox.addEventListener('keydown', (event) => {
        if (event.key === 'Enter' && !event.shiftKey) {
            event.preventDefault();
            sendDM();
        } else if (event.key === 'Enter' && event.shiftKey) {
            event.preventDefault();
            const cursorPos = inputBox.selectionStart;
            const textBefore = inputBox.value.substring(0, cursorPos);
            const textAfter = inputBox.value.substring(cursorPos);
            inputBox.value = `${textBefore}\n${textAfter}`;
            inputBox.selectionStart = cursorPos + 1;
            inputBox.selectionEnd = cursorPos + 1;
        }
    });

    inputBox.addEventListener('input', () => {
        GM_setValue('inputBoxValue', inputBox.value);
    });

    tokenBox.addEventListener('input', () => {
        GM_setValue('tokenBoxValue', tokenBox.value);
    });

    function makeElementDraggable(el) {
        el.onmousedown = function(event) {
            if (event.target === inputBox || event.target === tokenBox || event.target === channelBox1 || event.target === channelBox2 || event.target === channelBox3) {
                return;
            }

            event.preventDefault();

            let shiftX = event.clientX - el.getBoundingClientRect().left;
            let shiftY = event.clientY - el.getBoundingClientRect().top;

            function moveAt(pageX, pageY) {
                el.style.left = pageX - shiftX + 'px';
                el.style.top = pageY - shiftY + 'px';
            }

            function onMouseMove(event) {
                moveAt(event.pageX, event.pageY);
            }

            document.addEventListener('mousemove', onMouseMove);

            el.onmouseup = function() {
                document.removeEventListener('mousemove', onMouseMove);
                el.onmouseup = null;
            };
        };

        el.ondragstart = function() {
            return false;
        };
    }

    async function sendMessage(channelId, message, token) {
        const nonce = generateNonce();
        return new Promise((resolve) => {
            GM_xmlhttpRequest({
                method: 'POST',
                url: `https://discord.com/api/v9/channels/${channelId}/messages`,
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': token
                },
                data: JSON.stringify({
                    content: message,
                                        flags: 0,
                    mobile_network_type: "unknown",
                    nonce: nonce,
                    tts: false
                }),
                onload: (response) => {
                    resolve(response.status === 200);
                },
                onerror: () => resolve(false)
            });
        });
    }

    function generateNonce() {
        const now = Date.now();
        return `${now}${Math.floor(Math.random() * 1000)}`;
    }
})();