141 lines
5.4 KiB
TypeScript
141 lines
5.4 KiB
TypeScript
import { DbInstance, SavePriority } from "../instance";
|
|
import consoleFactory from '@lib/console';
|
|
import { DatabasePlayerType, DatabaseWhitelistApprovalsType, DatabaseWhitelistRequestsType } from '../databaseTypes';
|
|
import { now } from '@lib/misc';
|
|
const console = consoleFactory('DatabaseDao');
|
|
|
|
|
|
/**
|
|
* Data access object for cleaning up the database.
|
|
*/
|
|
export default class CleanupDao {
|
|
constructor(private readonly db: DbInstance) { }
|
|
|
|
private get dbo() {
|
|
if (!this.db.obj || !this.db.isReady) throw new Error(`database not ready yet`);
|
|
return this.db.obj;
|
|
}
|
|
|
|
private get chain() {
|
|
if (!this.db.obj || !this.db.isReady) throw new Error(`database not ready yet`);
|
|
return this.db.obj.chain;
|
|
}
|
|
|
|
|
|
/**
|
|
* Cleans the database by removing every entry that matches the provided filter function.
|
|
* @returns {number} number of removed items
|
|
*/
|
|
bulkRemove(
|
|
tableName: 'players' | 'actions' | 'whitelistApprovals' | 'whitelistRequests',
|
|
filterFunc: Function
|
|
): number {
|
|
if (!Array.isArray(this.dbo.data[tableName])) throw new Error('Table selected isn\'t an array.');
|
|
if (typeof filterFunc !== 'function') throw new Error('filterFunc must be a function.');
|
|
|
|
try {
|
|
this.db.writeFlag(SavePriority.HIGH);
|
|
const removed = this.chain.get(tableName)
|
|
.remove(filterFunc as any)
|
|
.value();
|
|
return removed.length;
|
|
} catch (error) {
|
|
const msg = `Failed to clean database with error: ${(error as Error).message}`;
|
|
console.verbose.error(msg);
|
|
throw new Error(msg);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Cleans the hwids from the database.
|
|
* @returns {number} number of removed HWIDs
|
|
*/
|
|
wipeHwids(
|
|
fromPlayers: boolean,
|
|
fromBans: boolean,
|
|
): number {
|
|
if (!Array.isArray(this.dbo.data.players)) throw new Error('Players table isn\'t an array yet.');
|
|
if (!Array.isArray(this.dbo.data.players)) throw new Error('Actions table isn\'t an array yet.');
|
|
if (typeof fromPlayers !== 'boolean' || typeof fromBans !== 'boolean') throw new Error('The parameters should be booleans.');
|
|
|
|
try {
|
|
this.db.writeFlag(SavePriority.HIGH);
|
|
let removed = 0;
|
|
if (fromPlayers) {
|
|
this.chain.get('players')
|
|
.map(player => {
|
|
removed += player.hwids.length;
|
|
player.hwids = [];
|
|
return player;
|
|
})
|
|
.value();
|
|
}
|
|
if (fromBans)
|
|
this.chain.get('actions')
|
|
.map(action => {
|
|
if (action.type !== 'ban' || !action.hwids) {
|
|
return action;
|
|
} else {
|
|
removed += action.hwids.length;
|
|
action.hwids = [];
|
|
return action;
|
|
}
|
|
})
|
|
.value();
|
|
return removed;
|
|
} catch (error) {
|
|
const msg = `Failed to clean database with error: ${(error as Error).message}`;
|
|
console.verbose.error(msg);
|
|
throw new Error(msg);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Cron func to optimize the database removing players and whitelist reqs/approvals
|
|
*/
|
|
runDailyOptimizer() {
|
|
const oneDay = 24 * 60 * 60;
|
|
|
|
//Optimize players
|
|
//Players that have not joined the last 16 days, and have less than 2 hours of playtime
|
|
let playerRemoved;
|
|
try {
|
|
const sixteenDaysAgo = now() - (16 * oneDay);
|
|
const filter = (p: DatabasePlayerType) => {
|
|
return (p.tsLastConnection < sixteenDaysAgo && p.playTime < 120);
|
|
}
|
|
playerRemoved = this.bulkRemove('players', filter);
|
|
} catch (error) {
|
|
const msg = `Failed to optimize players database with error: ${(error as Error).message}`;
|
|
console.error(msg);
|
|
}
|
|
|
|
//Optimize whitelistRequests + whitelistApprovals
|
|
//Removing the ones older than 7 days
|
|
let wlRequestsRemoved, wlApprovalsRemoved;
|
|
const sevenDaysAgo = now() - (7 * oneDay);
|
|
try {
|
|
const wlRequestsFilter = (req: DatabaseWhitelistRequestsType) => {
|
|
return (req.tsLastAttempt < sevenDaysAgo);
|
|
}
|
|
wlRequestsRemoved = txCore.database.whitelist.removeManyRequests(wlRequestsFilter).length;
|
|
|
|
const wlApprovalsFilter = (req: DatabaseWhitelistApprovalsType) => {
|
|
return (req.tsApproved < sevenDaysAgo);
|
|
}
|
|
wlApprovalsRemoved = txCore.database.whitelist.removeManyApprovals(wlApprovalsFilter).length;
|
|
} catch (error) {
|
|
const msg = `Failed to optimize players database with error: ${(error as Error).message}`;
|
|
console.error(msg);
|
|
}
|
|
|
|
this.db.writeFlag(SavePriority.LOW);
|
|
console.ok(`Internal Database optimized. This applies only for the txAdmin internal database, and does not affect your MySQL or framework (ESX/QBCore/etc) databases.`);
|
|
console.ok(`- ${playerRemoved} players that haven't connected in the past 16 days and had less than 2 hours of playtime.`);
|
|
console.ok(`- ${wlRequestsRemoved} whitelist requests older than a week.`);
|
|
console.ok(`- ${wlApprovalsRemoved} whitelist approvals older than a week.`);
|
|
}
|
|
}
|