新海天帮你查课余量-正则匹配版

使用正则表达式自动提取课程号,监测特定课程的余量,并在有余量时发送浏览器通知,自动点击提交,仅需手动填写验证码

目前為 2024-12-19 提交的版本,檢視 最新版本

// ==UserScript==
// @name         新海天帮你查课余量-正则匹配版
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  使用正则表达式自动提取课程号,监测特定课程的余量,并在有余量时发送浏览器通知,自动点击提交,仅需手动填写验证码
// @author       上条当咩 & Claude
// @match        https://aa.bjtu.edu.cn/course_selection/courseselecttask/selects/
// @icon         https://yaya.csoci.com:1314/files/spc_ico_sora_sd.jpg\
// @license        MIT
// @grant        GM_xmlhttpRequest
// @grant        GM_notification
// ==/UserScript==

(function() {
    'use strict';
    
    // 您的愿望单课程数组 - 只需填写课程号和序号,例如: ['M402001B 01', 'A121033B 01']
    var wishListCourses = [
        'A121033B 01',
        'M402001B 01',
        'M402001B 02',
        'M402001B 03',
        'M402001B 04'
    ];

    let hasSubmitted = false;

    // 从课程描述中提取课程号的函数
    function extractCourseInfo(description) {
        // 匹配形如 "XXXXXXX:课程名称 XX" 或 "XXXXXXX 课程名称 XX" 的模式
        const regex = /^([A-Z]\d{6}[A-Z])(?::|:|\s)?.+?(\d{2})$/;
        const match = description.trim().match(regex);
        
        if (match) {
            return {
                courseCode: match[1],
                sectionNum: match[2],
                fullCode: `${match[1]} ${match[2]}`
            };
        }
        return null;
    }

    // 检查并点击提交按钮
    function clickSubmitButton() {
        var submitButton = document.querySelector('#select-submit-btn');
        if (submitButton) {
            submitButton.click();
            console.log('提交按钮已点击');
            return true;
        }
        console.log('提交按钮未找到');
        return false;
    }

    // 处理验证码
    async function handleCaptcha() {
        var captchaImage = document.querySelector('.captcha-dialog img');
        if (captchaImage) {
            var inputField = document.querySelector('.captcha-dialog input[name="answer"]');
            if (inputField) {
                console.log('请输入验证码后按下回车');
                return true;
            }
            console.log('验证码输入框未找到');
            return false;
        }
        console.log('验证码图片未找到');
        return false;
    }

    // 点击确认按钮
    function clickConfirmButton() {
        var confirmButton = document.querySelector('.modal-footer .btn-info');
        if (confirmButton) {
            confirmButton.click();
            console.log('确认按钮已点击');
            return true;
        }
        console.log('确认按钮未找到');
        return false;
    }

    // 点击复选框并处理理解模态框
    async function clickCheckboxAndUnderstandModal(courseCode) {
        var checkbox = document.querySelector(`input[type="checkbox"][kch="${courseCode}"]`);
        if (checkbox) {
            checkbox.click();
            console.log('成功找到checkbox');
            
            // 等待模态框出现并点击"已了解"
            await waitForModal();
            var understandButton = document.querySelector('.modal-footer button[data-bb-handler="info"]');
            if (understandButton) {
                understandButton.click();
                console.log(`${courseCode} 加入提交列表`);
            } else {
                console.log('未找到已了解按钮');
            }
        } else {
            console.log('未找到checkbox');
        }
    }

    // 等待模态框出现
    function waitForModal() {
        return new Promise(resolve => {
            const checkExist = setInterval(() => {
                const modal = document.querySelector('.modal-content');
                if (modal && modal.style.display !== 'none') {
                    clearInterval(checkExist);
                    resolve();
                }
            }, 100);
        });
    }

    // 执行脚本
    function executeScript() {
        setTimeout(() => {
            if (handleCaptcha()) {
                // 等待用户输入验证码
            }
        }, 1000);
    }

    // 提交选课
    function submit() {
        const submitButton = document.querySelector('#select-submit-btn');
        if (submitButton) {
            submitButton.click();
            hasSubmitted = true;
            executeScript();
            handleCaptcha();
            
            // 监听回车键以确认验证码
            document.addEventListener('keydown', function(event) {
                if (event.key === 'Enter') {
                    clickConfirmButton();
                }
            });
        } else {
            console.log('提交按钮未找到');
        }
    }

    // 主要逻辑
    function main() {
        const rows = document.querySelectorAll('table tbody tr');
        if (rows.length === 0) {
            GM_notification({
                title: '错误',
                text: '未找到课程表',
                timeout: 5000
            });
            return;
        }

        let availableCourseCount = 0;
        rows.forEach(row => {
            if (row.cells[1] && row.cells[0]) {
                const courseDescription = row.cells[1].innerText;
                const seatsText = row.cells[0].innerText.trim();
                const courseInfo = extractCourseInfo(courseDescription);

                if (courseInfo) {
                    const fullCode = courseInfo.fullCode;
                    
                    if (wishListCourses.includes(fullCode)) {
                        console.log(`检查课程: ${fullCode}`);
                        
                        if (!seatsText.includes('无余量') && !seatsText.includes('已选')) {
                            availableCourseCount++;
                            if (!hasSubmitted) {
                                clickCheckboxAndUnderstandModal(courseInfo.courseCode);
                            }
                            
                            // 发送通知
                            setInterval(() => {
                                GM_notification({
                                    title: '课程余量提醒',
                                    image: "https://yaya.csoci.com:1314/files/spc_ico_sora_sd.jpg",
                                    text: `课程 ${fullCode} 有余量!`,
                                    timeout: 5000
                                });
                            }, 1000);
                        } else {
                            console.log(`${fullCode} 当前状态:${seatsText}`);
                        }
                    }
                }
            }
        });

        // 根据可选课程数量决定下一步操作
        if (availableCourseCount === 0) {
            setTimeout(() => {
                location.reload();
            }, 2000);
        } else {
            submit();
        }
    }

    // 启动脚本
    main();
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址