Skip to content

Commit 06c81d9

Browse files
committed
Overhaul prefix commands, config wizard, and logging UX
Add prefix command execution with usage validation and response coordinator fixes, expand config wizard with DM setup flow and channel/role selectors, unify ticket feedback logging, and adopt minimal log embeds across ticket and audit events. Improve notification embeds so titles stay in the title field while mentions render in descriptions.
1 parent 6101773 commit 06c81d9

259 files changed

Lines changed: 7028 additions & 8567 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ PORT_RETRY_ATTEMPTS=5
1919
CORS_ORIGIN=*
2020

2121
# PostgreSQL Configuration (Primary Database)
22+
# Railway: use the private POSTGRES_URL / DATABASE_URL variable (includes SSL).
23+
# Public proxy logs showing "invalid length of startup packet" or "SSL without ALPN"
24+
# are usually internet scanners — not your bot.
2225
POSTGRES_URL=postgresql://postgres:yourpassword@localhost:5432/titanbot
26+
POSTGRES_SSL=
2327
POSTGRES_HOST=localhost
2428
POSTGRES_PORT=5432
2529
POSTGRES_DB=titanbot

index.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
import './src/app.js';
2-
1+
import './src/app.js';

package-lock.json

Lines changed: 1 addition & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"dependencies": {
1818
"@discordjs/rest": "^2.6.1",
1919
"axios": "^1.15.2",
20-
"discord.js": "^14.15.3",
20+
"discord.js": "^14.26.4",
2121
"dotenv": "^17.2.3",
2222
"express": "^5.1.0",
2323
"node-cron": "^4.2.1",
@@ -26,7 +26,6 @@
2626
"winston-daily-rotate-file": "^5.0.0",
2727
"zod": "^3.25.76"
2828
},
29-
"devDependencies": {},
3029
"engines": {
3130
"node": ">=18.0.0"
3231
}

scripts/backup.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,4 +147,4 @@ run().catch((error) => {
147147
error: error.message
148148
});
149149
process.exit(1);
150-
});
150+
});

