Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add config limits for portal rooms #469

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions mautrix_telegram/commands/portal/bridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ async def bridge(evt: CommandEvent) -> EventID:
"`$cmdprefix+sp delete-and-continue`. To unbridge the portal "
"without kicking Matrix users, use `$cmdprefix+sp unbridge-and-"
"continue`. To cancel, use `$cmdprefix+sp cancel`")

if await po.Portal.reached_portal_limit():
return await evt.reply("This bridge has reached the maximum number of rooms that "
"can be bridged.")

evt.sender.command_status = {
"next": confirm_bridge,
"action": "Room bridging",
Expand Down
1 change: 1 addition & 0 deletions mautrix_telegram/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ def do_update(self, helper: ConfigUpdateHelper) -> None:
copy("bridge.backfill.missed_limit")
copy("bridge.backfill.disable_notifications")
copy("bridge.backfill.normal_groups")
copy("bridge.max_portal_rooms")

copy("bridge.initial_power_level_overrides.group")
copy("bridge.initial_power_level_overrides.user")
Expand Down
15 changes: 12 additions & 3 deletions mautrix_telegram/db/portal.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from typing import Optional, Iterable

from sqlalchemy import Column, Integer, String, Boolean, Text, func, sql
from sqlalchemy import Column, Integer, String, Boolean, Text, func, sql, select

from mautrix.types import RoomID, ContentURI
from mautrix.util.db import Base
Expand Down Expand Up @@ -54,8 +54,13 @@ def find_private_chats(cls, tg_receiver: TelegramID) -> Iterable['Portal']:
yield from cls._select_all(cls.c.tg_receiver == tg_receiver, cls.c.peer_type == "user")

@classmethod
def get_by_mxid(cls, mxid: RoomID) -> Optional['Portal']:
return cls._select_one_or_none(cls.c.mxid == mxid)
def count(cls) -> int:
rows = cls.db.execute(select([func.count()]))
try:
count, = next(rows)
return count
except StopIteration:
return 0

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Baby's first Python commits (don't commit blindly):

Suggested change
rows = cls.db.execute(select([func.count()]))
try:
count, = next(rows)
return count
except StopIteration:
return 0
return cls.db.query(func.count('*')).scalar()

Please test this. I haven't actually run this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No good unfortunately,

AttributeError: 'Engine' object has no attribute 'query'

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The table to count rows in probably needs to be specified somewhere 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh derp, I thought that was implied somewhere


@classmethod
def get_by_username(cls, username: str) -> Optional['Portal']:
Expand All @@ -64,3 +69,7 @@ def get_by_username(cls, username: str) -> Optional['Portal']:
@classmethod
def all(cls) -> Iterable['Portal']:
yield from cls._select_all()

@classmethod
def get_by_mxid(cls, mxid: RoomID) -> Integer:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems to have been changed accidentally

return cls._select_one_or_none(cls.c.mxid == mxid)
3 changes: 3 additions & 0 deletions mautrix_telegram/example-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ bridge:
# Whether or not created rooms should have federation enabled.
# If false, created portal rooms will never be federated.
federate_rooms: true
# The maximum number of rooms that can be bridged on this instance.
# When the maximum number of rooms has been reached, attempts to create new links will error. Set to -1 to disable.
max_portal_rooms: -1
# Settings for converting animated stickers.
animated_sticker:
# Format to which animated stickers should be converted.
Expand Down
8 changes: 8 additions & 0 deletions mautrix_telegram/portal/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,7 @@ def find_by_username(cls, username: str) -> Optional['Portal']:

return None


@classmethod
def get_by_tgid(cls, tgid: TelegramID, tg_receiver: Optional[TelegramID] = None,
peer_type: str = None) -> Optional['Portal']:
Expand Down Expand Up @@ -456,6 +457,13 @@ def get_by_entity(cls, entity: Union[TypeChat, TypePeer, TypeUser, TypeUserFull,
receiver_id if type_name == "user" else entity_id,
type_name if create else None)

@classmethod
async def reached_portal_limit(cls) -> bool:
limit = config.get("bridge.max_portal_rooms", -1)
if limit == -1:
return False
return DBPortal.count() >= limit

# endregion
# region Abstract methods (cross-called in matrix/metadata/telegram classes)

Expand Down
6 changes: 6 additions & 0 deletions mautrix_telegram/portal/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ async def create_telegram_chat(self, source: 'u.User', supergroup: bool = False)
raise ValueError("Can't create Telegram chat for portal without Matrix room.")
elif self.tgid:
raise ValueError("Can't create Telegram chat for portal with existing Telegram chat.")
elif await self.reached_portal_limit():
raise ValueError("Can't create Telegram chat, reached portal limit.")

invites = await self._get_telegram_users_in_matrix_room()
if len(invites) < 2:
Expand Down Expand Up @@ -303,6 +305,10 @@ async def _create_matrix_room(self, user: 'AbstractUser', entity: Union[TypeChat
direct = self.peer_type == "user"
invites = invites or []

if await self.reached_portal_limit():
raise ValueError("Can't create Telegram chat, reached portal limit.")


if not entity:
entity = await self.get_entity(user)
self.log.trace("Fetched data: %s", entity)
Expand Down