diff --git a/config.yaml.example b/config.yaml.example index 5feea56..6f4f640 100644 --- a/config.yaml.example +++ b/config.yaml.example @@ -1,7 +1,13 @@ # 教务cookie cookie: "JSESSIONID=asd;" -# 在 https://qmsg.zendee.cn 申请 -qmsgKey: "v9631222364dd7ae99909cb63b7445c5" +# 在 https://qmsg.zendee.cn 获取 +qmsgKey: "" +## telegram api 域名 +#tgApiDomain: "api.telegram.org" +## @BotFather 建立机器人获取 +#tgApiKey: "" +## @getidsbot 获取 +#tgChatId: -454888515 # 轮询间隔毫秒 interval: 100 # 监控列表 diff --git a/src/includes.ts b/src/includes.ts index 9df0e54..34650a2 100644 --- a/src/includes.ts +++ b/src/includes.ts @@ -9,10 +9,15 @@ import axiosRetry from "axios-retry" let sduAxios = axios.create({ headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', - 'Cookie': appConfig.cookie + 'Cookie': appConfig.cookie, + 'X-Requested-With': 'XMLHttpRequest', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0' }, baseURL: 'https://bkzhjx.wh.sdu.edu.cn/', - timeout: 5, + timeout: 5000, + transformResponse: data => { + return JSON.parse(data) + } // maxRedirects: 0 }) @@ -31,6 +36,10 @@ export async function logAndNotifyUser(text: string) { 'Content-Type': 'application/x-www-form-urlencoded' } }) + // await axios.post('https://' + appConfig.tgApiDomain + '/bot' + appConfig.tgApiKey + '/sendMessage', qs.stringify({ + // chat_id: appConfig.tgChatId, + // text: text + // })) } export function sleep(ms: number) { @@ -46,21 +55,44 @@ export function findJsonCourse(course: ICourse): IJsonCourse | undefined { } export async function acquireCourse(course: IJsonCourse, channel: TChannel): Promise { - if (channel == 'bx' || channel == 'xx') { - - } else { - + let segment = '' + switch (channel) { + case 'bx': + segment = 'bxxkOper' + break + case 'xx': + segment = 'xxxkOper' + break + case 'rx': + segment = 'ggxxkxkOper' + break + } + try { + let resp = await sduAxios.get('/jsxsd/xsxkkc/' + segment + '?kcid=' + course.jx02id + '&cfbs=null&jx0404id=' + course.jx0404id + '&xkzy=&trjf=') + if (resp.data.success === true) { + return true + } else { + logAndNotifyUser(resp.data.message) + return false + } + } catch (e) { + return false } - return true } export async function exitCourse(course: IJsonCourse, channel: TChannel): Promise { - if (channel == 'bx' || channel == 'xx') { - - } else { - + try { + let resp = await sduAxios.get('/jsxsd/xsxkjg/xstkOper?jx0404id=' + course.jx0404id) + if (resp.data.success === true) { + return true + } else { + logAndNotifyUser('[exitCourse]退课失败:' + resp.data.message) + return false + } + } catch (e) { + logAndNotifyUser('[exitCourse]网络异常,退课失败') + return false } - return true } export {sduAxios} diff --git a/src/poll.ts b/src/poll.ts index 06bcc88..7bb19cd 100644 --- a/src/poll.ts +++ b/src/poll.ts @@ -3,28 +3,8 @@ import {getTimeNow, sduAxios, sleep} from "./includes" import {appConfig} from "./config" import * as qs from "qs" -let reqData = [ - {"name": "sEcho", "value": "1"}, - {"name": "iColumns", "value": "2000"},// 1 - {"name": "sColumns", "value": ""}, - {"name": "iDisplayStart", "value": "0"}, - {"name": "iDisplayLength", "value": "2000"},// 1 - {"name": "mDataProp_0", "value": "kch"}, - {"name": "mDataProp_1", "value": "kcmc"}, - {"name": "mDataProp_2", "value": "kxhnew"}, - {"name": "mDataProp_3", "value": "jkfs"}, - {"name": "mDataProp_4", "value": "xmmc"}, - {"name": "mDataProp_5", "value": "xf"}, - {"name": "mDataProp_6", "value": "skls"}, - {"name": "mDataProp_7", "value": "sksj"}, - {"name": "mDataProp_8", "value": "skdd"}, - {"name": "mDataProp_9", "value": "xqmc"}, - {"name": "mDataProp_10", "value": "xkrs"}, - {"name": "mDataProp_11", "value": "syrs"}, - {"name": "mDataProp_12", "value": "ctsm"}, - {"name": "mDataProp_13", "value": "szkcflmc"}, - {"name": "mDataProp_14", "value": "czOper"} -] +let reqBody = 'sEcho=1&iColumns=15&sColumns=&iDisplayStart=0&iDisplayLength=2000&mDataProp_0=kch&mDataProp_1=kcmc&mDataProp_2=kxhnew&mDataProp_3=jkfs&mDataProp_4=xmmc&mDataProp_5=fzmc&mDataProp_6=ktmc&mDataProp_7=xf&mDataProp_8=skls&mDataProp_9=sksj&mDataProp_10=skdd&mDataProp_11=xqmc&mDataProp_12=syrs&mDataProp_13=ctsm&mDataProp_14=czOper' + export const JsonCourseList = <{ bx: IJsonCourse[], xx: IJsonCourse[], rx: IJsonCourse[] }>{ bx: [], xx: [], @@ -33,10 +13,9 @@ export const JsonCourseList = <{ bx: IJsonCourse[], xx: IJsonCourse[], rx: IJson async function updateBx() { try { - let resp = await sduAxios.post('/jsxsd/xsxkkc/xsxkBxxk?1=1&kcxx=&skls=&skfs=', qs.stringify(reqData)) + let resp = await sduAxios.post('/jsxsd/xsxkkc/xsxkBxxk?1=1&kcxx=&skls=&skfs=&xqid=', reqBody) JsonCourseList.bx.length = 0 JsonCourseList.bx.push(...resp.data.aaData) - console.log('更新必修JsonList成功') } catch (e) { console.log('获取必修JsonList失败 at ' + getTimeNow()) } @@ -44,7 +23,7 @@ async function updateBx() { async function updateXx() { try { - let resp = await sduAxios.post('/jsxsd/xsxkkc/xsxkXxxk?1=1&kcxx=&skls=&skfs=', qs.stringify(reqData)) + let resp = await sduAxios.post('/jsxsd/xsxkkc/xsxkXxxk?1=1&kcxx=&skls=&skfs=&xqid=', reqBody) JsonCourseList.xx.length = 0 JsonCourseList.xx.push(...resp.data.aaData) } catch (e) { @@ -54,7 +33,7 @@ async function updateXx() { async function updateRx() { try { - let resp = await sduAxios.post('/jsxsd/xsxkkc/xsxkGgxxkxk?kcxx=&skls=&skxq=&skjc=&sfym=false&sfct=false&szjylb=&sfxx=false&skfs=', qs.stringify(reqData)) + let resp = await sduAxios.post('/jsxsd/xsxkkc/xsxkGgxxkxk?kcxx=&skls=&skxq=&skjc=&sfym=false&sfct=false&szjylb=&sfxx=true&skfs=&xqid=', reqBody) JsonCourseList.rx.length = 0 JsonCourseList.rx.push(...resp.data.aaData) } catch (e) { diff --git a/src/test.ts b/src/test.ts index 1dde0e9..7986789 100644 --- a/src/test.ts +++ b/src/test.ts @@ -1,15 +1,19 @@ import {appConfig} from "./config" -console.log('channels: ' + appConfig.channels) -for (let course of appConfig.monit?.list || []) { - console.log('添加监控课程 ' + course.kch + ' on channel ' + course.channel) -} -for (let course of appConfig.acquire?.list || []) { - console.log('添加抢课课程 ' + course.kch + ' on channel ' + course.channel) -} -if (appConfig.replace) { - console.log('添加退课课程 ' + appConfig.replace.exit.kch + ' on channel ' + appConfig.replace.exit.channel) - for (let course of appConfig.replace.list) { - console.log('添加换课课程 ' + course.kch + ' on channel ' + course.channel) +async function test() { + console.log('channels: ' + appConfig.channels) + for (let course of appConfig.monit?.list || []) { + console.log('添加监控课程 ' + course.kch + ' on channel ' + course.channel) + } + for (let course of appConfig.acquire?.list || []) { + console.log('添加抢课课程 ' + course.kch + ' on channel ' + course.channel) + } + if (appConfig.replace) { + console.log('添加退课课程 ' + appConfig.replace.exit.kch + ' on channel ' + appConfig.replace.exit.channel) + for (let course of appConfig.replace.list) { + console.log('添加换课课程 ' + course.kch + ' on channel ' + course.channel) + } } } + +test() diff --git a/src/types.ts b/src/types.ts index 21899dd..fecc3f5 100644 --- a/src/types.ts +++ b/src/types.ts @@ -9,6 +9,9 @@ export interface ICourse { export interface IAppConfig { cookie: string, qmsgKey: string, + tgApiDomain: string, + tgApiKey: string, + tgChatId: number, interval: number, channels: TChannel[], monit?: {