5
0
mirror of https://github.com/spantaleev/matrix-docker-ansible-deploy.git synced 2026-08-16 22:00:59 +00:00
Files
matrix-docker-ansible-deploy/roles/custom/matrix-bot-meowlnir/tasks/util/ensure_bot_created.yml
T
Slavi Pantaleev f9222dc70c Add support for Meowlnir
Meowlnir (https://github.com/maunium/meowlnir) is a Matrix moderation
bot which speaks the same policy-list protocol as Mjolnir and Draupnir,
but runs as an appservice and can override individual policies coming
from ban lists you do not control.

Bots and their management rooms live only in Meowlnir's own database —
nothing in its configuration file can declare one — so the role
provisions them through the management API from a declarative roster
(matrix_bot_meowlnir_bots_custom), applied under the
ensure-matrix-users-created tag. Management rooms may be declared or
created for you; bots and rooms no longer declared get pruned.

Wrapper scripts for driving the management API by hand are installed
to /matrix/meowlnir/bin.

Meowlnir re-runs its configuration upgrader in memory on every start,
so a literal `generate` value yields a new secret per restart. All
secrets are therefore rendered explicitly, validation rejects
`generate`, and the configuration directory is mounted read-only.

Draupnir and Meowlnir both want synapse-http-antispam, which the
playbook wires up to a single consumer. The wiring prefers Draupnir,
and both roles fail the run when each claims it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 06:05:30 +03:00

82 lines
4.0 KiB
YAML

# SPDX-FileCopyrightText: 2026 Slavi Pantaleev
#
# SPDX-License-Identifier: AGPL-3.0-or-later
---
# The management API endpoints are idempotent PUTs, so re-running is safe.
# Meowlnir's own record of this bot, as fetched before the loop started.
# Empty when the bot does not exist yet.
- name: Look up what Meowlnir already knows about the bot - {{ bot.username | quote }}
ansible.builtin.set_fact:
matrix_bot_meowlnir_bot_live: >-
{{
(matrix_bot_meowlnir_live_bots | selectattr('username', 'equalto', bot.username) | list | first)
| default({}, true)
}}
# `PUT /_meowlnir/v1/bot/…` answers 200 whether it created the bot, updated it, or did nothing at all, so the response cannot tell us whether anything changed.
# Comparing against what Meowlnir already holds lets the request be skipped when it would be a no-op, which both avoids pointless calls and lets the task report an honest changed state.
#
# Note that this trusts Meowlnir's own record.
# Changing a bot's profile directly through a Matrix client goes behind its back and will not be corrected here.
- name: Determine whether the Meowlnir bot needs creating or updating - {{ bot.username | quote }}
ansible.builtin.set_fact:
matrix_bot_meowlnir_bot_needs_update: >-
{{
not matrix_bot_meowlnir_bot_live
or (matrix_bot_meowlnir_bot_live.displayname | default('', true)) != bot.displayname
or (matrix_bot_meowlnir_bot_live.avatar_url | default('', true)) != bot.avatar_url
}}
matrix_bot_meowlnir_bot_body: >-
{{
{
'displayname': bot.displayname,
'avatar_url': bot.avatar_url,
}
}}
- name: Ensure Meowlnir bot exists and is up to date - {{ bot.username | quote }}
when: matrix_bot_meowlnir_bot_needs_update | bool
ansible.builtin.command:
cmd: >-
{{ matrix_bot_meowlnir_bin_path }}/meowlnir-api
PUT /_meowlnir/v1/bot/{{ bot.username }}
{{ matrix_bot_meowlnir_bot_body | to_json | quote }}
register: matrix_bot_meowlnir_bot_create_result
# The task only runs when something needs changing, so a successful call is reported as a change.
# Deriving this from the status keeps a failed call from also claiming to have changed anything.
# Meowlnir answers 200 even when it could not apply the displayname or avatar (it only logs that), so this is what was asked for, not proof of what landed. A later run retries, since its stored record is unchanged.
changed_when: "matrix_bot_meowlnir_bot_create_result.stdout_lines | default([]) | last | default('') == '200'"
failed_when: false
- name: Fail if the Meowlnir bot could not be created - {{ bot.username | quote }}
ansible.builtin.fail:
msg: >-
Creating the Meowlnir bot `{{ bot.username }}` failed.
Meowlnir said: {{ matrix_bot_meowlnir_bot_create_result.stdout | default('') | trim }}
{{ matrix_bot_meowlnir_bot_create_result.stderr | default('') | trim }}
when: >-
matrix_bot_meowlnir_bot_needs_update | bool
and (
matrix_bot_meowlnir_bot_create_result.rc | default(1) != 0
or (matrix_bot_meowlnir_bot_create_result.stdout_lines | default([]) | length == 0)
or (matrix_bot_meowlnir_bot_create_result.stdout_lines | last != '200')
)
- name: Determine which management rooms Meowlnir already has for this bot - {{ bot.username | quote }}
ansible.builtin.set_fact:
matrix_bot_meowlnir_bot_live_rooms: >-
{{ matrix_bot_meowlnir_bot_live.management_rooms | default([], true) | map(attribute='room_id') | list }}
- name: Ensure Meowlnir management room created - {{ bot.username | quote }}
when: "bot.management_room_auto_create | bool and matrix_bot_meowlnir_bot_live_rooms | length == 0"
ansible.builtin.include_tasks: "{{ role_path }}/tasks/util/ensure_management_room_created.yml"
- name: Ensure declared Meowlnir management rooms registered - {{ bot.username | quote }}
ansible.builtin.include_tasks: "{{ role_path }}/tasks/util/ensure_management_room_registered.yml"
with_items: "{{ bot.management_rooms }}"
loop_control:
loop_var: management_room