diff --git a/lib/config.ts b/lib/config.ts index 261d3646f97d..c1aa101d1908 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -234,7 +234,8 @@ type ConfigEnvKeys = | 'ZSXQ_ACCESS_TOKEN' | 'SMZDM_COOKIE' | 'REMOTE_CONFIG' - | 'REMOTE_CONFIG_AUTH'; + | 'REMOTE_CONFIG_AUTH' + | 'JAAuthCookie'; export type ConfigEnv = Partial>; @@ -570,6 +571,9 @@ export type Config = { sis001: { baseUrl?: string; }; + sjtu: { + JAAuthCookie?: string; + }; skeb: { bearerToken?: string; }; @@ -1048,6 +1052,9 @@ const calculateValue = () => { sis001: { baseUrl: envs.SIS001_BASE_URL || 'https://sis001.com', }, + sjtu: { + JAAuthCookie: envs.JAAuthCookie, + }, skeb: { bearerToken: envs.SKEB_BEARER_TOKEN, }, diff --git a/lib/routes/sjtu/publicoa.ts b/lib/routes/sjtu/publicoa.ts new file mode 100644 index 000000000000..52f6f317777c --- /dev/null +++ b/lib/routes/sjtu/publicoa.ts @@ -0,0 +1,96 @@ +import { CookieJar } from 'tough-cookie'; + +import { config } from '@/config'; +import ConfigNotFoundError from '@/errors/types/config-not-found'; +import type { Route } from '@/types'; +import ofetch from '@/utils/ofetch'; +import { parseDate } from '@/utils/parse-date'; +import timezone from '@/utils/timezone'; + +const urlRoot = 'https://publicoa.sjtu.edu.cn'; + +export const route: Route = { + path: '/publicoa', + categories: ['university'], + example: '/sjtu/publicoa', + parameters: {}, + features: { + requireConfig: [ + { + name: 'JAAuthCookie', + description: '登录 jaccount.sjtu.edu.cn 后的 JAAuthCookie 值,可在浏览器开发工具的 Cookie 中找到', + }, + ], + requirePuppeteer: false, + antiCrawler: false, + supportBT: false, + supportPodcast: false, + supportScihub: false, + }, + name: '上海交通大学公文系统', + maintainers: ['dzx-dzx'], + handler, + description: `需要用户认证`, +}; + +const cookieJar = new CookieJar(); + +async function handler() { + if (!config.sjtu?.JAAuthCookie) { + throw new ConfigNotFoundError('JAAuthCookie needs to be set to use this route.'); + } + + cookieJar.setCookieSync(`JAAuthCookie=${config.sjtu.JAAuthCookie}; Domain=.jaccount.sjtu.edu.cn; Path=/`, 'https://jaccount.sjtu.edu.cn'); + async function getPublicOAList() { + return await ofetch(`${urlRoot}/api/doc/list`, { + headers: { + cookie: (await cookieJar.getCookieString(urlRoot)) as string, + }, + }); + } + const list: any = await new Promise((resolve) => { + resolve( + getPublicOAList().catch(async (error) => { + if (error.response?.status === 401) { + let requestUrl = urlRoot; + for (let iteration = 10; iteration > 0; iteration--) { + // eslint-disable-next-line no-await-in-loop + const res = await ofetch.raw(requestUrl, { + headers: { + // eslint-disable-next-line no-await-in-loop + cookie: (await cookieJar.getCookieString(requestUrl)) as string, + }, + redirect: 'manual', + }); + const setCookies = res.headers.getSetCookie(); + for (const c of setCookies) { + cookieJar.setCookieSync(c, requestUrl); + } + + if (res.status >= 300 && res.status < 400) { + const location = res.headers.get('location'); + if (typeof location === 'string') { + requestUrl = new URL(location, requestUrl).href; + } + } else { + break; + } + } + return await getPublicOAList(); + } + throw error; + }) + ); + }); + + return { + title: '上海交通大学公文系统', + item: list.entities.map((item) => ({ + title: item.title, + author: item.doccode, + pubDate: timezone(parseDate(item.qfdate), +8), + link: item.pdfpath, + })), + link: urlRoot, + }; +}