Pride Vote

xxxxx

// ==UserScript==
// @name         Pride Vote
// @namespace    http://tampermonkey.net/
// @version      1.3
// @description  xxxxx
// @author       B
// @match        https://awards.bangkokpride.org/*
// @icon         https://awards.bangkokpride.org/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // ========== 弹窗拦截 ==========
    const originalAlert = window.alert;
    window.alert = function(message) {
        console.log("拦截弹窗:", message);
        return;
    };

    if (window.XMLHttpRequest) {
        const originalSend = XMLHttpRequest.prototype.send;
        XMLHttpRequest.prototype.send = function(body) {
            this.addEventListener('load', function() {
                if (this.status === 200) {
                    console.log("AJAX请求成功");
                }
            });
            return originalSend.apply(this, arguments);
        };
    }

    const originalFetch = window.fetch;
    window.fetch = async function(...args) {
        const response = await originalFetch.apply(this, args);
        if (response.ok) {
            console.log("Fetch请求成功");
        }
        return response;
    };

    // ========== 全局配置 ==========
    const config = {
        baseDelay: () => Math.random() * 500 + 500,
        voteDelay: () => Math.random() * 2000 + 3000,
        postVoteDelay: () => Math.random() * 100 + 500,
        checkInterval: 1000,
        timeout: 180000
    };

    // ========== 数据管理 ==========
    function clearSessionData() {
        // 清除所有Cookie
        document.cookie.split(";").forEach(cookie => {
            const [name] = cookie.trim().split("=");
            document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
        });

        // 清除本地存储
        localStorage.clear();
        sessionStorage.clear();
        console.log('已清除所有会话数据');
    }

    // ========== 首页监控 ==========
    function setupHomepageMonitoring() {
        let timeoutId = null;

        function handleTimeout() {
            console.log('操作超时');
            clearSessionData();
            window.location.reload();
        }

        function checkElements() {
            // 检测投票按钮
            const voteButton = document.querySelector(
                'section.py-4 button.bg-\\[\\#FF6699\\] a[href="/en/vote/"]'
            );
            if (voteButton) {
                console.log('发现有效投票按钮');
                clearTimeout(timeoutId);
                voteButton.click();
                return true;
            }

            // 检测冷却提示
            const waitDiv = document.querySelector(
                'section.py-4 div.bg-gray-500'
            );
            if (waitDiv?.textContent.includes('Wait another')) {
                console.log('检测到投票冷却');
                clearSessionData();
                window.location.reload();
                return true;
            }

            return false;
        }

        // 初始检查
        if (checkElements()) return;

        // 设置定时检查
        const intervalId = setInterval(() => {
            if (checkElements()) clearInterval(intervalId);
        }, config.checkInterval);

        // 设置定时器
        timeoutId = setTimeout(() => {
            clearInterval(intervalId);
            handleTimeout();
        }, config.timeout);

        // DOM变动
        const observer = new MutationObserver(mutations => {
            if (checkElements()) observer.disconnect();
        });
        observer.observe(document, {
            childList: true,
            subtree: true
        });
    }

    // ========== 自动化投票 ==========
    const random = {
        // 生成随机字符串
        string: (min, max) => {
            const length = Math.floor(Math.random() * (max - min + 1)) + min;
            return Array.from({length}, () =>
                String.fromCharCode(97 + Math.floor(Math.random() * 26))
            ).join('');
        },
        // 生成随机年份
        year: () => Math.floor(Math.random() * (2000 - 1980 + 1)) + 1980,
        // 随机选择国家
        country: () => ["Afghanistan", "Bahrain", "Brazil", "Sudan", "Belize",
                      "Georgia", "France", "Austria", "Benin", "Comoros",
                      "Chad", "Fiji", "Thailand"][Math.floor(Math.random() * 13)],
        // 生成随机邮箱
        email: () => `${random.string(5,8)}${Math.floor(Math.random()*1000)}@${['gmail','qq','yahoo','outlook','163','hotmail','sina','126','sohu'][Math.floor(Math.random()*4)]}.com`
    };

    // 元素等待
    function waitForElm(selector) {
        return new Promise(resolve => {
            if (document.querySelector(selector)) return resolve(document.querySelector(selector));
            const observer = new MutationObserver(() => {
                if (document.querySelector(selector)) {
                    resolve(document.querySelector(selector));
                    observer.disconnect();
                }
            });
            observer.observe(document.body, { childList: true, subtree: true });
        });
    }

    // 选择器
    const selectors = {
        firstCategory: {
            button: '//section[3]//button[contains(@class,"px-3 py-1")]',
            option: '//section[3]//label[3]//span[contains(@class,"text-lg")]'
        },
        secondCategory: {
            button: '//section[6]//button[contains(@class,"px-3 py-1")]',
            option: '//section[6]//label[8]//span[contains(@class,"text-lg")]'
        }
    };

    // 封装
    function xpathSelector(xpath) {
        return document.evaluate(xpath, document, null,
                               XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
    }

    // 选项选择
    async function selectOptions() {
        // 第一个奖项
        let cat1Btn = xpathSelector(selectors.firstCategory.button);
        if (cat1Btn) {
            cat1Btn.click();
            await new Promise(r => setTimeout(r, 500));
            let opt1 = xpathSelector(selectors.firstCategory.option);
            if (opt1) opt1.closest('label').click();
        }

        await new Promise(r => setTimeout(r, 300));

        // 第二个奖项
        let cat2Btn = xpathSelector(selectors.secondCategory.button);
        if (cat2Btn) {
            cat2Btn.click();
            await new Promise(r => setTimeout(r, 500));
            let opt2 = xpathSelector(selectors.secondCategory.option);
            if (opt2) opt2.closest('label').click();
        }
    }

    // 表单填写
    async function fillForm() {
        const fieldDelay = () => Math.random() * 10 + 10;

        async function fillField(id, value) {
            const el = document.getElementById(id);
            if (!el) return;

            el.focus();
            await new Promise(r => setTimeout(r, fieldDelay()));

            el.value = '';
            el.dispatchEvent(new Event('input', { bubbles: true }));
            await new Promise(r => setTimeout(r, fieldDelay()));

            for (const char of value.split('')) {
                el.value += char;
                el.dispatchEvent(new Event('input', { bubbles: true }));
                await new Promise(r => setTimeout(r, fieldDelay()));
            }

            el.dispatchEvent(new Event('change', { bubbles: true }));
            el.dispatchEvent(new Event('blur', { bubbles: true }));
            await new Promise(r => setTimeout(r, fieldDelay()));
        }

        await fillField('firstName', random.string(3, 5));
        await fillField('lastName', random.string(3, 5));
        await fillField('birthYear', random.year().toString());
        await fillField('gender', 'Female');
        await fillField('country', random.country().toUpperCase());
        await fillField('email', random.email());
    }

    // ========== 主控制流程 ==========
    async function main() {
        // 首页监控
        if (location.pathname === '/en/') {
            setupHomepageMonitoring();
            return;
        }

        // 处理投票页面
        if (location.pathname === '/en/vote/') {
            try {
                await waitForElm('#firstName');
                await fillForm();
                await selectOptions();

                await new Promise(r => setTimeout(r, config.voteDelay()));

                const voteButton = document.querySelector('button[class*="bg-[#FF6699]"]');
                if (voteButton) {
                    voteButton.click();
                    await new Promise(r => setTimeout(r, config.postVoteDelay()));
                    window.location.href = '/en/';
                }
            } catch (error) {
                console.error('投票错误:', error);
                window.location.reload();
            }
        }
    }

    // ========== 脚本启动器 ==========
    if (document.readyState === 'complete') main();
    else window.addEventListener('load', main);
})();