Skip to content

Commit 881faa2

Browse files
committed
Temporary solution to fcm notifications problem
1 parent c30143c commit 881faa2

16 files changed

+875
-28
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ node_modules
22
.env
33
instances
44
credentials
5+
authtokens
56
maps
67
logs
78
temp

Dockerfile

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ RUN npm install
1010
COPY . /app
1111

1212
VOLUME [ "/app/credentials" ]
13+
VOLUME [ "/app/authtokens" ]
1314
VOLUME [ "/app/instances" ]
1415
VOLUME [ "/app/logs" ]
1516
VOLUME [ "/app/maps" ]

docker-compose.yml

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ services:
33
app:
44
volumes:
55
- ./credentials:/app/credentials
6+
- ./authtokens:/app/authtokens
67
- ./instances:/app/instances
78
- ./logs:/app/logs
89
- ./maps:/app/maps

index.ts

+4
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ function createMissingDirectories() {
5353
Fs.mkdirSync(Path.join(__dirname, 'credentials'));
5454
}
5555

56+
if (!Fs.existsSync(Path.join(__dirname, 'authtokens'))) {
57+
Fs.mkdirSync(Path.join(__dirname, 'authtokens'));
58+
}
59+
5660
if (!Fs.existsSync(Path.join(__dirname, 'maps'))) {
5761
Fs.mkdirSync(Path.join(__dirname, 'maps'));
5862
}

src/commands/authtoken.js

