import { Client } from "@gradio/client"; // Backend local URL //const BACKEND_URL = "http://localhost:7860/"; // 後端 HF Space 名稱 const BACKEND_URL = "My-Project-Team/InfoSecure"; let client: any = null; export const gradioService = { // Get connection instance (singleton pattern) async getClient() { if (!client) { try { client = await Client.connect(BACKEND_URL); } catch (error) { console.error("Failed to connect to Gradio backend:", error); throw new Error("無法連接到後端服務,請檢查網路連線或後端狀態"); } } return client; }, // Unified DataFrame to JSON conversion parseDataFrame(df: any) { if (!df) return []; // Gradio 更新包裝形式 if (df.__type__ === 'update' && df.value) { df = df.value; } // 如果已是陣列物件,直接回傳 if (Array.isArray(df)) { return df; } // 典型 Dataframe 物件 if (df.headers && df.data) { return df.data.map((row: any) => { return df.headers.reduce((obj: any, header: string, index: number) => { obj[header] = row[index]; return obj; }, {}); }); } // 其他格式,嘗試直接轉換為單一物件陣列 if (typeof df === 'object') { return [df]; } return []; }, // Error handling wrapper async handleApiCall(apiCall: () => Promise) { try { return await apiCall(); } catch (error) { console.error("API call failed:", error); throw error; } }, // Core API endpoints // Update dataframes - returns [dataframe1, dataframe2] async updateDataframes() { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/update_dataframes", {}); const dataframe1 = this.parseDataFrame(result.data?.[0]); const dataframe2 = this.parseDataFrame(result.data?.[1]); return { dataframe1, dataframe2 }; }); }, // Timer update - returns [html_content, plot_data] async timerUpdate(selectedKey: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/timer_update", { selected_key: selectedKey }); return { htmlContent: result.data[0], plotData: result.data[1] }; }); }, // Timer update 1 - returns [html_content, plot_data] async timerUpdate1(selectedKey: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/timer_update_1", { selected_key: selectedKey }); return { htmlContent: result.data[0], plotData: result.data[1] }; }); }, // Get plot data - returns plot_data async getPlotData(selectedKey: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/get_plot_data_api", { selected_key: selectedKey }); return result.data[0]; }); }, // Toggle time input - returns custom_time_value async toggleTimeInput(mode: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/toggle_time_input", { mode: mode }); return result.data[0]; }); }, // Explain abnormal log - returns explanation async explainAbnormalLog(logText: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/explain_abnormal_log", { log_text: logText }); return result.data[0]; }); }, // Update system weights - returns result async updateSystemWeights(ow: number, tw: number, iw: number, dw: number, gw: number, fw: number) { try { const c = await this.getClient(); const result = await c.predict("/update_system_weights", { ow: ow, tw: tw, iw: iw, dw: dw, gw: gw, fw: fw }); return result.data?.[0] ?? null; } catch (error: any) { // Gracefully degrade if endpoint doesn't exist or returns status without data if (error && error.endpoint === "/update_system_weights") { console.warn("update_system_weights endpoint not available, skip backend update.", error); return null; } console.error("API call failed:", error); return null; } }, // Process login - returns [markdown1, markdown2, abnormal_log_text] async processLogin(ip: string, cookie: string, account: string, password: string, captcha: string, timeMode: string, customTime: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/process_login", { ip: ip, cookie: cookie, account: account, password: password, captcha: captcha, time_mode: timeMode, custom_time: customTime }); return { markdown1: result.data[0], markdown2: result.data[1], abnormalLogText: result.data[2] }; }); }, // Logout - returns [account, password, captcha, markdown, abnormal_log_text] async logout(ip: string, cookie: string, account: string, timeMode: string, customTime: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/logout", { ip: ip, cookie: cookie, account: account, time_mode: timeMode, custom_time: customTime }); return { account: result.data[0], password: result.data[1], captcha: result.data[2], markdown: result.data[3], abnormalLogText: result.data[4] }; }); }, // Lambda functions (student actions) - all return abnormal_log_text async lambda(ip: string, cookie: string, timeMode: string, customTime: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda", { ip: ip, c: cookie, tm: timeMode, ct: customTime }); return result.data[0]; }); }, async lambda1(ip: string, cookie: string, timeMode: string, customTime: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_1", { ip: ip, c: cookie, tm: timeMode, ct: customTime }); return result.data[0]; }); }, async lambda2(ip: string, cookie: string, account: string, timeMode: string, customTime: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_2", { ip: ip, c: cookie, acc: account, tm: timeMode, ct: customTime }); return result.data[0]; }); }, async lambda3(ip: string, cookie: string, account: string, timeMode: string, customTime: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_3", { ip: ip, c: cookie, acc: account, tm: timeMode, ct: customTime }); return result.data[0]; }); }, async lambda4(ip: string, cookie: string, account: string, timeMode: string, customTime: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_4", { ip: ip, c: cookie, acc: account, tm: timeMode, ct: customTime }); return result.data[0]; }); }, async lambda5(ip: string, cookie: string, account: string, timeMode: string, customTime: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_5", { ip: ip, c: cookie, acc: account, tm: timeMode, ct: customTime }); return result.data[0]; }); }, async lambda6(ip: string, cookie: string, account: string, timeMode: string, customTime: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_6", { ip: ip, c: cookie, acc: account, tm: timeMode, ct: customTime }); return result.data[0]; }); }, async lambda7(ip: string, cookie: string, account: string, timeMode: string, customTime: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_7", { ip: ip, c: cookie, acc: account, tm: timeMode, ct: customTime }); return result.data[0]; }); }, async lambda8(ip: string, cookie: string, account: string, timeMode: string, customTime: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_8", { ip: ip, c: cookie, acc: account, tm: timeMode, ct: customTime }); return result.data[0]; }); }, async lambda9(ip: string, cookie: string, account: string, timeMode: string, customTime: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_9", { ip: ip, c: cookie, acc: account, tm: timeMode, ct: customTime }); return result.data[0]; }); }, async lambda10(ip: string, cookie: string, account: string, timeMode: string, customTime: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_10", { ip: ip, c: cookie, acc: account, tm: timeMode, ct: customTime }); return result.data[0]; }); }, async lambda11(ip: string, cookie: string, account: string, timeMode: string, customTime: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_11", { ip: ip, c: cookie, acc: account, tm: timeMode, ct: customTime }); return result.data[0]; }); }, async lambda12(ip: string, cookie: string, account: string, timeMode: string, customTime: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_12", { ip: ip, c: cookie, acc: account, tm: timeMode, ct: customTime }); return result.data[0]; }); }, async lambda13(ip: string, cookie: string, account: string, timeMode: string, customTime: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_13", { ip: ip, c: cookie, acc: account, tm: timeMode, ct: customTime }); return result.data[0]; }); }, async lambda14(ip: string, cookie: string, account: string, timeMode: string, customTime: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_14", { ip: ip, c: cookie, acc: account, tm: timeMode, ct: customTime }); return result.data[0]; }); }, async lambda15(ip: string, cookie: string, account: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_15", { ip: ip, c: cookie, acc: account }); return result.data[0]; }); }, async lambda16(ip: string, cookie: string, account: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_16", { ip: ip, c: cookie, acc: account }); return result.data[0]; }); }, async lambda17(ip: string, cookie: string, account: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_17", { ip: ip, c: cookie, acc: account }); return result.data[0]; }); }, async lambda18(ip: string, cookie: string, account: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_18", { ip: ip, c: cookie, acc: account }); return result.data[0]; }); }, async lambda19(ip: string, cookie: string, account: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_19", { ip: ip, c: cookie, acc: account }); return result.data[0]; }); }, async lambda20(ip: string, cookie: string, account: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_20", { ip: ip, c: cookie, acc: account }); return result.data[0]; }); }, async lambda21(ip: string, cookie: string, account: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_21", { ip: ip, c: cookie, acc: account }); return result.data[0]; }); }, async lambda22(ip: string, cookie: string, account: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_22", { ip: ip, c: cookie, acc: account }); return result.data[0]; }); }, async lambda23(ip: string, cookie: string, account: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_23", { ip: ip, c: cookie, acc: account }); return result.data[0]; }); }, async lambda24(ip: string, cookie: string, account: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/lambda_24", { ip: ip, c: cookie, acc: account }); return result.data[0]; }); }, // Toggle role - returns [markdown, abnormal_log_text, account] async toggleRole(currentAccount: string, ip: string, cookie: string, timeMode: string, customTime: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/toggle_role", { current_account: currentAccount, ip: ip, cookie: cookie, time_mode: timeMode, custom_time: customTime }); return { markdown: result.data[0], abnormalLogText: result.data[1], account: result.data[2] }; }); }, // Get stats - returns system status and weights async getStats() { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/get_stats", {}); return result.data[0]; }); }, // Get logs - returns latest N logs async getLogs(limit: number = 20) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("/get_logs", { limit: limit }); return result.data[0]; }); }, // Get chart data - returns raw chart data for specific action async getChartData(actionName: string) { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("get_chart_data", { action_name: actionName }); return result.data[0]; }); }, // Get abnormal logs - returns all abnormal logs async getAbnormalLogs() { return this.handleApiCall(async () => { const c = await this.getClient(); const result = await c.predict("get_abnormal_logs", {}); return result.data[0]; }); } };