forked from vbatts/maubot
Blacken and isort code
This commit is contained in:
parent
6257979e7c
commit
068e268c63
97 changed files with 1781 additions and 1086 deletions
|
@ -1 +1 @@
|
|||
from . import upload, build, login, init, logs, auth
|
||||
from . import auth, build, init, login, logs, upload
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# maubot - A plugin-based Matrix bot system.
|
||||
# Copyright (C) 2021 Tulir Asokan
|
||||
# Copyright (C) 2022 Tulir Asokan
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
|
@ -13,8 +13,8 @@
|
|||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
import webbrowser
|
||||
import json
|
||||
import webbrowser
|
||||
|
||||
from colorama import Fore
|
||||
from yarl import URL
|
||||
|
@ -26,12 +26,16 @@ from ..cliq import cliq
|
|||
history_count: int = 10
|
||||
|
||||
friendly_errors = {
|
||||
"server_not_found": "Registration target server not found.\n\n"
|
||||
"To log in or register through maubot, you must add the server to the\n"
|
||||
"homeservers section in the config. If you only want to log in,\n"
|
||||
"leave the `secret` field empty.",
|
||||
"registration_no_sso": "The register operation is only for registering with a password.\n\n"
|
||||
"To register with SSO, simply leave out the --register flag.",
|
||||
"server_not_found": (
|
||||
"Registration target server not found.\n\n"
|
||||
"To log in or register through maubot, you must add the server to the\n"
|
||||
"homeservers section in the config. If you only want to log in,\n"
|
||||
"leave the `secret` field empty."
|
||||
),
|
||||
"registration_no_sso": (
|
||||
"The register operation is only for registering with a password.\n\n"
|
||||
"To register with SSO, simply leave out the --register flag."
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
|
@ -46,26 +50,58 @@ async def list_servers(server: str, sess: aiohttp.ClientSession) -> None:
|
|||
|
||||
@cliq.command(help="Log into a Matrix account via the Maubot server")
|
||||
@cliq.option("-h", "--homeserver", help="The homeserver to log into", required_unless="list")
|
||||
@cliq.option("-u", "--username", help="The username to log in with",
|
||||
required_unless=["list", "sso"])
|
||||
@cliq.option("-p", "--password", help="The password to log in with", inq_type="password",
|
||||
required_unless=["list", "sso"])
|
||||
@cliq.option("-s", "--server", help="The maubot instance to log in through", default="",
|
||||
required=False, prompt=False)
|
||||
@click.option("-r", "--register", help="Register instead of logging in", is_flag=True,
|
||||
default=False)
|
||||
@click.option("-c", "--update-client", help="Instead of returning the access token, "
|
||||
"create or update a client in maubot using it",
|
||||
is_flag=True, default=False)
|
||||
@cliq.option(
|
||||
"-u", "--username", help="The username to log in with", required_unless=["list", "sso"]
|
||||
)
|
||||
@cliq.option(
|
||||
"-p",
|
||||
"--password",
|
||||
help="The password to log in with",
|
||||
inq_type="password",
|
||||
required_unless=["list", "sso"],
|
||||
)
|
||||
@cliq.option(
|
||||
"-s",
|
||||
"--server",
|
||||
help="The maubot instance to log in through",
|
||||
default="",
|
||||
required=False,
|
||||
prompt=False,
|
||||
)
|
||||
@click.option(
|
||||
"-r", "--register", help="Register instead of logging in", is_flag=True, default=False
|
||||
)
|
||||
@click.option(
|
||||
"-c",
|
||||
"--update-client",
|
||||
help="Instead of returning the access token, " "create or update a client in maubot using it",
|
||||
is_flag=True,
|
||||
default=False,
|
||||
)
|
||||
@click.option("-l", "--list", help="List available homeservers", is_flag=True, default=False)
|
||||
@click.option("-o", "--sso", help="Use single sign-on instead of password login",
|
||||
is_flag=True, default=False)
|
||||
@click.option("-n", "--device-name", help="The initial e2ee device displayname (only for login)",
|
||||
default="Maubot", required=False)
|
||||
@click.option(
|
||||
"-o", "--sso", help="Use single sign-on instead of password login", is_flag=True, default=False
|
||||
)
|
||||
@click.option(
|
||||
"-n",
|
||||
"--device-name",
|
||||
help="The initial e2ee device displayname (only for login)",
|
||||
default="Maubot",
|
||||
required=False,
|
||||
)
|
||||
@cliq.with_authenticated_http
|
||||
async def auth(homeserver: str, username: str, password: str, server: str, register: bool,
|
||||
list: bool, update_client: bool, device_name: str, sso: bool,
|
||||
sess: aiohttp.ClientSession) -> None:
|
||||
async def auth(
|
||||
homeserver: str,
|
||||
username: str,
|
||||
password: str,
|
||||
server: str,
|
||||
register: bool,
|
||||
list: bool,
|
||||
update_client: bool,
|
||||
device_name: str,
|
||||
sso: bool,
|
||||
sess: aiohttp.ClientSession,
|
||||
) -> None:
|
||||
if list:
|
||||
await list_servers(server, sess)
|
||||
return
|
||||
|
@ -88,8 +124,9 @@ async def auth(homeserver: str, username: str, password: str, server: str, regis
|
|||
await print_response(resp, is_register=register)
|
||||
|
||||
|
||||
async def wait_sso(resp: aiohttp.ClientResponse, sess: aiohttp.ClientSession,
|
||||
server: str, homeserver: str) -> None:
|
||||
async def wait_sso(
|
||||
resp: aiohttp.ClientResponse, sess: aiohttp.ClientSession, server: str, homeserver: str
|
||||
) -> None:
|
||||
data = await resp.json()
|
||||
sso_url, reg_id = data["sso_url"], data["id"]
|
||||
print(f"{Fore.GREEN}Opening {Fore.CYAN}{sso_url}{Fore.RESET}")
|
||||
|
@ -110,9 +147,11 @@ async def print_response(resp: aiohttp.ClientResponse, is_register: bool) -> Non
|
|||
elif resp.status in (201, 202):
|
||||
data = await resp.json()
|
||||
action = "created" if resp.status == 201 else "updated"
|
||||
print(f"{Fore.GREEN}Successfully {action} client for "
|
||||
f"{Fore.CYAN}{data['id']}{Fore.GREEN} / "
|
||||
f"{Fore.CYAN}{data['device_id']}{Fore.GREEN}.{Fore.RESET}")
|
||||
print(
|
||||
f"{Fore.GREEN}Successfully {action} client for "
|
||||
f"{Fore.CYAN}{data['id']}{Fore.GREEN} / "
|
||||
f"{Fore.CYAN}{data['device_id']}{Fore.GREEN}.{Fore.RESET}"
|
||||
)
|
||||
else:
|
||||
await print_error(resp, is_register)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# maubot - A plugin-based Matrix bot system.
|
||||
# Copyright (C) 2019 Tulir Asokan
|
||||
# Copyright (C) 2022 Tulir Asokan
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
|
@ -13,26 +13,28 @@
|
|||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
from typing import Optional, Union, IO
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import IO
|
||||
from io import BytesIO
|
||||
import zipfile
|
||||
import asyncio
|
||||
import glob
|
||||
import os
|
||||
import zipfile
|
||||
|
||||
from ruamel.yaml import YAML, YAMLError
|
||||
from aiohttp import ClientSession
|
||||
from questionary import prompt
|
||||
from colorama import Fore
|
||||
from questionary import prompt
|
||||
from ruamel.yaml import YAML, YAMLError
|
||||
import click
|
||||
|
||||
from mautrix.types import SerializerError
|
||||
|
||||
from ...loader import PluginMeta
|
||||
from ..cliq.validators import PathValidator
|
||||
from ..base import app
|
||||
from ..config import get_token
|
||||
from ..cliq import cliq
|
||||
from ..cliq.validators import PathValidator
|
||||
from ..config import get_token
|
||||
from .upload import upload_file
|
||||
|
||||
yaml = YAML()
|
||||
|
@ -44,7 +46,7 @@ def zipdir(zip, dir):
|
|||
zip.write(os.path.join(root, file))
|
||||
|
||||
|
||||
def read_meta(path: str) -> Optional[PluginMeta]:
|
||||
def read_meta(path: str) -> PluginMeta | None:
|
||||
try:
|
||||
with open(os.path.join(path, "maubot.yaml")) as meta_file:
|
||||
try:
|
||||
|
@ -65,7 +67,7 @@ def read_meta(path: str) -> Optional[PluginMeta]:
|
|||
return meta
|
||||
|
||||
|
||||
def read_output_path(output: str, meta: PluginMeta) -> Optional[str]:
|
||||
def read_output_path(output: str, meta: PluginMeta) -> str | None:
|
||||
directory = os.getcwd()
|
||||
filename = f"{meta.id}-v{meta.version}.mbp"
|
||||
if not output:
|
||||
|
@ -73,18 +75,15 @@ def read_output_path(output: str, meta: PluginMeta) -> Optional[str]:
|
|||
elif os.path.isdir(output):
|
||||
output = os.path.join(output, filename)
|
||||
elif os.path.exists(output):
|
||||
override = prompt({
|
||||
"type": "confirm",
|
||||
"name": "override",
|
||||
"message": f"{output} exists, override?"
|
||||
})["override"]
|
||||
q = [{"type": "confirm", "name": "override", "message": f"{output} exists, override?"}]
|
||||
override = prompt(q)["override"]
|
||||
if not override:
|
||||
return None
|
||||
os.remove(output)
|
||||
return os.path.abspath(output)
|
||||
|
||||
|
||||
def write_plugin(meta: PluginMeta, output: Union[str, IO]) -> None:
|
||||
def write_plugin(meta: PluginMeta, output: str | IO) -> None:
|
||||
with zipfile.ZipFile(output, "w") as zip:
|
||||
meta_dump = BytesIO()
|
||||
yaml.dump(meta.serialize(), meta_dump)
|
||||
|
@ -104,7 +103,7 @@ def write_plugin(meta: PluginMeta, output: Union[str, IO]) -> None:
|
|||
|
||||
|
||||
@cliq.with_authenticated_http
|
||||
async def upload_plugin(output: Union[str, IO], *, server: str, sess: ClientSession) -> None:
|
||||
async def upload_plugin(output: str | IO, *, server: str, sess: ClientSession) -> None:
|
||||
server, token = get_token(server)
|
||||
if not token:
|
||||
return
|
||||
|
@ -115,14 +114,20 @@ async def upload_plugin(output: Union[str, IO], *, server: str, sess: ClientSess
|
|||
await upload_file(sess, output, server)
|
||||
|
||||
|
||||
@app.command(short_help="Build a maubot plugin",
|
||||
help="Build a maubot plugin. First parameter is the path to root of the plugin "
|
||||
"to build. You can also use --output to specify output file.")
|
||||
@app.command(
|
||||
short_help="Build a maubot plugin",
|
||||
help=(
|
||||
"Build a maubot plugin. First parameter is the path to root of the plugin "
|
||||
"to build. You can also use --output to specify output file."
|
||||
),
|
||||
)
|
||||
@click.argument("path", default=os.getcwd())
|
||||
@click.option("-o", "--output", help="Path to output built plugin to",
|
||||
type=PathValidator.click_type)
|
||||
@click.option("-u", "--upload", help="Upload plugin to server after building", is_flag=True,
|
||||
default=False)
|
||||
@click.option(
|
||||
"-o", "--output", help="Path to output built plugin to", type=PathValidator.click_type
|
||||
)
|
||||
@click.option(
|
||||
"-u", "--upload", help="Upload plugin to server after building", is_flag=True, default=False
|
||||
)
|
||||
@click.option("-s", "--server", help="Server to upload built plugin to")
|
||||
def build(path: str, output: str, upload: bool, server: str) -> None:
|
||||
meta = read_meta(path)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# maubot - A plugin-based Matrix bot system.
|
||||
# Copyright (C) 2019 Tulir Asokan
|
||||
# Copyright (C) 2022 Tulir Asokan
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
|
@ -13,11 +13,11 @@
|
|||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
from pkg_resources import resource_string
|
||||
import os
|
||||
|
||||
from packaging.version import Version
|
||||
from jinja2 import Template
|
||||
from packaging.version import Version
|
||||
from pkg_resources import resource_string
|
||||
|
||||
from .. import cliq
|
||||
from ..cliq import SPDXValidator, VersionValidator
|
||||
|
@ -40,26 +40,55 @@ def load_templates():
|
|||
|
||||
|
||||
@cliq.command(help="Initialize a new maubot plugin")
|
||||
@cliq.option("-n", "--name", help="The name of the project", required=True,
|
||||
default=os.path.basename(os.getcwd()))
|
||||
@cliq.option("-i", "--id", message="ID", required=True,
|
||||
help="The maubot plugin ID (Java package name format)")
|
||||
@cliq.option("-v", "--version", help="Initial version for project (PEP-440 format)",
|
||||
default="0.1.0", validator=VersionValidator, required=True)
|
||||
@cliq.option("-l", "--license", validator=SPDXValidator, default="AGPL-3.0-or-later",
|
||||
help="The license for the project (SPDX identifier)", required=False)
|
||||
@cliq.option("-c", "--config", message="Should the plugin include a config?",
|
||||
help="Include a config in the plugin stub", default=False, is_flag=True)
|
||||
@cliq.option(
|
||||
"-n",
|
||||
"--name",
|
||||
help="The name of the project",
|
||||
required=True,
|
||||
default=os.path.basename(os.getcwd()),
|
||||
)
|
||||
@cliq.option(
|
||||
"-i",
|
||||
"--id",
|
||||
message="ID",
|
||||
required=True,
|
||||
help="The maubot plugin ID (Java package name format)",
|
||||
)
|
||||
@cliq.option(
|
||||
"-v",
|
||||
"--version",
|
||||
help="Initial version for project (PEP-440 format)",
|
||||
default="0.1.0",
|
||||
validator=VersionValidator,
|
||||
required=True,
|
||||
)
|
||||
@cliq.option(
|
||||
"-l",
|
||||
"--license",
|
||||
validator=SPDXValidator,
|
||||
default="AGPL-3.0-or-later",
|
||||
help="The license for the project (SPDX identifier)",
|
||||
required=False,
|
||||
)
|
||||
@cliq.option(
|
||||
"-c",
|
||||
"--config",
|
||||
message="Should the plugin include a config?",
|
||||
help="Include a config in the plugin stub",
|
||||
default=False,
|
||||
is_flag=True,
|
||||
)
|
||||
def init(name: str, id: str, version: Version, license: str, config: bool) -> None:
|
||||
load_templates()
|
||||
main_class = name[0].upper() + name[1:]
|
||||
meta = meta_template.render(id=id, version=str(version), license=license, config=config,
|
||||
main_class=main_class)
|
||||
meta = meta_template.render(
|
||||
id=id, version=str(version), license=license, config=config, main_class=main_class
|
||||
)
|
||||
with open("maubot.yaml", "w") as file:
|
||||
file.write(meta)
|
||||
if license:
|
||||
with open("LICENSE", "w") as file:
|
||||
file.write(spdx.get(license)["text"])
|
||||
file.write(spdx.get(license)["licenseText"])
|
||||
if not os.path.isdir(name):
|
||||
os.mkdir(name)
|
||||
mod = mod_template.render(config=config, name=main_class)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# maubot - A plugin-based Matrix bot system.
|
||||
# Copyright (C) 2021 Tulir Asokan
|
||||
# Copyright (C) 2022 Tulir Asokan
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
|
@ -20,17 +20,39 @@ from colorama import Fore
|
|||
from yarl import URL
|
||||
import aiohttp
|
||||
|
||||
from ..config import save_config, config
|
||||
from ..cliq import cliq
|
||||
from ..config import config, save_config
|
||||
|
||||
|
||||
@cliq.command(help="Log in to a Maubot instance")
|
||||
@cliq.option("-u", "--username", help="The username of your account", default=os.environ.get("USER", None), required=True)
|
||||
@cliq.option("-p", "--password", help="The password to your account", inq_type="password", required=True)
|
||||
@cliq.option("-s", "--server", help="The server to log in to", default="http://localhost:29316", required=True)
|
||||
@cliq.option("-a", "--alias", help="Alias to reference the server without typing the full URL", default="", required=False)
|
||||
@cliq.option(
|
||||
"-u",
|
||||
"--username",
|
||||
help="The username of your account",
|
||||
default=os.environ.get("USER", None),
|
||||
required=True,
|
||||
)
|
||||
@cliq.option(
|
||||
"-p", "--password", help="The password to your account", inq_type="password", required=True
|
||||
)
|
||||
@cliq.option(
|
||||
"-s",
|
||||
"--server",
|
||||
help="The server to log in to",
|
||||
default="http://localhost:29316",
|
||||
required=True,
|
||||
)
|
||||
@cliq.option(
|
||||
"-a",
|
||||
"--alias",
|
||||
help="Alias to reference the server without typing the full URL",
|
||||
default="",
|
||||
required=False,
|
||||
)
|
||||
@cliq.with_http
|
||||
async def login(server: str, username: str, password: str, alias: str, sess: aiohttp.ClientSession) -> None:
|
||||
async def login(
|
||||
server: str, username: str, password: str, alias: str, sess: aiohttp.ClientSession
|
||||
) -> None:
|
||||
data = {
|
||||
"username": username,
|
||||
"password": password,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# maubot - A plugin-based Matrix bot system.
|
||||
# Copyright (C) 2019 Tulir Asokan
|
||||
# Copyright (C) 2022 Tulir Asokan
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
|
@ -16,14 +16,14 @@
|
|||
from datetime import datetime
|
||||
import asyncio
|
||||
|
||||
from aiohttp import ClientSession, WSMessage, WSMsgType
|
||||
from colorama import Fore
|
||||
from aiohttp import WSMsgType, WSMessage, ClientSession
|
||||
import click
|
||||
|
||||
from mautrix.types import Obj
|
||||
|
||||
from ..config import get_token
|
||||
from ..base import app
|
||||
from ..config import get_token
|
||||
|
||||
history_count: int = 10
|
||||
|
||||
|
@ -50,7 +50,7 @@ def logs(server: str, tail: int) -> None:
|
|||
def parsedate(entry: Obj) -> None:
|
||||
i = entry.time.index("+")
|
||||
i = entry.time.index(":", i)
|
||||
entry.time = entry.time[:i] + entry.time[i + 1:]
|
||||
entry.time = entry.time[:i] + entry.time[i + 1 :]
|
||||
entry.time = datetime.strptime(entry.time, "%Y-%m-%dT%H:%M:%S.%f%z")
|
||||
|
||||
|
||||
|
@ -66,13 +66,16 @@ levelcolors = {
|
|||
def print_entry(entry: dict) -> None:
|
||||
entry = Obj(**entry)
|
||||
parsedate(entry)
|
||||
print("{levelcolor}[{date}] [{level}@{logger}] {message}{resetcolor}"
|
||||
.format(date=entry.time.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
level=entry.levelname,
|
||||
levelcolor=levelcolors.get(entry.levelname, ""),
|
||||
resetcolor=Fore.RESET,
|
||||
logger=entry.name,
|
||||
message=entry.msg))
|
||||
print(
|
||||
"{levelcolor}[{date}] [{level}@{logger}] {message}{resetcolor}".format(
|
||||
date=entry.time.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
level=entry.levelname,
|
||||
levelcolor=levelcolors.get(entry.levelname, ""),
|
||||
resetcolor=Fore.RESET,
|
||||
logger=entry.name,
|
||||
message=entry.msg,
|
||||
)
|
||||
)
|
||||
if entry.exc_info:
|
||||
print(entry.exc_info)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# maubot - A plugin-based Matrix bot system.
|
||||
# Copyright (C) 2021 Tulir Asokan
|
||||
# Copyright (C) 2022 Tulir Asokan
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
|
@ -43,8 +43,10 @@ async def upload_file(sess: aiohttp.ClientSession, file: IO, server: str) -> Non
|
|||
async with sess.post(url, data=file, headers=headers) as resp:
|
||||
if resp.status in (200, 201):
|
||||
data = await resp.json()
|
||||
print(f"{Fore.GREEN}Plugin {Fore.CYAN}{data['id']} v{data['version']}{Fore.GREEN} "
|
||||
f"uploaded to {Fore.CYAN}{server}{Fore.GREEN} successfully.{Fore.RESET}")
|
||||
print(
|
||||
f"{Fore.GREEN}Plugin {Fore.CYAN}{data['id']} v{data['version']}{Fore.GREEN} "
|
||||
f"uploaded to {Fore.CYAN}{server}{Fore.GREEN} successfully.{Fore.RESET}"
|
||||
)
|
||||
else:
|
||||
try:
|
||||
err = await resp.json()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue