feat: Complete match notification service implementation

This commit is contained in:
VinceC
2024-11-29 03:42:21 -06:00
parent 15082d03c7
commit beab9a514a

View File

@@ -4,94 +4,101 @@ const { createMatchRequestEmbed } = require('../utils/embedBuilders');
const { createMatchActionRow } = require('../utils/componentBuilders'); const { createMatchActionRow } = require('../utils/componentBuilders');
class NotificationService { class NotificationService {
constructor(bot, supabaseService) { constructor(bot, supabase) {
this.bot = bot; this.bot = bot;
this.supabaseService = supabaseService; this.supabase = supabase;
this.app = express(); this.app = express();
this.app.use(express.json()); this.app.use(express.json());
this.setupRoutes(); this.setupRoutes();
} }
setupRoutes() { setupRoutes() {
this.app.post('/api/match-notification', this.handleMatchNotification.bind(this)); this.app.post('/api/match-notification', this.handleMatchNotification.bind(this));
} }
async start(port = 3000) { async start(port = 3000) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
try { try {
this.server = this.app.listen(port, () => { this.server = this.app.listen(port, () => {
console.log(`Notification service listening on port ${port}`); console.log(`Notification service listening on port ${port}`);
resolve(); resolve();
});
} catch (error) {
reject(error);
}
}); });
} catch (error) {
reject(error);
}
});
}
async stop() {
if (this.server) {
return new Promise((resolve) => {
this.server.close(resolve);
});
} }
}
async handleMatchNotification(req, res) { async stop() {
try { if (this.server) {
const authToken = req.headers['x-webhook-token']; return new Promise((resolve) => {
if (authToken !== process.env.WEBHOOK_SECRET) { this.server.close(resolve);
return res.status(401).json({ error: 'Unauthorized' }); });
}
const matchData = req.body;
if (!this.validateMatchData(matchData)) {
return res.status(400).json({ error: 'Invalid match data' });
}
const subscriptions = await this.supabaseService.getSubscriptions();
const relevantSubscriptions = subscriptions.filter(sub => sub.game_name === matchData.game_name);
for (const subscription of relevantSubscriptions) {
try {
const channel = await this.bot.client.channels.fetch(subscription.channel_id);
const embed = createMatchRequestEmbed(matchData);
const actionRow = createMatchActionRow(matchData.game_name);
await channel.send({
embeds: [embed],
components: [actionRow]
});
} catch (error) {
console.error(`Error sending notification to channel ${subscription.channel_id}:`, error);
} }
}
res.json({ success: true });
} catch (error) {
console.error('Error handling match notification:', error);
res.status(500).json({ error: 'Internal server error' });
}
}
validateMatchData(matchData) {
if (matchData.type !== 'match_request') {
return false;
} }
const requiredFields = [ async handleMatchNotification(req, res) {
'game_name', try {
'game_id', const authToken = req.headers['x-webhook-token'];
'team_size', if (authToken !== process.env.WEBHOOK_SECRET) {
'match_type', return res.status(401).json({ error: 'Unauthorized' });
'region', }
'match_date',
'match_class',
'status'
];
return requiredFields.every(field => matchData[field] !== undefined); const matchData = req.body;
} if (!this.validateMatchData(matchData)) {
return res.status(400).json({ error: 'Invalid match data' });
}
const { data: subscriptions, error } = await this.supabase
.from('active_subscriptions')
.select('*')
.eq('game_name', matchData.game_name);
if (error) {
console.error('Error fetching subscriptions:', error);
return res.status(500).json({ error: 'Failed to fetch subscriptions' });
}
for (const subscription of (subscriptions || [])) {
try {
const channel = await this.bot.client.channels.fetch(subscription.notification_channel_id);
const embed = createMatchRequestEmbed(matchData);
const actionRow = createMatchActionRow(matchData.game_name);
await channel.send({
embeds: [embed],
components: [actionRow]
});
} catch (error) {
console.error(`Error sending notification to channel ${subscription.notification_channel_id}:`, error);
}
}
res.json({ success: true });
} catch (error) {
console.error('Error handling match notification:', error);
res.status(500).json({ error: 'Internal server error' });
}
}
validateMatchData(matchData) {
if (matchData.type !== 'match_request') {
return false;
}
const requiredFields = [
'game_name',
'game_id',
'team_size',
'match_type',
'region',
'match_date',
'match_class',
'status'
];
return requiredFields.every(field => matchData[field] !== undefined);
}
} }
module.exports = NotificationService; module.exports = NotificationService;