scripts/migrate.js

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ const createTables = async (client) => {
7474
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
7575
)`,
7676

77-
7877
`CREATE TABLE IF NOT EXISTS user_levels (
7978
id SERIAL PRIMARY KEY,
8079
user_id VARCHAR(255) NOT NULL,
@@ -86,7 +85,6 @@ const createTables = async (client) => {
8685
UNIQUE(user_id, guild_id)
8786
)`,
8887

89-
9088
`CREATE TABLE IF NOT EXISTS user_economy (
9189
id SERIAL PRIMARY KEY,
9290
user_id VARCHAR(255) NOT NULL,
@@ -98,7 +96,6 @@ const createTables = async (client) => {
9896
UNIQUE(user_id, guild_id)
9997
)`,
10098

101-
10299
`CREATE TABLE IF NOT EXISTS birthdays (
103100
id SERIAL PRIMARY KEY,
104101
user_id VARCHAR(255) NOT NULL,
@@ -110,7 +107,6 @@ const createTables = async (client) => {
110107
UNIQUE(user_id, guild_id)
111108
)`,
112109

113-
114110
`CREATE TABLE IF NOT EXISTS tickets (
115111
id SERIAL PRIMARY KEY,
116112
ticket_id VARCHAR(255) UNIQUE NOT NULL,
@@ -124,7 +120,6 @@ const createTables = async (client) => {
124120
closed_at TIMESTAMP
125121
)`,
126122

127-
128123
`CREATE TABLE IF NOT EXISTS giveaways (
129124
id SERIAL PRIMARY KEY,
130125
giveaway_id VARCHAR(255) UNIQUE NOT NULL,
@@ -139,7 +134,6 @@ const createTables = async (client) => {
139134
ends_at TIMESTAMP NOT NULL
140135
)`,
141136

142-
143137
`CREATE TABLE IF NOT EXISTS giveaway_entries (
144138
id SERIAL PRIMARY KEY,
145139
giveaway_id INTEGER NOT NULL,
@@ -149,7 +143,6 @@ const createTables = async (client) => {
149143
FOREIGN KEY(giveaway_id) REFERENCES giveaways(id) ON DELETE CASCADE
150144
)`,
151145

152-
153146
`CREATE TABLE IF NOT EXISTS reaction_roles (
154147
id SERIAL PRIMARY KEY,
155148
guild_id VARCHAR(255) NOT NULL,
@@ -162,7 +155,6 @@ const createTables = async (client) => {
162155
UNIQUE(message_id, emoji)
163156
)`,
164157

165-
166158
`CREATE TABLE IF NOT EXISTS welcome_system (
167159
id SERIAL PRIMARY KEY,
168160
guild_id VARCHAR(255) UNIQUE NOT NULL,
@@ -173,7 +165,6 @@ const createTables = async (client) => {
173165
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
174166
)`,
175167

176-
177168
`CREATE TABLE IF NOT EXISTS counters (
178169
id SERIAL PRIMARY KEY,
179170
guild_id VARCHAR(255) UNIQUE NOT NULL,
@@ -184,7 +175,6 @@ const createTables = async (client) => {
184175
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
185176
)`,
186177

187-
188178
`CREATE TABLE IF NOT EXISTS audit_logs (
189179
id SERIAL PRIMARY KEY,
190180
guild_id VARCHAR(255) NOT NULL,
@@ -286,7 +276,6 @@ const createTriggers = async (client) => {
286276
$$ LANGUAGE plpgsql;
287277
`);
288278

289-
290279
await client.query(`
291280
DROP TRIGGER IF EXISTS ${name} ON ${table};
292281
CREATE TRIGGER ${name}
@@ -391,4 +380,4 @@ if (command === 'apply') {
391380
} else {
392381
logger.error(`Unknown command: ${command}. Use one of: apply, check, status`);
393382
process.exit(1);
394-
}
383+
}

scripts/restore-drill.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,4 +205,4 @@ run().catch((error) => {
205205
error: error.message
206206
});
207207
process.exit(1);
208-
});
208+
});

scripts/restore.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,4 @@ run().catch((error) => {
134134
error: error.message
135135
});
136136
process.exit(1);
137-
});
137+
});

src/app.js

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,14 @@ class TitanBot extends Client {
2020

2121
GatewayIntentBits.Guilds,
2222
GatewayIntentBits.GuildMembers,
23-
24-
23+
2524
GatewayIntentBits.GuildMessages,
2625
GatewayIntentBits.GuildMessageReactions,
2726
GatewayIntentBits.MessageContent,
28-
27+
GatewayIntentBits.DirectMessages,
28+
2929
GatewayIntentBits.GuildVoiceStates,
30-
31-
30+
3231
GatewayIntentBits.GuildBans,
3332
],
3433
});
@@ -52,7 +51,7 @@ class TitanBot extends Client {
5251
startupLog('Initializing database...');
5352
const dbInstance = await initializeDatabase();
5453
this.db = dbInstance.db;
55-
54+
5655
// Check database status and report
5756
const dbStatus = this.db.getStatus();
5857
if (dbStatus.isDegraded) {
@@ -196,8 +195,8 @@ class TitanBot extends Client {
196195
hasStartedListening = true;
197196
this.webServer = server;
198197
startupLog(`✅ Web Server running on ${host}:${port}`);
199-
startupLog(`Health endpoint: http://localhost:${port}/health`);
200-
startupLog(`Ready endpoint: http://localhost:${port}/ready`);
198+
startupLog(`Health endpoint: http://${host}:${port}/health`);
199+
startupLog(`Ready endpoint: http://${host}:${port}/ready`);
201200
});
202201

203202
server.on('error', (error) => {
@@ -258,6 +257,7 @@ class TitanBot extends Client {
258257
}
259258
}
260259

260+
// Save cleaned counters if any were orphaned
261261
// Save cleaned counters if any were orphaned
262262
if (orphanedCounters.length > 0) {
263263
await saveServerCounters(this, guildId, validCounters);
@@ -270,21 +270,23 @@ class TitanBot extends Client {
270270
}
271271

272272
async loadHandlers() {
273+
startupLog('Loading handlers...');
273274
const handlers = [
274275
{ path: 'events', type: 'default', required: true },
275276
{ path: 'interactions', type: 'default', required: true }
276277
];
277278

278279
for (const handler of handlers) {
279280
try {
281+
startupLog(`Loading handler: ${handler.path}`);
280282
const module = await import(`./handlers/${handler.path}.js`);
281-
const loaderFn = handler.type.startsWith('named:')
282-
? module[handler.type.split(':')[1]]
283+
const loaderFn = handler.type.startsWith('named:')
284+
? module[handler.type.split(':')[1]]
283285
: module.default;
284-
286+
285287
if (typeof loaderFn === 'function') {
286288
await loaderFn(this);
287-
logger.info(`✅ Loaded ${handler.path}`);
289+
startupLog(`✅ Loaded ${handler.path}`);
288290
} else {
289291
throw new Error(`Invalid loader export from ${handler.path}`);
290292
}
@@ -319,6 +321,7 @@ class TitanBot extends Client {
319321
cron.getTasks().forEach(task => task.stop());
320322
logger.info('✅ Cron jobs stopped');
321323

324+
// Close database connection
322325
// Close database connection
323326
if (this.db && this.db.db) {
324327
logger.info('Closing database connection...');
@@ -332,15 +335,13 @@ class TitanBot extends Client {
332335
}
333336
}
334337

335-
336338
logger.info('Destroying Discord client...');
337339
if (this.isReady()) {
338340
try {
339341
this.destroy();
340342
logger.info('✅ Discord client destroyed');
341343
} catch (error) {
342-
343-
344+
344345
logger.warn('Discord client destroy warning (non-critical):', error.message);
345346
}
346347
}
@@ -368,19 +369,25 @@ try {
368369
});
369370

370371
process.on('unhandledRejection', (reason, promise) => {
372+
const code = reason?.code;
373+
if (code === 10062 || code === 40060 || code === 50027) {
374+
logger.warn('Recoverable Discord interaction rejection:', reason?.message || reason);
375+
return;
376+
}
377+
371378
logger.error('Unhandled Rejection at:', promise, 'reason:', reason);
372379
bot.shutdown('UNHANDLED_REJECTION');
373380
});
374381
};
375382

376383
setupShutdown();
377-
bot.start();
384+
bot.start().catch((error) => {
385+
logger.error('Fatal error during bot startup:', error);
386+
bot.shutdown('STARTUP_ERROR');
387+
});
378388
} catch (error) {
379389
logger.error('Fatal error during bot startup:', error);
380390
process.exit(1);
381391
}
382392

383-
export default TitanBot;
384-
385-
386-
393+
export default TitanBot;

src/commands/Birthday/birthday.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,4 @@ export default {
113113
});
114114
}
115115
}
116-
};
117-
118-
116+
};

0 commit comments

Comments
 (0)