server registration and subscription
This commit is contained in:
82
src/services/ServerRegistrationService.js
Normal file
82
src/services/ServerRegistrationService.js
Normal file
@@ -0,0 +1,82 @@
|
||||
class ServerRegistrationService {
|
||||
constructor(supabase, logger) {
|
||||
this.supabase = supabase;
|
||||
this.logger = logger;
|
||||
// Log when service is instantiated
|
||||
this.logger.info('ServerRegistrationService initialized');
|
||||
}
|
||||
|
||||
async registerServer(guildId, serverName) {
|
||||
// Add entry point log
|
||||
this.logger.info('registerServer method called', {
|
||||
guildId,
|
||||
serverName,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
try {
|
||||
this.logger.debug('Starting server registration process', {
|
||||
guildId,
|
||||
serverName,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
const { data: existingServer, error: checkError } = await this.supabase
|
||||
.from('servers')
|
||||
.select('*')
|
||||
.eq('discord_server_id', guildId)
|
||||
.single();
|
||||
|
||||
// Log the database query result
|
||||
this.logger.debug('Database query result', {
|
||||
hasExistingServer: !!existingServer,
|
||||
hasError: !!checkError,
|
||||
errorCode: checkError?.code
|
||||
});
|
||||
|
||||
if (existingServer) {
|
||||
this.logger.info('Server already exists', {
|
||||
serverId: existingServer.id,
|
||||
guildId
|
||||
});
|
||||
return { status: 'exists', server: existingServer };
|
||||
}
|
||||
|
||||
if (!existingServer || checkError?.code === 'PGRST116') {
|
||||
this.logger.debug('Attempting to create new server');
|
||||
const { data: newServer, error: insertError } = await this.supabase
|
||||
.from('servers')
|
||||
.insert([{
|
||||
discord_server_id: guildId,
|
||||
server_name: serverName,
|
||||
active: true
|
||||
}])
|
||||
.select()
|
||||
.single();
|
||||
|
||||
if (insertError) {
|
||||
this.logger.error('Failed to insert new server', { error: insertError });
|
||||
throw insertError;
|
||||
}
|
||||
|
||||
this.logger.info('New server created successfully', {
|
||||
serverId: newServer.id,
|
||||
guildId
|
||||
});
|
||||
return { status: 'created', server: newServer };
|
||||
}
|
||||
|
||||
throw checkError;
|
||||
} catch (error) {
|
||||
this.logger.error('Error in registerServer:', {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
guildId,
|
||||
serverName
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ServerRegistrationService;
|
||||
@@ -1,142 +1,370 @@
|
||||
const { createClient } = require('@supabase/supabase-js');
|
||||
const Logger = require('../utils/Logger');
|
||||
|
||||
class SupabaseService {
|
||||
constructor() {
|
||||
this.logger = new Logger('SupabaseService');
|
||||
const supabaseUrl = process.env.SUPABASE_URL;
|
||||
const supabaseKey = process.env.SUPABASE_KEY;
|
||||
|
||||
if (!supabaseUrl || !supabaseKey) {
|
||||
console.error('Supabase URL or key is missing. Please check your .env file.');
|
||||
this.logger.error('Missing configuration', {
|
||||
hasUrl: !!supabaseUrl,
|
||||
hasKey: !!supabaseKey
|
||||
});
|
||||
this.supabase = null;
|
||||
} else {
|
||||
this.supabase = createClient(supabaseUrl, supabaseKey);
|
||||
this.logger.debug('Supabase client created');
|
||||
}
|
||||
}
|
||||
|
||||
async testConnection() {
|
||||
if (!this.supabase) {
|
||||
console.error('Supabase client is not initialized.');
|
||||
this.logger.error('Client not initialized');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const { data, error } = await this.supabase
|
||||
this.logger.debug('Testing database connection...');
|
||||
|
||||
// Test servers table
|
||||
const { data: serverTest, error: serverError } = await this.supabase
|
||||
.from('servers')
|
||||
.select('count')
|
||||
.limit(1);
|
||||
|
||||
if (serverError) {
|
||||
this.logger.error('Server table test failed:', serverError);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test games table
|
||||
const { data: gameTest, error: gameError } = await this.supabase
|
||||
.from('games')
|
||||
.select('count')
|
||||
.limit(1);
|
||||
|
||||
if (error) {
|
||||
console.error('Supabase connection test error:', error);
|
||||
|
||||
if (gameError) {
|
||||
this.logger.error('Games table test failed:', gameError);
|
||||
return false;
|
||||
}
|
||||
|
||||
console.log('Supabase connection successful');
|
||||
this.logger.info('Database connection successful');
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Supabase connection test failed:', error);
|
||||
this.logger.error('Connection test failed:', {
|
||||
error: error.message,
|
||||
stack: error.stack
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async ensureServerRegistered(guildId, serverName) {
|
||||
try {
|
||||
this.logger.debug('Ensuring server is registered', { guildId, serverName });
|
||||
|
||||
// Try to find existing server
|
||||
const { data: existingServer, error: fetchError } = await this.supabase
|
||||
.from('servers')
|
||||
.select('*')
|
||||
.eq('discord_server_id', guildId)
|
||||
.single();
|
||||
|
||||
// If server exists, return it
|
||||
if (existingServer) {
|
||||
this.logger.debug('Server already registered', {
|
||||
serverId: existingServer.id,
|
||||
guildId,
|
||||
serverName: existingServer.server_name
|
||||
});
|
||||
return existingServer;
|
||||
}
|
||||
|
||||
// If server doesn't exist, create it
|
||||
this.logger.debug('Registering new server', { guildId, serverName });
|
||||
const { data: newServer, error: insertError } = await this.supabase
|
||||
.from('servers')
|
||||
.insert([{
|
||||
discord_server_id: guildId,
|
||||
server_name: serverName,
|
||||
active: true
|
||||
}])
|
||||
.select()
|
||||
.single();
|
||||
|
||||
if (insertError) {
|
||||
this.logger.error('Failed to register server', {
|
||||
error: insertError,
|
||||
guildId,
|
||||
serverName
|
||||
});
|
||||
throw insertError;
|
||||
}
|
||||
|
||||
this.logger.info('New server registered successfully', {
|
||||
serverId: newServer.id,
|
||||
guildId,
|
||||
serverName
|
||||
});
|
||||
|
||||
return newServer;
|
||||
} catch (error) {
|
||||
this.logger.error('Error in ensureServerRegistered:', {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
guildId,
|
||||
serverName
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the addSubscription method to use ensureServerRegistered
|
||||
async addSubscription(guildId, gameName, channelId, serverName) {
|
||||
if (!this.supabase) {
|
||||
this.logger.error('Client not initialized');
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
this.logger.debug('Adding subscription', { guildId, gameName, channelId });
|
||||
|
||||
// Ensure server is registered
|
||||
const server = await this.ensureServerRegistered(guildId, serverName);
|
||||
if (!server) {
|
||||
throw new Error('Failed to ensure server registration');
|
||||
}
|
||||
|
||||
// Get game ID
|
||||
const { data: gameData, error: gameError } = await this.supabase
|
||||
.from('games')
|
||||
.select('id')
|
||||
.eq('name', gameName)
|
||||
.eq('active', true)
|
||||
.single();
|
||||
|
||||
if (gameError) {
|
||||
this.logger.error('Game fetch error:', { gameError, gameName });
|
||||
throw gameError;
|
||||
}
|
||||
|
||||
// Create subscription
|
||||
const { data, error } = await this.supabase
|
||||
.from('server_game_preferences')
|
||||
.upsert({
|
||||
server_id: server.id,
|
||||
game_id: gameData.id,
|
||||
notification_channel_id: channelId
|
||||
}, {
|
||||
onConflict: '(server_id,game_id)',
|
||||
returning: true
|
||||
});
|
||||
|
||||
if (error) {
|
||||
this.logger.error('Subscription upsert error:', { error });
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.logger.debug('Subscription added successfully', {
|
||||
serverId: server.id,
|
||||
gameId: gameData.id,
|
||||
channelId
|
||||
});
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
this.logger.error('Error in addSubscription:', {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
guildId,
|
||||
gameName
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async getSubscriptions(guildId) {
|
||||
if (!this.supabase) {
|
||||
console.error('Supabase client is not initialized.');
|
||||
this.logger.error('Client not initialized');
|
||||
return [];
|
||||
}
|
||||
|
||||
const { data, 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);
|
||||
try {
|
||||
this.logger.debug('Fetching subscriptions', { guildId });
|
||||
|
||||
const { data, 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) throw error;
|
||||
return data;
|
||||
if (error) {
|
||||
this.logger.error('Error fetching subscriptions:', { error, guildId });
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.logger.debug('Subscriptions fetched', {
|
||||
count: data?.length || 0,
|
||||
guildId
|
||||
});
|
||||
|
||||
return data || [];
|
||||
} catch (error) {
|
||||
this.logger.error('Error in getSubscriptions:', {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
guildId
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async addSubscription(guildId, gameName, channelId) {
|
||||
if (!this.supabase) {
|
||||
console.error('Supabase client is not initialized.');
|
||||
this.logger.error('Client 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
|
||||
try {
|
||||
this.logger.debug('Adding subscription', { guildId, gameName, channelId });
|
||||
|
||||
// First, get or create server record
|
||||
const { data: serverData, error: serverError } = await this.supabase
|
||||
.from('servers')
|
||||
.upsert({
|
||||
discord_server_id: guildId,
|
||||
active: true
|
||||
}, {
|
||||
onConflict: 'discord_server_id',
|
||||
returning: true
|
||||
});
|
||||
|
||||
if (serverError) {
|
||||
this.logger.error('Server upsert error:', { serverError, guildId });
|
||||
throw serverError;
|
||||
}
|
||||
|
||||
if (!serverData || serverData.length === 0) {
|
||||
this.logger.error('Server creation failed - no data returned', { guildId });
|
||||
throw new Error('Server creation failed');
|
||||
}
|
||||
|
||||
// Get game ID
|
||||
const { data: gameData, error: gameError } = await this.supabase
|
||||
.from('games')
|
||||
.select('id')
|
||||
.eq('name', gameName)
|
||||
.eq('active', true)
|
||||
.single();
|
||||
|
||||
if (gameError) {
|
||||
this.logger.error('Game fetch error:', { gameError, gameName });
|
||||
throw gameError;
|
||||
}
|
||||
|
||||
// Create subscription
|
||||
const { data, error } = await this.supabase
|
||||
.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) {
|
||||
this.logger.error('Subscription upsert error:', { error });
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.logger.debug('Subscription added successfully', {
|
||||
serverId: serverData[0].id,
|
||||
gameId: gameData.id,
|
||||
channelId
|
||||
});
|
||||
|
||||
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('server_game_preferences')
|
||||
.upsert({
|
||||
server_id: serverData[0].id,
|
||||
game_id: gameData.id,
|
||||
notification_channel_id: channelId
|
||||
}, {
|
||||
onConflict: '(server_id,game_id)',
|
||||
returning: true
|
||||
return data;
|
||||
} catch (error) {
|
||||
this.logger.error('Error in addSubscription:', {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
guildId,
|
||||
gameName
|
||||
});
|
||||
|
||||
if (error) throw error;
|
||||
return data;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async removeSubscription(guildId, gameName) {
|
||||
if (!this.supabase) {
|
||||
console.error('Supabase client is not initialized.');
|
||||
this.logger.error('Client 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();
|
||||
try {
|
||||
this.logger.debug('Removing subscription', { guildId, gameName });
|
||||
|
||||
if (serverError) throw serverError;
|
||||
// Get server ID
|
||||
const { data: serverData, error: serverError } = await this.supabase
|
||||
.from('servers')
|
||||
.select('id')
|
||||
.eq('discord_server_id', guildId)
|
||||
.single();
|
||||
|
||||
// Get game ID
|
||||
const { data: gameData, error: gameError } = await this.supabase
|
||||
.from('games')
|
||||
.select('id')
|
||||
.eq('name', gameName)
|
||||
.single();
|
||||
if (serverError) {
|
||||
this.logger.error('Server fetch error:', { serverError, guildId });
|
||||
throw serverError;
|
||||
}
|
||||
|
||||
if (gameError) throw gameError;
|
||||
// Get game ID
|
||||
const { data: gameData, error: gameError } = await this.supabase
|
||||
.from('games')
|
||||
.select('id')
|
||||
.eq('name', gameName)
|
||||
.single();
|
||||
|
||||
// Delete subscription
|
||||
const { data, error } = await this.supabase
|
||||
.from('server_game_preferences')
|
||||
.delete()
|
||||
.match({
|
||||
server_id: serverData.id,
|
||||
game_id: gameData.id
|
||||
})
|
||||
.single();
|
||||
if (gameError) {
|
||||
this.logger.error('Game fetch error:', { gameError, gameName });
|
||||
throw gameError;
|
||||
}
|
||||
|
||||
if (error) throw error;
|
||||
return data;
|
||||
// Delete subscription
|
||||
const { data, error } = await this.supabase
|
||||
.from('server_game_preferences')
|
||||
.delete()
|
||||
.match({
|
||||
server_id: serverData.id,
|
||||
game_id: gameData.id
|
||||
})
|
||||
.single();
|
||||
|
||||
if (error) {
|
||||
this.logger.error('Subscription deletion error:', { error });
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.logger.debug('Subscription removed successfully', {
|
||||
serverId: serverData.id,
|
||||
gameId: gameData.id
|
||||
});
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
this.logger.error('Error in removeSubscription:', {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
guildId,
|
||||
gameName
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
getClient() {
|
||||
|
||||
Reference in New Issue
Block a user