kcnki
// ==UserScript==
// @name kcnki
// @namespace https://bbs.tampermonkey.net.cn/
// @version 0.1.1
// @description try to take over the world!
// @author chao
// @crontab * * once * *
// @grant GM_xmlhttpRequest
// @grant GM_log
// @grant GM_notification
// ==/UserScript==
return new Promise((resolve, reject) => {
// Your code here...
const courseId = '24613';
//'24609' '24610' '24611' '24612' '24613'
const sessionId = '341tug0i';
const order = 1;
const typeId = 1; //1为回放,2为直播
const watchTime = 1800;
const lectureId = 50499; //直播时为"" 这个和courseId有点对应不上
// 50493 50496 50497 50498 50499
let time = 10;
const token = '5f88eca3-e2e1-4012-b2dc-64507c939fa0';
const tools = {
sleep: t => new Promise(res => setTimeout(res, t)),// 箭头函数体只有一句,可以省略return
net: {
change: (str, withCookie) => {
str = str.trim(); //去除文本首位\s
let method = str.match(/(.*?)\s/)[1];
let url = str.match(/\s(.*?)\s/)[1];
str = str.replace(/.*?\n/, ''); //去除第一行
let data = /\n\s*\n\s*(.*)$/m.test(str) ? str.slice(str.match(/\n\s*\n\s*(.*)$/m).index).trim() : ''; //获取请求体,没有则返回'', 用slice截取防止请求体含有\n时出错
str = str.replace(new RegExp(data), '').trim(); //去除data
str = str.replace(/^(\s*?)(\S.*)/gm, `$2`); //去除每行行首的\s
str = str.replace(/\sContent-Length:.*/im, ''); //去除Content-Length所在行,不用/^\sContent-Length:./im, 这样做会多一个空白行避免一些问题
str = withCookie ? str : str.replace(/\s*cookie:.*/im, '') //去除cookie所在行,不用/^\s*cookie.*/im, 这样做会多一个空白行
let headers = {}, h = str.match(/(\S*?):\s*(\S.*)/mg);
// GM_log(h)
h.forEach(e => {
let t = e.match(/(\S*?):\s*(.*)/);
headers[t[1]] = t[2].replace(/\s*$/, '');//去除行尾\s,避免一下总没错吧
});
//去除浏览器默认携带的请求头
if (!/origin:/i.test(str)) headers.origin = '';//脚本猫默认有一个拓展origin,这里去掉
if (!/dnt/i.test(str)) headers.dnt = '';
if (!/referer/i.test(str)) headers.referer = '';
//if (!/accept/i.test(str)) headers.accept='';
if (!/user-agent/i.test(str)) headers['user-agent'] = '';
if (!/sec-ch-ua/i.test(str)) headers['sec-ch-ua'] = '';
if (!/sec-ch-ua-mobile/i.test(str)) headers['sec-ch-ua-mobile'] = '';
if (!/sec-ch-ua-platform/i.test(str)) headers['sec-ch-ua-platform'] = '';
if (!/sec-fetch-dest/i.test(str)) headers['sec-fetch-dest'] = '';
if (!/sec-fetch-mode/i.test(str)) headers['sec-fetch-mode'] = '';
if (!/sec-fetch-site/i.test(str)) headers['sec-fetch-site'] = '';
//if (!/accept-language/i.test(str)) headers['accept-language']='';
if (!/accept-encoding/i.test(str)) headers['accept-encoding'] = '';
return { url, method, data, headers }
},
}
};
tools.net.send = (str, onload = (xhr => xhr), anonymous = false, withCookie = false) => {
let t = tools.net.change(str, withCookie);
return new Promise((resolve, reject) => {
t.anonymous = anonymous;
t.onload = (xhr) => {
resolve(onload(xhr))
};
t.onerror = _ => { GM_log('net error') };
GM_xmlhttpRequest(t)
})
};
(async _ => {
for (let i = 0; i < 10000; i++) {
let j = i;
await tools.net.send(`
POST https://k.cnki.net/kedu/record/recordlearnFoot HTTP/1.1
Host: k.cnki.net
Origin: https://k.cnki.net
Referer: https://k.cnki.net/courseLive/${courseId}
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36
accept: application/json, text/plain, */*
accept-language: zh-CN,zh;q=0.9
authtoken: ${token}
content-type: application/json;charset=UTF-8
edutoken: ${token}
noticetoken: ${token}
orgtoken: ${token}
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="102", "Google Chrome";v="102"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
x-auth: true
{"courseId":"${courseId}","typeId":${typeId},"duration":60,"endTime":"2023-08-11 10:29:27","remark":"windows 10&&chrome 102.0.0.0","source":"k-wb-edu-courseLearn","watchTime":${watchTime + i},"lectureId":"${lectureId}","isComplete":false,"browserName":"chrome","secondTerminalName":"windows","terminalName":"pc","sessionId":"${sessionId}","order":${order+i}}
`, xhr => xhr);
await tools.sleep(1000 * 30)
}
})();
resolve();
});