diff --git a/.gitignore b/.gitignore index 724cb5d..7a0b2c4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ config.yml .idea/ __pycache__/ +*.egg-info/ diff --git a/README.md b/README.md index 715890a..70302c1 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,18 @@ Listens to HTTP only. Should be used behind a reverse-proxy with HTTPS. An example configuration is at `config.yml.example` and the program always reads the configuration file `config.yml`. -## Testing the Hook locally +## Running the command line notifier + +To notify a room with a simple text message, ensure credentials are filled out in your local config.yml and run + +``` +python -m wmn.notify -r '!room:matrix.org' simple text message +``` + +Installing the webhook-matrix-notifier will create the shorthand script "matrix-notify" for this. + + +## Testing the webhook application locally First, start the webserver locally by `env FLASK_APP=wmn.py flask run` or have your IDE start it for you. \ Then, send a POST request using curl. diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..c930171 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,23 @@ +[build-system] +requires = ["setuptools", "setuptools-scm"] +build-backend = "setuptools.build_meta" + +[project] +name = "webhook_matrix_notifier" +authors = [ + {name = "Benedikt Ziemons", email = "ben@rs485.network"}, +] +description = "Flask webhook application for matrix notification and command-line matrix notification tool" +version = "1.1" +readme = "README.md" +requires-python = ">=3.9" +license = {text = "MIT"} +dependencies = [ + "pyyaml", + "flask[async]", + "matrix-nio[e2e]", + "python-dateutil", +] + +[project.scripts] +matrix-notify = "wmn.notify:main" diff --git a/wmn/notify.py b/wmn/notify.py index 51bd9d2..2e642ec 100755 --- a/wmn/notify.py +++ b/wmn/notify.py @@ -39,39 +39,7 @@ from .common import ( room_pattern = re.compile(r"^!\w+:[\w\-.]+$") -async def main(): - """ - config.yml Example: - - matrix: - server: https://matrix.org - username: ... - password: "..." - """ - logging.basicConfig() - cfg = load_configuration() - - parser = argparse.ArgumentParser(description="Notify a Matrix room.") - parser.add_argument( - "-c", "--channel", required=False, help="the channel to send the message to (deprecated, use --room)" - ) - parser.add_argument( - "-r", "--room", required=False, help="the Matrix room to send the message to" - ) - parser.add_argument( - "-t", - "--type", - required=False, - help="the msgtype", - choices=("m.text", "m.notice"), - default="m.text", - ) - parser.add_argument("text", help="the text message to send to the room") - parser.add_argument( - "html", nargs="?", help="the html message to send to the room" - ) - args = parser.parse_args() - +def get_a_room(args): if not args.channel and not args.room: logging.error("Specify the Matrix room to send the message to") sys.exit(1) @@ -83,8 +51,13 @@ async def main(): if room_pattern.fullmatch(room) is None: logging.error("Could not parse Matrix room '%s'", room) sys.exit(1) + return room + +async def login_and_send(args): + cfg = load_configuration() client = await client_login(cfg) + room = get_a_room(args) try: room_id = await resolve_room(client=client, room=room) response = await client.join(room_id=room_id) @@ -108,6 +81,45 @@ async def main(): logging.info("Message sent. %s", response.event_id) -if __name__ == "__main__": +def parse_arguments(): + parser = argparse.ArgumentParser(description="Notify a Matrix room.") + parser.add_argument( + "-c", "--channel", required=False, help="the channel to send the message to (deprecated, use --room)" + ) + parser.add_argument( + "-r", "--room", required=False, help="the Matrix room to send the message to" + ) + parser.add_argument( + "-t", + "--type", + required=False, + help="the msgtype", + choices=("m.text", "m.notice"), + default="m.text", + ) + parser.add_argument("text", help="the text message to send to the room") + parser.add_argument( + "html", nargs="?", help="the html message to send to the room" + ) + return parser.parse_args() + + +def main(): + """ + Config path is local config.yml by default. Specify with environment variable WMN_CONFIG_PATH. + + config.yml Example: + + matrix: + server: https://matrix.org + username: ... + password: "..." + """ + logging.basicConfig() + args = parse_arguments() loop = asyncio.get_event_loop() - loop.run_until_complete(main()) + loop.run_until_complete(login_and_send(args)) + + +if __name__ == "__main__": + main()