From 4f69dd8d323efa37628aa93d21aba0a47ff91b93 Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Wed, 24 Nov 2021 16:33:37 +0000 Subject: [PATCH] Add API for reviews --- app/blueprints/api/endpoints.py | 18 ++++++++++++++++- app/flatpages/help/api.md | 36 +++++++++++++++++++++++++++++++++ app/models/threads.py | 20 ++++++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) diff --git a/app/blueprints/api/endpoints.py b/app/blueprints/api/endpoints.py index 87523e3..56999f8 100644 --- a/app/blueprints/api/endpoints.py +++ b/app/blueprints/api/endpoints.py @@ -20,7 +20,8 @@ from sqlalchemy.sql.expression import func from app import csrf from app.markdown import render_markdown -from app.models import Tag, PackageState, PackageType, Package, db, PackageRelease, Permission, ForumTopic, MinetestRelease, APIToken, PackageScreenshot, License, ContentWarning, User +from app.models import Tag, PackageState, PackageType, Package, db, PackageRelease, Permission, ForumTopic, \ + MinetestRelease, APIToken, PackageScreenshot, License, ContentWarning, User, PackageReview from app.querybuilder import QueryBuilder from app.utils import is_package_page, get_int_or_abort from . import bp @@ -362,6 +363,21 @@ def order_screenshots(token: APIToken, package: Package): return api_order_screenshots(token, package, request.json) +@bp.route("/api/packages///reviews/") +@is_package_page +@cors_allowed +def list_reviews(package): + reviews = package.reviews + return jsonify([review.getAsDictionary() for review in reviews]) + + +@bp.route("/api/reviews/") +@cors_allowed +def list_all_reviews(): + reviews = PackageReview.query.all() + return jsonify([review.getAsDictionary(True) for review in reviews]) + + @bp.route("/api/scores/") @cors_allowed def package_scores(): diff --git a/app/flatpages/help/api.md b/app/flatpages/help/api.md index 6e5693c..6631c83 100644 --- a/app/flatpages/help/api.md +++ b/app/flatpages/help/api.md @@ -210,6 +210,42 @@ curl -X POST https://content.minetest.net/api/packages/username/name/screenshots ``` +## Reviews + +* GET `/api/packages//releases/` (List) + * Returns array of review dictionaries with keys: + * `user`: dictionary with `display_name` and `username`. + * `title`: review title + * `comment`: the text + * `is_positive`: boolean + * `created_at`: iso timestamp + * `votes`: dictionary with `helpful` and `unhelpful`, +* GET `/api/reviews/` (List) + * Above, but for all packages. + * Each review has a `package` dictionary with `type`, `author` and `name` + +Example: + +```json +[ + { + "comment": "This is a really good mod!", + "created_at": "2021-11-24T16:18:33.764084", + "is_positive": true, + "title": "Really good", + "user": { + "display_name": "rubenwardy", + "username": "rubenwardy" + }, + "votes": { + "helpful": 0, + "unhelpful": 0 + } + } +] +``` + + ## Topics * GET `/api/topics/` ([View](/api/topics/)): Supports [Package Queries](#package-queries), and the following two options: diff --git a/app/models/threads.py b/app/models/threads.py index 2035229..c48eaee 100644 --- a/app/models/threads.py +++ b/app/models/threads.py @@ -168,6 +168,26 @@ class PackageReview(db.Model): user_vote = next(filter(lambda vote: vote.user == current_user, votes), None) return pos, neg, user_vote.is_positive if user_vote else None + def getAsDictionary(self, include_package=False): + pos, neg, _user = self.get_totals() + ret = { + "is_positive": self.recommends, + "user": { + "username": self.author.username, + "display_name": self.author.display_name, + }, + "created_at": self.created_at.isoformat(), + "votes": { + "helpful": pos, + "unhelpful": neg, + }, + "title": self.thread.title, + "comment": self.thread.replies[0].comment, + } + if include_package: + ret["package"] = self.package.getAsDictionaryKey() + return ret + def asSign(self): return 1 if self.recommends else -1