cea-check-in
Version:
check in plugin for cea
193 lines (192 loc) • 6.33 kB
JavaScript
import crypto from "crypto";
import { CampusphereEndpoint } from "cea-core";
import { handleCookie, log, sstore } from "cea-core";
import fetch from "node-fetch";
import * as uuid from "uuid";
import { LogInfoKeys } from "./types.js";
const _CheckIn = class {
constructor(user) {
const school = sstore.get("schools")[user.school];
this.school = school;
this.user = user;
this.headers = {
"user-agent": "Mozilla/5.0 (Linux; Android 10; GM1910 Build/QKQ1.190716.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/87.0.4280.101 Mobile Safari/537.36 cpdaily/8.2.13 wisedu/8.2.13",
"content-type": "application/json"
};
}
async signInfo() {
var _a;
const { user, school } = this;
const storeCookiePath = `cookie.${user.alias}`;
const cookie = sstore.get(storeCookiePath);
const campusCookieIdx = new URL(school.campusphere).host;
if (!cookie) {
return;
}
this.headers.cookie = cookie[campusCookieIdx];
const res = await fetch(`${school.campusphere}${CampusphereEndpoint.getStuSignInfosInOneDay}`, {
method: "POST",
headers: this.headers,
body: JSON.stringify({})
});
if ((_a = res.headers.get("content-type")) == null ? void 0 : _a.includes("json")) {
const signQ = await res.json();
const isValidCookie = signQ.message === "SUCCESS";
if (isValidCookie) {
return signQ.datas;
}
}
}
async signWithForm(curTask) {
const { school, headers, user } = this;
const { signInstanceWid, signWid } = curTask;
let res = await fetch(`${school.campusphere}${CampusphereEndpoint.detailSignInstance}`, {
headers,
method: "POST",
body: JSON.stringify({ signInstanceWid, signWid })
});
const signDetails = (await res.json()).datas;
let {
extraField,
longitude,
latitude,
signPlaceSelected,
isNeedExtra,
signedStuInfo
} = signDetails;
let position;
const placeList = signPlaceSelected[0];
const isSignAtHome = !Boolean(school.defaultAddr);
[longitude, latitude, position] = isSignAtHome ? this.user.addr : [placeList.longitude, placeList.latitude, school.defaultAddr];
const extraFieldItems = _CheckIn.fillExtra(extraField);
const formBody = {
longitude: _CheckIn.fixedFloatRight(longitude),
latitude: _CheckIn.fixedFloatRight(latitude),
isMalposition: isSignAtHome ? 1 : 0,
abnormalReason: "",
signPhotoUrl: "",
isNeedExtra,
position,
uaIsCpadaily: true,
signInstanceWid,
extraFieldItems
};
const bodyString = _CheckIn.formBodyEncrypt(formBody);
const signHashBody = {
appVersion: _CheckIn.VERSION.app,
bodyString,
deviceId: uuid.v1(),
lat: formBody.latitude,
lon: formBody.longitude,
model: "Cock",
systemName: "android",
systemVersion: "11",
userId: this.user.username
};
const signExtensionBody = {
...signHashBody,
bodyString: void 0
};
const signHash = crypto.createHash("md5").update(`${new URLSearchParams(signHashBody).toString()}&${_CheckIn.FORMBODY_ENCRYPT.key}`).digest("hex");
const postBody = {
sign: signHash,
version: _CheckIn.VERSION.version,
calVersion: _CheckIn.VERSION.calVersion,
...signHashBody
};
headers["Cpdaily-Extension"] = _CheckIn.extensionEncrypt(signExtensionBody);
res = await fetch(`${school.campusphere}${CampusphereEndpoint.submitSign}`, {
headers,
method: "POST",
body: JSON.stringify(postBody)
});
const result = await res.json();
const logInfo = {
[LogInfoKeys.result]: result.message,
[LogInfoKeys.addr]: formBody.position
};
if (process.env.GITHUB_ACTION) {
delete logInfo[LogInfoKeys.addr];
}
return logInfo;
}
static fixedFloatRight(floatStr) {
return parseFloat(floatStr.replace(/(\d+\.\d{5})(\d{1})(.*)/, (s, p, p2) => `${p}${p2 == 0 ? 1 : p2}`));
}
static fillExtra(extraField) {
return extraField.map((e) => {
let chosenWid;
const normal = e.extraFieldItems.filter((i) => {
if (i.isAbnormal === false)
chosenWid = i.wid;
return !i.isAbnormal;
})[0];
return {
extraFieldItemWid: chosenWid,
extraFieldItemValue: normal.content
};
});
}
static extensionEncrypt(body) {
const { algo, key, iv } = _CheckIn.EXTENSION_ENCRYPT;
const cipher = crypto.createCipheriv(algo, key, iv);
let encrypted = cipher.update(JSON.stringify(body), "utf8", "base64");
encrypted += cipher.final("base64");
return encrypted;
}
static formBodyEncrypt(body) {
const { algo, key, iv } = _CheckIn.FORMBODY_ENCRYPT;
const cipher = crypto.createCipheriv(algo, key, iv);
let encrypted = cipher.update(JSON.stringify(body), "utf8", "base64");
encrypted += cipher.final("base64");
return encrypted;
}
};
export let CheckIn = _CheckIn;
CheckIn.VERSION = {
app: "9.0.12",
version: "first_v2",
calVersion: "firstv"
};
CheckIn.EXTENSION_ENCRYPT = {
key: "b3L26XNL",
iv: Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]),
algo: "des-cbc"
};
CheckIn.FORMBODY_ENCRYPT = {
key: "ytUQ7l2ZZu8mLvJZ",
iv: Buffer.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7]),
algo: "aes-128-cbc"
};
export async function checkIn() {
await handleCookie();
const users = sstore.get("users");
if (users == null ? void 0 : users.length) {
const logs = await signIn(users);
if (logs) {
console.table(logs);
}
}
}
async function signIn(users) {
const logs = {};
await Promise.all(users.map(async (i) => {
const instance = new CheckIn(i);
const curTask = await instance.signInfo();
if (curTask) {
const needCheckInTasks = curTask.unSignedTasks.concat(curTask.leaveTasks);
if (needCheckInTasks.length) {
const result = await instance.signWithForm(needCheckInTasks[0]);
logs[i.alias] = result;
} else {
logs[i.alias] = {
[LogInfoKeys.result]: `\u5DF2\u5B8C\u6210\uFF1A${curTask.signedTasks[0].taskName}`
};
}
}
}));
log.notify(`\u7B7E\u5230\u7ED3\u679C =>
${JSON.stringify(logs, null, " ")}`);
return Object.keys(logs).length ? logs : null;
}
//# sourceMappingURL=index.js.map