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 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, }
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
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)
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
def test_audiodesc_video_url_media(self): """Media with both Audio files and Video files attatched should be Video type.""" try: # Create the media object media = self._new_publishable_media(u'description-video', u'(Audio Description + Video)') DBSession.add(media) # Add an audio description media_file = add_new_media_file(media, None, u'http://fakesite.com/fakefile.mp3') media_file.type = AUDIO_DESC media.update_status() # Add a video file media_file = add_new_media_file(media, None, u'http://fakesite.com/fakefile.m4v') media.update_status() # Commit + test DBSession.commit() assert media.type == VIDEO, \ "A Media object with a .m4v file and an Audio Description " \ "was not labelled as a video type; it was labelled %s" % \ (t, media.type) except SQLAlchemyError, e: DBSession.rollback() raise e
def rate(self, slug, rating=1, **kwargs): """Rate up or down the given media. :param slug: The media :attr:`~mediacore.model.media.Media.slug` :param rating: ``1`` or ``0`` if the rating is up or down. :rtype: JSON dict :returns: succcess bool upRating Pluralized count of up raters, "# people" or "1 person" downRating Pluralized count of down raters, "# people" or "1 person" """ media = fetch_row(Media, slug=slug) if rating > 0: media.rating.add_vote(1) else: media.rating.add_vote(0) DBSession.add(media) if request.is_xhr: return dict( success = True, upRating = helpers.text.plural(media.rating.sum, 'person', 'people'), downRating = None, ) else: redirect(action='view')
def test_audiodesc_video_url_media(self): """Media with both Audio files and Video files attatched should be Video type.""" try: # Create the media object media = self._new_publishable_media( u'description-video', u'(Audio Description + Video)') DBSession.add(media) # Add an audio description media_file = add_new_media_file( media, None, u'http://fakesite.com/fakefile.mp3') media_file.type = AUDIO_DESC media.update_status() # Add a video file media_file = add_new_media_file( media, None, u'http://fakesite.com/fakefile.m4v') media.update_status() # Commit + test DBSession.commit() assert media.type == VIDEO, \ "A Media object with a .m4v file and an Audio Description " \ "was not labelled as a video type; it was labelled %s" % \ (t, media.type) except SQLAlchemyError, e: DBSession.rollback() raise e
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
def comment(self, slug, **values): """Post a comment from :class:`~mediacore.forms.media.PostCommentForm`. :param slug: The media :attr:`~mediacore.model.media.Media.slug` :returns: Redirect to :meth:`view` page for media. """ if tmpl_context.form_errors: if request.is_xhr: return dict( success = False, errors = tmpl_context.form_errors ) else: redirect(action='view') media = fetch_row(Media, slug=slug) c = Comment() c.status = 'unreviewed' c.author = AuthorWithIP(values['name'], None, request.environ['REMOTE_ADDR']) c.subject = 'Re: %s' % media.title c.body = helpers.clean_xhtml(values['body']) media.comments.append(c) DBSession.add(media) email.send_comment_notification(media, c) if request.is_xhr: return dict(success = True) else: redirect(action='view')
def main(parser, options, args): app_globs = app_globals._current_obj() app_id = app_globals.settings['facebook_appid'] if not app_id: print 'No Facebook app_id configured, exiting' sys.exit(3) app_secret = options.app_secret fb = FacebookAPI(app_id, app_secret) from mediacore.model import DBSession, Media # eager loading of 'meta' to speed up later check. all_media = Media.query.options(joinedload('_meta')).all() print 'Checking all media for existing Facebook comments' progress = ProgressBar(maxval=len(all_media)).start() for i, media in enumerate(all_media): progress.update(i + 1) if 'facebook-comment-xid' not in media.meta: continue if not fb.has_xid_comments(media): continue media.meta[u'facebook-comment-xid'] = unicode(media.id) DBSession.add(media) DBSession.commit() progress.finish()
def main(parser, options, args): app_globs = app_globals._current_obj() app_id = app_globals.settings['facebook_appid'] if not app_id: print 'No Facebook app_id configured, exiting' sys.exit(3) app_secret = options.app_secret fb = FacebookAPI(app_id, app_secret) from mediacore.model import DBSession, Media # eager loading of 'meta' to speed up later check. all_media = Media.query.options(joinedload('_meta')).all() print 'Checking all media for existing Facebook comments' progress = ProgressBar(maxval=len(all_media)).start() for i, media in enumerate(all_media): progress.update(i+1) if 'facebook-comment-xid' not in media.meta: continue if not fb.has_xid_comments(media): continue media.meta[u'facebook-comment-xid'] = unicode(media.id) DBSession.add(media) DBSession.commit() progress.finish()
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 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, }
def save(self, id, delete, category='topics', **kwargs): """Save changes or create a topic or tag. See :class:`~mediacore.forms.categories.EditCategoryForm` for POST vars. :param id: Topic or tag ID :param category: ``topics`` or ``tags`` :param delete: If true the category is deleted rather than saved. :type delete: bool :rtype: JSON dict :returns: success bool category ``topics`` or ``tags`` """ model = self.select_model(category) item = fetch_row(model, id) if delete: DBSession.delete(item) item = None else: item.name = kwargs['name'] item.slug = get_available_slug(model, kwargs['slug'], item) DBSession.add(item) if request.is_xhr: return dict(success=True, category=item) else: redirect(action='index', category=category)
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 _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 save_media_obj(author_name, author_email, title, description, tags, file, url): media = Media() media.author = Author(author_name, author_email) media.title = title media.description = description media.tags = tags add_new_media_file(media, file=file, url=url) DBSession.add(media) DBSession.commit() return media
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 comment(self, slug, **values): """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. """ akismet_key = helpers.fetch_setting('akismet_key') akismet_url = helpers.fetch_setting('akismet_url') if akismet_key: akismet = Akismet(agent='MediaCore/%s' % MEDIACORE_VERSION) akismet.key = akismet_key akismet.blog_url = akismet_url or url_for('/', qualified=True) akismet.verify_key() data = {'comment_author': values['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(values['body'].encode('utf-8'), data): title = "Comment Rejected" text = "Your comment appears to be spam and has been rejected." add_transient_message('comment_posted', title, text) redirect(action='view', anchor='top') media = fetch_row(Media, slug=slug) c = Comment() c.author = AuthorWithIP( values['name'], values['email'], request.environ['REMOTE_ADDR'] ) c.subject = 'Re: %s' % media.title c.body = values['body'] require_review = asbool(helpers.fetch_setting('req_comment_approval')) if not require_review: c.reviewed = True c.publishable = True media.comments.append(c) DBSession.add(media) email.send_comment_notification(media, c) if require_review: title = "Thanks for your comment!" text = "We will post it just as soon as a moderator approves it." add_transient_message('comment_posted', title, text) redirect(action='view', anchor='top') else: redirect(action='view', anchor='comment-%s' % c.id)
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) media.increment_views() DBSession.add(media) 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: related = Media.query.published()\ .options(orm.undefer('comment_count_published'))\ .filter(Media.id != media.id)\ .search('>(%s) <(%s)' % (media.title, media.fulltext.tags))[:6] else: related = [] return dict( media = media, related_media = related, 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, )
def test_add_file_url(self): slug = u'test-add-file-url' title = u'Test Adding File by URL on Media Edit Page.' try: media = self._new_publishable_media(slug, title) media.publishable = False media.reviewed = False DBSession.add(media) DBSession.commit() media_id = media.id except SQLAlchemyError, e: DBSession.rollback() raise e
def test_add_file_url(self): slug = u'test-add-file-url' title = u'Test Adding File by URL on Media Edit Page.' try: media = self._new_publishable_media(slug, title) media.publishable = False media.reviewed = False DBSession.add(media) DBSession.commit() media_id = media.id except SQLAlchemyError, e: DBSession.rollback() raise e
def save(self, id, **kwargs): player = fetch_row(PlayerPrefs, id) form = player.settings_form if id == 'new': DBSession.add(player) @validate(form, error_handler=self.edit) def save(id, **kwargs): # Allow the form to modify the player directly # since each can have radically different fields. save_func = getattr(form, 'save_data') save_func(player, **tmpl_context.form_values) redirect(controller='/admin/players', action='index') return save(id, **kwargs)
def save(self, id, **kwargs): player = fetch_row(PlayerPrefs, id) form = player.settings_form if id == 'new': DBSession.add(player) @validate(form, error_handler=self.edit) def save(id, **kwargs): # Allow the form to modify the player directly # since each can have radically different fields. save_func = getattr(form, 'save_data') save_func(player, **tmpl_context.form_values) redirect(controller='/admin/players', action='index') return save(id, **kwargs)
def rate(self, slug, **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) likes = media.increment_likes() DBSession.add(media) if request.is_xhr: return unicode(likes) else: redirect(action='view')
def _get_media(self, unique): """Return the media/mediafiles required for the Helpers tests""" try: media = self._new_publishable_media(u'media-selection-%s' % unique, u'Media Selection Test (%s)' % unique) DBSession.add(media) media_files = {} for t in ['oga', 'ogv', 'm4a', 'm4v', 'flv', 'mp3', 'xml']: media_files[t] = add_new_media_file(media, None, u'http://fakesite.com/fakefile.%s' % t) media_files['youtube'] = add_new_media_file(media, None, u'http://www.youtube.com/watch?v=3RsbmjNLQkc') media.update_status() DBSession.commit() except SQLAlchemyError, e: DBSession.rollback() raise e
def test_captioned_url_media(self): """Media with only subtitles attatched should be None type.""" try: for t in self.caption_types: media = self._new_publishable_media(u'caption-%s' % t, u'%s (Captioned)' % t.upper()) DBSession.add(media) media_file = add_new_media_file(media, None, u'http://fakesite.com/fakefile.%s' % t) media.update_status() DBSession.commit() assert media.type == None, \ "A Media object with only an .%s file associated was " \ "not labelled as a 'None' type; it was labelled %s" % \ (t, media.type) except SQLAlchemyError, e: DBSession.rollback() raise e
def test_captioned_url_media(self): """Media with only subtitles attatched should be None type.""" try: for t in self.caption_types: media = self._new_publishable_media( u'caption-%s' % t, u'%s (Captioned)' % t.upper()) DBSession.add(media) media_file = add_new_media_file( media, None, u'http://fakesite.com/fakefile.%s' % t) media.update_status() DBSession.commit() assert media.type == None, \ "A Media object with only an .%s file associated was " \ "not labelled as a 'None' type; it was labelled %s" % \ (t, media.type) except SQLAlchemyError, e: DBSession.rollback() raise e
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')
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')
def test_audio_description_url_media(self): """Media with only Audio Descriptions attatched should be None type.""" try: for t in self.audio_types: media = self._new_publishable_media(u'description-%s' % t, u'%s (Audio Description)' % t.upper()) DBSession.add(media) media_file = add_new_media_file(media, None, u'http://fakesite.com/fakefile.%s' % t) media_file.type = AUDIO_DESC media.update_status() DBSession.commit() assert media.type == None, \ "A Media object with only an Audio Description file " \ "associated was not labelled as a None type; it " \ "was labelled %s" % (t, media.type) except SQLAlchemyError, e: DBSession.rollback() raise e
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)
def save(self, id, engine_type=None, **kwargs): if id == 'new': assert engine_type is not None, 'engine_type must be specified when saving a new StorageEngine.' engine = self.fetch_engine(id, engine_type) form = engine.settings_form if id == 'new': DBSession.add(engine) @validate(form, error_handler=self.edit) def save_engine_params(id, general, **kwargs): # Allow the form to modify the StorageEngine directly # since each can have radically different fields. save_func = getattr(form, 'save_engine_params') save_func(engine, **tmpl_context.form_values) redirect(controller='/admin/storage', action='index') return save_engine_params(id, **kwargs)
def save(self, id, engine_type=None, **kwargs): if id == 'new': assert engine_type is not None, 'engine_type must be specified when saving a new StorageEngine.' engine = self.fetch_engine(id, engine_type) form = engine.settings_form if id == 'new': DBSession.add(engine) @validate(form, error_handler=self.edit) def save_engine_params(id, general, **kwargs): # Allow the form to modify the StorageEngine directly # since each can have radically different fields. save_func = getattr(form, 'save_engine_params') save_func(engine, **tmpl_context.form_values) redirect(controller='/admin/storage', action='index') return save_engine_params(id, **kwargs)
def inject_in_db(cls, enable_player=False): from mediacore.model import DBSession from mediacore.model.players import players as players_table, PlayerPrefs prefs = PlayerPrefs() prefs.name = cls.name prefs.enabled = enable_player # didn't get direct SQL expression to work with SQLAlchemy # player_table = sql.func.max(player_table.c.priority) query = sql.select([sql.func.max(players_table.c.priority)]) max_priority = DBSession.execute(query).first()[0] if max_priority is None: max_priority = -1 prefs.priority = max_priority + 1 prefs.created_on = datetime.now() prefs.modified_on = datetime.now() prefs.data = cls.default_data DBSession.add(prefs) DBSession.commit()
def inject_in_db(cls, enable_player=False): from mediacore.model import DBSession from mediacore.model.players import players as players_table, PlayerPrefs prefs = PlayerPrefs() prefs.name = cls.name prefs.enabled = enable_player # didn't get direct SQL expression to work with SQLAlchemy # player_table = sql.func.max(player_table.c.priority) query = sql.select([sql.func.max(players_table.c.priority)]) max_priority = DBSession.execute(query).first()[0] if max_priority is None: max_priority = -1 prefs.priority = max_priority + 1 prefs.created_on = datetime.now() prefs.modified_on = datetime.now() prefs.data = cls.default_data DBSession.add(prefs) DBSession.commit()
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 ids: An optional string of IDs separated by commas. :type ids: ``unicode`` or ``None`` :param status: ``"approve"`` or ``"trash"`` depending on what action the user requests. :rtype: JSON dict :returns: success bool ids A list of :attr:`~mediacore.model.comments.Comment.id` that have changed. """ if id == 'bulk': ids = ids.split(',') else: ids = [id] approve = status == 'approve' comments = DBSession.query(Comment)\ .filter(Comment.id.in_(ids))\ .all() for comment in comments: if approve: comment.status.discard('unreviewed') comment.status.add('publish') else: comment.status.add('trash') DBSession.add(comment) if request.is_xhr: return dict(success=True, ids=ids) else: redirect(action='index')
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)
def save_edit(self, id, body, **kwargs): """Save an edit from :class:`~mediacore.forms.comments.EditCommentForm`. :param id: Comment ID :type id: ``int`` :rtype: JSON dict :returns: success bool body The edited comment body after validation/filtering """ comment = fetch_row(Comment, id) comment.body = helpers.clean_xhtml(body) DBSession.add(comment) return dict( success = True, body = comment.body, )
def test_edit_media(self): title = u'Edit Existing Media Test' slug = u'edit-existing-media-test' # this should be unique # Values that we will change during the edit process name = u'Frederick Awesomeson' email = u'*****@*****.**' description = u'This media item was created to test the "admin/media/edit/someID" method' htmlized_description = '<p>This media item was created to test the "admin/media/edit/someID" method</p>' notes = u'Some Notes!' try: media = self._new_publishable_media(slug, title) media.publishable = False media.reviewed = False DBSession.add(media) DBSession.commit() media_id = media.id except SQLAlchemyError, e: DBSession.rollback() raise e
def test_edit_media(self): title = u'Edit Existing Media Test' slug = u'edit-existing-media-test' # this should be unique # Values that we will change during the edit process name = u'Frederick Awesomeson' email = u'*****@*****.**' description = u'This media item was created to test the "admin/media/edit/someID" method' htmlized_description = '<p>This media item was created to test the "admin/media/edit/someID" method</p>' notes = u'Some Notes!' try: media = self._new_publishable_media(slug, title) media.publishable = False media.reviewed = False DBSession.add(media) DBSession.commit() media_id = media.id except SQLAlchemyError, e: DBSession.rollback() raise e
def save(self, id, engine_type=None, **kwargs): if id == "new": assert engine_type is not None, "engine_type must be specified when saving a new StorageEngine." engine_class = [x for x in StorageEngine if x.engine_type == engine_type][0] else: engine_class = StorageEngine engine = fetch_row(engine_class, id) form = engine.settings_form if id == "new": DBSession.add(engine) @validate(form, error_handler=self.edit) def save_engine_params(id, general, **kwargs): # Allow the form to modify the StorageEngine directly # since each can have radically different fields. save_func = getattr(form, "save_engine_params") save_func(engine, **tmpl_context.form_values) redirect(controller="/admin/storage", action="index") return save_engine_params(id, **kwargs)
def add_default_data(): log.info('Adding default data') settings = [ (u'email_media_uploaded', None), (u'email_comment_posted', None), (u'email_support_requests', None), (u'email_send_from', u'noreply@localhost'), (u'wording_user_uploads', N_(u"Upload your media using the form below. We'll review it and get back to you." )), (u'wording_administrative_notes', None), (u'wording_display_administrative_notes', u''), (u'popularity_decay_exponent', u'4'), (u'popularity_decay_lifetime', u'36'), (u'rich_text_editor', u'tinymce'), (u'google_analytics_uacct', u''), (u'featured_category', u'1'), (u'max_upload_size', u'314572800'), (u'ftp_storage', u'false'), (u'ftp_server', u'ftp.someserver.com'), (u'ftp_user', u'username'), (u'ftp_password', u'password'), (u'ftp_upload_directory', u'media'), (u'ftp_download_url', u'http://www.someserver.com/web/accessible/media/'), (u'ftp_upload_integrity_retries', u'10'), (u'akismet_key', u''), (u'akismet_url', u''), (u'req_comment_approval', u''), (u'use_embed_thumbnails', u'true'), (u'api_secret_key_required', u'true'), (u'api_secret_key', random_string(20)), (u'api_media_max_results', u'50'), (u'api_tree_max_depth', u'10'), (u'general_site_name', u'MediaCore'), (u'general_site_title_display_order', u'prepend'), (u'sitemaps_display', u'True'), (u'rss_display', u'True'), (u'vulgarity_filtered_words', u''), (u'primary_language', u'en'), (u'advertising_banner_html', u''), (u'advertising_sidebar_html', u''), (u'comments_engine', u'mediacore'), (u'facebook_appid', u''), ] settings.extend(appearance_settings) for key, value in settings: s = Setting() s.key = key s.value = value DBSession.add(s) admin_user = User() admin_user.user_name = u'admin' admin_user.display_name = u'Admin' admin_user.email_address = u'*****@*****.**' admin_user.password = u'admin' DBSession.add(admin_user) admin_group = Group() admin_group.group_name = u'admins' admin_group.display_name = u'Admins' admin_group.users.append(admin_user) DBSession.add(admin_group) editor_group = Group() editor_group.group_name = u'editors' editor_group.display_name = u'Editors' DBSession.add(editor_group) admin_perm = Permission() admin_perm.permission_name = u'admin' admin_perm.description = u'Grants access to the admin panel' admin_perm.groups.append(admin_group) DBSession.add(admin_perm) edit_perm = Permission() edit_perm.permission_name = u'edit' edit_perm.description = u'Grants access to edit site content' edit_perm.groups.append(admin_group) edit_perm.groups.append(editor_group) DBSession.add(edit_perm) category = Category() category.name = u'Featured' category.slug = u'featured' DBSession.add(category) category2 = Category() category2.name = u'Instructional' category2.slug = u'instructional' DBSession.add(category2) podcast = Podcast() podcast.slug = u'hello-world' podcast.title = u'Hello World' podcast.subtitle = u'My very first podcast!' podcast.description = u"""<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>""" podcast.category = u'Technology' podcast.author = Author(admin_user.display_name, admin_user.email_address) podcast.explicit = None podcast.copyright = u'Copyright 2009 Xyz' podcast.itunes_url = None podcast.feedburner_url = None DBSession.add(podcast) comment = Comment() comment.subject = u'Re: New Media' comment.author = AuthorWithIP(name=u'John Doe', ip=2130706433) comment.body = u'<p>Hello to you too!</p>' DBSession.add(comment) media = Media() media.type = None media.slug = u'new-media' media.reviewed = True media.encoded = False media.publishable = False media.title = u'New Media' media.subtitle = None media.description = u"""<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>""" media.description_plain = u"""Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.""" media.author = Author(admin_user.display_name, admin_user.email_address) media.categories.append(category) media.comments.append(comment) DBSession.add(media) #XXX The list of default players is actually defined in model.players # and should at some point be moved here to avoid inconsistency # between the default storage engines and default players. remote_url_storage = RemoteURLStorage() default_engines = [ LocalFileStorage(), remote_url_storage, YoutubeStorage(), VimeoStorage(), BlipTVStorage(), DailyMotionStorage(), GoogleVideoStorage(), ] for engine in default_engines: DBSession.add(engine) import datetime instructional_media = [ ( u'workflow-in-mediacore', u'Workflow in MediaCore', u'<p>This sceencast explains the publish status feature in MediaCore.</p><p>Initially all videos uploaded through the front-end or admin panel are placed under "awaiting review" status. Once the administrator hits the "review complete" button, they can upload media. Videos can be added in any format, however, they can only be published if they are in a web-ready format such as FLV, M4V, MP3, or MP4. Alternatively, if they are published through Youtube or Vimeo the encoding step is skipped</p><p>Once uploaded and encoded the administrator can then publish the video.</p>', u'This sceencast explains the publish status feature in MediaCore.\nInitially all videos uploaded through the front-end or admin panel are placed under \"awaiting review\" status. Once the administrator hits the \"review complete\" button, they can upload media. Videos can be added in any format, however, they can only be published if they are in a web-ready format such as FLV, M4V, MP3, or MP4. Alternatively, if they are published through Youtube or Vimeo the encoding step is skipped\nOnce uploaded and encoded the administrator can then publish the video.', datetime.datetime(2010, 5, 13, 2, 29, 40), 218, u'http://getmediacore.com/files/tutorial-workflow-in-mediacore.mp4', u'video', u'mp4', ), ( u'creating-a-podcast-in-mediacore', u'Creating a Podcast in MediaCore', u'<p>This describes the process an administrator goes through in creating a podcast in MediaCore. An administrator can enter information that will automatically generate the iTunes/RSS feed information. Any episodes published to a podcast will automatically publish to iTunes/RSS.</p>', u'This describes the process an administrator goes through in creating a podcast in MediaCore. An administrator can enter information that will automatically generate the iTunes/RSS feed information. Any episodes published to a podcast will automatically publish to iTunes/RSS.', datetime.datetime(2010, 5, 13, 2, 33, 44), 100, u'http://getmediacore.com/files/tutorial-create-podcast-in-mediacore.mp4', u'video', u'mp4', ), ( u'adding-a-video-in-mediacore', u'Adding a Video in MediaCore', u'<p>This screencast shows how video or audio can be added in MediaCore.</p><p>MediaCore supports a wide range of formats including (but not limited to): YouTube, Vimeo, Google Video, Amazon S3, Bits on the Run, BrightCove, Kaltura, and either your own server or someone else\'s.</p><p>Videos can be uploaded in any format, but can only be published in web-ready formats such as FLV, MP3, M4V, MP4 etc.</p>', u'This screencast shows how video or audio can be added in MediaCore.\nMediaCore supports a wide range of formats including (but not limited to): YouTube, Vimeo, Google Video, Amazon S3, Bits on the Run, BrightCove, Kaltura, and either your own server or someone else\'s.\nVideos can be uploaded in any format, but can only be published in web-ready formats such as FLV, MP3, M4V, MP4 etc.', datetime.datetime(2010, 5, 13, 02, 37, 36), 169, u'http://getmediacore.com/files/tutorial-add-video-in-mediacore.mp4', u'video', u'mp4', ), ] name = u'MediaCore Team' email = u'*****@*****.**' for slug, title, desc, desc_plain, publish_on, duration, url, type_, container in instructional_media: media = Media() media.author = Author(name, email) media.description = desc media.description_plain = desc_plain media.duration = duration media.publish_on = publish_on media.slug = slug media.title = title media.type = type_ media_file = MediaFile() media_file.container = container media_file.created_on = publish_on media_file.display_name = os.path.basename(url) media_file.duration = duration media_file.type = type_ media_file.storage = remote_url_storage media_file.unique_id = url DBSession.add(media) DBSession.add(media_file) media.files.append(media_file) media.categories.append(category2) media.encoded = True media.reviewed = True media.publishable = True