Add deduplication and auto-name for subscriptions

- Config: add_subscription returns None on duplicate (same src, filter, dst)
- Bot: resolve chat titles via get_entity, name rule as
  "src -> dst (filter_value)"; show duplicate message instead of adding

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
bvn13 2026-06-28 18:23:16 +03:00
parent df2cab6b2b
commit 51bd0b4b03
2 changed files with 22 additions and 6 deletions

View File

@ -63,7 +63,7 @@ class Bot():
async def onMessageSub(event):
if not self.__is_admin(event.sender_id):
raise events.StopPropagation
reply = self.__handle_sub_command(event.message.text or "")
reply = await self.__handle_sub_command(event.message.text or "")
await event.reply(reply)
await self.__bot.send_read_acknowledge(event.chat_id, event.message)
raise events.StopPropagation
@ -116,7 +116,7 @@ class Bot():
def __is_admin(self, user_id) -> bool:
return user_id == self.__owner_id or user_id in self.__admin_ids
def __handle_sub_command(self, text: str) -> str:
async def __handle_sub_command(self, text: str) -> str:
parts = text.strip().split()
if len(parts) < 2:
return self.__sub_help()
@ -135,9 +135,13 @@ class Bot():
if ftype not in ('contain', 'regexp'):
return "filter type must be 'contain' or 'regexp'"
value = tokens[5]
rule = self.__config.add_subscription(src, ftype, value, dst)
return "Added #{0}: {1} [{2}] '{3}' -> {4}".format(
rule['id'], src, ftype, value, dst)
src_title = await self.__get_chat_title(src)
dst_title = await self.__get_chat_title(dst)
name = "{0} -> {1} ({2})".format(src_title, dst_title, value)
rule = self.__config.add_subscription(src, ftype, value, dst, name=name)
if rule is None:
return "Already exists: {0} [{1}] '{2}' -> {3}".format(src, ftype, value, dst)
return "Added #{0}: {1}".format(rule['id'], rule.get('name', ''))
if cmd in ('del', 'rm', 'delete'):
sub_id = int(parts[2])
ok = self.__config.remove_subscription(sub_id)
@ -154,6 +158,13 @@ class Bot():
return self.__sub_help()
return self.__sub_help()
async def __get_chat_title(self, chat_id: int) -> str:
try:
entity = await self.__bot.get_entity(chat_id)
return getattr(entity, 'title', None) or getattr(entity, 'username', None) or str(chat_id)
except Exception:
return str(chat_id)
def __sub_list(self) -> str:
subs = self.__config.list_subscriptions()
if not subs:

View File

@ -41,10 +41,15 @@ class Config():
return result
def add_subscription(self, src_chat_id: int, filter_type: str, filter_value: str,
dst_chat_id: int, name: Optional[str] = None) -> dict:
dst_chat_id: int, name: Optional[str] = None) -> Optional[dict]:
with self.__lock:
on_message = self.__config.setdefault('onMessage', {})
rules = on_message.setdefault(str(src_chat_id), [])
for existing in rules:
if (existing.get('filter', {}).get('type') == filter_type and
existing.get('filter', {}).get('value') == filter_value and
existing.get('action', {}).get('chatId') == dst_chat_id):
return None
rule = {
'id': self.__next_id(),
'enabled': True,