mirror of
https://github.com/an-anime-team/an-anime-game-launcher.git
synced 2025-03-17 21:50:11 +03:00
API improvements
- added `Game.versions` field - created custom `fetch` function for proper work with http requests - `Downloader.download()` was rewritten to work with custom `fetch` function
This commit is contained in:
parent
9e6672c797
commit
23445bc85e
8 changed files with 172 additions and 20 deletions
|
@ -7,12 +7,13 @@
|
|||
"build": "vite build && neu build --release"
|
||||
},
|
||||
"dependencies": {
|
||||
"js-md5": "^0.7.3",
|
||||
"vue": "^3.2.25"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@neutralinojs/neu": "^8.0.0",
|
||||
"@vitejs/plugin-vue": "^2.0.1",
|
||||
"vite": "^2.7.4",
|
||||
"sass": "^1.45.1"
|
||||
"sass": "^1.45.1",
|
||||
"vite": "^2.7.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
import * as Vue from 'vue/dist/vue.esm-bundler';
|
||||
|
||||
import Window from '../ts/neutralino/Window';
|
||||
import Patch from '../ts/Patch';
|
||||
import Voice from '../ts/Voice';
|
||||
import fetch from '../ts/core/Fetch';
|
||||
import Downloader from '../ts/core/Downloader';
|
||||
|
||||
const app = Vue.createApp({
|
||||
data: () => ({
|
||||
|
@ -15,8 +18,12 @@ const app = Vue.createApp({
|
|||
mounted: () => {
|
||||
Window.current.show();
|
||||
|
||||
Voice.getDiff('2.1.0')
|
||||
.then((data) => console.log(data));
|
||||
/*fetch('https://sdk-os-static.mihoyo.com/hk4e_global/mdk/launcher/api/resource?key=gcStgarh&launcher_id=10', 1000)
|
||||
.then((response) => {
|
||||
console.log(response);
|
||||
|
||||
response.body().then((body) => console.log(body.length));
|
||||
});*/
|
||||
|
||||
/*Downloader.download('https://github.com/GloriousEggroll/wine-ge-custom/releases/download/6.20-GE-1/wine-lutris-ge-6.20-1-x86_64.tar.xz', '123.tar.xz').then((stream) => {
|
||||
stream.start(() => console.log('Downloading started'));
|
||||
|
|
|
@ -173,9 +173,6 @@ export default class constants
|
|||
public static readonly versionsUri: string = `${this.uri.api}/resource?key=gcStgarh&launcher_id=10`;
|
||||
public static readonly backgroundUri: string = `${this.uri.api}/content?filter_adv=true&launcher_id=10&key=gcStgarh&language=`;
|
||||
|
||||
public static readonly runnersUri: string = `${this.uri.launcher}/raw/main/runners.json`;
|
||||
public static readonly dxvksUri: string = `${this.uri.launcher}/raw/main/dxvks.json`;
|
||||
|
||||
public static getPatchUri(source: 'origin' | 'additional'): string
|
||||
{
|
||||
return `${this.uri.patch[source]}/archive/master.zip`;
|
||||
|
|
|
@ -74,6 +74,26 @@ export default class Game
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get game versions list
|
||||
*
|
||||
* @returns rejects Error object if company's servers are unreachable or they responded with an error
|
||||
*/
|
||||
public static get versions(): Promise<string[]>
|
||||
{
|
||||
return new Promise((resolve, reject) => {
|
||||
this.getLatestData()
|
||||
.then((data) => {
|
||||
let versions = [data.game.latest.version];
|
||||
|
||||
data.game.diffs.forEach((diff) => versions.push(diff.version));
|
||||
|
||||
resolve(versions);
|
||||
})
|
||||
.catch((error) => reject(error));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get updated game data from the specified version to the latest
|
||||
*
|
||||
|
|
29
src/ts/Patch.ts
Normal file
29
src/ts/Patch.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
import type {
|
||||
PatchState,
|
||||
PatchInfo
|
||||
} from './types/Patch';
|
||||
|
||||
import md5 from 'js-md5';
|
||||
|
||||
import constants from './Constants';
|
||||
|
||||
declare const Neutralino;
|
||||
|
||||
export default class Patch
|
||||
{
|
||||
/*public static get latest(): Promise<PatchInfo>
|
||||
{
|
||||
return new Promise((resolve) => {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public static getPatchInfo(version: string, source: 'origin' | 'additional' = 'origin'): Promise<PatchInfo|null>
|
||||
{
|
||||
return new Promise(async (resolve) => {
|
||||
const patchUri = constants.uri.patch[source];
|
||||
|
||||
const patchSh = await fetch(`${patchUri}/raw/master/${version.replaceAll('.', '')}/patch.sh`);
|
||||
});
|
||||
}*/
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
import fetch from './Fetch';
|
||||
|
||||
declare const Neutralino;
|
||||
|
||||
class Stream
|
||||
|
@ -107,19 +109,9 @@ export default class Downloader
|
|||
public static async download(uri: string, output: string|null = null): Promise<Stream>
|
||||
{
|
||||
return new Promise(async (resolve) => {
|
||||
let statsRaw = await Neutralino.os.execCommand(`curl -s -I -L "${uri}"`);
|
||||
|
||||
if (statsRaw.stdOut == '')
|
||||
statsRaw = statsRaw.stdErr;
|
||||
|
||||
else statsRaw = statsRaw.stdOut;
|
||||
|
||||
let length = 0;
|
||||
|
||||
for (const match of statsRaw.matchAll(/content-length: ([\d]+)/gi))
|
||||
length = match[1];
|
||||
|
||||
resolve(new Stream(uri, output ?? this.fileFromUri(uri), length));
|
||||
fetch(uri).then((response) => {
|
||||
resolve(new Stream(uri, output ?? this.fileFromUri(uri), response.length));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
79
src/ts/core/Fetch.ts
Normal file
79
src/ts/core/Fetch.ts
Normal file
|
@ -0,0 +1,79 @@
|
|||
declare const Neutralino;
|
||||
|
||||
class Response
|
||||
{
|
||||
/**
|
||||
* Requested url
|
||||
*/
|
||||
public readonly url: string;
|
||||
|
||||
/**
|
||||
* HTTP status code
|
||||
*/
|
||||
public readonly status: number|null;
|
||||
|
||||
/**
|
||||
* Content length
|
||||
*/
|
||||
public readonly length: number|null;
|
||||
|
||||
/**
|
||||
* Represents whether the response was successful (status in the range 200-299) or not
|
||||
*/
|
||||
public readonly ok: boolean;
|
||||
|
||||
public constructor(url: string, status: number|null, length: number|null)
|
||||
{
|
||||
this.url = url;
|
||||
this.status = status;
|
||||
this.length = length;
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Response/ok
|
||||
this.ok = status >= 200 && status <= 299;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get request's body
|
||||
*
|
||||
* @param delay maximal request delay in milliseconds
|
||||
*/
|
||||
public body(delay: number|null = null): Promise<string>
|
||||
{
|
||||
return new Promise((resolve) => {
|
||||
Neutralino.os.execCommand(`curl -s -L ${delay !== null ? `-m ${(delay / 1000).toFixed(3)}` : ''} "${this.url}"`)
|
||||
.then((output) => resolve(output.stdOut));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch data from the URL
|
||||
*
|
||||
* @param delay maximal request delay in milliseconds
|
||||
*/
|
||||
export default function fetch(url: string, delay: number|null = null): Promise<Response>
|
||||
{
|
||||
return new Promise(async (resolve) => {
|
||||
let header = await Neutralino.os.execCommand(`curl -s -I -L ${delay !== null ? `-m ${(delay / 1000).toFixed(3)}` : ''} "${url}"`);
|
||||
|
||||
if (header.stdOut == '')
|
||||
header = header.stdErr;
|
||||
|
||||
else header = header.stdOut;
|
||||
|
||||
header = header.split(/^HTTP\/[\d]+ /mi).pop();
|
||||
|
||||
let status: any = /^([\d]+)[\s]+$/m.exec(header);
|
||||
let length: any = /^content-length: ([\d]+)/mi.exec(header);
|
||||
|
||||
if (status !== null)
|
||||
status = parseInt(status[1]);
|
||||
|
||||
if (length !== null)
|
||||
length = parseInt(length[1]);
|
||||
|
||||
resolve(new Response(url, status, length));
|
||||
});
|
||||
};
|
||||
|
||||
export { Response };
|
27
src/ts/types/Patch.d.ts
vendored
Normal file
27
src/ts/types/Patch.d.ts
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
type PatchState =
|
||||
| 'preparation'
|
||||
| 'testing'
|
||||
| 'stable';
|
||||
|
||||
type PatchInfo = {
|
||||
/**
|
||||
* Applied patch version
|
||||
*/
|
||||
version: string;
|
||||
state: PatchState;
|
||||
|
||||
/**
|
||||
* If the main UnityPlayer patch applied
|
||||
*/
|
||||
player: boolean;
|
||||
|
||||
/**
|
||||
* If the anti-login crash patch applied
|
||||
*/
|
||||
xlua: boolean;
|
||||
};
|
||||
|
||||
export type {
|
||||
PatchState,
|
||||
PatchInfo
|
||||
};
|
Loading…
Add table
Reference in a new issue