1+ # -*- coding: utf-8 -*-
2+ """Daily outreach module for asking users about programming languages and GitHub profiles."""
3+ import random
4+ from datetime import datetime , timedelta
5+ from typing import List , NoReturn , Optional
6+ from regex import search , IGNORECASE
7+
8+ from .data_service import BetterBotBaseDataService
9+ import sys
10+ import os
11+ sys .path .append (os .path .dirname (os .path .dirname (__file__ )))
12+ import config
13+
14+
15+ class DailyOutreach :
16+ """Handles daily outreach to users without programming languages or GitHub profiles."""
17+
18+ QUESTIONS = [
19+ "У вас есть страничка на GitHub?" ,
20+ "Какие языки программирования вы знаете?"
21+ ]
22+
23+ def __init__ (self , vk_instance , data_service : BetterBotBaseDataService ):
24+ self .vk_instance = vk_instance
25+ self .data_service = data_service
26+ self .last_outreach_date = None
27+
28+ def should_run_daily_outreach (self ) -> bool :
29+ """Check if daily outreach should run (once per day)."""
30+ today = datetime .now ().date ()
31+ if self .last_outreach_date != today :
32+ self .last_outreach_date = today
33+ return True
34+ return False
35+
36+ def find_users_without_profile_info (self , peer_id : int ) -> List [int ]:
37+ """Find users without programming languages or GitHub profiles."""
38+ try :
39+ member_ids = self .vk_instance .get_members_ids (peer_id )
40+ if not member_ids :
41+ return []
42+
43+ candidates = []
44+ for uid in member_ids :
45+ user = self .data_service .get_user (uid , self .vk_instance )
46+
47+ # Check if user has no programming languages and no GitHub profile
48+ has_languages = (hasattr (user , 'programming_languages' ) and
49+ user .programming_languages and
50+ len (user .programming_languages ) > 0 )
51+ has_github = (hasattr (user , 'github_profile' ) and
52+ user .github_profile and
53+ user .github_profile .strip () != "" )
54+
55+ if not has_languages and not has_github :
56+ candidates .append (uid )
57+
58+ return candidates
59+ except Exception as e :
60+ print (f"Error finding users: { e } " )
61+ return []
62+
63+ def select_random_user_and_question (self , candidates : List [int ]) -> Optional [tuple ]:
64+ """Select a random user and question."""
65+ if not candidates :
66+ return None
67+
68+ user_id = random .choice (candidates )
69+ question = random .choice (self .QUESTIONS )
70+ return user_id , question
71+
72+ def send_daily_question (self , peer_id : int ) -> NoReturn :
73+ """Send daily question to a random user."""
74+ candidates = self .find_users_without_profile_info (peer_id )
75+
76+ if not candidates :
77+ return
78+
79+ selection = self .select_random_user_and_question (candidates )
80+ if not selection :
81+ return
82+
83+ user_id , question = selection
84+ try :
85+ user_name = self .vk_instance .get_user_name (user_id , "nom" )
86+ message = f"[id{ user_id } |{ user_name } ], { question } "
87+ self .vk_instance .send_msg (message , peer_id )
88+ except Exception as e :
89+ print (f"Error sending daily question: { e } " )
90+
91+ def process_potential_response (self , msg : str , from_id : int ) -> bool :
92+ """
93+ Process a message that might be a response to our daily questions.
94+ Returns True if response was processed, False otherwise.
95+ """
96+ msg_lower = msg .lower ()
97+
98+ # Check for GitHub profile response
99+ github_match = search (r'github\.com/([a-zA-Z0-9-_]+)' , msg , IGNORECASE )
100+ if github_match :
101+ username = github_match .group (1 )
102+ user = self .data_service .get_user (from_id , self .vk_instance )
103+ user .github_profile = username
104+ self .data_service .save_user (user )
105+ return True
106+
107+ # Check for programming language response
108+ for lang in config .DEFAULT_PROGRAMMING_LANGUAGES :
109+ # Remove regex escaping for matching
110+ lang_clean = lang .replace (r'\+' , '+' ).replace (r'\-' , '-' ).replace (r'\\' , '' )
111+ if search (lang_clean , msg , IGNORECASE ):
112+ user = self .data_service .get_user (from_id , self .vk_instance )
113+ if not hasattr (user , 'programming_languages' ):
114+ user .programming_languages = []
115+ if lang_clean not in user .programming_languages :
116+ user .programming_languages .append (lang_clean )
117+ self .data_service .save_user (user )
118+ return True
119+
120+ return False
0 commit comments