1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011 Free Software Foundation, Inc
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.
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.
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/>.
17 import mediagoblin
.mg_globals
as mg_globals
19 from os
.path
import splitext
20 from cgi
import FieldStorage
22 from werkzeug
.utils
import secure_filename
24 from mediagoblin
.db
.util
import ObjectId
25 from mediagoblin
.util
import (
26 render_to_response
, redirect
, cleaned_markdown_conversion
, \
27 convert_to_tag_list_of_dicts
)
28 from mediagoblin
.util
import pass_to_ugettext
as _
29 from mediagoblin
.decorators
import require_active_login
30 from mediagoblin
.submit
import forms
as submit_forms
, security
31 from mediagoblin
.process_media
import process_media
, mark_entry_failed
32 from mediagoblin
.messages
import add_message
, SUCCESS
36 def submit_start(request
):
38 First view for submitting a file.
40 submit_form
= submit_forms
.SubmitStartForm(request
.POST
)
42 if request
.method
== 'POST' and submit_form
.validate():
43 if not (request
.POST
.has_key('file')
44 and isinstance(request
.POST
['file'], FieldStorage
)
45 and request
.POST
['file'].file):
46 submit_form
.file.errors
.append(
47 _(u
'You must provide a file.'))
48 elif not security
.check_filetype(request
.POST
['file']):
49 submit_form
.file.errors
.append(
50 _(u
"The file doesn't seem to be an image!"))
52 filename
= request
.POST
['file'].filename
54 # create entry and save in database
55 entry
= request
.db
.MediaEntry()
56 entry
['_id'] = ObjectId()
58 unicode(request
.POST
['title'])
59 or unicode(splitext(filename
)[0]))
61 entry
['description'] = unicode(request
.POST
.get('description'))
62 entry
['description_html'] = cleaned_markdown_conversion(
65 entry
['media_type'] = u
'image' # heh
66 entry
['uploader'] = request
.user
['_id']
68 # Process the user's folksonomy "tags"
69 entry
['tags'] = convert_to_tag_list_of_dicts(
70 request
.POST
.get('tags'))
72 # Generate a slug from the title
75 # Now store generate the queueing related filename
76 queue_filepath
= request
.app
.queue_store
.get_unique_filepath(
78 unicode(entry
['_id']),
79 secure_filename(filename
)])
82 queue_file
= request
.app
.queue_store
.get_file(
86 queue_file
.write(request
.POST
['file'].file.read())
88 # Add queued filename to the entry
89 entry
['queued_media_file'] = queue_filepath
91 # We generate this ourselves so we know what the taks id is for
93 # (If we got it off the task's auto-generation, there'd be a risk of
94 # a race condition when we'd save after sending off the task)
95 task_id
= unicode(uuid
.uuid4())
96 entry
['queued_task_id'] = task_id
98 # Save now so we have this data before kicking off processing
99 entry
.save(validate
=True)
101 # Pass off to processing
103 # (... don't change entry after this point to avoid race
104 # conditions with changes to the document via processing code)
106 process_media
.apply_async(
107 [unicode(entry
['_id'])], {},
109 except BaseException
as exc
:
110 # The purpose of this section is because when running in "lazy"
111 # or always-eager-with-exceptions-propagated celery mode that
112 # the failure handling won't happen on Celery end. Since we
113 # expect a lot of users to run things in this way we have to
114 # capture stuff here.
116 # ... not completely the diaper pattern because the exception is
118 mark_entry_failed(entry
[u
'_id'], exc
)
119 # re-raise the exception
122 add_message(request
, SUCCESS
, _('Woohoo! Submitted!'))
124 return redirect(request
, "mediagoblin.user_pages.user_home",
125 user
= request
.user
['username'])
127 return render_to_response(
129 'mediagoblin/submit/start.html',
130 {'submit_form': submit_form
,
131 'app_config': mg_globals
.app_config
})