supabase setup

This commit is contained in:
VinceC
2024-11-24 03:49:23 -06:00
parent c62c1f81e4
commit 3b10e77c82
3 changed files with 330 additions and 103 deletions

View File

@@ -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...");

View File

@@ -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;

View File

@@ -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;