SquadJS/squad-server/plugins/auto-kick-afk.js

159 lines
5.7 KiB
JavaScript
Raw Normal View History

2020-10-22 16:06:28 -05:00
import BasePlugin from './base-plugin.js';
2020-10-25 18:31:46 -05:00
import Logger from 'core/logger';
2020-10-22 16:06:28 -05:00
export default class AutoKickAFK extends BasePlugin {
static get description() {
return 'The <code>AutoKickAFK</code> plugin will automatically kick players that are not in a squad after a specified ammount of time.';
}
static get defaultEnabled() {
return true;
}
static get optionsSpecification() {
return {
warningMessage: {
2020-10-22 16:06:28 -05:00
required: false,
description: 'Message SquadJS will send to players warning them they will be kicked',
default: 'Join a squad, you are are unassigned and will be kicked'
2020-10-22 16:06:28 -05:00
},
kickMessage: {
2020-10-22 19:22:34 -05:00
required: false,
description: 'Message to send to players when they are kicked',
default: 'Unassigned - automatically removed'
},
2020-10-27 16:31:05 -05:00
frequencyOfWarnings: {
required: false,
description: 'How often in seconds should we warn the player about being AFK?',
default: 30
},
afkTimer: {
required: false,
description: 'How long in minutes to wait before a player that is AFK is kicked',
default: 6
2020-10-22 19:22:34 -05:00
},
2020-10-27 16:31:05 -05:00
playerThreshold: {
2020-10-22 19:22:34 -05:00
required: false,
2020-10-27 16:31:05 -05:00
description:
'Player count required for Auto Kick to start kicking players to disable set to -1 to disable',
2020-10-22 19:22:34 -05:00
default: 93
},
2020-10-27 16:31:05 -05:00
queueThreshold: {
2020-10-22 19:22:34 -05:00
required: false,
2020-10-27 16:31:05 -05:00
description:
'The number of players in the queue before Auto Kick starts kicking players set to -1 to disable',
2020-10-22 19:22:34 -05:00
default: -1
},
2020-10-27 16:31:05 -05:00
roundStartDelay: {
required: false,
2020-10-27 16:31:05 -05:00
description:
'Time delay in minutes from start of the round before auto AFK starts kicking again',
default: 15
2020-10-27 16:31:05 -05:00
} /*, to be added in future when we can track admins better
2020-10-22 19:22:34 -05:00
ignoreAdmins:{
required: false,
description: 'Whether or not admins will be auto kicked for being unassigned',
default: false
2020-10-27 16:31:05 -05:00
} */
2020-10-22 16:06:28 -05:00
};
}
constructor(server, options) {
super();
2020-10-27 16:31:05 -05:00
this.kickTimeout = options.afkTimer * 60 * 1000;
this.warningInterval = options.frequencyOfWarnings * 1000;
this.gracePeriod = options.roundStartDelay * 60 * 1000;
this.betweenRounds = false;
this.trackedPlayers = {};
server.on('NEW_GAME', async (info) => {
this.betweenRounds = true;
updateTrackingList();
2020-10-27 16:31:05 -05:00
setTimeout(async () => {
this.betweenRounds = false;
}, this.gracePeriod);
});
2020-10-27 16:31:05 -05:00
server.on('PLAYER_SQUAD_CHANGE', async (player) => {
if (player.steamID in this.trackedPlayers && player.squadID !== null) {
untrackPlayer(player.steamID);
}
});
2020-10-22 16:06:28 -05:00
2020-10-27 16:31:05 -05:00
const runConditions = () => {
// return true; // force run for testing TODO: remove
return (
!this.betweenRounds ||
options.playerCountThreshold > 0 < server.players.count ||
options.queueThreshold > 0 < server.publicQueue + server.reserveQueue
);
};
2020-10-22 16:06:28 -05:00
2020-10-27 16:31:05 -05:00
const updateTrackingList = async () => {
if (!runConditions()) {
// clear all tracked players if run conditions are not met.
2020-10-27 16:31:05 -05:00
for (const steamID of Object.keys(this.trackedPlayers)) untrackPlayer(steamID);
2020-10-22 19:22:34 -05:00
return;
2020-10-27 16:31:05 -05:00
}
2020-10-27 16:31:05 -05:00
// await server.updatePlayerList(); //possibly unneeded as updates to player list are already common
// loop through players on server and start tracking players not in a squad
2020-10-22 19:22:34 -05:00
for (const player of server.players) {
2020-10-27 16:31:05 -05:00
const isTracked = player.steamID in this.trackedPlayers;
const isUnassigned = player.squadID === null;
const isAdmin = player.steamID in server.admins.map((a) => a.steamID);
2020-10-27 16:31:05 -05:00
if (isUnassigned && !isTracked && !isAdmin)
2020-10-26 02:03:45 -05:00
this.trackedPlayers[player.steamID] = trackPlayer(player); // start tracking player
2020-10-27 16:31:05 -05:00
if (!isUnassigned && isTracked) untrackPlayer(player.steamID); // tracked player joined a squad remove them (redundant afer addming PLAYER_SQUAD_CHANGE, keeping for now)
2020-10-22 16:06:28 -05:00
}
2020-10-27 16:31:05 -05:00
};
const msFormat = (ms) => {
const min = Math.floor((ms / 1000 / 60) << 0);
const sec = Math.floor((ms / 1000) % 60);
2020-10-26 02:03:45 -05:00
return `${min}:${sec}`;
2020-10-27 16:31:05 -05:00
};
2020-10-27 16:31:05 -05:00
const trackPlayer = (player) => {
2020-10-26 02:03:45 -05:00
Logger.verbose('AutoAFK', 1, `Tracking: ${player.name}`);
2020-10-27 16:31:05 -05:00
const tracker = {};
tracker.player = player;
2020-10-26 02:03:45 -05:00
tracker.startTime = Date.now();
2020-10-27 16:31:05 -05:00
tracker.warnTimerID = setInterval(async () => {
const timeLeft = msFormat(this.kickTimeout - (Date.now() - tracker.startTime));
2020-10-26 02:03:45 -05:00
Logger.verbose('AutoAFK', 1, `Warning: ${player.name} (${timeLeft})`);
server.rcon.warn(player.steamID, `${options.warningMessage} - ${timeLeft}`);
}, this.warningInterval);
2020-10-27 16:31:05 -05:00
tracker.kickTimerID = setTimeout(async () => {
2020-10-26 02:03:45 -05:00
Logger.verbose('AutoAFK', 1, `Kicked: ${player.name}`);
server.rcon.kick(player.steamID, options.kickMessage);
untrackPlayer(player.steamID);
}, this.kickTimeout);
2020-10-26 02:03:45 -05:00
return tracker;
2020-10-27 16:31:05 -05:00
};
2020-10-27 16:31:05 -05:00
const untrackPlayer = (steamID) => {
const tracker = this.trackedPlayers[steamID];
2020-10-26 02:03:45 -05:00
Logger.verbose('AutoAFK', 1, `[AutoAFK] unTrack: ${tracker.player.name}`);
clearInterval(tracker.warnTimerID); // clears warning interval
clearTimeout(tracker.kickTimerID); // clears kick timeout
delete this.trackedPlayers[steamID];
2020-10-27 16:31:05 -05:00
};
2020-10-27 16:31:05 -05:00
setInterval(updateTrackingList, 1 * 60 * 1000); // tracking list update loop
2020-10-22 19:22:34 -05:00
2020-10-27 16:31:05 -05:00
// clean up every 20 minutes, removes players no longer on the server that may be stuck in the tracking dict
const cleanupMS = 20 * 60 * 1000;
setInterval(() => {
for (const steamID of Object.keys(this.trackedPlayers))
if (!(steamID in server.players.map((p) => p.steamID))) untrackPlayer(steamID);
2020-10-22 19:22:34 -05:00
}, cleanupMS);
2020-10-22 16:06:28 -05:00
}
}