require("dotenv").config(); const Sequelize = require('sequelize'); const express = require('express'); const bodyParser = require('body-parser'); const { Card, User, DropHistory, Character, Group } = require("../models"); const { Op } = require('sequelize'); const ACCESS_TOKEN = process.env.API_ACCESS_TOKEN; const app = express(); const router = express.Router(); const PREFIX = '/api/v1'; app.use(bodyParser.json()); function isAuthorized(req, res=null) { const providedToken = req.headers['apikey']; if (providedToken !== ACCESS_TOKEN) { if(res) { res.status(401).json({ error: 'Unauthorized' }); } return false; } return true; } router.get('/', (req, res) => { const routes = router.stack .filter(layer => layer.route) // Filter out non-routes .map(layer => { return { route: PREFIX + layer.route.path, methods: layer.route.methods }; }); res.json({ routes: routes }); }); router.get('/ping', (req, res) => { res.json({ status: 'Pong' }); }); router.get('/stats', async (req, res) => { if(!isAuthorized(req, res)){return;} res.json({ users: await User.count(), cards: await Card.count({where: { burned: { [Op.eq]: false }}}), burned: await Card.count({where: { burned: { [Op.eq]: true }}}), drops: await DropHistory.count(), groups: await Group.count({where: { enabled: { [Op.eq]: true }}}), characters: await Character.count({where: { enabled: { [Op.eq]: true }}}), uptime: app.client.uptime }); }); router.get('/most-recent-drop', async (req, res) => { if(!isAuthorized(req, res)){return;} try { const mostRecentDrop = await DropHistory.findOne({ order: [['createdAt', 'DESC']], where: { type: 0 } }); if (!mostRecentDrop) { return res.status(404).send('No drops found'); } const dropData = JSON.parse(mostRecentDrop.dropData); const cards = await Promise.all(Object.keys(dropData).map(async key => { const cardData = dropData[key]?.cardData; if(!cardData) {return}; const card = JSON.parse(cardData); return { identifier: card.identifier, quality: card.quality, character: await Character.findByPk(card.characterId) }; })); let response = { dropper: await User.findByPk(dropData.dropper), cards: cards.filter(Boolean)}; res.json(response); } catch (error) { console.error(error); res.status(500).send('Error fetching most recent drop'); } }); /** * Groups */ router.get('/groups', async (req, res) => { let condition = { where: { [Sequelize.Op.or]: [ {enabled: 1} ] } } if(isAuthorized && req.query.include_disabled) { condition['where'][Sequelize.Op.or].push({enabled: 0}); } let groups = await Group.findAll(condition); res.json(groups); }); router.get('/groups/:group_id', async (req, res) => { let group = await Group.findByPk(req.params.group_id); if (!group.enabled && !isAuthorized(req)) { res.status(404).json({ error: 'Group not found' }); return; } res.json(group); }); router.post('/groups', async (req, res) => { try { const newGroupData = req.body; const newGroup = await Group.create(newGroupData); res.status(201).json({ message: 'Group created successfully.', group: newGroup }); } catch (error) { res.status(500).json({ message: 'Error creating group.', error }); } }); router.put('/groups/:group_id', async (req, res) => { if(!isAuthorized(req, res)){return;} try { const groupId = req.params.group_id; const updatedGroupData = req.body; const [updatedRowCount] = await Group.update(updatedGroupData, { where: { id: groupId } }); if (updatedRowCount === 0) { return res.status(404).json({ message: 'Group not found.' }); } res.status(200).json({ message: 'Group updated successfully.' }); } catch (error) { res.status(500).json({ message: 'Error updating Group.', error }); } }); /** * Characters */ router.get('/characters', async (req, res) => { let condition = { where: { [Sequelize.Op.or]: [ {enabled: 1} ] } } if(isAuthorized && req.query.include_disabled) { condition['where'][Sequelize.Op.or].push({enabled: 0}); } let characters = await Character.findAll(condition); res.json(characters); }); router.get('/characters/:character_id', async (req, res) => { let character = await Character.findByPk(req.params.character_id); if (!character.enabled && !isAuthorized(req)) { res.status(404).json({ error: 'Character not found' }); return; } res.json(character); }); router.post('/characters', async (req, res) => { try { const newCharacterData = req.body; const newCharacter = await Character.create(newCharacterData); res.status(201).json({ message: 'Character created successfully.', character: newCharacter }); } catch (error) { res.status(500).json({ message: 'Error creating character.', error }); } }); router.put('/characters/:character_id', async (req, res) => { if(!isAuthorized(req, res)){return;} try { const characterId = req.params.character_id; const updatedCharacterData = req.body; const [updatedRowCount] = await Character.update(updatedCharacterData, { where: { id: characterId } }); if (updatedRowCount === 0) { return res.status(404).json({ message: 'Character not found.' }); } res.status(200).json({ message: 'Character updated successfully.' }); } catch (error) { res.status(500).json({ message: 'Error updating character.', error }); } }); app.use(PREFIX, router); module.exports = app;