From fffcbe33496c9207d7b5185aac00c82d2604d69b Mon Sep 17 00:00:00 2001 From: konard Date: Sun, 14 Sep 2025 06:46:49 +0300 Subject: [PATCH 1/3] Initial commit with task details for issue #7 Adding CLAUDE.md with task information for AI processing. This file will be removed when the task is complete. Issue: https://github.com/linksplatform/Bot/issues/7 --- CLAUDE.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..6c583004 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,5 @@ +Issue to solve: https://github.com/linksplatform/Bot/issues/7 +Your prepared branch: issue-7-a6dbd962 +Your prepared working directory: /tmp/gh-issue-solver-1757821606687 + +Proceed. \ No newline at end of file From 32c1b41f75fcf627d39031c8ecc6bf5090146a25 Mon Sep 17 00:00:00 2001 From: konard Date: Sun, 14 Sep 2025 06:52:14 +0300 Subject: [PATCH 2/3] Implement upvote functionality for "+" messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add UPVOTE_PREVIOUS pattern to match simple "+" messages - Add get_conversation_messages method to retrieve message history - Implement upvote_previous method to find and upvote previous non-command messages - Integrate with existing karma system using collective vote mechanism - Add comprehensive pattern tests Fixes #7 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- experiments/test_upvote_pattern.py | 51 +++++++++++++++++ python/__main__.py | 15 +++++ python/modules/commands.py | 92 ++++++++++++++++++++++++++++++ python/patterns.py | 3 + 4 files changed, 161 insertions(+) create mode 100644 experiments/test_upvote_pattern.py diff --git a/experiments/test_upvote_pattern.py b/experiments/test_upvote_pattern.py new file mode 100644 index 00000000..b4bb6404 --- /dev/null +++ b/experiments/test_upvote_pattern.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +"""Test script for the new UPVOTE_PREVIOUS pattern.""" +import sys +import os + +# Add python directory to path +python_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'python') +sys.path.append(python_dir) + +from patterns import UPVOTE_PREVIOUS +from regex import match + +def test_upvote_pattern(): + """Test the UPVOTE_PREVIOUS pattern.""" + + test_cases = [ + # Should match + ("+", True), + (" + ", True), + (" + ", True), + (" +", True), + ("+ ", True), + + # Should not match + ("++", False), + ("+ hello", False), + ("hello +", False), + ("+5", False), + ("+-", False), + ("", False), + ("hello", False), + ] + + print("Testing UPVOTE_PREVIOUS pattern...") + + all_passed = True + for test_input, expected in test_cases: + result = bool(match(UPVOTE_PREVIOUS, test_input)) + status = "PASS" if result == expected else "FAIL" + + if result != expected: + all_passed = False + + print(f" '{test_input}' -> {result} (expected {expected}) [{status}]") + + print(f"\nOverall: {'PASS' if all_passed else 'FAIL'}") + return all_passed + +if __name__ == "__main__": + test_upvote_pattern() \ No newline at end of file diff --git a/python/__main__.py b/python/__main__.py index cdcbf7f6..515bd844 100644 --- a/python/__main__.py +++ b/python/__main__.py @@ -63,6 +63,7 @@ def __init__( (patterns.WHAT_IS, self.commands.what_is), (patterns.WHAT_MEAN, self.commands.what_is), (patterns.APPLY_KARMA, self.commands.apply_karma), + (patterns.UPVOTE_PREVIOUS, self.commands.upvote_previous), (patterns.GITHUB_COPILOT, self.commands.github_copilot) ) @@ -198,6 +199,20 @@ def get_messages( reply_message = event.get("reply_message", {}) return [reply_message] if reply_message else event.get("fwd_messages", []) + def get_conversation_messages( + self, + peer_id: int, + count: int = 10 + ) -> List[Dict[str, Any]]: + """Returns recent messages from conversation. + """ + response = self.call_method( + 'messages.getHistory', + dict(peer_id=peer_id, count=count)) + if "error" in response: + return [] + return response["response"]["items"] + if __name__ == '__main__': vk = Bot(token=BOT_TOKEN, group_id=config.BOT_GROUP_ID, debug=True) diff --git a/python/modules/commands.py b/python/modules/commands.py index 93d99817..04a8ec75 100644 --- a/python/modules/commands.py +++ b/python/modules/commands.py @@ -379,6 +379,98 @@ def github_copilot(self) -> NoReturn: f'Пожалуйста, подождите {round(config.GITHUB_COPILOT_TIMEOUT - (now - self.now))} секунд', self.peer_id ) + def upvote_previous(self) -> NoReturn: + """Upvotes the previous non-command message.""" + if self.peer_id < 2e9 or not self.karma_enabled: + return + + # Get recent conversation messages + recent_messages = self.vk_instance.get_conversation_messages(self.peer_id, 20) + + # Find the previous non-command message + current_msg_found = False + for message in recent_messages: + # Skip until we find current message + if not current_msg_found: + if message["conversation_message_id"] == self.msg_id: + current_msg_found = True + continue + + # Skip messages from bots or system + if message["from_id"] <= 0: + continue + + message_text = message["text"].lstrip("/") + + # Check if this message matches any command pattern + is_command = False + for cmd_pattern in Commands.cmds.keys(): + if match(cmd_pattern, message_text): + is_command = True + break + + # If not a command, this is our target message + if not is_command and message_text.strip(): + target_user_id = message["from_id"] + target_user = self.data_service.get_user(target_user_id, self.vk_instance) + + # Don't allow self-upvote + if target_user_id == self.from_id: + self.vk_instance.send_msg( + 'Нельзя голосовать за свои сообщения.', self.peer_id) + return + + # Apply upvote (equivalent to +0 karma - collective vote) + self.user = target_user + utcnow = datetime.utcnow() + + # Check if already voted for this user + if self.current_user.uid in target_user.supporters: + self.vk_instance.send_msg( + (f'Вы уже голосовали за [id{target_user.uid}|' + f'{self.vk_instance.get_user_name(target_user.uid, "acc")}].'), + self.peer_id + ) + return + + # Check collective vote time limit + utclast = datetime.fromtimestamp( + float(self.current_user.last_collective_vote)) + difference = utcnow - utclast + hours_difference = difference.total_seconds() / 3600 + hours_limit = karma_limit(self.current_user.karma) + + if hours_difference < hours_limit: + self.vk_instance.delete_message(self.peer_id, self.msg_id) + self.vk_instance.send_msg( + CommandsBuilder.build_not_enough_hours( + self.current_user, self.data_service, + hours_limit, difference.total_seconds() / 60), + self.peer_id) + return + + # Apply the upvote + user_karma_change, selected_user_karma_change, collective_vote_applied, voters = self.apply_karma_change( + "+", 0) + + if collective_vote_applied: + self.current_user.last_collective_vote = int(utcnow.timestamp()) + self.data_service.save_user(self.current_user) + + if user_karma_change: + self.data_service.save_user(target_user) + + self.vk_instance.send_msg( + CommandsBuilder.build_karma_change( + user_karma_change, selected_user_karma_change, voters), + self.peer_id) + self.vk_instance.delete_message(self.peer_id, self.msg_id) + return + + # No previous non-command message found + self.vk_instance.send_msg( + 'Не найдено предыдущее сообщение для голосования.', self.peer_id) + def match_command( self, pattern: Pattern diff --git a/python/patterns.py b/python/patterns.py index 1834c72c..88cd2d74 100644 --- a/python/patterns.py +++ b/python/patterns.py @@ -65,3 +65,6 @@ GITHUB_COPILOT = recompile( r'\A\s*(code|код)\s+(?P(' + COPILOT_LANGUAGES + r'))(?P[\S\s]+)\Z', IGNORECASE) + +UPVOTE_PREVIOUS = recompile( + r'\A\s*\+\s*\Z', IGNORECASE) From 15127d3e79805c5c8f698d61ab094116235a86c8 Mon Sep 17 00:00:00 2001 From: konard Date: Sun, 14 Sep 2025 06:53:04 +0300 Subject: [PATCH 3/3] Remove CLAUDE.md - Claude command completed --- CLAUDE.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 6c583004..00000000 --- a/CLAUDE.md +++ /dev/null @@ -1,5 +0,0 @@ -Issue to solve: https://github.com/linksplatform/Bot/issues/7 -Your prepared branch: issue-7-a6dbd962 -Your prepared working directory: /tmp/gh-issue-solver-1757821606687 - -Proceed. \ No newline at end of file