The Ugvs Auto Message V3

You Can Do Auto Message And Raid Server

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

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

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

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

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

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         The Ugvs Auto Message V3
// @namespace    http://tampermonkey.net/
// @version      5.0
// @description  You Can Do Auto Message And Raid Server
// @match        *://discord.com/*
// @grant        none
// @require      https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js
// ==/UserScript==

(async function () {
    'use strict';
    const ENCRYPTION_KEY = "super_secret_internal_key_123";
    const html = `
    <div id="dms-wrapper" style="position:fixed;top:50px;right:50px;z-index:9999;background:#51fcf4;color:white;border-radius:8px;font-size:13px;width:300px;box-shadow:0 0 8px rgba(0,0,0,0.6);user-select:none;font-family:Arial,sans-serif;">
      <div id="dms-titlebar" style="cursor:move;background:#27b0cf;padding:6px 10px;border-radius:8px 8px 0 0;display:flex;justify-content:space-between;align-items:center;user-select:none;">
        <span style="font-weight:bold;">The Ugvs Auto Message V3</span>
        <div style="display:flex;align-items:center;gap:10px;">
          <span id="dms-status" style="font-weight:bold;color:#ff4d4d;">Stop</span>
          <button id="dms-toggle" style="background:none;border:none;color:white;font-size:18px;cursor:pointer;line-height:1;">−</button>
        </div>
      </div>
      <div id="dms-body" style="padding:10px 12px;display:flex;flex-direction:column;gap:6px;user-select:text;">
        <div>
          <label style="font-weight:bold;">Discord Account Tokens:</label>
          <div id="dms-tokens-container" style="max-height:130px;overflow-y:auto;border:1px solid #7cfcf6;padding:4px;border-radius:4px;margin-top:3px;"></div>
          <button id="dms-add-token" style="margin-top:4px;width:100%;height:28px;font-weight:bold;cursor:pointer;">+ Add Discord Account Token</button>
          <button id="dms-gettoken" style="margin-top:5px;width:100%;height:28px;">Get Discord Account Token</button>
        </div>
        <div>
          <label style="font-weight:bold;">Server Channel ID:</label><br>
          <input id="dms-channel" style="width:100%;height:26px;margin-top:3px;"/>
          <button id="dms-getchannelid" style="margin-top:5px;width:100%;height:28px;">Get Server Channel ID</button>
        </div>
        <div>
          <label style="font-weight:bold;">Message:</label><br>
          <textarea id="dms-message" style="width:100%;height:50px;resize:vertical;margin-top:3px;"></textarea>
        </div>
        <div>
          <label style="font-weight:bold;">Interval (ms):</label><br>
          <input type="number" id="dms-interval" style="width:100%;height:26px;margin-top:3px;"/>
        </div>
      </div>
      <div id="dms-sendstop-container" style="display:flex;gap:8px;justify-content:flex-start;align-items:center;padding:8px 12px;border-top:1px solid #444;">
        <button id="dms-send" style="flex:1;height:30px;">Send</button>
        <button id="dms-stop" disabled style="flex:1;height:30px;">Stop</button>
      </div>
      <div id="dms-bypass-container" style="display:flex;gap:8px;align-items:center;font-size:13px;user-select:none;padding:0 12px 8px 12px;">
        <label style="display:flex;align-items:center;gap:4px;cursor:pointer;margin:0;">
          <input type="checkbox" id="dms-bypass" style="margin:0;vertical-align:middle;">Bypass
        </label>
        <label style="display:flex;align-items:center;gap:4px;cursor:default;margin:0;">
          <span>txt num:</span>
          <input type="number" id="dms-bypass-length" value="8" min="1" max="64" style="width:48px;height:24px;padding:2px 4px;text-align:center;"/>
        </label>
        <label style="display:flex;align-items:center;gap:4px;cursor:pointer;margin:0 0 0 8px;">
          <input type="checkbox" id="dms-splitmsg" style="margin:0;vertical-align:middle;">Return it
        </label>
      </div>
      <div style="display:flex;gap:8px;justify-content:center;padding:8px 12px;">
        <button id="dms-load" style="flex:1;height:28px;"> Load</button>
        <button id="dms-save" style="flex:1;height:28px;"> Save</button>
      </div>
      <div id="dms-log" style="max-height:90px;overflow:auto;background:#85d6bb;padding:6px;border-radius:4px;font-size:11px;margin:10px 12px 10px 12px;line-height:1.2;"></div>
    </div>`;

    let intervalId = null, currentTokenIndex = 0, simpleMode = false;

    // 改行分割メッセージ管理用
    let splitMessages = [];
    let splitMessageIndex = 0;

    const storedTokens = (() => {
        let val = localStorage.getItem("token") || "";
        val = val.replace(/^"(.*)"$/, "$1");
        return val.split(",").map(s => s.trim()).filter(Boolean);
    })();

    function log(msg, isError = false) {
        const logBox = document.getElementById("dms-log");
        if (!logBox) return;
        const line = document.createElement("div");
        line.style.color = isError ? "#ff4d4d" : "#80ff80";
        line.textContent = `[${new Date().toLocaleTimeString()}] ${msg}`;
        logBox.appendChild(line);
        logBox.scrollTop = logBox.scrollHeight;
    }

    function setStatus(running) {
        const el = document.getElementById("dms-status");
        if (!el) return;
        if (running) {
            el.textContent = "Running";
            el.style.color = "#80ff80";
        } else {
            el.textContent = "Stop";
            el.style.color = "#ff4d4d";
        }
    }

    function encryptData(data, key) {
        const json = JSON.stringify(data);
        return CryptoJS.AES.encrypt(json, key).toString();
    }

    function decryptData(ciphertext, key) {
        const bytes = CryptoJS.AES.decrypt(ciphertext, key);
        const json = bytes.toString(CryptoJS.enc.Utf8);
        return JSON.parse(json);
    }

    async function loadFromFile() {
        try {
            const [handle] = await window.showOpenFilePicker({
                types: [{
                    description: 'Discord Send Config File',
                    accept: { 'application/octet-stream': ['.dis'] }
                }],
                multiple: false
            });
            const file = await handle.getFile();
            const text = await file.text();
            const decrypted = decryptData(text, ENCRYPTION_KEY);
            const tokens = decrypted.tokens || (decrypted.token ? [decrypted.token] : []);
            const container = document.getElementById("dms-tokens-container");
            container.innerHTML = "";
            for (const t of tokens) addTokenInput(t);
            document.getElementById("dms-channel").value = decrypted.channel || "";
            document.getElementById("dms-message").value = decrypted.message || "";
            document.getElementById("dms-interval").value = decrypted.interval || "";
            log("Loaded settings in files");
        } catch (e) {
            log("Failed to load settings in files", true);
        }
    }

    function downloadToFile() {
        try {
            const tokens = Array.from(document.querySelectorAll(".dms-token-input")).map(input => input.value).filter(Boolean);
            const data = {
                tokens,
                channel: document.getElementById("dms-channel").value,
                message: document.getElementById("dms-message").value,
                interval: document.getElementById("dms-interval").value
            };
            const encrypted = encryptData(data, ENCRYPTION_KEY);
            const blob = new Blob([encrypted], { type: 'application/octet-stream' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = 'dispam_config.dis';
            document.body.appendChild(a);
            a.click();
            setTimeout(() => {
                document.body.removeChild(a);
                URL.revokeObjectURL(url);
            }, 100);
            log("File download started");
        } catch (e) {
            log("Failed to download files: " + e.message, true);
        }
    }

    function generateRandomChars(length) {
        const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        let result = '';
        for (let i = 0; i < length; i++) result += chars.charAt(Math.floor(Math.random() * chars.length));
        return result;
    }

    async function sendMessage() {
        const channelId = document.getElementById("dms-channel").value;
        let message = document.getElementById("dms-message").value;
        const bypassChecked = document.getElementById("dms-bypass")?.checked || false;
        const bypassLength = parseInt(document.getElementById("dms-bypass-length").value) || 8;
        const splitChecked = document.getElementById("dms-splitmsg")?.checked || false;

        if (!channelId) return;

        if (splitChecked) {
            if (splitMessages.length === 0) {
                splitMessages = message.split(/\r?\n/).map(s => s.trim()).filter(Boolean);
                splitMessageIndex = 0;
                if (splitMessages.length === 0) return;
            }
            message = splitMessages[splitMessageIndex];
            splitMessageIndex++;
            if (splitMessageIndex >= splitMessages.length) {
                splitMessageIndex = 0;
            }
        }

        if (!message) return;

        const tokens = Array.from(document.querySelectorAll(".dms-token-input")).map(input => input.value).filter(Boolean);
        if (tokens.length === 0) return;
        const token = tokens[currentTokenIndex];
        currentTokenIndex = (currentTokenIndex + 1) % tokens.length;

        let sendMsg = message;
        if (bypassChecked) sendMsg += ' ' + generateRandomChars(bypassLength);

        try {
            const response = await fetch(`https://discord.com/api/v9/channels/${channelId}/messages`, {
                method: 'POST',
                headers: {
                    'Authorization': token,
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({ content: sendMsg })
            });
            const json = await response.json().catch(() => ({}));
            if (response.status === 200) {
                log("✔Message Sended");
            } else if (response.status === 429) {
                log("⚠Rate Limit: retry_after=" + json.retry_after + "ms", true);
            } else {
                log(`❌️Failed to send: ${response.status}`, true);
            }
        } catch (err) {
            log("❌️Failed to send: " + err.message, true);
        }

        if (!splitChecked) {
            splitMessages = [];
            splitMessageIndex = 0;
        }
    }

    function startSending() {
        currentTokenIndex = 0;
        splitMessages = [];
        splitMessageIndex = 0;
        const interval = parseInt(document.getElementById("dms-interval").value) || 1000;
        if (intervalId) clearInterval(intervalId);
        intervalId = setInterval(sendMessage, interval);
        document.getElementById("dms-send").disabled = true;
        document.getElementById("dms-stop").disabled = false;
        setStatus(true);
        log("Send starting...");
    }

    function stopSending() {
        if (intervalId) clearInterval(intervalId);
        intervalId = null;
        document.getElementById("dms-send").disabled = false;
        document.getElementById("dms-stop").disabled = true;
        setStatus(false);
        log("Stop sending...");

        splitMessages = [];
        splitMessageIndex = 0;
    }

    function getChannelIdFromUrl() {
        const url = window.location.href;
        const match = url.match(/discord\.com\/channels\/\d+\/(\d+)/);
        return (match && match[1]) ? match[1] : null;
    }

    function addTokenInput(value = "") {
        const container = document.getElementById("dms-tokens-container");
        const wrapper = document.createElement("div");
        wrapper.style.display = "flex";
        wrapper.style.gap = "4px";
        wrapper.style.marginBottom = "3px";
        const input = document.createElement("input");
        input.type = "text";
        input.className = "dms-token-input";
        input.style.flexGrow = "1";
        input.style.width = "100%";
        input.style.height = "24px";
        input.value = value;
        const delBtn = document.createElement("button");
        delBtn.textContent = "×";
        delBtn.style.width = "26px";
        delBtn.style.height = "24px";
        delBtn.style.cursor = "pointer";
        delBtn.title = "このtokenを削除";
        delBtn.onclick = () => container.removeChild(wrapper);
        wrapper.appendChild(input);
        wrapper.appendChild(delBtn);
        container.appendChild(wrapper);
    }

    function toggleSimpleMode() {
        const body = document.getElementById("dms-body");
        const sendStop = document.getElementById("dms-sendstop-container");
        const bypass = document.getElementById("dms-bypass-container");
        const loadSave = bypass.nextElementSibling; // 読み込み・保存ボタン
        const logBox = document.getElementById("dms-log");
        const toggleBtn = document.getElementById("dms-toggle");
        if (!simpleMode) {
            // シンプルモード:トークン・チャネル・メッセージ等は非表示
            body.style.display = "none";
            sendStop.style.display = "flex";
            bypass.style.display = "none";
            if (loadSave) loadSave.style.display = "none";
            logBox.style.display = "block";
            toggleBtn.textContent = "+";
            simpleMode = true;
        } else {
            // フル表示モード
            body.style.display = "flex";
            sendStop.style.display = "flex";
            bypass.style.display = "flex";
            if (loadSave) loadSave.style.display = "flex";
            logBox.style.display = "block";
            toggleBtn.textContent = "−";
            simpleMode = false;
        }
    }

    function createUI() {
        if (document.getElementById("dms-wrapper")) return;
        document.body.insertAdjacentHTML('beforeend', html);
        document.getElementById("dms-send").onclick = startSending;
        document.getElementById("dms-stop").onclick = stopSending;
        document.getElementById("dms-load").onclick = loadFromFile;
        document.getElementById("dms-save").onclick = downloadToFile;
        document.getElementById("dms-add-token").onclick = () => addTokenInput("");
        document.getElementById("dms-gettoken").onclick = () => {
            if (storedTokens.length > 0) {
                const container = document.getElementById("dms-tokens-container");
                const inputs = container.querySelectorAll(".dms-token-input");
                if (inputs.length === 0) addTokenInput(storedTokens[0]);
                else if (!inputs[0].value.trim()) inputs[0].value = storedTokens[0];
                log("Pasted Token");
            } else {
                log("Couldn't found Token", true);
            }
        };
        document.getElementById("dms-getchannelid").onclick = () => {
            const id = getChannelIdFromUrl();
            if (id) {
                document.getElementById("dms-channel").value = id;
                log("Pasted ChannelID");
            } else {
                log("Couldn't found ChannelID", true);
            }
        };
        document.getElementById("dms-toggle").onclick = toggleSimpleMode;

        const wrapper = document.getElementById("dms-wrapper");
        const title = document.getElementById("dms-titlebar");
        let isDragging = false, offsetX = 0, offsetY = 0;
        title.addEventListener("mousedown", e => {
            isDragging = true;
            offsetX = e.clientX - wrapper.offsetLeft;
            offsetY = e.clientY - wrapper.offsetTop;
            e.preventDefault();
        });
        document.addEventListener("mousemove", e => {
            if (!isDragging) return;
            wrapper.style.left = (e.clientX - offsetX) + "px";
            wrapper.style.top = (e.clientY - offsetY) + "px";
            wrapper.style.right = "auto";
        });
        document.addEventListener("mouseup", () => { isDragging = false; });

        setStatus(false);
        addTokenInput("");
    }

    if (document.readyState === "complete" || document.readyState === "interactive") setTimeout(createUI, 100);
    else window.addEventListener("DOMContentLoaded", () => setTimeout(createUI, 100));
    setInterval(() => { if (!document.getElementById("dms-wrapper")) createUI(); }, 2000);
})();