const stringify = require('@stringify')
const html = require('@html')
const cache = require('@cache')
const dns = require('@dns')
const postgres = require('@pg')
const http = require('@http')
const socket = require('@socket')
const util = require('util.js')
const config = require('tfb.config.js')
const { getIPAddress } = dns
const { createSocket } = socket
const { createServer, responses } = http
const { SimpleCache } = cache
const { sprayer, sortByMessage, spawn, getUpdateQuery, Clock } = util
const { sjs, attr } = stringify
const {
db, fortunes, worlds, templates,
maxQuery, maxRows, message, json,
extra
} = config
async function main () {
const spray = sprayer(maxQuery)
const getRandom = () => Math.ceil(Math.random() * maxRows)
const getCount = (qs = { q: 1 }) => {
return Math.min(parseInt((qs.q) || 1, 10), maxQuery) || 1
}
const sJSON = sjs({ message: attr('string') })
const wJSON = sjs({ id: attr('number'), randomnumber: attr('number') })
const clock = new Clock()
const sock = createSocket()
const ip = await getIPAddress(db.hostname)
await sock.connect(ip, db.port)
const pg = await postgres.createSocket(sock, db)
sock.noDelay = false
const getWorldById = await pg.compile(worlds)
const getFortunes = await pg.compile(fortunes)
const worldCache = new SimpleCache(id => getWorldById(id))
const template = html.load(templates.fortunes, templates.settings)
const getRandomWorld = () => getWorldById(getRandom())
const getCachedWorld = () => worldCache.get(getRandom())
const server = createServer()
.get('/plaintext', res => res.text(message))
.get('/json', res => res.utf8(sJSON(json), responses.json))
.get('/db', async res => {
res.utf8(wJSON(await getRandomWorld()), responses.json)
})
.get('/fortunes', async res => {
res.html(template.call(sortByMessage([extra, ...await getFortunes()])))
})
.get('/cached-world', async (res, req) => {
res.json(await Promise.all(spray(getCount(req.query), getCachedWorld)))
})
.get('/query', async (res, req) => {
res.json(await Promise.all(spray(getCount(req.query), getRandomWorld)))
})
.get('/update', async (res, req) => {
const count = getCount(req.query)
const worlds = await Promise.all(spray(count, getRandomWorld))
const updateWorlds = await getUpdateQuery(count, pg)
await updateWorlds(...worlds.map(w => {
w.randomnumber = getRandom()
return [w.id, w.randomnumber]
}).flat())
res.json(worlds)
})
.listen('0.0.0.0', 8080)
clock.set(() => {
worldCache.tick()
server.update()
})
}
spawn(main).catch(err => just.error(err.stack))