Add room unbridge command
This commit is contained in:
@@ -85,6 +85,8 @@
|
||||
* [x] Upgrading the chat of a portal room into a supergroup (`upgrade`)
|
||||
* [x] Change username of supergroup/channel (`group-name`)
|
||||
* [x] Getting the Telegram invite link to a Matrix room (`invite-link`)
|
||||
* [ ] Bridging existing Matrix rooms to existing Telegram chats (`bridge`)
|
||||
* [ ] Unbridging Matrix rooms from Telegram chats (`unbridge`)
|
||||
* Bridge administration
|
||||
* [x] Clean up and forget a portal room (`delete-portal`)
|
||||
* [x] Find and clean up old portal rooms (`clean-rooms`)
|
||||
|
||||
@@ -127,10 +127,10 @@ class StateStore:
|
||||
def get_power_levels(self, room):
|
||||
return self.power_levels[room]
|
||||
|
||||
def has_power_level(self, room, user, event, is_state_event=False):
|
||||
def has_power_level(self, room, user, event, is_state_event=False, default=None):
|
||||
room_levels = self.power_levels.get(room, {})
|
||||
default_required = (room_levels.get("state_default", 50) if is_state_event
|
||||
else room_levels.get("events_default", 0))
|
||||
default_required = default or (room_levels.get("state_default", 50) if is_state_event
|
||||
else room_levels.get("events_default", 0))
|
||||
required = room_levels.get("events", {}).get(event, default_required)
|
||||
has = room_levels.get("users", {}).get(user, room_levels.get("users_default", 0))
|
||||
return has >= required
|
||||
|
||||
@@ -162,7 +162,7 @@ async def execute_room_cleanup(evt, rooms_to_clean):
|
||||
await room.cleanup_and_delete()
|
||||
cleaned += 1
|
||||
elif isinstance(room, str):
|
||||
await po.Portal.cleanup_room(evt.az.intent, room, type="Room")
|
||||
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.")
|
||||
|
||||
@@ -69,8 +69,10 @@ def help(evt):
|
||||
#### Portal management
|
||||
**upgrade** - Upgrade a normal Telegram group to a supergroup.
|
||||
**invite-link** - Get a Telegram invite link to the current chat.
|
||||
**delete-portal** - Forget the current portal room. Only works for group chats; to delete
|
||||
a private chat portal, simply leave the room.
|
||||
**delete-portal** - Remove all users from the current portal room and forget the portal.
|
||||
Only works for group chats; to delete a private chat portal, simply
|
||||
leave the room.
|
||||
**unbridge** - Remove puppets from the current portal room and forget the portal.
|
||||
**group-name** <_name_|`-`> - Change the username of a supergroup/channel. To disable, use a dash
|
||||
(`-`) as the name.
|
||||
**clean-rooms** - Clean up unused portal/management rooms.
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
from telethon.errors import *
|
||||
from mautrix_appservice import MatrixRequestError
|
||||
|
||||
from .. import portal as po
|
||||
from . import command_handler
|
||||
@@ -38,34 +39,78 @@ async def invite_link(evt):
|
||||
return await evt.reply("You don't have the permission to create an invite link.")
|
||||
|
||||
|
||||
@command_handler(needs_admin=True)
|
||||
async def delete_portal(evt):
|
||||
room_id = evt.args[0] if len(evt.args) > 0 else evt.room_id
|
||||
async def _has_access_to(room, intent, sender, event, default=50):
|
||||
if sender.is_admin:
|
||||
return True
|
||||
# Make sure the state store contains the power levels.
|
||||
try:
|
||||
await intent.get_power_levels(room)
|
||||
except MatrixRequestError:
|
||||
return False
|
||||
return intent.state_store.has_power_level(room, sender.mxid,
|
||||
event=f"net.maunium.telegram.{event}",
|
||||
default=default)
|
||||
|
||||
|
||||
async def _get_portal_and_check_permission(evt, permission, action=None, allow_that=False):
|
||||
room_id = evt.args[0] if len(evt.args) > 0 and allow_that else evt.room_id
|
||||
|
||||
portal = po.Portal.get_by_mxid(room_id)
|
||||
if not portal:
|
||||
that_this = "This" if room_id == evt.room_id else "That"
|
||||
return await evt.reply(f"{that_this} is not a portal room.")
|
||||
return await evt.reply(f"{that_this} is not a portal room."), False
|
||||
|
||||
if not _has_access_to(portal.mxid, portal.main_intent, evt.sender, permission):
|
||||
action = action or f"{permission.replace('_', ' ')}s"
|
||||
return await evt.reply(f"You do not have the permissions to {action}."), False
|
||||
return portal, True
|
||||
|
||||
|
||||
def _get_portal_murder_function(action, room_id, function, command, completed_message):
|
||||
async def post_confirm(confirm):
|
||||
evt.sender.command_status = None
|
||||
if len(confirm.args) > 0 and confirm.args[0] == "confirm-delete":
|
||||
await portal.cleanup_and_delete()
|
||||
confirm.sender.command_status = None
|
||||
if len(confirm.args) > 0 and confirm.args[0] == f"confirm-{command}":
|
||||
await function()
|
||||
if confirm.room_id != room_id:
|
||||
return await confirm.reply("Portal successfully deleted.")
|
||||
return await confirm.reply(completed_message)
|
||||
else:
|
||||
return await confirm.reply("Portal deletion cancelled.")
|
||||
return await confirm.reply(f"{action} cancelled.")
|
||||
|
||||
evt.sender.command_status = {
|
||||
return {
|
||||
"next": post_confirm,
|
||||
"action": "Portal deletion",
|
||||
"action": action,
|
||||
}
|
||||
|
||||
|
||||
@command_handler()
|
||||
async def delete_portal(evt):
|
||||
portal, ok = await _get_portal_and_check_permission(evt, "delete_portal")
|
||||
if not ok:
|
||||
return
|
||||
|
||||
evt.sender.command_status = _get_portal_murder_function("Portal deletion", portal.mxid,
|
||||
portal.cleanup_and_delete, "delete",
|
||||
"Portal successfully deleted.")
|
||||
return await evt.reply("Please confirm deletion of portal "
|
||||
f"[{room_id}](https://matrix.to/#/{room_id}) "
|
||||
f"[{portal.alias or portal.mxid}](https://matrix.to/#/{portal.mxid}) "
|
||||
f"to Telegram chat \"{portal.title}\" "
|
||||
"by typing `$cmdprefix+sp confirm-delete`")
|
||||
|
||||
|
||||
@command_handler()
|
||||
async def unbridge(evt):
|
||||
portal, ok = await _get_portal_and_check_permission(evt, "unbridge_room", allow_that=False)
|
||||
if not ok:
|
||||
return
|
||||
|
||||
evt.sender.command_status = _get_portal_murder_function("Room unbridging", portal.mxid,
|
||||
portal.unbridge, "unbridge",
|
||||
"Room successfully unbridged.")
|
||||
return await evt.reply(f"Please confirm unbridging chat \"{portal.title}\" from room "
|
||||
f"[{portal.alias or portal.mxid}](https://matrix.to/#/{portal.mxid}) "
|
||||
"by typing `$cmdprefix+sp confirm-unbridge`")
|
||||
|
||||
|
||||
async def _get_initial_state(evt):
|
||||
state = await evt.az.intent.get_room_state(evt.room_id)
|
||||
title = None
|
||||
|
||||
@@ -484,19 +484,24 @@ class Portal:
|
||||
return authenticated
|
||||
|
||||
@staticmethod
|
||||
async def cleanup_room(intent, room_id, type="Portal"):
|
||||
async def cleanup_room(intent, room_id, message="Portal deleted", puppets_only=False):
|
||||
try:
|
||||
members = await intent.get_room_members(room_id)
|
||||
except MatrixRequestError:
|
||||
members = []
|
||||
for user in members:
|
||||
if user != intent.mxid:
|
||||
is_puppet = p.Puppet.get_id_from_mxid(user)
|
||||
if user != intent.mxid and (not puppets_only or is_puppet):
|
||||
try:
|
||||
await intent.kick(room_id, user, f"{type} deleted.")
|
||||
await intent.kick(room_id, user, message)
|
||||
except (MatrixRequestError, IntentError):
|
||||
pass
|
||||
await intent.leave_room(room_id)
|
||||
|
||||
async def unbridge(self):
|
||||
await self.cleanup_room(self.main_intent, self.mxid, "Room unbridged", puppets_only=True)
|
||||
self.delete()
|
||||
|
||||
async def cleanup_and_delete(self):
|
||||
await self.cleanup_room(self.main_intent, self.mxid)
|
||||
self.delete()
|
||||
|
||||
Reference in New Issue
Block a user