-
Notifications
You must be signed in to change notification settings - Fork 9.5k
feat(route/sjtu): Add route for Public OA #20967
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 5 commits
8ed1a6d
cf622cd
91591e9
a44bd9b
17f3175
dc11625
3e17921
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -234,7 +234,8 @@ type ConfigEnvKeys = | |
| | 'ZSXQ_ACCESS_TOKEN' | ||
| | 'SMZDM_COOKIE' | ||
| | 'REMOTE_CONFIG' | ||
| | 'REMOTE_CONFIG_AUTH'; | ||
| | 'REMOTE_CONFIG_AUTH' | ||
| | 'JAAuthCookie'; | ||
|
|
||
| export type ConfigEnv = Partial<Record<ConfigEnvKeys, string | undefined>>; | ||
|
|
||
|
|
@@ -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, | ||
| }, | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,95 @@ | ||||||||||||||||||||||||
| import { CookieJar } from 'tough-cookie'; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| import { config } from '@/config'; | ||||||||||||||||||||||||
| import type { Route } from '@/types'; | ||||||||||||||||||||||||
| import ofetch from '@/utils/ofetch'; | ||||||||||||||||||||||||
| import { parseDate } from '@/utils/parse-date'; | ||||||||||||||||||||||||
| import timezone from '@/utils/timezone'; | ||||||||||||||||||||||||
| import ConfigNotFoundError from '@/errors/types/config-not-found'; | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| const urlRoot = 'https://publicoa.sjtu.edu.cn'; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| export const route: Route = { | ||||||||||||||||||||||||
| path: '/publicoa', | ||||||||||||||||||||||||
| categories: ['university'], | ||||||||||||||||||||||||
| example: '/sjtu/publicoa', | ||||||||||||||||||||||||
| parameters: {}, | ||||||||||||||||||||||||
| features: { | ||||||||||||||||||||||||
| requireConfig: [ | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| name: 'JAAuthCookie', | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
| description: 'JAAuthCookie, 登陆后提取自jaccount.sjtu.edu.cn', | ||||||||||||||||||||||||
dzx-dzx marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||
| requirePuppeteer: false, | ||||||||||||||||||||||||
| antiCrawler: false, | ||||||||||||||||||||||||
| supportBT: false, | ||||||||||||||||||||||||
| supportPodcast: false, | ||||||||||||||||||||||||
| supportScihub: false, | ||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||
| name: '上海交通大学公文系统', | ||||||||||||||||||||||||
| maintainers: ['dzx-dzx'], | ||||||||||||||||||||||||
| handler, | ||||||||||||||||||||||||
| description: `需要用户认证`, | ||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| const cookieJar = new CookieJar(); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| async function handler() { | ||||||||||||||||||||||||
|
Comment on lines
+36
to
+38
|
||||||||||||||||||||||||
| const cookieJar = new CookieJar(); | |
| async function handler() { | |
| async function handler() { | |
| const cookieJar = new CookieJar(); |
Copilot
AI
Feb 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Module-level cookieJar should be avoided as it creates a shared state between requests in a concurrent environment. Each request handler should create its own cookieJar instance to avoid cookie leakage between different users or concurrent requests. Move the cookieJar instantiation into the handler function.
| const cookieJar = new CookieJar(); | |
| async function handler() { | |
| async function handler() { | |
| const cookieJar = new CookieJar(); |
Copilot
AI
Feb 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handler functions in RSSHub routes conventionally accept a 'ctx' parameter containing request context, even if unused. This is seen in lib/routes/sjtu/gs.ts:49 and lib/routes/sjtu/jwc.ts:55. While not strictly necessary when no parameters are needed, omitting it breaks the established pattern and could cause issues if the route metadata is extended to include parameters later.
Copilot
AI
Feb 5, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The type annotation 'any' is too permissive and defeats TypeScript's type checking benefits. Based on the usage, this should have a proper type that includes an 'entities' array property with items that have 'title', 'doccode', 'qfdate', and 'pdfpath' fields. Define an interface or type for the API response structure.
Check warning
Code scanning / oxlint
github(no-then) Warning
Check failure
Code scanning / ESLint
Disallow `await` inside of loops
Check failure
Code scanning / ESLint
Disallow `await` inside of loops
Outdated
Copilot
AI
Jan 25, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error response handling in this redirect loop doesn't handle cases where the authentication flow fails completely or where redirects might be malicious. The loop should include a maximum iteration count to prevent infinite loops and should validate redirect URLs before following them.
Copilot
AI
Jan 25, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the initial API request at line 44 doesn't return a 401 error but fails in some other way (network error, timeout, 500 error, etc.), the promise will resolve with undefined. This will cause a runtime error at line 86 when trying to access list.entities. The error handling should be expanded to handle all failure cases, not just 401 authentication errors.
| } | |
| } | |
| throw error; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Environment variable names in this codebase follow SCREAMING_SNAKE_CASE convention (e.g., 'NCM_COOKIES', 'SKEB_BEARER_TOKEN', 'SPOTIFY_CLIENT_ID'). The 'JAAuthCookie' variable uses mixed camelCase which is inconsistent. It should be 'SJTU_JA_AUTH_COOKIE' or 'JA_AUTH_COOKIE' to match the established pattern. This affects both the ConfigEnvKeys type and the usage in calculateValue.