supabase setup
This commit is contained in:
14
src/Bot.js
14
src/Bot.js
@@ -38,9 +38,19 @@ class Bot {
|
||||
this.client.on('interactionCreate', this.handleInteraction.bind(this));
|
||||
}
|
||||
|
||||
async start(token) {
|
||||
// In the start method, add Supabase connection test:
|
||||
async start(token) {
|
||||
console.log("Starting bot...");
|
||||
try {
|
||||
// Test Supabase connection first
|
||||
if (this.supabaseService) {
|
||||
const connected = await this.supabaseService.testConnection();
|
||||
if (!connected) {
|
||||
console.warn('Supabase connection failed. Subscription features will be disabled.');
|
||||
this.subscriptionCommands = null;
|
||||
}
|
||||
}
|
||||
|
||||
await this.client.login(token);
|
||||
console.log("Login successful");
|
||||
|
||||
@@ -52,7 +62,7 @@ class Bot {
|
||||
console.error("Startup failed:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async stop() {
|
||||
console.log("Stopping bot...");
|
||||
|
||||
@@ -1,62 +1,190 @@
|
||||
const { EmbedBuilder } = require('discord.js');
|
||||
|
||||
class SubscriptionCommands {
|
||||
constructor(supabaseService) {
|
||||
this.supabaseService = supabaseService;
|
||||
constructor(supabase) {
|
||||
this.supabase = supabase;
|
||||
}
|
||||
|
||||
async handleSubscribe(interaction) {
|
||||
const gameName = interaction.options.getString('game');
|
||||
const channel = interaction.options.getChannel('channel') || interaction.channel;
|
||||
|
||||
try {
|
||||
// Defer the reply immediately
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
const gameName = interaction.options.getString('game');
|
||||
const channel = interaction.options.getChannel('channel');
|
||||
const guildId = interaction.guildId;
|
||||
|
||||
// Perform the subscription operation
|
||||
await this.supabaseService.addSubscription(interaction.guildId, gameName, channel.id);
|
||||
// First, get or create server record
|
||||
const { data: serverData, error: serverError } = await this.supabase
|
||||
.from('servers')
|
||||
.upsert({
|
||||
discord_server_id: guildId,
|
||||
server_name: interaction.guild.name
|
||||
}, {
|
||||
onConflict: 'discord_server_id',
|
||||
returning: true
|
||||
});
|
||||
|
||||
if (serverError) {
|
||||
console.error('Server upsert error:', serverError);
|
||||
await interaction.reply({ content: 'Failed to process server registration.', ephemeral: true });
|
||||
return;
|
||||
}
|
||||
|
||||
// Get game ID
|
||||
const { data: gameData, error: gameError } = await this.supabase
|
||||
.from('games')
|
||||
.select('id')
|
||||
.eq('name', gameName)
|
||||
.eq('active', true)
|
||||
.single();
|
||||
|
||||
if (gameError || !gameData) {
|
||||
console.error('Game fetch error:', gameError);
|
||||
await interaction.reply({ content: `Game "${gameName}" not found or not active.`, ephemeral: true });
|
||||
return;
|
||||
}
|
||||
|
||||
// Create subscription
|
||||
const { error: prefError } = await this.supabase
|
||||
.from('server_game_preferences')
|
||||
.upsert({
|
||||
server_id: serverData[0].id,
|
||||
game_id: gameData.id,
|
||||
notification_channel_id: channel.id
|
||||
}, {
|
||||
onConflict: '(server_id,game_id)',
|
||||
returning: true
|
||||
});
|
||||
|
||||
if (prefError) {
|
||||
console.error('Preference upsert error:', prefError);
|
||||
await interaction.reply({ content: 'Failed to save subscription.', ephemeral: true });
|
||||
return;
|
||||
}
|
||||
|
||||
await interaction.reply({
|
||||
content: `Successfully subscribed to ${gameName} notifications in ${channel}.`,
|
||||
ephemeral: true
|
||||
});
|
||||
|
||||
// Edit the deferred reply with the success message
|
||||
await interaction.editReply(`Successfully subscribed to ${gameName} notifications in ${channel}.`);
|
||||
} catch (error) {
|
||||
console.error('Error subscribing:', error);
|
||||
|
||||
// If we failed to defer earlier, try to reply now
|
||||
if (!interaction.deferred && !interaction.replied) {
|
||||
await interaction.reply({ content: 'An error occurred while subscribing. Please try again.', ephemeral: true }).catch(console.error);
|
||||
} else {
|
||||
// If we successfully deferred earlier, edit the reply
|
||||
await interaction.editReply('An error occurred while subscribing. Please try again.').catch(console.error);
|
||||
if (!interaction.replied && !interaction.deferred) {
|
||||
await interaction.reply({
|
||||
content: 'An error occurred while processing your subscription.',
|
||||
ephemeral: true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async handleUnsubscribe(interaction) {
|
||||
const gameName = interaction.options.getString('game');
|
||||
|
||||
try {
|
||||
await this.supabaseService.removeSubscription(interaction.guildId, gameName);
|
||||
await interaction.reply(`Successfully unsubscribed from ${gameName} notifications.`);
|
||||
const gameName = interaction.options.getString('game');
|
||||
const guildId = interaction.guildId;
|
||||
|
||||
// Get server ID
|
||||
const { data: serverData, error: serverError } = await this.supabase
|
||||
.from('servers')
|
||||
.select('id')
|
||||
.eq('discord_server_id', guildId)
|
||||
.single();
|
||||
|
||||
if (serverError) {
|
||||
await interaction.reply({ content: 'Server not found.', ephemeral: true });
|
||||
return;
|
||||
}
|
||||
|
||||
// Get game ID
|
||||
const { data: gameData, error: gameError } = await this.supabase
|
||||
.from('games')
|
||||
.select('id')
|
||||
.eq('name', gameName)
|
||||
.single();
|
||||
|
||||
if (gameError) {
|
||||
await interaction.reply({ content: 'Game not found.', ephemeral: true });
|
||||
return;
|
||||
}
|
||||
|
||||
// Delete subscription
|
||||
const { error: deleteError } = await this.supabase
|
||||
.from('server_game_preferences')
|
||||
.delete()
|
||||
.eq('server_id', serverData.id)
|
||||
.eq('game_id', gameData.id);
|
||||
|
||||
if (deleteError) {
|
||||
await interaction.reply({ content: 'Failed to remove subscription.', ephemeral: true });
|
||||
return;
|
||||
}
|
||||
|
||||
await interaction.reply({
|
||||
content: `Successfully unsubscribed from ${gameName} notifications.`,
|
||||
ephemeral: true
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error unsubscribing:', error);
|
||||
await interaction.reply('An error occurred while unsubscribing. Please try again.');
|
||||
if (!interaction.replied && !interaction.deferred) {
|
||||
await interaction.reply({
|
||||
content: 'An error occurred while processing your unsubscription.',
|
||||
ephemeral: true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async handleListSubscriptions(interaction) {
|
||||
try {
|
||||
const subscriptions = await this.supabaseService.getSubscriptions(interaction.guildId);
|
||||
if (subscriptions.length === 0) {
|
||||
await interaction.reply('This server has no active subscriptions.');
|
||||
} else {
|
||||
const subscriptionList = subscriptions.map(sub =>
|
||||
`${sub.game_name} in <#${sub.channel_id}>`
|
||||
).join('\n');
|
||||
await interaction.reply(`Active subscriptions:\n${subscriptionList}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error listing subscriptions:', error);
|
||||
await interaction.reply('An error occurred while fetching subscriptions. Please try again.');
|
||||
}
|
||||
}
|
||||
const guildId = interaction.guildId;
|
||||
|
||||
// Get all subscriptions for this server
|
||||
const { data: subscriptions, error } = await this.supabase
|
||||
.from('server_game_preferences')
|
||||
.select(`
|
||||
games (name),
|
||||
notification_channel_id,
|
||||
servers!inner (discord_server_id)
|
||||
`)
|
||||
.eq('servers.discord_server_id', guildId);
|
||||
|
||||
if (error) {
|
||||
await interaction.reply({ content: 'Failed to fetch subscriptions.', ephemeral: true });
|
||||
return;
|
||||
}
|
||||
|
||||
module.exports = SubscriptionCommands;
|
||||
if (!subscriptions || subscriptions.length === 0) {
|
||||
await interaction.reply({
|
||||
content: 'This server has no game subscriptions.',
|
||||
ephemeral: true
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle('Game Subscriptions')
|
||||
.setDescription('Current game notification subscriptions for this server:')
|
||||
.setColor('#0099ff');
|
||||
|
||||
subscriptions.forEach(sub => {
|
||||
embed.addFields({
|
||||
name: sub.games.name,
|
||||
value: `<#${sub.notification_channel_id}>`,
|
||||
inline: true
|
||||
});
|
||||
});
|
||||
|
||||
await interaction.reply({ embeds: [embed], ephemeral: true });
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error listing subscriptions:', error);
|
||||
if (!interaction.replied && !interaction.deferred) {
|
||||
await interaction.reply({
|
||||
content: 'An error occurred while fetching subscriptions.',
|
||||
ephemeral: true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SubscriptionCommands;
|
||||
@@ -13,15 +13,45 @@ class SupabaseService {
|
||||
}
|
||||
}
|
||||
|
||||
async testConnection() {
|
||||
if (!this.supabase) {
|
||||
console.error('Supabase client is not initialized.');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const { data, error } = await this.supabase
|
||||
.from('games')
|
||||
.select('count')
|
||||
.limit(1);
|
||||
|
||||
if (error) {
|
||||
console.error('Supabase connection test error:', error);
|
||||
return false;
|
||||
}
|
||||
|
||||
console.log('Supabase connection successful');
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Supabase connection test failed:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async getSubscriptions(guildId) {
|
||||
if (!this.supabase) {
|
||||
console.error('Supabase client is not initialized.');
|
||||
return [];
|
||||
}
|
||||
|
||||
const { data, error } = await this.supabase
|
||||
.from('subscriptions')
|
||||
.select('*')
|
||||
.eq('guild_id', guildId);
|
||||
.from('server_game_preferences')
|
||||
.select(`
|
||||
games (name),
|
||||
notification_channel_id,
|
||||
servers!inner (discord_server_id)
|
||||
`)
|
||||
.eq('servers.discord_server_id', guildId);
|
||||
|
||||
if (error) throw error;
|
||||
return data;
|
||||
@@ -32,9 +62,40 @@ class SupabaseService {
|
||||
console.error('Supabase client is not initialized.');
|
||||
return null;
|
||||
}
|
||||
|
||||
// First, get or create server record
|
||||
const { data: serverData, error: serverError } = await this.supabase
|
||||
.from('servers')
|
||||
.upsert({
|
||||
discord_server_id: guildId
|
||||
}, {
|
||||
onConflict: 'discord_server_id',
|
||||
returning: true
|
||||
});
|
||||
|
||||
if (serverError) throw serverError;
|
||||
|
||||
// Get game ID
|
||||
const { data: gameData, error: gameError } = await this.supabase
|
||||
.from('games')
|
||||
.select('id')
|
||||
.eq('name', gameName)
|
||||
.eq('active', true)
|
||||
.single();
|
||||
|
||||
if (gameError) throw gameError;
|
||||
|
||||
// Create subscription
|
||||
const { data, error } = await this.supabase
|
||||
.from('subscriptions')
|
||||
.insert({ guild_id: guildId, game_name: gameName, channel_id: channelId });
|
||||
.from('server_game_preferences')
|
||||
.upsert({
|
||||
server_id: serverData[0].id,
|
||||
game_id: gameData.id,
|
||||
notification_channel_id: channelId
|
||||
}, {
|
||||
onConflict: '(server_id,game_id)',
|
||||
returning: true
|
||||
});
|
||||
|
||||
if (error) throw error;
|
||||
return data;
|
||||
@@ -45,14 +106,42 @@ class SupabaseService {
|
||||
console.error('Supabase client is not initialized.');
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get server ID
|
||||
const { data: serverData, error: serverError } = await this.supabase
|
||||
.from('servers')
|
||||
.select('id')
|
||||
.eq('discord_server_id', guildId)
|
||||
.single();
|
||||
|
||||
if (serverError) throw serverError;
|
||||
|
||||
// Get game ID
|
||||
const { data: gameData, error: gameError } = await this.supabase
|
||||
.from('games')
|
||||
.select('id')
|
||||
.eq('name', gameName)
|
||||
.single();
|
||||
|
||||
if (gameError) throw gameError;
|
||||
|
||||
// Delete subscription
|
||||
const { data, error } = await this.supabase
|
||||
.from('subscriptions')
|
||||
.from('server_game_preferences')
|
||||
.delete()
|
||||
.match({ guild_id: guildId, game_name: gameName });
|
||||
.match({
|
||||
server_id: serverData.id,
|
||||
game_id: gameData.id
|
||||
})
|
||||
.single();
|
||||
|
||||
if (error) throw error;
|
||||
return data;
|
||||
}
|
||||
|
||||
getClient() {
|
||||
return this.supabase;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SupabaseService;
|
||||
Reference in New Issue
Block a user