167 行
5.6 KiB
TypeScript
167 行
5.6 KiB
TypeScript
import axios from 'axios'
|
|
import {appConfig} from "./config"
|
|
import * as qs from "qs"
|
|
import dayjs from "dayjs"
|
|
import {ICourse, IJsonCourse, TChannel} from "./types"
|
|
import {JsonCourseList, reqBody} from "./poll"
|
|
import axiosRetry from "axios-retry"
|
|
import tough from "tough-cookie"
|
|
import axiosCookieJarSupport from "axios-cookiejar-support"
|
|
import {strEnc} from "./des"
|
|
import {scalarOptions} from "yaml"
|
|
import * as process from "process"
|
|
|
|
let sduAxios = axios.create({
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
|
'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: 5000,
|
|
transformResponse: data => {
|
|
try {
|
|
return JSON.parse(data)
|
|
} catch (_e) {
|
|
return data
|
|
}
|
|
},
|
|
// maxRedirects: 10
|
|
})
|
|
axiosRetry(sduAxios, {
|
|
retries: 2,
|
|
shouldResetTimeout: true,
|
|
retryCondition: (_error) => true,
|
|
})
|
|
|
|
export async function logAndNotifyUser(text: string) {
|
|
console.log(text)
|
|
// await axios.post('https://qmsg.zendee.cn/send/' + appConfig.qmsgKey, qs.stringify({
|
|
// msg: text
|
|
// }), {
|
|
// headers: {
|
|
// '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) {
|
|
return new Promise(resolve => setTimeout(resolve, ms))
|
|
}
|
|
|
|
export function getTimeNow() {
|
|
return dayjs().format('hh:mm:ss A')
|
|
}
|
|
|
|
export function findJsonCourse(course: ICourse): IJsonCourse | undefined {
|
|
return JsonCourseList[course.channel].find(single => single.kch == course.kch && parseInt(single.kxh) == course.kxh)
|
|
}
|
|
|
|
export async function acquireCourse(course: IJsonCourse, channel: TChannel): Promise<boolean> {
|
|
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)
|
|
if (resp.data.message.includes('当前账号已在别处登录')) {
|
|
await resetCookie()// TODO 加锁、优化
|
|
}
|
|
return false
|
|
}
|
|
} catch (e) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
export async function exitCourse(course: IJsonCourse): Promise<boolean> {
|
|
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)
|
|
if (resp.data.message.includes('当前账号已在别处登录')) {
|
|
await resetCookie()
|
|
}
|
|
return false
|
|
}
|
|
} catch (e) {
|
|
logAndNotifyUser('[exitCourse]网络异常,退课失败')
|
|
return false
|
|
}
|
|
}
|
|
|
|
let resetCookieLock = false
|
|
|
|
export async function resetCookie() {
|
|
if (resetCookieLock) {
|
|
console.log('resetCookie 已被锁定')
|
|
return
|
|
}
|
|
resetCookieLock = true
|
|
try {
|
|
let cookieJar = new tough.CookieJar()
|
|
let cookieAxios = axios.create({
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0'
|
|
},
|
|
timeout: 6000,
|
|
maxRedirects: 10
|
|
})
|
|
axiosCookieJarSupport(cookieAxios)
|
|
cookieAxios.defaults.jar = cookieJar
|
|
cookieAxios.defaults.withCredentials = true
|
|
await cookieAxios.get('http://bkzhjx.wh.sdu.edu.cn/sso.jsp')
|
|
let casUrl = 'https://pass.sdu.edu.cn/cas/login?service=http%3A%2F%2Fbkzhjx.wh.sdu.edu.cn%2Fsso.jsp'
|
|
let resp = await cookieAxios.get(casUrl)
|
|
let ticket = /name="lt" value="(.*?)"/.exec(resp.data)?.[1] || null
|
|
let rsa = strEnc(appConfig.username + appConfig.password + ticket, '1', '2', '3')
|
|
resp = await cookieAxios.post(casUrl, qs.stringify({
|
|
rsa,
|
|
ul: appConfig.username.length,
|
|
pl: appConfig.password.length,
|
|
lt: ticket,
|
|
execution: 'e1s1',
|
|
_eventId: 'submit'
|
|
}))
|
|
let nextUrl = 'https://bkzhjx.wh.sdu.edu.cn' + /<a href="(.*?)">进入选课/.exec(resp.data)![1]
|
|
resp = await cookieAxios.get(nextUrl)
|
|
let xkId = /jrxk\('1','(.*?)'/.exec(resp.data)![1]
|
|
nextUrl = 'https://bkzhjx.wh.sdu.edu.cn/jsxsd/xsxk/newXsxkzx?jx0502zbid=' + xkId
|
|
await cookieAxios.get(nextUrl)
|
|
await cookieAxios.get('https://bkzhjx.wh.sdu.edu.cn/jsxsd/xsxk/selectBottom?jx0502zbid=' + xkId)
|
|
let cookieString = cookieJar.getCookieStringSync('https://bkzhjx.wh.sdu.edu.cn/jsxsd/xsxk')
|
|
console.log('[cookie]取得Cookie:' + cookieString)
|
|
appConfig.cookie = cookieString
|
|
sduAxios.defaults.headers['Cookie'] = cookieString
|
|
} catch (e) {
|
|
throw e
|
|
} finally {
|
|
resetCookieLock = false
|
|
}
|
|
}
|
|
|
|
export function countStr(str: string, word: string) {
|
|
return str.split(word).length - 1
|
|
}
|
|
|
|
export {sduAxios}
|