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:
Observer KRypt0n_ 2021-12-22 15:15:22 +02:00
parent 9e6672c797
commit 23445bc85e
No known key found for this signature in database
GPG key ID: DC5D4EC1303465DA
8 changed files with 172 additions and 20 deletions

View file

@ -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"
}
}

View file

@ -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'));

View file

@ -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`;

View file

@ -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
View 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`);
});
}*/
}

View file

@ -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
View 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
View 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
};