Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve migration to eosIDs #354

Merged
merged 10 commits into from
Jul 3, 2024
Merged
61 changes: 61 additions & 0 deletions core/id-parser.js
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally don't like the approach of having a "unified" regex to match the IDs because it depends only on the hope of OWI not breaking things with typos or non-standard formats, which has already happened, an example is a log line which has Contoller instead of Controller.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All suggestions are implemented apart from one: changing getAdminsWithPermission(perm) to return players instead of IDs is not yet implemented. I'm all for implementing it, just want to make sure it is greenlit. Or, as a compromise, we could extend it to getAdminsWithPermission(perm, returnPlayers=false), that would allow for the new feature without potentially breaking custom plugins.
As for unified regex, I kindly disagree. master implementation is prone to: changing ordering, extra spacing, lack of steamID (some regexes in master were fixed to have steam as an optional but not all), renaming a key. This implementation will break only if delimiters are broken. Swapping, cloning, removing arbitrary k:v pairs, introducing new IDs, surrounding colons with spaces won't break it. Renaming a key will break things down the line but not the parser itself. And when OWI eventually breaks some output again - we can patch that specific item within it's parser, while everything else follows the same logic and is easy to remember.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm good with the new changes after my first review, and with keeping your implementation of the ID parser since you proved to have went through an analysis of all the side effects of both your implementation and the one currently on the master branch.

Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
const ID_MATCHER = /\s*(?<name>[^\s:]+)\s*:\s*(?<id>[^\s]+)/g;

// COMMON CONSTANTS

/** All possible IDs that a player can have. */
export const playerIdNames = ["steamID", "eosID"];

// PARSING AND ITERATION

/**
* Main function intended for parsing `Online IDs:` body.
* @arg {string} idsStr - String with ids. Extra whitespace is allowed,
* Number of {platform: ID} pairs can be arbitrary. String example:
" platform1:id1 platform2: id2 platform3 : id3 "
Keys and values are not allowed contain colons or whitespace
characters.
* @returns {IdsIterator} An iterator that yields {platform: ID} pairs.
*/
export const iterateIDs = (idsStr) => {
return new IdsIterator(idsStr.matchAll(ID_MATCHER));
};

class IdsIterator {
constructor(matchIterator) {
this.inner = matchIterator;
}

[Symbol.iterator]() {
return this;
}

next() {
const match = this.inner.next();
if (match.done) return { value: undefined, done: true };
return { value: { key: match.value[1], value: match.value[2] }, done: false };
}

forEach(callbackFn) {
for (const { key, value } of this) callbackFn(key, value);
}
}

// FORMATTING

/**
* Generates capitalized ID names. Examples:
* steam -> SteamID
* EOSID -> EOSID
*/
export const capitalID = (str) => {
return str.charAt(0).toUpperCase() + str.slice(1) + 'ID';
};

/**
* Generates lowercase ID names. Examples:
* steam -> steamID
* EOSID -> eosID
*/
export const lowerID = (str) => {
return str.toLowerCase() + 'ID';
};
14 changes: 5 additions & 9 deletions core/log-parser/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,8 @@ export default class LogParser extends EventEmitter {

this.eventStore = {
disconnected: {}, // holding area, cleared on map change.
players: [], // persistent data, steamid, controller, suffix.
playersEOS: [], // proxies from EOSID to persistent data, steamid, controller, suffix.
connectionIdToSteamID: new Map(),
players: {}, // persistent data, steamid, controller, suffix.
session: {}, // old eventstore, nonpersistent data
clients: {}, // used in the connection chain before we resolve a player.
lastConnection: {}, // used to store the last client connection data to then associate a steamid
joinRequests: []
};

Expand Down Expand Up @@ -74,10 +70,10 @@ export default class LogParser extends EventEmitter {
clearEventStore() {
Logger.verbose('LogParser', 2, 'Cleaning Eventstore');
for (const player of Object.values(this.eventStore.players)) {
if (this.eventStore.disconnected[player.steamID] === true) {
Logger.verbose('LogParser', 2, `Removing ${player.steamID} from eventStore`);
delete this.eventStore.players[player.steamID];
delete this.eventStore.disconnected[player.steamID];
if (this.eventStore.disconnected[player.eosID] === true) {
Logger.verbose('LogParser', 2, `Removing ${player.eosID} from eventStore`);
delete this.eventStore.players[player.eosID];
delete this.eventStore.disconnected[player.eosID];
}
}
this.eventStore.session = {};
Expand Down
1 change: 1 addition & 0 deletions core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"exports": {
"./log-parser": "./log-parser/index.js",
"./constants": "./constants.js",
"./id-parser": "./id-parser.js",
"./logger": "./logger.js",
"./rcon": "./rcon.js"
},
Expand Down
12 changes: 6 additions & 6 deletions core/rcon.js
Original file line number Diff line number Diff line change
Expand Up @@ -414,15 +414,15 @@ export default class Rcon extends EventEmitter {
return util.inspect(decodedPacket, { breakLength: Infinity });
}

async warn(steamID, message) {
await this.execute(`AdminWarn "${steamID}" ${message}`);
async warn(anyID, message) {
await this.execute(`AdminWarn "${anyID}" ${message}`);
}

async kick(steamID, reason) {
await this.execute(`AdminKick "${steamID}" ${reason}`);
async kick(anyID, reason) {
await this.execute(`AdminKick "${anyID}" ${reason}`);
}

async forceTeamChange(steamID) {
await this.execute(`AdminForceTeamChange "${steamID}"`);
async forceTeamChange(anyID) {
await this.execute(`AdminForceTeamChange "${anyID}"`);
}
}
Loading