aboutsummaryrefslogtreecommitdiffstats
path: root/mediagoblin/db/mixin.py
diff options
context:
space:
mode:
Diffstat (limited to 'mediagoblin/db/mixin.py')
-rw-r--r--mediagoblin/db/mixin.py201
1 files changed, 181 insertions, 20 deletions
diff --git a/mediagoblin/db/mixin.py b/mediagoblin/db/mixin.py
index 1f2e7ec3..4602c709 100644
--- a/mediagoblin/db/mixin.py
+++ b/mediagoblin/db/mixin.py
@@ -31,17 +31,20 @@ import uuid
import re
from datetime import datetime
+from pytz import UTC
from werkzeug.utils import cached_property
-from mediagoblin import mg_globals
from mediagoblin.media_types import FileTypeNotSupported
from mediagoblin.tools import common, licenses
from mediagoblin.tools.pluginapi import hook_handle
from mediagoblin.tools.text import cleaned_markdown_conversion
from mediagoblin.tools.url import slugify
+from mediagoblin.tools.translate import pass_to_ugettext as _
class UserMixin(object):
+ object_type = "person"
+
@property
def bio_html(self):
return cleaned_markdown_conversion(self.bio)
@@ -84,42 +87,45 @@ class GenerateSlugMixin(object):
generated bits until it's unique. That'll be a little bit of junk,
but at least it has the basis of a nice slug.
"""
+
#Is already a slug assigned? Check if it is valid
if self.slug:
- self.slug = slugify(self.slug)
+ slug = slugify(self.slug)
# otherwise, try to use the title.
elif self.title:
# assign slug based on title
- self.slug = slugify(self.title)
+ slug = slugify(self.title)
- # We don't want any empty string slugs
- if self.slug == u"":
- self.slug = None
+ else:
+ # We don't have any information to set a slug
+ return
- # Do we have anything at this point?
- # If not, we're not going to get a slug
- # so just return... we're not going to force one.
- if not self.slug:
- return # giving up!
+ # We don't want any empty string slugs
+ if slug == u"":
+ return
# Otherwise, let's see if this is unique.
- if self.check_slug_used(self.slug):
+ if self.check_slug_used(slug):
# It looks like it's being used... lame.
# Can we just append the object's id to the end?
if self.id:
- slug_with_id = u"%s-%s" % (self.slug, self.id)
+ slug_with_id = u"%s-%s" % (slug, self.id)
if not self.check_slug_used(slug_with_id):
self.slug = slug_with_id
return # success!
# okay, still no success;
# let's whack junk on there till it's unique.
- self.slug += '-' + uuid.uuid4().hex[:4]
+ slug += '-' + uuid.uuid4().hex[:4]
# keep going if necessary!
- while self.check_slug_used(self.slug):
- self.slug += uuid.uuid4().hex[:4]
+ while self.check_slug_used(slug):
+ slug += uuid.uuid4().hex[:4]
+
+ # self.check_slug_used(slug) must be False now so we have a slug that
+ # we can use now.
+ self.slug = slug
class MediaEntryMixin(GenerateSlugMixin):
@@ -131,6 +137,11 @@ class MediaEntryMixin(GenerateSlugMixin):
return check_media_slug_used(self.uploader, slug, self.id)
@property
+ def object_type(self):
+ """ Converts media_type to pump-like type - don't use internally """
+ return self.media_type.split(".")[-1]
+
+ @property
def description_html(self):
"""
Rendered version of the description, run through
@@ -192,14 +203,14 @@ class MediaEntryMixin(GenerateSlugMixin):
# TODO: implement generic fallback in case MEDIA_MANAGER does
# not specify one?
if u'thumb' in self.media_files:
- thumb_url = mg_globals.app.public_store.file_url(
+ thumb_url = self._app.public_store.file_url(
self.media_files[u'thumb'])
else:
# No thumbnail in media available. Get the media's
# MEDIA_MANAGER for the fallback icon and return static URL
# Raises FileTypeNotSupported in case no such manager is enabled
manager = self.media_manager
- thumb_url = mg_globals.app.staticdirector(manager[u'default_thumb'])
+ thumb_url = self._app.staticdirector(manager[u'default_thumb'])
return thumb_url
@property
@@ -208,8 +219,8 @@ class MediaEntryMixin(GenerateSlugMixin):
will return self.thumb_url if original url doesn't exist"""
if u"original" not in self.media_files:
return self.thumb_url
-
- return mg_globals.app.public_store.file_url(
+
+ return self._app.public_store.file_url(
self.media_files[u"original"]
)
@@ -297,6 +308,8 @@ class MediaEntryMixin(GenerateSlugMixin):
class MediaCommentMixin(object):
+ object_type = "comment"
+
@property
def content_html(self):
"""
@@ -321,6 +334,8 @@ class MediaCommentMixin(object):
class CollectionMixin(GenerateSlugMixin):
+ object_type = "collection"
+
def check_slug_used(self, slug):
# import this here due to a cyclic import issue
# (db.models -> db.mixin -> db.util -> db.models)
@@ -363,3 +378,149 @@ class CollectionItemMixin(object):
Run through Markdown and the HTML cleaner.
"""
return cleaned_markdown_conversion(self.note)
+
+class ActivityMixin(object):
+ object_type = "activity"
+
+ VALID_VERBS = ["add", "author", "create", "delete", "dislike", "favorite",
+ "follow", "like", "post", "share", "unfavorite", "unfollow",
+ "unlike", "unshare", "update", "tag"]
+
+ def get_url(self, request):
+ return request.urlgen(
+ "mediagoblin.user_pages.activity_view",
+ username=self.get_actor.username,
+ id=self.id,
+ qualified=True
+ )
+
+ def generate_content(self):
+ """ Produces a HTML content for object """
+ # some of these have simple and targetted. If self.target it set
+ # it will pick the targetted. If they DON'T have a targetted version
+ # the information in targetted won't be added to the content.
+ verb_to_content = {
+ "add": {
+ "simple" : _("{username} added {object}"),
+ "targetted": _("{username} added {object} to {target}"),
+ },
+ "author": {"simple": _("{username} authored {object}")},
+ "create": {"simple": _("{username} created {object}")},
+ "delete": {"simple": _("{username} deleted {object}")},
+ "dislike": {"simple": _("{username} disliked {object}")},
+ "favorite": {"simple": _("{username} favorited {object}")},
+ "follow": {"simple": _("{username} followed {object}")},
+ "like": {"simple": _("{username} liked {object}")},
+ "post": {
+ "simple": _("{username} posted {object}"),
+ "targetted": _("{username} posted {object} to {target}"),
+ },
+ "share": {"simple": _("{username} shared {object}")},
+ "unfavorite": {"simple": _("{username} unfavorited {object}")},
+ "unfollow": {"simple": _("{username} stopped following {object}")},
+ "unlike": {"simple": _("{username} unliked {object}")},
+ "unshare": {"simple": _("{username} unshared {object}")},
+ "update": {"simple": _("{username} updated {object}")},
+ "tag": {"simple": _("{username} tagged {object}")},
+ }
+
+ object_map = {
+ "image": _("an image"),
+ "comment": _("a comment"),
+ "collection": _("a collection"),
+ "video": _("a video"),
+ "audio": _("audio"),
+ "person": _("a person"),
+ }
+
+ obj = self.get_object
+ target = self.get_target
+ actor = self.get_actor
+ content = verb_to_content.get(self.verb, None)
+
+ if content is None or obj is None:
+ return
+
+ # Decide what to fill the object with
+ if hasattr(obj, "title") and obj.title.strip(" "):
+ object_value = obj.title
+ elif obj.object_type in object_map:
+ object_value = object_map[obj.object_type]
+ else:
+ object_value = _("an object")
+
+ # Do we want to add a target (indirect object) to content?
+ if target is not None and "targetted" in content:
+ if hasattr(target, "title") and target.title.strip(" "):
+ target_value = target.title
+ elif target.object_type in object_map:
+ target_value = object_map[target.object_type]
+ else:
+ target_value = _("an object")
+
+ self.content = content["targetted"].format(
+ username=actor.username,
+ object=object_value,
+ target=target_value
+ )
+ else:
+ self.content = content["simple"].format(
+ username=actor.username,
+ object=object_value
+ )
+
+ return self.content
+
+ def serialize(self, request):
+ href = request.urlgen(
+ "mediagoblin.api.object",
+ object_type=self.object_type,
+ id=self.id,
+ qualified=True
+ )
+ published = UTC.localize(self.published)
+ updated = UTC.localize(self.updated)
+ obj = {
+ "id": href,
+ "actor": self.get_actor.serialize(request),
+ "verb": self.verb,
+ "published": published.isoformat(),
+ "updated": updated.isoformat(),
+ "content": self.content,
+ "url": self.get_url(request),
+ "object": self.get_object.serialize(request),
+ "objectType": self.object_type,
+ "links": {
+ "self": {
+ "href": href,
+ },
+ },
+ }
+
+ if self.generator:
+ obj["generator"] = self.get_generator.serialize(request)
+
+ if self.title:
+ obj["title"] = self.title
+
+ target = self.get_target
+ if target is not None:
+ obj["target"] = target.serialize(request)
+
+ return obj
+
+ def unseralize(self, data):
+ """
+ Takes data given and set it on this activity.
+
+ Several pieces of data are not written on because of security
+ reasons. For example changing the author or id of an activity.
+ """
+ if "verb" in data:
+ self.verb = data["verb"]
+
+ if "title" in data:
+ self.title = data["title"]
+
+ if "content" in data:
+ self.content = data["content"]