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