Add endpoint to replace specific plugin
This commit is contained in:
parent
2ba1f46149
commit
9a21c6ade8
3 changed files with 100 additions and 21 deletions
|
@ -69,6 +69,45 @@ async def reload_plugin(request: web.Request) -> web.Response:
|
|||
return resp.ok
|
||||
|
||||
|
||||
@routes.put("/plugin/{id}")
|
||||
async def put_plugin(request: web.Request) -> web.Response:
|
||||
plugin_id = request.match_info.get("id", None)
|
||||
content = await request.read()
|
||||
file = BytesIO(content)
|
||||
try:
|
||||
pid, version = ZippedPluginLoader.verify_meta(file)
|
||||
except MaubotZipImportError as e:
|
||||
return resp.plugin_import_error(str(e), traceback.format_exc())
|
||||
if pid != plugin_id:
|
||||
return resp.pid_mismatch
|
||||
plugin = PluginLoader.id_cache.get(plugin_id, None)
|
||||
if not plugin:
|
||||
return await upload_new_plugin(content, pid, version)
|
||||
elif isinstance(plugin, ZippedPluginLoader):
|
||||
return await upload_replacement_plugin(plugin, content, version)
|
||||
else:
|
||||
return resp.unsupported_plugin_loader
|
||||
|
||||
|
||||
@routes.post("/plugins/upload")
|
||||
async def upload_plugin(request: web.Request) -> web.Response:
|
||||
content = await request.read()
|
||||
file = BytesIO(content)
|
||||
try:
|
||||
pid, version = ZippedPluginLoader.verify_meta(file)
|
||||
except MaubotZipImportError as e:
|
||||
return resp.plugin_import_error(str(e), traceback.format_exc())
|
||||
plugin = PluginLoader.id_cache.get(pid, None)
|
||||
if not plugin:
|
||||
return await upload_new_plugin(content, pid, version)
|
||||
elif not request.query.get("allow_override"):
|
||||
return resp.plugin_exists
|
||||
elif isinstance(plugin, ZippedPluginLoader):
|
||||
return await upload_replacement_plugin(plugin, content, version)
|
||||
else:
|
||||
return resp.unsupported_plugin_loader
|
||||
|
||||
|
||||
async def upload_new_plugin(content: bytes, pid: str, version: str) -> web.Response:
|
||||
path = os.path.join(get_config()["plugin_directories.upload"], f"{pid}-v{version}.mbp")
|
||||
with open(path, "wb") as p:
|
||||
|
@ -86,10 +125,10 @@ async def upload_replacement_plugin(plugin: ZippedPluginLoader, content: bytes,
|
|||
dirname = os.path.dirname(plugin.path)
|
||||
old_filename = os.path.basename(plugin.path)
|
||||
if plugin.version in old_filename:
|
||||
filename = old_filename.replace(plugin.version, new_version)
|
||||
if filename == old_filename:
|
||||
filename = re.sub(f"{re.escape(plugin.version)}(-ts[0-9]+)?",
|
||||
f"{new_version}-ts{int(time())}", old_filename)
|
||||
replacement = (new_version if plugin.version != new_version
|
||||
else f"{new_version}-ts{int(time())}")
|
||||
filename = re.sub(f"{re.escape(plugin.version)}(-ts[0-9]+)?",
|
||||
replacement, old_filename)
|
||||
else:
|
||||
filename = old_filename.rstrip(".mbp")
|
||||
filename = f"{filename}-v{new_version}.mbp"
|
||||
|
@ -110,20 +149,3 @@ async def upload_replacement_plugin(plugin: ZippedPluginLoader, content: bytes,
|
|||
await plugin.start_instances()
|
||||
ZippedPluginLoader.trash(old_path, reason="update")
|
||||
return resp.updated(plugin.to_dict())
|
||||
|
||||
|
||||
@routes.post("/plugins/upload")
|
||||
async def upload_plugin(request: web.Request) -> web.Response:
|
||||
content = await request.read()
|
||||
file = BytesIO(content)
|
||||
try:
|
||||
pid, version = ZippedPluginLoader.verify_meta(file)
|
||||
except MaubotZipImportError as e:
|
||||
return resp.plugin_import_error(str(e), traceback.format_exc())
|
||||
plugin = PluginLoader.id_cache.get(pid, None)
|
||||
if not plugin:
|
||||
return await upload_new_plugin(content, pid, version)
|
||||
elif isinstance(plugin, ZippedPluginLoader):
|
||||
return await upload_replacement_plugin(plugin, content, version)
|
||||
else:
|
||||
return resp.unsupported_plugin_loader
|
||||
|
|
|
@ -61,6 +61,13 @@ class _Response:
|
|||
"errcode": "mxid_mismatch",
|
||||
}, status=HTTPStatus.BAD_REQUEST)
|
||||
|
||||
@property
|
||||
def pid_mismatch(self) -> web.Response:
|
||||
return web.json_response({
|
||||
"error": "The ID in the path does not match the ID of the uploaded plugin",
|
||||
"errcode": "pid_mismatch",
|
||||
}, status=HTTPStatus.BAD_REQUEST)
|
||||
|
||||
@property
|
||||
def bad_auth(self) -> web.Response:
|
||||
return web.json_response({
|
||||
|
@ -138,6 +145,13 @@ class _Response:
|
|||
"errcode": "user_exists",
|
||||
}, status=HTTPStatus.CONFLICT)
|
||||
|
||||
@property
|
||||
def plugin_exists(self) -> web.Response:
|
||||
return web.json_response({
|
||||
"error": "A plugin with the same ID as the uploaded plugin already exists",
|
||||
"errcode": "plugin_exists"
|
||||
}, status=HTTPStatus.CONFLICT)
|
||||
|
||||
@property
|
||||
def plugin_in_use(self) -> web.Response:
|
||||
return web.json_response({
|
||||
|
|
|
@ -85,6 +85,14 @@ paths:
|
|||
summary: Upload a new plugin
|
||||
description: Upload a new plugin. If the plugin already exists, enabled instances will be restarted.
|
||||
tags: [Plugins]
|
||||
parameters:
|
||||
- name: allow_override
|
||||
in: query
|
||||
description: Set to allow overriding existing plugins
|
||||
required: false
|
||||
schema:
|
||||
type: boolean
|
||||
default: false
|
||||
responses:
|
||||
200:
|
||||
description: Plugin uploaded and replaced current version successfully
|
||||
|
@ -102,6 +110,8 @@ paths:
|
|||
$ref: '#/components/responses/BadRequest'
|
||||
401:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
409:
|
||||
description: Plugin
|
||||
requestBody:
|
||||
content:
|
||||
application/zip:
|
||||
|
@ -150,6 +160,39 @@ paths:
|
|||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
put:
|
||||
operationId: put_plugin
|
||||
summary: Upload a new or replacement plugin
|
||||
description: |
|
||||
Upload a new or replacement plugin with the specified ID.
|
||||
A HTTP 400 will be returned if the ID of the uploaded plugin
|
||||
doesn't match the ID in the path. If the plugin already
|
||||
exists, enabled instances will be restarted.
|
||||
tags: [Plugins]
|
||||
responses:
|
||||
200:
|
||||
description: Plugin uploaded and replaced current version successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Plugin'
|
||||
201:
|
||||
description: New plugin uploaded successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Plugin'
|
||||
400:
|
||||
$ref: '#/components/responses/BadRequest'
|
||||
401:
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
requestBody:
|
||||
content:
|
||||
application/zip:
|
||||
schema:
|
||||
type: string
|
||||
format: binary
|
||||
example: The plugin maubot archive (.mbp)
|
||||
/plugin/{id}/reload:
|
||||
parameters:
|
||||
- name: id
|
||||
|
|
Loading…
Reference in a new issue