bf928f059b07ff1a305fc38dfc597ac60fd726f2
[zzz-floof.git] / floof / controllers / art.py
1 import logging
2
3 from pylons import config, request, response, session, tmpl_context as c, h
4 from pylons.controllers.util import abort, redirect
5 from pylons import url
6 from floof.lib.base import BaseController, render
7
8 log = logging.getLogger(__name__)
9
10 from floof.lib import file_storage as storage
11 from floof.model import Art, Rating, ArtUser
12 from floof.model.art import ArtUserType
13 from floof.model.comments import Discussion
14 from floof.model.users import User, UserRelationship
15
16 import elixir
17 #import magic
18 import os.path
19 import PIL
20 import PIL.Image
21 from sqlalchemy.exceptions import IntegrityError
22 from sqlalchemy.orm.exc import NoResultFound
23 from wtforms.validators import ValidationError
24 from wtforms import *
25
26
27 class ArtUploadForm(Form):
28 by = TextField('Artists')
29 file = FileField('Upload')
30 url = TextField('Link')
31
32 # TODO: make this general purpose
33 def validate_file(self, field):
34 if field.data == u'':
35 raise ValidationError('File is required')
36
37
38 class ArtController(BaseController):
39 def __before__(self, id=None):
40 super(ArtController, self).__before__()
41 # Awesome refactoring!
42 if id:
43 c.art = h.get_object_or_404(Art, id=id)
44
45 def new(self):
46 """ New Art! """
47 c.form = ArtUploadForm()
48 return render("/art/new.mako")
49
50 # TODO: login required
51 def create(self):
52 c.form = ArtUploadForm(request.params)
53 if not c.form.validate():
54 ## TODO: JavaScript should be added to the upload form so that it is
55 ## impossible to submit the form when it contains any invalid users,
56 ## so this never happens. Only autocompled usernames should be allowed.
57 return render("/art/new.mako")
58
59 # Save the file
60 upload = request.params['file']
61 hash = storage.save_file('art/original', upload.file)
62
63 # Create a thumbnail and a medium view
64 img = PIL.Image.open(
65 config['app_conf']['static_root']
66 + storage.get_path('art/original', hash)[1:]
67 )
68 for subdir, config_size in [('medium', config['medium_size']),
69 ('thumbnail', config['thumbnail_size'])]:
70 path = config['app_conf']['static_root'] + storage.get_path("art/{0}".format(subdir), hash)
71
72 dir, _ = os.path.split(path)
73 if not os.path.exists(dir):
74 os.makedirs(dir)
75
76 size = int(config_size)
77 shrunken_img = img.copy()
78 shrunken_img.thumbnail((size, size), PIL.Image.ANTIALIAS)
79 shrunken_img.save(path, img.format)
80
81 #magicker = magic.Magic(mime=True)
82 buffer = upload.file.read(64)
83 upload.file.seek(0)
84 mimetype = 'image/unknown' #magickery.from_buffer(buffer)
85
86 # XXX Ensure we can actually handle the mimetype
87
88 print mimetype
89 c.art = Art(
90 uploader=c.user,
91 original_filename=upload.filename,
92 hash=hash,
93 mimetype=mimetype,
94 )
95 c.art.discussion = Discussion(count=0)
96
97 # For the moment, cheerfully assume that people are uploading their own
98 # art
99 ArtUser(art=c.art, user=c.user, type=ArtUserType.BY)
100
101
102 try:
103 elixir.session.commit()
104 redirect(url('show_art', id=c.art.id))
105 except IntegrityError:
106 # XXX Check this as early as possible, and clean up the filesystem!
107 # Right now this replaces the original file!
108 hash = c.art.hash
109 elixir.session.rollback()
110 duplicate_art = Art.get_by(hash=hash)
111 h.flash("We already have that one.")
112 redirect(url('show_art', id=duplicate_art.id))
113
114
115
116 def show(self, id):
117 # c.art = h.get_object_or_404(Art, id=id)
118 if c.user:
119 c.your_score = c.art.user_score(c.user)
120 return render("/art/show.mako")
121
122
123 # TODO: login required
124 def rate(self, id):
125 # c.art = h.get_object_or_404(Art, id=id)
126 score = request.params.get("score")
127 if score and score.isnumeric():
128 score = int(score)
129 else:
130 score = Rating.reverse_options.get(score)
131
132 c.art.rate(score, c.user)
133 elixir.session.commit()
134
135 redirect(url('show_art', id=c.art.id))
136
137
138 def watchstream(self, name):
139 """Watchstream for a certain user."""
140 try:
141 c.watching_user = User.get_by(name=name)
142 except NoResultFound:
143 abort(404)
144
145 # This user has watches which are users which have art
146 # XXX use artist, not uploader
147 c.artwork = Art.query.join(Art.uploader,
148 User.target_of_relationships) \
149 .filter(UserRelationship.user_id == c.watching_user.id)
150
151 return render('/index.mako')