Add room unbridge command

This commit is contained in:
Tulir Asokan
2018-03-01 21:06:23 +02:00
parent 64b60559ee
commit 46cac040c7
6 changed files with 75 additions and 21 deletions
+2
View File
@@ -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`)
+3 -3
View File
@@ -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
+1 -1
View File
@@ -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.")
+4 -2
View File
@@ -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.
+57 -12
View File
@@ -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
+8 -3
View File
@@ -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()