From 788d1087ba0b52d9898d02ca73ed5e90f0ee3edd Mon Sep 17 00:00:00 2001 From: MathieuG-P <40181755+Zagrios@users.noreply.github.com> Date: Wed, 4 Oct 2023 15:24:41 +0200 Subject: [PATCH] [bugfix] use ipv4 agent to perform requests --- src/main/services/request.service.ts | 13 +++-- .../beat-saver/beat-saver-api.service.ts | 50 +++++++------------ .../beat-saver/beat-saver.service.ts | 22 ++++---- .../model-saber/model-saber-api.service.ts | 23 ++++----- .../model-saber/model-saber.service.ts | 22 +++----- 5 files changed, 51 insertions(+), 79 deletions(-) diff --git a/src/main/services/request.service.ts b/src/main/services/request.service.ts index 0864d6b4..87e5916d 100644 --- a/src/main/services/request.service.ts +++ b/src/main/services/request.service.ts @@ -1,4 +1,4 @@ -import { get } from "https"; +import { Agent, get } from "https"; import { createWriteStream, unlink } from "fs"; import { Progression } from "main/helpers/fs.helpers"; import { Observable, shareReplay, tap } from "rxjs"; @@ -17,9 +17,14 @@ export class RequestService { private constructor() {} + private get ipv4Agent(){ + return new Agent({ family: 4 }); + } + public async getJSON(url: RequestInfo, options?: RequestInit): Promise { + try { - const response = await fetch(url, options); + const response = await fetch(url, {...{ agent: this.ipv4Agent }, ...options}); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status} ${response}`); @@ -45,7 +50,7 @@ export class RequestService { }); file.on("error", err => unlink(dest, () => subscriber.error(err))); - const req = get(url, res => { + const req = get({href: url, agent: this.ipv4Agent}, res => { progress.total = parseInt(res.headers?.["content-length"] || "0", 10); res.on("data", chunk => { @@ -72,7 +77,7 @@ export class RequestService { const allChunks: Buffer[] = []; - const req = get(url, res => { + const req = get({href: url, agent: this.ipv4Agent}, res => { progress.total = parseInt(res.headers?.["content-length"] || "0", 10); res.on("data", chunk => { diff --git a/src/main/services/thrid-party/beat-saver/beat-saver-api.service.ts b/src/main/services/thrid-party/beat-saver/beat-saver-api.service.ts index 5743dc7e..a8fef0a4 100644 --- a/src/main/services/thrid-party/beat-saver/beat-saver-api.service.ts +++ b/src/main/services/thrid-party/beat-saver/beat-saver-api.service.ts @@ -1,7 +1,6 @@ -import { ApiResult } from "renderer/models/api/api.model"; import { BsvMapDetail } from "shared/models/maps"; import { BsvPlaylist, BsvPlaylistPage, MapFilter, SearchParams, SearchResponse } from "shared/models/maps/beat-saver.model"; -import fetch from "node-fetch"; +import { RequestService } from "../../request.service"; export class BeatSaverApiService { private static instance: BeatSaverApiService; @@ -13,9 +12,13 @@ export class BeatSaverApiService { return BeatSaverApiService.instance; } + private readonly request: RequestService; + private readonly bsaverApiUrl = "https://beatsaver.com/api"; - private constructor() {} + private constructor() { + this.request = RequestService.getInstance(); + } private mapFilterToUrlParams(filter: MapFilter): URLSearchParams { if (!filter) { @@ -68,15 +71,13 @@ export class BeatSaverApiService { }); } - public async getMapsDetailsByHashs(hashs: T[]): Promise, BsvMapDetail>>> { + public async getMapsDetailsByHashs(hashs: T[]): Promise, BsvMapDetail>> { if (hashs.length > 50) { throw "too musch map hashs"; } const paramsHashs = hashs.join(","); - const resp = await fetch(`${this.bsaverApiUrl}/maps/hash/${paramsHashs}`); - - const data = (await resp.json()) as Record, BsvMapDetail> | BsvMapDetail; + const data = await this.request.getJSON, BsvMapDetail> | BsvMapDetail>(`${this.bsaverApiUrl}/maps/hash/${paramsHashs}`); if ((data as BsvMapDetail).id) { const key = (data as BsvMapDetail).versions.at(0).hash.toLowerCase(); @@ -84,41 +85,24 @@ export class BeatSaverApiService { [key]: data as BsvMapDetail, } as Record, BsvMapDetail>; - return { status: resp.status, data: parsedData }; + return parsedData } - return { status: resp.status, data: data as Record, BsvMapDetail> }; + return data as Record, BsvMapDetail>; } - public async getMapDetailsById(id: string): Promise> { - const res = await fetch(`${this.bsaverApiUrl}/maps/id/${id}`); - - const data = (await res.json()) as BsvMapDetail; - - return { status: res.status, data }; + public async getMapDetailsById(id: string): Promise { + return this.request.getJSON(`${this.bsaverApiUrl}/maps/id/${id}`); } - public async searchMaps(search: SearchParams): Promise> { + public async searchMaps(search: SearchParams): Promise { const url = new URL(`${this.bsaverApiUrl}/search/text/${search?.page ?? 0}`); - url.search = this.searchParamsToUrlParams(search).toString(); - - const res = await fetch(url.toString()); - - if (!res.ok) { - return { status: res.status, data: null }; - } - - const data = await res.json(); - - return { status: res.status, data }; + return this.request.getJSON(url.toString()); } - public async getPlaylistDetails(id: string): Promise> { - const res = await fetch(`${this.bsaverApiUrl}/playlists/id/${id}/0`); - - const data = (await res.json()) as BsvPlaylistPage; - - return { status: res.status, data: data.playlist }; + public async getPlaylistDetails(id: string): Promise { + const res = await this.request.getJSON(`${this.bsaverApiUrl}/playlists/id/${id}/0`); + return res.playlist; } } diff --git a/src/main/services/thrid-party/beat-saver/beat-saver.service.ts b/src/main/services/thrid-party/beat-saver/beat-saver.service.ts index e71559f4..a6ae33e4 100644 --- a/src/main/services/thrid-party/beat-saver/beat-saver.service.ts +++ b/src/main/services/thrid-party/beat-saver/beat-saver.service.ts @@ -2,6 +2,7 @@ import { splitIntoChunk } from "../../../../shared/helpers/array.helpers"; import { BsvMapDetail } from "shared/models/maps"; import { BsvPlaylist, SearchParams } from "shared/models/maps/beat-saver.model"; import { BeatSaverApiService } from "./beat-saver-api.service"; +import log from "electron-log"; export class BeatSaverService { private static instance: BeatSaverService; @@ -36,12 +37,10 @@ export class BeatSaverService { chunkHash.map(async hashs => { const res = await this.bsaverApi.getMapsDetailsByHashs(hashs); - if (res.status === 200) { - mapDetails.push(...Object.values(res.data).filter(detail => !!detail)); - mapDetails.forEach(detail => { - this.cachedMapsDetails.set(detail.versions.at(0).hash.toLowerCase(), detail); - }); - } + mapDetails.push(...Object.values(res).filter(detail => !!detail)); + mapDetails.forEach(detail => { + this.cachedMapsDetails.set(detail.versions.at(0).hash.toLowerCase(), detail); + }); }) ); @@ -49,23 +48,22 @@ export class BeatSaverService { } public async getMapDetailsById(id: string): Promise { - const res = await this.bsaverApi.getMapDetailsById(id); - return res.data; + return this.bsaverApi.getMapDetailsById(id); } public searchMaps(search: SearchParams): Promise { return this.bsaverApi .searchMaps(search) .then(res => { - return res.status === 200 ? res.data.docs : []; + return res.docs; }) - .catch(() => { + .catch(e => { + log.error(e); return []; }); } public async getPlaylistPage(id: string): Promise { - const res = await this.bsaverApi.getPlaylistDetails(id); - return res.data; + return this.bsaverApi.getPlaylistDetails(id); } } diff --git a/src/main/services/thrid-party/model-saber/model-saber-api.service.ts b/src/main/services/thrid-party/model-saber/model-saber-api.service.ts index 88238670..122be8c2 100644 --- a/src/main/services/thrid-party/model-saber/model-saber-api.service.ts +++ b/src/main/services/thrid-party/model-saber/model-saber-api.service.ts @@ -1,8 +1,8 @@ -import fetch from "node-fetch"; -import { ApiResult } from "renderer/models/api/api.model"; import { MSGetQuery, MSGetQueryFilter, MSGetResponse } from "../../../../shared/models/models/model-saber.model"; +import { RequestService } from "../../request.service"; export class ModelSaberApiService { + private static instance: ModelSaberApiService; public static getInstance(): ModelSaberApiService { @@ -15,7 +15,11 @@ export class ModelSaberApiService { private readonly API_URL = "https://modelsaber.com/api/v2/"; private readonly ENDPOINTS = { get: "get.php", types: "types.php" }; - private constructor() {} + private readonly request: RequestService; + + private constructor() { + this.request = RequestService.getInstance(); + } private parseFilters(filters: MSGetQueryFilter[]): string { if (!filters) { @@ -50,19 +54,10 @@ export class ModelSaberApiService { return new URLSearchParams(searchParams); } - public async searchModel(query: MSGetQuery): Promise> { + public async searchModel(query: MSGetQuery): Promise { const url = new URL(this.ENDPOINTS.get, this.API_URL); - url.search = this.buildUrlQuery(query).toString(); - const res = await fetch(url.toString()); - - if (!res.ok) { - return { data: null, status: res.status }; - } - - const data = (await res.json()) as MSGetResponse; - - return { data, status: res.status }; + return this.request.getJSON(url.toString()); } } diff --git a/src/main/services/thrid-party/model-saber/model-saber.service.ts b/src/main/services/thrid-party/model-saber/model-saber.service.ts index 198e6a45..3437e4e8 100644 --- a/src/main/services/thrid-party/model-saber/model-saber.service.ts +++ b/src/main/services/thrid-party/model-saber/model-saber.service.ts @@ -33,15 +33,11 @@ export class ModelSaberService { try { const res = await this.modelSaberApi.searchModel(query); - if (res.status !== 200) { + if (Object.keys(res).length === 0) { return null; } - if (Object.keys(res.data).length === 0) { - return null; - } - - return res.data[`${id}`]; + return res[`${id}`]; } catch (e) { log.error(e); return null; @@ -63,15 +59,11 @@ export class ModelSaberService { try { const res = await this.modelSaberApi.searchModel(query); - if (res.status !== 200) { + if (Object.keys(res).length === 0) { return null; } - if (Object.keys(res.data).length === 0) { - return null; - } - - const model = Array.from(Object.values(res.data)).at(0); + const model = Array.from(Object.values(res)).at(0); model.name = striptags(model.name ?? ""); model.author = striptags(model.author ?? ""); @@ -89,11 +81,9 @@ export class ModelSaberService { return new Observable(observer => { (async () => { const res = await this.modelSaberApi.searchModel(query); - if (res.status !== 200) { - observer.error(res.status); - } + observer.next( - Object.values(res.data).map(model => { + Object.values(res).map(model => { if (!model?.name) { return null; }