158 lines
5.1 KiB
TypeScript
158 lines
5.1 KiB
TypeScript
const modulename = 'UpdateChecker';
|
|
import { txEnv } from '@core/globalData';
|
|
import consoleFactory from '@lib/console';
|
|
import { UpdateDataType } from '@shared/otherTypes';
|
|
import { UpdateAvailableEventType } from '@shared/socketioTypes';
|
|
import { queryChangelogApi } from './queryChangelogApi';
|
|
import { getUpdateRolloutDelay } from './updateRollout';
|
|
const console = consoleFactory(modulename);
|
|
|
|
|
|
type CachedDelayType = {
|
|
ts: number,
|
|
diceRoll: number,
|
|
}
|
|
|
|
/**
|
|
* Creates a cache string.
|
|
*/
|
|
const createCacheString = (delayData: CachedDelayType) => {
|
|
return `${delayData.ts},${delayData.diceRoll}`;
|
|
}
|
|
|
|
|
|
/**
|
|
* Parses the cached string.
|
|
* Format: "ts,diceRoll"
|
|
*/
|
|
const parseCacheString = (raw: any) => {
|
|
if (typeof raw !== 'string' || !raw) return;
|
|
const [ts, diceRoll] = raw.split(',');
|
|
const obj = {
|
|
ts: parseInt(ts),
|
|
diceRoll: parseInt(diceRoll),
|
|
} satisfies CachedDelayType;
|
|
if (isNaN(obj.ts) || isNaN(obj.diceRoll)) return;
|
|
return obj;
|
|
}
|
|
|
|
|
|
/**
|
|
* Rolls dice, gets integer between 0 and 100
|
|
*/
|
|
const rollDice = () => {
|
|
return Math.floor(Math.random() * 101);
|
|
}
|
|
|
|
const DELAY_CACHE_KEY = 'updateDelay';
|
|
|
|
|
|
/**
|
|
* Module to check for updates and notify the user according to a rollout strategy randomly picked.
|
|
*/
|
|
export default class UpdateChecker {
|
|
txaUpdateData?: UpdateDataType;
|
|
fxsUpdateData?: UpdateDataType;
|
|
|
|
constructor() {
|
|
//Check for updates ASAP
|
|
setImmediate(() => {
|
|
this.checkChangelog();
|
|
});
|
|
|
|
//Check again every 15 mins
|
|
setInterval(() => {
|
|
this.checkChangelog();
|
|
}, 15 * 60_000);
|
|
}
|
|
|
|
|
|
/**
|
|
* Check for txAdmin and FXServer updates
|
|
*/
|
|
async checkChangelog() {
|
|
const updates = await queryChangelogApi();
|
|
if (!updates) return;
|
|
|
|
//If fxserver, don't print anything, just update the data
|
|
if (updates.fxs) {
|
|
this.fxsUpdateData = {
|
|
version: updates.fxs.version,
|
|
isImportant: updates.fxs.isImportant,
|
|
}
|
|
}
|
|
|
|
//If txAdmin update, check for delay before printing
|
|
if (updates.txa) {
|
|
//Setup delay data
|
|
const currTs = Date.now();
|
|
let delayData: CachedDelayType;
|
|
const rawCache = txCore.cacheStore.get(DELAY_CACHE_KEY);
|
|
const cachedData = parseCacheString(rawCache);
|
|
if (cachedData) {
|
|
delayData = cachedData;
|
|
} else {
|
|
delayData = {
|
|
diceRoll: rollDice(),
|
|
ts: currTs,
|
|
}
|
|
txCore.cacheStore.set(DELAY_CACHE_KEY, createCacheString(delayData));
|
|
}
|
|
|
|
//Get the delay
|
|
const notifDelayDays = getUpdateRolloutDelay(
|
|
updates.txa.semverDiff,
|
|
txEnv.txaVersion.includes('-'),
|
|
delayData.diceRoll
|
|
);
|
|
const notifDelayMs = notifDelayDays * 24 * 60 * 60 * 1000;
|
|
console.verbose.debug(`Update available, notification delayed by: ${notifDelayDays} day(s).`);
|
|
if (currTs - delayData.ts >= notifDelayMs) {
|
|
txCore.cacheStore.delete(DELAY_CACHE_KEY);
|
|
this.txaUpdateData = {
|
|
version: updates.txa.version,
|
|
isImportant: updates.txa.isImportant,
|
|
}
|
|
if (updates.txa.isImportant) {
|
|
console.error('This version of txAdmin is outdated.');
|
|
console.error('Please update as soon as possible.');
|
|
console.error('For more information: https://discord.gg/uAmsGa2');
|
|
} else {
|
|
console.warn('This version of txAdmin is outdated.');
|
|
console.warn('A patch (bug fix) update is available for txAdmin.');
|
|
console.warn('If you are experiencing any kind of issue, please update now.');
|
|
console.warn('For more information: https://discord.gg/uAmsGa2');
|
|
}
|
|
}
|
|
}
|
|
|
|
//Sending event to the UI
|
|
if (this.txaUpdateData || this.fxsUpdateData) {
|
|
txCore.webServer.webSocket.pushEvent<UpdateAvailableEventType>('updateAvailable', {
|
|
fxserver: this.fxsUpdateData,
|
|
txadmin: this.txaUpdateData,
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
/*
|
|
TODO:
|
|
Create an page with the changelog, that queries for the following endpoint and caches it for 15 minutes:
|
|
https://changelogs-live.fivem.net/api/changelog/versions/2385/2375?tag=server
|
|
Maybe even grab the data from commits:
|
|
https://changelogs-live.fivem.net/api/changelog/versions/5562
|
|
Other relevant apis:
|
|
https://changelogs-live.fivem.net/api/changelog/versions/win32/server? (the one being used below)
|
|
https://changelogs-live.fivem.net/api/changelog/versions
|
|
https://api.github.com/repos/tabarra/txAdmin/releases (changelog in [].body)
|
|
|
|
NOTE: old logic
|
|
if == recommended, you're fine
|
|
if > recommended && < optional, pls update to optional
|
|
if == optional, you're fine
|
|
if > optional && < latest, pls update to latest
|
|
if == latest, duh
|
|
if < critical, BIG WARNING
|
|
*/
|