def fetch_params(): is_draft = Parser.bool('json', 'is_draft', optional=True) or False if is_draft: REVIEW_TEXT_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_TEXT_MIN_LENGTH, max=REVIEW_TEXT_MAX_LENGTH, optional=True) rating = Parser.int('json', 'rating', min=REVIEW_RATING_MIN, max=REVIEW_RATING_MAX, optional=True) license_choice = Parser.string('json', 'license_choice') language = Parser.string( 'json', 'language', min=2, max=3, optional=True) or 'en' if text is None and rating is None: raise InvalidRequest(desc='Review must have either text or rating') if language and language not in supported_languages: raise InvalidRequest(desc='Unsupported language') if db_review.list_reviews(user_id=user.id, entity_id=entity_id)[1]: raise InvalidRequest( desc='You have already published a review for this album') return entity_id, entity_type, text, rating, license_choice, language, is_draft
def review_vote_put_handler(review_id, user): """Set your vote for a specified review. **OAuth scope:** vote :json boolean vote: ``true`` if upvote, ``false`` if downvote :statuscode 200: success :statuscode 400: invalid request (see source) :statuscode 403: daily vote limit exceeded :statuscode 404: review not found :resheader Content-Type: *application/json* """ def fetch_params(): vote = Parser.bool('json', 'vote') return vote review = Review.query.get_or_404(str(review_id)) if review.is_hidden: raise NotFound("Review has been hidden.") vote = fetch_params() if review.user_id == user.id: raise InvalidRequest(desc='You cannot rate your own review.') if user.is_vote_limit_exceeded is True and user.has_voted(review) is False: raise LimitExceeded('You have exceeded your limit of votes per day.') if vote is True and user.user_type not in review.review_class.upvote: raise InvalidRequest(desc='You are not allowed to upvote this review.') if vote is False and user.user_type not in review.review_class.downvote: raise InvalidRequest(desc='You are not allowed to downvote this review.') Vote.create(user, review, vote) # overwrites an existing vote, if needed return jsonify(message='Request processed successfully')
def review_vote_put_handler(review_id, user): """Set your vote for a specified review. **OAuth scope:** vote **Request Example:** .. code-block:: bash $ curl "https://critiquebrainz.org/ws/1/review/9cb11424-d070-4ac1-8771-a8703ae5cccd/vote" \\ -X PUT \\ -H "Content-type: application/json" \\ -H "Authorization: Bearer <access token>" \\ -d '{"vote":true}' **Response Example:** .. code-block:: json { "message": "Request processed successfully" } :json boolean vote: ``true`` if upvote, ``false`` if downvote **NOTE:** Voting on reviews without text is not allowed. :statuscode 200: success :statuscode 400: invalid request (see source) :statuscode 403: daily vote limit exceeded :statuscode 404: review not found :resheader Content-Type: *application/json* """ def fetch_params(): vote = Parser.bool('json', 'vote') return vote review = get_review_or_404(review_id) if review["is_hidden"]: raise NotFound("Review has been hidden.") vote = fetch_params() if str(review["user_id"]) == user.id: raise InvalidRequest(desc='You cannot rate your own review.') if review["text"] is None: raise InvalidRequest( desc='Voting on reviews without text is not allowed.') if user.is_vote_limit_exceeded and not db_users.has_voted( user.id, review_id): raise LimitExceeded('You have exceeded your limit of votes per day.') db_vote.submit( user_id=user.id, revision_id=review["last_revision"]["id"], vote=vote, # overwrites an existing vote, if needed ) return jsonify(message='Request processed successfully')
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
def review_vote_delete_handler(review_id, user): """Delete your vote for a specified review. **OAuth scope:** vote **Request Example:** .. code-block:: bash $ curl "https://critiquebrainz.org/ws/1/review/9cb11424-d070-4ac1-8771-a8703ae5cccd/vote" \\ -X DELETE \\ -H "Authorization: Bearer <access token>" **Response Example:** .. code-block:: json { "message": "Request processed successfully" } :resheader Content-Type: *application/json* """ review = get_review_or_404(review_id) if review["is_hidden"]: raise NotFound("Review has been hidden.") try: vote = db_vote.get(user_id=user.id, revision_id=review["last_revision"]["id"]) except db_exceptions.NoDataFoundException: raise InvalidRequest("Review is not rated yet.") db_vote.delete(user_id=vote["user_id"], revision_id=vote["revision_id"]) return jsonify(message="Request processed successfully")
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 fetch_params(review): try: text = Parser.string('json', 'text', min=REVIEW_TEXT_MIN_LENGTH, max=REVIEW_TEXT_MAX_LENGTH) except MissingDataError: text = review['text'] try: rating = Parser.int('json', 'rating', min=REVIEW_RATING_MIN, max=REVIEW_RATING_MAX) except MissingDataError: rating = review['rating'] if text is None and rating is None: raise InvalidRequest(desc='Review must have either text or rating') return text, rating
def review_spam_report_handler(review_id, user): """Create spam report for a specified review. **OAuth scope:** vote :resheader Content-Type: *application/json* """ review = get_review_or_404(review_id) if review["is_hidden"]: raise NotFound("Review has been hidden.") if review["user_id"] == user.id: raise InvalidRequest('own') db_spam_report.create(review["last_revision"]["id"], user.id, "Spam") return jsonify(message="Spam report created successfully")
def review_spam_report_handler(review_id, user): """Create spam report for a specified review. **OAuth scope:** vote :resheader Content-Type: *application/json* """ review = Review.query.get_or_404(str(review_id)) if review.is_hidden: raise NotFound("Review has been hidden.") if review.user_id == user.id: raise InvalidRequest('own') SpamReport.create(review, user) return jsonify(message="Spam report created successfully")
def review_vote_delete_handler(review_id, user): """Delete your vote for a specified review. **OAuth scope:** vote :resheader Content-Type: *application/json* """ review = Review.query.get_or_404(str(review_id)) if review.is_hidden: raise NotFound("Review has been hidden.") vote = Vote.query.filter_by(user=user, revision=review.last_revision).first() if not vote: raise InvalidRequest(desc='Review is not rated yet.') vote.delete() return jsonify(message='Request processed successfully')
def review_list_handler(): """Get list of reviews. **Request Example:** .. code-block:: bash $ curl "https://critiquebrainz.org/ws/1/review/?limit=1&offset=50" \\ -X GET **Response Example:** .. code-block:: json { "count": 9197, "limit": 1, "offset": 50, "reviews": [ { "created": "Fri, 16 May 2008 00:00:00 GMT", "edits": 0, "entity_id": "09259937-6477-3959-8b10-af1cbaea8e6e", "entity_type": "release_group", "id": "c807d0b4-0dd0-43fe-a7c4-d29bb61f389e", "language": "en", "last_updated": "Fri, 16 May 2008 00:00:00 GMT", "license": { "full_name": "Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported", "id": "CC BY-NC-SA 3.0", "info_url": "https://creativecommons.org/licenses/by-nc-sa/3.0/" }, "popularity": 0, "source": "BBC", "source_url": "http://www.bbc.co.uk/music/reviews/vh54", "text": "TEXT CONTENT OF REVIEW", "rating": 5, "user": { "created": "Wed, 07 May 2014 16:20:47 GMT", "display_name": "Jenny Nelson", "id": "3bf3fe0c-6db2-4746-bcf1-f39912113852", "karma": 0, "user_type": "Noob" }, "votes": { "positive": 0, "negative": 0 } } ] } :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: ``popularity`` or ``published_on`` **(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=['popularity', 'published_on', 'rating', 'created'], optional=True) # "rating" and "created" sort values are deprecated and but allowed here for backward compatibility if sort == 'created': sort = 'published_on' if sort == 'rating': sort = 'popularity' 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 = db_review.list_reviews( entity_id=entity_id, entity_type=entity_type, user_id=user_id, sort=sort, limit=limit, offset=offset, language=language, ) reviews = [db_review.to_dict(p) 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)