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.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/<author>/<name>/")
@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])

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/).
* 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/<username>/<name>/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/`