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