+286
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
/*
2+
Copyright (C) 2024 Alexander Emanuelsson (alexemanuelol)
3+
4+
This program is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
This program is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU General Public License for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
17+
https://github.com/alexemanuelol/rustplusplus
18+
19+
*/
20+
21+
const _ = require('lodash');
22+
const Builder = require('@discordjs/builders');
23+
24+
const Config = require('../../config');
25+
const DiscordEmbeds = require('../discordTools/discordEmbeds.js');
26+
const DiscordMessages = require('../discordTools/discordMessages.js');
27+
const DiscordTools = require('../discordTools/discordTools.js');
28+
const InstanceUtils = require('../util/instanceUtils.js');
29+
const AuthTokenListenerTemp = require('../util/AuthTokenListener.js');
30+
31+
module.exports = {
32+
name: 'authtoken',
33+
34+
getData(client, guildId) {
35+
return new Builder.SlashCommandBuilder()
36+
.setName('authtoken')
37+
.setDescription('Set/Remove Authentication Token.')
38+
.addSubcommand(subcommand => subcommand
39+
.setName('add')
40+
.setDescription('Add Authentication Token.')
41+
.addStringOption(option => option
42+
.setName('token')
43+
.setDescription('Authentication Token.')
44+
.setRequired(true))
45+
.addStringOption(option => option
46+
.setName('steam_id')
47+
.setDescription('Steam ID.')
48+
.setRequired(true))
49+
.addStringOption(option => option
50+
.setName('issued_date')
51+
.setDescription('Issued date of the Authentication Token.')
52+
.setRequired(true))
53+
.addStringOption(option => option
54+
.setName('expire_date')
55+
.setDescription('Expire date of the Authentication Token.')
56+
.setRequired(true))
57+
.addBooleanOption(option => option
58+
.setName('hoster')
59+
.setDescription('Host the bot')
60+
.setRequired(false)))
61+
.addSubcommand(subcommand => subcommand
62+
.setName('remove')
63+
.setDescription('Remove Authentication Token.')
64+
.addStringOption(option => option
65+
.setName('steam_id')
66+
.setDescription('The SteamId of the Authentication Token to be removed.')
67+
.setRequired(false)))
68+
.addSubcommand(subcommand => subcommand
69+
.setName('show')
70+
.setDescription('Show the currently registered authentication token users.'))
71+
.addSubcommand(subcommand => subcommand
72+
.setName('set_hoster')
73+
.setDescription('Set the main hoster.')
74+
.addStringOption(option => option
75+
.setName('steam_id')
76+
.setDescription('The SteamId of the new hoster.')
77+
.setRequired(false)));
78+
},
79+
80+
async execute(client, interaction) {
81+
const verifyId = Math.floor(100000 + Math.random() * 900000);
82+
client.logInteraction(interaction, verifyId, 'slashCommand');
83+
84+
if (!await client.validatePermissions(interaction)) return;
85+
await interaction.deferReply({ ephemeral: true });
86+
87+
switch (interaction.options.getSubcommand()) {
88+
case 'add': {
89+
addAuthToken(client, interaction, verifyId);
90+
} break;
91+
92+
case 'remove': {
93+
removeAuthToken(client, interaction, verifyId);
94+
} break;
95+
96+
case 'show': {
97+
showAuthTokenUsers(client, interaction, verifyId);
98+
} break;
99+
100+
case 'set_hoster': {
101+
setHoster(client, interaction, verifyId);
102+
} break;
103+
104+
default: {
105+
} break;
106+
}
107+
},
108+
};
109+
110+
async function addAuthToken(client, interaction, verifyId) {
111+
const guildId = interaction.guildId;
112+
const authTokens = InstanceUtils.readAuthTokensFile(guildId);
113+
const steamId = interaction.options.getString('steam_id');
114+
const isHoster = interaction.options.getBoolean('host') || Object.keys(authTokens).length === 1;
115+
116+
if (Object.keys(authTokens) !== 1 && isHoster) {
117+
if (Config.discord.needAdminPrivileges && !client.isAdministrator(interaction)) {
118+
const str = client.intlGet(interaction.guildId, 'missingPermission');
119+
client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str));
120+
client.log(client.intlGet(null, 'warningCap'), str);
121+
return;
122+
}
123+
}
124+
125+
if (steamId in authTokens) {
126+
const str = `Authentication Token for steamId: ${steamId} is already registered.`;
127+
await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str));
128+
client.log(client.intlGet(null, 'warningCap'), str);
129+
return;
130+
}
131+
132+
authTokens[steamId] = new Object();
133+
authTokens[steamId].auth_token = interaction.options.getString('token');
134+
authTokens[steamId].issued_date = interaction.options.getString('issued_date');
135+
authTokens[steamId].expire_date = interaction.options.getString('expire_date');
136+
authTokens[steamId].discordUserId = interaction.member.user.id;
137+
138+
if (isHoster) authTokens.hoster = steamId;
139+
140+
InstanceUtils.writeAuthTokensFile(guildId, authTokens);
141+
142+
await AuthTokenListenerTemp.startNewAuthTokenListener(client, interaction.guildId, steamId);
143+
if (!isHoster) {
144+
const rustplus = client.rustplusInstances[guildId];
145+
if (rustplus && rustplus.team.leaderSteamId === steamId) {
146+
rustplus.updateLeaderRustPlusLiteInstance();
147+
}
148+
}
149+
150+
client.log(client.intlGet(null, 'infoCap'), client.intlGet(null, 'slashCommandValueChange', {
151+
id: `${verifyId}`,
152+
value: `add, ${steamId}, ` +
153+
`${authTokens[steamId].discordUserId}, ` +
154+
`${isHoster}, ` +
155+
`${authTokens[steamId].token}, ` +
156+
`${authTokens[steamId].issued_date}, ` +
157+
`${authTokens[steamId].expire_date}`
158+
}));
159+
160+
const str = `Authentication Token were added successfully for steamId: ${steamId}.`
161+
await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(0, str));
162+
client.log(client.intlGet(null, 'infoCap'), str);
163+
}
164+
165+
async function removeAuthToken(client, interaction, verifyId) {
166+
const guildId = interaction.guildId;
167+
const authTokens = InstanceUtils.readAuthTokensFile(guildId);
168+
let steamId = interaction.options.getString('steam_id');
169+
170+
if (steamId && (steamId in authTokens) && authTokens[steamId].discordUserId !== interaction.member.user.id) {
171+
if (Config.discord.needAdminPrivileges && !client.isAdministrator(interaction)) {
172+
const str = client.intlGet(interaction.guildId, 'missingPermission');
173+
client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str));
174+
client.log(client.intlGet(null, 'warningCap'), str);
175+
return;
176+
}
177+
}
178+
179+
if (!steamId) {
180+
for (const authToken of Object.keys(authTokens)) {
181+
if (authToken === 'hoster') continue;
182+
183+
if (authTokens[authToken].discordUserId === interaction.member.user.id) {
184+
steamId = authToken;
185+
break;
186+
}
187+
}
188+
}
189+
190+
if (!(steamId in authTokens)) {
191+
const str = `Authentication Token for steamId: ${steamId} does not exist.`;
192+
await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str));
193+
client.log(client.intlGet(null, 'warningCap'), str);
194+
return;
195+
}
196+
197+
if (!(client.authTokenListenerIntervalIds[guildId])) {
198+
client.authTokenListenerIntervalIds[guildId] = new Object();
199+
}
200+
201+
if (client.authTokenListenerIntervalIds[guildId] &&
202+
client.authTokenListenerIntervalIds[guildId][steamId]) {
203+
clearInterval(client.authTokenListenerIntervalIds[guildId][steamId]);
204+
delete client.authTokenListenerIntervalIds[guildId][steamId];
205+
}
206+
207+
if (client.authTokenReadNotifications[guildId] &&
208+
client.authTokenReadNotifications[guildId][steamId]) {
209+
delete client.authTokenReadNotifications[guildId][steamId];
210+
}
211+
212+
if (steamId === authTokens.hoster) {
213+
authTokens.hoster = null;
214+
}
215+
216+
delete authTokens[steamId];
217+
InstanceUtils.writeAuthTokensFile(guildId, authTokens);
218+
219+
client.log(client.intlGet(null, 'infoCap'), client.intlGet(null, 'slashCommandValueChange', {
220+
id: `${verifyId}`,
221+
value: `remove, ${steamId}`
222+
}));
223+
224+
const str = `Authentication Token for steamId: ${steamId} was removed successfully.`;
225+
await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(0, str));
226+
client.log(client.intlGet(null, 'infoCap'), str);
227+
}
228+
229+
async function showAuthTokenUsers(client, interaction, verifyId) {
230+
client.log(client.intlGet(null, 'infoCap'), client.intlGet(null, 'slashCommandValueChange', {
231+
id: `${verifyId}`,
232+
value: `show`
233+
}));
234+
235+
await DiscordMessages.sendAuthTokensShowMessage(interaction);
236+
}
237+
238+
async function setHoster(client, interaction, verifyId) {
239+
const guildId = interaction.guildId;
240+
const authTokens = InstanceUtils.readAuthTokensFile(guildId);
241+
let steamId = interaction.options.getString('steam_id');
242+
243+
if (Config.discord.needAdminPrivileges && !client.isAdministrator(interaction)) {
244+
const str = client.intlGet(interaction.guildId, 'missingPermission');
245+
client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str));
246+
client.log(client.intlGet(null, 'warningCap'), str);
247+
return;
248+
}
249+
250+
if (!steamId) {
251+
steamId = Object.keys(authTokens).find(e => authTokens[e] &&
252+
authTokens[e].discordUserId === interaction.member.user.id);
253+
}
254+
255+
if (!(steamId in authTokens)) {
256+
const str = `Authentication Token for steamId: ${steamId} does not exist.`;
257+
await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(1, str));
258+
client.log(client.intlGet(null, 'warningCap'), str);
259+
return;
260+
}
261+
262+
authTokens.hoster = steamId;
263+
InstanceUtils.writeAuthTokensFile(guildId, authTokens);
264+
265+
const instance = client.getInstance(guildId);
266+
const rustplus = client.rustplusInstances[guildId];
267+
if (rustplus) {
268+
instance.activeServer = null;
269+
client.setInstance(guildId, instance);
270+
client.resetRustplusVariables(guildId);
271+
rustplus.disconnect();
272+
delete client.rustplusInstances[guildId];
273+
await DiscordMessages.sendServerMessage(guildId, rustplus.serverId);
274+
}
275+
276+
await AuthTokenListenerTemp.startNewAuthTokenListener(client, interaction.guildId, steamId);
277+
278+
client.log(client.intlGet(null, 'infoCap'), client.intlGet(null, 'slashCommandValueChange', {
279+
id: `${verifyId}`,
280+
value: `setHoster, ${steamId}`
281+
}));
282+
283+
const str = `Authentication Token hoster was successfully set to steamId: ${steamId}.`;
284+
await client.interactionEditReply(interaction, DiscordEmbeds.getActionInfoEmbed(0, str));
285+
client.log(client.intlGet(null, 'infoCap'), str);
286+
}

