mirror of
https://github.com/minetest/contentdb.git
synced 2024-11-10 09:33:44 +01:00
Add Minetest-optimised package endpoint
This commit is contained in:
parent
0f5a97b539
commit
1be4155ab0
@ -35,7 +35,7 @@ from app.models import Tag, PackageState, PackageType, Package, db, PackageRelea
|
|||||||
PackageAlias, Language
|
PackageAlias, Language
|
||||||
from app.querybuilder import QueryBuilder
|
from app.querybuilder import QueryBuilder
|
||||||
from app.utils import is_package_page, get_int_or_abort, url_set_query, abs_url, is_yes, get_request_date
|
from app.utils import is_package_page, get_int_or_abort, url_set_query, abs_url, is_yes, get_request_date
|
||||||
from app.utils.minetest_hypertext import html_to_minetest
|
from app.utils.minetest_hypertext import html_to_minetest, package_info_as_hypertext
|
||||||
from . import bp
|
from . import bp
|
||||||
from .auth import is_api_authd
|
from .auth import is_api_authd
|
||||||
from .support import error, api_create_vcs_release, api_create_zip_release, api_create_screenshot, \
|
from .support import error, api_create_vcs_release, api_create_zip_release, api_create_screenshot, \
|
||||||
@ -110,12 +110,42 @@ def package_view(package):
|
|||||||
lang = request.accept_languages.best_match(allowed_languages)
|
lang = request.accept_languages.best_match(allowed_languages)
|
||||||
|
|
||||||
data = package.as_dict(current_app.config["BASE_URL"], lang=lang)
|
data = package.as_dict(current_app.config["BASE_URL"], lang=lang)
|
||||||
if "formspec_version" in request.args:
|
resp = jsonify(data)
|
||||||
formspec_version = request.args["formspec_version"]
|
resp.vary = "Accept-Language"
|
||||||
|
return resp
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/api/packages/<author>/<name>/for-client/")
|
||||||
|
@is_package_page
|
||||||
|
@cors_allowed
|
||||||
|
def package_view_client(package: Package):
|
||||||
|
protocol_version = request.args.get("protocol_version")
|
||||||
|
engine_version = request.args.get("engine_version")
|
||||||
|
if protocol_version or engine_version:
|
||||||
|
version = MinetestRelease.get(engine_version, get_int_or_abort(protocol_version))
|
||||||
|
else:
|
||||||
|
version = None
|
||||||
|
|
||||||
|
allowed_languages = set([x[0] for x in db.session.query(Language.id).all()])
|
||||||
|
lang = request.accept_languages.best_match(allowed_languages)
|
||||||
|
|
||||||
|
data = package.as_dict(current_app.config["BASE_URL"], version, lang=lang)
|
||||||
|
|
||||||
|
formspec_version = get_int_or_abort(request.args["formspec_version"])
|
||||||
include_images = is_yes(request.args.get("include_images", "true"))
|
include_images = is_yes(request.args.get("include_images", "true"))
|
||||||
html = render_markdown(data["long_description"])
|
html = render_markdown(data["long_description"])
|
||||||
data["long_description"] = html_to_minetest(html, formspec_version, include_images)
|
data["long_description"] = html_to_minetest(html, formspec_version, include_images)
|
||||||
|
|
||||||
|
data["info_hypertext"] = package_info_as_hypertext(package, formspec_version)
|
||||||
|
|
||||||
|
data["download_size"] = package.get_download_release(version).file_size
|
||||||
|
|
||||||
|
data["reviews"] = {
|
||||||
|
"positive": package.reviews.filter(PackageReview.rating > 3).count(),
|
||||||
|
"neutral": package.reviews.filter(PackageReview.rating == 3).count(),
|
||||||
|
"negative": package.reviews.filter(PackageReview.rating < 3).count(),
|
||||||
|
}
|
||||||
|
|
||||||
resp = jsonify(data)
|
resp = jsonify(data)
|
||||||
resp.vary = "Accept-Language"
|
resp.vary = "Accept-Language"
|
||||||
return resp
|
return resp
|
||||||
|
@ -78,9 +78,6 @@ curl -X DELETE https://content.minetest.net/api/delete-token/ \
|
|||||||
* GET `/api/packages/` (List)
|
* GET `/api/packages/` (List)
|
||||||
* See [Package Queries](#package-queries)
|
* See [Package Queries](#package-queries)
|
||||||
* GET `/api/packages/<username>/<name>/` (Read)
|
* GET `/api/packages/<username>/<name>/` (Read)
|
||||||
* Query arguments
|
|
||||||
* `formspec_version`: Optional. If present, `long_description` is returned a hypertext (see /hypertext/ below).
|
|
||||||
* `include_images`: Optional, defaults to true. Only used if `formspec_version` is provided.
|
|
||||||
* PUT `/api/packages/<author>/<name>/` (Update)
|
* PUT `/api/packages/<author>/<name>/` (Update)
|
||||||
* Requires authentication.
|
* Requires authentication.
|
||||||
* JSON dictionary with any of these keys (all are optional, null to delete Nullables):
|
* JSON dictionary with any of these keys (all are optional, null to delete Nullables):
|
||||||
@ -103,6 +100,15 @@ curl -X DELETE https://content.minetest.net/api/delete-token/ \
|
|||||||
* `donate_url`: URL to a donation page.
|
* `donate_url`: URL to a donation page.
|
||||||
* `translation_url`: URL to send users interested in translating your package.
|
* `translation_url`: URL to send users interested in translating your package.
|
||||||
* `game_support`: Array of game support information objects. Not currently documented, as subject to change.
|
* `game_support`: Array of game support information objects. Not currently documented, as subject to change.
|
||||||
|
* GET `/api/packages/<username>/<name>/for-client/`
|
||||||
|
* Similar to the read endpoint, but optimised for the Minetest client
|
||||||
|
* `long_description` is given as a hypertext object, see `/hypertext/` below.
|
||||||
|
* `info_hypertext` is the info sidebar as a hypertext object.
|
||||||
|
* Query arguments
|
||||||
|
* `formspec_version`: Required. See /hypertext/ below.
|
||||||
|
* `include_images`: Optional, defaults to true.
|
||||||
|
* `protocol_version`: Optional, used to get the correct release.
|
||||||
|
* `engine_version`: Optional, used to get the correct release. Ex: `5.3.0`.
|
||||||
* GET `/api/packages/<author>/<name>/hypertext/`
|
* GET `/api/packages/<author>/<name>/hypertext/`
|
||||||
* Converts the long description to [Minetest Markup Language](https://github.com/minetest/minetest/blob/master/doc/lua_api.md#markup-language)
|
* Converts the long description to [Minetest Markup Language](https://github.com/minetest/minetest/blob/master/doc/lua_api.md#markup-language)
|
||||||
to be used in a `hypertext` formspec element.
|
to be used in a `hypertext` formspec element.
|
||||||
|
@ -671,7 +671,7 @@ class Package(db.Model):
|
|||||||
return url_for("packages.move_to_state",
|
return url_for("packages.move_to_state",
|
||||||
author=self.author.username, name=self.name, state=state.name.lower())
|
author=self.author.username, name=self.name, state=state.name.lower())
|
||||||
|
|
||||||
def get_download_release(self, version=None):
|
def get_download_release(self, version=None) -> typing.Optional["PackageRelease"]:
|
||||||
for rel in self.releases:
|
for rel in self.releases:
|
||||||
if rel.approved and (version is None or
|
if rel.approved and (version is None or
|
||||||
((rel.min_rel is None or rel.min_rel_id <= version.id) and
|
((rel.min_rel is None or rel.min_rel_id <= version.id) and
|
||||||
|
@ -18,6 +18,10 @@ from html.parser import HTMLParser
|
|||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from flask_babel import gettext
|
||||||
|
|
||||||
|
from app.models import Package, PackageType
|
||||||
|
|
||||||
|
|
||||||
def normalize_whitespace(x):
|
def normalize_whitespace(x):
|
||||||
return re.sub(r"\s+", " ", x)
|
return re.sub(r"\s+", " ", x)
|
||||||
@ -188,7 +192,7 @@ class MinetestHTMLParser(HTMLParser):
|
|||||||
self.current_line += f"&{name};"
|
self.current_line += f"&{name};"
|
||||||
|
|
||||||
|
|
||||||
def html_to_minetest(html, formspec_version=6, include_images=True):
|
def html_to_minetest(html, formspec_version=7, include_images=True):
|
||||||
parser = MinetestHTMLParser(include_images)
|
parser = MinetestHTMLParser(include_images)
|
||||||
parser.feed(html)
|
parser.feed(html)
|
||||||
parser.finish_line()
|
parser.finish_line()
|
||||||
@ -200,3 +204,70 @@ def html_to_minetest(html, formspec_version=6, include_images=True):
|
|||||||
"images": parser.images,
|
"images": parser.images,
|
||||||
"image_tooltips": parser.image_tooltips,
|
"image_tooltips": parser.image_tooltips,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def package_info_as_hypertext(package: Package, formspec_version: int = 7):
|
||||||
|
body = ""
|
||||||
|
|
||||||
|
def add_value(label, value):
|
||||||
|
nonlocal body
|
||||||
|
body += f"{label}\n<b>{value}</b>\n\n"
|
||||||
|
|
||||||
|
def add_list(label, items):
|
||||||
|
nonlocal body
|
||||||
|
|
||||||
|
body += label + "\n<b>"
|
||||||
|
for i, item in enumerate(items):
|
||||||
|
if i != 0:
|
||||||
|
body += "</b>, <b>"
|
||||||
|
body += item
|
||||||
|
|
||||||
|
if len(items) == 0:
|
||||||
|
body += "-"
|
||||||
|
|
||||||
|
body += "</b>\n\n"
|
||||||
|
|
||||||
|
add_value(gettext("Type"), package.type.text)
|
||||||
|
add_list(gettext("Tags"), [tag.title for tag in package.tags])
|
||||||
|
|
||||||
|
if package.type != PackageType.GAME:
|
||||||
|
[supported, unsupported] = package.get_sorted_game_support_pair()
|
||||||
|
supports_all_games = package.supports_all_games or len(supported) == 0
|
||||||
|
if supports_all_games:
|
||||||
|
add_value(gettext("Supported Games"), gettext("No specific game required"))
|
||||||
|
else:
|
||||||
|
add_list(gettext("Supported Games"), [support.game.title for support in supported])
|
||||||
|
|
||||||
|
if unsupported and supports_all_games:
|
||||||
|
add_list(gettext("Unsupported Games"), [support.game.title for support in supported])
|
||||||
|
|
||||||
|
if package.type != PackageType.TXP:
|
||||||
|
add_list(gettext("Dependencies"), [x.meta_package.name for x in package.get_sorted_hard_dependencies()])
|
||||||
|
add_list(gettext("Optional dependencies"), [x.meta_package.name for x in package.get_sorted_optional_dependencies()])
|
||||||
|
|
||||||
|
languages = [trans.language.title for trans in package.translations]
|
||||||
|
languages.insert(0, "English")
|
||||||
|
add_list(gettext("Languages"), languages)
|
||||||
|
|
||||||
|
if package.license == package.media_license:
|
||||||
|
license = package.license.name
|
||||||
|
elif package.type == package.type.TXP:
|
||||||
|
license = package.media_license.name
|
||||||
|
else:
|
||||||
|
license = gettext("%(code_license)s for code,<br>%(media_license)s for media.",
|
||||||
|
code_license=package.license.name, media_license=package.media_license.name).replace("<br>", " ")
|
||||||
|
|
||||||
|
add_value(gettext("License"), license)
|
||||||
|
if package.dev_state:
|
||||||
|
add_value(gettext("Maintenance State"), package.dev_state.value)
|
||||||
|
add_value(gettext("Added"), package.created_at)
|
||||||
|
add_list(gettext("Maintainers"), [user.display_name for user in package.maintainers])
|
||||||
|
add_list(gettext("Provides"), [x.name for x in package.provides])
|
||||||
|
|
||||||
|
return {
|
||||||
|
"head": HEAD,
|
||||||
|
"body": body,
|
||||||
|
"links": {},
|
||||||
|
"images": {},
|
||||||
|
"image_tooltips": {},
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user