Get reaction limit from server app config
This commit is contained in:
@@ -2319,8 +2319,7 @@ class Portal(DBPortal, BasePortal):
|
|||||||
existing_reacts = await DBReaction.get_by_sender(msg.mxid, msg.mx_room, user.tgid)
|
existing_reacts = await DBReaction.get_by_sender(msg.mxid, msg.mx_room, user.tgid)
|
||||||
new_tg_reactions: list[TypeReaction] = []
|
new_tg_reactions: list[TypeReaction] = []
|
||||||
reactions_to_remove: list[DBReaction] = []
|
reactions_to_remove: list[DBReaction] = []
|
||||||
# TODO use config https://corefork.telegram.org/api/config#reactions-user-max-default
|
max_reactions = await user.get_max_reactions()
|
||||||
max_reactions = 3 if user.is_premium else 1
|
|
||||||
max_reactions -= 1 # Leave one reaction of space for the new reaction
|
max_reactions -= 1 # Leave one reaction of space for the new reaction
|
||||||
for db_reaction in existing_reacts:
|
for db_reaction in existing_reacts:
|
||||||
if db_reaction.reaction == emoji_id:
|
if db_reaction.reaction == emoji_id:
|
||||||
@@ -2862,12 +2861,12 @@ class Portal(DBPortal, BasePortal):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def _get_reaction_limit(sender: TelegramID) -> int:
|
async def _get_reaction_limit(source: au.AbstractUser, sender: TelegramID) -> int:
|
||||||
puppet = await p.Puppet.get_by_tgid(sender, create=False)
|
puppet = await p.Puppet.get_by_tgid(sender, create=False)
|
||||||
# TODO use config https://corefork.telegram.org/api/config#reactions-user-max-default
|
is_premium = puppet and puppet.is_premium
|
||||||
if puppet and puppet.is_premium:
|
if isinstance(source, u.User) and not source.is_bot:
|
||||||
return 3
|
return await source.get_max_reactions(is_premium)
|
||||||
return 1
|
return 3 if is_premium else 1
|
||||||
|
|
||||||
async def _handle_telegram_reactions_locked(
|
async def _handle_telegram_reactions_locked(
|
||||||
self,
|
self,
|
||||||
@@ -2903,7 +2902,7 @@ class Portal(DBPortal, BasePortal):
|
|||||||
else:
|
else:
|
||||||
if is_full or (
|
if is_full or (
|
||||||
new_reactions is not None
|
new_reactions is not None
|
||||||
and len(new_reactions) == await self._get_reaction_limit(sender_id)
|
and len(new_reactions) == await self._get_reaction_limit(source, sender_id)
|
||||||
):
|
):
|
||||||
removed.append(existing_reaction)
|
removed.append(existing_reaction)
|
||||||
# else: assume the reaction is still there, too much effort to fetch it
|
# else: assume the reaction is still there, too much effort to fetch it
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, AsyncGenerator, AsyncIterable, Awaitable, NamedTuple, cast
|
from typing import TYPE_CHECKING, Any, AsyncGenerator, AsyncIterable, Awaitable, NamedTuple, cast
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
import asyncio
|
import asyncio
|
||||||
import time
|
import time
|
||||||
@@ -24,6 +24,7 @@ from telethon.errors import AuthKeyDuplicatedError, RPCError, UnauthorizedError
|
|||||||
from telethon.tl.custom import Dialog
|
from telethon.tl.custom import Dialog
|
||||||
from telethon.tl.functions.account import UpdateStatusRequest
|
from telethon.tl.functions.account import UpdateStatusRequest
|
||||||
from telethon.tl.functions.contacts import GetContactsRequest, SearchRequest
|
from telethon.tl.functions.contacts import GetContactsRequest, SearchRequest
|
||||||
|
from telethon.tl.functions.help import GetAppConfigRequest
|
||||||
from telethon.tl.functions.messages import GetAvailableReactionsRequest
|
from telethon.tl.functions.messages import GetAvailableReactionsRequest
|
||||||
from telethon.tl.functions.updates import GetStateRequest
|
from telethon.tl.functions.updates import GetStateRequest
|
||||||
from telethon.tl.functions.users import GetUsersRequest
|
from telethon.tl.functions.users import GetUsersRequest
|
||||||
@@ -54,7 +55,7 @@ from mautrix.types import PushActionType, PushRuleKind, PushRuleScope, RoomID, R
|
|||||||
from mautrix.util.bridge_state import BridgeState, BridgeStateEvent
|
from mautrix.util.bridge_state import BridgeState, BridgeStateEvent
|
||||||
from mautrix.util.opt_prometheus import Gauge
|
from mautrix.util.opt_prometheus import Gauge
|
||||||
|
|
||||||
from . import portal as po, puppet as pu
|
from . import portal as po, puppet as pu, util
|
||||||
from .abstract_user import AbstractUser
|
from .abstract_user import AbstractUser
|
||||||
from .db import Message as DBMessage, PgSession, User as DBUser
|
from .db import Message as DBMessage, PgSession, User as DBUser
|
||||||
from .types import TelegramID
|
from .types import TelegramID
|
||||||
@@ -91,6 +92,7 @@ class User(DBUser, AbstractUser, BaseUser):
|
|||||||
_available_emoji_reactions_hash: int | None
|
_available_emoji_reactions_hash: int | None
|
||||||
_available_emoji_reactions_fetched: float
|
_available_emoji_reactions_fetched: float
|
||||||
_available_emoji_reactions_lock: asyncio.Lock
|
_available_emoji_reactions_lock: asyncio.Lock
|
||||||
|
_app_config: dict[str, Any] | None
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -121,6 +123,7 @@ class User(DBUser, AbstractUser, BaseUser):
|
|||||||
self._available_emoji_reactions_hash = None
|
self._available_emoji_reactions_hash = None
|
||||||
self._available_emoji_reactions_fetched = 0
|
self._available_emoji_reactions_fetched = 0
|
||||||
self._available_emoji_reactions_lock = asyncio.Lock()
|
self._available_emoji_reactions_lock = asyncio.Lock()
|
||||||
|
self._app_config = None
|
||||||
|
|
||||||
(
|
(
|
||||||
self.relaybot_whitelisted,
|
self.relaybot_whitelisted,
|
||||||
@@ -734,6 +737,25 @@ class User(DBUser, AbstractUser, BaseUser):
|
|||||||
)
|
)
|
||||||
return self._available_emoji_reactions
|
return self._available_emoji_reactions
|
||||||
|
|
||||||
|
def tl_to_json(self) -> Any:
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def get_app_config(self) -> dict[str, Any]:
|
||||||
|
if not self._app_config:
|
||||||
|
cfg = await self.client(GetAppConfigRequest())
|
||||||
|
self._app_config = util.parse_tl_json(cfg)
|
||||||
|
return self._app_config
|
||||||
|
|
||||||
|
async def get_max_reactions(self, is_premium: bool | None = None) -> int:
|
||||||
|
if is_premium is None:
|
||||||
|
is_premium = self.is_premium
|
||||||
|
cfg = await self.get_app_config()
|
||||||
|
return (
|
||||||
|
cfg.get("reactions_user_max_premium", 3)
|
||||||
|
if is_premium
|
||||||
|
else cfg.get("reactions_user_max_default", 1)
|
||||||
|
)
|
||||||
|
|
||||||
# endregion
|
# endregion
|
||||||
# region Class instance lookup
|
# region Class instance lookup
|
||||||
|
|
||||||
|
|||||||
@@ -8,3 +8,4 @@ from .file_transfer import (
|
|||||||
)
|
)
|
||||||
from .parallel_file_transfer import parallel_transfer_to_telegram
|
from .parallel_file_transfer import parallel_transfer_to_telegram
|
||||||
from .recursive_dict import recursive_del, recursive_get, recursive_set
|
from .recursive_dict import recursive_del, recursive_get, recursive_set
|
||||||
|
from .tl_json import parse_tl_json
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# mautrix-telegram - A Matrix-Telegram puppeting bridge
|
||||||
|
# Copyright (C) 2022 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 telethon.tl.types import (
|
||||||
|
JsonArray,
|
||||||
|
JsonBool,
|
||||||
|
JsonNull,
|
||||||
|
JsonNumber,
|
||||||
|
JsonObject,
|
||||||
|
JsonObjectValue,
|
||||||
|
JsonString,
|
||||||
|
TypeJSONValue,
|
||||||
|
)
|
||||||
|
|
||||||
|
from mautrix.types import JSON
|
||||||
|
|
||||||
|
|
||||||
|
def parse_tl_json(val: TypeJSONValue) -> JSON:
|
||||||
|
if isinstance(val, JsonObject):
|
||||||
|
return {entry.key: parse_tl_json(entry.value) for entry in val.value}
|
||||||
|
elif isinstance(val, JsonArray):
|
||||||
|
return [parse_tl_json(item) for item in val.value]
|
||||||
|
elif isinstance(val, (JsonBool, JsonNumber, JsonString)):
|
||||||
|
return val.value
|
||||||
|
elif isinstance(val, JsonNull):
|
||||||
|
return None
|
||||||
|
raise ValueError(f"Unsupported type {type(val)} in TL JSON object")
|
||||||
Reference in New Issue
Block a user