Making TForumData a ref object
Signed-off-by: Euan Torano <euantorano@gmail.com>
This commit is contained in:
parent
b780b970f4
commit
e6c4c85bb1
3 changed files with 55 additions and 54 deletions
20
forms.tmpl
20
forms.tmpl
|
|
@ -5,7 +5,7 @@
|
|||
#end template
|
||||
#
|
||||
#
|
||||
#proc genThreadsList(c: var TForumData, count: var int): string =
|
||||
#proc genThreadsList(c: TForumData, count: var int): string =
|
||||
# const queryModAdmin = sql"""select id, name, views, modified from thread
|
||||
# where id in (select thread from post where author in
|
||||
# (select id from person where status not in ('Spammer') or id = ?))
|
||||
|
|
@ -92,7 +92,7 @@
|
|||
#end proc
|
||||
#
|
||||
#
|
||||
#proc genPostPreview(c: var TForumData,
|
||||
#proc genPostPreview(c: TForumData,
|
||||
# title, content, author, date: string): string =
|
||||
# result = ""
|
||||
<a name="preview"></a>
|
||||
|
|
@ -119,7 +119,7 @@
|
|||
#end proc
|
||||
#
|
||||
#
|
||||
#proc genPostsList(c: var TForumData, threadId: string, count: var int): string =
|
||||
#proc genPostsList(c: TForumData, threadId: string, count: var int): string =
|
||||
# let query = sql("""select p.id, u.name, p.header, p.content, p.creation, p.author, u.email from post p,
|
||||
# person u
|
||||
# where u.id = p.author and p.thread = ? and $#
|
||||
|
|
@ -180,7 +180,7 @@
|
|||
#
|
||||
#proc genMarkHelp(): string
|
||||
#end proc
|
||||
#proc genFormPost(c: var TForumData, action: string,
|
||||
#proc genFormPost(c: TForumData, action: string,
|
||||
# topText, title, content: string, isEdit: bool): string =
|
||||
# result = ""
|
||||
<br />
|
||||
|
|
@ -225,7 +225,7 @@
|
|||
#end proc
|
||||
#
|
||||
#
|
||||
#proc genFormRegister(c: var TForumData): string =
|
||||
#proc genFormRegister(c: TForumData): string =
|
||||
# result = ""
|
||||
<div id="talk-head">
|
||||
<div class="info-post">
|
||||
|
|
@ -265,7 +265,7 @@
|
|||
</form>
|
||||
#end proc
|
||||
#
|
||||
#proc genFormSetRank(c: var TForumData; ui: TUserInfo): string =
|
||||
#proc genFormSetRank(c: TForumData; ui: TUserInfo): string =
|
||||
# result = ""
|
||||
<form action="${c.req.makeUri("/dosetrank/" & ui.nick, false)}" method="POST">
|
||||
<table border="0">
|
||||
|
|
@ -288,7 +288,7 @@
|
|||
</form>
|
||||
#end proc
|
||||
#
|
||||
#proc genFormLogin(c: var TForumData): string =
|
||||
#proc genFormLogin(c: TForumData): string =
|
||||
# result = ""
|
||||
# if not c.loggedIn:
|
||||
<form action="${c.req.makeUri("/dologin", false)}" method="POST">
|
||||
|
|
@ -307,7 +307,7 @@
|
|||
#end proc
|
||||
#
|
||||
#
|
||||
#proc genListOnline(c: var TForumData, stats: TForumStats): string =
|
||||
#proc genListOnline(c: TForumData, stats: TForumStats): string =
|
||||
# result = ""
|
||||
# var active: seq[string] = @[]
|
||||
# for i in stats.activeUsers:
|
||||
|
|
@ -324,7 +324,7 @@
|
|||
#
|
||||
#
|
||||
#
|
||||
#proc genSearchResults(c: var TForumData,
|
||||
#proc genSearchResults(c: TForumData,
|
||||
# results: iterator: db_sqlite.Row {.closure, tags: [ReadDbEffect].},
|
||||
# count: var int): string =
|
||||
# const threadId = 0
|
||||
|
|
@ -407,7 +407,7 @@
|
|||
#end proc
|
||||
#
|
||||
#
|
||||
#proc genFormResetPassword(c: var TForumData): string =
|
||||
#proc genFormResetPassword(c: TForumData): string =
|
||||
# result = ""
|
||||
<div id="talk-head">
|
||||
<div class="info-post">
|
||||
|
|
|
|||
81
forum.nim
81
forum.nim
|
|
@ -37,7 +37,7 @@ type
|
|||
|
||||
TPost = tuple[subject, content: string]
|
||||
|
||||
TForumData = object of TSession
|
||||
TForumData = ref object of TSession
|
||||
req: Request
|
||||
userid: string
|
||||
actionContent: string
|
||||
|
|
@ -80,7 +80,7 @@ var
|
|||
useCaptcha: bool
|
||||
captcha: ReCaptcha
|
||||
|
||||
proc init(c: var TForumData) =
|
||||
proc init(c: TForumData) =
|
||||
c.userPass = ""
|
||||
c.userName = ""
|
||||
c.threadId = unselectedThread
|
||||
|
|
@ -143,16 +143,16 @@ proc genThreadUrl(c: TForumData, postId = "", action = "", threadid = "", pageNu
|
|||
result.add("#" & postId)
|
||||
result = c.req.makeUri(result, absolute = false)
|
||||
|
||||
proc formSession(c: var TForumData, nextAction: string): string =
|
||||
proc formSession(c: TForumData, nextAction: string): string =
|
||||
return """<input type="hidden" name="threadid" value="$1" />
|
||||
<input type="hidden" name="postid" value="$2" />""" % [
|
||||
$c.threadId, $c.postid]
|
||||
|
||||
proc urlButton(c: var TForumData, text, url: string): string =
|
||||
proc urlButton(c: TForumData, text, url: string): string =
|
||||
return ("""<a class="url_button" href="$1">$2</a>""") % [
|
||||
url, text]
|
||||
|
||||
proc genButtons(c: var TForumData, btns: seq[TStyledButton]): string =
|
||||
proc genButtons(c: TForumData, btns: seq[TStyledButton]): string =
|
||||
if btns.len == 1:
|
||||
var anchor = ""
|
||||
|
||||
|
|
@ -279,13 +279,13 @@ proc validThreadId(c: TForumData): bool =
|
|||
const
|
||||
SecureChars = {'A'..'Z', 'a'..'z', '0'..'9', '_', '\128'..'\255'}
|
||||
|
||||
proc setError(c: var TForumData, field, msg: string): bool {.inline.} =
|
||||
proc setError(c: TForumData, field, msg: string): bool {.inline.} =
|
||||
c.invalidField = field
|
||||
c.errorMsg = "Error: " & msg
|
||||
return false
|
||||
|
||||
proc register(c: var TForumData, name, pass, antibot, userIp,
|
||||
email: string): bool =
|
||||
proc register(c: TForumData, name, pass, antibot, userIp,
|
||||
email: string): Future[bool] {.async.} =
|
||||
# Username validation:
|
||||
if name.len == 0 or not allCharsInSet(name, SecureChars):
|
||||
return setError(c, "name", "Invalid username!")
|
||||
|
|
@ -300,7 +300,7 @@ proc register(c: var TForumData, name, pass, antibot, userIp,
|
|||
if useCaptcha:
|
||||
var captchaValid: bool = false
|
||||
try:
|
||||
captchaValid = waitFor captcha.verify(antibot, userIp)
|
||||
captchaValid = await captcha.verify(antibot, userIp)
|
||||
except:
|
||||
echo("[ERROR] Error checking captcha: " & getCurrentExceptionMsg())
|
||||
captchaValid = false
|
||||
|
|
@ -341,12 +341,12 @@ proc register(c: var TForumData, name, pass, antibot, userIp,
|
|||
|
||||
return true
|
||||
|
||||
proc resetPassword(c: var TForumData, nick, antibot, userIp: string): bool =
|
||||
proc resetPassword(c: TForumData, nick, antibot, userIp: string): Future[bool] {.async.} =
|
||||
# captcha validation:
|
||||
if useCaptcha:
|
||||
var captchaValid: bool = false
|
||||
try:
|
||||
captchaValid = waitFor captcha.verify(antibot, userIp)
|
||||
captchaValid = await captcha.verify(antibot, userIp)
|
||||
except:
|
||||
echo("[ERROR] Error checking captcha: " & getCurrentExceptionMsg())
|
||||
captchaValid = false
|
||||
|
|
@ -378,7 +378,7 @@ proc resetPassword(c: var TForumData, nick, antibot, userIp: string): bool =
|
|||
|
||||
return true
|
||||
|
||||
proc logout(c: var TForumData) =
|
||||
proc logout(c: TForumData) =
|
||||
const query = sql"delete from session where ip = ? and password = ?"
|
||||
c.username = ""
|
||||
c.userpass = ""
|
||||
|
|
@ -395,7 +395,7 @@ proc getBanErrorMsg(banValue: string; rank: Rank): string =
|
|||
of Moderated, User, Moderator, Admin:
|
||||
return ""
|
||||
|
||||
proc checkLoggedIn(c: var TForumData) =
|
||||
proc checkLoggedIn(c: TForumData) =
|
||||
if not c.req.cookies.hasKey("sid"): return
|
||||
let pass = c.req.cookies["sid"]
|
||||
if execAffectedRows(db,
|
||||
|
|
@ -425,7 +425,7 @@ proc checkLoggedIn(c: var TForumData) =
|
|||
else:
|
||||
echo("SID not found in sessions. Assuming logged out.")
|
||||
|
||||
proc incrementViews(c: var TForumData) =
|
||||
proc incrementViews(c: TForumData) =
|
||||
const query = sql"update thread set views = views + 1 where id = ?"
|
||||
exec(db, query, $c.threadId)
|
||||
|
||||
|
|
@ -435,7 +435,7 @@ proc isPreview(c: TForumData): bool =
|
|||
proc isDelete(c: TForumData): bool =
|
||||
result = c.req.params.hasKey("delete")
|
||||
|
||||
proc validateRst(c: var TForumData, content: string): bool =
|
||||
proc validateRst(c: TForumData, content: string): bool =
|
||||
result = true
|
||||
try:
|
||||
discard rstToHtml(content)
|
||||
|
|
@ -513,7 +513,7 @@ template writeToDb(c, cr, setPostId: untyped) =
|
|||
if setPostId:
|
||||
c.postId = retID.int
|
||||
|
||||
proc updateThreads(c: var TForumData): int =
|
||||
proc updateThreads(c: TForumData): int =
|
||||
## Removes threads if they have no posts, or changes their modified field
|
||||
## if they still contain posts.
|
||||
const query =
|
||||
|
|
@ -531,7 +531,7 @@ proc updateThreads(c: var TForumData): int =
|
|||
result = -1
|
||||
discard setError(c, "", "database error")
|
||||
|
||||
proc edit(c: var TForumData, postId: int): bool =
|
||||
proc edit(c: TForumData, postId: int): bool =
|
||||
checkLogin(c)
|
||||
if c.isPreview:
|
||||
retrPost(c)
|
||||
|
|
@ -564,8 +564,8 @@ proc edit(c: var TForumData, postId: int): bool =
|
|||
exec(db, crud(crUpdate, "thread", "name"), subject, $c.threadId)
|
||||
result = true
|
||||
|
||||
proc gatherUserInfo(c: var TForumData, nick: string, ui: var TUserInfo): bool
|
||||
proc spamCheck(c: var TForumData, subject, content: string): bool =
|
||||
proc gatherUserInfo(c: TForumData, nick: string, ui: var TUserInfo): bool
|
||||
proc spamCheck(c: TForumData, subject, content: string): bool =
|
||||
# Check current user's info
|
||||
var ui: TUserInfo
|
||||
if gatherUserInfo(c, c.userName, ui):
|
||||
|
|
@ -595,7 +595,7 @@ proc spamCheck(c: var TForumData, subject, content: string): bool =
|
|||
word in contentAlphabet.toLowerAscii():
|
||||
return true
|
||||
|
||||
proc rateLimitCheck(c: var TForumData): bool =
|
||||
proc rateLimitCheck(c: TForumData): bool =
|
||||
const query40 =
|
||||
sql("SELECT count(*) FROM post where author = ? and " &
|
||||
"(strftime('%s', 'now') - strftime('%s', creation)) < 40")
|
||||
|
|
@ -614,7 +614,7 @@ proc rateLimitCheck(c: var TForumData): bool =
|
|||
if last300s > 6: return true
|
||||
return false
|
||||
|
||||
proc makeThreadURL(c: var TForumData): string =
|
||||
proc makeThreadURL(c: TForumData): string =
|
||||
c.req.makeUri("/t/" & $c.threadId)
|
||||
|
||||
template postChecks() {.dirty.} =
|
||||
|
|
@ -624,7 +624,7 @@ template postChecks() {.dirty.} =
|
|||
if rateLimitCheck(c):
|
||||
return setError(c, "subject", "You're posting too fast.")
|
||||
|
||||
proc reply(c: var TForumData): bool =
|
||||
proc reply(c: TForumData): bool =
|
||||
# reply to an existing thread
|
||||
checkLogin(c)
|
||||
retrPost(c)
|
||||
|
|
@ -642,7 +642,7 @@ proc reply(c: var TForumData): bool =
|
|||
threadUrl=c.makeThreadURL())
|
||||
result = true
|
||||
|
||||
proc newThread(c: var TForumData): bool =
|
||||
proc newThread(c: TForumData): bool =
|
||||
# create new conversation thread (permanent or transient)
|
||||
const query = sql"insert into thread(name, views, modified) values (?, 0, DATETIME('now'))"
|
||||
checkLogin(c)
|
||||
|
|
@ -665,7 +665,7 @@ proc newThread(c: var TForumData): bool =
|
|||
threadUrl=c.makeThreadURL())
|
||||
result = true
|
||||
|
||||
proc login(c: var TForumData, name, pass: string): bool =
|
||||
proc login(c: TForumData, name, pass: string): bool =
|
||||
# get form data:
|
||||
const query =
|
||||
sql"select id, name, password, email, salt, status, ban from person where name = ?"
|
||||
|
|
@ -693,7 +693,7 @@ proc login(c: var TForumData, name, pass: string): bool =
|
|||
else:
|
||||
return c.setError("password", "Login failed!")
|
||||
|
||||
proc verifyIdentHash(c: var TForumData, name, epoch, ident: string): bool =
|
||||
proc verifyIdentHash(c: TForumData, name, epoch, ident: string): bool =
|
||||
const query =
|
||||
sql"select password, salt, strftime('%s', lastOnline) from person where name = ?"
|
||||
var row = getRow(db, query, name)
|
||||
|
|
@ -704,13 +704,13 @@ proc verifyIdentHash(c: var TForumData, name, epoch, ident: string): bool =
|
|||
if row[2].parseInt > (epoch.parseInt + 60): return false
|
||||
result = newIdent == ident
|
||||
|
||||
proc deleteAll(c: var TForumData, nick: string): bool =
|
||||
proc deleteAll(c: TForumData, nick: string): bool =
|
||||
const query =
|
||||
sql("delete from post where author = (select id from person where name = ?)")
|
||||
result = tryExec(db, query, nick)
|
||||
result = result and updateThreads(c) >= 0
|
||||
|
||||
proc setStatus(c: var TForumData, nick: string, status: Rank;
|
||||
proc setStatus(c: TForumData, nick: string, status: Rank;
|
||||
reason: string): bool =
|
||||
const query =
|
||||
sql("update person set status = ?, ban = ? where name = ?")
|
||||
|
|
@ -722,13 +722,13 @@ proc setStatus(c: var TForumData, nick: string, status: Rank;
|
|||
if status == Spammer and result:
|
||||
result = deleteAll(c, nick)
|
||||
|
||||
proc setPassword(c: var TForumData, nick, pass: string): bool =
|
||||
proc setPassword(c: TForumData, nick, pass: string): bool =
|
||||
const query =
|
||||
sql("update person set password = ?, salt = ? where name = ?")
|
||||
var salt = makeSalt()
|
||||
result = tryExec(db, query, makePassword(pass, salt), salt, nick)
|
||||
|
||||
proc hasReplyBtn(c: var TForumData): bool =
|
||||
proc hasReplyBtn(c: TForumData): bool =
|
||||
result = c.req.pathInfo != "/donewthread" and c.req.pathInfo != "/doreply"
|
||||
result = result and c.req.params.getOrDefault("action") notin ["reply", "edit"]
|
||||
# If the user is not logged in and there are no page numbers then we shouldn't
|
||||
|
|
@ -737,7 +737,7 @@ proc hasReplyBtn(c: var TForumData): bool =
|
|||
result = result and (pages > 1 or c.loggedIn)
|
||||
return c.threadId >= 0 and result
|
||||
|
||||
proc getStats(c: var TForumData, simple: bool): TForumStats =
|
||||
proc getStats(c: TForumData, simple: bool): TForumStats =
|
||||
const totalUsersQuery =
|
||||
sql"select count(*) from person"
|
||||
result.totalUsers = getValue(db, totalUsersQuery).parseInt
|
||||
|
|
@ -762,7 +762,7 @@ proc getStats(c: var TForumData, simple: bool): TForumStats =
|
|||
result.newestMember = (row[1], row[0].parseInt)
|
||||
newestMemberCreation = row[3].parseInt
|
||||
|
||||
proc genPagenumNav(c: var TForumData, stats: TForumStats): string =
|
||||
proc genPagenumNav(c: TForumData, stats: TForumStats): string =
|
||||
result = ""
|
||||
var
|
||||
firstUrl = ""
|
||||
|
|
@ -835,22 +835,22 @@ proc genPagenumNav(c: var TForumData, stats: TForumStats): string =
|
|||
result.add(nextTag)
|
||||
result.add(lastTag)
|
||||
|
||||
proc gatherTotalPostsByID(c: var TForumData, thrid: int): int =
|
||||
proc gatherTotalPostsByID(c: TForumData, thrid: int): int =
|
||||
## Gets the total post count of a thread.
|
||||
result = getValue(db, sql"select count(*) from post where thread = ?", $thrid).parseInt
|
||||
|
||||
proc gatherTotalPosts(c: var TForumData) =
|
||||
proc gatherTotalPosts(c: TForumData) =
|
||||
if c.totalPosts > 0: return
|
||||
# Gather some data.
|
||||
const totalPostsQuery =
|
||||
sql"select count(*) from post p, person u where u.id = p.author and p.thread = ?"
|
||||
c.totalPosts = getValue(db, totalPostsQuery, $c.threadId).parseInt
|
||||
|
||||
proc getPagesInThread(c: var TForumData): int =
|
||||
proc getPagesInThread(c: TForumData): int =
|
||||
c.gatherTotalPosts() # Get total post count
|
||||
result = ceil(c.totalPosts / PostsPerPage).int-1
|
||||
|
||||
proc getPagesInThreadByID(c: var TForumData, thrid: int): int =
|
||||
proc getPagesInThreadByID(c: TForumData, thrid: int): int =
|
||||
result = ceil(c.gatherTotalPostsByID(thrid) / PostsPerPage).int
|
||||
|
||||
proc getThreadTitle(thrid: int, pageNum: int): string =
|
||||
|
|
@ -858,7 +858,7 @@ proc getThreadTitle(thrid: int, pageNum: int): string =
|
|||
if pageNum notin {0,1}:
|
||||
result.add(" - Page " & $pageNum)
|
||||
|
||||
proc genPagenumLocalNav(c: var TForumData, thrid: int): string =
|
||||
proc genPagenumLocalNav(c: TForumData, thrid: int): string =
|
||||
result = ""
|
||||
const maxPostPages = 6 # Maximum links to pages shown.
|
||||
const hmpp = maxPostPages div 2
|
||||
|
|
@ -878,7 +878,7 @@ proc genPagenumLocalNav(c: var TForumData, thrid: int): string =
|
|||
|
||||
result = htmlgen.span(class = "pages", result)
|
||||
|
||||
proc gatherUserInfo(c: var TForumData, nick: string, ui: var TUserInfo): bool =
|
||||
proc gatherUserInfo(c: TForumData, nick: string, ui: var TUserInfo): bool =
|
||||
ui.nick = nick
|
||||
const getUIDQuery = sql"select id from person where name = ?"
|
||||
var uid = getValue(db, getUIDQuery, nick)
|
||||
|
|
@ -908,7 +908,7 @@ proc gatherUserInfo(c: var TForumData, nick: string, ui: var TUserInfo): bool =
|
|||
include "forms.tmpl"
|
||||
include "main.tmpl"
|
||||
|
||||
proc genProfile(c: var TForumData, ui: TUserInfo): string =
|
||||
proc genProfile(c: TForumData, ui: TUserInfo): string =
|
||||
result = ""
|
||||
|
||||
result.add(htmlgen.`div`(id = "talk-head",
|
||||
|
|
@ -982,6 +982,7 @@ proc prependRe(s: string): string =
|
|||
|
||||
template createTFD() =
|
||||
var c {.inject.}: TForumData
|
||||
new(c)
|
||||
init(c)
|
||||
c.req = request
|
||||
c.startTime = epochTime()
|
||||
|
|
@ -1123,7 +1124,7 @@ routes:
|
|||
|
||||
post "/doregister":
|
||||
createTFD()
|
||||
if c.register(@"name", @"new_password", @"g-recaptcha-response", request.host, @"email"):
|
||||
if await c.register(@"name", @"new_password", @"g-recaptcha-response", request.host, @"email"):
|
||||
resp genMain(c, "You are now registered. You must now confirm your" &
|
||||
" email address by clicking the link sent to " & @"email",
|
||||
"Registration successful - Nim Forum")
|
||||
|
|
@ -1292,7 +1293,7 @@ routes:
|
|||
echo(request.params)
|
||||
cond(@"nick" != "")
|
||||
|
||||
if resetPassword(c, @"nick", @"g-recaptcha-response", request.host):
|
||||
if await resetPassword(c, @"nick", @"g-recaptcha-response", request.host):
|
||||
resp genMain(c, "Email sent!", "Reset Password - Nim Forum")
|
||||
else:
|
||||
resp genMain(c, genFormResetPassword(c), "Reset Password - Nim Forum")
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#? stdtmpl | standard
|
||||
#proc genMain(c: var TForumData, content: string, title = "Nim Forum",
|
||||
#proc genMain(c: TForumData, content: string, title = "Nim Forum",
|
||||
# additional_headers = "", showRssLinks = false): string =
|
||||
# result = ""
|
||||
# var stats: TForumStats
|
||||
|
|
@ -170,7 +170,7 @@
|
|||
</html>
|
||||
#end proc
|
||||
#
|
||||
#proc genRSSHeaders(c: var TForumData): string =
|
||||
#proc genRSSHeaders(c: TForumData): string =
|
||||
# result = ""
|
||||
<link href="${c.req.makeUri("/threadActivity.xml")}" title="Thread activity"
|
||||
type="application/atom+xml" rel="alternate">
|
||||
|
|
@ -178,7 +178,7 @@
|
|||
type="application/atom+xml" rel="alternate">
|
||||
#end proc
|
||||
#
|
||||
#proc genThreadsRSS(c: var TForumData): string =
|
||||
#proc genThreadsRSS(c: TForumData): string =
|
||||
# result = ""
|
||||
# const query = sql"""SELECT A.id, A.name,
|
||||
# strftime('%Y-%m-%dT%H:%M:%SZ', (A.modified)),
|
||||
|
|
@ -226,7 +226,7 @@ ${xmlEncode(rstToHtml(%postContent))}</content>
|
|||
</feed>
|
||||
#end proc
|
||||
#
|
||||
#proc genPostsRSS(c: var TForumData): string =
|
||||
#proc genPostsRSS(c: TForumData): string =
|
||||
# result = ""
|
||||
# const query = sql"""SELECT A.id, B.name, A.content, A.thread,
|
||||
# A.header, strftime('%Y-%m-%dT%H:%M:%SZ', A.creation),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue