diff --git a/app/blueprints/api/endpoints.py b/app/blueprints/api/endpoints.py index 8b968930..94aeecd3 100644 --- a/app/blueprints/api/endpoints.py +++ b/app/blueprints/api/endpoints.py @@ -14,18 +14,19 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . - -from flask import * +from flask import request, jsonify, current_app, abort from flask_login import current_user, login_required +from sqlalchemy.sql.expression import func + +from app import csrf +from app.markdown import render_markdown +from app.models import Tag, PackageState, PackageType, Package, db, PackageRelease, Tags, Permission, ForumTopic, MinetestRelease, APIToken +from app.querybuilder import QueryBuilder +from app.utils import is_package_page from . import bp from .auth import is_api_authd -from .support import error, api_create_vcs_release, api_create_zip_release -from app import csrf -from app.models import * -from app.utils import is_package_page -from app.markdown import render_markdown -from app.querybuilder import QueryBuilder -from sqlalchemy.sql.expression import func +from .support import error, api_create_vcs_release, api_create_zip_release, api_create_screenshot + @bp.route("/api/packages/") def packages(): @@ -230,3 +231,25 @@ def create_release(token, package): error(400, "Missing 'file' in multipart body") return api_create_zip_release(token, package, data["title"], file) + + +@bp.route("/api/packages///screenshots/new/", methods=["POST"]) +@csrf.exempt +@is_package_page +@is_api_authd +def create_screenshot(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 create screenshots") + + data = request.form + if "title" not in data: + error(400, "Title is required in the POST data") + + file = request.files.get("file") + if file is None: + error(400, "Missing 'file' in multipart body") + + return api_create_screenshot(token, package, data["title"], file) diff --git a/app/blueprints/api/support.py b/app/blueprints/api/support.py index f5b115bc..0e0c6c72 100644 --- a/app/blueprints/api/support.py +++ b/app/blueprints/api/support.py @@ -17,7 +17,8 @@ from flask import jsonify, abort, make_response, url_for from app.logic.releases import LogicError, do_create_vcs_release, do_create_zip_release -from app.models import APIToken, Package, MinetestRelease +from app.logic.screenshots import do_create_screenshot +from app.models import APIToken, Package, MinetestRelease, PackageScreenshot def error(code: int, msg: str): @@ -56,3 +57,15 @@ def api_create_zip_release(token: APIToken, package: Package, title: str, file, "task": url_for("tasks.check", id=rel.task_id), "release": rel.getAsDictionary() }) + + +def api_create_screenshot(token: APIToken, package: Package, title: str, file): + if not token.canOperateOnPackage(package): + error(403, "API token does not have access to the package") + + ss : PackageScreenshot = run_safe(do_create_screenshot, token.owner, package, title, file) + + return jsonify({ + "success": True, + "screenshot": ss.getAsDictionary() + }) diff --git a/app/flatpages/help/api.md b/app/flatpages/help/api.md index e69d349d..4ad3f5f1 100644 --- a/app/flatpages/help/api.md +++ b/app/flatpages/help/api.md @@ -69,6 +69,22 @@ curl https://content.minetest.net/api/packages/username/name/releases/new/ \ -F title="My Release" -F file=@path/to/file.zip ``` +### Screenshots + +* POST `/api/packages///screenshots/new/` (Create) + * Requires authentication. + * Body is multipart form data. + * `title`: human-readable name for the screenshot, shown as a caption and alt text. + * `file`: multipart file to upload, like ``. + +Example: + +```bash +curl https://content.minetest.net/api/packages/username/name/screenshots/new/ \ + -H "Authorization: Bearer YOURTOKEN" \ + -F title="My Release" -F file=@path/to/screnshot.png +``` + ### Topics * GET `/api/topics/` - Supports [Package Queries](#package-queries), and the following two options: