From d50ced1b8faca3f442e851f84bb03ec412dbc4b6 Mon Sep 17 00:00:00 2001 From: "2569718930@qq.com" <2569718930@qq.com> Date: Tue, 19 May 2026 18:55:47 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=86=E7=BE=A4=20-1003965137823=20=E7=BA=B3?= =?UTF-8?q?=E5=85=A5=E5=8F=91=E8=A8=80=E7=A7=AF=E5=88=86=E4=BD=93=E7=B3=BB?= =?UTF-8?q?=EF=BC=9A=E6=96=B0=E5=A2=9E=E7=A7=AF=E5=88=86=E7=BE=A4=E7=99=BD?= =?UTF-8?q?=E5=90=8D=E5=8D=95=E3=80=81=E9=98=B2=E8=AF=AF=E8=AE=A1=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 3 ++ src/bot/io_layer.py | 27 ++++++++++++++++ tests/test_bot_io_layer_points.py | 54 +++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 tests/test_bot_io_layer_points.py diff --git a/.env.example b/.env.example index 5bdaa1fe..153e89f9 100644 --- a/.env.example +++ b/.env.example @@ -30,6 +30,9 @@ TELEGRAM_BOT_TOKEN= TELEGRAM_CHAT_ID= TELEGRAM_CHAT_IDS= POLYWEATHER_TELEGRAM_GROUP_ID= +# Optional: restrict message-points accrual to these chat IDs. +# Example: POLYWEATHER_BOT_POINTS_CHAT_IDS=-1003965137823 +POLYWEATHER_BOT_POINTS_CHAT_IDS= POLYWEATHER_GROUP_MEMBER_PRICE_USDC=5 POLYWEATHER_PUBLIC_PRICE_USDC=10 TELEGRAM_QUERY_TOPIC_CHAT_ID= diff --git a/src/bot/io_layer.py b/src/bot/io_layer.py index a5913d91..1f24a55a 100644 --- a/src/bot/io_layer.py +++ b/src/bot/io_layer.py @@ -15,6 +15,8 @@ from src.bot.settings import ( MESSAGE_POINTS, ) from src.database.db_manager import DBManager +from src.utils.telegram_chat_ids import get_telegram_chat_ids_from_env +from src.utils.telegram_chat_ids import parse_telegram_chat_ids class BotIOLayer: @@ -29,6 +31,7 @@ class BotIOLayer: self.message_cooldown_map = self._parse_int_map( os.getenv("POLYWEATHER_BOT_MESSAGE_COOLDOWN_BY_CHAT") ) + self.points_chat_ids = self._resolve_points_chat_ids() self.query_topic_chat_id = str( os.getenv("TELEGRAM_QUERY_TOPIC_CHAT_ID") or "" ).strip() @@ -98,6 +101,22 @@ class BotIOLayer: return self.message_cooldown_map[chat_key] return MESSAGE_COOLDOWN_SEC + @staticmethod + def _resolve_points_chat_ids() -> set[str]: + dedicated = parse_telegram_chat_ids( + os.getenv("POLYWEATHER_BOT_POINTS_CHAT_IDS"), + os.getenv("POLYWEATHER_BOT_POINTS_CHAT_ID"), + ) + if dedicated: + return set(dedicated) + return set(get_telegram_chat_ids_from_env()) + + def _is_points_chat_allowed(self, chat_id: Any) -> bool: + if not self.points_chat_ids: + return True + chat_key = str(chat_id).strip() if chat_id is not None else "" + return chat_key in self.points_chat_ids + def _resolve_query_target( self, source_chat_id: Any, @@ -249,6 +268,14 @@ class BotIOLayer: chat = getattr(message, "chat", None) if not chat or chat.type not in ("group", "supergroup"): return + if not self._is_points_chat_allowed(getattr(chat, "id", None)): + logger.info( + "message points skipped chat_id={} thread_id={} user_id={} reason=chat_not_allowed", + getattr(chat, "id", None), + getattr(message, "message_thread_id", None), + getattr(getattr(message, "from_user", None), "id", None), + ) + return user = message.from_user username = self.display_name(user) diff --git a/tests/test_bot_io_layer_points.py b/tests/test_bot_io_layer_points.py new file mode 100644 index 00000000..c1b476e1 --- /dev/null +++ b/tests/test_bot_io_layer_points.py @@ -0,0 +1,54 @@ +from __future__ import annotations + +from types import SimpleNamespace + +from src.bot.io_layer import BotIOLayer + + +class DummyDB: + def __init__(self): + self.upserts = [] + self.activities = [] + + def upsert_user(self, telegram_id, username): + self.upserts.append((telegram_id, username)) + + def add_message_activity(self, telegram_id, **kwargs): + self.activities.append({"telegram_id": telegram_id, **kwargs}) + return {"awarded": True, "points_added": kwargs.get("points_to_add", 0)} + + +def _message(chat_id: int | str, text: str = "有效发言"): + return SimpleNamespace( + text=text, + from_user=SimpleNamespace(id=123, username="alice", first_name="Alice"), + chat=SimpleNamespace(id=chat_id, type="supergroup"), + message_thread_id=None, + ) + + +def test_group_message_points_include_configured_forum_chat(monkeypatch): + monkeypatch.delenv("POLYWEATHER_BOT_POINTS_CHAT_IDS", raising=False) + monkeypatch.delenv("POLYWEATHER_BOT_POINTS_CHAT_ID", raising=False) + monkeypatch.setenv("TELEGRAM_CHAT_IDS", "-1003965137823") + monkeypatch.delenv("TELEGRAM_CHAT_ID", raising=False) + db = DummyDB() + io_layer = BotIOLayer(bot=SimpleNamespace(), db=db) + + io_layer.track_group_text_activity(_message(-1003965137823)) + + assert db.upserts == [(123, "alice")] + assert len(db.activities) == 1 + assert db.activities[0]["telegram_id"] == 123 + + +def test_group_message_points_skip_unconfigured_chat_when_allowlist_exists(monkeypatch): + monkeypatch.setenv("POLYWEATHER_BOT_POINTS_CHAT_IDS", "-1003965137823") + monkeypatch.setenv("TELEGRAM_CHAT_IDS", "-1003965137823") + db = DummyDB() + io_layer = BotIOLayer(bot=SimpleNamespace(), db=db) + + io_layer.track_group_text_activity(_message(-1000000000000)) + + assert db.upserts == [] + assert db.activities == []