示例#1
0
    def comment(self, slug, name="", email=None, body="", **kwargs):
        """Post a comment from :class:`~mediacore.forms.comments.PostCommentForm`.

        :param slug: The media :attr:`~mediacore.model.media.Media.slug`
        :returns: Redirect to :meth:`view` page for media.

        """

        def result(success, message=None, comment=None):
            if request.is_xhr:
                result = dict(success=success, message=message)
                if comment:
                    result["comment"] = render("comments/_list.html", {"comment_to_render": comment}, method="xhtml")
                return result
            elif success:
                return redirect(action="view")
            else:
                return self.view(slug, name=name, email=email, body=body, **kwargs)

        akismet_key = request.settings["akismet_key"]
        if akismet_key:
            akismet = Akismet(agent=USER_AGENT)
            akismet.key = akismet_key
            akismet.blog_url = request.settings["akismet_url"] or url_for("/", qualified=True)
            akismet.verify_key()
            data = {
                "comment_author": name.encode("utf-8"),
                "user_ip": request.environ.get("REMOTE_ADDR"),
                "user_agent": request.environ.get("HTTP_USER_AGENT", ""),
                "referrer": request.environ.get("HTTP_REFERER", "unknown"),
                "HTTP_ACCEPT": request.environ.get("HTTP_ACCEPT"),
            }

            if akismet.comment_check(body.encode("utf-8"), data):
                return result(False, _(u"Your comment has been rejected."))

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

        c = Comment()

        name = filter_vulgarity(name)
        c.author = AuthorWithIP(name, email, request.environ["REMOTE_ADDR"])
        c.subject = "Re: %s" % media.title
        c.body = filter_vulgarity(body)

        require_review = request.settings["req_comment_approval"]
        if not require_review:
            c.reviewed = True
            c.publishable = True

        media.comments.append(c)
        DBSession.flush()
        send_comment_notification(media, c)

        if require_review:
            message = _("Thank you for your comment! We will post it just as " "soon as a moderator approves it.")
            return result(True, message=message)
        else:
            return result(True, comment=c)
示例#2
0
    def save_media_obj(self, name, email, title, description, tags, uploaded_file, url):
        # create our media object as a status-less placeholder initially
        media_obj = Media()
        media_obj.author = Author(name, email)
        media_obj.title = title
        media_obj.slug = get_available_slug(Media, title)
        media_obj.description = description
        if request.settings['wording_display_administrative_notes']:
            media_obj.notes = request.settings['wording_administrative_notes']
        media_obj.set_tags(tags)

        # Give the Media object an ID.
        DBSession.add(media_obj)
        DBSession.flush()

        # Create a MediaFile object, add it to the media_obj, and store the file permanently.
        media_file = add_new_media_file(media_obj, file=uploaded_file, url=url)

        # The thumbs may have been created already by add_new_media_file
        if not has_thumbs(media_obj):
            create_default_thumbs_for(media_obj)

        media_obj.update_status()
        DBSession.flush()

        return media_obj
示例#3
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)
        DBSession.flush()
        redirect(action="index", id=None)
示例#4
0
    def _update_settings(self, values):
        """Modify the settings associated with the given dictionary."""
        for name, value in values.iteritems():
            if name in tmpl_context.settings:
                setting = tmpl_context.settings[name]
            else:
                setting = Setting(key=name, value=value)
            if value is None:
                value = u''
            else:
                value = unicode(value)
            if setting.value != value:
                setting.value = value
                DBSession.add(setting)
        DBSession.flush()

        # Clear the settings cache unless there are multiple processes.
        # We have no way of notifying the other processes that they need
        # to clear their caches too, so we've just gotta let it play out
        # until all the caches expire.
        if not request.environ.get('wsgi.multiprocess', False):
            app_globals.settings_cache.clear()
        else:
            # uWSGI provides an automagically included module
            # that we can use to call a graceful restart of all
            # the uwsgi processes.
            # http://projects.unbit.it/uwsgi/wiki/uWSGIReload
            try:
                import uwsgi
                uwsgi.reload()
            except ImportError:
                pass
示例#5
0
def _add_new_media_file(media, original_filename, file):
    # FIXME: I think this will raise a KeyError if the uploaded
    #        file doesn't have an extension.
    file_ext = os.path.splitext(original_filename)[1].lower()[1:]

    # set the file paths depending on the file type
    media_file = MediaFile()
    media_file.type = file_ext
    media_file.url = 'dummy_url' # model requires that url not NULL
    media_file.is_original = True
    media_file.enable_player = media_file.is_playable
    media_file.enable_feed = not media_file.is_embeddable
    media_file.size = os.fstat(file.fileno())[6]

    # update media relations
    media.files.append(media_file)

    # add the media file (and its media, if new) to the database to get IDs
    DBSession.add(media_file)
    DBSession.flush()

    # copy the file to its permanent location
    file_name = '%d_%d_%s.%s' % (media.id, media_file.id, media.slug, file_ext)
    file_url = _store_media_file(file, file_name)
    media_file.url = file_url

    return media_file
示例#6
0
    def save_media_obj(self, name, email, title, description, tags, uploaded_file, url):
        # create our media object as a status-less placeholder initially
        media_obj = Media()
        media_obj.author = Author(name, email)
        media_obj.title = title
        media_obj.slug = get_available_slug(Media, title)
        media_obj.description = description
        if request.settings['wording_display_administrative_notes']:
            media_obj.notes = request.settings['wording_administrative_notes']
        media_obj.set_tags(tags)

        # Give the Media object an ID.
        DBSession.add(media_obj)
        DBSession.flush()

        # Create a MediaFile object, add it to the media_obj, and store the file permanently.
        media_file = add_new_media_file(media_obj, file=uploaded_file, url=url)

        # The thumbs may have been created already by add_new_media_file
        if not has_thumbs(media_obj):
            create_default_thumbs_for(media_obj)

        media_obj.update_status()
        DBSession.flush()

        return media_obj
 def _create_user_without_groups(self):
     user = User()
     user.user_name = u'joe'
     user.email_address = u'*****@*****.**'
     user.display_name = u'Joe'
     user.groups = []
     DBSession.add(user)
     DBSession.flush()
     return user
 def test_can_restrict_query_if_user_does_not_have_the_required_permission(self):
     query = Media.query
     permission = u'view'
     perm = self.perm()
     view_permission = DBSession.query(Permission).filter(Permission.permission_name == permission).one()
     view_permission.groups = []
     DBSession.flush()
     
     assert_none(self.policy.access_condition_for_query(query, permission, perm))
 def _create_user_without_groups(self):
     user = User()
     user.user_name = u'joe'
     user.email_address = u'*****@*****.**'
     user.display_name = u'Joe'
     user.groups = []
     DBSession.add(user)
     DBSession.flush()
     return user
示例#10
0
    def save_album_art(self, id, album_art, **kwargs):
        """Save album art uploaded with :class:`~mediacore.forms.media.AlbumArtForm`.

        :param id: Media ID. If ``"new"`` a new Media stub is created with
            :func:`~mediacore.model.media.create_media_stub`.
        :type id: ``int`` or ``"new"``
        :param file: The uploaded file
        :type file: :class:`cgi.FieldStorage` or ``None``
        :rtype: JSON dict
        :returns:
            success
                bool
            message
                Error message, if unsuccessful
            id
                The :attr:`~mediacore.model.media.Media.id` which is
                important if a new media has just been created.

        """
        if id == 'new':
            media = create_media_stub()
        else:
            media = fetch_row(Media, id, incl_trash=True)

        im_path = os.path.join(config.image_dir, 'media/%s%s.%s')

        try:
            # Create thumbnails
            im = Image.open(album_art.file)

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

            # TODO: Allow other formats?
            for key, dimensions in config.album_art_sizes.iteritems():
                file_path = im_path % (media.id, key, 'jpg')
                im.resize(dimensions, 1).save(file_path)

            # Backup the original image just for kicks
            orig_type = os.path.splitext(album_art.filename)[1].lower()[1:]
            backup_file = open(im_path % (media.id, 'orig', orig_type), 'w')
            copyfileobj(album_art.file, backup_file)
            album_art.file.close()
            backup_file.close()

            success = True
            message = None
        except IOError:
            success = False
            message = 'Unsupported image type'
        except Exception, e:
            success = False
            message = e.message
    def test_can_restrict_query_if_user_does_not_have_the_required_permission(
            self):
        query = Media.query
        permission = u'view'
        perm = self.perm()
        view_permission = DBSession.query(Permission).filter(
            Permission.permission_name == permission).one()
        view_permission.groups = []
        DBSession.flush()

        assert_none(
            self.policy.access_condition_for_query(query, permission, perm))
示例#12
0
def fetch_and_create_tags(tag_names):
    tag_dict = dict()
    for t in tag_names:
        tag_dict[slugify(t)] = t

    existing_tags = DBSession.query(Tag).filter(Tag.slug.in_(tag_dict.keys())).all()
    existing_slugs = [t.slug for t in existing_tags]
    new_slugs = [s for s in tag_dict.keys() if s not in existing_slugs]
    new_tags = [{'name': tag_dict[s], 'slug': s} for s in new_slugs]

    if new_tags:
        DBSession.connection().execute(tags.insert(), new_tags)
        DBSession.flush()
        existing_tags += DBSession.query(Tag).filter(Tag.slug.in_(new_slugs)).all()
    return existing_tags
    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)
示例#14
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)
示例#15
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')
示例#16
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')
示例#17
0
    def reorder_file(self, id, file_id, budge_infront_id, **kwargs):
        """Change the position of the given file relative to the 2nd file.

        :param file_id: The file to move
        :type file_id: ``int``
        :param budge_infront_id: The file whos position the first file takes.
            All files behind/after this file are bumped back as well.
        :type budge_infront_id: ``int`` or ``None``
        :rtype: JSON dict
        :returns:
            success
                bool

        """
        media = fetch_row(Media, id, incl_trash=True)
        media.reposition_file(file_id, budge_infront_id)
        DBSession.add(media)
        DBSession.flush()
        return dict(success=True)
示例#18
0
    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, incl_trash=True)

        # Make the requested change assuming it will be allowed
        if update_button == 'Review Complete':
            media.status.discard('unreviewed')
        elif update_button == 'Publish Now':
            media.status.discard('draft')
            media.status.add('publish')
            media.publish_on = publish_on or datetime.now()
        elif publish_on:
            media.publish_on = publish_on

        try:
            # Verify the change is valid by re-determining the status
            media.update_status()
            DBSession.add(media)
            DBSession.flush()
            data = dict(success=True)
        except Exception, e:
            data = dict(success=False, message=e.message)
示例#19
0
    def save(self, email, legal_wording, default_wording, **kwargs):
        """Save :class:`~mediacore.forms.settings.SettingsForm`.

        Redirects back to :meth:`edit` after successful editing.

        """
        settings = self._fetch_keyed_settings()
        settings['email_media_uploaded'].value = email['media_uploaded']
        settings['email_comment_posted'].value = email['comment_posted']
        settings['email_support_requests'].value = email['support_requests']
        settings['email_send_from'].value = email['send_from']
#        settings['ftp_server'].value = ftp['server']
#        settings['ftp_username'].value = ftp['username']
#        if ftp['password'] is not None and ftp['password'] != '':
#            settings['ftp_password'].value = ftp['password']
#        settings['ftp_upload_path'].value = ftp['upload_path']
#        settings['ftp_download_url'].value = ftp['download_url']
        settings['wording_user_uploads'].value = legal_wording['user_uploads']
        settings['wording_additional_notes'].value = default_wording['additional_notes']

        DBSession.add_all(settings.values())
        DBSession.flush()
        redirect(action='edit')
示例#20
0
    def save(self, id, slug, title, author_name, author_email,
             description, notes, details, podcast, tags, topics, 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.media.MediaForm`.

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

        """
        media = fetch_row(Media, id, incl_trash=True)

        if delete:
            media.status.add('trash')
            DBSession.add(media)
            DBSession.flush()
            redirect(action='index', id=None)

        if id == 'new':
            media.status = 'draft,unencoded,unreviewed'

        media.slug = get_available_slug(Media, slug, media)
        media.title = title
        media.author = Author(author_name, author_email)
        media.description = helpers.clean_admin_xhtml(description)
        media.notes = notes
        media.duration = helpers.duration_to_seconds(details['duration'])
        media.podcast_id = podcast
        media.set_tags(tags)
        media.set_topics(topics)

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

        redirect(action='edit', id=media.id)
示例#21
0
def add_new_media_file(media, file=None, url=None):
    """Create a MediaFile instance from the given file or URL.

    This function MAY modify the given media object.

    :type media: :class:`~mediacore.model.media.Media` instance
    :param media: The media object that this file or URL will belong to.
    :type file: :class:`cgi.FieldStorage` or None
    :param file: A freshly uploaded file object.
    :type url: unicode or None
    :param url: A remote URL string.
    :rtype: :class:`~mediacore.model.media.MediaFile`
    :returns: A newly created media file instance.
    :raises StorageError: If the input file or URL cannot be
        stored with any of the registered storage engines.

    """
    sorted_engines = enabled_engines()
    for engine in sorted_engines:
        try:
            meta = engine.parse(file=file, url=url)
            log.debug('Engine %r returned meta %r', engine, meta)
            break
        except UnsuitableEngineError:
            log.debug('Engine %r unsuitable for %r/%r', engine, file, url)
            continue
    else:
        raise StorageError(_('Unusable file or URL provided.'), None, None)

    from mediacore.model import DBSession, MediaFile
    mf = MediaFile()
    mf.storage = engine
    mf.media = media

    mf.type = meta['type']
    mf.display_name = meta.get('display_name', default_display_name(file, url))
    mf.unique_id = meta.get('unique_id', None)

    mf.container = meta.get('container', None)
    mf.size = meta.get('size', None)
    mf.bitrate = meta.get('bitrate', None)
    mf.width = meta.get('width', None)
    mf.height = meta.get('height', None)

    media.files.append(mf)
    DBSession.flush()

    unique_id = engine.store(media_file=mf, file=file, url=url, meta=meta)

    if unique_id:
        mf.unique_id = unique_id
    elif not mf.unique_id:
        raise StorageError('Engine %r returned no unique ID.', engine)

    if not media.duration and meta.get('duration', 0):
        media.duration = meta['duration']
    if not media.description and meta.get('description'):
        media.description = clean_xhtml(meta['description'])
    if not media.title:
        media.title = meta.get('title', None) or mf.display_name
    if media.type is None:
        media.type = mf.type

    if ('thumbnail_url' in meta or 'thumbnail_file' in meta) \
    and (not has_thumbs(media) or has_default_thumbs(media)):
        thumb_file = meta.get('thumbnail_file', None)

        if thumb_file is not None:
            thumb_filename = thumb_file.filename
        else:
            thumb_url = meta['thumbnail_url']
            thumb_filename = os.path.basename(thumb_url)

            # Download the image to a buffer and wrap it as a file-like object
            try:
                temp_img = urlopen(thumb_url)
                thumb_file = StringIO(temp_img.read())
                temp_img.close()
            except URLError, e:
                log.exception(e)

        if thumb_file is not None:
            create_thumbs_for(media, thumb_file, thumb_filename)
            thumb_file.close()
示例#22
0
文件: api.py 项目: isaleem/cumin
            thumb_url = meta['thumbnail_url']
            thumb_filename = os.path.basename(thumb_url)

            # Download the image to a buffer and wrap it as a file-like object
            try:
                temp_img = urlopen(thumb_url)
                thumb_file = StringIO(temp_img.read())
                temp_img.close()
            except URLError, e:
                log.exception(e)

        if thumb_file is not None:
            create_thumbs_for(media, thumb_file, thumb_filename)
            thumb_file.close()

    DBSession.flush()

    engine.postprocess(mf)

    # Try to transcode the file.
    for engine in sorted_engines:
        try:
            engine.transcode(mf)
            log.debug('Engine %r has agreed to transcode %r', engine, mf)
            break
        except CannotTranscode:
            log.debug('Engine %r unsuitable for transcoding %r', engine, mf)
            continue

    return mf
示例#23
0
    def edit_file(self, id, file_id, player_enabled, feed_enabled,
                  toggle_feed, toggle_player, delete, **kwargs):
        """Save action for the :class:`~mediacore.forms.media.EditFileForm`.

        Changes or delets a :class:`~mediacore.model.media.MediaFile`.

        :param id: Media ID
        :type id: :class:`int`
        :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, incl_trash=True)
        data = {}

#        try:
        try:
            file = [file for file in media.files if file.id == file_id][0]
        except IndexError:
            raise Exception, 'File does not exist.'

        if toggle_player:
            data['field'] = 'player_enabled'
            file.enable_player = data['value'] = not player_enabled
            DBSession.add(file)
        elif toggle_feed:
            data['field'] = 'feed_enabled'
            file.enable_feed = data['value'] = not feed_enabled
            # Raises an exception if it is the only feed enabled file for
            # an already published podcast episode.
            DBSession.add(file)
        elif delete:
            data['field'] = 'delete'
            DBSession.delete(file)
            media.files.remove(file)
        else:
            raise Exception, 'No action to perform.'

        data['success'] = True
        media.update_type()
        media.update_status()
        DBSession.add(media)
#        except Exception, e:
#            data['success'] = False
#            data['message'] = e.message

        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))
            data['status_form'] = status_form_xhtml
            return data
        else:
            DBSession.flush()
            redirect(action='edit')
示例#24
0
            thumb_url = meta['thumbnail_url']
            thumb_filename = os.path.basename(thumb_url)

            # Download the image to a buffer and wrap it as a file-like object
            try:
                temp_img = urlopen(thumb_url)
                thumb_file = StringIO(temp_img.read())
                temp_img.close()
            except URLError, e:
                log.exception(e)

        if thumb_file is not None:
            create_thumbs_for(media, thumb_file, thumb_filename)
            thumb_file.close()

    DBSession.flush()

    engine.postprocess(mf)

    # Try to transcode the file.
    for engine in sorted_engines:
        try:
            engine.transcode(mf)
            log.debug('Engine %r has agreed to transcode %r', engine, mf)
            break
        except CannotTranscode:
            log.debug('Engine %r unsuitable for transcoding %r', engine, mf)
            continue

    return mf
示例#25
0
    def comment(self, slug, name='', email=None, body='', **kwargs):
        """Post a comment from :class:`~mediacore.forms.comments.PostCommentForm`.

        :param slug: The media :attr:`~mediacore.model.media.Media.slug`
        :returns: Redirect to :meth:`view` page for media.

        """
        def result(success, message=None, comment=None):
            if request.is_xhr:
                result = dict(success=success, message=message)
                if comment:
                    result['comment'] = render('comments/_list.html',
                                               {'comment_to_render': comment},
                                               method='xhtml')
                return result
            elif success:
                return redirect(action='view')
            else:
                return self.view(slug,
                                 name=name,
                                 email=email,
                                 body=body,
                                 **kwargs)

        if request.settings['comments_engine'] != 'mediacore':
            abort(404)
        akismet_key = request.settings['akismet_key']
        if akismet_key:
            akismet = Akismet(agent=USER_AGENT)
            akismet.key = akismet_key
            akismet.blog_url = request.settings['akismet_url'] or \
                url_for('/', qualified=True)
            akismet.verify_key()
            data = {
                'comment_author': name.encode('utf-8'),
                'user_ip': request.environ.get('REMOTE_ADDR'),
                'user_agent': request.environ.get('HTTP_USER_AGENT', ''),
                'referrer': request.environ.get('HTTP_REFERER', 'unknown'),
                'HTTP_ACCEPT': request.environ.get('HTTP_ACCEPT')
            }

            if akismet.comment_check(body.encode('utf-8'), data):
                return result(False, _(u'Your comment has been rejected.'))

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

        c = Comment()

        name = filter_vulgarity(name)
        c.author = AuthorWithIP(name, email, request.environ['REMOTE_ADDR'])
        c.subject = 'Re: %s' % media.title
        c.body = filter_vulgarity(body)

        require_review = request.settings['req_comment_approval']
        if not require_review:
            c.reviewed = True
            c.publishable = True

        media.comments.append(c)
        DBSession.flush()
        send_comment_notification(media, c)

        if require_review:
            message = _('Thank you for your comment! We will post it just as '
                        'soon as a moderator approves it.')
            return result(True, message=message)
        else:
            return result(True, comment=c)
    def test_sizeless_file_picking(self):
        """Test while file gets served to each browser, given that all files
        are the same filesize.
        """
        media, media_files = self._get_media('unsized')

        for mf in media_files:
            media_files[mf].size = None
        DBSession.flush()

        pylons.app_globals.settings['html5_player'] = 'html5'
        pylons.app_globals.settings['flash_player'] = 'flowplayer'

        combinations = [
            # Prefer flash, without embeds
            ('firefox', 2,          'flash', False, 'flv', 'flowplayer'),
            ('firefox', 3,          'flash', False, 'flv', 'flowplayer'),
            ('firefox', 3.5,        'flash', False, 'flv', 'flowplayer'),
            ('safari', 522,         'flash', False, 'flv', 'flowplayer'),
            ('opera', 10.5,         'flash', False, 'flv', 'flowplayer'),
            ('opera', 9,            'flash', False, 'flv', 'flowplayer'),
            ('chrome', 3.0,         'flash', False, 'flv', 'flowplayer'),
            ('android', 0,          'flash', False, 'flv', 'flowplayer'),
            ('itunes', 0,           'flash', False, 'm4v', 'html5'),
            ('iphone-ipod-ipad', 0, 'flash', False, 'm4v', 'html5'),
            ('unknown', 0,          'flash', False, 'flv', 'flowplayer'),
            # Prefer flash, including embeds
            ('firefox', 2,          'flash', True, 'youtube', 'youtube'),
            ('firefox', 3,          'flash', True, 'youtube', 'youtube'),
            ('firefox', 3.5,        'flash', True, 'youtube', 'youtube'),
            ('safari', 522,         'flash', True, 'youtube', 'youtube'),
            ('opera', 10.5,         'flash', True, 'youtube', 'youtube'),
            ('opera', 9,            'flash', True, 'youtube', 'youtube'),
            ('chrome', 3.0,         'flash', True, 'youtube', 'youtube'),
            ('android', 0,          'flash', True, 'youtube', 'youtube'),
            ('itunes', 0,           'flash', True, 'm4v',     'html5'),
            ('iphone-ipod-ipad', 0, 'flash', True, 'm4v',     'html5'),
            ('unknown', 0,          'flash', True, 'youtube', 'youtube'),
            # Prefer HTML5, without embeds
            ('firefox', 2,          'best', False, 'flv', 'flowplayer'),
            ('firefox', 3,          'best', False, 'flv', 'flowplayer'),
            ('firefox', 3.5,        'best', False, 'ogv', 'html5'),
            ('safari', 522,         'best', False, 'm4v', 'html5'),
            ('opera', 10.5,         'best', False, 'ogv', 'html5'),
            ('opera', 9,            'best', False, 'flv', 'flowplayer'),
            ('chrome', 3.0,         'best', False, 'm4v', 'html5'),
            ('android', 0,          'best', False, 'm4v', 'html5'),
            ('itunes', 0,           'best', False, 'm4v', 'html5'),
            ('iphone-ipod-ipad', 0, 'best', False, 'm4v', 'html5'),
            ('unknown', 0,          'best', False, 'flv', 'flowplayer'),
            # Prefer HTML5, including embeds
            ('firefox', 2,          'best', True, 'youtube', 'youtube'),
            ('firefox', 3,          'best', True, 'youtube', 'youtube'),
            ('firefox', 3.5,        'best', True, 'ogv',     'html5'),
            ('safari', 522,         'best', True, 'm4v',     'html5'),
            ('opera', 10.5,         'best', True, 'ogv',     'html5'),
            ('opera', 9,            'best', True, 'youtube', 'youtube'),
            ('chrome', 3.0,         'best', True, 'm4v',     'html5'),
            ('android', 0,          'best', True, 'm4v',     'html5'),
            ('itunes', 0,           'best', True, 'm4v',     'html5'),
            ('iphone-ipod-ipad', 0, 'best', True, 'm4v',     'html5'),
            ('unknown', 0,          'best', True, 'youtube', 'youtube'),
            # HTML5 only, without embeds
            ('firefox', 2,          'html5', False, None,  None),
            ('firefox', 3,          'html5', False, None,  None),
            ('firefox', 3.5,        'html5', False, 'ogv', 'html5'),
            ('safari', 522,         'html5', False, 'm4v', 'html5'),
            ('opera', 10.5,         'html5', False, 'ogv', 'html5'),
            ('opera', 9,            'html5', False, None,  None),
            ('chrome', 3.0,         'html5', False, 'm4v', 'html5'),
            ('android', 0,          'html5', False, 'm4v', 'html5'),
            ('itunes', 0,           'html5', False, 'm4v', 'html5'),
            ('iphone-ipod-ipad', 0, 'html5', False, 'm4v', 'html5'),
            ('unknown', 0,          'html5', False, None, None),
            # HTML5 only, including embeds
            ('firefox', 2,          'html5', True, None,  None),
            ('firefox', 3,          'html5', True, None,  None),
            ('firefox', 3.5,        'html5', True, 'ogv', 'html5'),
            ('safari', 522,         'html5', True, 'm4v', 'html5'),
            ('opera', 10.5,         'html5', True, 'ogv', 'html5'),
            ('opera', 9,            'html5', True, None,  None),
            ('chrome', 3.0,         'html5', True, 'm4v', 'html5'),
            ('android', 0,          'html5', True, 'm4v', 'html5'),
            ('itunes', 0,           'html5', True, 'm4v', 'html5'),
            ('iphone-ipod-ipad', 0, 'html5', True, 'm4v', 'html5'),
            ('unknown', 0,          'html5', True, None, None),
        ]

        from mediacore.lib.players import players
        players = dict(players)
        players[None] = None
        media_files[None] = None

        for browser, version, p_type, embedded, e_file, e_player in combinations:
            player = pick_media_file_player(media,
                    browser = browser,
                    version = version,
                    player_type = p_type,
                    include_embedded = embedded
            )
            if player:
                file = player.file
                browser, version = player.browser
            else:
                file, browser, version = None, None, None
            print "Unsized:", browser, version, p_type, embedded, e_file, e_player
            player_class = player and player.__class__ or None
            assert player_class == players[e_player], "Expected %r but was %r" % (players[e_player], player_class)
            assert file == media_files[e_file], "Expected %r but got %r" % (media_files[e_file], file)
示例#27
0
文件: media.py 项目: wafe/mediadrop
    def comment(self, slug, name='', email=None, body='', **kwargs):
        """Post a comment from :class:`~mediacore.forms.comments.PostCommentForm`.

        :param slug: The media :attr:`~mediacore.model.media.Media.slug`
        :returns: Redirect to :meth:`view` page for media.

        """
        def result(success, message=None, comment=None):
            if request.is_xhr:
                result = dict(success=success, message=message)
                if comment:
                    result['comment'] = render('comments/_list.html',
                        {'comment_to_render': comment},
                        method='xhtml')
                return result
            elif success:
                return redirect(action='view')
            else:
                return self.view(slug, name=name, email=email, body=body,
                                 **kwargs)

        if request.settings['comments_engine'] != 'mediacore':
            abort(404)
        akismet_key = request.settings['akismet_key']
        if akismet_key:
            akismet = Akismet(agent=USER_AGENT)
            akismet.key = akismet_key
            akismet.blog_url = request.settings['akismet_url'] or \
                url_for('/', qualified=True)
            akismet.verify_key()
            data = {'comment_author': name.encode('utf-8'),
                    'user_ip': request.environ.get('REMOTE_ADDR'),
                    'user_agent': request.environ.get('HTTP_USER_AGENT', ''),
                    'referrer': request.environ.get('HTTP_REFERER',  'unknown'),
                    'HTTP_ACCEPT': request.environ.get('HTTP_ACCEPT')}

            if akismet.comment_check(body.encode('utf-8'), data):
                return result(False, _(u'Your comment has been rejected.'))

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

        c = Comment()

        name = filter_vulgarity(name)
        c.author = AuthorWithIP(name, email, request.environ['REMOTE_ADDR'])
        c.subject = 'Re: %s' % media.title
        c.body = filter_vulgarity(body)

        require_review = request.settings['req_comment_approval']
        if not require_review:
            c.reviewed = True
            c.publishable = True

        media.comments.append(c)
        DBSession.flush()
        send_comment_notification(media, c)

        if require_review:
            message = _('Thank you for your comment! We will post it just as '
                        'soon as a moderator approves it.')
            return result(True, message=message)
        else:
            return result(True, comment=c)
示例#28
0
文件: api.py 项目: isaleem/cumin
def add_new_media_file(media, file=None, url=None):
    """Create a MediaFile instance from the given file or URL.

    This function MAY modify the given media object.

    :type media: :class:`~mediacore.model.media.Media` instance
    :param media: The media object that this file or URL will belong to.
    :type file: :class:`cgi.FieldStorage` or None
    :param file: A freshly uploaded file object.
    :type url: unicode or None
    :param url: A remote URL string.
    :rtype: :class:`~mediacore.model.media.MediaFile`
    :returns: A newly created media file instance.
    :raises StorageError: If the input file or URL cannot be
        stored with any of the registered storage engines.

    """
    sorted_engines = enabled_engines()
    for engine in sorted_engines:
        try:
            meta = engine.parse(file=file, url=url)
            log.debug('Engine %r returned meta %r', engine, meta)
            break
        except UnsuitableEngineError:
            log.debug('Engine %r unsuitable for %r/%r', engine, file, url)
            continue
    else:
        raise StorageError(_('Unusable file or URL provided.'), None, None)

    from mediacore.model import DBSession, MediaFile
    mf = MediaFile()
    mf.storage = engine
    mf.media = media

    mf.type = meta['type']
    mf.display_name = meta.get('display_name', default_display_name(file, url))
    mf.unique_id = meta.get('unique_id', None)

    mf.container = meta.get('container', None)
    mf.size = meta.get('size', None)
    mf.bitrate = meta.get('bitrate', None)
    mf.width = meta.get('width', None)
    mf.height = meta.get('height', None)

    media.files.append(mf)
    DBSession.flush()

    unique_id = engine.store(media_file=mf, file=file, url=url, meta=meta)

    if unique_id:
        mf.unique_id = unique_id
    elif not mf.unique_id:
        raise StorageError('Engine %r returned no unique ID.', engine)

    if not media.duration and meta.get('duration', 0):
        media.duration = meta['duration']
    if not media.description and meta.get('description'):
        media.description = clean_xhtml(meta['description'])
    if not media.title:
        media.title = meta.get('title', None) or mf.display_name
    if media.type is None:
        media.type = mf.type

    if ('thumbnail_url' in meta or 'thumbnail_file' in meta) \
    and (not has_thumbs(media) or has_default_thumbs(media)):
        thumb_file = meta.get('thumbnail_file', None)

        if thumb_file is not None:
            thumb_filename = thumb_file.filename
        else:
            thumb_url = meta['thumbnail_url']
            thumb_filename = os.path.basename(thumb_url)

            # Download the image to a buffer and wrap it as a file-like object
            try:
                temp_img = urlopen(thumb_url)
                thumb_file = StringIO(temp_img.read())
                temp_img.close()
            except URLError, e:
                log.exception(e)

        if thumb_file is not None:
            create_thumbs_for(media, thumb_file, thumb_filename)
            thumb_file.close()
示例#29
0
    def add_file(self, id, file=None, url=None, **kwargs):
        """Save action for the :class:`~mediacore.forms.media.AddFileForm`.

        Creates a new :class:`~mediacore.model.media.MediaFile` from the
        uploaded file or the local or remote URL.

        :param id: Media ID. If ``"new"`` a new Media stub is created with
            :func:`~mediacore.model.media.create_media_stub`.
        :type id: :class:`int` or ``"new"``
        :param file: The uploaded file
        :type file: :class:`cgi.FieldStorage` or ``None``
        :param url: A URL to a recognizable audio or video file
        :type url: :class:`unicode` or ``None``
        :rtype: JSON dict
        :returns:
            success
                bool
            message
                Error message, if unsuccessful
            media_id
                The :attr:`~mediacore.model.media.Media.id` which is
                important if new media has just been created.
            file_id
                The :attr:`~mediacore.model.media.MediaFile.id` for the newly
                created file.
            edit_form
                The rendered XHTML :class:`~mediacore.forms.media.EditFileForm`
                for this file.
            status_form
                The rendered XHTML :class:`~mediacore.forms.media.UpdateStatusForm`

        """
        if id == 'new':
            media = create_media_stub()
        else:
            media = fetch_row(Media, id, incl_trash=True)

        try:
            if file is not None:
                # Create a media object, add it to the video, and store the file permanently.
                media_file = _add_new_media_file(media, file.filename, file.file)
            elif url:
                media_file = MediaFile()
                # Parse the URL checking for known embeddables like YouTube
                for type, info in config.embeddable_filetypes.iteritems():
                    match = re.match(info['pattern'], url)
                    if match:
                        media_file.type = type
                        media_file.url = match.group('id')
                        media_file.enable_feed = False
                        break
                else:
                    # Check for types we can play ourselves
                    type = os.path.splitext(url)[1].lower()[1:]
                    for playable_types in config.playable_types.itervalues():
                        if type in playable_types:
                            media_file.type = type
                            media_file.url = url
                            break
                    else:
                        raise Exception, 'Unsupported URL %s' % url
            else:
                raise Exception, 'Given no action to perform.'

            media.files.append(media_file)
            media.update_type()
            media.update_status()
            DBSession.add(media)
            DBSession.flush()

            # Render some widgets so the XHTML can be injected into the page
            edit_form_xhtml = unicode(edit_file_form.display(
                action=url_for(action='edit_file', id=media.id),
                file=media_file))
            status_form_xhtml = unicode(update_status_form.display(
                action=url_for(action='update_status', id=media.id),
                media=media))

            return dict(
                success = True,
                media_id = media.id,
                file_id = media_file.id,
                edit_form = edit_form_xhtml,
                status_form = status_form_xhtml,
            )
        except Exception, e:
            return dict(
                success = False,
                message = e.message,
            )