diff options
Diffstat (limited to 'mediagoblin/db/mixin.py')
-rw-r--r-- | mediagoblin/db/mixin.py | 201 |
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"] |