This repository was archived by the owner on Sep 3, 2025. It is now read-only.
Repository navigation
Expand file tree
/
Copy pathindex.js
More file actions
225 lines (196 loc) · 7.57 KB
/
Copy pathindex.js
File metadata and controls
225 lines (196 loc) · 7.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/*
Domain-Unchained, src of the discord bot, that uses openai api to generate messages
Copyright (C) 2025 Anchietae
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
const Sentry = require("@sentry/bun");
// init sentry for error tracking
Sentry.init({
dsn: "https://33b9563a3d438b9ea893d5e0852bed2d@o4509481270902784.ingest.de.sentry.io/4509481272410192",
release: `domain@${require("./package.json").version}`,
attachStacktrace: true,
beforeSend(event) {
if (event.server_name) {
delete event.server_name;
}
},
ignoreErrors: [],
});
require("./utils/betterLogs.js");
process.on("uncaughtException", (error) => {
Sentry.captureException(error);
console.error("Uncaught Exception:", error);
});
process.on("unhandledRejection", (reason, promise) => {
Sentry.captureException(
reason instanceof Error
? reason
: new Error(`Unhandled Rejection: ${reason}`),
);
console.error("Unhandled Rejection at:", promise, "reason:", reason);
});
const log = require("./utils/betterLogs");
const { Events } = require("discord.js");
const state = require("./initializers/state");
const { botReady, botOffline } = require("./functions/presenceManager");
const { initializeSpinner, stopSpinner } = require("./utils/processInfo");
const {
configurationChecker,
loadConfig,
loadStrings,
} = require("./initializers/configuration");
const { loadAllHistories, saveHistory } = require("./db/history.js");
// async main thread hell yeah
async function main() {
state.locationHelper.init = "index.js/main startup";
global.dirname = __dirname;
const needsFullSetup = await configurationChecker();
if (needsFullSetup) {
log(
"Bot needs configuration. Please edit config.toml and restart.",
"info",
);
return;
}
const config = loadConfig();
state.config = config;
loadStrings(config);
state.history = await loadAllHistories();
// Continue with normal bot initialization if setup is complete
const allowInteraction = !process.argv.includes("--no-interaction");
await initializeSpinner();
log(`Starting Domain-Unchained ${state.version}`, "info");
if (!allowInteraction) {
log("Interaction is disabled via --no-interaction flag.", "warn");
}
const { deleteArtifacts, deleteUploadedItems } = require("./utils/cleanup");
await deleteArtifacts();
await deleteUploadedItems();
const initData = require("./utils/initData");
await initData(); // init stuff that will be used by the bot
const getBannedSites = require("./utils/bannedSiteGen");
// we don't need to wait for this, bc it might take a long time
// noinspection ES6MissingAwait
getBannedSites();
// imports
const { model } = require("./initializers/openaiClient");
const { messageHandler } = require("./eventHandlers/messageHandler");
// initialize stuff inside async thingy
state.locationHelper.init = "index.js/discordClient";
let discordClientReady = false;
const discordClient = require("./initializers/botClient");
discordClient.once(Events.ClientReady, () => {
discordClientReady = true;
});
// wait for client to finish auth
while (!discordClientReady) {
await new Promise((resolve) => setTimeout(resolve, 100));
}
global.discordClient = discordClient;
const emojiResolver = require("./initializers/emojiResolver");
await emojiResolver();
const leaveUnknownServers = require("./initializers/leaveUnknownServers");
await leaveUnknownServers(discordClient);
// announce commands to servers
const announceCommands = require("./commands/setCommands");
await announceCommands(discordClient);
// ha jol megy minden akkor siman kiolvasom historyt statebol
const generateHistory = require("./initializers/historyCreator");
await generateHistory();
global.openaiModel = await model(state.history);
setInterval(async () => {
for (const channelId in state.history) {
// prevent tempchannels from being saved
if (Object.hasOwn(state.tempChannels, channelId)) {
continue;
}
if (Object.hasOwn(state.history, channelId)) {
await saveHistory(channelId, state.history[channelId]);
}
}
}, 60000);
await botReady(discordClient);
// sync sleeping state
const schedSleep = require("./functions/sleeping");
schedSleep(config.SLEEPINGRANGE, discordClient);
// register some handlers
process.on("SIGINT", () => gracefulShutdown("SIGINT", discordClient));
process.on("SIGTERM", () => gracefulShutdown("SIGTERM", discordClient));
process.on("SIGHUP", () => gracefulShutdown("SIGHUP", discordClient));
process.on("beforeExit", () => gracefulShutdown("beforeExit", discordClient));
process.on("exit", () => gracefulShutdown("exit", discordClient));
await stopSpinner(true, "Domain-Unchained ready");
state.locationHelper.init = "init complete";
require("./cronJobs/cronReset"); // this should be run after bot is ready
require("./cronJobs/repDecay");
require("./webui/index");
discordClient.on(Events.MessageCreate, async (message) => {
if (!allowInteraction) return;
// ignore messages when "sleeping"
if (state.isSleeping) return;
// noinspection JSUnresolvedReference
await messageHandler(message, discordClient, global.openaiModel);
});
discordClient.on("interactionCreate", async (interaction) => {
if (!interaction.isCommand()) return;
// noinspection JSUnresolvedReference
const command = discordClient.commands.get(interaction.commandName);
if (!command) return;
try {
await command.execute(interaction);
} catch (error) {
console.error(error);
// skizofrenias az intellijm, pont mint en
// noinspection JSCheckFunctionSignatures,JSDeprecatedSymbols
await interaction.editReply({
content: state.strings.commandRunFailed,
flags: ["Ephemeral"],
});
}
});
}
async function gracefulShutdown(signal, client) {
const { deleteArtifacts, deleteUploadedItems } = require("./utils/cleanup");
await initializeSpinner();
log(`Received ${signal}`, "info");
try {
// set bot to offline
// igen, jol latod csak ide kell a global, ja varj
// mostmar nem kell global
await botOffline(client);
await client.destroy();
// nagyon fontos, elmentjuk a historyt
for (const channelId in state.history) {
if (Object.hasOwn(state.history, channelId)) {
await saveHistory(channelId, state.history[channelId]);
}
}
await deleteArtifacts();
await deleteUploadedItems();
await stopSpinner(true, "Domain-Unchained shutting down");
} catch (e) {
console.error(`Error while doing stuff before shutdown: ${e}`);
} finally {
setTimeout(() => {
process.exit(0);
}, 1000);
}
}
main()
.then()
.catch((error) => {
console.error(`Unhandled error in main: ${JSON.stringify(error, null, 2)}`);
console.error("Stack trace:", error.stack);
console.error(state.locationHelper.init);
stopSpinner(false, "Bot crashed during startup.").then();
process.exit(1);
});