src/discordEvents/guildCreate.js

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ module.exports = {
2323
async execute(client, guild) {
2424
require('../util/CreateInstanceFile')(client, guild);
2525
require('../util/CreateCredentialsFile')(client, guild);
26+
require('../util/CreateAuthTokensFile')(client, guild);
2627
client.fcmListenersLite[guild.id] = new Object();
2728

2829
client.loadGuildIntl(guild.id);

src/discordEvents/guildMemberRemove.js

+31-16
Original file line numberDiff line numberDiff line change
@@ -26,27 +26,42 @@ module.exports = {
2626
const guildId = member.guild.id;
2727
const userId = member.user.id;
2828

29-
const credentials = InstanceUtils.readCredentialsFile(guildId);
29+
//const credentials = InstanceUtils.readCredentialsFile(guildId);
30+
const authTokens = InstanceUtils.readAuthTokensFile(guildId);
3031

31-
const steamId = Object.keys(credentials).find(e => credentials[e] && credentials[e].discordUserId === userId);
32+
//const steamId = Object.keys(credentials).find(e => credentials[e] && credentials[e].discordUserId === userId);
33+
const steamId = Object.keys(authTokens).find(e => authTokens[e] && authTokens[e].discordUserId === userId);
3234

33-
if (!(steamId in credentials)) return;
35+
//if (!(steamId in credentials)) return;
36+
if (!(steamId in authTokens)) return;
3437

35-
if (steamId === credentials.hoster) {
36-
if (client.fcmListeners[guildId]) {
37-
client.fcmListeners[guildId].destroy();
38-
}
39-
delete client.fcmListeners[guildId];
40-
credentials.hoster = null;
38+
//if (steamId === credentials.hoster) {
39+
// if (client.fcmListeners[guildId]) {
40+
// client.fcmListeners[guildId].destroy();
41+
// }
42+
// delete client.fcmListeners[guildId];
43+
// credentials.hoster = null;
44+
//}
45+
//else {
46+
// if (client.fcmListenersLite[guildId][steamId]) {
47+
// client.fcmListenersLite[guildId][steamId].destroy();
48+
// }
49+
// delete client.fcmListenersLite[guildId][steamId];
50+
//}
51+
52+
if (client.authTokenListenerIntervalsIds[guildId] &&
53+
client.authTokenListenerIntervalsIds[guildId][steamId]) {
54+
clearInterval(client.authTokenListenerIntervalsIds[guildId][steamId]);
55+
delete client.authTokenListenerIntervalsIds[guildId][steamId];
4156
}
42-
else {
43-
if (client.fcmListenersLite[guildId][steamId]) {
44-
client.fcmListenersLite[guildId][steamId].destroy();
45-
}
46-
delete client.fcmListenersLite[guildId][steamId];
57+
58+
if (steamId === authTokens.hoster) {
59+
authTokens.hoster = null;
4760
}
4861

49-
delete credentials[steamId];
50-
InstanceUtils.writeCredentialsFile(guildId, credentials);
62+
//delete credentials[steamId];
63+
delete authTokens[steamId];
64+
//InstanceUtils.writeCredentialsFile(guildId, credentials);
65+
InstanceUtils.writeAuthTokensFile(guildId, authTokens);
5166
},
5267
}

src/discordEvents/ready.js

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ module.exports = {
3131
for (const guild of client.guilds.cache) {
3232
require('../util/CreateInstanceFile')(client, guild[1]);
3333
require('../util/CreateCredentialsFile')(client, guild[1]);
34+
require('../util/CreateAuthTokensFile')(client, guild[1]);
3435
client.fcmListenersLite[guild[0]] = new Object();
3536
}
3637

0 commit comments

Comments
 (0)