Electron-Svelte-Recipe-Planner/package/NimRecipe/ColdFusion.nim
2021-12-16 00:55:59 -05:00

194 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 = open("recipes.db", "", "", "")
#var db2 = open("recipes2.db", "", "", "")
#db2.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
# )""")
#quit()
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()