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