def entity(id): id = str(id) event = musicbrainz.get_event_by_id(id) if not event: raise NotFound(gettext("Sorry, we couldn't find a event with that MusicBrainz ID.")) if 'artist-relation-list' in event and event['artist-relation-list']: artists_sorted = sorted(event['artist-relation-list'], key=itemgetter('type')) event['artists_grouped'] = groupby(artists_sorted, itemgetter('type')) if current_user.is_authenticated: my_reviews, my_count = Review.list(entity_id=id, entity_type='event', user_id=current_user.id) if my_count != 0: my_review = my_reviews[0] else: my_review = None else: my_review = None limit = int(request.args.get('limit', default=10)) offset = int(request.args.get('offset', default=0)) reviews, count = Review.list(entity_id=id, entity_type='event', sort='rating', limit=limit, offset=offset) return render_template('event/entity.html', id=id, event=event, reviews=reviews, my_review=my_review, limit=limit, offset=offset, count=count)
def entity(id): id = str(id) place = musicbrainz.get_place_by_id(id) if not place: raise NotFound( gettext( "Sorry, we couldn't find a place with that MusicBrainz ID.")) if current_user.is_authenticated: my_reviews, my_count = Review.list(entity_id=id, entity_type='place', user_id=current_user.id) if my_count != 0: my_review = my_reviews[0] else: my_review = None else: my_review = None limit = int(request.args.get('limit', default=10)) offset = int(request.args.get('offset', default=0)) reviews, count = Review.list(entity_id=id, entity_type='place', sort='rating', limit=limit, offset=offset) return render_template('place/entity.html', id=id, place=place, reviews=reviews, my_review=my_review, limit=limit, offset=offset, count=count)
def entity(id): id = str(id) event = musicbrainz.get_event_by_id(id) if not event: raise NotFound(gettext("Sorry, we couldn't find a event with that MusicBrainz ID.")) if 'artist-relation-list' in event and event['artist-relation-list']: artists_sorted = sorted(event['artist-relation-list'], key=itemgetter('type')) event['artists_grouped'] = groupby(artists_sorted, itemgetter('type')) if current_user.is_authenticated(): my_reviews, my_count = Review.list(entity_id=id, entity_type='event', user_id=current_user.id) if my_count != 0: my_review = my_reviews[0] else: my_review = None else: my_review = None limit = int(request.args.get('limit', default=10)) offset = int(request.args.get('offset', default=0)) reviews, count = Review.list(entity_id=id, entity_type='event', sort='rating', limit=limit, offset=offset) return render_template('event/entity.html', id=id, event=event, reviews=reviews, my_review=my_review, limit=limit, offset=offset, count=count)
def test_get_popular(self): reviews = Review.get_popular() self.assertEqual(len(reviews), 0) new_review = Review.create( user=self.user, release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"Testing!", is_draft=False, license_id=self.license.id) reviews = Review.get_popular() self.assertEqual(len(reviews), 1)
def entity(id): id = str(id) release_group = musicbrainz.get_release_group_by_id(id) if not release_group: raise NotFound( gettext( "Sorry, we couldn't find a release group with that MusicBrainz ID." )) if 'tag-list' in release_group: tags = release_group['tag-list'] else: tags = None if len(release_group['release-list']) > 0: release = musicbrainz.get_release_by_id( release_group['release-list'][0]['id']) else: release = None soundcloud_url = soundcloud.get_url(id) if soundcloud_url: spotify_mappings = None else: spotify_mappings = mbspotify.mappings(id) limit = int(request.args.get('limit', default=10)) offset = int(request.args.get('offset', default=0)) if current_user.is_authenticated: my_reviews, my_count = Review.list(entity_id=id, entity_type='release_group', user_id=current_user.id) if my_count != 0: my_review = my_reviews[0] else: my_review = None else: my_review = None reviews, count = Review.list(entity_id=id, entity_type='release_group', sort='rating', limit=limit, offset=offset) return render_template('release_group/entity.html', id=id, release_group=release_group, reviews=reviews, release=release, my_review=my_review, spotify_mappings=spotify_mappings, tags=tags, soundcloud_url=soundcloud_url, limit=limit, offset=offset, count=count)
def test_get_popular(self): reviews = Review.get_popular() self.assertEqual(len(reviews), 0) new_review = Review.create( user=self.user, release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"Testing!", is_draft=False, license_id=self.license.id ) reviews = Review.get_popular() self.assertEqual(len(reviews), 1)
def reviews(user_id): user_id = str(user_id) if current_user.is_authenticated and current_user.id == user_id: user = current_user else: user = User.query.get_or_404(user_id) page = int(request.args.get('page', default=1)) if page < 1: return redirect(url_for('.reviews')) limit = 12 offset = (page - 1) * limit reviews, count = Review.list(user_id=user_id, sort='created', limit=limit, offset=offset, inc_hidden=current_user.is_admin(), inc_drafts=current_user.is_authenticated and current_user.id == user_id) return render_template('user/reviews.html', section='reviews', user=user, reviews=reviews, page=page, limit=limit, count=count)
def setUp(self): super(VoteTestCase, self).setUp() author = User( db_users.get_or_create('0', new_user_data={ "display_name": "Author", })) self.user_1 = User( db_users.get_or_create('1', new_user_data={ "display_name": "Tester #1", })) self.user_2 = User( db_users.get_or_create('2', new_user_data={ "display_name": "Tester #2", })) license = License(id='Test', full_name='Test License') db.session.add(license) db.session.commit() self.review = Review.create( release_group='e7aad618-fa86-3983-9e77-405e21796eca', text="Testing!", user_id=author.id, is_draft=False, license_id=license.id)
def test_update(self): review = Review.create(user=self.user, release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"Awesome!", is_draft=True, license_id=self.license.id) another_license = License(id=u"License-2", full_name=u"Another license") db.session.add(another_license) db.session.commit() review.update(text=u"Bad...", is_draft=False, license_id=another_license.id, language='es') # Checking if contents are updated retrieved_review = Review.query.all()[0] self.assertEqual(retrieved_review.text, u"Bad...") self.assertFalse(retrieved_review.is_draft) self.assertEqual(retrieved_review.license_id, another_license.id) self.assertEqual(retrieved_review.language, 'es') # Updating should create a new revision. self.assertEqual(len(retrieved_review.revisions), 2) self.assertNotEqual(retrieved_review.revisions[0], retrieved_review.last_revision) # Let's try doing some things that shouldn't be allowed! with self.assertRaises(BadRequest): # like changing license... review.update(text=u"Sucks!", license_id=self.license.id) with self.assertRaises(BadRequest): # or converting review back to draft... review.update(text=u"Sucks!", is_draft=True)
def setUp(self): super(UserTestCase, self).setUp() self.user1 = User( db_users.get_or_create('tester_1', new_user_data={ "display_name": "test", })) self.user2 = User( db_users.get_or_create("тестер", new_user_data={ "display_name": "test1", })) self.author = User( db_users.get_or_create("author1", new_user_data={ "display_name": "Author1", })) license = License(id='Test', full_name='Test License') db.session.add(license) db.session.commit() self.review = Review.create( release_group='e7aad618-fa86-3983-9e77-405e21796eca', text="Testing!", user_id=self.author.id, is_draft=False, license_id=license.id, ) vote = db_vote.submit(self.user1.id, self.review.last_revision.id, True) self.review_created = self.review.last_revision.timestamp self.review_id = self.review.id self.revision_id = self.review.last_revision.id self.report = SpamReport.create(self.revision_id, self.user1.id, "Testing Reason Report")
def test_user_has_voted(self): # Review needs user user_1 = User(display_name=u'Tester #1') db.session.add(user_1) db.session.commit() # and license license = License(id=u"Test", full_name=u'Test License') db.session.add(license) db.session.commit() review = Review.create( user_id=user_1.id, release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"Testing!", is_draft=False, license_id=license.id) db.session.add(review) db.session.commit() user_2 = User(display_name=u'Tester #2') db.session.add(user_2) db.session.commit() self.assertFalse(user_2.has_voted(review)) Vote.create(user_2.id, review, True) self.assertTrue(user_2.has_voted(review))
def entity(id): """Artist page. Displays release groups (split up into several sections depending on their type), artist information (type, members/member of, external links). """ artist = musicbrainz.get_artist_by_id(id) if not artist: raise NotFound(gettext("Sorry, we couldn't find an artist with that MusicBrainz ID.")) # Note that some artists might not have a list of members because they are not a band band_members = _get_band_members(artist) release_type = request.args.get('release_type', default='album') if release_type not in ['album', 'single', 'ep', 'broadcast', 'other']: # supported release types raise BadRequest("Unsupported release type.") page = int(request.args.get('page', default=1)) if page < 1: return redirect(url_for('.reviews')) limit = 20 offset = (page - 1) * limit count, release_groups = musicbrainz.browse_release_groups(artist_id=id, release_types=[release_type], limit=limit, offset=offset) for release_group in release_groups: # TODO(roman): Count reviews instead of fetching them. reviews, review_count = Review.list(entity_id=release_group['id'], entity_type='release_group', sort='created', limit=1) release_group['review_count'] = review_count return render_template( 'artist.html', id=id, artist=artist, release_type=release_type, release_groups=release_groups, page=page, limit=limit, count=count, band_members=band_members )
def test_user_has_voted(self): # Review needs user user_1 = User(display_name=u'Tester #1') db.session.add(user_1) db.session.commit() # and license license = License(id=u"Test", full_name=u'Test License') db.session.add(license) db.session.commit() review = Review.create(user=user_1, release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"Testing!", is_draft=False, license_id=license.id) db.session.add(review) db.session.commit() user_2 = User(display_name=u'Tester #2') db.session.add(user_2) db.session.commit() self.assertFalse(user_2.has_voted(review)) Vote.create(user_2, review, True) self.assertTrue(user_2.has_voted(review))
def test_vote_create(self): # Preparing test data author = User.get_or_create(u'Author', musicbrainz_id=u'0') user_1 = User.get_or_create(u'Tester #1', musicbrainz_id=u'1') user_2 = User.get_or_create(u'Tester #2', musicbrainz_id=u'2') license = License(id=u'Test', full_name=u'Test License') db.session.add(license) db.session.commit() review = Review.create( release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"Testing!", user=author, is_draft=False, license_id=license.id) vote_u1_positive = Vote.create(user_1, review, True) votes = db.session.query(Vote).all() self.assertEqual(len(votes), 1) self.assertIn(vote_u1_positive, votes) vote_u2_negative = Vote.create(user_2, review, False) votes = db.session.query(Vote).all() self.assertEqual(len(votes), 2) self.assertIn(vote_u1_positive, votes) self.assertIn(vote_u2_negative, votes)
def test_created_property(self): review = Review.create(user=self.user, release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"Testing!", is_draft=False, license_id=self.license.id) self.assertEqual(review.created, review.revisions[0].timestamp)
def test_vote_create(self): # Preparing test data author = User.get_or_create(u'Author', musicbrainz_id=u'0') user_1 = User.get_or_create(u'Tester #1', musicbrainz_id=u'1') user_2 = User.get_or_create(u'Tester #2', musicbrainz_id=u'2') license = License(id=u'Test', full_name=u'Test License') db.session.add(license) db.session.commit() review = Review.create(release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"Testing!", user=author, is_draft=False, license_id=license.id) vote_u1_positive = Vote.create(user_1, review, True) votes = db.session.query(Vote).all() self.assertEqual(len(votes), 1) self.assertIn(vote_u1_positive, votes) vote_u2_negative = Vote.create(user_2, review, False) votes = db.session.query(Vote).all() self.assertEqual(len(votes), 2) self.assertIn(vote_u1_positive, votes) self.assertIn(vote_u2_negative, votes)
def browse(): page = int(request.args.get('page', default=1)) if page < 1: return redirect(url_for('.browse')) limit = 3 * 9 # 9 rows offset = (page - 1) * limit reviews, count = Review.list(sort='created', limit=limit, offset=offset) if not reviews: if page - 1 > count / limit: return redirect( url_for('review.browse', page=int(ceil(count / limit)))) else: raise NotFound(gettext("No reviews to display.")) # Loading info about entities for reviews entities = [(review.entity_id, review.entity_type) for review in reviews] entities_info = musicbrainz.get_multiple_entities(entities) return render_template('review/browse.html', reviews=reviews, entities=entities_info, page=page, limit=limit, count=count)
def json(location=os.path.join(os.getcwd(), 'export', 'json'), rotate=False): """Create JSON dumps with all reviews. This command will create an archive for each license available on CB. Archives will be put into a specified directory (default is *dump*). """ create_path(location) current_app.json_encoder = DumpJSONEncoder print("Creating new archives...") for license in License.query.all(): safe_name = slugify(license.id) with tarfile.open( os.path.join( location, "critiquebrainz-%s-%s-json.tar.bz2" % (datetime.today().strftime('%Y%m%d'), safe_name)), "w:bz2") as tar: temp_dir = tempfile.mkdtemp() license_dir = os.path.join(temp_dir, safe_name) create_path(license_dir) # Finding release groups that have reviews with current license query = db.session.query(Review.entity_id).group_by( Review.entity_id) for entity in query.all(): entity = entity[0] # Creating directory structure and dumping reviews dir_part = os.path.join(entity[0:1], entity[0:2]) reviews = Review.list(entity_id=entity, license_id=license.id)[0] if len(reviews) > 0: rg_dir = '%s/%s' % (license_dir, dir_part) create_path(rg_dir) f = open('%s/%s.json' % (rg_dir, entity), 'w+') f.write( jsonify(reviews=[r.to_dict() for r in reviews]).data) f.close() tar.add(license_dir, arcname='reviews') # Copying legal text tar.add(os.path.join("critiquebrainz", "data", "licenses", safe_name + ".txt"), arcname='COPYING') print(" + %s/critiquebrainz-%s-%s-json.tar.bz2" % (location, datetime.today().strftime('%Y%m%d'), safe_name)) shutil.rmtree(temp_dir) # Cleanup if rotate: print("Removing old sets of archives (except two latest)...") remove_old_archives(location, "critiquebrainz-[0-9]+-[-\w]+-json.tar.bz2", is_dir=False, sort_key=lambda x: os.path.getmtime(x)) print("Done!")
def index(): # Popular reviews popular_reviews = Review.get_popular(6) for review in popular_reviews: # Preparing text for preview preview = markdown(review['text'], safe_mode="escape") review['preview'] = ''.join(BeautifulSoup(preview, "html.parser").findAll(text=True)) # Recent reviews recent_reviews, _ = Review.list(sort='created', limit=9) # Statistics review_count = format_number(Review.get_count(is_draft = False)) user_count = format_number(User.get_count()) return render_template('index/index.html', popular_reviews=popular_reviews, recent_reviews=recent_reviews, reviews_total=review_count, users_total=user_count)
def test_created_property(self): review = Review.create( user=self.user, release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"Testing!", is_draft=False, license_id=self.license.id) self.assertEqual(review.created, review.revisions[0].timestamp)
def index(): # Popular reviews popular_reviews = Review.get_popular(6) for review in popular_reviews: # Preparing text for preview preview = markdown(review['text'], safe_mode="escape") review['preview'] = ''.join(BeautifulSoup(preview).findAll(text=True)) # Recent reviews recent_reviews, _ = Review.list(sort='created', limit=9) # Statistics # TODO(roman): Move these into models: review_count = format_number(Review.query.filter(Review.is_draft == False).count()) user_count = format_number(User.query.count()) return render_template('index.html', popular_reviews=popular_reviews, recent_reviews=recent_reviews, reviews_total=review_count, users_total=user_count)
def create_dummy_review(self, is_draft=False): review = Review.create( release_group="6b3cd75d-7453-39f3-86c4-1441f360e121", user_id=self.user.id, text=self.review_text, is_draft=is_draft, license_id=self.license.id, ) return review
def create(): for entity_type in ENTITY_TYPES: entity_id = request.args.get(entity_type) if entity_id: break if not entity_id: flash(gettext("Please choose an entity to review.")) return redirect(url_for('search.selector', next=url_for('.create'))) if current_user.is_blocked: flash( gettext("You are not allowed to write new reviews because your " "account has been blocked by a moderator."), 'error') return redirect(url_for('user.reviews', user_id=current_user.id)) # Checking if the user already wrote a review for this entity review = Review.query.filter_by(user=current_user, entity_id=entity_id).first() if review: flash(gettext("You have already published a review for this entity!"), 'error') return redirect(url_for('review.entity', id=review.id)) form = ReviewCreateForm(default_language=get_locale()) if form.validate_on_submit(): if current_user.is_review_limit_exceeded: flash(gettext("You have exceeded your limit of reviews per day."), 'error') return redirect(url_for('user.reviews', user_id=current_user.id)) is_draft = form.state.data == 'draft' review = Review.create(user=current_user, entity_id=entity_id, entity_type=entity_type, text=form.text.data, license_id=form.license_choice.data, language=form.language.data, is_draft=is_draft) if is_draft: flash(gettext("Review has been saved!"), 'success') else: flash(gettext("Review has been published!"), 'success') return redirect(url_for('.entity', id=review.id)) entity = musicbrainz.get_entity_by_id(entity_id, entity_type) if not entity: flash( gettext( "You can only write a review for an entity that exists on MusicBrainz!" ), 'error') return redirect(url_for('search.selector', next=url_for('.create'))) return render_template('review/write.html', form=form, entity_type=entity_type, entity=entity)
def create_dummy_review(self, is_draft=False): review = Review.create( release_group="6b3cd75d-7453-39f3-86c4-1441f360e121", user=self.user, text=self.review_text, is_draft=is_draft, license_id=self.license.id, ) return review
def test_review_deletion(self): review = Review.create(user=self.user, release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"Testing!", is_draft=False, license_id=self.license.id) self.assertEqual(Review.query.count(), 1) review.delete() self.assertEqual(Review.query.count(), 0)
def review_list_handler(): """Get list of reviews. :json uuid entity_id: UUID of the release group that is being reviewed :json string entity_type: One of the supported reviewable entities. 'release_group' or 'event' etc. **(optional)** :query user_id: user's UUID **(optional)** :query sort: ``rating`` or ``created`` **(optional)** :query limit: results limit, min is 0, max is 50, default is 50 **(optional)** :query offset: result offset, default is 0 **(optional)** :query language: language code (ISO 639-1) **(optional)** :resheader Content-Type: *application/json* """ # TODO: This checking is added to keep old clients working and needs to be removed. release_group = Parser.uuid('uri', 'release_group', optional=True) if release_group: entity_id = release_group entity_type = 'release_group' else: entity_id = Parser.uuid('uri', 'entity_id', optional=True) entity_type = Parser.string('uri', 'entity_type', valid_values=ENTITY_TYPES, optional=True) user_id = Parser.uuid('uri', 'user_id', optional=True) sort = Parser.string('uri', 'sort', valid_values=['rating', 'created'], optional=True) limit = Parser.int('uri', 'limit', min=1, max=50, optional=True) or 50 offset = Parser.int('uri', 'offset', optional=True) or 0 language = Parser.string('uri', 'language', min=2, max=3, optional=True) if language and language not in supported_languages: raise InvalidRequest(desc='Unsupported language') # TODO(roman): Ideally caching logic should live inside the model. Otherwise it # becomes hard to track all this stuff. cache_key = cache.gen_key('list', entity_id, user_id, sort, limit, offset, language) cached_result = cache.get(cache_key, Review.CACHE_NAMESPACE) if cached_result: reviews = cached_result['reviews'] count = cached_result['count'] else: reviews, count = Review.list( entity_id=entity_id, entity_type=entity_type, user_id=user_id, sort=sort, limit=limit, offset=offset, language=language, ) reviews = [p.to_dict() for p in reviews] cache.set(cache_key, { 'reviews': reviews, 'count': count, }, namespace=Review.CACHE_NAMESPACE) return jsonify(limit=limit, offset=offset, count=count, reviews=reviews)
def test_review_deletion(self): review = Review.create( user=self.user, release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"Testing!", is_draft=False, license_id=self.license.id) self.assertEqual(Review.query.count(), 1) review.delete() self.assertEqual(Review.query.count(), 0)
def test_languages(self): review_en = Review.create(user=self.user, release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"Testing!", is_draft=False, license_id=self.license.id, language='en') review_de = Review.create(user=self.user, release_group='e7aad618-fa86-3983-9e77-405e21796ece', text=u"Testing!", is_draft=False, license_id=self.license.id, language='de') reviews, count = Review.list(language='de') self.assertEqual(len(reviews), 1) self.assertEqual(count, 1) reviews, count = Review.list(language='ru') self.assertEqual(len(reviews), 0) self.assertEqual(count, 0)
def entity(id): id = str(id) place = musicbrainz.get_place_by_id(id) if not place: raise NotFound(gettext("Sorry, we couldn't find a place with that MusicBrainz ID.")) if current_user.is_authenticated(): my_reviews, my_count = Review.list(entity_id=id, entity_type='place', user_id=current_user.id) if my_count != 0: my_review = my_reviews[0] else: my_review = None else: my_review = None limit = int(request.args.get('limit', default=10)) offset = int(request.args.get('offset', default=0)) reviews, count = Review.list(entity_id=id, entity_type='place', sort='rating', limit=limit, offset=offset) return render_template('place/entity.html', id=id, place=place, reviews=reviews, my_review=my_review, limit=limit, offset=offset, count=count)
def test_list(self): reviews, count = Review.list() self.assertEqual(count, 0) self.assertEqual(len(reviews), 0) review = Review.create( user=self.user, release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"Awesome!", is_draft=False, license_id=self.license.id) reviews, count = Review.list() self.assertEqual(count, 1) self.assertEqual(len(reviews), 1) self.assertEqual(reviews[0].text, u"Awesome!") review.update(text=u"Beautiful!", ) reviews, count = Review.list() self.assertEqual(count, 1) self.assertEqual(len(reviews), 1) self.assertEqual(reviews[0].text, u"Beautiful!") reviews, count = Review.list(sort='rating') self.assertEqual(count, 1) self.assertEqual(len(reviews), 1) reviews, count = Review.list(sort='created') self.assertEqual(count, 1) self.assertEqual(len(reviews), 1)
def test_list(self): reviews, count = Review.list() self.assertEqual(count, 0) self.assertEqual(len(reviews), 0) review = Review.create( user=self.user, release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"Awesome!", is_draft=False, license_id=self.license.id ) reviews, count = Review.list() self.assertEqual(count, 1) self.assertEqual(len(reviews), 1) self.assertEqual(reviews[0].text, u"Awesome!") review.update( text=u"Beautiful!", ) reviews, count = Review.list() self.assertEqual(count, 1) self.assertEqual(len(reviews), 1) self.assertEqual(reviews[0].text, u"Beautiful!") reviews, count = Review.list(sort='rating') self.assertEqual(count, 1) self.assertEqual(len(reviews), 1) reviews, count = Review.list(sort='created') self.assertEqual(count, 1) self.assertEqual(len(reviews), 1)
def entity(id, rev=None): review = Review.query.get_or_404(str(id)) # Not showing review if it isn't published yet and not viewed by author. if review.is_draft and not (current_user.is_authenticated and current_user == review.user): raise NotFound(gettext("Can't find a review with the specified ID.")) if review.is_hidden: if not current_user.is_admin(): raise Forbidden( gettext("Review has been hidden. " "You need to be an administrator to view it.")) else: flash.warn(gettext("Review has been hidden.")) spotify_mappings = None soundcloud_url = None if review.entity_type == 'release_group': spotify_mappings = mbspotify.mappings(review.entity_id) soundcloud_url = soundcloud.get_url(review.entity_id) count = db_revision.get_count(id) if not rev: rev = count if rev < count: flash.info( gettext( 'You are viewing an old revision, the review has been updated since then.' )) elif rev > count: raise NotFound( gettext("The revision you are looking for does not exist.")) revision = db_revision.get(id, offset=count - rev)[0] if not review.is_draft and current_user.is_authenticated: # if user is logged in, get their vote for this review try: vote = db_vote.get(user_id=current_user.id, revision_id=revision['id']) except db_exceptions.NoDataFoundException: vote = None else: # otherwise set vote to None, its value will not be used vote = None review.text_html = markdown(revision['text'], safe_mode="escape") user_all_reviews, review_count = Review.list(user_id=review.user_id, sort="random", exclude=[review.id]) other_reviews = user_all_reviews[:3] return render_template('review/entity/%s.html' % review.entity_type, review=review, spotify_mappings=spotify_mappings, soundcloud_url=soundcloud_url, vote=vote, other_reviews=other_reviews)
def test_revisions(self): review = Review.create(user=self.user, release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"Awesome!", is_draft=False, license_id=self.license.id) self.assertEqual(len(review.revisions), 1) self.assertEqual(review.revisions[0], review.last_revision) # Updating should create a new revision. review.update(text=u"The worst!") self.assertEqual(len(review.revisions), 2) self.assertNotEqual(review.revisions[0], review.last_revision)
def test_review_creation(self): self.assertEqual(Review.query.count(), 0) review = Review.create(user=self.user, release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"Testing!", is_draft=False, license_id=self.license.id) reviews = Review.query.all() self.assertEqual(len(reviews), 1) self.assertEqual(reviews[0].id, review.id) self.assertEqual(reviews[0].entity_id, review.entity_id) self.assertEqual(reviews[0].license_id, review.license_id)
def test_languages(self): review_en = Review.create( user=self.user, release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"Testing!", is_draft=False, license_id=self.license.id, language='en') review_de = Review.create( user=self.user, release_group='e7aad618-fa86-3983-9e77-405e21796ece', text=u"Testing!", is_draft=False, license_id=self.license.id, language='de') reviews, count = Review.list(language='de') self.assertEqual(len(reviews), 1) self.assertEqual(count, 1) reviews, count = Review.list(language='ru') self.assertEqual(len(reviews), 0) self.assertEqual(count, 0)
def review_post_handler(user): """Publish a review. **OAuth scope:** review :reqheader Content-Type: *application/json* :json uuid entity_id: UUID of the release group that is being reviewed :json string entity_type: One of the supported reviewable entities. 'release_group' or 'event' etc. :json string text: review contents, min length is 25, max is 5000 :json string license_choice: license ID :json string lang: language code (ISO 639-1), default is ``en`` **(optional)** :json boolean is_draft: whether the review should be saved as a draft or not, default is ``False`` **(optional)** :resheader Content-Type: *application/json* """ def fetch_params(): is_draft = Parser.bool('json', 'is_draft', optional=True) or False if is_draft: REVIEW_MIN_LENGTH = None entity_id = Parser.uuid('json', 'entity_id') entity_type = Parser.string('json', 'entity_type', valid_values=ENTITY_TYPES) text = Parser.string('json', 'text', min=REVIEW_MIN_LENGTH, max=REVIEW_MAX_LENGTH) license_choice = Parser.string('json', 'license_choice') language = Parser.string( 'json', 'language', min=2, max=3, optional=True) or 'en' if language and language not in supported_languages: raise InvalidRequest(desc='Unsupported language') if Review.query.filter_by(user=user, entity_id=entity_id).count(): raise InvalidRequest( desc='You have already published a review for this album') return entity_id, entity_type, text, license_choice, language, is_draft if user.is_review_limit_exceeded: raise LimitExceeded('You have exceeded your limit of reviews per day.') entity_id, entity_type, text, license_choice, language, is_draft = fetch_params( ) review = Review.create(user=user, entity_id=entity_id, entity_type=entity_type, text=text, license_id=license_choice, language=language, is_draft=is_draft) return jsonify(message='Request processed successfully', id=review.id)
def setUp(self): super(VoteTestCase, self).setUp() author = User.get_or_create('Author', musicbrainz_id='0') self.user_1 = User.get_or_create('Tester #1', musicbrainz_id='1') self.user_2 = User.get_or_create('Tester #2', musicbrainz_id='2') license = License(id='Test', full_name='Test License') db.session.add(license) db.session.commit() self.review = Review.create( release_group='e7aad618-fa86-3983-9e77-405e21796eca', text="Testing!", user=author, is_draft=False, license_id=license.id)
def test_revisions(self): review = Review.create( user=self.user, release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"Awesome!", is_draft=False, license_id=self.license.id) self.assertEqual(len(review.revisions), 1) self.assertEqual(review.revisions[0], review.last_revision) # Updating should create a new revision. review.update(text=u"The worst!") self.assertEqual(len(review.revisions), 2) self.assertNotEqual(review.revisions[0], review.last_revision)
def entity(mbid): """Artist page. Displays release groups (split up into several sections depending on their type), artist information (type, members/member of, external links). """ artist = musicbrainz.get_artist_by_id(mbid) if not artist: raise NotFound( gettext( "Sorry, we couldn't find an artist with that MusicBrainz ID.")) # Note that some artists might not have a list of members because they are not a band band_members = _get_band_members(artist) release_type = request.args.get('release_type', default='album') if release_type not in ['album', 'single', 'ep', 'broadcast', 'other']: # supported release types raise BadRequest("Unsupported release type.") page = int(request.args.get('page', default=1)) if page < 1: return redirect(url_for('.reviews')) limit = 20 offset = (page - 1) * limit count, release_groups = musicbrainz.browse_release_groups( artist_id=mbid, release_types=[release_type], limit=limit, offset=offset) for release_group in release_groups: # TODO(roman): Count reviews instead of fetching them. reviews, review_count = Review.list(entity_id=release_group['id'], entity_type='release_group', sort='created', limit=1) release_group['review_count'] = review_count return render_template( 'artist/entity.html', id=mbid, artist=artist, release_type=release_type, release_groups=release_groups, page=page, limit=limit, count=count, band_members=band_members, )
def entity(id): """Artist page. Displays release groups (split up into several sections depending on their type), artist information (type, members/member of, external links). """ artist = musicbrainz.get_artist_by_id(id) if not artist: raise NotFound( gettext( "Sorry, we couldn't find an artist with that MusicBrainz ID.")) # Preparing artist-rels if 'band-members' in artist: artist['current_members'] = [] artist['former_members'] = [] for member in artist['band-members']: if 'ended' in member and member['ended'] == 'true': artist['former_members'].append(member) else: artist['current_members'].append(member) release_type = request.args.get('release_type', default='album') if release_type not in ['album', 'single', 'ep', 'broadcast', 'other']: # supported release types raise BadRequest("Unsupported release type.") page = int(request.args.get('page', default=1)) if page < 1: return redirect(url_for('.reviews')) limit = 20 offset = (page - 1) * limit count, release_groups = musicbrainz.browse_release_groups( artist_id=id, release_types=[release_type], limit=limit, offset=offset) for release_group in release_groups: # TODO(roman): Count reviews instead of fetching them. reviews, review_count = Review.list(entity_id=release_group['id'], entity_type='release_group', sort='created', limit=1) release_group['review_count'] = review_count return render_template('artist.html', id=id, artist=artist, release_type=release_type, release_groups=release_groups, page=page, limit=limit, count=count)
def setUp(self): super(RevisionTestCase, self).setUp() self.author = User.get_or_create('Author', musicbrainz_id='0') self.user_1 = User.get_or_create('Tester #1', musicbrainz_id='1') self.user_2 = User.get_or_create('Tester #2', musicbrainz_id='2') self.license = License(id=u'TEST', full_name=u"Test License") db.session.add(self.license) db.session.commit() self.review = Review.create( user_id=self.author.id, release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"Testing!", is_draft=False, license_id=self.license.id)
def entity(id): id = str(id) release_group = musicbrainz.get_release_group_by_id(id) if not release_group: raise NotFound(gettext("Sorry, we couldn't find a release group with that MusicBrainz ID.")) if len(release_group['release-list']) > 0: release = musicbrainz.get_release_by_id(release_group['release-list'][0]['id']) else: release = None spotify_mappings = mbspotify.mappings(id) limit = int(request.args.get('limit', default=10)) offset = int(request.args.get('offset', default=0)) if current_user.is_authenticated(): my_reviews, my_count = Review.list(entity_id=id, entity_type='release_group', user_id=current_user.id) if my_count != 0: my_review = my_reviews[0] else: my_review = None else: my_review = None reviews, count = Review.list(entity_id=id, entity_type='release_group', sort='rating', limit=limit, offset=offset) return render_template('release_group/entity.html', id=id, release_group=release_group, reviews=reviews, release=release, my_review=my_review, spotify_mappings=spotify_mappings, limit=limit, offset=offset, count=count)
def test_review_creation(self): self.assertEqual(Review.query.count(), 0) review = Review.create( user=self.user, release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"Testing!", is_draft=False, license_id=self.license.id) reviews = Review.query.all() self.assertEqual(len(reviews), 1) self.assertEqual(reviews[0].id, review.id) self.assertEqual(reviews[0].entity_id, review.entity_id) self.assertEqual(reviews[0].license_id, review.license_id)
def json(location=os.path.join(os.getcwd(), 'export', 'json'), rotate=False): """Create JSON dumps with all reviews. This command will create an archive for each license available on CB. Archives will be put into a specified directory (default is *dump*). """ create_path(location) current_app.json_encoder = DumpJSONEncoder print("Creating new archives...") for license in License.query.all(): safe_name = slugify(license.id) with tarfile.open(os.path.join(location, "critiquebrainz-%s-%s-json.tar.bz2" % (datetime.today().strftime('%Y%m%d'), safe_name)), "w:bz2") as tar: temp_dir = tempfile.mkdtemp() license_dir = os.path.join(temp_dir, safe_name) create_path(license_dir) # Finding release groups that have reviews with current license query = db.session.query(Review.entity_id).group_by(Review.entity_id) for entity in query.all(): entity = entity[0] # Creating directory structure and dumping reviews dir_part = os.path.join(entity[0:1], entity[0:2]) reviews = Review.list(entity_id=entity, license_id=license.id)[0] if len(reviews) > 0: rg_dir = '%s/%s' % (license_dir, dir_part) create_path(rg_dir) f = open('%s/%s.json' % (rg_dir, entity), 'w+') f.write(jsonify(reviews=[r.to_dict() for r in reviews]).data) f.close() tar.add(license_dir, arcname='reviews') # Copying legal text tar.add(os.path.join("critiquebrainz", "data", "licenses", safe_name + ".txt"), arcname='COPYING') print(" + %s/critiquebrainz-%s-%s-json.tar.bz2" % (location, datetime.today().strftime('%Y%m%d'), safe_name)) shutil.rmtree(temp_dir) # Cleanup if rotate: print("Removing old sets of archives (except two latest)...") remove_old_archives(location, "critiquebrainz-[0-9]+-[-\w]+-json.tar.bz2", is_dir=False, sort_key=lambda x: os.path.getmtime(x)) print("Done!")
def reviews(user_id): user_id = str(user_id) if current_user.is_authenticated() and current_user.id == user_id: user = current_user else: user = User.query.get_or_404(user_id) page = int(request.args.get('page', default=1)) if page < 1: return redirect(url_for('.reviews')) limit = 12 offset = (page - 1) * limit reviews, count = Review.list(user_id=user_id, sort='created', limit=limit, offset=offset, inc_hidden=current_user.is_admin(), inc_drafts=current_user.is_authenticated() and current_user.id == user_id) return render_template('user/reviews.html', section='reviews', user=user, reviews=reviews, page=page, limit=limit, count=count)
def setUp(self): super(RevisionTestCase, self).setUp() self.user = User(display_name=u'Tester') db.session.add(self.user) db.session.commit() self.license = License(id=u'TEST', full_name=u"Test License") db.session.add(self.license) db.session.commit() self.review = Review.create(user=self.user, release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"Testing!", is_draft=False, license_id=self.license.id)
def create(): for entity_type in ENTITY_TYPES: entity_id = request.args.get(entity_type) if entity_id: break if not entity_id: flash(gettext("Please choose an entity to review.")) return redirect(url_for('search.selector', next=url_for('.create'))) if current_user.is_blocked: flash(gettext("You are not allowed to write new reviews because your " "account has been blocked by a moderator."), 'error') return redirect(url_for('user.reviews', user_id=current_user.id)) # Checking if the user already wrote a review for this entity review = Review.query.filter_by(user=current_user, entity_id=entity_id).first() if review: flash(gettext("You have already published a review for this entity!"), 'error') return redirect(url_for('review.entity', id=review.id)) form = ReviewCreateForm(default_language=get_locale()) if form.validate_on_submit(): if current_user.is_review_limit_exceeded: flash(gettext("You have exceeded your limit of reviews per day."), 'error') return redirect(url_for('user.reviews', user_id=current_user.id)) is_draft = form.state.data == 'draft' review = Review.create(user=current_user, entity_id=entity_id, entity_type=entity_type, text=form.text.data, license_id=form.license_choice.data, language=form.language.data, is_draft=is_draft) if is_draft: flash(gettext("Review has been saved!"), 'success') else: flash(gettext("Review has been published!"), 'success') return redirect(url_for('.entity', id=review.id)) entity = musicbrainz.get_entity_by_id(entity_id, entity_type) if not entity: flash(gettext("You can only write a review for an entity that exists on MusicBrainz!"), 'error') return redirect(url_for('search.selector', next=url_for('.create'))) if entity_type == 'release_group': spotify_mappings = mbspotify.mappings(entity_id) return render_template('review/modify/write.html', form=form, entity_type=entity_type, entity=entity, spotify_mappings = spotify_mappings) return render_template('review/modify/write.html', form=form, entity_type=entity_type, entity=entity)
def setUp(self): super(SpamReportTestCase, self).setUp() # We need review and a couple of users to work with. self.reporter = User(display_name=u'Reporter') db.session.add(self.reporter) self.author = User(display_name=u'Author') db.session.add(self.author) self.license = License(id=u'Test', full_name=u'Test License') db.session.add(self.license) db.session.flush() self.review = Review.create(user=self.author, release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"It's... beautiful!", is_draft=False, license_id=self.license.id, language='en')
def setUp(self): super(ModerationLogCase, self).setUp() self.admin = User(display_name=u'Admin') db.session.add(self.admin) self.user = User(display_name=u'User') db.session.add(self.user) self.reason = "Testing Reason" self.license = License(id=u'Test', full_name=u'Test License') db.session.add(self.license) db.session.flush() self.review = Review.create(user=self.user, release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"It's... beautiful!", is_draft=False, license_id=self.license.id, language='en')
def setUp(self): super(ModerationLogCase, self).setUp() self.admin = User(display_name=u'Admin') db.session.add(self.admin) self.user = User(display_name=u'User') db.session.add(self.user) self.reason = "Testing Reason" self.license = License(id=u'Test', full_name=u'Test License') db.session.add(self.license) db.session.flush() self.review = Review.create(user_id=self.user.id, release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"It's... beautiful!", is_draft=False, license_id=self.license.id, language='en')
def browse(): page = int(request.args.get('page', default=1)) if page < 1: return redirect(url_for('.browse')) limit = 3 * 9 # 9 rows offset = (page - 1) * limit reviews, count = Review.list(sort='created', limit=limit, offset=offset) if not reviews: if page - 1 > count / limit: return redirect(url_for('review.browse', page=int(ceil(count/limit)))) else: raise NotFound(gettext("No reviews to display.")) # Loading info about entities for reviews entities = [(review.entity_id, review.entity_type) for review in reviews] entities_info = musicbrainz.get_multiple_entities(entities) return render_template('review/browse.html', reviews=reviews, entities=entities_info, page=page, limit=limit, count=count)
def test_reviews_property(self): user = User(display_name=u'Tester') db.session.add(user) db.session.commit() self.assertEqual(len(user.reviews), 0) license = License(id=u"Test", full_name=u'Test License') db.session.add(license) db.session.flush() review = Review.create(user=user, release_group='e7aad618-fa86-3983-9e77-405e21796eca', text=u"Testing!", is_draft=False, license_id=license.id) db.session.add(review) db.session.commit() self.assertEqual(len(user.reviews), 1) review.delete() self.assertEqual(len(user.reviews), 0)
def review_post_handler(user): """Publish a review. **OAuth scope:** review :reqheader Content-Type: *application/json* :json uuid entity_id: UUID of the release group that is being reviewed :json string entity_type: One of the supported reviewable entities. 'release_group' or 'event' etc. :json string text: review contents, min length is 25, max is 5000 :json string license_choice: license ID :json string lang: language code (ISO 639-1), default is ``en`` **(optional)** :json boolean is_draft: whether the review should be saved as a draft or not, default is ``False`` **(optional)** :resheader Content-Type: *application/json* """ def fetch_params(): is_draft = Parser.bool('json', 'is_draft', optional=True) or False if is_draft: REVIEW_MIN_LENGTH = None entity_id = Parser.uuid('json', 'entity_id') entity_type = Parser.string('json', 'entity_type', valid_values=ENTITY_TYPES) text = Parser.string('json', 'text', min=REVIEW_MIN_LENGTH, max=REVIEW_MAX_LENGTH) license_choice = Parser.string('json', 'license_choice') language = Parser.string('json', 'language', min=2, max=3, optional=True) or 'en' if language and language not in supported_languages: raise InvalidRequest(desc='Unsupported language') if Review.query.filter_by(user=user, entity_id=entity_id).count(): raise InvalidRequest(desc='You have already published a review for this album') return entity_id, entity_type, text, license_choice, language, is_draft if user.is_review_limit_exceeded: raise LimitExceeded('You have exceeded your limit of reviews per day.') entity_id, entity_type, text, license_choice, language, is_draft = fetch_params() review = Review.create(user=user, entity_id=entity_id, entity_type=entity_type, text=text, license_id=license_choice, language=language, is_draft=is_draft) return jsonify(message='Request processed successfully', id=review.id)
def create_dummy_review(self): return Review.create(**self.review)
def review(self): return Review.get(id=self.review_id)