192 lines
6.2 KiB
Nim
192 lines
6.2 KiB
Nim
import db_sqlite, os, strutils, times, json, std/jsonutils, threadpool, tables
|
|
import asyncnet, asyncdispatch, net, ColdFusionlib
|
|
from NimRecipe import Recipe
|
|
var clients {.threadvar.}: seq[AsyncSocket]
|
|
var db : DbConn
|
|
try: db = open("recipes2.db", "", "", "")
|
|
except:
|
|
db.exec(sql"""CREATE TABLE recipes(
|
|
id INTEGER PRIMARY KEY,
|
|
name VARCHAR(50) NOT NULL,
|
|
author VARCHAR(50) NOT NULL,
|
|
url VARCHAR(50) NOT NULL,
|
|
dateadded VARCHAR(50) NOT NULL,
|
|
ingredients LONGTEXT NOT NULL
|
|
)""")
|
|
|
|
type Log = ref object
|
|
date : Time
|
|
message : string
|
|
var logger {.threadvar.}: seq[Log]
|
|
|
|
proc log(a : string) =
|
|
proc initLog(a : string) : Log =
|
|
return Log(date : getTime(), message : a)
|
|
logger.add(initLog(a))
|
|
|
|
|
|
#writes long on exit.
|
|
proc writeLog() {.noconv.} =
|
|
log "Exited without exception!"
|
|
var output : seq[string]
|
|
proc timeStamp(now : Time, flag = 0) : string =
|
|
#this thing is stupid and probably not temporary
|
|
let stringnow = $now
|
|
#this flag thing is stupid and temporary.
|
|
if flag == 0:
|
|
return $now().month() & "/" & $now().monthday() & "/" & $now().year() & "@" & $now.toUnix
|
|
else:
|
|
return $now().month() & "." & $now().monthday() & "." & $now().year() & "." & stringnow.split("T")[1]
|
|
for loggy in logger:
|
|
output.add("[" & timeStamp(loggy.date) & "]: " & loggy.message)
|
|
var filename = timeStamp(logger[0].date, 1)
|
|
writeFile("ColdFusionLogs/"&filename&".txt", output.join("\n"))
|
|
quit()
|
|
|
|
|
|
proc init() =
|
|
if not dirExists("ColdFusionLogs"):
|
|
createDir("ColdFusionLogs")
|
|
|
|
proc dbContainsRecipe(input : Recipe) : bool =
|
|
var pusedoID = input.name
|
|
for x in db.fastRows(sql"SELECT name FROM recipes"):
|
|
if x[1] == pusedoID:
|
|
return true
|
|
return false
|
|
#we're creating an "ID" from the name and the author
|
|
#this is to make sure we dont have any duplicates.
|
|
#the same recipe by the same author cannot be entered twice.
|
|
#This can malfunction, as anything can. However, I don't care.
|
|
|
|
var load = false
|
|
if load == true:
|
|
let recipes = compileFromFile()
|
|
echo "recipes loaded uwu"
|
|
var count = 0
|
|
var notdone = 0
|
|
for recipe in recipes:
|
|
if not dbContainsRecipe(recipe):
|
|
try :
|
|
db.exec(sql"INSERT INTO recipes (name, author, url, imgurl, dateadded, ingredients) VALUES (?, ?, ?, ?, ?, ?)",
|
|
recipe.name, recipe.author, recipe.url, recipe.img, $now(), packArchive(recipe))
|
|
except:
|
|
echo "failed to parse " & recipe.name
|
|
inc count
|
|
inc notdone
|
|
log recipe.name & " Failed to be added..."; continue
|
|
inc count
|
|
echo recipe.name
|
|
echo $(((count-notdone)/count)*100) & "% added"
|
|
log "inserted " & $count & " recipes"
|
|
log $((count-notdone)/count) & "% where added..."
|
|
log "Started!"
|
|
|
|
type query* = tuple
|
|
id : int
|
|
name : string
|
|
|
|
type fullQuery* = tuple
|
|
id: int
|
|
name : string
|
|
author : string
|
|
url : string
|
|
imgurl : string
|
|
dateadded : string
|
|
ingredients : string
|
|
|
|
proc sendClient(client : AsyncSocket, ip: string, message : string, index : seq[query], idQuery : seq[fullQuery]) {.async.} =
|
|
echo "testproc "
|
|
try :
|
|
let parsed = parseJson(message)
|
|
case parsed["query"].getStr:
|
|
of "index":
|
|
echo "sending index"
|
|
await client.send($jsonutils.toJson(index))
|
|
echo "sent"
|
|
|
|
of "fetch":
|
|
echo "fetching"
|
|
var queriedList : seq[fullQuery]
|
|
if parsed["ints"].getInt == 0:
|
|
await client.send($jsonutils.toJson(idQuery))
|
|
return
|
|
for x in parsed["ints"]:
|
|
queriedList.add(idQuery[x.getInt])
|
|
await client.send($jsonutils.toJson(queriedList))
|
|
echo "sent"
|
|
return
|
|
|
|
except:
|
|
await client.send("Malformed message. Please send in a formal JSON message.")
|
|
echo "malformed...."
|
|
log "Recieved malformed message from " & ip & ": " & message
|
|
return
|
|
|
|
|
|
proc serve() {.async.} =
|
|
echo "starting up server"
|
|
var nameQuery : seq[query]
|
|
var idQuery : seq[fullQuery]
|
|
for row in db.fastRows(sql"SELECT id, name, author, url, imgurl, dateadded, ingredients FROM recipes"):
|
|
var query = (parseInt(row[0]), row[1])
|
|
idQuery.add ((query[0], query[1], row[2], row[3], row[4], row[5], $row[6]))
|
|
|
|
echo "setup finished :) "
|
|
var server = newAsyncSocket()
|
|
#this stuff is kinda just stock code.
|
|
server.setSockOpt(OptReuseAddr, true)
|
|
server.bindAddr(Port(12345))
|
|
server.listen()
|
|
while true:
|
|
# accept addr assigns client to a tuple of the socket and the ip as a string.
|
|
let client = await server.acceptAddr()
|
|
#ths is for readablity.
|
|
let ip = client[0]
|
|
let clientsocket = client[1]
|
|
log "Connection Recieved from: " & ip
|
|
echo "Connection Recieved from: " & ip
|
|
var recieved = clientsocket.recvLine()
|
|
#this is just to make sure that you cant connect and not send any messages
|
|
await sleepAsync(100)
|
|
|
|
if recieved.finished:
|
|
var recieved = recieved.read
|
|
if recieved.isEmptyOrWhitespace:
|
|
log "Message Recieved from " & ip & " is malformed!"
|
|
echo "message incomplete, breaking"
|
|
continue
|
|
log "Message Recieved from " & ip & ": " & """"""" & recieved & """""""
|
|
clients.add clientsocket
|
|
|
|
#this is the actual server function.
|
|
await sendClient(clientsocket, ip, recieved, nameQuery, idQuery)
|
|
#this is just to make it safe.
|
|
await sleepAsync(200)
|
|
try:
|
|
clientsocket.close()
|
|
except:
|
|
echo "forceful disconnect."
|
|
log ip & " has disconnected without being forced."
|
|
log ip & " has disconnected."
|
|
#if no message is there by 100 miliseconds after connection then close it.
|
|
else:
|
|
echo "timeout."
|
|
log "timeout reached for: " & ip & "... closing."
|
|
clientsocket.close()
|
|
|
|
if isMainModule:
|
|
init()
|
|
#cool thing here.
|
|
setControlCHook(writeLog)
|
|
#dunno if this works /shrug
|
|
spawn asyncCheck serve()
|
|
#when that breaks it writes to log.
|
|
try: runForever()
|
|
except:
|
|
echo "logging exception..."
|
|
log "ERROR! EXITING"
|
|
log "EXCEPTION FOUND..."
|
|
log $Exception
|
|
writeLog()
|
|
|