Switching the syntax of this exception-raise
[mediagoblin.git] / mediagoblin / submit / views.py
CommitLineData
e323a068 1# GNU MediaGoblin -- federated, autonomous media hosting
cf29e8a8 2# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
e323a068
CAW
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU Affero General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Affero General Public License for more details.
13#
14# You should have received a copy of the GNU Affero General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
2c437493 17import mediagoblin.mg_globals as mg_globals
4a477e24 18import uuid
bb49e56f 19from os.path import splitext
03afc828
CAW
20from cgi import FieldStorage
21
8e5f9746 22from celery import registry
deea3f66
JW
23import urllib
24import urllib2
77b91efc 25import logging
8e5f9746 26
c03d13cd 27_log = logging.getLogger(__name__)
8e5f9746 28
f6f524bf 29from werkzeug.utils import secure_filename
e323a068 30
f64e5250 31from mediagoblin.db.util import ObjectId
1e72e075 32from mediagoblin.tools.text import convert_to_tag_list_of_dicts
ae3bc7fa 33from mediagoblin.tools.translate import pass_to_ugettext as _
152a3bfa 34from mediagoblin.tools.response import render_to_response, redirect
e323a068 35from mediagoblin.decorators import require_active_login
32d8cf45 36from mediagoblin.submit import forms as submit_forms
eace050a
E
37from mediagoblin.processing import mark_entry_failed
38from mediagoblin.processing.task import ProcessMedia
4dc74441 39from mediagoblin.messages import add_message, SUCCESS
ec4261a4 40from mediagoblin.media_types import sniff_media, \
4601c30c 41 InvalidFileType, FileTypeNotSupported
e323a068
CAW
42
43
44@require_active_login
45def submit_start(request):
46 """
47 First view for submitting a file.
48 """
20439236 49 submit_form = submit_forms.SubmitStartForm(request.POST)
e323a068 50
f6f524bf 51 if request.method == 'POST' and submit_form.validate():
285ffedd 52 if not ('file' in request.POST
03afc828
CAW
53 and isinstance(request.POST['file'], FieldStorage)
54 and request.POST['file'].file):
55 submit_form.file.errors.append(
4b1adc13 56 _(u'You must provide a file.'))
03afc828 57 else:
6788b412 58 try:
0bce749b 59 filename = request.POST['file'].filename
ec4261a4
JW
60
61 # Sniff the submitted media to determine which
62 # media plugin should handle processing
63 media_type, media_manager = sniff_media(
64 request.POST['file'])
bb49e56f 65
0bce749b
JW
66 # create entry and save in database
67 entry = request.db.MediaEntry()
58f96a13 68 entry.id = ObjectId()
f4ee8399 69 entry.media_type = unicode(media_type)
ec82fbd8 70 entry.title = (
0bce749b
JW
71 unicode(request.POST['title'])
72 or unicode(splitext(filename)[0]))
93bdab9d 73
1d939966 74 entry.description = unicode(request.POST.get('description'))
4bf8e888 75
2788e6a1 76 entry.license = unicode(request.POST.get('license', "")) or None
99a270e9 77
1ceb4fc8 78 entry.uploader = request.user._id
03afc828 79
0bce749b 80 # Process the user's folksonomy "tags"
de917303 81 entry.tags = convert_to_tag_list_of_dicts(
0bce749b 82 request.POST.get('tags'))
03afc828 83
0bce749b
JW
84 # Generate a slug from the title
85 entry.generate_slug()
4a477e24 86
572d4f01
E
87 # We generate this ourselves so we know what the taks id is for
88 # retrieval later.
89
90 # (If we got it off the task's auto-generation, there'd be
91 # a risk of a race condition when we'd save after sending
92 # off the task)
93 task_id = unicode(uuid.uuid4())
4dc74441 94
0bce749b
JW
95 # Now store generate the queueing related filename
96 queue_filepath = request.app.queue_store.get_unique_filepath(
97 ['media_entries',
572d4f01 98 task_id,
0bce749b 99 secure_filename(filename)])
03afc828 100
0bce749b
JW
101 # queue appropriately
102 queue_file = request.app.queue_store.get_file(
103 queue_filepath, 'wb')
03afc828 104
0bce749b
JW
105 with queue_file:
106 queue_file.write(request.POST['file'].file.read())
03afc828 107
0bce749b 108 # Add queued filename to the entry
8545cfc9 109 entry.queued_media_file = queue_filepath
03afc828 110
572d4f01 111 entry.queued_task_id = task_id
07934b44 112
0bce749b
JW
113 # Save now so we have this data before kicking off processing
114 entry.save(validate=True)
fa7f9c61 115
0bce749b 116 # Pass off to processing
6788b412 117 #
0bce749b
JW
118 # (... don't change entry after this point to avoid race
119 # conditions with changes to the document via processing code)
120 process_media = registry.tasks[ProcessMedia.name]
121 try:
122 process_media.apply_async(
123 [unicode(entry._id)], {},
124 task_id=task_id)
125 except BaseException as exc:
126 # The purpose of this section is because when running in "lazy"
127 # or always-eager-with-exceptions-propagated celery mode that
128 # the failure handling won't happen on Celery end. Since we
129 # expect a lot of users to run things in this way we have to
130 # capture stuff here.
131 #
132 # ... not completely the diaper pattern because the
133 # exception is re-raised :)
134 mark_entry_failed(entry._id, exc)
135 # re-raise the exception
136 raise
137
bb025ebd 138 if mg_globals.app_config["push_urls"]:
deea3f66 139 feed_url = request.urlgen(
5b1a7bae 140 'mediagoblin.user_pages.atom_feed',
deea3f66
JW
141 qualified=True,
142 user=request.user.username)
5b1a7bae 143 hubparameters = {
77b91efc
MA
144 'hub.mode': 'publish',
145 'hub.url': feed_url}
5b1a7bae 146 hubdata = urllib.urlencode(hubparameters)
bb025ebd
MA
147 hubheaders = {
148 "Content-type": "application/x-www-form-urlencoded",
149 "Connection": "close"}
150 for huburl in mg_globals.app_config["push_urls"]:
77b91efc
MA
151 hubrequest = urllib2.Request(huburl, hubdata, hubheaders)
152 try:
153 hubresponse = urllib2.urlopen(hubrequest)
154 except urllib2.HTTPError as exc:
155 # This is not a big issue, the item will be fetched
156 # by the PuSH server next time we hit it
c03d13cd 157 _log.warning(
77b91efc
MA
158 "push url %r gave error %r", huburl, exc.code)
159 except urllib2.URLError as exc:
c03d13cd 160 _log.warning(
77b91efc 161 "push url %r is unreachable %r", huburl, exc.reason)
5b1a7bae 162
0bce749b
JW
163 add_message(request, SUCCESS, _('Woohoo! Submitted!'))
164
165 return redirect(request, "mediagoblin.user_pages.user_home",
5a4e3ff1 166 user=request.user.username)
a246ccca
JW
167 except Exception as e:
168 '''
deea3f66 169 This section is intended to catch exceptions raised in
a246ccca
JW
170 mediagobling.media_types
171 '''
4601c30c
JW
172 if isinstance(e, InvalidFileType) or \
173 isinstance(e, FileTypeNotSupported):
174 submit_form.file.errors.append(
175 e)
176 else:
177 raise
f6f524bf 178
9038c9f9
CAW
179 return render_to_response(
180 request,
c9c24934 181 'mediagoblin/submit/start.html',
2c437493
JW
182 {'submit_form': submit_form,
183 'app_config': mg_globals.app_config})