mirror of
https://github.com/Zagrios/bs-manager.git
synced 2026-07-03 14:08:25 +02:00
[bugfix] use ipv4 agent to perform requests
This commit is contained in:
@@ -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<T = unknown>(url: RequestInfo, options?: RequestInit): Promise<T> {
|
||||
|
||||
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 => {
|
||||
|
||||
@@ -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<T extends string>(hashs: T[]): Promise<ApiResult<Record<Lowercase<T>, BsvMapDetail>>> {
|
||||
public async getMapsDetailsByHashs<T extends string>(hashs: T[]): Promise<Record<Lowercase<T>, 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<Lowercase<T>, BsvMapDetail> | BsvMapDetail;
|
||||
const data = await this.request.getJSON<Record<Lowercase<T>, 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<Lowercase<T>, BsvMapDetail>;
|
||||
|
||||
return { status: resp.status, data: parsedData };
|
||||
return parsedData
|
||||
}
|
||||
|
||||
return { status: resp.status, data: data as Record<Lowercase<T>, BsvMapDetail> };
|
||||
return data as Record<Lowercase<T>, BsvMapDetail>;
|
||||
}
|
||||
|
||||
public async getMapDetailsById(id: string): Promise<ApiResult<BsvMapDetail>> {
|
||||
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<BsvMapDetail> {
|
||||
return this.request.getJSON<BsvMapDetail>(`${this.bsaverApiUrl}/maps/id/${id}`);
|
||||
}
|
||||
|
||||
public async searchMaps(search: SearchParams): Promise<ApiResult<SearchResponse>> {
|
||||
public async searchMaps(search: SearchParams): Promise<SearchResponse> {
|
||||
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<SearchResponse>(url.toString());
|
||||
}
|
||||
|
||||
public async getPlaylistDetails(id: string): Promise<ApiResult<BsvPlaylist>> {
|
||||
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<BsvPlaylist> {
|
||||
const res = await this.request.getJSON<BsvPlaylistPage>(`${this.bsaverApiUrl}/playlists/id/${id}/0`);
|
||||
return res.playlist;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<BsvMapDetail>(res.data).filter(detail => !!detail));
|
||||
mapDetails.forEach(detail => {
|
||||
this.cachedMapsDetails.set(detail.versions.at(0).hash.toLowerCase(), detail);
|
||||
});
|
||||
}
|
||||
mapDetails.push(...Object.values<BsvMapDetail>(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<BsvMapDetail> {
|
||||
const res = await this.bsaverApi.getMapDetailsById(id);
|
||||
return res.data;
|
||||
return this.bsaverApi.getMapDetailsById(id);
|
||||
}
|
||||
|
||||
public searchMaps(search: SearchParams): Promise<BsvMapDetail[]> {
|
||||
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<BsvPlaylist> {
|
||||
const res = await this.bsaverApi.getPlaylistDetails(id);
|
||||
return res.data;
|
||||
return this.bsaverApi.getPlaylistDetails(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<ApiResult<MSGetResponse>> {
|
||||
public async searchModel(query: MSGetQuery): Promise<MSGetResponse> {
|
||||
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<MSGetResponse>(url.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<MSModel[]>(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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user