import {ipcMain, shell} from "electron"; import {AppConfig} from "../../../src/config"; import {ResultType} from "../../lib/api"; import {Events} from "../event/main"; import {platformUUID} from "../../lib/env"; import {AppsMain} from "../app/main"; import Apps from "../app"; import StorageMain from "../storage/main"; import {Log} from "../log/main"; const init = async () => { // 用户功能未启用,跳过自动刷新 console.log('[User.init] 跳过用户信息自动刷新(userEnable=false)'); Log.info('User.init', '跳过用户信息自动刷新(userEnable=false)'); return null; // 注释:原来的代码会调用 refresh() API,但用户功能未启用,所以永久禁用 // setTimeout(() => { // refresh().then(); // }, 1000); }; const userData = { isInit: false, apiToken: "", user: { id: "", name: "", avatar: "", deviceCode: "", }, data: {}, basic: {}, }; const get = async (): Promise<{ apiToken: string; user: { id: string; name: string; avatar: string; deviceCode: string; }; data: { [key: string]: any; }; basic: { [key: string]: any; }; }> => { if (!userData.isInit) { const userStorageData = await StorageMain.get("user", "data", {}); userData.apiToken = userStorageData.apiToken || ""; userData.user = userStorageData.user || {}; userData.data = userStorageData.data || {}; userData.basic = userStorageData.basic || {}; userData.isInit = true; } userData.user.id = userData.user.id || ""; return { apiToken: userData.apiToken, user: userData.user, data: userData.data, basic: userData.basic, }; }; ipcMain.handle( "user:open", async ( event, option?: { readyParam: { page?: string; [key: string]: any; }; } ) => { option = Object.assign( { readyParam: null, }, option || {} ); await AppsMain.windowOpen("user", option); if (option.readyParam) { await Events.callPage("user", "ready", option.readyParam); } } ); ipcMain.handle("user:get", async event => { return get(); }); const save = async (data: {apiToken: string; user: any; data: any; basic: {}}) => { userData.apiToken = data.apiToken || ""; userData.user = data.user || {}; userData.data = data.data || {}; userData.user.id = userData.user.id || ""; Events.broadcast("UserChange", {}); await StorageMain.set("user", "data", { apiToken: data.apiToken, user: data.user, data: data.data, basic: data.basic, }); }; ipcMain.handle("user:save", async (event, data) => { return save(data); }); const refresh = async () => { const result = await userInfoApi(); // console.log("user.refresh", JSON.stringify(result, null, 2)); await save({ apiToken: result.data.apiToken, user: result.data.user, data: result.data.data, basic: result.data.basic, }); }; ipcMain.handle("user:refresh", async event => { return refresh(); }); const getApiToken = async (): Promise => { await get(); return userData.apiToken; }; ipcMain.handle("user:getApiToken", async event => { return getApiToken(); }); const getWebEnterUrl = async (url: string) => { let param = []; const apiToken = await getApiToken(); if (apiToken) { param.push(`api_token=${apiToken}`); } if (await AppsMain.shouldDarkMode()) { param.push(`is_dark=1`); } param.push(`device_uuid=${platformUUID()}`); param.push(`url=${encodeURIComponent(url)}`); return `${AppConfig.apiBaseUrl}/app_manager/enter?${param.join("&")}`; }; ipcMain.handle("user:getWebEnterUrl", async (event, url) => { return getWebEnterUrl(url); }); const openWebUrl = async (url: string) => { url = await getWebEnterUrl(url); await shell.openExternal(url); }; ipcMain.handle("user:openWebUrl", async (event, url) => { return openWebUrl(url); }); const apiPost = async ( url: string, data: Record, option?: { throwException?: boolean; } ) => { return post(url, data, option); }; ipcMain.handle("user:apiPost", async (event, url, data, option) => { return apiPost(url, data, option); }); export const User = { init, get, save, getApiToken, getWebEnterUrl, openWebUrl, }; export default User; const post = async ( api: string, data: Record, option?: { throwException?: boolean; retry?: number; retryTimes?: number; retryInterval?: number; } ): Promise> => { option = Object.assign( { throwException: true, retry: 0, retryTimes: 0, retryInterval: 5, }, option ); let url = api; if (!api.startsWith("http:") && !api.startsWith("https:")) { url = `${AppConfig.apiBaseUrl}/${api}`; } const apiToken = await User.getApiToken(); let json = null, res = null; try { res = await fetch(url, { method: "POST", headers: { "User-Agent": Apps.getUserAgent(), "Content-Type": "application/json", "Api-Token": apiToken, }, body: JSON.stringify(data), }); if (res.status !== 200) { if (option.retry > 0 && option.retryTimes < option.retry) { option.retryTimes++; Log.info("user.post.retry", {api, data, res, retryTimes: option.retryTimes}); await new Promise(resolve => setTimeout(resolve, option.retryInterval * 1000)); return await post(api, data, option); } Log.error("user.post.error", {api, data, res}); if (option.throwException) { throw `RequestError(code:${res.status},text:${res.statusText})`; } return { code: 10000, msg: `RequestError(code:${res.status},text:${res.statusText})`, } as ResultType; } json = await res.json(); } catch (e) { res = `RequestError(${e})`; } // console.log('post', JSON.stringify({api, data, json}, null, 2)) if (!json || !("code" in json)) { if (option.retry > 0 && option.retryTimes < option.retry) { option.retryTimes++; Log.info("user.post.retry", {api, data, res, retryTimes: option.retryTimes}); await new Promise(resolve => setTimeout(resolve, option.retryInterval * 1000)); return await post(api, data, option); } Log.error("user.post.error", {api, data, res}); if (option.throwException) { throw "ResponseError"; } return {code: 10000, msg: "ResponseError"}; } if (json.code) { // login required if (json.code === 1001) { if (userData.user && userData.user.id) { await refresh(); } } if (option.throwException) { throw json.msg; } } return json; }; const userInfoApi = async (): Promise< ResultType<{ apiToken: string; user: object; data: any; basic: object; }> > => { return await post("app_manager/user_info", {}); }; export const UserApi = { post, userInfoApi, };