mirror of
https://github.com/mautrix/telegram.git
synced 2026-05-16 23:15:45 +03:00
171 lines
7.1 KiB
Python
171 lines
7.1 KiB
Python
# -*- coding: future_fstrings -*-
|
|
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
|
# Copyright (C) 2018 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
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Affero General Public License for more details.
|
|
#
|
|
# 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 mautrix_appservice import MatrixRequestError
|
|
|
|
from . import command_handler
|
|
from .. import puppet as pu, portal as po
|
|
|
|
|
|
async def _find_rooms(intent):
|
|
management_rooms = []
|
|
unidentified_rooms = []
|
|
portals = []
|
|
empty_portals = []
|
|
|
|
rooms = await intent.get_joined_rooms()
|
|
for room in rooms:
|
|
portal = po.Portal.get_by_mxid(room)
|
|
if not portal:
|
|
try:
|
|
members = await intent.get_room_members(room)
|
|
except MatrixRequestError:
|
|
members = []
|
|
if len(members) == 2:
|
|
other_member = members[0] if members[0] != intent.mxid else members[1]
|
|
if pu.Puppet.get_id_from_mxid(other_member):
|
|
unidentified_rooms.append(room)
|
|
else:
|
|
management_rooms.append((room, other_member))
|
|
else:
|
|
unidentified_rooms.append(room)
|
|
else:
|
|
members = await portal.get_authenticated_matrix_users()
|
|
if len(members) == 0:
|
|
empty_portals.append(portal)
|
|
else:
|
|
portals.append(portal)
|
|
|
|
return management_rooms, unidentified_rooms, portals, empty_portals
|
|
|
|
|
|
@command_handler(needs_admin=True, needs_auth=False, name="clean-rooms")
|
|
async def clean_rooms(evt):
|
|
if not evt.is_management:
|
|
return await evt.reply("`clean-rooms` is a particularly spammy command. Please don't "
|
|
"run it in non-management rooms.")
|
|
|
|
management_rooms, unidentified_rooms, portals, empty_portals = await _find_rooms(evt.az.intent)
|
|
|
|
reply = ["#### Management rooms (M)"]
|
|
reply += ([f"{n+1}. [M{n+1}](https://matrix.to/#/{room}) (with {other_member}"
|
|
for n, (room, other_member) in enumerate(management_rooms)]
|
|
or ["No management rooms found."])
|
|
reply.append("#### Active portal rooms (A)")
|
|
reply += ([f"{n+1}. [P{n+1}](https://matrix.to/#/{portal.mxid}) "
|
|
f"(to Telegram chat \"{portal.title}\")"
|
|
for n, portal in enumerate(portals)]
|
|
or ["No active portal rooms found."])
|
|
reply.append("#### Unidentified rooms (U)")
|
|
reply += ([f"{n+1}. [U{n+1}](https://matrix.to/#/{room})"
|
|
for n, room in enumerate(unidentified_rooms)]
|
|
or ["No unidentified rooms found."])
|
|
reply.append("#### Inactive portal rooms (I)")
|
|
reply += ([f"{n}. [E{n}](https://matrix.to/#/{portal.mxid}) "
|
|
f"(to Telegram chat \"{portal.title}\")"
|
|
for n, portal in enumerate(empty_portals)]
|
|
or ["No inactive portal rooms found."])
|
|
|
|
reply += ["#### Usage",
|
|
("To clean the recommended set of rooms (unidentified & inactive portals), "
|
|
"type `$cmdprefix+sp clean-recommended`"),
|
|
"",
|
|
("To clean other groups of rooms, type `$cmdprefix+sp clean-groups <letters>` "
|
|
"where `letters` are the first letters of the group names (M, A, U, I)"),
|
|
"",
|
|
("To clean specific rooms, type `$cmdprefix+sp clean-range <range>` "
|
|
"where `range` is the range (e.g. `5-21`) prefixed with the first letter of"
|
|
"the group name."),
|
|
"",
|
|
("Please note that you will have to re-run `$cmdprefix+sp cleanrooms` "
|
|
"between each use of the commands above.")]
|
|
|
|
evt.sender.command_status = {
|
|
"next": lambda clean_evt: set_rooms_to_clean(clean_evt, management_rooms,
|
|
unidentified_rooms, portals, empty_portals),
|
|
"action": "Room cleaning",
|
|
}
|
|
|
|
return await evt.reply("\n".join(reply))
|
|
|
|
|
|
async def set_rooms_to_clean(evt, management_rooms, unidentified_rooms, portals, empty_portals):
|
|
command = evt.args[0]
|
|
rooms_to_clean = []
|
|
if command == "clean-recommended":
|
|
rooms_to_clean = empty_portals + unidentified_rooms
|
|
elif command == "clean-groups":
|
|
if len(evt.args) < 2:
|
|
return await evt.reply("**Usage:** `$cmdprefix+sp clean-groups [M][A][U][I]")
|
|
groups_to_clean = evt.args[1]
|
|
if "M" in groups_to_clean:
|
|
rooms_to_clean += management_rooms
|
|
if "A" in groups_to_clean:
|
|
rooms_to_clean += portals
|
|
if "U" in groups_to_clean:
|
|
rooms_to_clean += unidentified_rooms
|
|
if "I" in groups_to_clean:
|
|
rooms_to_clean += empty_portals
|
|
elif command == "clean-range":
|
|
try:
|
|
range = evt.args[1]
|
|
group, range = range[0], range[1:]
|
|
start, end = range.split("-")
|
|
start, end = int(start), int(end)
|
|
if group == "M":
|
|
group = management_rooms
|
|
elif group == "A":
|
|
group = portals
|
|
elif group == "U":
|
|
group = unidentified_rooms
|
|
elif group == "I":
|
|
group = empty_portals
|
|
else:
|
|
raise ValueError("Unknown group")
|
|
rooms_to_clean = group[start - 1:end]
|
|
except (KeyError, ValueError):
|
|
return await evt.reply(
|
|
"**Usage:** `$cmdprefix+sp clean-groups <_M|A|U|I_><range>")
|
|
else:
|
|
return await evt.reply(f"Unknown room cleaning action `{command}`. "
|
|
"Use `$cmdprefix+sp cancel` to cancel room "
|
|
"cleaning.")
|
|
|
|
evt.sender.command_status = {
|
|
"next": lambda confirm: execute_room_cleanup(confirm, rooms_to_clean),
|
|
"action": "Room cleaning",
|
|
}
|
|
await evt.reply(f"To confirm cleaning up {len(rooms_to_clean)} rooms, type"
|
|
"`$cmdprefix+sp confirm-clean`.")
|
|
|
|
|
|
async def execute_room_cleanup(evt, rooms_to_clean):
|
|
if len(evt.args) > 0 and evt.args[0] == "confirm-clean":
|
|
await evt.reply(f"Cleaning {len(rooms_to_clean)} rooms. "
|
|
"This might take a while.")
|
|
cleaned = 0
|
|
for room in rooms_to_clean:
|
|
if isinstance(room, po.Portal):
|
|
await room.cleanup_and_delete()
|
|
cleaned += 1
|
|
elif isinstance(room, str):
|
|
await po.Portal.cleanup_room(evt.az.intent, room, message="Room deleted")
|
|
cleaned += 1
|
|
evt.sender.command_status = None
|
|
await evt.reply(f"{cleaned} rooms cleaned up successfully.")
|
|
else:
|
|
await evt.reply("Room cleaning cancelled.")
|