Пример #1
0
class PlaylistVideo(TimestampMixin, db.Model):
    __tablename__ = 'playlist_video'
    playlist_id = db.Column(db.Integer, db.ForeignKey('playlist.id'), primary_key=True)
    video_id = db.Column(db.Integer, db.ForeignKey('video.id'), primary_key=True)
    video = db.relationship('Video', backref=db.backref('_playlists', cascade='all, delete-orphan'))
    seq = db.Column(db.Integer, nullable=False)
    description = db.Column(db.UnicodeText, nullable=False, default=True)
Пример #2
0
class PlaylistRedirect(BaseMixin, db.Model):
    __tablename__ = "playlist_redirect"

    channel_id = db.Column(None, db.ForeignKey('channel.id'), nullable=False)
    channel = db.relationship(Channel,
                              backref=db.backref('playlist_redirects',
                                                 cascade='all, delete-orphan'))

    name = db.Column(db.Unicode(250), nullable=False)
    playlist_id = db.Column(None, db.ForeignKey('playlist.id'), nullable=False)
    playlist = db.relationship(Playlist,
                               backref=db.backref(
                                   'redirects', cascade='all, delete-orphan'))

    __table_args__ = (db.UniqueConstraint(channel_id, name), )

    def redirect_view_args(self):
        return {'playlist': self.playlist.name}

    @classmethod
    def migrate_profile(cls, oldchannel, newchannel):
        """
        There's no point trying to migrate playlists when merging channels, so discard them.
        """
        oldchannel.playlist_redirects = []
        return [cls.__table__.name]
Пример #3
0
class ChannelVideo(TimestampMixin, db.Model):
    __tablename__ = 'channel_video'
    channel_id = db.Column(db.Integer,
                           db.ForeignKey('channel.id'),
                           primary_key=True)
    video_id = db.Column(db.Integer,
                         db.ForeignKey('video.id'),
                         primary_key=True)
    video = db.relationship('Video',
                            backref=db.backref('_channels',
                                               cascade='all, delete-orphan'))
    seq = db.Column(db.Integer, nullable=False)
    relation = db.Column(
        db.Integer,
        nullable=False)  # Describes why the channel is linked to the video
Пример #4
0
class Playlist(BaseScopedNameMixin, db.Model):
    __tablename__ = 'playlist'
    short_title = db.Column(db.Unicode(80), nullable=False, default=u'')
    channel_id = db.Column(db.Integer,
                           db.ForeignKey('channel.id'),
                           nullable=False)
    channel = db.relationship(Channel,
                              primaryjoin=channel_id == Channel.id,
                              backref=db.backref('playlists',
                                                 cascade='all, delete-orphan'))
    parent = db.synonym('channel')
    description = db.Column(db.UnicodeText, default=u'', nullable=False)
    public = db.Column(db.Boolean, nullable=False, default=True)
    recorded_date = db.Column(db.Date, nullable=True)
    published_date = db.Column(db.Date, nullable=False, default=date.today)
    featured = db.Column(db.Boolean, default=False, nullable=False)
    type = db.Column(db.Integer, default=PLAYLIST_TYPE.REGULAR, nullable=False)
    auto_type = db.Column(db.Integer, nullable=True)

    __table_args__ = (db.UniqueConstraint('channel_id', 'auto_type'),
                      db.UniqueConstraint('channel_id', 'name'))

    _videos = db.relationship(PlaylistVideo,
                              order_by=[PlaylistVideo.seq],
                              collection_class=ordering_list('seq'),
                              backref='playlist',
                              cascade='all, delete-orphan')
    videos = association_proxy('_videos',
                               'video',
                               creator=lambda x: PlaylistVideo(video=x))

    def __repr__(self):
        if self.auto_type:
            return '<AutoPlaylist %s of %s>' % (self.type_label(),
                                                self.channel.title)
        else:
            return '<Playlist %s of %s>' % (self.title, self.channel.title)

    @classmethod
    def get_featured(cls, count):
        return cls.query.filter_by(
            public=True, auto_type=None, featured=True).order_by(
                'featured').order_by('updated_at').limit(count).all()

    def type_label(self):
        if self.auto_type is not None:
            return playlist_auto_types.get(self.auto_type)
        else:
            return playlist_types.get(self.type, playlist_types[0])

    def permissions(self, user, inherited=None):
        perms = super(Playlist, self).permissions(user, inherited)
        if self.public:
            perms.add('view')
        if user and self.channel.userid in user.user_organizations_owned_ids():
            perms.add('view')  # In case playlist is not public
            perms.add('edit')
            perms.add('delete')
            perms.add('new-video')
            perms.add('add-video')
            perms.add('remove-video')
        return perms

    def url_for(self, action='view'):
        if action == 'view':
            return url_for('playlist_view',
                           channel=self.channel.name,
                           playlist=self.name)
        elif action == 'edit':
            return url_for('playlist_edit',
                           channel=self.channel.name,
                           playlist=self.name)
        elif action == 'delete':
            return url_for('playlist_delete',
                           channel=self.channel.name,
                           playlist=self.name)
        elif action == 'new-video':
            return url_for('video_new',
                           channel=self.channel.name,
                           playlist=self.name)
        # The remove-video view URL is in Video, not here. Only the permission comes from here.

    def next(self, video):
        return Video.query.filter_by(id=video.id + 1, playlist=self).first()

    def prev(self, video):
        return Video.query.filter_by(id=video.id - 1, playlist=self).first()
Пример #5
0
class Video(BaseIdNameMixin, CommentingMixin, db.Model):
    __tablename__ = 'video'
    playlist_id = db.Column(db.Integer, db.ForeignKey('playlist.id'), nullable=False)
    playlist = db.relationship('Playlist',
        backref=db.backref('primary_videos', cascade='all, delete-orphan'))
    channel = association_proxy('playlist', 'channel')
    description = db.Column(db.UnicodeText, nullable=False, default=u'')
    video_url = db.Column(db.Unicode(250), nullable=False)
    slides_url = db.Column(db.Unicode(250), nullable=False, default=u'')
    thumbnail_path = db.Column(db.Unicode(250), nullable=True, default=u'')

    video_source = db.Column(db.Unicode(80), nullable=False, default=u'')
    video_sourceid = db.Column(db.Unicode(80), nullable=False, default=u'')

    slides_source = db.Column(db.Unicode(80), nullable=False, default=u'')
    slides_sourceid = db.Column(db.Unicode(80), nullable=False, default=u'')
    video_slides_mapping = db.Column(db.UnicodeText, nullable=True, default=u'')
    video_slides_mapping_json = db.Column(db.UnicodeText, nullable=True, default=u'')

    playlists = association_proxy('_playlists', 'playlist', creator=lambda x: PlaylistVideo(playlist=x))

    tags = db.relationship('Tag', secondary=tags_videos, backref=db.backref('videos'))

    def __repr__(self):
        return u'<Video %s>' % self.url_name

    def permissions(self, user, inherited=None):
        perms = super(Video, self).permissions(user, inherited)
        perms.add('view')
        if user and self.channel.userid in user.user_organizations_owned_ids():
            perms.add('edit')
            perms.add('delete')
        else:
            perms.discard('edit')
            perms.discard('delete')
        # Allow speakers to edit
        if user:
            pl = user.channel.playlist_for_speaking_in()
            if pl and self in pl.videos:
                perms.add('edit')
        return perms

    def url_for(self, action='view', channel=None, playlist=None, _external=False):
        channel = channel or self.channel
        playlist = playlist or self.playlist
        if playlist.channel != channel or playlist not in self.playlists:
            return
        if action == 'view':
            return url_for('video_view',
                videopath='%s/%s/%s' % (channel.name, playlist.name, self.url_name),
                _external=_external)
        elif action == 'remove-video':
            return url_for('video_remove',
                channel=channel.name, playlist=playlist.name,
                video=self.url_name, _external=_external)
        # Edit and Delete can only be from the source playlist
        elif action == 'edit':
            return url_for('video_edit',
                channel=self.channel.name, playlist=self.playlist.name,
                video=self.url_name, _external=_external)
        elif action == 'delete':
            return url_for('video_delete',
                channel=self.channel.name, playlist=self.playlist.name,
                video=self.url_name, _external=_external)
        elif action == 'add-speaker':
            return url_for('video_add_speaker',
                channel=channel.name, playlist=playlist.name,
                video=self.url_name, _external=_external)
        elif action == 'autocomplete-speaker':
            return url_for('video_autocomplete_speaker',
                channel=channel.name, playlist=playlist.name,
                video=self.url_name, _external=_external)
        elif action == 'remove-speaker':
            return url_for('video_remove_speaker',
                channel=channel.name, playlist=playlist.name,
                video=self.url_name, _external=_external)
        elif action == 'action':
            return url_for('video_action',
                channel=channel.name, playlist=playlist.name,
                video=self.url_name, _external=_external)

    def embed_video_for(self, action='view'):
        if self.video_source == u'youtube':
            if action == 'edit':
                return Markup('<iframe id="youtube_player" src="//www.youtube.com/embed/%s?wmode=transparent&showinfo=0&rel=0&autohide=0&autoplay=0&enablejsapi=1&version=3" frameborder="0" allowfullscreen></iframe>' % self.video_sourceid)
            elif action == 'view':
                return Markup('<iframe id="youtube_player" src="//www.youtube.com/embed/%s?wmode=transparent&showinfo=0&rel=0&autohide=0&autoplay=1&enablejsapi=1&version=3" frameborder="0" allowfullscreen></iframe>' % self.video_sourceid)
        elif self.video_source == u"vimeo":
            if action == 'edit':
                return Markup('<iframe id="vimeo_player" src="//player.vimeo.com/video/%s?api=1&player_id=vimeoplayer" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>' % self.video_sourceid)
            elif action == 'view':
                return Markup('<iframe id="vimeo_player" src="//player.vimeo.com/video/%s?api=1&autoplay=1" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>' % self.video_sourceid)
        elif self.video_source == u"ustream":
            if action == 'edit':
                return Markup('<iframe id="ustream_player" src="//www.ustream.tv/embed/%s?v=3&amp;wmode=direct" scrolling="no" frameborder="0" style="border: 0px none transparent;"> </iframe>' % self.video_sourceid)
            elif action == 'view':
                return Markup('<iframe id="ustream_player" src="//www.ustream.tv/embed/%s?v=3&amp;wmode=direct" scrolling="no" frameborder="0" style="border: 0px none transparent;"> </iframe>' % self.video_sourceid)
        return u''

    def embed_slides_for(self, action=None):
        if self.slides_source == u'speakerdeck':
            html = '<iframe src="//www.speakerdeck.com/embed/%s" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>' % urllib.quote(self.slides_sourceid)
            return Markup(html)
        elif self.slides_source == u'slideshare':
            html = '<iframe id="slideshare" src="//www.slideshare.net/slideshow/embed_code/%s" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>' % urllib.quote(self.slides_sourceid)
            return Markup(html)
        return u''

    @cached_property
    def speakers(self):
        return [plv.playlist.channel for plv in PlaylistVideo.query.filter_by(video=self) if plv.playlist.auto_type == PLAYLIST_AUTO_TYPE.SPEAKING_IN]
Пример #6
0
class Playlist(BaseScopedNameMixin, db.Model):
    __tablename__ = 'playlist'
    channel_id = db.Column(db.Integer,
                           db.ForeignKey('channel.id'),
                           nullable=False)
    description = db.Column(db.UnicodeText, default=u'', nullable=False)
    public = db.Column(db.Boolean, nullable=False, default=True)
    recorded_date = db.Column(db.Date, nullable=True)
    published_date = db.Column(db.Date, nullable=False, default=date.today)
    featured = db.Column(db.Boolean, default=False, nullable=False)
    type = db.Column(db.Integer, default=PLAYLIST_TYPE.REGULAR, nullable=False)
    auto_type = db.Column(db.Integer, nullable=True)
    banner_ad_filename = db.Column(db.Unicode(250), nullable=True, default=u'')
    banner_ad_url = db.Column(db.Unicode(250), nullable=False, default=u'')
    channel = db.relationship(Channel,
                              primaryjoin=channel_id == Channel.id,
                              backref=db.backref(
                                  'playlists',
                                  order_by=(recorded_date.desc(),
                                            published_date.desc()),
                                  cascade='all, delete-orphan'))
    parent = db.synonym('channel')

    __table_args__ = (db.UniqueConstraint('channel_id', 'auto_type'),
                      db.UniqueConstraint('channel_id', 'name'))

    _videos = db.relationship(PlaylistVideo,
                              order_by=[PlaylistVideo.seq],
                              collection_class=ordering_list('seq'),
                              backref='playlist',
                              cascade='all, delete-orphan')
    videos = association_proxy('_videos',
                               'video',
                               creator=lambda x: PlaylistVideo(video=x))

    def __repr__(self):
        if self.auto_type:
            return '<AutoPlaylist %s of %s>' % (self.type_label(),
                                                self.channel.title)
        else:
            return '<Playlist %s of %s>' % (self.title, self.channel.title)

    @classmethod
    def get_featured(cls, count):
        return cls.query.filter_by(
            public=True, auto_type=None, featured=True).order_by(
                'featured').order_by('updated_at').limit(count).all()

    @classmethod
    def migrate_profile(cls, oldchannel, newchannel):
        """
        Move all playlists from the old channel to the new channel.
        """
        def move_playlist(playlist, channel):
            """
            Move playlist to a new channel
            """
            conflict = bool(
                playlist.query.filter_by(name=playlist.name,
                                         channel=channel).count())
            playlist.channel = channel
            if conflict:
                playlist.make_name()

        for playlist in oldchannel.playlists:
            if playlist.auto_type:
                # Check for matching playlist in newchannel
                newplaylist = newchannel.get_auto_playlist(
                    auto_type=playlist.auto_type, create=False)
                if not newplaylist:
                    move_playlist(playlist, newchannel)
                else:
                    while playlist._videos:
                        plv = playlist._videos.pop(0)
                        if plv.video not in newplaylist.videos:
                            newplaylist._videos.append(plv)
                    for video in playlist.primary_videos:
                        video.playlist = newplaylist
                    db.session.delete(playlist)
            else:
                move_playlist(playlist, newchannel)
        return [cls.__table__.name, PlaylistVideo.__table__.name]

    def type_label(self):
        if self.auto_type is not None:
            return PLAYLIST_AUTO_TYPE[self.auto_type].title
        else:
            return PLAYLIST_TYPE.get(self.type, PLAYLIST_TYPE[0])

    def permissions(self, user, inherited=None):
        perms = super(Playlist, self).permissions(user, inherited)
        if self.public:
            perms.add('view')
        if user and self.channel.userid in user.user_organizations_owned_ids():
            perms.add('view')  # In case playlist is not public
            perms.add('edit')
            perms.add('delete')
            if not self.auto_type or self.auto_type == PLAYLIST_AUTO_TYPE.STREAM:
                perms.add('new-video')
                perms.add('extend')
            perms.add('add-video')
            perms.add('remove-video')
        return perms

    def url_for(self, action='view', _external=False):
        if action == 'view':
            return url_for('playlist_view',
                           channel=self.channel.name,
                           playlist=self.name,
                           _external=_external)
        elif action == 'feed':
            return url_for('playlist_feed',
                           channel=self.channel.name,
                           playlist=self.name,
                           _external=_external)
        elif action == 'edit':
            return url_for('playlist_edit',
                           channel=self.channel.name,
                           playlist=self.name,
                           _external=_external)
        elif action == 'extend':
            return url_for('playlist_extend',
                           channel=self.channel.name,
                           playlist=self.name,
                           _external=_external)
        elif action == 'delete':
            return url_for('playlist_delete',
                           channel=self.channel.name,
                           playlist=self.name,
                           _external=_external)
        elif action == 'new-video':
            return url_for('video_new',
                           channel=self.channel.name,
                           playlist=self.name,
                           _external=_external)

    def next(self, video):
        for index, _video in enumerate(self.videos):
            if video is _video:
                try:
                    return self.videos[index + 1]
                except IndexError:
                    return None
        else:
            return None

    def prev(self, video):
        for index, _video in enumerate(self.videos):
            if video is _video:
                if index == 0:
                    return None
                try:
                    return self.videos[index - 1]
                except IndexError:
                    return None
        else:
            return None
Пример #7
0
        return self.name

    @classmethod
    def get(cls, title):
        tag = cls.query.filter_by(title=title).first()
        if tag:
            return tag
        else:
            name = make_name(title)
            # Is this name already in use? If yes, return it
            tag = cls.query.filter_by(name=name).first()
            if tag:
                return tag
            else:
                tag = cls(name=name, title=title)
                db.session.add(tag)
                return tag

    def rename(self, title):
        name = make_name(title)
        if self.query.filter_by(name=name).first() is not None:
            raise ValueError(u"Name already in use")
        else:
            self.name = name
            self.title = title


tags_videos = db.Table(
    'tags_videos', db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')),
    db.Column('video_id', db.Integer, db.ForeignKey('video.id')))
Пример #8
0
class Video(BaseIdNameMixin, CommentingMixin, db.Model):
    __tablename__ = 'video'
    playlist_id = db.Column(db.Integer,
                            db.ForeignKey('playlist.id'),
                            nullable=False)
    playlist = db.relationship('Playlist',
                               backref=db.backref(
                                   'primary_videos',
                                   cascade='all, delete-orphan'))
    channel = association_proxy('playlist', 'channel')
    description = db.Column(db.UnicodeText, nullable=False, default=u'')
    video_url = db.Column(db.Unicode(250), nullable=False)
    slides_url = db.Column(db.Unicode(250), nullable=False, default=u'')
    thumbnail_path = db.Column(db.Unicode(250), nullable=True, default=u'')

    video_source = db.Column(db.Unicode(80), nullable=False, default=u'')
    video_sourceid = db.Column(db.Unicode(80), nullable=False, default=u'')

    slides_source = db.Column(db.Unicode(80), nullable=False, default=u'')
    slides_sourceid = db.Column(db.Unicode(80), nullable=False, default=u'')

    channels = association_proxy('_channels',
                                 'channel',
                                 creator=lambda x: ChannelVideo(channel=x))
    playlists = association_proxy('_playlists',
                                  'playlist',
                                  creator=lambda x: PlaylistVideo(playlist=x))

    tags = db.relationship('Tag',
                           secondary=tags_videos,
                           backref=db.backref('videos'))

    def __repr__(self):
        return u'<Video %s>' % self.url_name

    def permissions(self, user, inherited=None):
        perms = super(Video, self).permissions(user, inherited)
        perms.add('view')
        if user and self.channel.userid in user.user_organizations_owned_ids():
            perms.add('edit')
            perms.add('delete')
        else:
            if 'edit' in perms:
                perms.remove('edit')
            if 'delete' in perms:
                perms.remove('delete')
        # Allow speakers to edit
        if user:
            pl = user.channel.playlist_for_speaking_in()
            if pl and self in pl.videos:
                perms.add('edit')
        return perms

    def url_for(self,
                action='view',
                channel=None,
                playlist=None,
                _external=False):
        channel = channel or self.channel
        playlist = playlist or self.playlist
        if playlist.channel != channel or playlist not in self.playlists:
            return
        if action == 'view':
            return url_for('video_view',
                           channel=channel.name,
                           playlist=playlist.name,
                           video=self.url_name,
                           _external=_external)
        elif action == 'remove-video':
            return url_for('video_remove',
                           channel=channel.name,
                           playlist=playlist.name,
                           video=self.url_name,
                           _external=_external)
        # Edit and Delete can only be from the source playlist
        elif action == 'edit':
            return url_for('video_edit',
                           channel=self.channel.name,
                           playlist=self.playlist.name,
                           video=self.url_name,
                           _external=_external)
        elif action == 'delete':
            return url_for('video_delete',
                           channel=self.channel.name,
                           playlist=self.playlist.name,
                           video=self.url_name,
                           _external=_external)
        elif action == 'add-speaker':
            return url_for('video_add_speaker',
                           channel=channel.name,
                           playlist=playlist.name,
                           video=self.url_name,
                           _external=_external)
        elif action == 'remove-speaker':
            return url_for('video_remove_speaker',
                           channel=channel.name,
                           playlist=playlist.name,
                           video=self.url_name,
                           _external=_external)
        elif action == 'action':
            return url_for('video_action',
                           channel=channel.name,
                           playlist=playlist.name,
                           video=self.url_name,
                           _external=_external)

    def embed_video_for(self, action='view'):
        if self.video_source == u'youtube':
            if action == 'edit':
                return Markup(
                    '<iframe src="http://www.youtube.com/embed/%s?wmode=transparent&showinfo=0&rel=0&autohide=1&autoplay=0" frameborder="0" allowfullscreen></iframe>'
                    % self.video_sourceid)
            elif action == 'view':
                return Markup(
                    '<iframe src="http://www.youtube.com/embed/%s?wmode=transparent&showinfo=0&rel=0&autohide=1&autoplay=1" frameborder="0" allowfullscreen></iframe>'
                    % self.video_sourceid)
        return u''

    def embed_slides_for(self, action=None):
        if self.slides_source == u'speakerdeck':
            html = '<iframe src="http://www.speakerdeck.com/embed/%s" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>' % self.slides_sourceid
            return Markup(html)
        elif self.slides_source == u'slideshare':
            html = '<iframe src="http://www.slideshare.net/slideshow/embed_code/%s" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>' % self.slides_sourceid
            return Markup(html)
        return u''