Download src/api/index.ts from xcolorday/ps: direct link, hf CLI and curl.
- Browser
- Download file 6.29 kB
-
https://huggingface.co/spaces/xcolorday/ps/resolve/main/src/api/index.ts
- Command line
-
hf download hf://spaces/xcolorday/ps/src/api/index.ts
-
curl -L -o index.ts https://huggingface.co/spaces/xcolorday/ps/resolve/main/src/api/index.ts
6.29 kB
| import axios from 'axios'; | |
| import type { SearchResponse } from '@/types'; | |
| const api = axios.create({ | |
| baseURL: '/api', | |
| timeout: 10000 | |
| }); | |
| // 请求拦截器 - 自动添加token | |
| api.interceptors.request.use( | |
| (config) => { | |
| const token = localStorage.getItem('auth_token'); | |
| if (token) { | |
| config.headers.Authorization = `Bearer ${token}`; | |
| } | |
| return config; | |
| }, | |
| (error) => { | |
| return Promise.reject(error); | |
| } | |
| ); | |
| // 响应拦截器 - 处理401 | |
| api.interceptors.response.use( | |
| (response) => response, | |
| (error) => { | |
| if (error.response?.status === 401) { | |
| // 清除token | |
| localStorage.removeItem('auth_token'); | |
| localStorage.removeItem('auth_username'); | |
| // 触发显示登录窗口的事件 | |
| window.dispatchEvent(new CustomEvent('auth:required')); | |
| } | |
| return Promise.reject(error); | |
| } | |
| ); | |
| // 搜索参数接口 | |
| export interface SearchParams { | |
| kw: string; | |
| refresh?: boolean; | |
| res?: 'all' | 'results' | 'merge'; | |
| src?: 'all' | 'tg' | 'plugin'; | |
| plugins?: string; | |
| ext?: string; | |
| } | |
| // API响应包装类型 | |
| interface ApiResponse<T> { | |
| code: number; | |
| message: string; | |
| data: T; | |
| } | |
| // 健康状态接口(基于实际API返回) | |
| export interface HealthStatus { | |
| status: string; | |
| plugins_enabled: boolean; | |
| plugin_count: number; | |
| plugins: string[]; | |
| channels: string[]; | |
| auth_enabled?: boolean; | |
| } | |
| // 登录请求参数 | |
| export interface LoginParams { | |
| username: string; | |
| password: string; | |
| } | |
| // 登录响应 | |
| export interface LoginResponse { | |
| token: string; | |
| expires_at: number; | |
| username: string; | |
| } | |
| // 认证状态 | |
| export interface AuthStatus { | |
| enabled: boolean; | |
| authenticated: boolean; | |
| } | |
| // 获取API健康状态 | |
| export const getHealth = async (): Promise<HealthStatus> => { | |
| try { | |
| const response = await api.get<HealthStatus>('/health'); | |
| return response.data; | |
| } catch (error) { | |
| console.error('获取健康状态失败:', error); | |
| // 返回模拟数据 | |
| return getMockHealthData(); | |
| } | |
| }; | |
| // 模拟健康状态数据 | |
| const getMockHealthData = (): HealthStatus => { | |
| return { | |
| status: "ok", | |
| plugins_enabled: true, | |
| plugin_count: 6, | |
| plugins: ["pansearch", "hdr4k", "shandian", "muou", "duoduo", "labi"], | |
| channels: ["tgsearchers3", "SharePanBaidu", "yunpanxunlei", "tianyifc", "BaiduCloudDisk"] | |
| }; | |
| }; | |
| // 搜索API | |
| export const search = async (params: SearchParams): Promise<SearchResponse> => { | |
| // 添加ext参数,包含referer信息 | |
| const searchParams = { | |
| ...params, | |
| ext: JSON.stringify({ referer: "https://dm.xueximeng.com" }) | |
| }; | |
| // console.log('搜索参数:', searchParams); | |
| try { | |
| const response = await api.get<ApiResponse<SearchResponse>>('/search', { params: searchParams }); | |
| // console.log('API响应:', response.data); | |
| // 如果响应中包含data字段,则返回data | |
| if (response.data && response.data.data) { | |
| // console.log('提取的数据:', response.data.data); | |
| return response.data.data; | |
| } | |
| // 如果响应本身就是SearchResponse格式 | |
| if (response.data && response.data.total !== undefined && response.data.merged_by_type) { | |
| return response.data as unknown as SearchResponse; | |
| } | |
| // 如果都不匹配,使用模拟数据 | |
| console.warn('API响应格式不匹配,使用模拟数据'); | |
| return getMockData(); | |
| } catch (error) { | |
| console.error('API错误:', error); | |
| // 开发阶段使用模拟数据 | |
| // console.log('使用模拟数据'); | |
| return getMockData(); | |
| } | |
| }; | |
| // 模拟数据(开发阶段使用) | |
| const getMockData = (): SearchResponse => { | |
| return { | |
| total: 15, | |
| results: [ | |
| { | |
| message_id: "12345", | |
| unique_id: "channel-12345", | |
| channel: "tgsearchers3", | |
| datetime: "2023-06-10T14:23:45Z", | |
| title: "速度与激情全集1-10", | |
| content: "速度与激情系列全集,1080P高清...", | |
| links: [ | |
| { | |
| type: "baidu", | |
| url: "https://pan.baidu.com/s/1abcdef", | |
| password: "1234" | |
| } | |
| ], | |
| tags: ["电影", "合集"] | |
| } | |
| ], | |
| merged_by_type: { | |
| baidu: [ | |
| { | |
| url: "https://pan.baidu.com/s/1abcdef", | |
| password: "1234", | |
| note: "速度与激情全集1-10", | |
| datetime: "2023-06-10T14:23:45Z", | |
| source: "tgsearchers3" | |
| }, | |
| { | |
| url: "https://pan.baidu.com/s/1ghijkl", | |
| password: "5678", | |
| note: "速度与激情9", | |
| datetime: "2023-05-15T10:20:30Z", | |
| source: "SharePanBaidu" | |
| } | |
| ], | |
| aliyun: [ | |
| { | |
| url: "https://www.aliyundrive.com/s/abcdef", | |
| note: "速度与激情系列合集", | |
| datetime: "2023-07-01T08:15:20Z", | |
| source: "yunpanxunlei" | |
| } | |
| ], | |
| "115": [ | |
| { | |
| url: "https://115.com/s/abcdefg", | |
| password: "abc123", | |
| note: "速度与激情1-10全集高清资源", | |
| datetime: "2023-04-22T16:45:12Z", | |
| source: "pansearch插件" | |
| } | |
| ] | |
| } | |
| }; | |
| }; | |
| // 登录 | |
| export const login = async (params: LoginParams): Promise<LoginResponse> => { | |
| const response = await api.post<LoginResponse>('/auth/login', params); | |
| return response.data; | |
| }; | |
| // 验证token | |
| export const verifyToken = async (): Promise<boolean> => { | |
| try { | |
| await api.post('/auth/verify'); | |
| return true; | |
| } catch { | |
| return false; | |
| } | |
| }; | |
| // 退出登录 | |
| export const logout = async (): Promise<void> => { | |
| try { | |
| await api.post('/auth/logout'); | |
| } finally { | |
| localStorage.removeItem('auth_token'); | |
| localStorage.removeItem('auth_username'); | |
| } | |
| }; | |
| // 检查认证状态 | |
| export const checkAuthStatus = async (): Promise<AuthStatus> => { | |
| try { | |
| const health = await getHealth(); | |
| const authEnabled = health.auth_enabled || false; | |
| const token = localStorage.getItem('auth_token'); | |
| if (!authEnabled) { | |
| return { enabled: false, authenticated: true }; | |
| } | |
| if (!token) { | |
| return { enabled: true, authenticated: false }; | |
| } | |
| const valid = await verifyToken(); | |
| return { enabled: true, authenticated: valid }; | |
| } catch { | |
| return { enabled: false, authenticated: true }; | |
| } | |
| }; | |
| export default api; |