147 lines
4.2 KiB
TypeScript
147 lines
4.2 KiB
TypeScript
import { userApis as defaultUserApis } from './config'
|
|
import { STORE_NAMES } from '@common/constants'
|
|
import getStore from '@main/utils/store'
|
|
import zlib from 'node:zlib'
|
|
|
|
let userApis: LX.UserApi.UserApiInfo[] | null
|
|
let scripts = new Map<string, string>()
|
|
|
|
const saveData = () => {
|
|
getStore(STORE_NAMES.USER_API).set('userApis', userApis!.map(api => {
|
|
return {
|
|
...api,
|
|
script: scripts.get(api.id),
|
|
}
|
|
}))
|
|
}
|
|
|
|
export const getUserApis = (): LX.UserApi.UserApiInfo[] => {
|
|
if (userApis) return userApis
|
|
|
|
const electronStore_userApi = getStore(STORE_NAMES.USER_API)
|
|
let infoFull = electronStore_userApi.get('userApis') as LX.UserApi.UserApiInfoFull[]
|
|
let requiredUpdate = false
|
|
if (infoFull) {
|
|
for (let i = 0; i < infoFull.length; i++) {
|
|
const api = infoFull[i]
|
|
if (api.version != null) continue
|
|
requiredUpdate ||= true
|
|
try {
|
|
infoFull.splice(i, 1, {
|
|
...parseScriptInfo(api.script),
|
|
...api,
|
|
})
|
|
} catch (e) {
|
|
infoFull.splice(i, 1)
|
|
i--
|
|
}
|
|
}
|
|
} else {
|
|
infoFull = defaultUserApis
|
|
electronStore_userApi.set('userApis', userApis)
|
|
}
|
|
userApis = infoFull.map(api => {
|
|
if (api.allowShowUpdateAlert == null) api.allowShowUpdateAlert = false
|
|
const { script, ...info } = api
|
|
scripts.set(api.id, script)
|
|
return info
|
|
})
|
|
if (requiredUpdate) saveData()
|
|
return userApis
|
|
}
|
|
|
|
const INFO_NAMES = {
|
|
name: 24,
|
|
description: 36,
|
|
author: 56,
|
|
homepage: 1024,
|
|
version: 36,
|
|
} as const
|
|
type INFO_NAMES_Type = typeof INFO_NAMES
|
|
const matchInfo = (scriptInfo: string) => {
|
|
const infoArr = scriptInfo.split(/\r?\n/)
|
|
const rxp = /^\s?\*\s?@(\w+)\s(.+)$/
|
|
const infos: Partial<Record<keyof typeof INFO_NAMES, string>> = {}
|
|
for (const info of infoArr) {
|
|
const result = rxp.exec(info)
|
|
if (!result) continue
|
|
const key = result[1] as keyof typeof INFO_NAMES
|
|
if (INFO_NAMES[key] == null) continue
|
|
infos[key] = result[2].trim()
|
|
}
|
|
|
|
for (const [key, len] of Object.entries(INFO_NAMES) as Array<{ [K in keyof INFO_NAMES_Type]: [K, INFO_NAMES_Type[K]] }[keyof INFO_NAMES_Type]>) {
|
|
infos[key] ||= ''
|
|
if (infos[key] == null) infos[key] = ''
|
|
else if (infos[key]!.length > len) infos[key] = infos[key]!.substring(0, len) + '...'
|
|
}
|
|
|
|
return infos as Record<keyof typeof INFO_NAMES, string>
|
|
}
|
|
const parseScriptInfo = (script: string) => {
|
|
const result = /^\/\*[\S|\s]+?\*\//.exec(script)
|
|
if (!result) throw new Error('无效的自定义源文件')
|
|
|
|
let scriptInfo = matchInfo(result[0])
|
|
|
|
scriptInfo.name ||= `user_api_${new Date().toLocaleString()}`
|
|
return scriptInfo
|
|
}
|
|
const deflateScript = async(script: string) => new Promise<string>((resolve, reject) => {
|
|
zlib.deflate(Buffer.from(script, 'utf8'), (err, buf) => {
|
|
if (err) {
|
|
reject(err)
|
|
return
|
|
}
|
|
resolve('gz_' + buf.toString('base64'))
|
|
})
|
|
})
|
|
const inflateScript = async(script: string) => new Promise<string>((resolve, reject) => {
|
|
if (script.startsWith('gz_')) {
|
|
zlib.inflate(Buffer.from(script.substring(3), 'base64'), (err, buf) => {
|
|
if (err) {
|
|
reject(err)
|
|
return
|
|
}
|
|
resolve(buf.toString('utf8'))
|
|
})
|
|
} else resolve(script)
|
|
})
|
|
export const importApi = async(scriptRaw: string): Promise<LX.UserApi.UserApiInfo> => {
|
|
let scriptInfo = parseScriptInfo(scriptRaw)
|
|
const apiInfo = {
|
|
id: `user_api_${Math.random().toString().substring(2, 5)}_${Date.now()}`,
|
|
...scriptInfo,
|
|
allowShowUpdateAlert: true,
|
|
}
|
|
userApis ??= []
|
|
userApis.push(apiInfo)
|
|
const script = await deflateScript(scriptRaw)
|
|
scripts.set(apiInfo.id, script)
|
|
saveData()
|
|
return apiInfo
|
|
}
|
|
|
|
export const removeApi = (ids: string[]) => {
|
|
if (!userApis) return
|
|
for (let index = userApis.length - 1; index > -1; index--) {
|
|
if (ids.includes(userApis[index].id)) {
|
|
scripts.delete(userApis[index].id)
|
|
userApis.splice(index, 1)
|
|
ids.splice(index, 1)
|
|
}
|
|
}
|
|
saveData()
|
|
}
|
|
|
|
export const setAllowShowUpdateAlert = (id: string, enable: boolean) => {
|
|
const targetApi = userApis?.find(api => api.id == id)
|
|
if (!targetApi) return
|
|
targetApi.allowShowUpdateAlert = enable
|
|
saveData()
|
|
}
|
|
|
|
export const getScript = async(id: string) => {
|
|
return inflateScript(scripts.get(id) ?? '')
|
|
}
|