@@ -3,6 +3,7 @@ import { calculateRankFromScore } from './converter'
33
44const LXNS_BASE_URL = 'https://maimai.lxns.net/api/v0'
55const SHUIYU_BASE_URL = 'https://www.diving-fish.com/api/chunithmprober'
6+ const WORKER_PROXY = import . meta. env . VITE_WORKER_PROXY_URL || ''
67
78async function fetchJson ( url : string , headers : Record < string , string > ) : Promise < unknown > {
89 const res = await fetch ( url , {
@@ -20,23 +21,13 @@ async function fetchJson(url: string, headers: Record<string, string>): Promise<
2021 return res . json ( )
2122}
2223
23- async function postJson ( url : string , body : Record < string , unknown > ) : Promise < unknown > {
24- const res = await fetch ( url , {
25- method : 'POST' ,
26- headers : { 'Content-Type' : 'application/json' } ,
27- body : JSON . stringify ( body ) ,
28- } )
29-
30- if ( ! res . ok ) {
31- if ( res . status === 400 ) {
32- const data = await res . json ( ) . catch ( ( ) => ( { } ) ) as Record < string , unknown >
33- throw new Error ( ( data [ 'message' ] as string ) || '请求失败' )
34- }
35- if ( res . status === 403 ) throw new Error ( '该用户已设置隐私或未同意用户协议' )
36- throw new Error ( `HTTP ${ res . status } : ${ res . statusText } ` )
37- }
24+ function proxyUrl ( url : string ) : string {
25+ if ( ! WORKER_PROXY ) throw new Error ( '此站点未配置 CORS 代理,水鱼 Import-Token / Developer-Token 模式不可用' )
26+ return `${ WORKER_PROXY } ?url=${ encodeURIComponent ( url ) } `
27+ }
3828
39- return res . json ( )
29+ async function fetchViaProxy ( url : string , headers : Record < string , string > ) : Promise < unknown > {
30+ return fetchJson ( proxyUrl ( url ) , headers )
4031}
4132
4233function parseLxnsPlayer ( data : Record < string , unknown > ) : PlayerInfo {
@@ -136,6 +127,8 @@ export async function fetchFromApi(mode: ApiMode, options: {
136127 lxnsToken ?: string
137128 lxnsDeveloperToken ?: string
138129 lxnsFriendCode ?: number
130+ shuiyuImportToken ?: string
131+ shuiyuDeveloperToken ?: string
139132 shuiyuUsername ?: string
140133 onProgress ?: ( msg : string ) => void
141134} ) : Promise < ApiFetchResult > {
@@ -188,13 +181,30 @@ export async function fetchFromApi(mode: ApiMode, options: {
188181 return { player, scores }
189182 }
190183
191- if ( mode === 'shuiyu' ) {
192- if ( ! options . shuiyuUsername ) throw new Error ( '水鱼查询模式需要用户名' )
184+ if ( mode === 'shuiyu-import' ) {
185+ if ( ! options . shuiyuImportToken ) throw new Error ( '水鱼个人模式需要 Import-Token' )
186+ const headers = { 'Import-Token' : options . shuiyuImportToken }
187+
188+ progress ( '正在通过代理获取玩家成绩...' )
189+ const data = await fetchViaProxy ( `${ SHUIYU_BASE_URL } /player/records` , headers ) as Record < string , unknown >
190+ const player = parseShuiyuPlayer ( data )
191+ const records = ( ( data [ 'records' ] as Record < string , unknown > ) ?. [ 'best' ] || [ ] ) as Record < string , unknown > [ ]
192+ const scores = records . map ( parseShuiyuScore )
193+
194+ progress ( `获取到 ${ scores . length } 条成绩` )
195+ return { player, scores }
196+ }
197+
198+ if ( mode === 'shuiyu-dev' ) {
199+ if ( ! options . shuiyuDeveloperToken ) throw new Error ( '水鱼开发者模式需要 Developer-Token' )
200+ if ( ! options . shuiyuUsername ) throw new Error ( '水鱼开发者模式需要用户名' )
201+ const headers = { 'Developer-Token' : options . shuiyuDeveloperToken }
193202
194- progress ( `正在查询玩家 "${ options . shuiyuUsername } " 的成绩...` )
195- const data = await postJson ( `${ SHUIYU_BASE_URL } /query/player` , {
196- username : options . shuiyuUsername ,
197- } ) as Record < string , unknown >
203+ progress ( `正在通过代理获取玩家 "${ options . shuiyuUsername } " 的成绩...` )
204+ const data = await fetchViaProxy (
205+ `${ SHUIYU_BASE_URL } /dev/player/records?username=${ encodeURIComponent ( options . shuiyuUsername ) } ` ,
206+ headers ,
207+ ) as Record < string , unknown >
198208 const player = parseShuiyuPlayer ( data )
199209 const records = ( ( data [ 'records' ] as Record < string , unknown > ) ?. [ 'best' ] || [ ] ) as Record < string , unknown > [ ]
200210 const scores = records . map ( parseShuiyuScore )
0 commit comments