rsshub
Version:
Make RSS Great Again!
200 lines (199 loc) • 5.49 kB
JavaScript
import { t as rofetch } from "./ofetch-eUBdfMpp.mjs";
import { n as generateHeaders } from "./header-generator-DACPoxdp.mjs";
import { createHash } from "node:crypto";
import { load } from "cheerio";
//#region lib/routes/ichunqiu/jsl.ts
const toPrimitive = (v) => Array.isArray(v) ? v.join(",") : typeof v === "object" ? "[object Object]" : v;
const binaryPrecedence = {
"|": 1,
"^": 2,
"&": 3,
"<<": 4,
">>": 4,
"+": 5,
"-": 5,
"*": 6,
"/": 6,
"%": 6
};
const evaluateJsl = (source) => {
let pos = 0;
const skipSpaces = () => {
while (source[pos] === " ") pos++;
};
const expect = (char) => {
skipSpaces();
if (source[pos++] !== char) throw new Error(`Expected ${char} at ${pos - 1} in JSL expression`);
};
const primary = () => {
skipSpaces();
const char = source[pos];
if (char === "(") {
pos++;
const value = expression(0);
expect(")");
return value;
}
if (char === "'") {
const end = source.indexOf("'", pos + 1);
const value = source.slice(pos + 1, end);
pos = end + 1;
return value;
}
if (char === "[") {
pos++;
skipSpaces();
if (source[pos] === "]") {
pos++;
return [];
}
const value = expression(0);
expect("]");
return [value];
}
if (char === "{") {
pos++;
expect("}");
return {};
}
if (source.startsWith("true", pos)) {
pos += 4;
return true;
}
if (source.startsWith("false", pos)) {
pos += 5;
return false;
}
const digits = /^\d+/.exec(source.slice(pos));
if (digits) {
pos += digits[0].length;
return Number(digits[0]);
}
throw new Error(`Unexpected ${JSON.stringify(char)} at ${pos} in JSL expression`);
};
const unary = () => {
skipSpaces();
const op = source[pos];
if (op !== void 0 && "-+~!".includes(op)) {
pos++;
const value = unary();
switch (op) {
case "-": return -Number(toPrimitive(value));
case "+": return Number(toPrimitive(value));
case "~": return ~Number(toPrimitive(value));
default: return !value;
}
}
return primary();
};
const readBinaryOperator = () => {
skipSpaces();
const two = source.slice(pos, pos + 2);
if (two === "<<" || two === ">>") return two;
const one = source[pos];
return one && binaryPrecedence[one] === void 0 ? void 0 : one;
};
const applyBinary = (op, left, right) => {
const a = toPrimitive(left);
const b = toPrimitive(right);
if (op === "+") return typeof a === "string" || typeof b === "string" ? `${a}${b}` : Number(a) + Number(b);
const x = Number(a);
const y = Number(b);
switch (op) {
case "-": return x - y;
case "*": return x * y;
case "/": return x / y;
case "%": return x % y;
case "<<": return x << y;
case ">>": return x >> y;
case "&": return x & y;
case "^": return x ^ y;
default: return x | y;
}
};
const expression = (minPrecedence) => {
let left = unary();
let op = readBinaryOperator();
while (op && binaryPrecedence[op] >= minPrecedence) {
pos += op.length;
left = applyBinary(op, left, expression(binaryPrecedence[op] + 1));
op = readBinaryOperator();
}
return left;
};
const result = expression(0);
skipSpaces();
if (pos !== source.length) throw new Error(`Unexpected trailing input at ${pos} in JSL expression`);
return String(toPrimitive(result));
};
//#endregion
//#region lib/routes/ichunqiu/index.ts
const route = {
path: "/",
categories: ["programming"],
example: "/ichunqiu",
features: { antiCrawler: true },
name: "资讯",
maintainers: ["8430177"],
handler
};
const solveJsl = ({ bts, chars, ct, ha }) => {
for (const a of chars) for (const b of chars) {
const answer = bts[0] + a + b + bts[1];
if (createHash(ha).update(answer).digest("hex") === ct) return answer;
}
throw new Error("Failed to solve __jsl_clearance_s");
};
async function handler() {
const baseSite = "https://bbs.ichunqiu.com/";
const link = `${baseSite}portal.php`;
const cookies = /* @__PURE__ */ new Map();
const headers = generateHeaders();
const fetchPage = async () => {
const response = await rofetch.raw(link, {
headers: {
...headers,
cookie: [...cookies].map(([name, value]) => `${name}=${value}`).join("; ")
},
ignoreResponseError: true,
responseType: "text"
});
for (const cookie of response.headers.getSetCookie()) {
const [name, value] = cookie.split(";", 1)[0].split("=", 2);
cookies.set(name, value);
}
return response._data;
};
let body = await fetchPage();
for (let round = 0; round < 5 && !body.includes("class=\"module"); round++) {
const assignment = body.match(/document\.cookie=(.+?);location\.href/s);
const challenge = body.match(/go\((\{.+?\})\)/s);
if (assignment) {
const [name, value] = evaluateJsl(assignment[1]).split(";", 1)[0].split("=", 2);
cookies.set(name, value);
} else if (challenge) {
const puzzle = JSON.parse(challenge[1]);
cookies.set(puzzle.tn, solveJsl(puzzle));
} else throw new Error("Unrecognized response");
body = await fetchPage();
}
const $ = load(body);
return {
title: "i春秋学院 ~ 资讯",
link: baseSite,
description: "i春秋学院 ~ 资讯",
item: $(".module dl").toArray().map((item) => {
const $item = $(item);
const a = $item.find("dt a[title]");
const title = a.attr("title");
if (!title) return;
return {
title,
link: new URL(a.attr("href"), baseSite).href,
description: $item.find("dd:not(.m)").text().trim()
};
}).filter((item) => item !== void 0)
};
}
//#endregion
export { route };