Big refactor, split client and server. add weapon get route
This commit is contained in:
Vendored
+18
@@ -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
@@ -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}`)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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', () => {
|
||||
@@ -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()
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user