2016-02-12 10:29:04 +00:00
import asyncdispatch , db_sqlite , httpclient , jester , json , moustachu , os , shorturl ,
2016-02-10 10:45:09 +00:00
strutils , tables , templates / all , times , tweet / parse , twtxt , typetraits
2016-02-06 15:54:55 +00:00
let
db = open ( " data/twtxt.db " , nil , nil , nil )
try :
db . exec sql""" create table if not exists users (
id INTEGER PRIMARY KEY ,
username TEXT UNIQUE ,
url TEXT UNIQUE
) ; """
db . exec sql""" create table if not exists tweets (
id INTEGER PRIMARY KEY ,
username TEXT ,
time REAL ,
tweet TEXT ,
UNIQUE ( username , time , tweet )
) ; """
except :
quit getCurrentExceptionMsg ( )
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 )
2016-02-06 17:49:14 +00:00
template pagination ( ctx : Context , isnt1 : bool , prev , next : string ) : expr =
ctx [ " paging " ] = true
ctx [ " isnt1 " ] = isnt1
ctx [ " prev " ] = prev
ctx [ " next " ] = next
2016-02-06 15:54:55 +00:00
settings :
2016-02-06 15:56:27 +00:00
port = getEnv ( " PORT " ) . parseInt ( ) . Port
bindAddr = " 0.0.0.0 "
2016-02-06 15:54:55 +00:00
routes :
get " / " :
2016-02-11 15:44:45 +00:00
var ctx = newContext ( )
let
users = db . getValue sql" select count(*) from users "
tweets = db . getValue sql" select count(*) from tweets "
ctx [ " users " ] = users
ctx [ " tweets " ] = tweets
renderMustache ( " home " , indexTemplate , ctx )
2016-02-06 16:27:31 +00:00
2016-02-08 03:16:33 +00:00
get " /changelog " :
const log = staticExec " git log -10 "
var ctx = newContext ( )
ctx [ " changelog " ] = log
renderMustache ( " changelog " , changelogTemplate , ctx )
2016-02-06 17:49:14 +00:00
get " /content/system " :
2016-02-06 18:45:51 +00:00
let
myHeaders = {
" Content-Type " : " text/plain " ,
}
tweets = db . getAllRows ( sql" select * from tweets where username= ' system ' " )
2016-02-06 17:49:14 +00:00
2016-02-06 18:45:51 +00:00
var res = " "
for tweet in tweets . items ( ) :
res & = $ ( tweet . fromDBRow ( ) ) & " \r \n "
resp Http200 , myHeaders , res
2016-02-06 17:49:14 +00:00
get " /timeline " :
redirect " /timeline/0 "
2016-02-06 18:18:57 +00:00
get " /submit " :
renderMustache " submit " , submitTemplate , newContext ( )
post " /submit " :
try :
var
username = $ ( request . formData . mget " username " ) . body
url = $ ( request . formData . mget " url " ) . body
2016-02-10 18:50:01 +00:00
db . updateTweetsByUser ( username , url )
2016-02-06 18:18:57 +00:00
db . exec ( sql" insert into users values (null, ?, ?) " , username , url )
2016-02-12 10:46:59 +00:00
db . exec ( sql" insert into tweets values (null, ' twtxtlist ' , ?, ?) " ,
$ ( getTime ( ) . getGMTime ( ) . timeinfoToTime ( ) . toSeconds ( ) ) ,
2016-02-13 00:31:27 +00:00
" Added user @< " & username & " " & url & " > " )
2016-02-06 18:18:57 +00:00
redirect " /users/ " & username & " /0 "
except : fail ( )
2016-02-06 16:27:31 +00:00
get " /users " :
var
2016-02-06 18:18:57 +00:00
users = db . getAllRows ( sql" select username, url from users order by username " )
2016-02-06 16:27:31 +00:00
ctx = newContext ( )
userList = newSeq [ Context ] ( )
for user in users . items ( ) :
var c = newContext ( )
c [ " username " ] = user [ 0 ]
c [ " url " ] = user [ 1 ]
userList . add c
ctx [ " users " ] = userList
renderMustache " users " , usersTemplate , ctx
2016-02-06 15:54:55 +00:00
2016-02-12 10:29:04 +00:00
get " /users.txt " :
let
headers = {
" Content-Type " : " text/plain "
}
users = db . getAllRows ( sql" select username, url from users order by username " )
var outBuf = " "
for user in users . items ( ) :
outBuf & = " twtxt follow " & user [ 0 ] & " " & user [ 1 ] & " \r \n "
resp Http200 , headers , outBuf
2016-02-06 17:49:14 +00:00
get " /users/@name/@page " :
try :
var
tweets = db . getAllRows ( sql" select * from tweets where username=? order by time desc limit 20 offset ? " , @ " name " , ( @ " page " ) . parseInt ( ) * 20 )
ctx = newContext ( )
tweetList = newSeq [ Context ] ( )
if len ( tweets ) = = 0 :
raise newException ( ValueError , " no such page " )
var
userctx = newContext ( )
userurl = db . getValue ( sql" select url from users where username=? " , @ " name " )
userctx [ " url " ] = userurl
2016-02-07 15:15:22 +00:00
userctx [ " username " ] = @ " name "
2016-02-06 17:49:14 +00:00
ctx [ " user " ] = userctx
for tweet in tweets . items ( ) :
var c = newContext ( )
let time = tweet [ 2 ] . split ( " . " ) [ 0 ] . parseInt ( )
c [ " id " ] = tweet [ 0 ]
c [ " permalink " ] = tweet [ 0 ] . parseInt ( ) . encodeURLSimple ( )
c [ " username " ] = tweet [ 1 ]
c [ " time " ] = time
2016-02-10 10:45:09 +00:00
c [ " tweet " ] = $ tweet [ 3 ] . prettyfyTweet ( )
2016-02-06 17:49:14 +00:00
tweetList . add c
ctx [ " tweets " ] = tweetList
let id = ( @ " page " ) . parseInt ( )
if @ " page " = = " 0 " :
ctx . pagination ( false , " " , " /users/ " & @ " name " & " / " & $ ( id + 1 ) )
else :
ctx . pagination ( true , " /users/ " & @ " name " & " / " & $ ( id - 1 ) , " /users/ " & @ " name " & " / " & $ ( id + 1 ) )
renderMustache ( @ " name " & " page " & @ " page " , tweetsTemplate , ctx )
except : fail ( )
get " /timeline/@page " :
try :
var
2016-02-12 19:59:27 +00:00
tweets = db . getAllRows ( sql" select * from tweets where username <> ' twtxtlist ' and username <> ' directory ' order by time desc limit 20 offset ? " , ( @ " page " ) . parseInt ( ) * 20 )
2016-02-06 17:49:14 +00:00
ctx = newContext ( )
tweetList = newSeq [ Context ] ( )
if tweets . len = = 0 :
raise newException ( ValueError , " no such page " )
for tweet in tweets . items ( ) :
var c = newContext ( )
let time = tweet [ 2 ] . split ( " . " ) [ 0 ] . parseInt ( )
c [ " id " ] = tweet [ 0 ]
c [ " permalink " ] = tweet [ 0 ] . parseInt ( ) . encodeURLSimple ( )
c [ " username " ] = tweet [ 1 ]
c [ " time " ] = time
2016-02-10 10:45:09 +00:00
c [ " tweet " ] = $ tweet [ 3 ] . prettyfyTweet ( )
2016-02-06 17:49:14 +00:00
tweetList . add c
ctx [ " tweets " ] = tweetList
let id = ( @ " page " ) . parseInt ( )
if @ " page " = = " 0 " :
ctx . pagination ( false , " " , " /timeline/ " & $ ( id + 1 ) )
else :
ctx . pagination ( true , " /timeline/ " & $ ( id - 1 ) , " /timeline/ " & $ ( id + 1 ) )
renderMustache ( " timeline page " & @ " page " , tweetsTemplate , ctx )
except : fail ( )
2016-02-06 18:18:57 +00:00
get " /tweet/@tid " :
try :
var
tweets = db . getAllRows ( sql" select * from tweets where id=? limit 1 " , ( @ " tid " ) . decodeURLSimple ( ) )
ctx = newContext ( )
tweetList = newSeq [ Context ] ( )
if tweets . len = = 0 :
raise newException ( ValueError , " no such tweet " )
for tweet in tweets . items ( ) :
var c = newContext ( )
let time = tweet [ 2 ] . split ( " . " ) [ 0 ] . parseInt ( )
c [ " id " ] = tweet [ 0 ]
c [ " permalink " ] = tweet [ 0 ] . parseInt ( ) . encodeURLSimple ( )
c [ " username " ] = tweet [ 1 ]
c [ " time " ] = time
2016-02-10 10:45:09 +00:00
c [ " tweet " ] = $ tweet [ 3 ] . prettyfyTweet ( )
2016-02-06 18:18:57 +00:00
tweetList . add c
ctx [ " tweets " ] = tweetList
renderMustache ( " tweet " & @ " tid " , tweetsTemplate , ctx )
except : fail ( )
2016-02-06 15:54:55 +00:00
runForever ( )