Add licenses API

This commit is contained in:
rubenwardy 2021-02-02 22:41:48 +00:00
parent ca58c70206
commit 12e364969b
2 changed files with 109 additions and 99 deletions

View File

@ -20,7 +20,7 @@ from sqlalchemy.sql.expression import func
from app import csrf from app import csrf
from app.utils.markdown import render_markdown 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.querybuilder import QueryBuilder
from app.utils import is_package_page from app.utils import is_package_page
from . import bp from . import bp
@ -42,15 +42,6 @@ def packages():
return jsonify(pkgs) 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/<author>/<name>/") @bp.route("/api/packages/<author>/<name>/")
@is_package_page @is_package_page
def package(package): def package(package):
@ -68,47 +59,6 @@ def edit_package(token, package):
return api_edit_package(token, package, request.json) 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): def resolve_package_deps(out, package, only_hard):
id = package.getId() id = package.getId()
if id in out: if id in out:
@ -177,12 +127,6 @@ def topic_set_discard():
return jsonify(topic.getAsDictionary()) 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/") @bp.route("/api/whoami/")
@is_api_authd @is_api_authd
def whoami(token): def whoami(token):
@ -357,3 +301,65 @@ def order_screenshots(token: APIToken, package: Package):
error(400, "Expected order body to be array") error(400, "Expected order body to be array")
return api_order_screenshots(token, package, request.json) 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])

View File

@ -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/). Tokens can be attained by visiting [Settings > API Tokens](/user/tokens/).
* GET `/api/whoami/` - JSON dictionary with the following keys: * GET `/api/whoami/`: JSON dictionary with the following keys:
* `is_authenticated` - True on successful API authentication * `is_authenticated`: True on successful API authentication
* `username` - Username of the user authenticated as, null otherwise. * `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. * 4xx status codes will be thrown on unsupported authentication type, invalid access token, or other errors.
## Packages ## Packages
* GET `/api/packages/` (List) * GET `/api/packages/` (List)
@ -34,21 +35,6 @@ Tokens can be attained by visiting [Settings > API Tokens](/user/tokens/).
* `issue_tracker`: Issue tracker URL. * `issue_tracker`: Issue tracker URL.
* GET `/api/packages/<username>/<name>/dependencies/` * GET `/api/packages/<username>/<name>/dependencies/`
* If query argument `only_hard` is present, only hard deps will be returned. * 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 ### Package Queries
@ -58,20 +44,20 @@ Example:
Supported query parameters: Supported query parameters:
* `type` - Package types (`mod`, `game`, `txp`). * `type`: Package types (`mod`, `game`, `txp`).
* `q` - Query string. * `q`: Query string.
* `author` - Filter by author. * `author`: Filter by author.
* `tag` - Filter by tags. * `tag`: Filter by tags.
* `random` - When present, enable random ordering and ignore `sort`. * `random`: When present, enable random ordering and ignore `sort`.
* `limit` - Return at most `limit` packages. * `limit`: Return at most `limit` packages.
* `hide` - Hide content based on [Content Flags](/help/content_flags/). * `hide`: Hide content based on [Content Flags](/help/content_flags/).
* `sort` - Sort by (`name`, `title`, `score`, `reviews`, `downloads`, `created_at`, `approved_at`, `last_release`). * `sort`: Sort by (`name`, `title`, `score`, `reviews`, `downloads`, `created_at`, `approved_at`, `last_release`).
* `order` - Sort ascending (`asc`) or descending (`desc`). * `order`: Sort ascending (`asc`) or descending (`desc`).
* `protocol_version` - Only show packages supported by this Minetest protocol version. * `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`. * `engine_version`: Only show packages supported by this Minetest engine version, eg: `5.3.0`.
* `fmt` - How the response is formated. * `fmt`: How the response is formated.
* `keys` - author/name only. * `keys`: author/name only.
* `short` - stuff needed for the Minetest client. * `short`: stuff needed for the Minetest client.
## Releases ## Releases
@ -165,9 +151,9 @@ curl -X POST https://content.minetest.net/api/packages/username/name/screenshots
## Topics ## Topics
* GET `/api/topics/` - Supports [Package Queries](#package-queries), and the following two options: * GET `/api/topics/`: Supports [Package Queries](#package-queries), and the following two options:
* `show_added` - Show topics which exist as packages, default true. * `show_added`: Show topics which exist as packages, default true.
* `show_discarded` - Show topics which have been marked as outdated, default false. * `show_discarded`: Show topics which have been marked as outdated, default false.
### Topic Queries ### Topic Queries
@ -177,14 +163,32 @@ Example:
Supported query parameters: Supported query parameters:
* `q` - Query string. * `q`: Query string.
* `sort` - Sort by (`name`, `views`, `date`). * `sort`: Sort by (`name`, `views`, `date`).
* `order` - Sort ascending (`asc`) or descending (`desc`). * `order`: Sort ascending (`asc`) or descending (`desc`).
* `show_added` - Show topics that have an existing package. * `show_added`: Show topics that have an existing package.
* `show_discarded` - Show topics marked as discarded. * `show_discarded`: Show topics marked as discarded.
* `limit` - Return at most `limit` topics. * `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/` * GET `/api/minetest_versions/`