A Python content management system designed for kirsle.net featuring a blog, comments and photo albums. https://rophako.kirsle.net/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

219 rivejä
6.9 KiB

  1. # -*- coding: utf-8 -*-
  2. """Endpoints for the commenting subsystem."""
  3. from flask import Blueprint, g, request, redirect, url_for, flash
  4. import time
  5. import rophako.model.user as User
  6. import rophako.model.comment as Comment
  7. from rophako.utils import (template, pretty_time, login_required, sanitize_name,
  8. remote_addr)
  9. from rophako.plugin import load_plugin
  10. from rophako.settings import Config
  11. mod = Blueprint("comment", __name__, url_prefix="/comments")
  12. load_plugin("rophako.modules.emoticons")
  13. @mod.route("/")
  14. def index():
  15. return template("blog/index.html")
  16. @mod.route("/preview", methods=["POST"])
  17. def preview():
  18. # Get the form fields.
  19. form = get_comment_form(request.form)
  20. thread = sanitize_name(form["thread"])
  21. # Trap fields.
  22. trap1 = request.form.get("website", "x") != "http://"
  23. trap2 = request.form.get("email", "x") != ""
  24. if trap1 or trap2:
  25. flash("Wanna try that again?")
  26. return redirect(url_for("index"))
  27. # Validate things.
  28. if len(form["message"]) == 0:
  29. flash("You must provide a message with your comment.")
  30. return redirect(form["url"])
  31. # Gravatar?
  32. gravatar = Comment.gravatar(form["contact"])
  33. # Are they submitting?
  34. if form["action"] == "submit":
  35. Comment.add_comment(
  36. thread=thread,
  37. uid=g.info["session"]["uid"],
  38. ip=remote_addr(),
  39. time=int(time.time()),
  40. image=gravatar,
  41. name=form["name"],
  42. subject=form["subject"],
  43. message=form["message"],
  44. url=form["url"],
  45. )
  46. # Are we subscribing to the thread?
  47. if form["subscribe"] == "true":
  48. email = form["contact"]
  49. if "@" in email:
  50. Comment.add_subscriber(thread, email)
  51. flash("You have been subscribed to future comments on this page.")
  52. flash("Your comment has been added!")
  53. return redirect(form["url"])
  54. # Gravatar.
  55. g.info["gravatar"] = gravatar
  56. g.info["preview"] = Comment.format_message(form["message"])
  57. g.info["pretty_time"] = pretty_time(Config.comment.time_format, time.time())
  58. g.info.update(form)
  59. return template("comment/preview.html")
  60. @mod.route("/delete/<thread>/<cid>")
  61. @login_required
  62. def delete(thread, cid):
  63. """Delete a comment."""
  64. url = request.args.get("url")
  65. Comment.delete_comment(thread, cid)
  66. flash("Comment deleted!")
  67. return redirect(url or url_for("index"))
  68. @mod.route("/edit/<thread>/<cid>", methods=["GET", "POST"])
  69. @login_required
  70. def edit(thread, cid):
  71. """Edit an existing comment."""
  72. url = request.args.get("url")
  73. comment = Comment.get_comment(thread, cid)
  74. if not comment:
  75. flash("The comment wasn't found!")
  76. return redirect(url or url_for("index"))
  77. # Submitting?
  78. if request.method == "POST":
  79. action = request.form.get("action")
  80. message = request.form.get("message")
  81. url = request.form.get("url") # Preserve the URL!
  82. if len(message) == 0:
  83. flash("The comment must have a message!")
  84. return redirect(url_for(".edit", thread=thread, cid=cid, url=url))
  85. # Update the real comment data with the submitted message (for preview),
  86. # if they clicked Save it will then be saved back to disk.
  87. comment["message"] = message
  88. if action == "save":
  89. # Saving the changes!
  90. Comment.update_comment(thread, cid, comment)
  91. flash("Comment updated successfully!")
  92. return redirect(url or url_for("index"))
  93. # Render the Markdown.
  94. comment["formatted_message"] = Comment.format_message(comment["message"])
  95. g.info["thread"] = thread
  96. g.info["cid"] = cid
  97. g.info["comment"] = comment
  98. g.info["url"] = url or ""
  99. return template("comment/edit.html")
  100. @mod.route("/privacy")
  101. def privacy():
  102. """The privacy policy and global unsubscribe page."""
  103. return template("comment/privacy.html")
  104. @mod.route("/unsubscribe", methods=["GET", "POST"])
  105. def unsubscribe():
  106. """Unsubscribe an e-mail from a comment thread (or all threads)."""
  107. # This endpoint can be called with either method. For the unsubscribe links
  108. # inside the e-mails, it uses GET. For the global out-opt, it uses POST.
  109. thread, email = None, None
  110. if request.method == "POST":
  111. thread = request.form.get("thread", "")
  112. email = request.form.get("email", "")
  113. # Spam check.
  114. trap1 = request.form.get("url", "x") != "http://"
  115. trap2 = request.form.get("message", "x") != ""
  116. if trap1 or trap2:
  117. flash("Wanna try that again?")
  118. return redirect(url_for("index"))
  119. else:
  120. thread = request.args.get("thread", "")
  121. email = request.args.get("who", "")
  122. # Input validation.
  123. if not thread:
  124. flash("Comment thread not found.")
  125. return redirect(url_for("index"))
  126. if not email:
  127. flash("E-mail address not provided.")
  128. return redirect(url_for("index"))
  129. # Do the unsubscribe. If thread is *, this means a global unsubscribe from
  130. # all threads.
  131. Comment.unsubscribe(thread, email)
  132. g.info["thread"] = thread
  133. g.info["email"] = email
  134. return template("comment/unsubscribed.html")
  135. def partial_index(thread, subject, header=True):
  136. """Partial template for including the index view of a comment thread."""
  137. comments = Comment.get_comments(thread)
  138. # Sort the comments by most recent on bottom.
  139. sorted_cids = [ x for x in sorted(comments, key=lambda y: comments[y]["time"]) ]
  140. sorted_comments = []
  141. for cid in sorted_cids:
  142. comment = comments[cid]
  143. comment["id"] = cid
  144. # Was the commenter logged in?
  145. if comment["uid"] > 0:
  146. user = User.get_user(uid=comment["uid"])
  147. avatar = User.get_picture(uid=comment["uid"])
  148. comment["name"] = user["name"]
  149. comment["username"] = user["username"]
  150. comment["image"] = avatar
  151. # Add the pretty time.
  152. comment["pretty_time"] = pretty_time(Config.comment.time_format, comment["time"])
  153. # Format the message for display.
  154. comment["formatted_message"] = Comment.format_message(comment["message"])
  155. sorted_comments.append(comment)
  156. g.info["header"] = header
  157. g.info["thread"] = thread
  158. g.info["subject"] = subject
  159. g.info["url"] = request.url
  160. g.info["comments"] = sorted_comments
  161. g.info["photo_url"] = Config.photo.root_public
  162. return template("comment/index.inc.html")
  163. def get_comment_form(form):
  164. return dict(
  165. action = request.form.get("action", ""),
  166. thread = request.form.get("thread", ""),
  167. url = request.form.get("url", ""),
  168. subject = request.form.get("subject", "[No Subject]"),
  169. name = request.form.get("name", ""),
  170. contact = request.form.get("contact", ""),
  171. message = request.form.get("message", ""),
  172. subscribe = request.form.get("subscribe", "false"),
  173. )