|
@ -3,21 +3,25 @@ import twitter |
|
|
import templates |
|
|
import templates |
|
|
import jester |
|
|
import jester |
|
|
|
|
|
|
|
|
|
|
|
type Author = object |
|
|
|
|
|
name: string |
|
|
|
|
|
authorID : int |
|
|
|
|
|
|
|
|
type ThreadRequest = object |
|
|
type ThreadRequest = object |
|
|
tweetID: string |
|
|
tweetID: string |
|
|
author: string |
|
|
author: Author |
|
|
|
|
|
|
|
|
type TwitterThread = ref object of RootObj |
|
|
type TwitterThread = ref object of RootObj |
|
|
tweetID: string |
|
|
tweetID: string |
|
|
author: string |
|
|
|
|
|
tweets: string |
|
|
tweets: string |
|
|
|
|
|
author: Author |
|
|
|
|
|
|
|
|
proc parseTweetUrl(url : string) : Option[ThreadRequest] = |
|
|
proc parseTweetUrl(url : string) : Option[ThreadRequest] = |
|
|
let path = url.parseUri.path |
|
|
let path = url.parseUri.path |
|
|
var author : string |
|
|
var author : string |
|
|
var tweetID : int |
|
|
var tweetID : int |
|
|
if scanf(path, "/$w/status/$i$.", author, tweetID): |
|
|
if scanf(path, "/$w/status/$i$.", author, tweetID): |
|
|
some(ThreadRequest(tweetID : $tweetID, author: author)) |
|
|
some(ThreadRequest(tweetID : $tweetID, author: Author(name: author))) |
|
|
else: |
|
|
else: |
|
|
none(ThreadRequest) |
|
|
none(ThreadRequest) |
|
|
|
|
|
|
|
@ -30,38 +34,70 @@ chan.open(20) |
|
|
|
|
|
|
|
|
let db = open("tweetlog.db", "", "", "") |
|
|
let db = open("tweetlog.db", "", "", "") |
|
|
|
|
|
|
|
|
proc createTweetTable() = |
|
|
proc createTweetTables() = |
|
|
db.exec(sql"""CREATE TABLE IF NOT EXISTS threads ( |
|
|
db.exec(sql"""CREATE TABLE IF NOT EXISTS threads ( |
|
|
id INTEGER PRIMARY KEY, |
|
|
id INTEGER PRIMARY KEY, |
|
|
tid TEXT, |
|
|
tid TEXT, |
|
|
author TEXT, |
|
|
tweets TEXT, |
|
|
tweets TEXT |
|
|
authorID INTEGER |
|
|
|
|
|
)""") |
|
|
|
|
|
|
|
|
|
|
|
db.exec(sql"""CREATE TABLE IF NOT EXISTS authors ( |
|
|
|
|
|
id INTEGER PRIMARY KEY, |
|
|
|
|
|
name TEXT, |
|
|
|
|
|
UNIQUE(name, id) |
|
|
)""") |
|
|
)""") |
|
|
|
|
|
|
|
|
proc threadExists(threadID : string, author : string) : Option[TwitterThread] = |
|
|
proc authorExists(authorName : string) : Option[Author] = |
|
|
let row = db.getRow(sql"SELECT * FROM threads WHERE tid=? AND author=?", threadID, author) |
|
|
let authorID = db.getRow(sql"SELECT * from authors where name=?", authorName) |
|
|
|
|
|
|
|
|
|
|
|
if authorID.all(col => col == ""): |
|
|
|
|
|
return none(Author) |
|
|
|
|
|
|
|
|
|
|
|
return some(Author(name: authorName, authorID: authorID[0].parseInt)) |
|
|
|
|
|
|
|
|
|
|
|
proc threadExists(threadID : string, authorName : string) : Option[TwitterThread] = |
|
|
|
|
|
let author = authorName.authorExists |
|
|
|
|
|
|
|
|
|
|
|
if not author.isSome: |
|
|
|
|
|
return none(TwitterThread) |
|
|
|
|
|
|
|
|
|
|
|
let row = db.getRow(sql"SELECT * FROM threads WHERE tid=? AND authorID=?", threadID, author.get.authorID) |
|
|
|
|
|
|
|
|
if row.all(col => col == ""): |
|
|
if row.all(col => col == ""): |
|
|
return none(TwitterThread) |
|
|
return none(TwitterThread) |
|
|
|
|
|
|
|
|
some( |
|
|
some( |
|
|
TwitterThread(tweetID: row[1], |
|
|
TwitterThread(tweetID: row[1], |
|
|
author: row[2], |
|
|
author: author.get, |
|
|
tweets: row[3]) |
|
|
tweets: row[2]) |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
iterator allAuthors() : string = |
|
|
iterator allAuthors() : string = |
|
|
for author in db.getAllRows(sql"SELECT DISTINCT author FROM threads"): |
|
|
for author in db.getAllRows(sql"SELECT DISTINCT name FROM authors"): |
|
|
yield author[0] |
|
|
yield author[0] |
|
|
|
|
|
|
|
|
iterator threadIDs(author : string) : string = |
|
|
iterator threadIDs(author : string) : string = |
|
|
for threadID in db.getAllRows(sql"SELECT tid from threads WHERE author=?", author): |
|
|
let authorID = db.getRow(sql"SELECT * from authors where name=?", author) |
|
|
|
|
|
|
|
|
|
|
|
if authorID.all(col => col == ""): |
|
|
|
|
|
yield "" |
|
|
|
|
|
else: |
|
|
|
|
|
for threadID in db.getAllRows(sql"SELECT tid from threads WHERE authorID=?", authorID): |
|
|
yield threadID[0] |
|
|
yield threadID[0] |
|
|
|
|
|
|
|
|
proc insertThread(thread : TwitterThread) = |
|
|
proc insertThread(thread : TwitterThread) = |
|
|
db.exec(sql"INSERT INTO threads (tid, author, tweets) VALUES (?, ?, ?)", |
|
|
db.exec(sql"INSERT OR IGNORE INTO authors (name) VALUES (?)", thread.author.name) |
|
|
|
|
|
|
|
|
|
|
|
let author = thread.author.name.authorExists |
|
|
|
|
|
|
|
|
|
|
|
if not author.isSome: |
|
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
|
|
db.exec(sql"INSERT INTO threads (tid, tweets, authorID) VALUES (?, ?, ?)", |
|
|
thread.tweetID, |
|
|
thread.tweetID, |
|
|
thread.author, |
|
|
thread.tweets, |
|
|
thread.tweets) |
|
|
author.get.authorID) |
|
|
|
|
|
|
|
|
# Routes |
|
|
# Routes |
|
|
|
|
|
|
|
@ -96,7 +132,7 @@ router twitblog: |
|
|
else: |
|
|
else: |
|
|
# Send it off to the rendering thread for processing |
|
|
# Send it off to the rendering thread for processing |
|
|
# Let them know to check back later |
|
|
# Let them know to check back later |
|
|
chan.send(ThreadRequest(tweetID: tweetID, author: author)) |
|
|
chan.send(ThreadRequest(tweetID: tweetID, author: Author(name: author))) |
|
|
resp checkBack() |
|
|
resp checkBack() |
|
|
|
|
|
|
|
|
get "/author/@author/threads": |
|
|
get "/author/@author/threads": |
|
@ -108,7 +144,7 @@ router twitblog: |
|
|
# Entry points |
|
|
# Entry points |
|
|
|
|
|
|
|
|
proc startServer* = |
|
|
proc startServer* = |
|
|
createTweetTable() |
|
|
createTweetTables() |
|
|
defer: db.close() |
|
|
defer: db.close() |
|
|
let port = 8080.Port |
|
|
let port = 8080.Port |
|
|
let settings = newSettings(port=port) |
|
|
let settings = newSettings(port=port) |
|
@ -120,10 +156,10 @@ proc handleRenders* = |
|
|
while true: |
|
|
while true: |
|
|
let t : ThreadRequest = chan.recv() |
|
|
let t : ThreadRequest = chan.recv() |
|
|
|
|
|
|
|
|
if threadExists(t.tweetID, t.author).isSome: |
|
|
if threadExists(t.tweetID, t.author.name).isSome: |
|
|
continue |
|
|
continue |
|
|
|
|
|
|
|
|
let tweets = t.tweetID.renderThread(t.author) |
|
|
let tweets = t.tweetID.renderThread(t.author.name) |
|
|
|
|
|
|
|
|
if tweets.isSome: |
|
|
if tweets.isSome: |
|
|
insertThread( |
|
|
insertThread( |
|
|