Implements newthread logic on backend and marries it all together.

This commit is contained in:
Dominik Picheta 2018-05-15 20:40:59 +01:00
commit 702967f624
3 changed files with 84 additions and 14 deletions

View file

@ -77,6 +77,7 @@ type
lastIp: string
ForumError = object of Exception
data: PostError
var
db: DbConn
@ -85,6 +86,16 @@ var
useCaptcha: bool
captcha: ReCaptcha
proc newForumError(message: string,
fields: seq[string] = @[]): ref ForumError =
new(result)
result.msg = message
result.data =
PostError(
errorFields: fields,
message: message
)
proc init(c: TForumData) =
c.userPass = ""
c.userName = ""
@ -1076,9 +1087,10 @@ proc executeReply(c: TForumData, threadId: int, content: string,
let subject = "" # TODO: Remove this redundant field.
if rateLimitCheck(c):
raise newException(ForumError, "You're posting too fast!")
raise newForumError("You're posting too fast!")
# TODO: Replying to.
# Verify that content can be parsed as RST.
let retID = insertID(
db,
crud(crCreate, "post", "author", "ip", "header", "content", "thread"),
@ -1095,6 +1107,35 @@ proc executeReply(c: TForumData, threadId: int, content: string,
return retID
proc executeNewThread(c: TForumData, subject, msg: string): (int64, int64) =
const
query = sql"""
insert into thread(name, views, modified) values (?, 0, DATETIME('now'))
"""
assert c.loggedIn()
if subject.len <= 2:
raise newForumError("Subject is too short", @["subject"])
if subject.len > 100:
raise newForumError("Subject is too long", @["subject"])
if not validateRst(c, msg):
raise newForumError("Message needs to be valid RST", @["msg"])
if rateLimitCheck(c):
raise newForumError("You're posting too fast!")
result[0] = tryInsertID(db, query, subject).int
if result[0] < 0:
raise newForumError("Subject already exists", @["subject"])
discard tryExec(db, crud(crCreate, "thread_fts", "id", "name"),
c.threadID, subject)
result[1] = executeReply(c, result[0].int, msg, -1)
discard tryExec(db, sql"insert into post_fts(post_fts) values('optimize')")
discard tryExec(db, sql"insert into post_fts(thread_fts) values('optimize')")
initialise()
routes:
@ -1370,12 +1411,31 @@ routes:
try:
let id = executeReply(c, threadId, msg, replyingTo)
resp Http200, $(%id), "application/json"
except ForumError:
except ForumError as exc:
resp Http400, $(%exc.data), "application/json"
post "/karax/newthread":
createTFD()
if not c.loggedIn():
let err = PostError(
errorFields: @[],
message: getCurrentExceptionMsg()
message: "Not logged in."
)
resp Http400, $(%err), "application/json"
resp Http401, $(%err), "application/json"
let formData = request.formData
cond "msg" in formData
cond "subject" in formData
let msg = formData["msg"].body
let subject = formData["subject"].body
# TODO: category
try:
let res = executeNewThread(c, subject, msg)
resp Http200, $(%[res[0], res[1]]), "application/json"
except ForumError as exc:
resp Http400, $(%exc.data), "application/json"
get re"/karax/(.+)?":
resp readFile("redesign/karax.html")

View file

@ -13,28 +13,35 @@ when defined(js):
loading: bool
error: Option[PostError]
replyBox: ReplyBox
subject: kstring
proc newNewThread*(): NewThread =
NewThread(
replyBox: newReplyBox(nil),
subject: ""
)
proc onSubjectChange(e: Event, n: VNode, state: NewThread) =
state.subject = n.value
proc onCreatePost(httpStatus: int, response: kstring, state: NewThread) =
postFinished:
# TODO
discard
let j = parseJson($response)
let response = to(j, array[2, int])
navigateTo(renderPostUrl(response[0], response[1]))
proc onCreateClick(ev: Event, n: VNode, state: NewThread) =
state.loading = true
state.error = none[PostError]()
let uri = makeUri("login")
let uri = makeUri("newthread")
# TODO: This is a hack, karax should support this.
let formData = newFormData()
#formData.append("" TODO
formData.append("subject", state.subject)
formData.append("msg", state.replyBox.getText())
ajaxPost(uri, @[], cast[cstring](formData),
(s: int, r: kstring) => onCreatePost(s, r, state))
proc newNewThread*(): NewThread =
NewThread(
replyBox: newReplyBox(nil)
)
proc render*(state: NewThread): VNode =
result = buildHtml():
section(class="container grid-xl"):
@ -43,7 +50,8 @@ when defined(js):
p(): text "New Thread"
tdiv(class="content"):
input(class="form-input", `type`="text", name="username",
placeholder="Type the title here")
placeholder="Type the title here",
onChange=(e: Event, n: VNode) => onSubjectChange(e, n, state))
renderContent(state.replyBox, none[Thread](), none[Post]())
tdiv(class="footer"):
button(class=class(

View file

@ -39,6 +39,8 @@ when defined(js):
state.shown = true
proc getText*(state: ReplyBox): kstring = state.text
proc onPreviewPost(httpStatus: int, response: kstring, state: ReplyBox) =
postFinished:
kout(response)