import lodash from "lodash"; import { parse } from "flags/mod.ts"; import { dirname, fromFileUrl, SEP } from "path/mod.ts"; import { networkInterfaces } from "node:os"; const REFERER = "https://w.seu.edu.cn/"; const EPORTAL_API = "https://w.seu.edu.cn:802/eportal"; const headers = { "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/117.0", }; const PROG_PATH = Deno.args.includes("--is_compiled_binary") ? Deno.execPath() : fromFileUrl(Deno.mainModule); const CONFIG_FILE = `${dirname(PROG_PATH)}${SEP}credentials.json`; (async () => { const flags = parse(Deno.args, { boolean: ["login", "logout"], string: ["config"], default: { login: true, config: CONFIG_FILE } }); try { const credentials = JSON.parse(await Deno.readTextFile(flags.config)); if (lodash.isEmpty(credentials.username) || lodash.isEmpty(credentials.password)) { throw "Invalid credentials! "; } const { ipv4, ipv6, mac } = getNetIfInfo(); if (flags.logout) { const LOGOUT_URL = `${EPORTAL_API}/?c=Portal&a=unbind_mac&callback=dr1004&user_account=&wlan_user_mac=${mac.replaceAll(":", "").toUpperCase()}&wlan_user_ip=${ipv4}&jsVersion=3.3.3`; await logout(LOGOUT_URL); } else { const LOGIN_URL = `${EPORTAL_API}/?c=Portal&a=login&callback=dr1004&login_method=1&user_account=%2C0%2C${credentials.username}&user_password=${credentials.password}&wlan_user_ip=${lodash.isEmpty(ipv4) ? '' : ipv4}&wlan_user_ipv6=${lodash.isEmpty(ipv6) ? '' : ipv6}&wlan_user_mac=000000000000&wlan_ac_ip=&wlan_ac_name=&jsVersion=3.3.3`; await login(LOGIN_URL); }; } catch (err) { if (err instanceof SyntaxError) { exitWithError("Parse json failed!"); } else if (err instanceof Deno.errors.NotFound) { exitWithError(`${CONFIG_FILE} not found!`) } else { console.error(`[ERROR]: ${err.toString()}`); exitWithError(''); } } })(); function exitWithError(errstr) { if (!lodash.isEmpty(errstr)) { console.error(errstr) }; Deno.exit(1); } function getNetIfInfo() { let ipv4, ipv6, mac; const netIf = networkInterfaces(); const wlanIf = netIf.wlan0 || netIf.WLAN; if (lodash.isEmpty(wlanIf)) { exitWithError("No valid wireless network interface Found!"); } for (let i = 0; i < wlanIf.length; i++) { var alias = wlanIf[i]; if (alias.family === 'IPv4' && !alias.internal) { const re = /^169.254.*/g; if (lodash.isEmpty(alias.address.match(re))) { ipv4 = alias.address; } } else if (alias.family === 'IPv6' && !alias.internal) { const re = /^fe80::*/g; if (lodash.isEmpty(alias.address.match(re))) { ipv6 = alias.address; } } mac = alias.mac; } return { ipv4, ipv6, mac }; } async function login(LOGIN_URL) { const resp = await fetch(LOGIN_URL, { "credentials": "include", headers, "referrer": REFERER, "mode": "cors" }); if (resp.ok) { const resp_text = await resp.text(); const re = /dr1004\((.*?)\)/g; const match = re.exec(resp_text); if (lodash.isEmpty(match) || match.length <= 1) { throw "No match in response!"; } const parsedData = JSON.parse(match[1]); if (parsedData.result == 1) { console.log("Login success!"); } else if (parsedData.result == 0 && (parsedData.ret_code == 1 || parsedData.ret_code == 2)) { console.log("Already logged in!") } else { throw `Login failed.${lodash.isEmpty(parsedData.msg) ? '' : `\nServer responds message: ${parsedData.msg}`}`; } } } async function logout(LOGOUT_URL) { const resp = await fetch(LOGOUT_URL, { "credentials": "include", headers, "referrer": REFERER, "mode": "cors" }); if (resp.ok) { const resp_text = await resp.text(); const re = /dr1004\((.*?)\)/g; const match = re.exec(resp_text); if (lodash.isEmpty(match) || match.length <= 1) { throw "No match in response!"; } const parsedData = JSON.parse(match[1]); if (parsedData.result == 1) { console.log("Logout success!"); } else { throw `Logout failed.${lodash.isEmpty(parsedData.msg) ? '' : `\nServer responds message: ${parsedData.msg}`}`; } } }