Big refactor, split client and server. add weapon get route

This commit is contained in:
2023-03-12 21:18:33 +01:00
parent 72385f0c11
commit fee43b1a98
12 changed files with 258 additions and 53 deletions
+18
View File
@@ -0,0 +1,18 @@
import { createClient } from 'redis'
const client = createClient({
url: process.env.REDIS_URL,
username: process.env.REDIS_USER,
password: process.env.REDIS_PASSWORD
})
client.on('error', (err) => console.log('Redis Client Error', err))
export function cacheReady() {
return client.connect()
}
export default client
//await client.set('key', 'value');
//const value = await client.get('key');
//await client.disconnect();
+24 -18
View File
@@ -1,21 +1,27 @@
import { Router } from 'express'
const router = Router()
//timeout middleware ?
router.get('/*', (req, res, next) => {
next()
import * as dotenv from 'dotenv'
dotenv.config()
import express from 'express'
import cors from 'cors'
import client from './client/client'
import { dbReady } from './db/db'
import { cacheReady } from './cache/redis'
const app = express()
const port = 3001
app.use(express.json())
app.use(cors())
app.get('/', (req, res) => {
res.send('Hello World!')
})
router.get('/weapons/', (req, res, next) => {})
app.use('/v1/client', client)
router.get('/maps/', (req, res, next) => {})
router.get('/players', (req, res, next) => {})
router.get('/players/:playerId', (req, res, next) => {})
router.get('/servers/', (req, res, next) => {})
router.get('/servers/:serverId/', (req, res, next) => {})
router.get('/servers/:serverId/players', (req, res, next) => {})
router.get('/servers/:serverId/players/:playerId', (req, res, next) => {})
router.get('/servers/:serverId/weapons', (req, res, next) => {})
export default router
dbReady().then((e) => {
cacheReady().then((e) => {
app.listen(port, '0.0.0.0', () => {
console.log(`Example app listening on port ${port}`)
})
})
})
+22
View File
@@ -0,0 +1,22 @@
import { Router } from 'express'
import weapons from './weapons'
const router = Router()
//timeout middleware ?
router.get('/*', (req, res, next) => {
next()
})
router.get('/weapons/', (req, res, next) => {})
router.get('/maps/', (req, res, next) => {})
router.get('/players', (req, res, next) => {})
router.get('/players/:playerId', (req, res, next) => {})
router.get('/servers/', (req, res, next) => {})
router.get('/servers/:serverId/', (req, res, next) => {})
router.get('/servers/:serverId/players', (req, res, next) => {})
router.get('/servers/:serverId/players/:playerId', (req, res, next) => {})
router.use('/', weapons)
export default router
+63
View File
@@ -0,0 +1,63 @@
import { Router } from 'express'
import { param, validationResult } from 'express-validator'
import cache from '../cache/redis'
import db from '../db/db'
const router = Router()
const { count, max } = db.fn
router.get(
'/servers/:serverId/weapons',
param('serverId').exists().toInt().isInt(),
async (req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) {
console.error(JSON.stringify(errors))
return res.status(400).json({ errors: errors.array() })
}
if (!req.params) {
res.sendStatus(500)
return
}
const server = Number(req.params.serverId)
await processTopWeapons(server)
const data = await cache.HGETALL(`servers:${server}:weapons`)
delete data.last_entry
res.status(200).send(data)
}
)
async function processTopWeapons(server: number) {
let last_entry =
Number(await cache.HGET(`servers:${server}:weapons`, 'last_entry')) || 0
const newData = await db
.selectFrom(['kill'])
.select([
count<number>('kill.id').as('num_kills'),
'kill.cause_of_death',
max('kill.id').as('last_entry')
])
.where('server', '=', server)
.where('kill.id', '>', last_entry)
.groupBy('cause_of_death')
.execute()
//if no new kills
if (newData.length == 0) {
return
}
last_entry = newData.reduce(
(acc, current) => (current.last_entry > acc ? current.last_entry : acc),
0
)
const promises: Promise<number>[] = []
newData.forEach(({ num_kills, cause_of_death }) => {
promises.push(
cache.HINCRBY(`servers:${server}:weapons`, cause_of_death, num_kills)
)
})
promises.push(
cache.HSET(`servers:${server}:weapons`, 'last_entry', newData[0].last_entry)
)
await Promise.all(promises)
}
export default router
+7 -1
View File
@@ -12,7 +12,13 @@ const db = new Kysely<Database>({
user: process.env.POSTGRES_USER,
password: process.env.POSTGRES_PASSWORD
})
})
}),
log(event) {
if (event.level === 'query') {
console.log(event.query.sql)
console.log(event.query.parameters)
}
}
})
interface RemoveFromKill {
+1 -3
View File
@@ -2,7 +2,6 @@ import * as dotenv from 'dotenv'
dotenv.config()
import express from 'express'
import cors from 'cors'
import client from './client'
import { dbReady } from './db/db'
import server from './server/server'
@@ -16,8 +15,7 @@ app.get('/', (req, res) => {
res.send('Hello World!')
})
app.use('/v1/', server)
app.use('/v1/', client)
app.use('/v1/servers', server)
dbReady().then((e) => {
app.listen(port, '0.0.0.0', () => {
+2 -2
View File
@@ -12,7 +12,7 @@ const hostsCount: { [id: string]: number } = {}
const hostsTimeout: { [id: string]: NodeJS.Timeout } = {}
//Very simple rate limiting. max 2 registers per IP every 5 mins. Maybe 2 is a bit few ?
router.post('/servers/register', (req, res, next) => {
router.post('/register', (req, res, next) => {
let ip =
req.header('x-forwarded-for') || req.socket.remoteAddress || 'undefined'
if (hostsCount[ip] > 2) {
@@ -31,7 +31,7 @@ router.post('/servers/register', (req, res, next) => {
})
router.post(
'/servers/register',
'/register',
body(['name', 'description']).isString().withMessage('must be strings'),
body('auth_port')
.toInt()
+4 -4
View File
@@ -10,7 +10,7 @@ router.use('/', register)
//auth middleware
router.post(
'/servers/:serverId/*',
'/:serverId/*',
header('authorization')
.exists({ checkFalsy: true })
.withMessage('Missing Authorization Header')
@@ -37,7 +37,7 @@ router.post(
)
//Route to check auth
router.post('/servers/:serverId', (req, res) => {
router.post('/:serverId', (req, res) => {
res.sendStatus(200)
})
@@ -45,7 +45,7 @@ const serversCount: { [id: string]: number } = {}
const serversTimeout: { [id: string]: NodeJS.Timeout } = {}
//same rate limiting code as register. max 10 kills per server every 1 sec. should be enough.
router.post('/servers/:serverId/kill', (req, res, next) => {
router.post('/:serverId/kill', (req, res, next) => {
let serverId = req.body.serverId || 'undefined'
if (serversCount[serverId] > 2) {
return res.status(429).json({
@@ -62,7 +62,7 @@ router.post('/servers/:serverId/kill', (req, res, next) => {
})
router.post(
'/servers/:serverId/kill',
'/:serverId/kill',
body([
'attacker_current_weapon_mods',
'attacker_weapon_1_mods',