mirror of
https://gh.catmak.name/https://github.com/mihomo-party-org/mihomo-party
synced 2025-12-26 20:50:30 +08:00
refactor: migrate external HTTP requests from Node.js to Chromium network stack
(cherry picked from commit ad96c558a3d46c79848e2c9e469673c7e7f68e25)
This commit is contained in:
parent
98be9d3065
commit
80b59fc9de
3
.gitignore
vendored
3
.gitignore
vendored
@ -8,4 +8,5 @@ out
|
||||
*.log*
|
||||
.idea
|
||||
*.ttf
|
||||
party.md
|
||||
party.md
|
||||
CLAUDE.md
|
||||
@ -2,7 +2,7 @@ import { overrideConfigPath, overridePath } from '../utils/dirs'
|
||||
import { getControledMihomoConfig } from './controledMihomo'
|
||||
import { readFile, writeFile, rm } from 'fs/promises'
|
||||
import { existsSync } from 'fs'
|
||||
import axios from 'axios'
|
||||
import * as chromeRequest from '../utils/chromeRequest'
|
||||
import { parse, stringify } from '../utils/yaml'
|
||||
|
||||
let overrideConfig: IOverrideConfig // override.yaml
|
||||
@ -70,7 +70,7 @@ export async function createOverride(item: Partial<IOverrideItem>): Promise<IOve
|
||||
case 'remote': {
|
||||
const { 'mixed-port': mixedPort = 7890 } = await getControledMihomoConfig()
|
||||
if (!item.url) throw new Error('Empty URL')
|
||||
const res = await axios.get(item.url, {
|
||||
const res = await chromeRequest.get(item.url, {
|
||||
proxy: {
|
||||
protocol: 'http',
|
||||
host: '127.0.0.1',
|
||||
|
||||
@ -5,7 +5,7 @@ import { readFile, rm, writeFile } from 'fs/promises'
|
||||
import { restartCore } from '../core/manager'
|
||||
import { getAppConfig } from './app'
|
||||
import { existsSync } from 'fs'
|
||||
import axios, { AxiosResponse } from 'axios'
|
||||
import * as chromeRequest from '../utils/chromeRequest'
|
||||
import { parse, stringify } from '../utils/yaml'
|
||||
import { defaultProfile } from '../utils/template'
|
||||
import { subStorePort } from '../resolve/server'
|
||||
@ -148,7 +148,7 @@ export async function createProfile(item: Partial<IProfileItem>): Promise<IProfi
|
||||
const { userAgent, subscriptionTimeout = 30000 } = await getAppConfig()
|
||||
const { 'mixed-port': mixedPort = 7890 } = await getControledMihomoConfig()
|
||||
if (!item.url) throw new Error('Empty URL')
|
||||
let res: AxiosResponse
|
||||
let res: chromeRequest.Response<string>
|
||||
if (newItem.substore) {
|
||||
const urlObj = new URL(`http://127.0.0.1:${subStorePort}${item.url}`)
|
||||
urlObj.searchParams.set('target', 'ClashMeta')
|
||||
@ -158,7 +158,7 @@ export async function createProfile(item: Partial<IProfileItem>): Promise<IProfi
|
||||
} else {
|
||||
urlObj.searchParams.delete('proxy')
|
||||
}
|
||||
res = await axios.get(urlObj.toString(), {
|
||||
res = await chromeRequest.get(urlObj.toString(), {
|
||||
headers: {
|
||||
'User-Agent': userAgent || `mihomo.party/v${app.getVersion()} (clash.meta)`
|
||||
},
|
||||
@ -166,7 +166,7 @@ export async function createProfile(item: Partial<IProfileItem>): Promise<IProfi
|
||||
timeout: subscriptionTimeout
|
||||
})
|
||||
} else {
|
||||
res = await axios.get(item.url, {
|
||||
res = await chromeRequest.get(item.url, {
|
||||
proxy: newItem.useProxy
|
||||
? {
|
||||
protocol: 'http',
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
import axios from 'axios'
|
||||
import * as chromeRequest from '../utils/chromeRequest'
|
||||
import { subStorePort } from '../resolve/server'
|
||||
import { getAppConfig } from '../config'
|
||||
|
||||
export async function subStoreSubs(): Promise<ISubStoreSub[]> {
|
||||
const { useCustomSubStore = false, customSubStoreUrl = '' } = await getAppConfig()
|
||||
const baseUrl = useCustomSubStore ? customSubStoreUrl : `http://127.0.0.1:${subStorePort}`
|
||||
const res = await axios.get(`${baseUrl}/api/subs`, { responseType: 'json' })
|
||||
const res = await chromeRequest.get(`${baseUrl}/api/subs`, { responseType: 'json' })
|
||||
return res.data.data as ISubStoreSub[]
|
||||
}
|
||||
|
||||
export async function subStoreCollections(): Promise<ISubStoreSub[]> {
|
||||
const { useCustomSubStore = false, customSubStoreUrl = '' } = await getAppConfig()
|
||||
const baseUrl = useCustomSubStore ? customSubStoreUrl : `http://127.0.0.1:${subStorePort}`
|
||||
const res = await axios.get(`${baseUrl}/api/collections`, { responseType: 'json' })
|
||||
const res = await chromeRequest.get(`${baseUrl}/api/collections`, { responseType: 'json' })
|
||||
return res.data.data as ISubStoreSub[]
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import axios from 'axios'
|
||||
import * as chromeRequest from '../utils/chromeRequest'
|
||||
import { parse } from '../utils/yaml'
|
||||
import { app, shell } from 'electron'
|
||||
import { getControledMihomoConfig } from '../config'
|
||||
@ -14,7 +14,7 @@ import { checkAdminPrivileges } from '../core/manager'
|
||||
|
||||
export async function checkUpdate(): Promise<IAppVersion | undefined> {
|
||||
const { 'mixed-port': mixedPort = 7890 } = await getControledMihomoConfig()
|
||||
const res = await axios.get(
|
||||
const res = await chromeRequest.get(
|
||||
'https://github.com/mihomo-party-org/mihomo-party/releases/latest/download/latest.yml',
|
||||
{
|
||||
headers: { 'Content-Type': 'application/octet-stream' },
|
||||
@ -83,7 +83,7 @@ export async function downloadAndInstallUpdate(version: string): Promise<void> {
|
||||
}
|
||||
try {
|
||||
if (!existsSync(path.join(dataDir(), file))) {
|
||||
const res = await axios.get(`${baseUrl}${file}`, {
|
||||
const res = await chromeRequest.get(`${baseUrl}${file}`, {
|
||||
responseType: 'arraybuffer',
|
||||
proxy: {
|
||||
protocol: 'http',
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import axios from 'axios'
|
||||
import * as chromeRequest from '../utils/chromeRequest'
|
||||
import { getAppConfig, getControledMihomoConfig } from '../config'
|
||||
import { getRuntimeConfigStr } from '../core/factory'
|
||||
|
||||
@ -10,7 +10,7 @@ interface GistInfo {
|
||||
|
||||
async function listGists(token: string): Promise<GistInfo[]> {
|
||||
const { 'mixed-port': port = 7890 } = await getControledMihomoConfig()
|
||||
const res = await axios.get('https://api.github.com/gists', {
|
||||
const res = await chromeRequest.get('https://api.github.com/gists', {
|
||||
headers: {
|
||||
Accept: 'application/vnd.github+json',
|
||||
Authorization: `Bearer ${token}`,
|
||||
@ -28,7 +28,7 @@ async function listGists(token: string): Promise<GistInfo[]> {
|
||||
|
||||
async function createGist(token: string, content: string): Promise<void> {
|
||||
const { 'mixed-port': port = 7890 } = await getControledMihomoConfig()
|
||||
return await axios.post(
|
||||
await chromeRequest.post(
|
||||
'https://api.github.com/gists',
|
||||
{
|
||||
description: 'Auto Synced Clash Party Runtime Config',
|
||||
@ -52,7 +52,7 @@ async function createGist(token: string, content: string): Promise<void> {
|
||||
|
||||
async function updateGist(token: string, id: string, content: string): Promise<void> {
|
||||
const { 'mixed-port': port = 7890 } = await getControledMihomoConfig()
|
||||
return await axios.patch(
|
||||
await chromeRequest.patch(
|
||||
`https://api.github.com/gists/${id}`,
|
||||
{
|
||||
description: 'Auto Synced Clash Party Runtime Config',
|
||||
|
||||
@ -9,7 +9,7 @@ import net from 'net'
|
||||
import path from 'path'
|
||||
import { nativeImage } from 'electron'
|
||||
import express from 'express'
|
||||
import axios from 'axios'
|
||||
import * as chromeRequest from '../utils/chromeRequest'
|
||||
import AdmZip from 'adm-zip'
|
||||
import { systemLogger } from '../utils/logger'
|
||||
|
||||
@ -155,7 +155,7 @@ export async function downloadSubStore(): Promise<void> {
|
||||
|
||||
// 下载后端文件
|
||||
const tempBackendPath = path.join(tempDir, 'sub-store.bundle.cjs')
|
||||
const backendRes = await axios.get(
|
||||
const backendRes = await chromeRequest.get(
|
||||
'https://github.com/sub-store-org/Sub-Store/releases/latest/download/sub-store.bundle.js',
|
||||
{
|
||||
responseType: 'arraybuffer',
|
||||
@ -167,9 +167,9 @@ export async function downloadSubStore(): Promise<void> {
|
||||
}
|
||||
}
|
||||
)
|
||||
await writeFile(tempBackendPath, Buffer.from(backendRes.data))
|
||||
await writeFile(tempBackendPath, Buffer.from(backendRes.data as Buffer))
|
||||
// 下载前端文件
|
||||
const frontendRes = await axios.get(
|
||||
const frontendRes = await chromeRequest.get(
|
||||
'https://github.com/sub-store-org/Sub-Store-Front-End/releases/latest/download/dist.zip',
|
||||
{
|
||||
responseType: 'arraybuffer',
|
||||
@ -182,7 +182,7 @@ export async function downloadSubStore(): Promise<void> {
|
||||
}
|
||||
)
|
||||
// 先解压到临时目录
|
||||
const zip = new AdmZip(Buffer.from(frontendRes.data))
|
||||
const zip = new AdmZip(Buffer.from(frontendRes.data as Buffer))
|
||||
zip.extractAllTo(tempDir, true)
|
||||
await cp(tempBackendPath, backendPath)
|
||||
if (existsSync(frontendDir)) {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { copyFile, readdir, readFile, writeFile } from 'fs/promises'
|
||||
import { themesDir } from '../utils/dirs'
|
||||
import path from 'path'
|
||||
import axios from 'axios'
|
||||
import * as chromeRequest from '../utils/chromeRequest'
|
||||
import AdmZip from 'adm-zip'
|
||||
import { getControledMihomoConfig } from '../config'
|
||||
import { existsSync } from 'fs'
|
||||
@ -36,7 +36,7 @@ export async function resolveThemes(): Promise<{ key: string; label: string }[]>
|
||||
export async function fetchThemes(): Promise<void> {
|
||||
const zipUrl = 'https://github.com/mihomo-party-org/theme-hub/releases/download/latest/themes.zip'
|
||||
const { 'mixed-port': mixedPort = 7890 } = await getControledMihomoConfig()
|
||||
const zipData = await axios.get(zipUrl, {
|
||||
const zipData = await chromeRequest.get(zipUrl, {
|
||||
responseType: 'arraybuffer',
|
||||
headers: { 'Content-Type': 'application/octet-stream' },
|
||||
proxy: {
|
||||
@ -45,7 +45,7 @@ export async function fetchThemes(): Promise<void> {
|
||||
port: mixedPort
|
||||
}
|
||||
})
|
||||
const zip = new AdmZip(zipData.data as Buffer)
|
||||
const zip = new AdmZip(Buffer.from(zipData.data as Buffer))
|
||||
zip.extractAllTo(themesDir(), true)
|
||||
}
|
||||
|
||||
|
||||
252
src/main/utils/chromeRequest.ts
Normal file
252
src/main/utils/chromeRequest.ts
Normal file
@ -0,0 +1,252 @@
|
||||
import { net, session } from 'electron'
|
||||
|
||||
export interface RequestOptions {
|
||||
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'
|
||||
headers?: Record<string, string>
|
||||
body?: string | Buffer
|
||||
proxy?: {
|
||||
protocol: 'http' | 'https' | 'socks5'
|
||||
host: string
|
||||
port: number
|
||||
} | false
|
||||
timeout?: number
|
||||
responseType?: 'text' | 'json' | 'arraybuffer'
|
||||
followRedirect?: boolean
|
||||
maxRedirects?: number
|
||||
}
|
||||
|
||||
export interface Response<T = any> {
|
||||
data: T
|
||||
status: number
|
||||
statusText: string
|
||||
headers: Record<string, string>
|
||||
url: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Make HTTP request using Chromium's network stack (via electron.net)
|
||||
* This provides better compatibility, HTTP/2 support, and system certificate integration
|
||||
*/
|
||||
export async function request<T = any>(
|
||||
url: string,
|
||||
options: RequestOptions = {}
|
||||
): Promise<Response<T>> {
|
||||
const {
|
||||
method = 'GET',
|
||||
headers = {},
|
||||
body,
|
||||
proxy,
|
||||
timeout = 30000,
|
||||
responseType = 'text',
|
||||
followRedirect = true,
|
||||
maxRedirects = 20
|
||||
} = options
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let sessionToUse = session.defaultSession
|
||||
let tempPartition: string | null = null
|
||||
|
||||
// Set up proxy if specified
|
||||
const setupProxy = async (): Promise<void> => {
|
||||
if (proxy) {
|
||||
// Create temporary session partition to avoid affecting global proxy settings
|
||||
tempPartition = `temp-request-${Date.now()}-${Math.random()}`
|
||||
sessionToUse = session.fromPartition(tempPartition, { cache: false })
|
||||
const proxyUrl = `${proxy.protocol}://${proxy.host}:${proxy.port}`
|
||||
await sessionToUse.setProxy({ proxyRules: proxyUrl })
|
||||
}
|
||||
}
|
||||
|
||||
const cleanup = (): void => {
|
||||
// Cleanup temporary session if created
|
||||
if (tempPartition) {
|
||||
// Note: Electron doesn't provide session.destroy(), but temporary sessions
|
||||
// will be garbage collected when no longer referenced
|
||||
sessionToUse = null as any
|
||||
}
|
||||
}
|
||||
|
||||
setupProxy()
|
||||
.then(() => {
|
||||
const req = net.request({
|
||||
method,
|
||||
url,
|
||||
session: sessionToUse,
|
||||
redirect: followRedirect ? 'follow' : 'manual',
|
||||
useSessionCookies: true
|
||||
})
|
||||
|
||||
// Set request headers
|
||||
Object.entries(headers).forEach(([key, value]) => {
|
||||
req.setHeader(key, value)
|
||||
})
|
||||
|
||||
// Timeout handling
|
||||
let timeoutId: NodeJS.Timeout | undefined
|
||||
if (timeout > 0) {
|
||||
timeoutId = setTimeout(() => {
|
||||
req.abort()
|
||||
cleanup()
|
||||
reject(new Error(`Request timeout after ${timeout}ms`))
|
||||
}, timeout)
|
||||
}
|
||||
|
||||
const chunks: Buffer[] = []
|
||||
let redirectCount = 0
|
||||
|
||||
req.on('redirect', () => {
|
||||
redirectCount++
|
||||
if (redirectCount > maxRedirects) {
|
||||
req.abort()
|
||||
cleanup()
|
||||
if (timeoutId) clearTimeout(timeoutId)
|
||||
reject(new Error(`Too many redirects (>${maxRedirects})`))
|
||||
}
|
||||
})
|
||||
|
||||
req.on('response', (res) => {
|
||||
const { statusCode, statusMessage } = res
|
||||
|
||||
// Extract response headers
|
||||
const responseHeaders: Record<string, string> = {}
|
||||
const rawHeaders = res.rawHeaders || []
|
||||
for (let i = 0; i < rawHeaders.length; i += 2) {
|
||||
responseHeaders[rawHeaders[i].toLowerCase()] = rawHeaders[i + 1]
|
||||
}
|
||||
|
||||
res.on('data', (chunk: Buffer) => {
|
||||
chunks.push(chunk)
|
||||
})
|
||||
|
||||
res.on('end', () => {
|
||||
cleanup()
|
||||
if (timeoutId) clearTimeout(timeoutId)
|
||||
|
||||
const buffer = Buffer.concat(chunks)
|
||||
let data: any
|
||||
|
||||
try {
|
||||
switch (responseType) {
|
||||
case 'json':
|
||||
data = JSON.parse(buffer.toString('utf-8'))
|
||||
break
|
||||
case 'arraybuffer':
|
||||
data = buffer
|
||||
break
|
||||
case 'text':
|
||||
default:
|
||||
data = buffer.toString('utf-8')
|
||||
}
|
||||
|
||||
resolve({
|
||||
data,
|
||||
status: statusCode,
|
||||
statusText: statusMessage,
|
||||
headers: responseHeaders,
|
||||
url: url
|
||||
})
|
||||
} catch (error) {
|
||||
reject(new Error(`Failed to parse response: ${error}`))
|
||||
}
|
||||
})
|
||||
|
||||
res.on('error', (error) => {
|
||||
cleanup()
|
||||
if (timeoutId) clearTimeout(timeoutId)
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
|
||||
req.on('error', (error) => {
|
||||
cleanup()
|
||||
if (timeoutId) clearTimeout(timeoutId)
|
||||
reject(error)
|
||||
})
|
||||
|
||||
req.on('abort', () => {
|
||||
cleanup()
|
||||
if (timeoutId) clearTimeout(timeoutId)
|
||||
reject(new Error('Request aborted'))
|
||||
})
|
||||
|
||||
// Send request body
|
||||
if (body) {
|
||||
if (typeof body === 'string') {
|
||||
req.write(body, 'utf-8')
|
||||
} else {
|
||||
req.write(body)
|
||||
}
|
||||
}
|
||||
|
||||
req.end()
|
||||
})
|
||||
.catch((error) => {
|
||||
cleanup()
|
||||
reject(new Error(`Failed to setup proxy: ${error}`))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for GET requests
|
||||
*/
|
||||
export const get = <T = any>(
|
||||
url: string,
|
||||
options?: Omit<RequestOptions, 'method' | 'body'>
|
||||
): Promise<Response<T>> => request<T>(url, { ...options, method: 'GET' })
|
||||
|
||||
/**
|
||||
* Convenience method for POST requests
|
||||
*/
|
||||
export const post = <T = any>(
|
||||
url: string,
|
||||
data: any,
|
||||
options?: Omit<RequestOptions, 'method' | 'body'>
|
||||
): Promise<Response<T>> => {
|
||||
const body = typeof data === 'string' ? data : JSON.stringify(data)
|
||||
const headers = options?.headers || {}
|
||||
if (typeof data !== 'string' && !headers['content-type']) {
|
||||
headers['content-type'] = 'application/json'
|
||||
}
|
||||
return request<T>(url, { ...options, method: 'POST', body, headers })
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for PUT requests
|
||||
*/
|
||||
export const put = <T = any>(
|
||||
url: string,
|
||||
data: any,
|
||||
options?: Omit<RequestOptions, 'method' | 'body'>
|
||||
): Promise<Response<T>> => {
|
||||
const body = typeof data === 'string' ? data : JSON.stringify(data)
|
||||
const headers = options?.headers || {}
|
||||
if (typeof data !== 'string' && !headers['content-type']) {
|
||||
headers['content-type'] = 'application/json'
|
||||
}
|
||||
return request<T>(url, { ...options, method: 'PUT', body, headers })
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for DELETE requests
|
||||
*/
|
||||
export const del = <T = any>(
|
||||
url: string,
|
||||
options?: Omit<RequestOptions, 'method' | 'body'>
|
||||
): Promise<Response<T>> => request<T>(url, { ...options, method: 'DELETE' })
|
||||
|
||||
/**
|
||||
* Convenience method for PATCH requests
|
||||
*/
|
||||
export const patch = <T = any>(
|
||||
url: string,
|
||||
data: any,
|
||||
options?: Omit<RequestOptions, 'method' | 'body'>
|
||||
): Promise<Response<T>> => {
|
||||
const body = typeof data === 'string' ? data : JSON.stringify(data)
|
||||
const headers = options?.headers || {}
|
||||
if (typeof data !== 'string' && !headers['content-type']) {
|
||||
headers['content-type'] = 'application/json'
|
||||
}
|
||||
return request<T>(url, { ...options, method: 'PATCH', body, headers })
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
import axios from 'axios'
|
||||
import * as chromeRequest from './chromeRequest'
|
||||
import { createWriteStream, createReadStream } from 'fs'
|
||||
import { writeFile } from 'fs/promises'
|
||||
import { mihomoCoreDir } from './dirs'
|
||||
import AdmZip from 'adm-zip'
|
||||
import { execSync } from 'child_process'
|
||||
@ -62,29 +63,30 @@ export async function getGitHubTags(owner: string, repo: string, forceRefresh =
|
||||
|
||||
try {
|
||||
console.log(`[GitHub] Fetching tags for ${owner}/${repo}`)
|
||||
const response = await axios.get<GitHubTag[]>(
|
||||
const response = await chromeRequest.get<GitHubTag[]>(
|
||||
`${GITHUB_API_CONFIG.BASE_URL}/repos/${owner}/${repo}/tags?per_page=${GITHUB_API_CONFIG.TAGS_PER_PAGE}`,
|
||||
{
|
||||
headers: {
|
||||
Accept: 'application/vnd.github+json',
|
||||
'X-GitHub-Api-Version': GITHUB_API_CONFIG.API_VERSION
|
||||
},
|
||||
responseType: 'json',
|
||||
timeout: 10000
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
// 更新缓存
|
||||
versionCache.set(cacheKey, {
|
||||
data: response.data,
|
||||
timestamp: Date.now()
|
||||
})
|
||||
|
||||
|
||||
console.log(`[GitHub] Successfully fetched ${response.data.length} tags for ${owner}/${repo}`)
|
||||
return response.data
|
||||
} catch (error) {
|
||||
console.error(`[GitHub] Failed to fetch tags for ${owner}/${repo}:`, error)
|
||||
if (axios.isAxiosError(error)) {
|
||||
throw new Error(`GitHub API error: ${error.response?.status} - ${error.response?.statusText}`)
|
||||
if (error instanceof Error) {
|
||||
throw new Error(`GitHub API error: ${error.message}`)
|
||||
}
|
||||
throw new Error('Failed to fetch version list')
|
||||
}
|
||||
@ -110,30 +112,17 @@ export function clearVersionCache(owner: string, repo: string): void {
|
||||
async function downloadGitHubAsset(url: string, outputPath: string): Promise<void> {
|
||||
try {
|
||||
console.log(`[GitHub] Downloading asset from ${url}`)
|
||||
const writer = createWriteStream(outputPath)
|
||||
const response = await axios({
|
||||
url,
|
||||
method: 'GET',
|
||||
responseType: 'stream',
|
||||
const response = await chromeRequest.get(url, {
|
||||
responseType: 'arraybuffer',
|
||||
timeout: 30000
|
||||
})
|
||||
|
||||
response.data.pipe(writer)
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
writer.on('finish', () => {
|
||||
console.log(`[GitHub] Successfully downloaded asset to ${outputPath}`)
|
||||
resolve()
|
||||
})
|
||||
writer.on('error', (error) => {
|
||||
console.error(`[GitHub] Failed to write asset to ${outputPath}:`, error)
|
||||
reject(new Error(`Failed to download core file: ${error.message}`))
|
||||
})
|
||||
})
|
||||
await writeFile(outputPath, Buffer.from(response.data as Buffer))
|
||||
console.log(`[GitHub] Successfully downloaded asset to ${outputPath}`)
|
||||
} catch (error) {
|
||||
console.error(`[GitHub] Failed to download asset from ${url}:`, error)
|
||||
if (axios.isAxiosError(error)) {
|
||||
throw new Error(`Download error: ${error.response?.status} - ${error.response?.statusText}`)
|
||||
if (error instanceof Error) {
|
||||
throw new Error(`Download error: ${error.message}`)
|
||||
}
|
||||
throw new Error('Failed to download core file')
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import axios from 'axios'
|
||||
import * as chromeRequest from './chromeRequest'
|
||||
import { getControledMihomoConfig } from '../config'
|
||||
|
||||
export async function getImageDataURL(url: string): Promise<string> {
|
||||
const { 'mixed-port': port = 7890 } = await getControledMihomoConfig()
|
||||
const res = await axios.get(url, {
|
||||
const res = await chromeRequest.get(url, {
|
||||
responseType: 'arraybuffer',
|
||||
proxy: {
|
||||
protocol: 'http',
|
||||
@ -12,6 +12,6 @@ export async function getImageDataURL(url: string): Promise<string> {
|
||||
}
|
||||
})
|
||||
const mimeType = res.headers['content-type']
|
||||
const dataURL = `data:${mimeType};base64,${Buffer.from(res.data).toString('base64')}`
|
||||
const dataURL = `data:${mimeType};base64,${Buffer.from(res.data as Buffer).toString('base64')}`
|
||||
return dataURL
|
||||
}
|
||||
|
||||
@ -291,7 +291,7 @@ export function registerIpcMainHandlers(): void {
|
||||
})
|
||||
ipcMain.handle('showMainWindow', showMainWindow)
|
||||
ipcMain.handle('closeMainWindow', closeMainWindow)
|
||||
ipcMain.handle('triggerMainWindow', triggerMainWindow)
|
||||
ipcMain.handle('triggerMainWindow', (_e, force) => triggerMainWindow(force))
|
||||
ipcMain.handle('showFloatingWindow', () => ipcErrorWrapper(showFloatingWindow)())
|
||||
ipcMain.handle('closeFloatingWindow', () => ipcErrorWrapper(closeFloatingWindow)())
|
||||
ipcMain.handle('showContextMenu', () => ipcErrorWrapper(showContextMenu)())
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user