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.
 
 
 
 
 

266 lines
7.7 KiB

  1. # -*- coding: utf-8 -*-
  2. """Endpoints for the photo albums."""
  3. from flask import Blueprint, g, request, redirect, url_for, session, flash
  4. import rophako.model.user as User
  5. import rophako.model.photo as Photo
  6. from rophako.utils import template, pretty_time, login_required, ajax_response
  7. from rophako.log import logger
  8. from config import *
  9. mod = Blueprint("photo", __name__, url_prefix="/photos")
  10. @mod.route("/")
  11. def index():
  12. return redirect(url_for(".albums"))
  13. @mod.route("/albums")
  14. def albums():
  15. """View the index of the photo albums."""
  16. albums = Photo.list_albums()
  17. # If there's only one album, jump directly to that one.
  18. if len(albums) == 1:
  19. return redirect(url_for(".album_index", name=albums[0]["name"]))
  20. g.info["albums"] = albums
  21. return template("photos/albums.html")
  22. @mod.route("/album/<name>")
  23. def album_index(name):
  24. """View the photos inside an album."""
  25. photos = Photo.list_photos(name)
  26. if photos is None:
  27. flash("That album doesn't exist.")
  28. return redirect(url_for(".albums"))
  29. g.info["album"] = name
  30. g.info["photos"] = photos
  31. return template("photos/album.html")
  32. @mod.route("/view/<key>")
  33. def view_photo(key):
  34. """View a specific photo."""
  35. photo = Photo.get_photo(key)
  36. if photo is None:
  37. flash("That photo wasn't found!")
  38. return redirect(url_for(".albums"))
  39. # Get the author info.
  40. author = User.get_user(uid=photo["author"])
  41. if author:
  42. g.info["author"] = author
  43. g.info["photo"] = photo
  44. g.info["photo"]["key"] = key
  45. g.info["photo"]["pretty_time"] = pretty_time(PHOTO_TIME_FORMAT, photo["uploaded"])
  46. return template("photos/view.html")
  47. @mod.route("/upload", methods=["GET", "POST"])
  48. @login_required
  49. def upload():
  50. """Upload a photo."""
  51. if request.method == "POST":
  52. # We're posting the upload.
  53. # Is this an ajax post or a direct post?
  54. is_ajax = request.form.get("__ajax", "false") == "true"
  55. # Album name.
  56. album = request.form.get("album") or request.form.get("new-album")
  57. # What source is the pic from?
  58. result = None
  59. location = request.form.get("location")
  60. if location == "pc":
  61. # An upload from the PC.
  62. result = Photo.upload_from_pc(request)
  63. elif location == "www":
  64. # An upload from the Internet.
  65. result = Photo.upload_from_www(request.form)
  66. else:
  67. flash("Stop messing around.")
  68. return redirect(url_for(".upload"))
  69. # How'd it go?
  70. if result["success"] is not True:
  71. if is_ajax:
  72. return ajax_response(False, result["error"])
  73. else:
  74. flash("The upload has failed: {}".format(result["error"]))
  75. return redirect(url_for(".upload"))
  76. # Good!
  77. if is_ajax:
  78. # Was it a multiple upload?
  79. if result.get("multi"):
  80. return ajax_response(True, url_for(".album_index", name=album))
  81. else:
  82. return ajax_response(True, url_for(".crop", photo=result["photo"]))
  83. else:
  84. if result["multi"]:
  85. return redirect(url_for(".album_index", name=album))
  86. else:
  87. return redirect(url_for(".crop", photo=result["photo"]))
  88. # Get the list of available albums.
  89. g.info["album_list"] = [
  90. "My Photos", # the default
  91. ]
  92. g.info["selected"] = PHOTO_DEFAULT_ALBUM
  93. albums = Photo.list_albums()
  94. if len(albums):
  95. g.info["album_list"] = [ album["name"] for album in albums ]
  96. g.info["selected"] = albums[0]
  97. return template("photos/upload.html")
  98. @mod.route("/crop/<photo>", methods=["GET", "POST"])
  99. @login_required
  100. def crop(photo):
  101. pic = Photo.get_photo(photo)
  102. if not pic:
  103. flash("The photo you want to crop wasn't found!")
  104. return redirect(url_for(".albums"))
  105. # Saving?
  106. if request.method == "POST":
  107. try:
  108. x = int(request.form.get("x", 0))
  109. y = int(request.form.get("y", 0))
  110. length = int(request.form.get("length", 0))
  111. except:
  112. flash("Error with form inputs.")
  113. return redirect(url_for(".crop", photo=photo))
  114. # Re-crop the photo!
  115. Photo.crop_photo(photo, x, y, length)
  116. flash("The photo has been cropped!")
  117. return redirect(url_for(".albums")) # TODO go to photo
  118. # Get the photo's true size.
  119. true_width, true_height = Photo.get_image_dimensions(pic)
  120. g.info["true_width"] = true_width
  121. g.info["true_height"] = true_height
  122. g.info["photo"] = photo
  123. g.info["preview"] = pic["large"]
  124. return template("photos/crop.html")
  125. @mod.route("/set_cover/<album>/<key>")
  126. @login_required
  127. def set_cover(album, key):
  128. """Set the pic as the album cover."""
  129. pic = Photo.get_photo(key)
  130. if not pic:
  131. flash("The photo you want to crop wasn't found!")
  132. return redirect(url_for(".albums"))
  133. Photo.set_album_cover(album, key)
  134. flash("Album cover has been set.")
  135. return redirect(url_for(".albums"))
  136. @mod.route("/set_profile/<key>")
  137. @login_required
  138. def set_profile(key):
  139. """Set the pic as your profile picture."""
  140. pic = Photo.get_photo(key)
  141. if not pic:
  142. flash("The photo wasn't found!")
  143. return redirect(url_for(".albums"))
  144. uid = g.info["session"]["uid"]
  145. User.update_user(uid, dict(picture=key))
  146. flash("Your profile picture has been updated.")
  147. return redirect(url_for(".view_photo", key=key))
  148. @mod.route("/edit/<key>", methods=["GET", "POST"])
  149. @login_required
  150. def edit(key):
  151. """Edit a photo."""
  152. pic = Photo.get_photo(key)
  153. if not pic:
  154. flash("The photo wasn't found!")
  155. return redirect(url_for(".albums"))
  156. if request.method == "POST":
  157. caption = request.form.get("caption", "")
  158. Photo.edit_photo(key, dict(caption=caption))
  159. flash("The photo has been updated.")
  160. return redirect(url_for(".view_photo", key=key))
  161. g.info["key"] = key
  162. g.info["photo"] = pic
  163. return template("photos/edit.html")
  164. @mod.route("/delete/<key>", methods=["GET", "POST"])
  165. @login_required
  166. def delete(key):
  167. """Delete a photo."""
  168. pic = Photo.get_photo(key)
  169. if not pic:
  170. flash("The photo wasn't found!")
  171. return redirect(url_for(".albums"))
  172. if request.method == "POST":
  173. # Do it.
  174. Photo.delete_photo(key)
  175. flash("The photo has been deleted.")
  176. return redirect(url_for(".albums"))
  177. g.info["key"] = key
  178. g.info["photo"] = pic
  179. return template("photos/delete.html")
  180. @mod.route("/arrange_albums", methods=["GET", "POST"])
  181. @login_required
  182. def arrange_albums():
  183. """Rearrange the photo album order."""
  184. albums = Photo.list_albums()
  185. if len(albums) == 0:
  186. flash("There are no albums yet.")
  187. return redirect(url_for(".albums"))
  188. if request.method == "POST":
  189. order = request.form.get("order", "").split(";")
  190. Photo.order_albums(order)
  191. flash("The albums have been rearranged!")
  192. return redirect(url_for(".albums"))
  193. g.info["albums"] = albums
  194. return template("photos/arrange_albums.html")
  195. @mod.route("/arrange_photos/<album>", methods=["GET", "POST"])
  196. @login_required
  197. def arrange_photos(album):
  198. """Rearrange the photos in an album."""
  199. photos = Photo.list_photos(album)
  200. if photos is None:
  201. flash("That album doesn't exist.")
  202. return redirect(url_for(".albums"))
  203. if request.method == "POST":
  204. order = request.form.get("order", "").split(";")
  205. Photo.order_photos(album, order)
  206. flash("The albums have been rearranged!")
  207. return redirect(url_for(".album_index", name=album))
  208. g.info["album"] = album
  209. g.info["photos"] = photos
  210. return template("photos/arrange_photos.html")