monitor/core/modules/UpdateChecker/queryChangelogApi.ts
2025-04-16 22:30:27 +07:00

112 lines
3.8 KiB
TypeScript

const modulename = 'UpdateChecker';
import semver, { ReleaseType } from 'semver';
import { z } from "zod";
import got from '@lib/got';
import { txEnv } from '@core/globalData';
import consoleFactory from '@lib/console';
import { UpdateDataType } from '@shared/otherTypes';
import { fromError } from 'zod-validation-error';
const console = consoleFactory(modulename);
//Schemas
const txVersion = z.string().refine(
(x) => x !== '0.0.0',
{ message: 'must not be 0.0.0' }
);
const changelogRespSchema = z.object({
recommended: z.coerce.number().positive(),
recommended_download: z.string().url(),
recommended_txadmin: txVersion,
optional: z.coerce.number().positive(),
optional_download: z.string().url(),
optional_txadmin: txVersion,
latest: z.coerce.number().positive(),
latest_download: z.string().url(),
latest_txadmin: txVersion,
critical: z.coerce.number().positive(),
critical_download: z.string().url(),
critical_txadmin: txVersion,
});
//Types
type DetailedUpdateDataType = {
semverDiff: ReleaseType;
version: string;
isImportant: boolean;
};
export const queryChangelogApi = async () => {
//GET changelog data
let apiResponse: z.infer<typeof changelogRespSchema>;
try {
//perform request - cache busting every ~1.4h
const osTypeApiUrl = (txEnv.isWindows) ? 'win32' : 'linux';
const cacheBuster = Math.floor(Date.now() / 5_000_000);
const reqUrl = `https://changelogs-live.fivem.net/api/changelog/versions/${osTypeApiUrl}/server?${cacheBuster}`;
const resp = await got(reqUrl).json()
apiResponse = changelogRespSchema.parse(resp);
} catch (error) {
let msg = (error as Error).message;
if(error instanceof z.ZodError){
msg = fromError(error, { prefix: null }).message
}
console.verbose.warn(`Failed to retrieve FXServer/txAdmin update data with error: ${msg}`);
return;
}
//Checking txAdmin version
let txaUpdateData: DetailedUpdateDataType | undefined;
try {
const isOutdated = semver.lt(txEnv.txaVersion, apiResponse.latest_txadmin);
if (isOutdated) {
const semverDiff = semver.diff(txEnv.txaVersion, apiResponse.latest_txadmin) ?? 'patch';
const isImportant = (semverDiff === 'major' || semverDiff === 'minor');
txaUpdateData = {
semverDiff,
isImportant,
version: apiResponse.latest_txadmin,
};
}
} catch (error) {
console.verbose.warn('Error checking for txAdmin updates.');
console.verbose.dir(error);
}
//Checking FXServer version
let fxsUpdateData: UpdateDataType | undefined;
try {
if (txEnv.fxsVersion < apiResponse.critical) {
if (apiResponse.critical > apiResponse.recommended) {
fxsUpdateData = {
version: apiResponse.critical.toString(),
isImportant: true,
}
} else {
fxsUpdateData = {
version: apiResponse.recommended.toString(),
isImportant: true,
}
}
} else if (txEnv.fxsVersion < apiResponse.recommended) {
fxsUpdateData = {
version: apiResponse.recommended.toString(),
isImportant: true,
};
} else if (txEnv.fxsVersion < apiResponse.optional) {
fxsUpdateData = {
version: apiResponse.optional.toString(),
isImportant: false,
};
}
} catch (error) {
console.warn('Error checking for FXServer updates.');
console.verbose.dir(error);
}
return {
txa: txaUpdateData,
fxs: fxsUpdateData,
};
};