├── 7z.dll ├── libxl.dll ├── pz.ini ├── 超级列表框数据.xlsx ├── HPSocket4C.dll ├── RapidJSON.dll ├── a20240201.exe ├── 说明.txt ├── README.md ├── jscq.php └── xxqg.txt /7z.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixxqg2023/yixxqg/HEAD/7z.dll -------------------------------------------------------------------------------- /libxl.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixxqg2023/yixxqg/HEAD/libxl.dll -------------------------------------------------------------------------------- /pz.ini: -------------------------------------------------------------------------------- 1 | [pz] 2 | t=8 3 | k= 4 | zj=http://yixxqg2.000webhostapp.com 5 | -------------------------------------------------------------------------------- /超级列表框数据.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixxqg2023/yixxqg/HEAD/超级列表框数据.xlsx -------------------------------------------------------------------------------- /HPSocket4C.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixxqg2023/yixxqg/HEAD/HPSocket4C.dll -------------------------------------------------------------------------------- /RapidJSON.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixxqg2023/yixxqg/HEAD/RapidJSON.dll -------------------------------------------------------------------------------- /a20240201.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixxqg2023/yixxqg/HEAD/a20240201.exe -------------------------------------------------------------------------------- /说明.txt: -------------------------------------------------------------------------------- 1 | 推送token: 微信登录https://www.pushplus.plus/ 获取 2 | 3 | 4 | 以下运行组件软件启动会自动检测下载。如果下载失败可以手动下载并解压到运行目录 5 | 6 | chrome下载地址:https://shuax.lanzoux.com/iJbGmpidhsb 7 | 8 | webview2运行时下载:https://wwi.lanzoup.com/imxoT0tyh2cf 9 | 10 | 未安装webview2运行时的话软件会启动报错,可以直接下载了手动安装 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 最新中继服务器地址 2 | 直接在pz.ini里面的zj值填写 ~~http://yixxqg.dothome.co.kr~~ https://yixxqg.serv00.net 这俩随便填一个就行 3 | 4 | # 自建中继服务器 5 | 源码在上面。自己部署在能使用php的空间,文件名称不要改,自己把域名填进pz.ini里面的zj值就行,确认文件地址为 【中继服务器地址】/jscq.php,例如https://yixxqg.serv00.net/jscq.php 6 | 7 | 8 | # 写在前面的话 9 | 本软件主要是依靠第三方浏览器脚本进行视频和文章的自动浏览,不打算做题,只是为了节省浏览视频文章的时间 10 | 11 | 我的理想状态是每天睡醒躺在床上通过推送的消息让挂机软件自动开始浏览文章视频,等我吃完饭打开手机花一分钟答题截图发给领导,每天的40分就完工。 12 | 13 | 答题是有这个功能,但是我默认是关闭了的,会被查。 14 | 15 | # 关于多账号版本 16 | 之前做过多账号版本的。现在懒得做了。其实也能做,但是这种手动登录的现在已经没有必要多账号了,之后有空了想办法做个多账号的公开版吧 17 | 18 | # 易语言开发的学习强国挂机软件 19 | 易语言 学习强国 挂机 ~~多账户~~ windows版本 20 | 21 | # 软件思路 22 | ~~原有思路:基于techstudy油猴脚本,通过chrome调试端口管理操作浏览器。定时启用浏览器刷新cookies,定时执行脚本~~ 23 | 24 | ~~更新为全后台模拟,不载入油猴脚本,软件测试为单机版不需要授权~~ 25 | 软件长期挂机在电脑 26 | 27 | 1.时间到推送登录消息到微信公众号 28 | 29 | 1.1 没醒,错过了登录二维码,此时软件会持续监听登录请求,睡醒后可以通过消息自带的页面推送登录请求到软件,软件会再次发起登录 30 | 31 | 1.2 醒了,收到的消息不能直接跳转到学习强国软件,此时可以 32 | 33 | 1.2.1 截图自带的二维码,打开学习强国扫码从图库读取,然后登录 34 | 35 | 1.2.2 微信右上角,选择浏览器打开,此时通过浏览器,直接点击蓝色字体跳转到学习强国登录即可 36 | 37 | 2. 学习完了,推送分数到微信,等待第二天到时间,中间不需要干啥,除非有时候莫名其妙bug,如果一个小时你都没收到浏览完毕的推送消息,那么你自己去电脑上看看卡哪了。自己手动点 “全流程” 按钮走一边就行 38 | 39 | 40 | # 安全性 41 | 42 | 不要在更换陌生网络环境挂机,已测试高分账号长期手机刷分的换浏览器刷会被警告。低分10000以下的警告程度大大减少。建议单机版在自己办公室挂机 43 | 44 | ~~# 授权~~ 45 | 46 | ~~多账户版本目前仅提供给内测用户授权使用,绑定机器~~ 47 | ~~单账户挂机的免费无限使用~~ 48 | ~~- 需要授权请邮件:yixxqg@gmail.com~~ 49 | 50 | # 单机版 - 无需授权 51 | ~~后台刷新保活,定时执行脚本。更简单更安全。~~ 52 | 53 | 现在不保活cookie,每天使用指令获取二维码到微信自己登录就行 54 | 55 | # 使用方式 56 | 1.首先,你得有个pushplus的推送token [https://www.pushplus.plus/](https://www.pushplus.plus/) 57 | 58 | 然后没了。直接把token填进软件,设置好定时时间然后重启软件就行,不放心就点那个全流程的按钮体验一下 59 | 60 | -------------------------------------------------------------------------------- /jscq.php: -------------------------------------------------------------------------------- 1 | 94 | -------------------------------------------------------------------------------- /xxqg.txt: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name 不学习何以强国-beta 3 | // @namespace http://tampermonkey.net/ 4 | // @version 20220318 5 | // @description 问题反馈位置: https://github.com/TechXueXi/techxuexi-js/issues 。读文章,看视频,做习题。 6 | // @author techxuexi ,荷包蛋。 7 | // @match https://www.xuexi.cn 8 | // @match https://www.xuexi.cn/* 9 | // @match https://pc.xuexi.cn/points/login.html* 10 | // @match https://pc.xuexi.cn/points/exam-practice.html 11 | // @match https://pc.xuexi.cn/points/exam-weekly-detail.html?id=* 12 | // @match https://pc.xuexi.cn/points/exam-weekly-list.html 13 | // @match https://pc.xuexi.cn/points/exam-paper-detail.html?id=* 14 | // @match https://pc.xuexi.cn/points/exam-paper-list.html 15 | // @require https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.5.1.min.js 16 | // @require https://cdn.bootcdn.net/ajax/libs/blueimp-md5/2.19.0/js/md5.min.js 17 | // @grant GM_addStyle 18 | // @grant GM_setValue 19 | // @grant GM_getValue 20 | // @grant GM_deleteValue 21 | // @grant GM_openInTab 22 | // ==/UserScript== 23 | var study_css = ".egg_study_btn{outline:0;border:0;position:fixed;top:5px;left:5px;padding:12px 20px;border-radius:10px;cursor:pointer;background-color:#fff;color:#d90609;font-size:18px;font-weight:bold;text-align:center;box-shadow:0 0 9px #666777}.egg_manual_btn{transition:0.5s;outline:none;border:none;padding:12px 20px;border-radius:10px;cursor:pointer;background-color:#e3484b;color:rgb(255,255,255);font-size:18px;font-weight:bold;text-align:center;}.egg_auto_btn{transition:0.5s;outline:none;border:none;padding:12px 20px;border-radius:10px;cursor:pointer;background-color:#666777;color:rgb(255,255,255);font-size:18px;font-weight:bold;text-align:center;}.egg_setting_box{position:fixed;top:70px;left:5px;padding:12px 20px;border-radius:10px;background-color:#fff;box-shadow:0 0 9px #666777}.egg_setting_item{margin-top:5px;height:30px;width:140px;font-size:16px;display:flex;justify-items:center;justify-content:space-between}input[type='checkbox'].egg_setting_switch{cursor:pointer;margin:0;outline:0;appearance:none;-webkit-appearance:none;-moz-appearance:none;position:relative;width:40px;height:22px;background:#ccc;border-radius:50px;transition:border-color .3s,background-color .3s}input[type='checkbox'].egg_setting_switch::after{content:'';display:inline-block;width:1rem;height:1rem;border-radius:50%;background:#fff;box-shadow:0,0,2px,#999;transition:.4s;top:3px;position:absolute;left:3px}input[type='checkbox'].egg_setting_switch:checked{background:#fd5052}input[type='checkbox'].egg_setting_switch:checked::after{content:'';position:absolute;left:55%;top:3px}"; 24 | GM_addStyle(study_css); 25 | //https://www.xuexi.cn/lgdata/3uoe1tg20en0.json 26 | //查询今日完成情况 27 | const SearchSocreUrl = "https://pc-proxy-api.xuexi.cn/delegate/score/days/listScoreProgress?sence=score&deviceType=2"; 28 | //重要新闻列表(主) 29 | const NewsUrl1 = "https://www.xuexi.cn/lgdata/1jscb6pu1n2.json"; 30 | //学习时评新闻列表 31 | const NewsUrl2 = "https://www.xuexi.cn/lgdata/1ap1igfgdn2.json"; 32 | //新闻视频列表 33 | const VideosUrl1 = "https://www.xuexi.cn/lgdata/3o3ufqgl8rsn.json"; 34 | //新闻视频列表 35 | const VideosUrl2 = "https://www.xuexi.cn/lgdata/1742g60067k.json"; 36 | //每日答题页面 37 | const ExamPracticeUrl = "https://pc.xuexi.cn/points/exam-practice.html"; 38 | //每周答题列表API 39 | const ExamWeeklyListUrl = "https://pc-proxy-api.xuexi.cn/api/exam/service/practice/pc/weekly/more?pageNo={pageNo}&pageSize=50"; 40 | //专项答题列表API 41 | const ExamPaperListUrl = "https://pc-proxy-api.xuexi.cn/api/exam/service/paper/pc/list?pageSize=50&pageNo={pageNo}"; 42 | //题目API(只有每周答题和专项练习) 43 | //const ExamQueryUrl = "https://pc-proxy-api.xuexi.cn/api/exam/service/detail/queryV3?type={type}&id={id}&forced=true";//type=1专项练习,type=2每周答题 44 | //每周答题页面 45 | const ExamWeeklyUrl = "https://pc.xuexi.cn/points/exam-weekly-detail.html?id={id}"; 46 | //专项测试页面 47 | const ExamPaperUrl = "https://pc.xuexi.cn/points/exam-paper-detail.html?id={id}"; 48 | //文本服务器保存API 49 | const AnswerSaveUrl = "https://a6.qikekeji.com/txt/data/save/"; 50 | //文本服务器获取API 51 | const AnswerDetailUrl = "https://a6.qikekeji.com/txt/data/detail/"; 52 | //获取当前日期 53 | var currDate = new Date().toISOString().split('T')[0]; 54 | var newsNum = 6; 55 | var news = []; 56 | var videoNum = 6; 57 | var videos = []; 58 | //配置 59 | var settings = {}; 60 | var settingsDefault = { 61 | News: true, //0 62 | Video: true,//1 63 | ExamPractice: false, //6 每日答题 64 | ExamWeekly: false,//2 每周答题 65 | ExamPaper: false,//5 专项练习 66 | ShowMenu: false, //7 隐藏菜单 67 | AutoStart: false, //是否加载脚本后自动播放 68 | } 69 | var pause = true;//是否暂停答题 70 | //每周答题当前页码 71 | var examWeeklyPageNo = 1; 72 | //每周答题总页码 73 | var examWeeklyTotalPageCount = null; 74 | //每周答题开启逆序答题: false: 顺序答题; true: 逆序答题 75 | var examWeeklyReverse = false; 76 | //专项答题当前页码 77 | var examPaperPageNo = 1; 78 | //专项答题总页码 79 | var examPaperTotalPageCount = null; 80 | //专项答题开启逆序答题: false: 顺序答题; true: 逆序答题 81 | var examPaperReverse = false; 82 | //每周答题,专项答题 请求rate 限制 每 3000ms 一次 83 | const ratelimitms = 3000; 84 | 85 | //默认情况下, chrome 只允许 window.close 关闭 window.open 打开的窗口,所以我们就要用window.open命令,在原地网页打开自身窗口再关上,就可以成功关闭了 86 | function closeWin() { 87 | try { 88 | //window.opener = window; 89 | //var win = window.open("", "_self"); 90 | //win.close(); 91 | top.close(); 92 | } catch (e) { 93 | } 94 | 95 | } 96 | 97 | async function sleep( timeMS ) { 98 | return new Promise( res => setTimeout( res, time ) ); 99 | } 100 | 101 | /** 模拟鼠标移动 改方法来自https://blog.csdn.net/Wuzihui___/article/details/79952068 102 | * @param id 103 | * @param clientX 相对窗口横坐标 104 | * @param clientY 相对窗口纵坐标 105 | * @param distance 滑动距离 106 | */ 107 | function dragandDrop(btn_hk, clientX, clientY, distance) { 108 | var elem = btn_hk; 109 | var k = 0; 110 | var interval; 111 | iME(elem,"mousedown", clientX, clientY); 112 | interval = setInterval(function() { 113 | k++; 114 | iME(elem, "mousemove", clientX + k, clientY); 115 | if (k === distance) { 116 | clearInterval(interval); 117 | iME(elem, "mouseup", clientX + k, clientY); 118 | } 119 | }, 16); 120 | 121 | function iME(obj, event, clientXArg, clientYArg) { 122 | var mouseEvent = new MouseEvent(event, { 123 | bubbles: true, 124 | cancelable: true, 125 | clientX: clientXArg, 126 | clientY: clientYArg 127 | }); 128 | obj.dispatchEvent(mouseEvent); 129 | } 130 | } 131 | 132 | /** 133 | * 随机等待最小到最大之间几秒, 需要await 134 | * @param {number} minSecond 最短时长 135 | * @param {number} MaxSecond 最长时长 136 | * @returns Promise 137 | */ 138 | function waitRandomBetween(minSecond = 2, MaxSecond = 5) { 139 | if (MaxSecond <= minSecond) { 140 | MaxSecond = minSecond + 3 141 | } 142 | 143 | let waitTime = Math.floor(Math.random() * (MaxSecond * 1000 - minSecond * 1000) + minSecond * 1000) 144 | return new Promise((resolve, reject) => { 145 | setTimeout(() => { 146 | console.log(`随机等待${waitTime / 1000}秒`) 147 | resolve() 148 | }, waitTime) 149 | }) 150 | } 151 | 152 | $(document).ready(function () { 153 | let url = window.location.href; 154 | if (url == "https://www.xuexi.cn" || url == "https://www.xuexi.cn/" || url == "https://www.xuexi.cn/index.html") { 155 | let ready = setInterval(function () { 156 | if (document.getElementsByClassName("text-wrap")[0]) { 157 | clearInterval(ready);//停止定时器 158 | //初始化设置 159 | initSetting(); 160 | //创建"开始学习"按钮 161 | createStartButton(); 162 | } 163 | }, 800); 164 | } else if (url.indexOf("login.html") !== -1) { 165 | console.log("检测到登录页") 166 | setTimeout(() => { 167 | window.scrollTo(0, 1000); 168 | }, 500); 169 | } 170 | else if (typeof GM_getValue("readingUrl") != 'object' && url == GM_getValue("readingUrl")) { 171 | try { 172 | let settingTemp = JSON.parse(GM_getValue('studySetting')); 173 | if (!settingTemp[7]) { 174 | createTip();//创建学习提示 175 | } 176 | reading(0); 177 | } catch (e) { 178 | createTip();//创建学习提示 179 | reading(0); 180 | } 181 | } else if (typeof GM_getValue("watchingUrl") != 'object' && url == GM_getValue("watchingUrl")) { 182 | try { 183 | let settingTemp = JSON.parse(GM_getValue('studySetting')); 184 | if (!settingTemp[7]) { 185 | createTip();//创建学习提示 186 | } 187 | } catch (e) { 188 | createTip();//创建学习提示 189 | } 190 | let randNum = 0; 191 | var checkVideoPlayingInterval = setInterval(function () { 192 | let temp = getVideoTag(); 193 | if (temp.video) { 194 | if (!temp.video.muted) { 195 | temp.video.muted = true; 196 | } 197 | if (temp.video.paused) { 198 | temp.video.paused = false; 199 | console.log("正在尝试播放视频") 200 | if (randNum == 0) {//尝试使用js的方式播放 201 | try { 202 | temp.video.play();//尝试使用js的方式播放 203 | } catch (e) { } 204 | randNum++; 205 | } else { 206 | try { 207 | temp.pauseButton.click();//尝试点击播放按钮播放 208 | } catch (e) { } 209 | randNum--; 210 | } 211 | } else { 212 | console.log("成功播放") 213 | clearInterval(checkVideoPlayingInterval); 214 | reading(1); 215 | } 216 | } else { 217 | console.log("等待加载") 218 | } 219 | }, 800); 220 | } else if (url.indexOf("exam") != -1 && url.indexOf("list") == -1) { 221 | //答题页面 222 | let ready = setInterval(function () { 223 | if (document.getElementsByClassName("title")[0]) { 224 | clearInterval(ready);//停止定时器 225 | //创建“手动答题”按钮 226 | createManualButton(); 227 | //去除答题验证 228 | //cancelVerify(); 229 | //开始答题 230 | doingExam(); 231 | } 232 | }, 500); 233 | } else { 234 | } 235 | }); 236 | 237 | 238 | //获取video标签 239 | function getVideoTag() { 240 | let iframe = document.getElementsByTagName("iframe")[0]; 241 | let video = null; 242 | let pauseButton = null; 243 | var u = navigator.userAgent; 244 | 245 | // 视频播放按钮更新 246 | video = document.getElementsByTagName("video")[0]; 247 | pauseButton = document.getElementsByClassName("prism-big-play-btn")[0]; 248 | 249 | return { 250 | "video": video, 251 | "pauseButton": pauseButton 252 | } 253 | 254 | // if (u.indexOf('Mac') > -1) {//Mac 255 | // if (iframe != null && iframe.innerHTML) { 256 | // //如果有iframe,说明外面的video标签是假的 257 | // video = iframe.contentWindow.document.getElementsByTagName("video")[0]; 258 | // pauseButton = iframe.contentWindow.document.getElementsByClassName("prism-play-btn")[0]; 259 | // } else { 260 | // //否则这个video标签是真的 261 | // video = document.getElementsByTagName("video")[0]; 262 | // pauseButton = document.getElementsByClassName("prism-play-btn")[0]; 263 | // } 264 | // return { 265 | // "video": video, 266 | // "pauseButton": pauseButton 267 | // } 268 | // } 269 | // else { 270 | // if (iframe) { 271 | // //如果有iframe,说明外面的video标签是假的 272 | // video = iframe.contentWindow.document.getElementsByTagName("video")[0]; 273 | // pauseButton = iframe.contentWindow.document.getElementsByClassName("prism-play-btn")[0]; 274 | // } else { 275 | // //否则这个video标签是真的 276 | // video = document.getElementsByTagName("video")[0]; 277 | // pauseButton = document.getElementsByClassName("prism-play-btn")[0]; 278 | // } 279 | // return { 280 | // "video": video, 281 | // "pauseButton": pauseButton 282 | // } 283 | // } 284 | } 285 | 286 | //读新闻或者看视频 287 | //type:0为新闻,1为视频 288 | async function reading(type) { 289 | //看文章或者视频 290 | var time = 1; 291 | if (type == 0) { 292 | time = parseInt(Math.random() * (100 - 80 + 1) + 80, 10);//80-100秒后关闭页面,看文章 293 | } else { 294 | time = parseInt(Math.random() * (250 - 230 + 1) + 230, 10);//230-250秒后关闭页面,看视频 295 | } 296 | let firstTime = time - 2; 297 | let secendTime = 12; 298 | let scrollLength = document.body.scrollHeight / 2; 299 | var readingInterval = setInterval(function () { 300 | time--; 301 | $("#studyTip").text(time + " 秒后关闭页面"); 302 | if (time <= firstTime) { 303 | try { 304 | $("html,body").animate({ scrollTop: 394 }, 1000); 305 | } catch (e) { 306 | window.scrollTo(0, 394); 307 | } 308 | firstTime = -1; 309 | } 310 | if (time <= secendTime) { 311 | try { 312 | $("html,body").animate({ scrollTop: scrollLength / 3 }, 1000); 313 | } catch (e) { 314 | window.scrollTo(0, scrollLength / 3); 315 | } 316 | secendTime = -1; 317 | } 318 | if (time <= 0) { 319 | if (type == 0) { 320 | GM_setValue('readingUrl', null); 321 | } else { 322 | GM_setValue('watchingUrl', null); 323 | } 324 | clearInterval(readingInterval); 325 | closeWin(); 326 | } 327 | }, 1000); 328 | //关闭文章或视频页面 329 | } 330 | //创建学习提示 331 | function createTip() { 332 | let tipInfo = document.createElement("div"); 333 | //添加样式 334 | tipInfo.setAttribute("id", "studyTip"); 335 | tipInfo.innerText = "正在初始化...."; 336 | tipInfo.style.position = "fixed"; 337 | tipInfo.style.bottom = "15px"; 338 | tipInfo.style.left = "5px"; 339 | tipInfo.style.padding = "12px 14px"; 340 | tipInfo.style.border = "none"; 341 | tipInfo.style.borderRadius = "10px"; 342 | tipInfo.style.backgroundColor = "#222222"; 343 | tipInfo.style.color = "#ffffff"; 344 | tipInfo.style.fontSize = "14px"; 345 | tipInfo.style.fontWeight = "bold"; 346 | //插入节点 347 | let body = document.getElementsByTagName("body")[0]; 348 | body.append(tipInfo) 349 | } 350 | //等待窗口关闭 351 | function waitingClose(newPage) { 352 | return new Promise(resolve => { 353 | let doing = setInterval(function () { 354 | if (newPage.closed) { 355 | clearInterval(doing);//停止定时器 356 | resolve('done'); 357 | } 358 | }, 1000); 359 | }); 360 | } 361 | //阅读文章 362 | async function readNews() { 363 | await getNews(); 364 | for (let i = 0; i < news.length; i++) { 365 | GM_setValue('readingUrl', news[i].url); 366 | console.log("正在看第" + (i + 1) + "个新闻"); 367 | let newPage = GM_openInTab(news[i].url, { active: true, insert: true, setParent: true }); 368 | await waitingClose(newPage); 369 | await waitRandomBetween(1, 3); 370 | } 371 | } 372 | //获取新闻列表 373 | function getNews() { 374 | return new Promise(resolve => { 375 | news = new Array(); 376 | let n = 6; 377 | if (newsNum < 6) {//如果需要学习的新闻数量不到6,也就是已经学过了,但是积分不够,补的 378 | n = newsNum; 379 | } 380 | console.log("还需要看" + n + "个新闻") 381 | //新闻数量是否足够 382 | let enough = true; 383 | //获取重要新闻 384 | $.ajax({ 385 | type: "GET", 386 | url: NewsUrl1, 387 | dataType: "json", 388 | success: function (data) { 389 | let j = 0; 390 | if (n == 6) {//如果今天还没学过,则优先找今天的新闻 391 | for (let i = 0; i < n; i++) { 392 | //如果有当天日期的,则加入 393 | if (data[j].auditTime.indexOf(currDate) != -1) { 394 | news.push(data[j]); 395 | j++; 396 | } else {//否则跳出循环 397 | break; 398 | } 399 | } 400 | } 401 | for (j; j < n; j++) { 402 | let temp = parseInt(Math.random() * (data.length + 1), 10); 403 | news.push(data[temp]); 404 | } 405 | resolve('done'); 406 | }, 407 | error: function () { 408 | news = null; 409 | resolve('done'); 410 | } 411 | }); 412 | }); 413 | } 414 | //获取视频列表 415 | function getVideos() { 416 | return new Promise(resolve => { 417 | videos = new Array(); 418 | let n = 6; 419 | if (videoNum < 6) {//如果需要学习的视频数量不到6,也就是已经学过了,但是积分不够,补的 420 | n = videoNum; 421 | } 422 | console.log("还需要看" + n + "个视频") 423 | $.ajax({ 424 | type: "GET", 425 | url: VideosUrl1, 426 | dataType: "json", 427 | success: function (data) { 428 | let j = 0; 429 | if (n == 6) { 430 | for (let i = 0; i < n; i++) { 431 | //如果有当天日期的,则加入 432 | if (data[j].auditTime.indexOf(currDate) != -1) { 433 | videos.push(data[j]); 434 | j++; 435 | } else {//否则跳出循环 436 | break; 437 | } 438 | } 439 | } 440 | for (j; j < n; j++) { 441 | let temp = parseInt(Math.random() * (data.length + 1), 10); 442 | videos.push(data[temp]); 443 | } 444 | resolve('done'); 445 | }, 446 | error: function () { 447 | videos = []; 448 | resolve('done'); 449 | } 450 | }); 451 | }); 452 | } 453 | //看学习视频 454 | async function watchVideo() { 455 | await getVideos(); 456 | for (let i = 0; i < videos.length; i++) { 457 | GM_setValue('watchingUrl', videos[i].url); 458 | console.log("正在观看第" + (i + 1) + "个视频"); 459 | let newPage = GM_openInTab(videos[i].url, { active: true, insert: true, setParent: true }) 460 | await waitingClose(newPage); 461 | await waitRandomBetween(1, 3); 462 | } 463 | } 464 | //做每日答题 465 | function doExamPractice() { 466 | return new Promise(resolve => { 467 | console.log("正在完成每日答题") 468 | let newPage = GM_openInTab(ExamPracticeUrl, { active: true, insert: true, setParent: true }); 469 | let doing = setInterval(function () { 470 | if (newPage.closed) { 471 | clearInterval(doing);//停止定时器 472 | resolve('done'); 473 | } 474 | }, 1000); 475 | }); 476 | } 477 | 478 | //fix code = 429 479 | async function waitingDependStartTime(startTime) { 480 | let remainms = Date.now() - startTime; 481 | if (remainms < ratelimitms) { 482 | let second = (ratelimitms - remainms) / 1000 483 | await waitRandomBetween(second + 1, second + 3) 484 | } 485 | } 486 | //初始化专项答题总页数属性 487 | async function InitExamPaperAttr() { 488 | let startTime = Date.now(); 489 | var data = await getExamPaperByPageNo(1); // 默认从第一页获取全部页属性 490 | if (data) { 491 | // 初始化总页码 492 | examPaperTotalPageCount = data.totalPageCount; 493 | // 若专项答题逆序, 则从最后一页开始 494 | if (examPaperReverse) { 495 | examPaperPageNo = examPaperTotalPageCount; 496 | } 497 | } 498 | await waitingDependStartTime(startTime); 499 | } 500 | 501 | //获取指定页数的专项答题列表 502 | function getExamPaperByPageNo(examPaperPageNoParam) { 503 | return new Promise(function (resolve) { 504 | $.ajax({ 505 | type: "GET", 506 | url: ExamPaperListUrl.replace("{pageNo}", examPaperPageNoParam), 507 | xhrFields: { 508 | withCredentials: true //如果没有这个请求失败 509 | }, 510 | dataType: "json", 511 | success: function (data) { 512 | data = decodeURIComponent(escape(window.atob(data.data_str.replace(/-/g, "+").replace(/_/g, "/")))); 513 | //JSON格式化 514 | data = JSON.parse(data); 515 | resolve(data); 516 | }, 517 | error: function () { 518 | resolve(new Array()); 519 | } 520 | }); 521 | }) 522 | } 523 | 524 | //查询专项答题列表看看还有没有没做过的,有则返回id 525 | async function findExamPaper() { 526 | var continueFind = true; 527 | var examPaperId = null; 528 | console.log("初始化专项答题属性"); 529 | await InitExamPaperAttr(); 530 | console.log("正在寻找未完成的专项答题"); 531 | while (continueFind) { 532 | let startTime = Date.now(); 533 | 534 | await getExamPaperByPageNo(examPaperPageNo).then(async (data) => { 535 | if (data) { 536 | let examPapers = data.list;//获取专项答题的列表 537 | if (examPaperReverse) { 538 | // 若开启逆序答题, 则反转专项答题列表 539 | console.log("专项答题,开启逆序模式,从最早的题目开始答题"); 540 | examPapers.reverse(); 541 | } 542 | for (let j = 0; j < examPapers.length; j++) { 543 | //遍历查询有没有没做过的 544 | if (examPapers[j].status != 2) {//status: 1为"开始答题" , 2为"重新答题" 545 | //如果不是"重新答题",则可以做 546 | examPaperId = examPapers[j].id; 547 | continueFind = false; 548 | break; 549 | } 550 | } 551 | if (!continueFind) { 552 | } else { 553 | //增加页码 (若开启逆序翻页, 则减少页码) 554 | examPaperPageNo += examPaperReverse ? -1 : 1; 555 | if (examPaperTotalPageCount == null 556 | || examPaperPageNo > examPaperTotalPageCount 557 | || examPaperPageNo < 1) { 558 | //已经找完所有页码,还是没找到,不再继续查找 559 | continueFind = false; 560 | } 561 | } 562 | } else { 563 | continueFind = false; 564 | } 565 | //fix code = 429 566 | await waitingDependStartTime(startTime); 567 | }) 568 | } 569 | return examPaperId; 570 | } 571 | 572 | //做专项答题 573 | function doExamPaper() { 574 | return new Promise(function (resolve) { 575 | //查找有没有没做过的专项答题,有则返回ID 576 | findExamPaper().then(examPaperId => { 577 | if (examPaperId != null) { 578 | console.log("正在做专项答题") 579 | let newPage = GM_openInTab(ExamPaperUrl.replace("{id}", examPaperId), { active: true, insert: true, setParent: true }); 580 | let doing = setInterval(function () { 581 | if (newPage.closed) { 582 | clearInterval(doing);//停止定时器 583 | resolve('done'); 584 | } 585 | }, 1000); 586 | } else { 587 | console.log("没有找到未完成的专项答题,跳过") 588 | resolve('noTest'); 589 | } 590 | }); 591 | }) 592 | } 593 | 594 | //初始化每周答题总页数属性 595 | async function InitExamWeeklyAttr() { 596 | let startTime = Date.now(); 597 | var data = await getExamWeeklyByPageNo(1); // 默认从第一页获取全部页属性 598 | if (data) { 599 | // 初始化总页码 600 | examWeeklyTotalPageCount = data.totalPageCount; 601 | // 若每周答题逆序, 则从最后一页开始 602 | if (examWeeklyReverse) { 603 | examWeeklyPageNo = examWeeklyTotalPageCount; 604 | } 605 | } 606 | await waitingDependStartTime(startTime); 607 | } 608 | 609 | //获取指定页数的每周答题列表 610 | function getExamWeeklyByPageNo(examWeeklyPageNoParam) { 611 | return new Promise(function (resolve) { 612 | $.ajax({ 613 | type: "GET", 614 | url: ExamWeeklyListUrl.replace("{pageNo}", examWeeklyPageNoParam), 615 | xhrFields: { 616 | withCredentials: true //如果没有这个请求失败 617 | }, 618 | dataType: "json", 619 | success: function (data) { 620 | data = decodeURIComponent(escape(window.atob(data.data_str.replace(/-/g, "+").replace(/_/g, "/")))); 621 | //JSON格式化 622 | data = JSON.parse(data); 623 | resolve(data); 624 | }, 625 | error: function () { 626 | resolve(new Array()); 627 | } 628 | }); 629 | }) 630 | } 631 | 632 | //查询每周答题列表看看还有没有没做过的,有则返回id 633 | async function findExamWeekly() { 634 | var continueFind = true; 635 | var examWeeklyId = null; 636 | console.log("初始化每周答题"); 637 | await InitExamWeeklyAttr(); 638 | console.log("正在寻找未完成的每周答题"); 639 | while (continueFind) { 640 | let startTime = Date.now(); 641 | await getExamWeeklyByPageNo(examWeeklyPageNo).then(async (data) => { 642 | if (data) { 643 | if (examWeeklyReverse) { 644 | // 若开启逆序答题, 则反转列表 645 | console.log("每周答题,开启逆序模式,从最早的题目开始答题"); 646 | data.list.reverse(); 647 | } 648 | for (let i = 0; i < data.list.length; i++) { 649 | let examWeeks = data.list[i].practices;//获取每周的测试列表 650 | if (examWeeklyReverse) { 651 | // 若开启逆序, 则反转每周的测试列表 652 | examWeeks.reverse(); 653 | } 654 | for (let j = 0; j < examWeeks.length; j++) { 655 | //遍历查询有没有没做过的 656 | if (examWeeks[j].status != 2) {//status: 1为"开始答题" , 2为"重新答题" 657 | //如果不是"重新答题",则可以做 658 | examWeeklyId = examWeeks[j].id; 659 | continueFind = false; 660 | break; 661 | } 662 | } 663 | if (!continueFind) { 664 | //如果已经找到了,则退出循环 665 | break; 666 | } 667 | } 668 | if (!continueFind) { 669 | } else { 670 | //增加页码 671 | examWeeklyPageNo += examWeeklyReverse ? -1 : 1; 672 | if (examWeeklyTotalPageCount == null 673 | || examWeeklyPageNo > examWeeklyTotalPageCount 674 | || examWeeklyPageNo < 1) { 675 | //已经找完所有页码,还是没找到,不再继续查找 676 | continueFind = false; 677 | } 678 | } 679 | } else { 680 | continueFind = false; 681 | } 682 | 683 | //fix code = 429 684 | await waitingDependStartTime(startTime); 685 | }) 686 | } 687 | return examWeeklyId; 688 | } 689 | //做每周答题 690 | function doExamWeekly() { 691 | return new Promise(function (resolve) { 692 | //查找有没有没做过的每周测试,有则返回ID 693 | //examWeeklyId = 147;//测试题目 694 | findExamWeekly().then(examWeeklyId => { 695 | if (examWeeklyId != null) { 696 | console.log("正在做每周答题") 697 | let newPage = GM_openInTab(ExamWeeklyUrl.replace("{id}", examWeeklyId), { active: true, insert: true, setParent: true }); 698 | let doing = setInterval(function () { 699 | if (newPage.closed) { 700 | clearInterval(doing);//停止定时器 701 | resolve('done'); 702 | } 703 | }, 1000); 704 | } else { 705 | console.log("没有找到未完成的每周答题,跳过") 706 | resolve('noTest'); 707 | } 708 | }); 709 | }) 710 | } 711 | //获取答题按钮 712 | function getNextButton() { 713 | return new Promise(function (resolve) { 714 | let nextInterVal = setInterval(() => { 715 | let nextAll = document.querySelectorAll(".ant-btn"); 716 | let next = nextAll[0]; 717 | if (nextAll.length == 2) { 718 | next = nextAll[1]; 719 | } 720 | if (next.textContent) { 721 | clearInterval(nextInterVal);//停止定时器 722 | resolve(next); 723 | } 724 | }, 800); 725 | }) 726 | } 727 | //暂停锁 728 | function doingPause() { 729 | return new Promise(function (resolve) { 730 | let doing = setInterval(function () { 731 | if (!pause) { 732 | clearInterval(doing);//停止定时器 733 | resolve('done'); 734 | } 735 | console.log("等待") 736 | }, 500); 737 | }) 738 | } 739 | //答题过程(整合) 740 | async function doingExam() { 741 | let nextButton = null; 742 | let qNum = 0;//题号,第一题从0开始算 743 | let shouldSaveAnswer = false; 744 | while (true) { 745 | //先等等再开始做题 746 | await waitRandomBetween(2, 5); 747 | await doingPause(); 748 | nextButton = await getNextButton(); 749 | if(document.getElementsByClassName('nc_iconfont btn_slide')[0] != null) { 750 | dragandDrop(document.getElementsByClassName('nc_iconfont btn_slide')[0],0,0,300); 751 | } 752 | if (nextButton.textContent == "再练一次" || nextButton.textContent == "再来一组" || nextButton.textContent == "查看解析") { 753 | break; 754 | } 755 | try { 756 | document.querySelector(".tips").click(); 757 | } catch (e) { 758 | console.log(e); 759 | } 760 | //所有提示 761 | var allTips = document.querySelectorAll("font[color=red]"); 762 | await waitRandomBetween(2, 3); 763 | //选项按钮 764 | var allbuttons = document.querySelectorAll(".q-answer"); 765 | //获取所有填空 766 | var blanks = document.querySelectorAll("input[type=text][class=blank]"); 767 | try { 768 | //获取问题类型 769 | var questionType = document.querySelector(".q-header").textContent; 770 | questionType = questionType.substr(0, 3) 771 | } catch (e) { 772 | } 773 | var results = []; 774 | switch (questionType) { 775 | case "填空题": { 776 | //第几个填空 777 | var inputBubblesEvent = new Event('input', { bubbles: true }); 778 | if (blanks.length > 1) {//如果有多个填空 779 | if (allTips.length == 0) {//如果没有提示,先获取看看有没有答案 780 | try {//尝试点击视频播放按钮,播不播都没关系 781 | document.getElementsByClassName("outter")[0].click(); 782 | } catch (e) { } 783 | //生成秘钥 784 | let key = getKey(); 785 | //尝试获取答案 786 | let answerData = await getAnswer(key); 787 | if (answerData.status == 0 || answerData == "error") {//没有答案 788 | for (let i = 0; i < blanks.length; i++) {//没答案,随便填点东西 789 | blanks[i].setAttribute("value", i); 790 | //必须要阻止事件,不然无效 791 | blanks[i].dispatchEvent(inputBubblesEvent); 792 | } 793 | shouldSaveAnswer = true;//答完保存答案 794 | } else {//获取到了答案 795 | //格式化 796 | answerData = JSON.parse(answerData.data.txt_content); 797 | answerData = answerData[0].content; 798 | //因为有多个空,所以有多个答案,先切割 799 | answerData = answerData.split(";"); 800 | for (let i = 0; i < answerData.length; i++) {//将答案填入 801 | blanks[i].setAttribute("value", answerData[i]); 802 | blanks[i].dispatchEvent(inputBubblesEvent); 803 | } 804 | } 805 | } else if (allTips.length == blanks.length) { 806 | //如果填空数量和提示数量一致 807 | for (let i = 0; i < allTips.length; i++) { 808 | //将答案填写到对应的空中 809 | let answer = allTips[i].textContent; 810 | if (answer && answer.length > 0) { 811 | blanks[i].setAttribute("value", answer); 812 | blanks[i].dispatchEvent(inputBubblesEvent); 813 | } else { 814 | //发生了错误,只好随便填一下 815 | blanks[i].setAttribute("value", i); 816 | blanks[i].dispatchEvent(inputBubblesEvent); 817 | } 818 | } 819 | } else if (allTips.length > blanks.length) { 820 | //若提示数量比填空的数量多 821 | //直接将所有答案整合填进去 822 | let answer = ""; 823 | for (let i = 0; i < allTips.length; allTips++) { 824 | answer += allTips[i].textContent(); 825 | } 826 | for (let j = 0; j < blanks.length; j++) { 827 | blanks[j].setAttribute("value", answer); 828 | blanks[j].dispatchEvent(inputBubblesEvent); 829 | } 830 | } else { 831 | //一般不会跑到这,如果到这了输出一下,表示惊讶 832 | console.log("居然跑到了这里") 833 | } 834 | } else if (blanks.length == 1) {//只有一个空,直接把所有tips合并。 835 | let answer = ""; 836 | if (allTips.length != 0) {//如果有提示 837 | for (let i = 0; i < allTips.length; i++) { 838 | answer += allTips[i].textContent; 839 | } 840 | } else { 841 | try {//尝试点击视频播放按钮,不过播不播都没关系 842 | document.querySelector('video').play(); 843 | } catch (e) { } 844 | let key = getKey(); 845 | let answerData = await getAnswer(key); 846 | if (answerData.status == 0 || answerData == "error") { 847 | //没有获取到答案 848 | answer = "不知道"; 849 | //没有其他人做过这道视频题,所以需要答完保存答案,这样其他人遇到就能做对 850 | shouldSaveAnswer = true; 851 | } else { 852 | //有答案 853 | answerData = JSON.parse(answerData.data.txt_content); 854 | answer = answerData[0].content; 855 | } 856 | } 857 | blanks[0].setAttribute("value", answer); 858 | blanks[0].dispatchEvent(inputBubblesEvent); 859 | break; 860 | } 861 | else { 862 | //怕有没空白的情况。 863 | } 864 | break; 865 | } 866 | case "多选题": { 867 | results = []; 868 | let hasButton = false; 869 | for (let i = 0; i < allTips.length; i++) { 870 | let tip = allTips[i]; 871 | let answer = tip.textContent; 872 | if (answer && answer.length > 0) { 873 | for (let j = 0; j < allbuttons.length; j++) { 874 | //获取按钮 875 | let selectButton = allbuttons[j]; 876 | //获取按钮的上的答案 877 | let buttonAnswer = selectButton.textContent; 878 | if (buttonAnswer == answer || buttonAnswer.indexOf(answer) != -1 || answer.indexOf(buttonAnswer) != -1) { 879 | hasButton = true; 880 | if (!$(selectButton).hasClass("chosen")) { 881 | selectButton.click(); 882 | } 883 | break; 884 | } 885 | } 886 | } 887 | } 888 | if (!hasButton) { 889 | allbuttons[0].click(); 890 | } 891 | break; 892 | } 893 | case "单选题": { 894 | let results = []; 895 | let answer = ""; 896 | for (let i = 0; i < allTips.length; i++) { 897 | answer += allTips[i].textContent; 898 | } 899 | if (answer && answer.length > 0) { 900 | let hasButton = false; 901 | for (let i = 0; i < allbuttons.length; i++) { 902 | let radioButton = allbuttons[i]; 903 | let buttonAnswer = radioButton.textContent; 904 | //对比答案 905 | if (buttonAnswer == answer || buttonAnswer.indexOf(answer) != -1 || answer.indexOf(buttonAnswer) != -1) { 906 | hasButton = true; 907 | radioButton.click(); 908 | break; 909 | } 910 | } 911 | if (!hasButton) { 912 | //没找到按钮,随便选一个 913 | allbuttons[0].click(); 914 | } 915 | } else { 916 | //没答案,随便选一个 917 | try { 918 | allbuttons[0].click(); 919 | } catch(e) { 920 | console.log(e); 921 | } 922 | } 923 | break; 924 | } 925 | default: 926 | break; 927 | } 928 | qNum++; 929 | nextButton = await getNextButton(); 930 | if (nextButton.textContent != "再练一次" && nextButton.textContent != "再来一组" && nextButton.textContent != "查看解析") { 931 | nextButton.click(); 932 | if (shouldSaveAnswer) {//如果应该保存答案 933 | let key = getKey();//获取key 934 | let answerTemp = document.getElementsByClassName("answer")[0].innerText; 935 | let reg = new RegExp(' ', "g") 936 | let answer = ""; 937 | try {//从字符串中拿出答案 938 | answer = answerTemp.split(":")[1]; 939 | answer = answer.replace(reg, ";"); 940 | } catch (e) { 941 | answer = answerTemp; 942 | } 943 | await saveAnswer(key, answer); 944 | shouldSaveAnswer = false; 945 | } 946 | } else { 947 | //已经做完,跳出循环 948 | break; 949 | } 950 | } 951 | closeWin(); 952 | } 953 | //获取关键字 954 | function getKey() { 955 | //获取题目的文本内容 956 | let key = document.getElementsByClassName("q-body")[0].innerText; 957 | //外部引用md5加密 958 | key = md5(key); 959 | console.log(key) 960 | return key; 961 | } 962 | //保存答案 963 | function saveAnswer(key, value) { 964 | return new Promise(function (resolve) { 965 | value = [{ "title": key, "content": value }]; 966 | value = JSON.stringify(value); 967 | $.ajax({ 968 | type: "POST", 969 | url: AnswerSaveUrl, 970 | data: { 971 | txt_name: key, 972 | txt_content: value, 973 | password: "", 974 | v_id: "" 975 | }, 976 | dataType: "json", 977 | success: function (data) { 978 | resolve(data); 979 | }, 980 | error: function () { 981 | resolve("error"); 982 | } 983 | }); 984 | }) 985 | } 986 | //获取答案 987 | function getAnswer(key) { 988 | return new Promise(function (resolve) { 989 | $.ajax({ 990 | type: "POST", 991 | url: AnswerDetailUrl, 992 | data: { 993 | txt_name: key, 994 | password: "" 995 | }, 996 | dataType: "json", 997 | success: function (data) { 998 | resolve(data); 999 | }, 1000 | error: function () { 1001 | resolve("error"); 1002 | } 1003 | }); 1004 | }) 1005 | } 1006 | //去除答题验证 1007 | function cancelVerify() { 1008 | try { 1009 | let verifyBox = document.getElementById("nc_mask"); 1010 | verifyBox.id = "egg_nc_mask"; 1011 | verifyBox.innerHTML = ""; 1012 | verifyBox.remove(); 1013 | } catch (e) { 1014 | console.log("去除验证失败"); 1015 | } 1016 | } 1017 | //查询今日完成情况 1018 | function getToday() { 1019 | return new Promise(function (resolve) { 1020 | $.ajax({ 1021 | type: "GET", 1022 | url: SearchSocreUrl, 1023 | xhrFields: { 1024 | withCredentials: true //如果没有这个请求失败 1025 | }, 1026 | dataType: "json", 1027 | success: function (temp) { 1028 | resolve(temp.data.taskProgress); 1029 | }, 1030 | error: function () { 1031 | resolve(new Array()); 1032 | } 1033 | }); 1034 | }) 1035 | } 1036 | //初始化配置 1037 | function initSetting() { 1038 | try { 1039 | let settingTemp = JSON.parse(GM_getValue('studySetting')); 1040 | if (settingTemp != null && Object.prototype.toString.call(settingTemp) === '[object Object]') { 1041 | // 增加判断是否为旧数组类型缓存 1042 | settings = settingTemp; 1043 | } else { 1044 | settings = JSON.parse(JSON.stringify(settingsDefault)); 1045 | } 1046 | } catch (e) { 1047 | //没有则直接初始化 1048 | settings = JSON.parse(JSON.stringify(settingsDefault)); 1049 | } 1050 | } 1051 | //创建“手动答题”按钮 1052 | function createManualButton() { 1053 | let title = document.getElementsByClassName("title")[0]; 1054 | let manualButton = document.createElement("button"); 1055 | manualButton.setAttribute("id", "manualButton"); 1056 | manualButton.innerText = "关闭自动答题"; 1057 | manualButton.className = "egg_auto_btn"; 1058 | //添加事件监听 1059 | try {// Chrome、FireFox、Opera、Safari、IE9.0及其以上版本 1060 | manualButton.addEventListener("click", clickManualButton, false); 1061 | } catch (e) { 1062 | try {// IE8.0及其以下版本 1063 | manualButton.attachEvent('onclick', clickManualButton); 1064 | } catch (e) {// 早期浏览器 1065 | console.log("不学习何以强国error: 手动答题按钮绑定事件失败") 1066 | } 1067 | } 1068 | //插入节点 1069 | title.parentNode.insertBefore(manualButton, title.nextSibling); 1070 | } 1071 | //点击手动学习按钮 1072 | function clickManualButton() { 1073 | let manualButton = document.getElementById("manualButton"); 1074 | if (manualButton.innerText == "关闭自动答题") { 1075 | manualButton.innerText = "开启自动答题"; 1076 | manualButton.className = "egg_manual_btn"; 1077 | pause = true; 1078 | } else { 1079 | manualButton.innerText = "关闭自动答题"; 1080 | manualButton.className = "egg_auto_btn"; 1081 | pause = false; 1082 | } 1083 | } 1084 | //创建“开始学习”按钮和配置 1085 | function createStartButton() { 1086 | let base = document.createElement("div"); 1087 | var baseInfo = ""; 1088 | baseInfo += "