+8
-3
@@ -144,11 +144,15 @@ bridge:
|
|||||||
leave: "<b>$displayname</b> left the room."
|
leave: "<b>$displayname</b> left the room."
|
||||||
name_change: "<b>$prev_displayname</b> changed their name to <b>$displayname</b>"
|
name_change: "<b>$prev_displayname</b> changed their name to <b>$displayname</b>"
|
||||||
|
|
||||||
|
# Filter rooms that can/can't be bridged. Can also be managed using the `filter` and
|
||||||
|
# `filter-mode` management commands.
|
||||||
|
#
|
||||||
|
# Filters do not affect direct chats.
|
||||||
|
# An empty blacklist will essentially disable the filter.
|
||||||
filter:
|
filter:
|
||||||
# Filter mode to use. Either "blacklist" or "whitelist".
|
# Filter mode to use. Either "blacklist" or "whitelist".
|
||||||
# If the mode is "blacklist", the listed chats will never be bridged. An empty blacklist disables the filter.
|
# If the mode is "blacklist", the listed chats will never be bridged.
|
||||||
# If the mode is "whitelist", only the listed chats can be bridged.
|
# If the mode is "whitelist", only the listed chats can be bridged.
|
||||||
# Direct chats are not affected.
|
|
||||||
mode: blacklist
|
mode: blacklist
|
||||||
# The list of group/channel IDs to filter.
|
# The list of group/channel IDs to filter.
|
||||||
list: []
|
list: []
|
||||||
@@ -159,6 +163,7 @@ bridge:
|
|||||||
# Permissions for using the bridge.
|
# Permissions for using the bridge.
|
||||||
# Permitted values:
|
# Permitted values:
|
||||||
# relaybot - Only use the bridge via the relaybot, no access to commands.
|
# relaybot - Only use the bridge via the relaybot, no access to commands.
|
||||||
|
# user - Relaybot level + access to commands to create bridges (no puppeting)
|
||||||
# full - Full access to use the bridge via relaybot or logging in with Telegram account.
|
# full - Full access to use the bridge via relaybot or logging in with Telegram account.
|
||||||
# admin - Full access to use the bridge and some extra administration commands.
|
# admin - Full access to use the bridge and some extra administration commands.
|
||||||
# Permitted keys:
|
# Permitted keys:
|
||||||
@@ -167,8 +172,8 @@ bridge:
|
|||||||
# mxid - Specific user
|
# mxid - Specific user
|
||||||
permissions:
|
permissions:
|
||||||
"*": "relaybot"
|
"*": "relaybot"
|
||||||
|
"public.example.com": "user"
|
||||||
"example.com": "full"
|
"example.com": "full"
|
||||||
"public.example.com": "full"
|
|
||||||
"@admin:example.com": "admin"
|
"@admin:example.com": "admin"
|
||||||
|
|
||||||
# Options related to the message relay Telegram bot.
|
# Options related to the message relay Telegram bot.
|
||||||
|
|||||||
@@ -36,7 +36,10 @@ class AbstractUser:
|
|||||||
az = None
|
az = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
self.puppet_whitelisted = False
|
||||||
self.whitelisted = False
|
self.whitelisted = False
|
||||||
|
self.relaybot_whitelisted = False
|
||||||
|
self.is_admin = False
|
||||||
self.client = None
|
self.client = None
|
||||||
self.tgid = None
|
self.tgid = None
|
||||||
self.mxid = None
|
self.mxid = None
|
||||||
@@ -93,7 +96,7 @@ class AbstractUser:
|
|||||||
return self.client and await self.client.is_user_authorized()
|
return self.client and await self.client.is_user_authorized()
|
||||||
|
|
||||||
async def has_full_access(self, allow_bot=False):
|
async def has_full_access(self, allow_bot=False):
|
||||||
return self.whitelisted and (not self.is_bot or allow_bot) and await self.is_logged_in()
|
return self.puppet_whitelisted and (not self.is_bot or allow_bot) and await self.is_logged_in()
|
||||||
|
|
||||||
async def start(self, delete_unless_authenticated=False):
|
async def start(self, delete_unless_authenticated=False):
|
||||||
if not self.client:
|
if not self.client:
|
||||||
@@ -103,7 +106,7 @@ class AbstractUser:
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
async def ensure_started(self, even_if_no_session=False):
|
async def ensure_started(self, even_if_no_session=False):
|
||||||
if not self.whitelisted:
|
if not self.puppet_whitelisted:
|
||||||
return self
|
return self
|
||||||
self.log.debug("ensure_started(%s, connected=%s, even_if_no_session=%s, session_count=%s)",
|
self.log.debug("ensure_started(%s, connected=%s, even_if_no_session=%s, session_count=%s)",
|
||||||
self.mxid, self.connected, even_if_no_session,
|
self.mxid, self.connected, even_if_no_session,
|
||||||
|
|||||||
@@ -39,7 +39,9 @@ class Bot(AbstractUser):
|
|||||||
def __init__(self, token: str):
|
def __init__(self, token: str):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.token = token
|
self.token = token
|
||||||
|
self.puppet_whitelisted = True
|
||||||
self.whitelisted = True
|
self.whitelisted = True
|
||||||
|
self.relaybot_whitelisted = True
|
||||||
self.username = None
|
self.username = None
|
||||||
self.is_relaybot = True
|
self.is_relaybot = True
|
||||||
self.is_bot = True
|
self.is_bot = True
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ async def ping(evt):
|
|||||||
return await evt.reply("You're not logged in.")
|
return await evt.reply("You're not logged in.")
|
||||||
|
|
||||||
|
|
||||||
@command_handler()
|
@command_handler(needs_auth=False, needs_puppeting=False)
|
||||||
async def ping_bot(evt):
|
async def ping_bot(evt):
|
||||||
if not evt.tgbot:
|
if not evt.tgbot:
|
||||||
return await evt.reply("Telegram message relay bot not configured.")
|
return await evt.reply("Telegram message relay bot not configured.")
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ from ..util import format_duration
|
|||||||
command_handlers = {}
|
command_handlers = {}
|
||||||
|
|
||||||
|
|
||||||
def command_handler(needs_auth=True, management_only=False, needs_admin=False, name=None):
|
def command_handler(needs_auth=True, management_only=False, needs_puppeting=True,
|
||||||
|
needs_admin=False, name=None):
|
||||||
def decorator(func):
|
def decorator(func):
|
||||||
async def wrapper(evt):
|
async def wrapper(evt):
|
||||||
if management_only and not evt.is_management:
|
if management_only and not evt.is_management:
|
||||||
@@ -32,8 +33,10 @@ def command_handler(needs_auth=True, management_only=False, needs_admin=False, n
|
|||||||
"you may only run it in management rooms.")
|
"you may only run it in management rooms.")
|
||||||
elif needs_auth and not await evt.sender.is_logged_in():
|
elif needs_auth and not await evt.sender.is_logged_in():
|
||||||
return await evt.reply("This command requires you to be logged in.")
|
return await evt.reply("This command requires you to be logged in.")
|
||||||
|
elif needs_puppeting and not evt.sender.puppet_whitelisted:
|
||||||
|
return await evt.reply("This command requires puppeting privileges.")
|
||||||
elif needs_admin and not evt.sender.is_admin:
|
elif needs_admin and not evt.sender.is_admin:
|
||||||
return await evt.reply("This is command requires administrator privileges.")
|
return await evt.reply("This command requires administrator privileges.")
|
||||||
return await func(evt)
|
return await func(evt)
|
||||||
|
|
||||||
command_handlers[name or func.__name__.replace("_", "-")] = wrapper
|
command_handlers[name or func.__name__.replace("_", "-")] = wrapper
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
from . import command_handler
|
from . import command_handler
|
||||||
|
|
||||||
|
|
||||||
@command_handler(needs_auth=False)
|
@command_handler(needs_auth=False, needs_puppeting=False)
|
||||||
def cancel(evt):
|
def cancel(evt):
|
||||||
if evt.sender.command_status:
|
if evt.sender.command_status:
|
||||||
action = evt.sender.command_status["action"]
|
action = evt.sender.command_status["action"]
|
||||||
@@ -27,12 +27,12 @@ def cancel(evt):
|
|||||||
return evt.reply("No ongoing command.")
|
return evt.reply("No ongoing command.")
|
||||||
|
|
||||||
|
|
||||||
@command_handler(needs_auth=False)
|
@command_handler(needs_auth=False, needs_puppeting=False)
|
||||||
def unknown_command(evt):
|
def unknown_command(evt):
|
||||||
return evt.reply("Unknown command. Try `$cmdprefix+sp help` for help.")
|
return evt.reply("Unknown command. Try `$cmdprefix+sp help` for help.")
|
||||||
|
|
||||||
|
|
||||||
@command_handler(needs_auth=False)
|
@command_handler(needs_auth=False, needs_puppeting=False)
|
||||||
def help(evt):
|
def help(evt):
|
||||||
if evt.is_management:
|
if evt.is_management:
|
||||||
management_status = ("This is a management room: prefixing commands "
|
management_status = ("This is a management room: prefixing commands "
|
||||||
@@ -44,7 +44,24 @@ def help(evt):
|
|||||||
else:
|
else:
|
||||||
management_status = ("**This is not a management room**: you must "
|
management_status = ("**This is not a management room**: you must "
|
||||||
"prefix commands with `$cmdprefix`.\n")
|
"prefix commands with `$cmdprefix`.\n")
|
||||||
help = """\n
|
help = None
|
||||||
|
if not evt.sender.puppet_whitelisted:
|
||||||
|
help = """\n
|
||||||
|
#### Generic bridge commands
|
||||||
|
**help** - Show this help message.
|
||||||
|
**cancel** - Cancel an ongoing action (such as login).
|
||||||
|
**ping-bot** - Get info of the message relay Telegram bot.
|
||||||
|
**invite-link** - Get a Telegram invite link to the current chat.
|
||||||
|
**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.
|
||||||
|
**bridge** [_id_] - Bridge the current Matrix room to the Telegram chat with the given
|
||||||
|
ID. The ID must be the prefixed version that you get with the `/id`
|
||||||
|
command of the Telegram-side bot.
|
||||||
|
|
||||||
|
"""
|
||||||
|
help = help or """\n
|
||||||
#### Generic bridge commands
|
#### Generic bridge commands
|
||||||
**help** - Show this help message.
|
**help** - Show this help message.
|
||||||
**cancel** - Cancel an ongoing action (such as login).
|
**cancel** - Cancel an ongoing action (such as login).
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ def _get_portal_murder_function(action, room_id, function, command, completed_me
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@command_handler(needs_auth=False)
|
@command_handler(needs_auth=False, needs_puppeting=False)
|
||||||
async def delete_portal(evt: CommandEvent):
|
async def delete_portal(evt: CommandEvent):
|
||||||
portal, ok = await _get_portal_and_check_permission(evt, "delete_portal")
|
portal, ok = await _get_portal_and_check_permission(evt, "delete_portal")
|
||||||
if not ok:
|
if not ok:
|
||||||
|
|||||||
@@ -224,9 +224,10 @@ class Config(DictWithRecursion):
|
|||||||
def _get_permissions(self, key):
|
def _get_permissions(self, key):
|
||||||
level = self["bridge.permissions"].get(key, "")
|
level = self["bridge.permissions"].get(key, "")
|
||||||
admin = level == "admin"
|
admin = level == "admin"
|
||||||
whitelisted = level == "full" or admin
|
puppeting = level == "full" or admin
|
||||||
relaybot = level == "relaybot" or whitelisted
|
user = level == "user" or puppeting
|
||||||
return relaybot, whitelisted, admin
|
relaybot = level == "relaybot" or user
|
||||||
|
return relaybot, user, puppeting, admin
|
||||||
|
|
||||||
def get_permissions(self, mxid):
|
def get_permissions(self, mxid):
|
||||||
permissions = self["bridge.permissions"] or {}
|
permissions = self["bridge.permissions"] or {}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ class PublicBridgeWebsite:
|
|||||||
return self.render_login(
|
return self.render_login(
|
||||||
mxid=request.rel_url.query["mxid"] if "mxid" in request.rel_url.query else None,
|
mxid=request.rel_url.query["mxid"] if "mxid" in request.rel_url.query else None,
|
||||||
state=state)
|
state=state)
|
||||||
elif not user.whitelisted:
|
elif not user.puppet_whitelisted:
|
||||||
return self.render_login(mxid=user.mxid, error="You are not whitelisted.", status=403)
|
return self.render_login(mxid=user.mxid, error="You are not whitelisted.", status=403)
|
||||||
await user.ensure_started()
|
await user.ensure_started()
|
||||||
if not await user.is_logged_in():
|
if not await user.is_logged_in():
|
||||||
@@ -160,7 +160,7 @@ class PublicBridgeWebsite:
|
|||||||
return self.render_login(error="Please enter your Matrix ID.", status=400)
|
return self.render_login(error="Please enter your Matrix ID.", status=400)
|
||||||
|
|
||||||
user = await User.get_by_mxid(data["mxid"]).ensure_started()
|
user = await User.get_by_mxid(data["mxid"]).ensure_started()
|
||||||
if not user.whitelisted:
|
if not user.puppet_whitelisted:
|
||||||
return self.render_login(mxid=user.mxid, error="You are not whitelisted.", status=403)
|
return self.render_login(mxid=user.mxid, error="You are not whitelisted.", status=403)
|
||||||
elif await user.is_logged_in():
|
elif await user.is_logged_in():
|
||||||
return self.render_login(mxid=user.mxid, username=user.username)
|
return self.render_login(mxid=user.mxid, username=user.username)
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ class User(AbstractUser):
|
|||||||
|
|
||||||
(self.relaybot_whitelisted,
|
(self.relaybot_whitelisted,
|
||||||
self.whitelisted,
|
self.whitelisted,
|
||||||
|
self.puppet_whitelisted,
|
||||||
self.is_admin) = config.get_permissions(self.mxid)
|
self.is_admin) = config.get_permissions(self.mxid)
|
||||||
|
|
||||||
self.by_mxid[mxid] = self
|
self.by_mxid[mxid] = self
|
||||||
|
|||||||
Reference in New Issue
Block a user