清华社视听说 - 自动答题

解放你的双手

目前為 2020-12-20 提交的版本,檢視 最新版本

// ==UserScript==
// @name         清华社视听说 - 自动答题
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  解放你的双手
// @author       Hyun
// @include      *://www.tsinghuaelt.com/course-study-student/*
// @icon        https://www.tsinghuaelt.com/favicon.ico
// @require     https://cdn.staticfile.org/jquery/3.5.1/jquery.min.js
// @grant        GM_addStyle
// @grant       GM.setValue
// @grant       GM.getValue
// @grant       GM.deleteValue
// @run-at       document-idle
// ==/UserScript==

(function() {
    'use strict';

    let vocabulary = ['fantastic', 'error', 'whatsoever', 'arouse', 'magnificent', 'remarkable', 'schoolwork', 'ease', 'devil', 'factor', 'outstanding', 'infinite', 'infinitely', 'accomplish', 'accomplished', 'mission', 'investigate', 'mysterious', 'analysis', 'peak', 'excellence', 'credit', 'responsibility', 'amount', 'entertain', 'alternative', 'irregular', 'grant', 'cease', 'concentration', 'adapt', 'weird', 'profit', 'alter', 'performance', 'echo', 'hallway', 'await', 'abortion', 'database', 'available', 'indecision', 'ban', 'predict', 'breakthrough', 'fate', 'host', 'pose', 'instance', 'expert', 'surgery', 'naval', 'aircraft', 'target', 'spoonful', 'navigation', 'numerous', 'fluent', 'mechanic', 'advertise', 'advertising', 'waken', 'enormous', 'enormously', 'oversleep', 'survey', 'best-selling', 'filmmaker', 'prosperous', 'involve']
    let phrases = ['Yes, he is', 'No, he isn\'t', 'Yes', 'No']
    let getRanWord = ()=> { return vocabulary[parseInt(Math.random()*vocabulary.length)] }
    let getRanPhrase = ()=> { return phrases[parseInt(Math.random()*phrases.length)] }
    let sleep = (ms)=> { return new Promise(resolve => setTimeout(resolve, ms)); }
    let click_btn = ()=> { $('.wy-course-bottom .wy-course-btn-right .wy-btn').click(); }
    let config = {
        'autodo': ['auto_tiankong', 'auto_luyin', 'auto_lytk', 'auto_roleplay', 'auto_danxuan'],
        'autotryerr': true,
        'autostop': false,
        'delay': 10000
    };

    function input_in(e, txt) {
        if (e.type == 'textarea') {
            e.value= txt;
        } else {
            e.innerText= txt;
        }

        let changeEvent = null;
        changeEvent = document.createEvent ("HTMLEvents");
        changeEvent.initEvent ("input", true, true);
        e.dispatchEvent (changeEvent);

        changeEvent = document.createEvent ("HTMLEvents");
        changeEvent.initEvent ("keyup", true, true);
        e.dispatchEvent (changeEvent);

        changeEvent = document.createEvent ("HTMLEvents");
        changeEvent.initEvent ("change", true, true);
        e.dispatchEvent (changeEvent);
    }

    async function doTopic() {
        let setTixing = async (t)=> {
            console.log('[+] 题型:', t);
            $('#yun_status').text('当前题型:'+t);
            await sleep(config.delay) // 挂机10s,增加时长
        }; 

        if($('.wy-course-bottom .wy-course-btn-right .wy-btn').text().indexOf('Submit')==-1) {
            $('.page-next')[1].click();
            await sleep(1500)
        }

        if($('img[title="录音"]').length!=0 && config.autodo.includes('auto_luyin')) {
            await setTixing('录音');
            await doReadRepeat();
        } else if($('.lib-textarea-container').length!=0 && config.autodo.includes('auto_lytk')) {
            await setTixing('听力填空');
            await doListenAnswer();
        } else if($('.lib-fill-blank-do-input-left').length!=0 && config.autodo.includes('auto_tiankong')) {
            await setTixing('填空');
            await doTianKone();
        } else if($('.lib-single-item-img').length!=0 && config.autodo.includes('auto_danxuan')) {
            await setTixing('单选');
            await doSingleChoose();
        } else if($('.lib-role-select-item').length!=0 && config.autodo.includes('auto_roleplay')) {
            await setTixing('角色扮演');
            await doRolePlay();
        } else {
            await unSupposedOrSkip();
            return false;
        }

        return true;
    }

    // ===========================================

    // 填空题
    async function doTianKone() {
        // 先填写随机单词,获得答案

        let inputs = $('.lib-fill-blank-do-input-left');
        $.each(inputs, function(i,item){
            input_in(item, getRanWord());
        });
        
        await sleep(500);
        click_btn(); // Submit
        await sleep(2000);

        let answer = [], anyAnswer = false;
        $('.lib-edit-score span[data-type="1"]').each((i,item)=>{
            if(item.innerText.toLowerCase().indexOf('may vary')!=-1) {
                // 任意填空
                anyAnswer = true;
                return false;
            }
            answer.push(item.innerText)
        });
        
        if(anyAnswer) {
            return;
        }

        click_btn(); // Retry
        await sleep(2000);

        // 提交正确答案
        inputs = $('.lib-fill-blank-do-input-left');
        $(inputs).each((i,item)=>{
            input_in(item, answer[i]);
        });
        
        await sleep(500);
        click_btn(); // Submit
    }

    // 录音题
    async function doReadRepeat() {
        let sum_record = 0;

        if($('.lib-oral-container-top').length!=0) {
            var rec_div = $('.lib-oral-container-top')
        } else {
            var rec_div = $('.lib-listen-item-right-img')
        }
        
        rec_div.each((i,div)=>{
            if($(div).find('img[title="播放"]').length!=0){
                return true;
            };
        
            let click_record = (e) => { 
                console.log('click:', e);
                $(e).find('img[title="录音"],img[title="停止"]').click();
            }
            
            setTimeout(()=>{click_record(div);}, sum_record*5000);
            setTimeout(()=>{click_record(div);}, 3000 + sum_record*5000);
            sum_record ++;
        });
        await sleep(2000 + sum_record*5000)
        click_btn(); // Submit
        await sleep(3000)
    }

    // 单选题
    async function doSingleChoose() {
        let answer_map = {'A':0, 'B':1, 'C':2, 'D':3, 'E':4, 'F':5}

        // 随机选择以获得正确答案
        $('.lib-single-item-img img').click()
        
        await sleep(500);
        click_btn(); // Submit
        await sleep(2000);

        let answer = []
        $('.lib-single-cs-answer').each((i,item)=>{
            answer.push(item.innerText)
        });

        click_btn(); // Retry
        await sleep(2000);

        $('.lib-single-box').each((i,item)=>{
            $($(item).find('.lib-single-item')[answer_map[answer[i]]]).find('img').click()
        });

        await sleep(500);
        click_btn(); // Submit
    }

    // 角色扮演
    async function doRolePlay() {
        $('.lib-role-select-item img')[0].click()
        $('.lib-role-select-start button').click()

        await sleep(30000);
        click_btn(); // Submit
    }

    // 听力填空
    async function doListenAnswer() {
        let inputs = $('.lib-textarea-container');
        $.each(inputs, function(i,item){
            input_in(item, getRanPhrase());
        });
        
        await sleep(500);
        click_btn(); // Submit
    }

    // 不支持体型
    async function unSupposedOrSkip(params) {
        console.log('[!]', '遇到不支持体型或未选择,自动跳过。。。');
    }
    // ===========================================

    let running = false;

    async function initConf() {
        config = await GM.getValue('config', config);

        $.each(config.autodo, (index, id)=>{
            $('#'+id).prop("checked",true);
        });
        $('#set_tryerr').prop("checked", config.autotryerr);
        $('#set_manu').prop("checked", config.autostop);
        $('#set_delay').val(config.delay);
    }

    async function doLoop() {
        while (running) {
            let status = await doTopic();
            if(!status && config.autostop) {
                $('#yun_status').text('不支持当前体型, 已停止');
                break;
            }
            console.log('[*]', '已完成,切换下一题。。。');
            await sleep(1500);
            $('.page-next')[1].click()
            await sleep(5000); 
        }
        $('.yunPanel button').prop('disabled', false);
        $('#yun_status').text('IDLE');
    }

    $(`<style>.yunPanel input[type="checkbox"]{margin-left: 10px;}.yunPanel h3,.yunPanel input,.yunPanel label{font-size:smaller}.yunPanel p{margin:10px 0}.yunPanel{padding:10px 20px;position:fixed;top:100px;right:150px;height:370px;width:200px;border:1px solid #000;background-color:#fcff6680;z-index:9999}.yunPanel .close{position:absolute;cursor:pointer;top:8px;right:10px}.yunPanel .close:hover{color:#00000088}</style>`).appendTo("head");
    $(document.body).after(`
        <div class="yunPanel">
        <div class="close">x</div>
        <h1 style="text-align: center;font-size: medium;">社听说 - 自动答题</h1>
        <hr>
        <h2 style="font-size: small;">自动完成题型:</h2>
        <p>
            <input type="checkbox" id="auto_tiankong">
            <label for="auto_tiankong">填空</label>
            <input type="checkbox" id="auto_luyin">
            <label for="auto_luyin">录音</label>
            <input type="checkbox" id="auto_lytk">
            <label for="auto_lytk">录音填空</label>
            <input type="checkbox" id="auto_roleplay">
            <label for="auto_roleplay">角色扮演</label>
            <input type="checkbox" id="auto_danxuan">
            <label for="auto_danxuan">单项选择</label>
        </p>
        <h2 style="font-size: small;">设置</h2>
        <p>
            <p>
                <input type="checkbox" id="set_tryerr">
                <label for="set_tryerr">自动试错</label>
                <input type="checkbox" id="set_manu">
                <label for="set_manu">不支持题型停止</label>
            </p>
            <label>每题耗时(ms) <input style="width: 50px;" type="text" id="set_delay"></label>
            <button id="yun_save" style="float: left;margin-top:5px;width: 48%;">保存</button>
            <button id="yun_reset" style="float: right;margin-top:5px;width: 48%;">默认</button>
            <div style="clear: both;"></div>
        </p>
        <hr>
        <h2 id="yun_status" style="font-size: small;text-align: center;margin-bottom:8px;">IDLE</h2>
        <button id="yun_doone" style="width: 100%;margin-bottom: 3px;">做一题</button>
        <button id="yun_start" style="width: 100%;">开始</button>
        </div>
    `);

    $('#yun_start').click(()=>{
        if($('#yun_start').text()=='开始') {
            $('#yun_doone').prop('disabled', true);
            running = true;
            doLoop();
            $('#yun_start').text('停止')
        } else {
            $('.yunPanel button').prop('disabled', true);
            running = false;
            $('#yun_start').text('开始')
        }
    });

    $('#yun_doone').click(()=>{
        $('#yun_start').text('开始');
        running = false;
        $('.yunPanel button').prop('disabled', true);
        doTopic().then(()=>{
            $('.yunPanel button').prop('disabled', false);
            $('#yun_status').text('Done!');
        });
        
    });
    $('.yunPanel .close').click(()=>{$('.yunPanel').hide()});
    $('#yun_reset').click(()=>{ GM.deleteValue('config'); window.location.reload(); });
    $('#yun_save').click(()=>{
        let ids = config.autodo.slice()
        config.autodo = []
        $.each(ids, (index, id)=>{
            if($('#'+id).prop("checked")) {
                config.autodo.push(id);
            }
        });
        config.autotryerr = $('#set_tryerr').prop("checked");
        config.autostop = $('#set_manu').prop("checked");
        config.delay = $('#set_delay').val();
        GM.setValue('config', config);
        $('#yun_status').text('保存成功');
    });
    

    initConf();
    // Your code here...
})();

QingJ © 2025

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