diff --git a/experiments/test_message_limits.py b/experiments/test_message_limits.py new file mode 100644 index 00000000..03e912af --- /dev/null +++ b/experiments/test_message_limits.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +"""Test script for message limiting functionality""" + +import sys +import os +sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'python')) + +from modules.utils import get_daily_message_limit + +def test_message_limits(): + """Test the daily message limit function""" + + # Test cases based on the issue requirements + test_cases = [ + # (karma, expected_limit) + (0, -1), # No limit for karma >= -10 + (-5, -1), # No limit for karma >= -10 + (-10, 64), # 64 messages for karma < -10 and >= -20 + (-15, 64), # 64 messages for karma < -10 and >= -20 + (-20, 32), # 32 messages for karma < -20 and >= -40 + (-30, 32), # 32 messages for karma < -20 and >= -40 + (-40, 16), # 16 messages for karma < -40 and >= -80 + (-60, 16), # 16 messages for karma < -40 and >= -80 + (-80, 8), # 8 messages for karma < -80 and >= -160 + (-120, 8), # 8 messages for karma < -80 and >= -160 + (-160, 4), # 4 messages for karma < -160 and >= -320 + (-240, 4), # 4 messages for karma < -160 and >= -320 + (-320, 2), # 2 messages for karma < -320 and >= -640 + (-480, 2), # 2 messages for karma < -320 and >= -640 + (-640, 1), # 1 message for karma < -640 and >= -1280 + (-960, 1), # 1 message for karma < -640 and >= -1280 + (-1280, 0), # Read-only mode for karma < -1280 + (-2000, 0), # Read-only mode for karma < -1280 + ] + + print("Testing daily message limits based on karma:") + print("=" * 50) + + all_passed = True + for karma, expected_limit in test_cases: + actual_limit = get_daily_message_limit(karma) + status = "✓ PASS" if actual_limit == expected_limit else "✗ FAIL" + + if actual_limit != expected_limit: + all_passed = False + + print(f"Karma: {karma:5d} | Expected: {expected_limit:3d} | Got: {actual_limit:3d} | {status}") + + print("=" * 50) + if all_passed: + print("🎉 All tests passed!") + else: + print("❌ Some tests failed!") + + return all_passed + +if __name__ == "__main__": + test_message_limits() \ No newline at end of file diff --git a/experiments/test_message_limits_simple.py b/experiments/test_message_limits_simple.py new file mode 100644 index 00000000..3cd03559 --- /dev/null +++ b/experiments/test_message_limits_simple.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +"""Standalone test for message limiting logic""" + +def get_daily_message_limit(karma: int) -> int: + """Returns daily message limit based on karma level. + + :param karma: user's karma value + :return: maximum number of messages allowed per day + """ + if karma > -10: + return -1 # No limit + elif karma > -20: + return 64 + elif karma > -40: + return 32 + elif karma > -80: + return 16 + elif karma > -160: + return 8 + elif karma > -320: + return 4 + elif karma > -640: + return 2 + elif karma > -1280: + return 1 + else: + return 0 # Read-only mode + + +def test_message_limits(): + """Test the daily message limit function""" + + # Test cases based on the issue requirements + test_cases = [ + # (karma, expected_limit) + (0, -1), # No limit for karma > -10 + (-5, -1), # No limit for karma > -10 + (-9, -1), # No limit for karma > -10 + (-10, 64), # 64 messages for karma < -10 and >= -20 + (-15, 64), # 64 messages for karma < -10 and >= -20 + (-19, 64), # 64 messages for karma < -10 and >= -20 + (-20, 32), # 32 messages for karma < -20 and >= -40 + (-30, 32), # 32 messages for karma < -20 and >= -40 + (-39, 32), # 32 messages for karma < -20 and >= -40 + (-40, 16), # 16 messages for karma < -40 and >= -80 + (-60, 16), # 16 messages for karma < -40 and >= -80 + (-79, 16), # 16 messages for karma < -40 and >= -80 + (-80, 8), # 8 messages for karma < -80 and >= -160 + (-120, 8), # 8 messages for karma < -80 and >= -160 + (-159, 8), # 8 messages for karma < -80 and >= -160 + (-160, 4), # 4 messages for karma < -160 and >= -320 + (-240, 4), # 4 messages for karma < -160 and >= -320 + (-319, 4), # 4 messages for karma < -160 and >= -320 + (-320, 2), # 2 messages for karma < -320 and >= -640 + (-480, 2), # 2 messages for karma < -320 and >= -640 + (-639, 2), # 2 messages for karma < -320 and >= -640 + (-640, 1), # 1 message for karma < -640 and >= -1280 + (-960, 1), # 1 message for karma < -640 and >= -1280 + (-1279, 1), # 1 message for karma < -640 and >= -1280 + (-1280, 0), # Read-only mode for karma < -1280 + (-2000, 0), # Read-only mode for karma < -1280 + ] + + print("Testing daily message limits based on karma:") + print("=" * 50) + + all_passed = True + for karma, expected_limit in test_cases: + actual_limit = get_daily_message_limit(karma) + status = "✓ PASS" if actual_limit == expected_limit else "✗ FAIL" + + if actual_limit != expected_limit: + all_passed = False + + print(f"Karma: {karma:5d} | Expected: {expected_limit:3d} | Got: {actual_limit:3d} | {status}") + + print("=" * 50) + if all_passed: + print("🎉 All tests passed!") + else: + print("❌ Some tests failed!") + + return all_passed + +if __name__ == "__main__": + test_message_limits() \ No newline at end of file diff --git a/python/__main__.py b/python/__main__.py index cdcbf7f6..5c29d976 100644 --- a/python/__main__.py +++ b/python/__main__.py @@ -10,6 +10,7 @@ from modules import ( BetterBotBaseDataService, Commands ) +from modules.utils import get_daily_message_limit from tokens import BOT_TOKEN from userbot import UserBot import patterns @@ -99,6 +100,40 @@ def message_new( user = self.data.get_user(from_id, self) if from_id > 0 else None + # Check daily message limit for users with negative karma + if user and peer_id >= CHAT_ID_OFFSET: # Only apply limits in group chats + current_date = datetime.now().strftime("%Y-%m-%d") + + # Reset daily message count if it's a new day + if user.last_message_date != current_date: + user.daily_message_count = 0 + user.last_message_date = current_date + self.data.save_user(user) + + # Check if user has exceeded their daily message limit + daily_limit = get_daily_message_limit(user.karma) + if daily_limit >= 0: # -1 means no limit + if user.daily_message_count >= daily_limit: + if daily_limit == 0: + # Read-only mode - delete message and notify + self.delete_message(peer_id, msg_id, 0) + self.send_msg( + f"[id{from_id}|Пользователь] находится в режиме только для чтения (карма < -1280).", + peer_id + ) + else: + # Message limit exceeded - delete message and notify + self.delete_message(peer_id, msg_id, 0) + self.send_msg( + f"[id{from_id}|Пользователь] превысил лимит сообщений на день ({daily_limit} сообщений). Текущая карма: {user.karma}", + peer_id + ) + return + else: + # Increment message count for this day + user.daily_message_count += 1 + self.data.save_user(user) + messages = self.get_messages(event) selected_message = messages[0] if len(messages) == 1 else None selected_user = ( diff --git a/python/modules/data_service.py b/python/modules/data_service.py index 45a0faeb..e4ccacdb 100644 --- a/python/modules/data_service.py +++ b/python/modules/data_service.py @@ -19,6 +19,8 @@ def __init__(self, db_name: str = "users"): self.base.addPattern("supporters", []) self.base.addPattern("opponents", []) self.base.addPattern("karma", 0) + self.base.addPattern("daily_message_count", 0) + self.base.addPattern("last_message_date", "") def get_or_create_user( self, diff --git a/python/modules/utils.py b/python/modules/utils.py index e30e7c2c..ac1968c4 100644 --- a/python/modules/utils.py +++ b/python/modules/utils.py @@ -68,3 +68,29 @@ def is_available_ghpage( """Returns True if github profile is available. """ return requests.get(f'https://github.com/{profile}').status_code == 200 + + +def get_daily_message_limit(karma: int) -> int: + """Returns daily message limit based on karma level. + + :param karma: user's karma value + :return: maximum number of messages allowed per day + """ + if karma > -10: + return -1 # No limit + elif karma > -20: + return 64 + elif karma > -40: + return 32 + elif karma > -80: + return 16 + elif karma > -160: + return 8 + elif karma > -320: + return 4 + elif karma > -640: + return 2 + elif karma > -1280: + return 1 + else: + return 0 # Read-only mode