diff --git a/app/blueprints/api/endpoints.py b/app/blueprints/api/endpoints.py index 72533f3..32bab02 100644 --- a/app/blueprints/api/endpoints.py +++ b/app/blueprints/api/endpoints.py @@ -31,7 +31,8 @@ from app.querybuilder import QueryBuilder from app.utils import is_package_page, get_int_or_abort, url_set_query, abs_url, isYes from . import bp from .auth import is_api_authd -from .support import error, api_create_vcs_release, api_create_zip_release, api_create_screenshot, api_order_screenshots, api_edit_package +from .support import error, api_create_vcs_release, api_create_zip_release, api_create_screenshot, \ + api_order_screenshots, api_edit_package, api_set_cover_image from functools import wraps @@ -356,7 +357,7 @@ def order_screenshots(token: APIToken, package: Package): error(401, "Authentication needed") if not package.checkPerm(token.owner, Permission.ADD_SCREENSHOTS): - error(403, "You do not have the permission to delete screenshots") + error(403, "You do not have the permission to change screenshots") if not token.canOperateOnPackage(package): error(403, "API token does not have access to the package") @@ -368,6 +369,28 @@ def order_screenshots(token: APIToken, package: Package): return api_order_screenshots(token, package, request.json) +@bp.route("/api/packages///screenshots/cover-image/", methods=["POST"]) +@csrf.exempt +@is_package_page +@is_api_authd +@cors_allowed +def set_cover_image(token: APIToken, package: Package): + if not token: + error(401, "Authentication needed") + + if not package.checkPerm(token.owner, Permission.ADD_SCREENSHOTS): + error(403, "You do not have the permission to change screenshots") + + if not token.canOperateOnPackage(package): + error(403, "API token does not have access to the package") + + json = request.json + if json is None or not isinstance(json, dict) or "cover_image" not in json: + error(400, "Expected body to be an object with cover_image as a key") + + return api_set_cover_image(token, package, request.json["cover_image"]) + + @bp.route("/api/packages///reviews/") @is_package_page @cors_allowed diff --git a/app/blueprints/api/support.py b/app/blueprints/api/support.py index d060c02..aa8ff53 100644 --- a/app/blueprints/api/support.py +++ b/app/blueprints/api/support.py @@ -19,7 +19,7 @@ from flask import jsonify, abort, make_response, url_for, current_app from app.logic.packages import do_edit_package from app.logic.releases import LogicError, do_create_vcs_release, do_create_zip_release -from app.logic.screenshots import do_create_screenshot, do_order_screenshots +from app.logic.screenshots import do_create_screenshot, do_order_screenshots, do_set_cover_image from app.models import APIToken, Package, MinetestRelease, PackageScreenshot @@ -94,6 +94,17 @@ def api_order_screenshots(token: APIToken, package: Package, order: [any]): }) +def api_set_cover_image(token: APIToken, package: Package, cover_image): + if not token.canOperateOnPackage(package): + error(403, "API token does not have access to the package") + + guard(do_set_cover_image)(token.owner, package, cover_image) + + return jsonify({ + "success": True + }) + + def api_edit_package(token: APIToken, package: Package, data: dict, reason: str = "API"): if not token.canOperateOnPackage(package): error(403, "API token does not have access to the package") diff --git a/app/flatpages/help/api.md b/app/flatpages/help/api.md index adb1e82..e641ba8 100644 --- a/app/flatpages/help/api.md +++ b/app/flatpages/help/api.md @@ -238,6 +238,9 @@ curl -X DELETE https://content.minetest.net/api/packages/username/name/releases/ * POST `/api/packages///screenshots/order/` * Requires authentication. * Body is a JSON array containing the screenshot IDs in their order. +* POST `/api/packages///screenshots/order/` + * Requires authentication. + * Body is a JSON dictionary with "cover_image" containing the screenshot ID. Currently, to get a different size of thumbnail you can replace the number in `/thumbnails/1/` with any number from 1-3. The resolutions returned may change in the future, and we may move to a more capable thumbnail generation. @@ -258,6 +261,11 @@ curl -X DELETE https://content.minetest.net/api/packages/username/name/screensho curl -X POST https://content.minetest.net/api/packages/username/name/screenshots/order/ \ -H "Authorization: Bearer YOURTOKEN" -H "Content-Type: application/json" \ -d "[13, 2, 5, 7]" + +# Set cover image +curl -X POST https://content.minetest.net/api/packages/username/name/screenshots/cover-image/ \ + -H "Authorization: Bearer YOURTOKEN" -H "Content-Type: application/json" \ + -d "{ 'cover_image': 123 }" ``` diff --git a/app/logic/screenshots.py b/app/logic/screenshots.py index e8bdc34..9eea434 100644 --- a/app/logic/screenshots.py +++ b/app/logic/screenshots.py @@ -66,3 +66,18 @@ def do_order_screenshots(_user: User, package: Package, order: [any]): raise LogicError(400, "Invalid id, not a number: {}".format(json.dumps(ss_id))) db.session.commit() + + +def do_set_cover_image(_user: User, package: Package, cover_image): + try: + cover_image = int(cover_image) + except (ValueError, TypeError) as e: + raise LogicError(400, "Invalid id, not a number: {}".format(json.dumps(cover_image))) + + for screenshot in package.screenshots.all(): + if screenshot.id == cover_image: + package.cover_image = screenshot + db.session.commit() + return + + raise LogicError(400, "Unable to find screenshot")