import asyncdispatch, db_sqlite, jester, moustachu, os, shorturl, strutils, tables, times, typetraits const baseTemplate*: string = staticRead "./templates/layout.mustache" browseTemplate*: string = staticRead "./templates/browse.mustache" errorTemplate*: string = staticRead "./templates/error.mustache" channelTemplate*: string = staticRead "./templates/channel.mustache" submitTemplate*: string = staticRead "./templates/submit.mustache" testTemplate*: string = """

hi!

""" let db = open("data/quotes.db", nil, nil, nil) try: db.exec(sql"""create table if not exists quotes ( id INTEGER PRIMARY KEY, channel TEXT, adder TEXT, nick TEXT, message TEXT, time REAL, deleted INTEGER DEFAULT 0)""") except: echo getCurrentExceptionMsg() raise proc validItem(s: string, channel: bool = false) = if channel: if s.startsWith "#": echo "fuck" else: raise newException(ValueError, "invalid layout of channel name") else: discard if s.contains " ": raise newException(ValueError, "invalid layout of quote") else: discard template renderMustache*(title: string, templ: string, ctx: Context): expr = var layoutCtx = moustachu.newContext() layoutCtx["title"] = title layoutCtx["body"] = render(templ, ctx) resp render(baseTemplate, layoutCtx) template fail*(): expr = var ctx = newContext() ctx["exception"] = getCurrentExceptionMsg() var layoutCtx = moustachu.newContext() layoutCtx["title"] = "fail" layoutCtx["body"] = render(errorTemplate, ctx) halt render(baseTemplate, layoutCtx) template contextQuote(ctx: Context, qid: int, quote: Row): expr = ctx["listid"] = qid ctx["id"] = quote[0].parseInt().encodeURLSimple() ctx["channel"] = quote[1] ctx["channelsafe"] = quote[1].replace("#", "hashtag-") ctx["nick"] = quote[2] ctx["adder"] = quote[3] ctx["message"] = quote[4] ctx["time"] = parseInt(split(quote[5], '.')[0]) template pagination(ctx: Context, qid: int, kind: string): expr = ctx["paging"] = true if qid != 0: ctx["isnt1"] = true ctx["prev"] = qid - 1 ctx["next"] = qid + 1 ctx["kind"] = kind settings: port = getEnv("PORT").parseInt().Port bindAddr = "0.0.0.0" routes: get "/test": renderMustache("test", testTemplate, newContext()) get "/": redirect "/browse/0" get "/channel": try: var channels = db.getAllRows(sql"select channel from quotes group by channel") ctx: Context = newContext() channelList = newSeq[Context]() for row in channels.items(): var c = newContext() c["name"] = row[0] c["safe"] = row[0].replace("#", "hashtag-") channelList.add c ctx["channels"] = channelList renderMustache("channel list", channelTemplate, ctx) except: fail() get "/submit": renderMustache "submit", submitTemplate, newContext() post "/submit": try: var channel = $(request.formData.mget "channel").body nick = $(request.formData.mget "nick").body adder = $(request.formData.mget "adder").body quote = $(request.formData.mget "quote").body channel.validItem() nick.validItem() adder.validItem() let now = $(getTime().toSeconds()) data = now.split(".")[0].parseInt() db.exec(sql"INSERT INTO quotes VALUES(null, ?, ?, ?, ?, ?, 0);", channel, nick, adder, quote, data) redirect (channel.replace("#", "hashtag-") & "/0") except: fail() get "/@kind/@id": var title: string = "" ctx: Context rows: seq[Row] qid: int = 0 try: qid = (@"id").parseInt except: qid = (@"id").decodeURLSimple() redirect "/" & @"kind" & "/" & $qid case @"kind": of "browse": rows = db.getAllRows(sql"SELECT * FROM quotes ORDER BY time desc LIMIT 20 OFFSET ?", (qid * 20)) title = "page " & @"id" of "quotes": rows = db.getAllRows(sql"SELECT * FROM quotes WHERE id = ?", qid) title = "quote #" & $qid & " by " & rows[0][2] else: if (@"kind").startsWith "hashtag-": let channel = (@"kind").replace("hashtag-", "#") rows = db.getAllRows(sql"SELECT * FROM quotes WHERE channel=? ORDER BY time desc LIMIT 20 OFFSET ?", channel, qid * 20) title = channel & " page " & @"id" else: halt Http404, "not found" echo request.headers.getOrDefault "X-Forwarded-For" ctx = newContext() var quoteSeq = newSeq[Context]() for row in items(rows): var c = newContext() c.contextQuote row[0].parseInt(), row quoteSeq.add c ctx["quotes"] = quoteSeq ctx.pagination(qid, @"kind") renderMustache(title, browseTemplate, ctx) runForever()