Implements newthread logic on backend and marries it all together.
This commit is contained in:
parent
76c7f43079
commit
702967f624
3 changed files with 84 additions and 14 deletions
68
forum.nim
68
forum.nim
|
|
@ -77,6 +77,7 @@ type
|
||||||
lastIp: string
|
lastIp: string
|
||||||
|
|
||||||
ForumError = object of Exception
|
ForumError = object of Exception
|
||||||
|
data: PostError
|
||||||
|
|
||||||
var
|
var
|
||||||
db: DbConn
|
db: DbConn
|
||||||
|
|
@ -85,6 +86,16 @@ var
|
||||||
useCaptcha: bool
|
useCaptcha: bool
|
||||||
captcha: ReCaptcha
|
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) =
|
proc init(c: TForumData) =
|
||||||
c.userPass = ""
|
c.userPass = ""
|
||||||
c.userName = ""
|
c.userName = ""
|
||||||
|
|
@ -1076,9 +1087,10 @@ proc executeReply(c: TForumData, threadId: int, content: string,
|
||||||
|
|
||||||
let subject = "" # TODO: Remove this redundant field.
|
let subject = "" # TODO: Remove this redundant field.
|
||||||
if rateLimitCheck(c):
|
if rateLimitCheck(c):
|
||||||
raise newException(ForumError, "You're posting too fast!")
|
raise newForumError("You're posting too fast!")
|
||||||
|
|
||||||
# TODO: Replying to.
|
# TODO: Replying to.
|
||||||
|
# Verify that content can be parsed as RST.
|
||||||
let retID = insertID(
|
let retID = insertID(
|
||||||
db,
|
db,
|
||||||
crud(crCreate, "post", "author", "ip", "header", "content", "thread"),
|
crud(crCreate, "post", "author", "ip", "header", "content", "thread"),
|
||||||
|
|
@ -1095,6 +1107,35 @@ proc executeReply(c: TForumData, threadId: int, content: string,
|
||||||
|
|
||||||
return retID
|
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()
|
initialise()
|
||||||
|
|
||||||
routes:
|
routes:
|
||||||
|
|
@ -1370,12 +1411,31 @@ routes:
|
||||||
try:
|
try:
|
||||||
let id = executeReply(c, threadId, msg, replyingTo)
|
let id = executeReply(c, threadId, msg, replyingTo)
|
||||||
resp Http200, $(%id), "application/json"
|
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(
|
let err = PostError(
|
||||||
errorFields: @[],
|
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/(.+)?":
|
get re"/karax/(.+)?":
|
||||||
resp readFile("redesign/karax.html")
|
resp readFile("redesign/karax.html")
|
||||||
|
|
|
||||||
|
|
@ -13,28 +13,35 @@ when defined(js):
|
||||||
loading: bool
|
loading: bool
|
||||||
error: Option[PostError]
|
error: Option[PostError]
|
||||||
replyBox: ReplyBox
|
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) =
|
proc onCreatePost(httpStatus: int, response: kstring, state: NewThread) =
|
||||||
postFinished:
|
postFinished:
|
||||||
# TODO
|
let j = parseJson($response)
|
||||||
discard
|
let response = to(j, array[2, int])
|
||||||
|
navigateTo(renderPostUrl(response[0], response[1]))
|
||||||
|
|
||||||
proc onCreateClick(ev: Event, n: VNode, state: NewThread) =
|
proc onCreateClick(ev: Event, n: VNode, state: NewThread) =
|
||||||
state.loading = true
|
state.loading = true
|
||||||
state.error = none[PostError]()
|
state.error = none[PostError]()
|
||||||
|
|
||||||
let uri = makeUri("login")
|
let uri = makeUri("newthread")
|
||||||
# TODO: This is a hack, karax should support this.
|
# TODO: This is a hack, karax should support this.
|
||||||
let formData = newFormData()
|
let formData = newFormData()
|
||||||
#formData.append("" TODO
|
formData.append("subject", state.subject)
|
||||||
|
formData.append("msg", state.replyBox.getText())
|
||||||
ajaxPost(uri, @[], cast[cstring](formData),
|
ajaxPost(uri, @[], cast[cstring](formData),
|
||||||
(s: int, r: kstring) => onCreatePost(s, r, state))
|
(s: int, r: kstring) => onCreatePost(s, r, state))
|
||||||
|
|
||||||
proc newNewThread*(): NewThread =
|
|
||||||
NewThread(
|
|
||||||
replyBox: newReplyBox(nil)
|
|
||||||
)
|
|
||||||
|
|
||||||
proc render*(state: NewThread): VNode =
|
proc render*(state: NewThread): VNode =
|
||||||
result = buildHtml():
|
result = buildHtml():
|
||||||
section(class="container grid-xl"):
|
section(class="container grid-xl"):
|
||||||
|
|
@ -43,7 +50,8 @@ when defined(js):
|
||||||
p(): text "New Thread"
|
p(): text "New Thread"
|
||||||
tdiv(class="content"):
|
tdiv(class="content"):
|
||||||
input(class="form-input", `type`="text", name="username",
|
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]())
|
renderContent(state.replyBox, none[Thread](), none[Post]())
|
||||||
tdiv(class="footer"):
|
tdiv(class="footer"):
|
||||||
button(class=class(
|
button(class=class(
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,8 @@ when defined(js):
|
||||||
|
|
||||||
state.shown = true
|
state.shown = true
|
||||||
|
|
||||||
|
proc getText*(state: ReplyBox): kstring = state.text
|
||||||
|
|
||||||
proc onPreviewPost(httpStatus: int, response: kstring, state: ReplyBox) =
|
proc onPreviewPost(httpStatus: int, response: kstring, state: ReplyBox) =
|
||||||
postFinished:
|
postFinished:
|
||||||
kout(response)
|
kout(response)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue