コード例 #1
0
ファイル: storage.py プロジェクト: greentv/mediacore
    def edit(self, id, engine_type=None, **kwargs):
        """Display the :class:`~mediacore.lib.storage.StorageEngine` for editing or adding.

        :param id: Storage ID
        :type id: ``int`` or ``"new"``
        :rtype: dict
        :returns:

        """
        if id != "new":
            engine = fetch_row(StorageEngine, id)
        else:
            types = dict((cls.engine_type, cls) for cls in StorageEngine)
            engine_cls = types.get(engine_type, None)
            if not engine_cls:
                redirect(controller="/admin/storage", action="index")
            engine = engine_cls()

            if not engine.settings_form:
                # XXX: If this newly created storage engine has no settings,
                #      just save it. This isn't RESTful (as edit is a GET
                #      action), but it simplifies the creation process.
                DBSession.add(engine)
                redirect(controller="/admin/storage", action="index")

        return {
            "engine": engine,
            "form": engine.settings_form,
            "form_action": url_for(action="save", engine_type=engine_type),
            "form_values": kwargs,
        }
コード例 #2
0
    def feed(self, slug, **kwargs):
        """Serve the feed as RSS 2.0.

        If :attr:`~mediacore.model.podcasts.Podcast.feedburner_url` is
        specified for this podcast, we redirect there if the useragent
        does not contain 'feedburner', as described here:
        http://www.google.com/support/feedburner/bin/answer.py?hl=en&answer=78464

        :param feedburner_bypass: If true, the redirect to feedburner is disabled.
        :rtype: Dict
        :returns:
            podcast
                A :class:`~mediacore.model.podcasts.Podcast` instance.
            episodes
                A list of :class:`~mediacore.model.media.Media` instances
                that belong to the ``podcast``.

        Renders: :data:`podcasts/feed.xml` XML

        """
        podcast = fetch_row(Podcast, slug=slug)

        if (
            podcast.feedburner_url
            and not "feedburner" in request.environ.get("HTTP_USER_AGENT", "").lower()
            and not kwargs.get("feedburner_bypass", False)
        ):
            redirect(podcast.feedburner_url.encode("utf-8"))

        response.content_type = content_type_for_response(["application/rss+xml", "application/xml", "text/xml"])

        episodes = podcast.media.published().order_by(Media.publish_on.desc())[:25]

        return dict(podcast=podcast, episodes=episodes)
コード例 #3
0
    def save(self,
             id,
             display_name,
             group_name,
             permissions,
             delete=None,
             **kwargs):
        """Save changes or create a new :class:`~mediacore.model.auth.Group` instance.

        :param id: Group ID. If ``"new"`` a new group is created.
        :type id: ``int`` or ``"new"``
        :returns: Redirect back to :meth:`index` after successful save.

        """
        group = fetch_row(Group, id)

        if delete:
            DBSession.delete(group)
            redirect(action='index', id=None)

        group.display_name = display_name
        group.group_name = group_name
        if permissions:
            query = DBSession.query(Permission).filter(
                Permission.permission_id.in_(permissions))
            group.permissions = list(query.all())
        else:
            group.permissions = []
        DBSession.add(group)

        redirect(action='index', id=None)
コード例 #4
0
ファイル: users.py プロジェクト: 86me/mediacore
    def save(self, id, email_address, display_name, login_details,
             delete=None, **kwargs):
        """Save changes or create a new :class:`~mediacore.model.auth.User` instance.

        :param id: User ID. If ``"new"`` a new user is created.
        :type id: ``int`` or ``"new"``
        :returns: Redirect back to :meth:`index` after successful save.

        """
        user = fetch_row(User, id)

        if delete:
            DBSession.delete(user)
            redirect(action='index', id=None)

        user.display_name = display_name
        user.email_address = email_address
        user.user_name = login_details['user_name']

        password = login_details['password']
        if password is not None and password != '':
            user.password = password

        if login_details['group']:
            group = fetch_row(Group, login_details['group'])
            user.groups = [group]
        else:
            user.groups = []

        DBSession.add(user)
        DBSession.flush()
        redirect(action='index', id=None)
コード例 #5
0
ファイル: base.py プロジェクト: Jpoudrier/mediacore-community
 def _save(self, form, redirect_action=None, values=None):
     """Save the values from the passed in form instance."""
     values = self._flatten_settings_from_form(tmpl_context.settings,
                                               form, values)
     self._update_settings(values)
     if redirect_action:
         helpers.redirect(action=redirect_action)
コード例 #6
0
ファイル: login.py プロジェクト: swdreams/mediacore-community
    def login(self, came_from=None, **kwargs):
        if request.environ.get('repoze.who.identity'):
            redirect(came_from or '/')

        # the friendlyform plugin requires that these values are set in the
        # query string
        form_url = url_for('/login/submit',
                           came_from=(came_from or '').encode('utf-8'),
                           __logins=str(self._is_failed_login()))

        login_errors = None
        if self._is_failed_login():
            login_errors = Invalid('dummy',
                                   None, {},
                                   error_dict={
                                       '_form':
                                       Invalid(
                                           _('Invalid username or password.'),
                                           None, {}),
                                       'login':
                                       Invalid('dummy', None, {}),
                                       'password':
                                       Invalid('dummy', None, {}),
                                   })
        return dict(
            login_form=login_form,
            form_action=form_url,
            form_values=kwargs,
            login_errors=login_errors,
        )
コード例 #7
0
    def update_status(self,
                      id,
                      status=None,
                      publish_on=None,
                      publish_until=None,
                      **values):
        """Update the publish status for the given media.

        :param id: Media ID
        :type id: ``int``
        :param update_status: The text of the submit button which indicates
            that the :attr:`~mediacore.model.media.Media.status` should change.
        :type update_status: ``unicode`` or ``None``
        :param publish_on: A date to set to
            :attr:`~mediacore.model.media.Media.publish_on`
        :type publish_on: :class:`datetime.datetime` or ``None``
        :param publish_until: A date to set to
            :attr:`~mediacore.model.media.Media.publish_until`
        :type publish_until: :class:`datetime.datetime` or ``None``
        :rtype: JSON dict
        :returns:
            success
                bool
            message
                Error message, if unsuccessful
            status_form
                Rendered XHTML for the status form, updated to reflect the
                changes made.

        """
        media = fetch_row(Media, id)
        new_slug = None

        # Make the requested change assuming it will be allowed
        if status == 'unreviewed':
            media.reviewed = True
        elif status == 'draft':
            self._publish_media(media, publish_on)
        elif publish_on:
            media.publish_on = publish_on
            media.update_popularity()
        elif publish_until:
            media.publish_until = publish_until

        # Verify the change is valid by re-determining the status
        media.update_status()
        DBSession.flush()

        if request.is_xhr:
            # Return the rendered widget for injection
            status_form_xhtml = unicode(
                update_status_form.display(
                    action=url_for(action='update_status'), media=media))
            return dict(
                success=True,
                status_form=status_form_xhtml,
                slug=new_slug,
            )
        else:
            redirect(action='edit')
コード例 #8
0
ファイル: media.py プロジェクト: 86me/mediacore
    def serve(self, id, slug, container, **kwargs):
        """Serve a :class:`~mediacore.model.media.MediaFile` binary.

        :param id: File ID
        :type id: ``int``
        :param slug: The media :attr:`~mediacore.model.media.Media.slug`
        :type slug: The file :attr:`~mediacore.model.media.MediaFile.container`
        :raises webob.exc.HTTPNotFound: If no file exists for the given params.
        :raises webob.exc.HTTPNotAcceptable: If an Accept header field
            is present, and if the mimetype of the requested file doesn't
            match, then a 406 (not acceptable) response is returned.

        """
        media = fetch_row(Media, slug=slug)

        for file in media.files:
            if file.id == id and file.container == container:
                # Catch external redirects in case they aren't linked to directly
                if file.url:
                    redirect(file.url.encode('utf-8'))

                # Ensure that the clients request allows for files of this container
                mimetype = mimeparse.best_match([file.mimetype],
                    request.environ.get('HTTP_ACCEPT', '*/*'))
                if mimetype == '':
                    raise webob.exc.HTTPNotAcceptable() # 406

                response.headers['Content-Type'] = mimetype
                response.headers['Content-Disposition'] = \
                    'attachment;filename="%s"' % file.display_name.encode('utf-8')
                return open(file.file_path, 'rb').read()
        else:
            raise webob.exc.HTTPNotFound()
コード例 #9
0
ファイル: podcasts.py プロジェクト: MechanisM/mediacore
    def index(self, page=1, **kwargs):
        """List podcasts and podcast media.

        Our custom paginate decorator allows us to have fewer podcast episodes
        display on the first page than on the rest with the ``items_first_page``
        param. See :class:`mediacore.lib.custompaginate.CustomPage`.

        :param page: Page number, defaults to 1.
        :type page: int
        :rtype: dict
        :returns:
            podcasts
                The :class:`~mediacore.model.podcasts.Podcast` instance

        """
        podcasts = Podcast.query\
            .options(orm.undefer('media_count_published'))\
            .all()

        if len(podcasts) == 1:
            redirect(action='view', slug=podcasts[0].slug)

        podcast_episodes = {}
        for podcast in podcasts:
            podcast_episodes[podcast] = podcast.media.published()\
                .order_by(Media.publish_on.desc())[:4]

        return dict(
            podcasts = podcasts,
            podcast_episodes = podcast_episodes,
        )
コード例 #10
0
    def index(self, page=1, **kwargs):
        """List podcasts and podcast media.

        Our custom paginate decorator allows us to have fewer podcast episodes
        display on the first page than on the rest with the ``items_first_page``
        param. See :class:`mediacore.lib.custompaginate.CustomPage`.

        :param page: Page number, defaults to 1.
        :type page: int
        :rtype: dict
        :returns:
            podcasts
                The :class:`~mediacore.model.podcasts.Podcast` instance

        """
        podcasts = Podcast.query\
            .options(orm.undefer('media_count_published'))\
            .all()

        if len(podcasts) == 1:
            redirect(action='view', slug=podcasts[0].slug)

        podcast_episodes = {}
        for podcast in podcasts:
            podcast_episodes[podcast] = podcast.media.published()\
                .order_by(Media.publish_on.desc())[:4]

        return dict(
            podcasts=podcasts,
            podcast_episodes=podcast_episodes,
        )
コード例 #11
0
    def index(self, **kwargs):
        """List podcasts and podcast media.

        :rtype: dict
        :returns:
            podcasts
                The :class:`~mediacore.model.podcasts.Podcast` instance

        """
        podcasts = Podcast.query\
            .options(orm.undefer('media_count_published'))\
            .all()

        if len(podcasts) == 1:
            redirect(action='view', slug=podcasts[0].slug)

        podcast_episodes = {}
        for podcast in podcasts:
            episode_query = podcast.media.published().order_by(Media.publish_on.desc())
            podcast_episodes[podcast] = viewable_media(episode_query)[:4]

        return dict(
            podcasts = podcasts,
            podcast_episodes = podcast_episodes,
        )
コード例 #12
0
ファイル: storage.py プロジェクト: donspaulding/mediacore
    def edit(self, id, engine_type=None, **kwargs):
        """Display the :class:`~mediacore.lib.storage.StorageEngine` for editing or adding.

        :param id: Storage ID
        :type id: ``int`` or ``"new"``
        :rtype: dict
        :returns:

        """
        if id != 'new':
            engine = fetch_row(StorageEngine, id)
        else:
            types = dict((cls.engine_type, cls) for cls in StorageEngine)
            engine_cls = types.get(engine_type, None)
            if not engine_cls:
                redirect(controller='/admin/storage', action='index')
            engine = engine_cls()

            if not engine.settings_form:
                # XXX: If this newly created storage engine has no settings,
                #      just save it. This isn't RESTful (as edit is a GET
                #      action), but it simplifies the creation process.
                DBSession.add(engine)
                redirect(controller='/admin/storage', action='index')

        return {
            'engine': engine,
            'form': engine.settings_form,
            'form_action': url_for(action='save', engine_type=engine_type),
            'form_values': kwargs,
        }
コード例 #13
0
ファイル: media.py プロジェクト: wafe/mediadrop
    def rate(self, slug, up=None, down=None, **kwargs):
        """Say 'I like this' for the given media.

        :param slug: The media :attr:`~mediacore.model.media.Media.slug`
        :rtype: unicode
        :returns:
            The new number of likes

        """
        media = fetch_row(Media, slug=slug)
        request.perm.assert_permission(u'view', media.resource)

        if up:
            if not request.settings['appearance_show_like']:
                abort(status_code=403)
            media.increment_likes()
        elif down:
            if not request.settings['appearance_show_dislike']:
                abort(status_code=403)
            media.increment_dislikes()

        if request.is_xhr:
            return u''
        else:
            redirect(action='view')
コード例 #14
0
ファイル: media.py プロジェクト: imclab/mediacore-community
    def rate(self, slug, up=None, down=None, **kwargs):
        """Say 'I like this' for the given media.

        :param slug: The media :attr:`~mediacore.model.media.Media.slug`
        :rtype: unicode
        :returns:
            The new number of likes

        """
        media = fetch_row(Media, slug=slug)
        request.perm.assert_permission(u'view', media.resource)

        if up:
            if not request.settings['appearance_show_like']:
                abort(status_code=403)
            media.increment_likes()
        elif down:
            if not request.settings['appearance_show_dislike']:
                abort(status_code=403)
            media.increment_dislikes()

        if request.is_xhr:
            return u''
        else:
            redirect(action='view')
コード例 #15
0
    def index(self, **kwargs):
        """List podcasts and podcast media.

        :rtype: dict
        :returns:
            podcasts
                The :class:`~mediacore.model.podcasts.Podcast` instance

        """
        podcasts = Podcast.query\
            .options(orm.undefer('media_count_published'))\
            .all()

        if len(podcasts) == 1:
            redirect(action='view', slug=podcasts[0].slug)

        podcast_episodes = {}
        for podcast in podcasts:
            episode_query = podcast.media.published().order_by(
                Media.publish_on.desc())
            podcast_episodes[podcast] = viewable_media(episode_query)[:4]

        return dict(
            podcasts=podcasts,
            podcast_episodes=podcast_episodes,
        )
コード例 #16
0
ファイル: base.py プロジェクト: imclab/mediacore-community
 def _save(self, form, redirect_action=None, values=None):
     """Save the values from the passed in form instance."""
     values = self._flatten_settings_from_form(tmpl_context.settings, form,
                                               values)
     self._update_settings(values)
     if redirect_action:
         helpers.redirect(action=redirect_action)
コード例 #17
0
ファイル: categories.py プロジェクト: kiberpipa/mediacore
    def save(self, id, delete=None, **kwargs):
        """Save changes or create a category.

        See :class:`~mediacore.forms.admin.settings.categories.CategoryForm` for POST vars.

        :param id: Category ID
        :param delete: If true the category is to be deleted rather than saved.
        :type delete: bool
        :rtype: JSON dict
        :returns:
            success
                bool

        """
        if tmpl_context.form_errors:
            if request.is_xhr:
                return dict(success=False, errors=tmpl_context.form_errors)
            else:
                # TODO: Add error reporting for users with JS disabled?
                return redirect(action="edit")

        cat = fetch_row(Category, id)

        if delete:
            DBSession.delete(cat)
            data = dict(success=True, id=cat.id, parent_options=unicode(category_form.c["parent_id"].display()))
        else:
            cat.name = kwargs["name"]
            cat.slug = get_available_slug(Category, kwargs["slug"], cat)

            if kwargs["parent_id"]:
                parent = fetch_row(Category, kwargs["parent_id"])
                if parent is not cat and cat not in parent.ancestors():
                    cat.parent = parent
            else:
                cat.parent = None

            DBSession.add(cat)
            DBSession.flush()

            data = dict(
                success=True,
                id=cat.id,
                name=cat.name,
                slug=cat.slug,
                parent_id=cat.parent_id,
                parent_options=unicode(category_form.c["parent_id"].display()),
                depth=cat.depth(),
                row=unicode(
                    category_row_form.display(
                        action=url_for(id=cat.id), category=cat, depth=cat.depth(), first_child=True
                    )
                ),
            )

        if request.is_xhr:
            return data
        else:
            redirect(action="index", id=None)
コード例 #18
0
ファイル: media.py プロジェクト: kiberpipa/mediacore
    def view(self, slug, podcast_slug=None, **kwargs):
        """Display the media player, info and comments.

        :param slug: The :attr:`~mediacore.models.media.Media.slug` to lookup
        :param podcast_slug: The :attr:`~mediacore.models.podcasts.Podcast.slug`
            for podcast this media belongs to. Although not necessary for
            looking up the media, it tells us that the podcast slug was
            specified in the URL and therefore we reached this action by the
            preferred route.
        :rtype dict:
        :returns:
            media
                The :class:`~mediacore.model.media.Media` instance for display.
            comment_form
                The :class:`~mediacore.forms.comments.PostCommentForm` instance.
            comment_form_action
                ``str`` comment form action
            comment_form_values
                ``dict`` form values
            next_episode
                The next episode in the podcast series, if this media belongs to
                a podcast, another :class:`~mediacore.model.media.Media`
                instance.

        """
        media = fetch_row(Media, slug=slug)

        if media.podcast_id is not None:
            # Always view podcast media from a URL that shows the context of the podcast
            if url_for() != url_for(podcast_slug=media.podcast.slug):
                redirect(podcast_slug=media.podcast.slug)

        if media.fulltext:
            search_terms = '%s %s' % (media.title, media.fulltext.tags)
            related = Media.query.published()\
                .options(orm.undefer('comment_count_published'))\
                .filter(Media.id != media.id)\
                .search(search_terms, bool=False)
        else:
            related = []

        media.increment_views()

        # Which style of 'likes' links has the admin selected?
        # TODO: Add settings to control these options.
        mediacore_likes = True
        facebook_likes = False

        return dict(
            media = media,
            related_media = related[:6],
            comments = media.comments.published().all(),
            comment_form = post_comment_form,
            comment_form_action = url_for(action='comment', anchor=post_comment_form.id),
            comment_form_values = kwargs,
            mediacore_likes = mediacore_likes,
            facebook_likes = facebook_likes,
        )
コード例 #19
0
ファイル: media.py プロジェクト: wafe/mediadrop
    def view(self, slug, podcast_slug=None, **kwargs):
        """Display the media player, info and comments.

        :param slug: The :attr:`~mediacore.models.media.Media.slug` to lookup
        :param podcast_slug: The :attr:`~mediacore.models.podcasts.Podcast.slug`
            for podcast this media belongs to. Although not necessary for
            looking up the media, it tells us that the podcast slug was
            specified in the URL and therefore we reached this action by the
            preferred route.
        :rtype dict:
        :returns:
            media
                The :class:`~mediacore.model.media.Media` instance for display.
            related_media
                A list of :class:`~mediacore.model.media.Media` instances that
                rank as topically related to the given media item.
            comments
                A list of :class:`~mediacore.model.comments.Comment` instances
                associated with the selected media item.
            comment_form_action
                ``str`` comment form action
            comment_form_values
                ``dict`` form values
            next_episode
                The next episode in the podcast series, if this media belongs to
                a podcast, another :class:`~mediacore.model.media.Media`
                instance.

        """
        media = fetch_row(Media, slug=slug)
        request.perm.assert_permission(u'view', media.resource)

        if media.podcast_id is not None:
            # Always view podcast media from a URL that shows the context of the podcast
            if url_for() != url_for(podcast_slug=media.podcast.slug):
                redirect(podcast_slug=media.podcast.slug)

        try:
            media.increment_views()
            DBSession.commit()
        except OperationalError:
            DBSession.rollback()

        if request.settings['comments_engine'] == 'facebook':
            response.facebook = Facebook(request.settings['facebook_appid'])

        related_media = viewable_media(Media.query.related(media))[:6]
        # TODO: finish implementation of different 'likes' buttons
        #       e.g. the default one, plus a setting to use facebook.
        return dict(
            media = media,
            related_media = related_media,
            comments = media.comments.published().all(),
            comment_form_action = url_for(action='comment'),
            comment_form_values = kwargs,
        )
コード例 #20
0
ファイル: media.py プロジェクト: imclab/mediacore-community
    def view(self, slug, podcast_slug=None, **kwargs):
        """Display the media player, info and comments.

        :param slug: The :attr:`~mediacore.models.media.Media.slug` to lookup
        :param podcast_slug: The :attr:`~mediacore.models.podcasts.Podcast.slug`
            for podcast this media belongs to. Although not necessary for
            looking up the media, it tells us that the podcast slug was
            specified in the URL and therefore we reached this action by the
            preferred route.
        :rtype dict:
        :returns:
            media
                The :class:`~mediacore.model.media.Media` instance for display.
            related_media
                A list of :class:`~mediacore.model.media.Media` instances that
                rank as topically related to the given media item.
            comments
                A list of :class:`~mediacore.model.comments.Comment` instances
                associated with the selected media item.
            comment_form_action
                ``str`` comment form action
            comment_form_values
                ``dict`` form values
            next_episode
                The next episode in the podcast series, if this media belongs to
                a podcast, another :class:`~mediacore.model.media.Media`
                instance.

        """
        media = fetch_row(Media, slug=slug)
        request.perm.assert_permission(u'view', media.resource)

        if media.podcast_id is not None:
            # Always view podcast media from a URL that shows the context of the podcast
            if url_for() != url_for(podcast_slug=media.podcast.slug):
                redirect(podcast_slug=media.podcast.slug)

        try:
            media.increment_views()
            DBSession.commit()
        except OperationalError:
            DBSession.rollback()

        if request.settings['comments_engine'] == 'facebook':
            response.facebook = Facebook(request.settings['facebook_appid'])

        related_media = viewable_media(Media.query.related(media))[:6]
        # TODO: finish implementation of different 'likes' buttons
        #       e.g. the default one, plus a setting to use facebook.
        return dict(
            media=media,
            related_media=related_media,
            comments=media.comments.published().all(),
            comment_form_action=url_for(action='comment'),
            comment_form_values=kwargs,
        )
コード例 #21
0
 def fetch_engine(self, id, engine_type=None):
     if id != 'new':
         engine = fetch_row(StorageEngine, id)
     else:
         types = dict((cls.engine_type, cls) for cls in StorageEngine)
         engine_cls = types.get(engine_type, None)
         if not engine_cls:
             redirect(controller='/admin/storage', action='index')
         engine = engine_cls()
     return engine
コード例 #22
0
ファイル: storage.py プロジェクト: greentv/mediacore
    def enable(self, id, **kwargs):
        """Enable a StorageEngine.

        :param id: Storage ID.
        :type id: ``int``
        :returns: Redirect back to :meth:`index` after success.
        """
        engine = fetch_row(StorageEngine, id)
        engine.enabled = True
        redirect(action="index", id=None)
コード例 #23
0
    def disable(self, id, **kwargs):
        """Disable a StorageEngine.

        :param id: engine ID.
        :type id: ``int``
        :returns: Redirect back to :meth:`index` after success.
        """
        engine = fetch_row(StorageEngine, id)
        engine.enabled = False
        redirect(action='index', id=None)
コード例 #24
0
 def fetch_engine(self, id, engine_type=None):
     if id != 'new':
         engine = fetch_row(StorageEngine, id)
     else:
         types = dict((cls.engine_type, cls) for cls in StorageEngine)
         engine_cls = types.get(engine_type, None)
         if not engine_cls:
             redirect(controller='/admin/storage', action='index')
         engine = engine_cls()
     return engine
コード例 #25
0
    def disable(self, id, **kwargs):
        """Disable a StorageEngine.

        :param id: engine ID.
        :type id: ``int``
        :returns: Redirect back to :meth:`index` after success.
        """
        engine = fetch_row(StorageEngine, id)
        engine.enabled = False
        redirect(action='index', id=None)
コード例 #26
0
ファイル: media.py プロジェクト: RadioErewan/mediacore
    def update_status(self, id, update_button=None, publish_on=None, **values):
        """Update the publish status for the given media.

        :param id: Media ID
        :type id: ``int``
        :param update_status: The text of the submit button which indicates
            that the :attr:`~mediacore.model.media.Media.status` should change.
        :type update_status: ``unicode`` or ``None``
        :param publish_on: A date to set to
            :attr:`~mediacore.model.media.Media.publish_on`
        :type publish_on: :class:`datetime.datetime` or ``None``
        :rtype: JSON dict
        :returns:
            success
                bool
            message
                Error message, if unsuccessful
            status_form
                Rendered XHTML for the status form, updated to reflect the
                changes made.

        """
        media = fetch_row(Media, id)
        new_slug = None

        # Make the requested change assuming it will be allowed
        if update_button == _('Review Complete'):
            media.reviewed = True
        elif update_button == _('Publish Now'):
            media.publishable = True
            media.publish_on = publish_on or datetime.now()
            media.update_popularity()
            # Remove the stub prefix if the user wants the default media title
            if media.slug.startswith('_stub_'):
                new_slug = get_available_slug(Media, media.slug[len('_stub_'):])
                media.slug = new_slug
        elif publish_on:
            media.publish_on = publish_on
            media.update_popularity()

        # Verify the change is valid by re-determining the status
        media.update_status()
        DBSession.flush()

        if request.is_xhr:
            # Return the rendered widget for injection
            status_form_xhtml = unicode(update_status_form.display(
                action=url_for(action='update_status'), media=media))
            return dict(
                success = True,
                status_form = status_form_xhtml,
                slug = new_slug,
            )
        else:
            redirect(action='edit')
コード例 #27
0
    def disable(self, id, **kwargs):
        """Disable a PlayerPref.

        :param id: Player ID.
        :type id: ``int``
        :returns: Redirect back to :meth:`index` after success.
        """
        player = fetch_row(PlayerPrefs, id)
        player.enabled = False
        update_enabled_players()
        redirect(action='index', id=None)
コード例 #28
0
ファイル: media.py プロジェクト: kidrane/mediacore-community
    def update_status(self, id, status=None, publish_on=None, publish_until=None, **values):
        """Update the publish status for the given media.

        :param id: Media ID
        :type id: ``int``
        :param update_status: The text of the submit button which indicates
            that the :attr:`~mediacore.model.media.Media.status` should change.
        :type update_status: ``unicode`` or ``None``
        :param publish_on: A date to set to
            :attr:`~mediacore.model.media.Media.publish_on`
        :type publish_on: :class:`datetime.datetime` or ``None``
        :param publish_until: A date to set to
            :attr:`~mediacore.model.media.Media.publish_until`
        :type publish_until: :class:`datetime.datetime` or ``None``
        :rtype: JSON dict
        :returns:
            success
                bool
            message
                Error message, if unsuccessful
            status_form
                Rendered XHTML for the status form, updated to reflect the
                changes made.

        """
        media = fetch_row(Media, id)
        new_slug = None

        # Make the requested change assuming it will be allowed
        if status == 'unreviewed':
            media.reviewed = True
        elif status == 'draft':
            self._publish_media(media, publish_on)
        elif publish_on:
            media.publish_on = publish_on
            media.update_popularity()
        elif publish_until:
            media.publish_until = publish_until

        # Verify the change is valid by re-determining the status
        media.update_status()
        DBSession.flush()

        if request.is_xhr:
            # Return the rendered widget for injection
            status_form_xhtml = unicode(update_status_form.display(
                action=url_for(action='update_status'), media=media))
            return dict(
                success = True,
                status_form = status_form_xhtml,
                slug = new_slug,
            )
        else:
            redirect(action='edit')
コード例 #29
0
    def popularity_save(self, **kwargs):
        """Save :class:`~mediacore.forms.admin.settings.PopularityForm`.

        Updates the popularity for every media item based on the submitted
        values.
        """
        self._save(popularity_form, values=kwargs)
        for m in Media.query:
            m.update_popularity()
            DBSession.add(m)
        redirect(action='popularity')
コード例 #30
0
ファイル: settings.py プロジェクト: donspaulding/mediacore
    def popularity_save(self, **kwargs):
        """Save :class:`~mediacore.forms.admin.settings.PopularityForm`.

        Updates the popularity for every media item based on the submitted
        values.
        """
        self._save(popularity_form, values=kwargs)
        for m in Media.query:
            m.update_popularity()
            DBSession.add(m)
        redirect(action='popularity')
コード例 #31
0
    def disable(self, id, **kwargs):
        """Disable a PlayerPref.

        :param id: Player ID.
        :type id: ``int``
        :returns: Redirect back to :meth:`index` after success.
        """
        player = fetch_row(PlayerPrefs, id)
        player.enabled = False
        update_enabled_players()
        redirect(action='index', id=None)
コード例 #32
0
ファイル: podcasts.py プロジェクト: donspaulding/mediacore
    def save(self,
             id,
             slug,
             title,
             subtitle,
             author_name,
             author_email,
             description,
             details,
             feed,
             delete=None,
             **kwargs):
        """Save changes or create a new :class:`~mediacore.model.podcasts.Podcast` instance.

        Form handler the :meth:`edit` action and the
        :class:`~mediacore.forms.admin.podcasts.PodcastForm`.

        Redirects back to :meth:`edit` after successful editing
        and :meth:`index` after successful deletion.

        """
        podcast = fetch_row(Podcast, id)

        if delete:
            file_paths = thumb_paths(podcast).values()
            DBSession.delete(podcast)
            DBSession.commit()
            helpers.delete_files(file_paths, Podcast._thumb_dir)
            redirect(action='index', id=None)

        if not slug:
            slug = title
        if slug != podcast.slug:
            podcast.slug = get_available_slug(Podcast, slug, podcast)
        podcast.title = title
        podcast.subtitle = subtitle
        podcast.author = Author(author_name, author_email)
        podcast.description = description
        podcast.copyright = details['copyright']
        podcast.category = details['category']
        podcast.itunes_url = feed['itunes_url']
        podcast.feedburner_url = feed['feedburner_url']
        podcast.explicit = {
            'yes': True,
            'clean': False
        }.get(details['explicit'], None)

        if id == 'new':
            DBSession.add(podcast)
            DBSession.flush()
            create_default_thumbs_for(podcast)

        redirect(action='edit', id=podcast.id)
コード例 #33
0
ファイル: settings.py プロジェクト: donspaulding/mediacore
    def comments_save(self, **kwargs):
        """Save :class:`~mediacore.forms.admin.settings.CommentsForm`."""
        old_vulgarity_filter = c.settings['vulgarity_filtered_words'].value

        self._save(comments_form, values=kwargs)

        # Run the filter now if it has changed
        if old_vulgarity_filter != c.settings['vulgarity_filtered_words'].value:
            for comment in DBSession.query(Comment):
                comment.body = filter_vulgarity(comment.body)

        redirect(action='comments')
コード例 #34
0
 def post_login(self, came_from=None, **kwargs):
     if not request.identity:
         # The FriendlyForm plugin will always issue a redirect to 
         # /login/continue (post login url) even for failed logins.
         # If 'came_from' is a protected page (i.e. /admin) we could just 
         # redirect there and the login form will be displayed again with
         # our login error message.
         # However if the user tried to login from the front page, this 
         # mechanism doesn't work so go to the login method directly here.
         self._increase_number_of_failed_logins()
         return self.login(came_from=came_from)
     redirect(came_from or url_for('/admin'))
コード例 #35
0
ファイル: settings.py プロジェクト: RadioErewan/mediacore
 def save_display(self, **kwargs):
     """Save :class:`~mediacore.forms.admin.settings.DisplayForm`."""
     player_type = c.settings['player_type'].value
     self._save(display_form, **kwargs)
     # If the player_type changes, we must update the Media.encoded flag,
     # since some things may play now and/or not play anymore with the
     # new setting.
     if player_type != c.settings['player_type'].value:
         for m in Media.query.options(orm.eagerload('files')):
             m.update_status()
             DBSession.add(m)
     redirect(action='display')
コード例 #36
0
    def save(self, id, slug, title, author_name, author_email,
             description, notes, podcast, tags, categories,
             delete=None, **kwargs):
        """Save changes or create a new :class:`~mediacore.model.media.Media` instance.

        Form handler the :meth:`edit` action and the
        :class:`~mediacore.forms.admin.media.MediaForm`.

        Redirects back to :meth:`edit` after successful editing
        and :meth:`index` after successful deletion.

        """
        media = fetch_row(Media, id)

        if delete:
            self._delete_media(media)
            DBSession.commit()
            redirect(action='index', id=None)

        if not slug:
            slug = title
        elif slug.startswith('_stub_'):
            slug = slug[len('_stub_'):]
        if slug != media.slug:
            media.slug = get_available_slug(Media, slug, media)
        media.title = title
        media.author = Author(author_name, author_email)
        media.description = description
        media.notes = notes
        media.podcast_id = podcast
        media.set_tags(tags)
        media.set_categories(categories)

        media.update_status()
        DBSession.add(media)
        DBSession.flush()

        if id == 'new' and not has_thumbs(media):
            create_default_thumbs_for(media)

        if request.is_xhr:
            status_form_xhtml = unicode(update_status_form.display(
                action=url_for(action='update_status', id=media.id),
                media=media))

            return dict(
                media_id = media.id,
                values = {'slug': slug},
                link = url_for(action='edit', id=media.id),
                status_form = status_form_xhtml,
            )
        else:
            redirect(action='edit', id=media.id)
コード例 #37
0
ファイル: media.py プロジェクト: donspaulding/mediacore
    def save(self, id, slug, title, author_name, author_email,
             description, notes, podcast, tags, categories,
             delete=None, **kwargs):
        """Save changes or create a new :class:`~mediacore.model.media.Media` instance.

        Form handler the :meth:`edit` action and the
        :class:`~mediacore.forms.admin.media.MediaForm`.

        Redirects back to :meth:`edit` after successful editing
        and :meth:`index` after successful deletion.

        """
        media = fetch_row(Media, id)

        if delete:
            self._delete_media(media)
            DBSession.commit()
            redirect(action='index', id=None)

        if not slug:
            slug = title
        elif slug.startswith('_stub_'):
            slug = slug[len('_stub_'):]
        if slug != media.slug:
            media.slug = get_available_slug(Media, slug, media)
        media.title = title
        media.author = Author(author_name, author_email)
        media.description = description
        media.notes = notes
        media.podcast_id = podcast
        media.set_tags(tags)
        media.set_categories(categories)

        media.update_status()
        DBSession.add(media)
        DBSession.flush()

        if id == 'new' and not has_thumbs(media):
            create_default_thumbs_for(media)

        if request.is_xhr:
            status_form_xhtml = unicode(update_status_form.display(
                action=url_for(action='update_status', id=media.id),
                media=media))

            return dict(
                media_id = media.id,
                values = {'slug': slug},
                link = url_for(action='edit', id=media.id),
                status_form = status_form_xhtml,
            )
        else:
            redirect(action='edit', id=media.id)
コード例 #38
0
    def comments_save(self, **kwargs):
        """Save :class:`~mediacore.forms.admin.settings.CommentsForm`."""
        old_vulgarity_filter = c.settings['vulgarity_filtered_words'].value

        self._save(comments_form, values=kwargs)

        # Run the filter now if it has changed
        if old_vulgarity_filter != c.settings['vulgarity_filtered_words'].value:
            for comment in DBSession.query(Comment):
                comment.body = filter_vulgarity(comment.body)

        redirect(action='comments')
コード例 #39
0
    def delete(self, id, **kwargs):
        """Delete a user.

        :param id: User ID.
        :type id: ``int``
        :returns: Redirect back to :meth:`index` after successful delete.
        """
        user = fetch_row(User, id)
        DBSession.delete(user)

        if request.is_xhr:
            return dict(success=True)
        redirect(action='index', id=None)
コード例 #40
0
    def delete(self, id, **kwargs):
        """Delete a StorageEngine.

        :param id: Storage ID.
        :type id: ``int``
        :returns: Redirect back to :meth:`index` after successful delete.
        """
        engine = fetch_row(StorageEngine, id)
        files = engine.files
        for f in files:
            engine.delete(f.unique_id)
        DBSession.delete(engine)
        redirect(action='index', id=None)
コード例 #41
0
    def submit(self, **kwargs):
        """
        """
        kwargs.setdefault("name")

        # Save the media_obj!
        media_obj = self.save_media_obj(
            kwargs["name"], kwargs["email"], kwargs["title"], kwargs["description"], None, kwargs["file"], kwargs["url"]
        )
        email.send_media_notification(media_obj)

        # Redirect to success page!
        redirect(action="success")
コード例 #42
0
    def delete(self, id, **kwargs):
        """Delete a StorageEngine.

        :param id: Storage ID.
        :type id: ``int``
        :returns: Redirect back to :meth:`index` after successful delete.
        """
        engine = fetch_row(StorageEngine, id)
        files = engine.files
        for f in files:
            engine.delete(f.unique_id)
        DBSession.delete(engine)
        redirect(action='index', id=None)
コード例 #43
0
    def delete(self, id, **kwargs):
        """Delete a group.

        :param id: Group ID.
        :type id: ``int``
        :returns: Redirect back to :meth:`index` after successful delete.
        """
        group = fetch_row(Group, id)
        DBSession.delete(group)

        if request.is_xhr:
            return dict(success=True)
        redirect(action='index', id=None)
コード例 #44
0
    def delete(self, id, **kwargs):
        """Delete a group.

        :param id: Group ID.
        :type id: ``int``
        :returns: Redirect back to :meth:`index` after successful delete.
        """
        group = fetch_row(Group, id)
        DBSession.delete(group)

        if request.is_xhr:
            return dict(success=True)
        redirect(action='index', id=None)
コード例 #45
0
ファイル: media.py プロジェクト: imclab/mediacore-community
    def random(self, **kwargs):
        """Redirect to a randomly selected media item."""
        # TODO: Implement something more efficient than ORDER BY RAND().
        #       This method does a full table scan every time.
        random_query = Media.query.published().order_by(sql.func.random())
        media = viewable_media(random_query).first()

        if media is None:
            redirect(action='explore')
        if media.podcast_id:
            podcast_slug = DBSession.query(Podcast.slug).get(media.podcast_id)
        else:
            podcast_slug = None
        redirect(action='view', slug=media.slug, podcast_slug=podcast_slug)
コード例 #46
0
ファイル: media.py プロジェクト: RadioErewan/mediacore
 def random(self, **kwargs):
     """Redirect to a randomly selected media item."""
     # TODO: Implement something more efficient than ORDER BY RAND().
     #       This method does a full table scan every time.
     media = Media.query.published()\
         .order_by(sql.func.random())\
         .first()
     if media is None:
         redirect(action='explore')
     if media.podcast_id:
         podcast_slug = DBSession.query(Podcast.slug).get(media.podcast_id)
     else:
         podcast_slug = None
     redirect(action='view', slug=media.slug, podcast_slug=podcast_slug)
コード例 #47
0
ファイル: media.py プロジェクト: seanbradley/mediacore_panda
    def panda_update(self, media_id=None, file_id=None, video_id=None, **kwargs):
        if file_id:
            media_file = fetch_row(MediaFile, file_id)
            media_files = [media_file]
        elif media_id:
            media = fetch_row(Media, media_id)
            media_files = media.files

        storage = DBSession.query(PandaStorage).first()

        for media_file in media_files:
            storage.panda_helper().video_status_update(media_file, video_id)

        redirect(controller='/admin/media', action='edit', id=media_id)
コード例 #48
0
ファイル: upload.py プロジェクト: donspaulding/mediacore
    def submit(self, **kwargs):
        """
        """
        kwargs.setdefault('name')

        # Save the media_obj!
        media_obj = self.save_media_obj(
            kwargs['name'], kwargs['email'],
            kwargs['title'], kwargs['description'],
            None, kwargs['file'], kwargs['url'],
        )
        email.send_media_notification(media_obj)

        # Redirect to success page!
        redirect(action='success')
コード例 #49
0
ファイル: upload.py プロジェクト: AshKash/mediacore-community
    def submit(self, **kwargs):
        """
        """
        kwargs.setdefault('name')

        # Save the media_obj!
        media_obj = self.save_media_obj(
            kwargs['name'], kwargs['email'],
            kwargs['title'], kwargs['description'],
            None, kwargs['file'], kwargs['url'],
        )
        email.send_media_notification(media_obj)

        # Redirect to success page!
        redirect(action='success')
コード例 #50
0
    def report(self, email='', description='', **kwargs):
        """Email a support request that's been submitted on :meth:`document`.

        Redirects back to the root URL ``/``.

        """
        url = ''
        get_vars = post_vars = {}
        for x in kwargs:
            if x.startswith('GET_'):
                get_vars[x] = kwargs[x]
            elif x.startswith('POST_'):
                post_vars[x] = kwargs[x]
        libemail.send_support_request(email, url, description, get_vars, post_vars)
        redirect('/')
コード例 #51
0
    def report(self, email='', description='', **kwargs):
        """Email a support request that's been submitted on :meth:`document`.

        Redirects back to the root URL ``/``.

        """
        url = ''
        get_vars = post_vars = {}
        for x in kwargs:
            if x.startswith('GET_'):
                get_vars[x] = kwargs[x]
            elif x.startswith('POST_'):
                post_vars[x] = kwargs[x]
        libemail.send_support_request(email, url, description, get_vars, post_vars)
        redirect('/')
コード例 #52
0
ファイル: media.py プロジェクト: donspaulding/mediacore
    def view(self, slug, podcast_slug=None, **kwargs):
        """Display the media player, info and comments.

        :param slug: The :attr:`~mediacore.models.media.Media.slug` to lookup
        :param podcast_slug: The :attr:`~mediacore.models.podcasts.Podcast.slug`
            for podcast this media belongs to. Although not necessary for
            looking up the media, it tells us that the podcast slug was
            specified in the URL and therefore we reached this action by the
            preferred route.
        :rtype dict:
        :returns:
            media
                The :class:`~mediacore.model.media.Media` instance for display.
            comment_form
                The :class:`~mediacore.forms.comments.PostCommentForm` instance.
            comment_form_action
                ``str`` comment form action
            comment_form_values
                ``dict`` form values
            next_episode
                The next episode in the podcast series, if this media belongs to
                a podcast, another :class:`~mediacore.model.media.Media`
                instance.

        """
        media = fetch_row(Media, slug=slug)

        if media.podcast_id is not None:
            # Always view podcast media from a URL that shows the context of the podcast
            if url_for() != url_for(podcast_slug=media.podcast.slug):
                redirect(podcast_slug=media.podcast.slug)

        media.increment_views()

        # Which style of 'likes' links has the admin selected?
        # TODO: Add settings to control these options.
        mediacore_likes = True
        facebook_likes = False

        return dict(
            media=media,
            related_media=Media.query.related(media)[:6],
            comments=media.comments.published().all(),
            comment_form_action=url_for(action='comment'),
            comment_form_values=kwargs,
            mediacore_likes=mediacore_likes,
            facebook_likes=facebook_likes,
        )
コード例 #53
0
class YouTubeImportController(BaseSettingsController):
    @expose('youtube_import/admin/import.html')
    def index(self, **kwargs):
        category_tree = Category.query.order_by(Category.name).populated_tree()
        return dict(
            form=import_form,
            form_values=kwargs,
            form_action=url_for(controller='youtube_import',
                                action='perform_import'),
            category_tree=category_tree,
        )

    @expose()
    @validate(import_form, error_handler=index)
    @autocommit
    def perform_import(self, youtube, **kwargs):
        auto_publish = youtube.get('auto_publish', False)
        user = request.perm.user
        tags = kwargs.get('youtube.tags')
        categories = kwargs.get('youtube.categories')

        channel_names = parse_channel_names(youtube.get('channel_names', ''))
        importer = YouTubeImporter(user, auto_publish, tags, categories)
        try:
            for channel_name in channel_names:
                importer.import_videos_from_channel(channel_name)
        except YouTubeQuotaExceeded, e:
            error_message = e.args[0]
            c.form_errors['_the_form'] = error_message
            return self.index(youtube=youtube, **kwargs)

        # Redirect to the Media view page, when the import is complete
        redirect(url_for(controller='admin/media', action='index'))
コード例 #54
0
    def save(self,
             id,
             email_address,
             display_name,
             login_details,
             delete=None,
             **kwargs):
        """Save changes or create a new :class:`~mediacore.model.auth.User` instance.

        :param id: User ID. If ``"new"`` a new user is created.
        :type id: ``int`` or ``"new"``
        :returns: Redirect back to :meth:`index` after successful save.

        """
        user = fetch_row(User, id)

        if delete:
            DBSession.delete(user)
            redirect(action='index', id=None)

        user.display_name = display_name
        user.email_address = email_address
        user.user_name = login_details['user_name']

        password = login_details['password']
        if password is not None and password != '':
            user.password = password

        if login_details['group']:
            group = fetch_row(Group, login_details['group'])
            user.groups = [group]
        else:
            user.groups = []

        DBSession.add(user)

        # Check if we're changing the logged in user's own password
        logged_in_user = request.environ['repoze.who.identity']['user']
        if user.user_id == logged_in_user.user_id \
        and password is not None and password != '':
            DBSession.commit()
            # repoze.who sees the Unauthorized response and clears the cookie,
            # forcing a fresh login with the new password
            raise webob.exc.HTTPUnauthorized().exception

        redirect(action='index', id=None)
コード例 #55
0
    def delete(self, id, **kwargs):
        """Delete a PlayerPref.

        After deleting the PlayerPref, cleans up the players table,
        ensuring that each Player class is represented--if the deleted
        PlayerPref is the last example of that Player class, creates a new
        disabled PlayerPref for that Player class with the default settings.

        :param id: Player ID.
        :type id: ``int``
        :returns: Redirect back to :meth:`index` after successful delete.
        """
        player = fetch_row(PlayerPrefs, id)
        DBSession.delete(player)
        DBSession.flush()
        cleanup_players_table()
        redirect(action='index', id=None)
コード例 #56
0
ファイル: comments.py プロジェクト: isaleem/cumin
    def save_status(self, id, status, ids=None, **kwargs):
        """Approve or delete a comment or comments.

        :param id: A :attr:`~mediacore.model.comments.Comment.id` if we are
            acting on a single comment, or ``"bulk"`` if we should refer to
            ``ids``.
        :type id: ``int`` or ``"bulk"``
        :param status: ``"approve"`` or ``"trash"`` depending on what action
            the user requests.
        :param ids: An optional string of IDs separated by commas.
        :type ids: ``unicode`` or ``None``
        :rtype: JSON dict
        :returns:
            success
                bool
            ids
                A list of :attr:`~mediacore.model.comments.Comment.id`
                that have changed.

        """
        if id != 'bulk':
            ids = [id]
        if not isinstance(ids, list):
            ids = [ids]

        if status == 'approve':
            publishable = True
        elif status == 'trash':
            publishable = False
        else:
            # XXX: This form should never be submitted without a valid status.
            raise AssertionError('Unexpected status: %r' % status)

        comments = Comment.query.filter(Comment.id.in_(ids)).all()

        for comment in comments:
            comment.reviewed = True
            comment.publishable = publishable
            DBSession.add(comment)

        DBSession.flush()

        if request.is_xhr:
            return dict(success=True, ids=ids)
        else:
            redirect(action='index')
コード例 #57
0
    def view(self, slug, podcast_slug=None, **kwargs):
        """Display the media player, info and comments.

        :param slug: The :attr:`~mediacore.models.media.Media.slug` to lookup
        :param podcast_slug: The :attr:`~mediacore.models.podcasts.Podcast.slug`
            for podcast this media belongs to. Although not necessary for
            looking up the media, it tells us that the podcast slug was
            specified in the URL and therefore we reached this action by the
            preferred route.
        :rtype dict:
        :returns:
            media
                The :class:`~mediacore.model.media.Media` instance for display.
            related_media
                A list of :class:`~mediacore.model.media.Media` instances that
                rank as topically related to the given media item.
            comments
                A list of :class:`~mediacore.model.comments.Comment` instances
                associated with the selected media item.
            comment_form_action
                ``str`` comment form action
            comment_form_values
                ``dict`` form values
            next_episode
                The next episode in the podcast series, if this media belongs to
                a podcast, another :class:`~mediacore.model.media.Media`
                instance.

        """
        media = fetch_row(Media, slug=slug)

        if media.podcast_id is not None:
            # Always view podcast media from a URL that shows the context of the podcast
            if url_for() != url_for(podcast_slug=media.podcast.slug):
                redirect(podcast_slug=media.podcast.slug)

        media.increment_views()

        # TODO: finish implementation of different 'likes' buttons
        #       e.g. the default one, plus a setting to use facebook.
        return dict(media=media,
                    related_media=Media.query.related(media)[:6],
                    comments=media.comments.published().all(),
                    comment_form_action=url_for(action='comment'),
                    comment_form_values=kwargs,
                    can_comment=self.can_comment())
コード例 #58
0
    def popularity_save(self, **kwargs):
        """Save :class:`~mediacore.forms.admin.settings.PopularityForm`.

        Updates the popularity for every media item based on the submitted
        values.
        """
        self._save(popularity_form, values=kwargs)
        # ".util.calculate_popularity()" uses the popularity settings from
        # the request.settings which are only updated when a new request
        # comes in.
        # update the settings manually so the popularity is actually updated
        # correctly.
        for key in ('popularity_decay_exponent', 'popularity_decay_lifetime'):
            request.settings[key] = kwargs['popularity.'+key]
        for m in Media.query:
            m.update_popularity()
            DBSession.add(m)
        redirect(action='popularity')
コード例 #59
0
    def rate(self, slug, up=None, down=None, **kwargs):
        """Say 'I like this' for the given media.

        :param slug: The media :attr:`~mediacore.model.media.Media.slug`
        :rtype: unicode
        :returns:
            The new number of likes

        """
        # we have to check if current user is anonymous or authenticated
        userid = check_user_authentication(request)
        if not userid:
            log.warn('Anonymous user cannot rate media')
            raise HTTPUnauthorized().exception

        media = fetch_row(Media, slug=slug)

        # check if current user has already voted this media object
        votes = Vote.query.get_votes(media_id=media.id, user_name=userid)
        if votes.count():
            # if true redirect to 'view'
            log.warn('User %s already voted this media')
            redirect(action='view')

        # create new vote object mapping current media and user
        vote = Vote()
        vote.media_id = media.id
        vote.user_name = userid

        # Give the Vote object an ID.
        DBSession.add(vote)
        DBSession.flush()

        if up:
            vote.increment_likes()
            media.increment_likes()
        elif down:
            vote.increment_dislikes()
            media.increment_dislikes()

        if request.is_xhr:
            return u''
        else:
            redirect(action='view')