From 12e364969b77c8416859a5ad170e60bea38ccdfd Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Tue, 2 Feb 2021 22:41:48 +0000 Subject: [PATCH] Add licenses API --- app/blueprints/api/endpoints.py | 120 +++++++++++++++++--------------- app/flatpages/help/api.md | 88 ++++++++++++----------- 2 files changed, 109 insertions(+), 99 deletions(-) diff --git a/app/blueprints/api/endpoints.py b/app/blueprints/api/endpoints.py index 3bf89f5..bfee815 100644 --- a/app/blueprints/api/endpoints.py +++ b/app/blueprints/api/endpoints.py @@ -20,7 +20,7 @@ from sqlalchemy.sql.expression import func from app import csrf from app.utils.markdown import render_markdown -from app.models import Tag, PackageState, PackageType, Package, db, PackageRelease, Permission, ForumTopic, MinetestRelease, APIToken, PackageScreenshot +from app.models import Tag, PackageState, PackageType, Package, db, PackageRelease, Permission, ForumTopic, MinetestRelease, APIToken, PackageScreenshot, License from app.querybuilder import QueryBuilder from app.utils import is_package_page from . import bp @@ -42,15 +42,6 @@ def packages(): return jsonify(pkgs) -@bp.route("/api/scores/") -def package_scores(): - qb = QueryBuilder(request.args) - query = qb.buildPackageQuery() - - pkgs = [package.getScoreDict() for package in query.all()] - return jsonify(pkgs) - - @bp.route("/api/packages///") @is_package_page def package(package): @@ -68,47 +59,6 @@ def edit_package(token, package): return api_edit_package(token, package, request.json) -@bp.route("/api/tags/") -def tags(): - return jsonify([tag.getAsDictionary() for tag in Tag.query.all() ]) - - -@bp.route("/api/homepage/") -def homepage(): - query = Package.query.filter_by(state=PackageState.APPROVED) - count = query.count() - - new = query.order_by(db.desc(Package.approved_at)).limit(4).all() - pop_mod = query.filter_by(type=PackageType.MOD).order_by(db.desc(Package.score)).limit(8).all() - pop_gam = query.filter_by(type=PackageType.GAME).order_by(db.desc(Package.score)).limit(8).all() - pop_txp = query.filter_by(type=PackageType.TXP).order_by(db.desc(Package.score)).limit(8).all() - high_reviewed = query.order_by(db.desc(Package.score - Package.score_downloads)) \ - .filter(Package.reviews.any()).limit(4).all() - - updated = db.session.query(Package).select_from(PackageRelease).join(Package) \ - .filter_by(state=PackageState.APPROVED) \ - .order_by(db.desc(PackageRelease.releaseDate)) \ - .limit(20).all() - updated = updated[:4] - - downloads_result = db.session.query(func.sum(Package.downloads)).one_or_none() - downloads = 0 if not downloads_result or not downloads_result[0] else downloads_result[0] - - def mapPackages(packages): - return [pkg.getAsDictionaryKey() for pkg in packages] - - return { - "count": count, - "downloads": downloads, - "new": mapPackages(new), - "updated": mapPackages(updated), - "pop_mod": mapPackages(pop_mod), - "pop_txp": mapPackages(pop_txp), - "pop_game": mapPackages(pop_gam), - "high_reviewed": mapPackages(high_reviewed) - } - - def resolve_package_deps(out, package, only_hard): id = package.getId() if id in out: @@ -177,12 +127,6 @@ def topic_set_discard(): return jsonify(topic.getAsDictionary()) -@bp.route("/api/minetest_versions/") -def versions(): - return jsonify([rel.getAsDictionary() \ - for rel in MinetestRelease.query.all() if rel.getActual() is not None]) - - @bp.route("/api/whoami/") @is_api_authd def whoami(token): @@ -357,3 +301,65 @@ def order_screenshots(token: APIToken, package: Package): error(400, "Expected order body to be array") return api_order_screenshots(token, package, request.json) + + +@bp.route("/api/scores/") +def package_scores(): + qb = QueryBuilder(request.args) + query = qb.buildPackageQuery() + + pkgs = [package.getScoreDict() for package in query.all()] + return jsonify(pkgs) + + +@bp.route("/api/tags/") +def tags(): + return jsonify([tag.getAsDictionary() for tag in Tag.query.all() ]) + + +@bp.route("/api/licenses/") +def licenses(): + return jsonify([ { "name": license.name, "is_foss": license.is_foss } \ + for license in License.query.order_by(db.asc(License.name)).all() ]) + + +@bp.route("/api/homepage/") +def homepage(): + query = Package.query.filter_by(state=PackageState.APPROVED) + count = query.count() + + new = query.order_by(db.desc(Package.approved_at)).limit(4).all() + pop_mod = query.filter_by(type=PackageType.MOD).order_by(db.desc(Package.score)).limit(8).all() + pop_gam = query.filter_by(type=PackageType.GAME).order_by(db.desc(Package.score)).limit(8).all() + pop_txp = query.filter_by(type=PackageType.TXP).order_by(db.desc(Package.score)).limit(8).all() + high_reviewed = query.order_by(db.desc(Package.score - Package.score_downloads)) \ + .filter(Package.reviews.any()).limit(4).all() + + updated = db.session.query(Package).select_from(PackageRelease).join(Package) \ + .filter_by(state=PackageState.APPROVED) \ + .order_by(db.desc(PackageRelease.releaseDate)) \ + .limit(20).all() + updated = updated[:4] + + downloads_result = db.session.query(func.sum(Package.downloads)).one_or_none() + downloads = 0 if not downloads_result or not downloads_result[0] else downloads_result[0] + + def mapPackages(packages): + return [pkg.getAsDictionaryKey() for pkg in packages] + + return { + "count": count, + "downloads": downloads, + "new": mapPackages(new), + "updated": mapPackages(updated), + "pop_mod": mapPackages(pop_mod), + "pop_txp": mapPackages(pop_txp), + "pop_game": mapPackages(pop_gam), + "high_reviewed": mapPackages(high_reviewed) + } + + +@bp.route("/api/minetest_versions/") +def versions(): + return jsonify([rel.getAsDictionary() \ + for rel in MinetestRelease.query.all() if rel.getActual() is not None]) diff --git a/app/flatpages/help/api.md b/app/flatpages/help/api.md index 61f21a9..b56b1e7 100644 --- a/app/flatpages/help/api.md +++ b/app/flatpages/help/api.md @@ -11,11 +11,12 @@ curl -H "Authorization: Bearer YOURTOKEN" https://content.minetest.net/api/whoam Tokens can be attained by visiting [Settings > API Tokens](/user/tokens/). -* GET `/api/whoami/` - JSON dictionary with the following keys: - * `is_authenticated` - True on successful API authentication - * `username` - Username of the user authenticated as, null otherwise. +* GET `/api/whoami/`: JSON dictionary with the following keys: + * `is_authenticated`: True on successful API authentication + * `username`: Username of the user authenticated as, null otherwise. * 4xx status codes will be thrown on unsupported authentication type, invalid access token, or other errors. + ## Packages * GET `/api/packages/` (List) @@ -34,21 +35,6 @@ Tokens can be attained by visiting [Settings > API Tokens](/user/tokens/). * `issue_tracker`: Issue tracker URL. * GET `/api/packages///dependencies/` * If query argument `only_hard` is present, only hard deps will be returned. -* GET `/api/scores/` - * See [Package Queries](#package-queries) -* GET `/api/tags/` - List of: - * `name` - technical name - * `title` - human-readable title - * `description` - tag description or null -* GET `/api/homepage/` - * `count` - number of packages - * `downloads` - get number of downloads - * `new` - new packages - * `updated` - recently updated packages - * `pop_mod` - popular mods - * `pop_txp` - popular textures - * `pop_game` - popular games - * `high_reviewed` - highest reviewed ### Package Queries @@ -58,20 +44,20 @@ Example: Supported query parameters: -* `type` - Package types (`mod`, `game`, `txp`). -* `q` - Query string. -* `author` - Filter by author. -* `tag` - Filter by tags. -* `random` - When present, enable random ordering and ignore `sort`. -* `limit` - Return at most `limit` packages. -* `hide` - Hide content based on [Content Flags](/help/content_flags/). -* `sort` - Sort by (`name`, `title`, `score`, `reviews`, `downloads`, `created_at`, `approved_at`, `last_release`). -* `order` - Sort ascending (`asc`) or descending (`desc`). -* `protocol_version` - Only show packages supported by this Minetest protocol version. -* `engine_version` - Only show packages supported by this Minetest engine version, eg: `5.3.0`. -* `fmt` - How the response is formated. - * `keys` - author/name only. - * `short` - stuff needed for the Minetest client. +* `type`: Package types (`mod`, `game`, `txp`). +* `q`: Query string. +* `author`: Filter by author. +* `tag`: Filter by tags. +* `random`: When present, enable random ordering and ignore `sort`. +* `limit`: Return at most `limit` packages. +* `hide`: Hide content based on [Content Flags](/help/content_flags/). +* `sort`: Sort by (`name`, `title`, `score`, `reviews`, `downloads`, `created_at`, `approved_at`, `last_release`). +* `order`: Sort ascending (`asc`) or descending (`desc`). +* `protocol_version`: Only show packages supported by this Minetest protocol version. +* `engine_version`: Only show packages supported by this Minetest engine version, eg: `5.3.0`. +* `fmt`: How the response is formated. + * `keys`: author/name only. + * `short`: stuff needed for the Minetest client. ## Releases @@ -165,9 +151,9 @@ curl -X POST https://content.minetest.net/api/packages/username/name/screenshots ## Topics -* GET `/api/topics/` - Supports [Package Queries](#package-queries), and the following two options: - * `show_added` - Show topics which exist as packages, default true. - * `show_discarded` - Show topics which have been marked as outdated, default false. +* GET `/api/topics/`: Supports [Package Queries](#package-queries), and the following two options: + * `show_added`: Show topics which exist as packages, default true. + * `show_discarded`: Show topics which have been marked as outdated, default false. ### Topic Queries @@ -177,14 +163,32 @@ Example: Supported query parameters: -* `q` - Query string. -* `sort` - Sort by (`name`, `views`, `date`). -* `order` - Sort ascending (`asc`) or descending (`desc`). -* `show_added` - Show topics that have an existing package. -* `show_discarded` - Show topics marked as discarded. -* `limit` - Return at most `limit` topics. +* `q`: Query string. +* `sort`: Sort by (`name`, `views`, `date`). +* `order`: Sort ascending (`asc`) or descending (`desc`). +* `show_added`: Show topics that have an existing package. +* `show_discarded`: Show topics marked as discarded. +* `limit`: Return at most `limit` topics. -## Minetest +## Misc +* GET `/api/scores/` + * See [Package Queries](#package-queries) +* GET `/api/tags/`: List of: + * `name`: technical name + * `title`: human-readable title + * `description`: tag description or null +* GET `/api/licenses/`: List of: + * `name` + * `is_foss`: whether the license is foss +* GET `/api/homepage/` + * `count`: number of packages + * `downloads`: get number of downloads + * `new`: new packages + * `updated`: recently updated packages + * `pop_mod`: popular mods + * `pop_txp`: popular textures + * `pop_game`: popular games + * `high_reviewed`: highest reviewed * GET `/api/minetest_versions/`