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 { 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 { 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' + /进入选课/.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}