aboutsummaryrefslogtreecommitdiffstats
path: root/mediagoblin/submit
diff options
context:
space:
mode:
Diffstat (limited to 'mediagoblin/submit')
-rw-r--r--mediagoblin/submit/forms.py11
-rw-r--r--mediagoblin/submit/lib.py83
-rwxr-xr-xmediagoblin/submit/task.py38
-rw-r--r--mediagoblin/submit/views.py78
4 files changed, 161 insertions, 49 deletions
diff --git a/mediagoblin/submit/forms.py b/mediagoblin/submit/forms.py
index 6c0e8e9c..69d211e6 100644
--- a/mediagoblin/submit/forms.py
+++ b/mediagoblin/submit/forms.py
@@ -16,7 +16,7 @@
import wtforms
-
+from wtforms.ext.sqlalchemy.fields import QuerySelectField
from mediagoblin import mg_globals
from mediagoblin.tools.text import tag_length_validator
from mediagoblin.tools.translate import lazy_pass_to_ugettext as _
@@ -33,7 +33,7 @@ def get_submit_start_form(form, **kwargs):
file = wtforms.FileField(
_('File'),
description=desc)
- title = wtforms.TextField(
+ title = wtforms.StringField(
_('Title'),
[wtforms.validators.Length(min=0, max=500)])
description = wtforms.TextAreaField(
@@ -41,7 +41,7 @@ def get_submit_start_form(form, **kwargs):
description=_("""You can use
<a href="http://daringfireball.net/projects/markdown/basics">
Markdown</a> for formatting."""))
- tags = wtforms.TextField(
+ tags = wtforms.StringField(
_('Tags'),
[tag_length_validator],
description=_(
@@ -50,6 +50,9 @@ def get_submit_start_form(form, **kwargs):
_('License'),
[wtforms.validators.Optional(),],
choices=licenses_as_choices())
+ collection = QuerySelectField(
+ _('Collection'),
+ allow_blank=True, blank_text=_('-- Select --'), get_label='title',)
max_file_size = wtforms.HiddenField('')
upload_limit = wtforms.HiddenField('')
uploaded = wtforms.HiddenField('')
@@ -57,7 +60,7 @@ def get_submit_start_form(form, **kwargs):
return SubmitStartForm(form, **kwargs)
class AddCollectionForm(wtforms.Form):
- title = wtforms.TextField(
+ title = wtforms.StringField(
_('Title'),
[wtforms.validators.Length(min=0, max=500), wtforms.validators.InputRequired()])
description = wtforms.TextAreaField(
diff --git a/mediagoblin/submit/lib.py b/mediagoblin/submit/lib.py
index d54591d6..08a603e9 100644
--- a/mediagoblin/submit/lib.py
+++ b/mediagoblin/submit/lib.py
@@ -18,11 +18,15 @@ import logging
import uuid
from os.path import splitext
+import six
+
from werkzeug.utils import secure_filename
from werkzeug.datastructures import FileStorage
from mediagoblin import mg_globals
+from mediagoblin.tools.response import json_response
from mediagoblin.tools.text import convert_to_tag_list_of_dicts
+from mediagoblin.tools.federation import create_activity, create_generator
from mediagoblin.db.models import Collection, MediaEntry, ProcessingMetaData
from mediagoblin.processing import mark_entry_failed
from mediagoblin.processing.task import ProcessMedia
@@ -49,7 +53,7 @@ def new_upload_entry(user):
Create a new MediaEntry for uploading
"""
entry = MediaEntry()
- entry.uploader = user.id
+ entry.actor = user.id
entry.license = user.license_preference
return entry
@@ -58,7 +62,7 @@ def get_upload_file_limits(user):
"""
Get the upload_limit and max_file_size for this user
"""
- if user.upload_limit >= 0:
+ if user.upload_limit is not None and user.upload_limit >= 0: # TODO: debug this
upload_limit = user.upload_limit
else:
upload_limit = mg_globals.app_config.get('upload_limit', None)
@@ -100,10 +104,7 @@ class UserPastUploadLimit(UploadLimitError):
def submit_media(mg_app, user, submitted_file, filename,
title=None, description=None, collection_slug=None,
license=None, metadata=None, tags_string=u"",
- upload_limit=None, max_file_size=None,
- callback_url=None,
- # If provided we'll do the feed_url update, otherwise ignore
- urlgen=None,):
+ callback_url=None, urlgen=None,):
"""
Args:
- mg_app: The MediaGoblinApp instantiated for this process
@@ -119,17 +120,17 @@ def submit_media(mg_app, user, submitted_file, filename,
- license: license for this media entry
- tags_string: comma separated string of tags to be associated
with this entry
- - upload_limit: size in megabytes that's the per-user upload limit
- - max_file_size: maximum size each file can be that's uploaded
- callback_url: possible post-hook to call after submission
- - urlgen: if provided, used to do the feed_url update
+ - urlgen: if provided, used to do the feed_url update and assign a public
+ ID used in the API (very important).
"""
+ upload_limit, max_file_size = get_upload_file_limits(user)
if upload_limit and user.uploaded >= upload_limit:
raise UserPastUploadLimit()
# If the filename contains non ascii generate a unique name
if not all(ord(c) < 128 for c in filename):
- filename = unicode(uuid.uuid4()) + splitext(filename)[-1]
+ filename = six.text_type(uuid.uuid4()) + splitext(filename)[-1]
# Sniff the submitted media to determine which
# media plugin should handle processing
@@ -138,7 +139,7 @@ def submit_media(mg_app, user, submitted_file, filename,
# create entry and save in database
entry = new_upload_entry(user)
entry.media_type = media_type
- entry.title = (title or unicode(splitext(filename)[0]))
+ entry.title = (title or six.text_type(splitext(filename)[0]))
entry.description = description or u""
@@ -155,7 +156,7 @@ def submit_media(mg_app, user, submitted_file, filename,
queue_file = prepare_queue_task(mg_app, entry, filename)
with queue_file:
- queue_file.write(submitted_file.read())
+ queue_file.write(submitted_file)
# Get file size and round to 2 decimal places
file_size = mg_app.queue_store.get_file_size(
@@ -187,15 +188,27 @@ def submit_media(mg_app, user, submitted_file, filename,
metadata.save()
if urlgen:
+ # Generate the public_id, this is very importent, especially relating
+ # to deletion, it allows the shell to be accessable post-delete!
+ entry.get_public_id(urlgen)
+
+ # Generate the feed URL
feed_url = urlgen(
'mediagoblin.user_pages.atom_feed',
qualified=True, user=user.username)
else:
feed_url = None
+ add_comment_subscription(user, entry)
+
+ # Create activity
+ create_activity("post", entry, entry.actor)
+ entry.save()
+
# add to collection
if collection_slug:
- collection = Collection.query.filter_by(slug=collection_slug, creator=user.id).first()
+ collection = Collection.query.filter_by(slug=collection_slug,
+ actor=user.id).first()
if collection:
add_media_to_collection(collection, entry)
@@ -205,8 +218,6 @@ def submit_media(mg_app, user, submitted_file, filename,
# conditions with changes to the document via processing code)
run_process_media(entry, feed_url)
- add_comment_subscription(user, entry)
-
return entry
@@ -220,7 +231,7 @@ def prepare_queue_task(app, entry, filename):
# (If we got it off the task's auto-generation, there'd be
# a risk of a race condition when we'd save after sending
# off the task)
- task_id = unicode(uuid.uuid4())
+ task_id = six.text_type(uuid.uuid4())
entry.queued_task_id = task_id
# Now store generate the queueing related filename
@@ -267,3 +278,43 @@ def run_process_media(entry, feed_url=None,
mark_entry_failed(entry.id, exc)
# re-raise the exception
raise
+
+
+def api_upload_request(request, file_data, entry):
+ """ This handles a image upload request """
+ # Use the same kind of method from mediagoblin/submit/views:submit_start
+ entry.title = file_data.filename
+
+ # This will be set later but currently we just don't have enough information
+ entry.slug = None
+
+ # This is a MUST.
+ entry.get_public_id(request.urlgen)
+
+ queue_file = prepare_queue_task(request.app, entry, file_data.filename)
+ with queue_file:
+ queue_file.write(request.data)
+
+ entry.save()
+ return json_response(entry.serialize(request))
+
+def api_add_to_feed(request, entry):
+ """ Add media to Feed """
+ feed_url = request.urlgen(
+ 'mediagoblin.user_pages.atom_feed',
+ qualified=True, user=request.user.username
+ )
+
+ add_comment_subscription(request.user, entry)
+
+ # Create activity
+ activity = create_activity(
+ verb="post",
+ obj=entry,
+ actor=entry.actor,
+ generator=create_generator(request)
+ )
+ entry.save()
+ run_process_media(entry, feed_url)
+
+ return activity
diff --git a/mediagoblin/submit/task.py b/mediagoblin/submit/task.py
new file mode 100755
index 00000000..4ebde502
--- /dev/null
+++ b/mediagoblin/submit/task.py
@@ -0,0 +1,38 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import celery
+import datetime
+import pytz
+
+from mediagoblin.db.models import MediaEntry
+
+@celery.task()
+def collect_garbage():
+ """
+ Garbage collection to clean up media
+
+ This will look for all critera on models to clean
+ up. This is primerally written to clean up media that's
+ entered a erroneous state.
+ """
+ cuttoff = datetime.datetime.now(pytz.UTC) - datetime.timedelta(days=1)
+
+ garbage = MediaEntry.query.filter(MediaEntry.created < cuttoff)
+ garbage = garbage.filter(MediaEntry.state == "unprocessed")
+
+ for entry in garbage.all():
+ entry.delete()
diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py
index 42c378a8..7bbfb645 100644
--- a/mediagoblin/submit/views.py
+++ b/mediagoblin/submit/views.py
@@ -14,6 +14,8 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import six
+
from mediagoblin import messages
import mediagoblin.mg_globals as mg_globals
@@ -21,17 +23,17 @@ import logging
_log = logging.getLogger(__name__)
-
+from mediagoblin.db.models import Collection
+from mediagoblin.tools.federation import create_activity
from mediagoblin.tools.translate import pass_to_ugettext as _
from mediagoblin.tools.response import render_to_response, redirect
from mediagoblin.decorators import require_active_login, user_has_privilege
from mediagoblin.submit import forms as submit_forms
-from mediagoblin.messages import add_message, SUCCESS
-from mediagoblin.media_types import \
- InvalidFileType, FileTypeNotSupported
+from mediagoblin.media_types import FileTypeNotSupported
from mediagoblin.submit.lib import \
check_file_field, submit_media, get_upload_file_limits, \
FileUploadLimit, UserUploadLimit, UserPastUploadLimit
+from mediagoblin.user_pages.lib import add_media_to_collection
@require_active_login
@@ -48,6 +50,17 @@ def submit_start(request):
max_file_size=max_file_size,
upload_limit=upload_limit,
uploaded=request.user.uploaded)
+ users_collections = Collection.query.filter_by(
+ actor=request.user.id,
+ type=Collection.USER_DEFINED_TYPE
+ ).order_by(Collection.title)
+
+ # Only show the Collections dropdown if the user has some
+ # collections set up
+ if users_collections.count() > 0:
+ submit_form.collection.query = users_collections
+ else:
+ del submit_form.collection
if request.method == 'POST' and submit_form.validate():
if not check_file_field(request, 'file'):
@@ -55,18 +68,27 @@ def submit_start(request):
_(u'You must provide a file.'))
else:
try:
- submit_media(
+ media = submit_media(
mg_app=request.app, user=request.user,
submitted_file=request.files['file'],
filename=request.files['file'].filename,
- title=unicode(submit_form.title.data),
- description=unicode(submit_form.description.data),
- license=unicode(submit_form.license.data) or None,
+ title=six.text_type(submit_form.title.data),
+ description=six.text_type(submit_form.description.data),
+ license=six.text_type(submit_form.license.data) or None,
tags_string=submit_form.tags.data,
- upload_limit=upload_limit, max_file_size=max_file_size,
urlgen=request.urlgen)
- add_message(request, SUCCESS, _('Woohoo! Submitted!'))
+ if submit_form.collection and submit_form.collection.data:
+ add_media_to_collection(
+ submit_form.collection.data, media)
+ create_activity(
+ "add", media, request.user,
+ target=submit_form.collection.data)
+
+ messages.add_message(
+ request,
+ messages.SUCCESS,
+ _('Woohoo! Submitted!'))
return redirect(request, "mediagoblin.user_pages.user_home",
user=request.user.username)
@@ -87,18 +109,10 @@ def submit_start(request):
_('Sorry, you have reached your upload limit.'))
return redirect(request, "mediagoblin.user_pages.user_home",
user=request.user.username)
-
+ except FileTypeNotSupported as e:
+ submit_form.file.errors.append(e)
except Exception as e:
- '''
- This section is intended to catch exceptions raised in
- mediagoblin.media_types
- '''
- if isinstance(e, InvalidFileType) or \
- isinstance(e, FileTypeNotSupported):
- submit_form.file.errors.append(
- e)
- else:
- raise
+ raise
return render_to_response(
request,
@@ -117,24 +131,30 @@ def add_collection(request, media=None):
if request.method == 'POST' and submit_form.validate():
collection = request.db.Collection()
- collection.title = unicode(submit_form.title.data)
- collection.description = unicode(submit_form.description.data)
- collection.creator = request.user.id
+ collection.title = six.text_type(submit_form.title.data)
+ collection.description = six.text_type(submit_form.description.data)
+ collection.actor = request.user.id
+ collection.type = request.db.Collection.USER_DEFINED_TYPE
collection.generate_slug()
# Make sure this user isn't duplicating an existing collection
existing_collection = request.db.Collection.query.filter_by(
- creator=request.user.id,
+ actor=request.user.id,
+ type=request.db.Collection.USER_DEFINED_TYPE,
title=collection.title).first()
if existing_collection:
- add_message(request, messages.ERROR,
- _('You already have a collection called "%s"!') \
- % collection.title)
+ messages.add_message(
+ request,
+ messages.ERROR,
+ _('You already have a collection called "%s"!') %
+ collection.title)
else:
collection.save()
- add_message(request, SUCCESS,
+ messages.add_message(
+ request,
+ messages.SUCCESS,
_('Collection "%s" added!') % collection.title)
return redirect(request, "mediagoblin.user_pages.user_home",