625 lines
26 KiB
Python
625 lines
26 KiB
Python
import os
|
|
import time
|
|
import json
|
|
import logging
|
|
import requests
|
|
from datetime import datetime
|
|
from dotenv import load_dotenv
|
|
import colorama
|
|
from colorama import Fore, Back, Style
|
|
|
|
# Initialize colorama for Windows
|
|
colorama.init()
|
|
|
|
# Load environment variables
|
|
load_dotenv()
|
|
|
|
# Configure logging with colors and terminal output
|
|
class ColoredFormatter(logging.Formatter):
|
|
"""Custom formatter with colors for different log levels"""
|
|
|
|
COLORS = {
|
|
'DEBUG': Fore.CYAN,
|
|
'INFO': Fore.GREEN,
|
|
'WARNING': Fore.YELLOW,
|
|
'ERROR': Fore.RED,
|
|
'CRITICAL': Fore.RED + Back.WHITE,
|
|
}
|
|
|
|
def format(self, record):
|
|
# Add color to the level name
|
|
levelname = record.levelname
|
|
if levelname in self.COLORS:
|
|
record.levelname = f"{self.COLORS[levelname]}{levelname}{Style.RESET_ALL}"
|
|
|
|
# Add color to the message based on content
|
|
if 'SENT' in record.getMessage():
|
|
record.msg = f"{Fore.BLUE}{record.msg}{Style.RESET_ALL}"
|
|
elif 'RECEIVED' in record.getMessage():
|
|
record.msg = f"{Fore.MAGENTA}{record.msg}{Style.RESET_ALL}"
|
|
elif 'AI GENERATED' in record.getMessage():
|
|
record.msg = f"{Fore.CYAN}{record.msg}{Style.RESET_ALL}"
|
|
elif 'ERROR' in record.getMessage():
|
|
record.msg = f"{Fore.RED}{record.msg}{Style.RESET_ALL}"
|
|
elif 'SUCCESS' in record.getMessage():
|
|
record.msg = f"{Fore.GREEN}{record.msg}{Style.RESET_ALL}"
|
|
|
|
return super().format(record)
|
|
|
|
# Set up logging
|
|
logger = logging.getLogger(__name__)
|
|
logger.setLevel(logging.INFO)
|
|
|
|
# Create console handler with colored formatter
|
|
console_handler = logging.StreamHandler()
|
|
console_handler.setLevel(logging.INFO)
|
|
formatter = ColoredFormatter(
|
|
'%(asctime)s - %(levelname)s - %(message)s',
|
|
datefmt='%Y-%m-%dT%H:%M:%S'
|
|
)
|
|
console_handler.setFormatter(formatter)
|
|
logger.addHandler(console_handler)
|
|
|
|
# Create file handler for persistent logs
|
|
file_handler = logging.FileHandler('icebreaker_bot.log')
|
|
file_handler.setLevel(logging.INFO)
|
|
file_formatter = logging.Formatter(
|
|
'%(asctime)s - %(levelname)s - %(message)s',
|
|
datefmt='%Y-%m-%dT%H:%M:%S'
|
|
)
|
|
file_handler.setFormatter(file_formatter)
|
|
logger.addHandler(file_handler)
|
|
|
|
class EnhancedMeetMeClient:
|
|
"""Enhanced client for interacting with MeetMe API (local or production)"""
|
|
|
|
def __init__(self):
|
|
self.session = requests.Session()
|
|
self.api_base_url = os.getenv('API_BASE_URL', 'https://api.meetme.com')
|
|
self.use_local_api = os.getenv('USE_LOCAL_API', 'false').lower() == 'true'
|
|
self.api_version = os.getenv('API_VERSION', 'v1')
|
|
self.api_fallback_version = os.getenv('API_FALLBACK_VERSION', 'v1')
|
|
self.api_retry_attempts = int(os.getenv('API_RETRY_ATTEMPTS', '3'))
|
|
self.api_retry_delay = int(os.getenv('API_RETRY_DELAY', '60'))
|
|
|
|
# Validate required environment variables
|
|
self._validate_environment()
|
|
|
|
# Configure headers based on API type
|
|
if self.use_local_api:
|
|
self.headers = {
|
|
'User-Agent': 'MeetMe-Bot/1.0',
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json'
|
|
}
|
|
else:
|
|
self.headers = {
|
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json'
|
|
}
|
|
|
|
self.session.headers.update(self.headers)
|
|
self.auth_token = None
|
|
self.my_user_id = None
|
|
|
|
# Statistics tracking
|
|
self.stats = {
|
|
'messages_sent': 0,
|
|
'users_processed': 0,
|
|
'errors': 0,
|
|
'start_time': datetime.now()
|
|
}
|
|
|
|
def _validate_environment(self):
|
|
"""Validate required environment variables"""
|
|
if self.use_local_api:
|
|
if not os.getenv('API_USERNAME'):
|
|
raise ValueError("API_USERNAME must be set for local API")
|
|
if not os.getenv('API_PASSWORD'):
|
|
raise ValueError("API_PASSWORD must be set for local API")
|
|
else:
|
|
if not os.getenv('MM_USERNAME'):
|
|
raise ValueError("MM_USERNAME must be set for production API")
|
|
if not os.getenv('MM_PASSWORD'):
|
|
raise ValueError("MM_PASSWORD must be set for production API")
|
|
|
|
if not os.getenv('OLLAMA_ENDPOINT'):
|
|
raise ValueError("OLLAMA_ENDPOINT must be set")
|
|
|
|
def detect_api_version(self):
|
|
"""Detect available API version (v2 first, fallback to v1)"""
|
|
if self.use_local_api:
|
|
return 'v1' # Local API always uses v1 structure
|
|
|
|
for version in [self.api_version, self.api_fallback_version]:
|
|
try:
|
|
logger.info(f"{Fore.CYAN}[DETECTING] Testing API version {version}...{Style.RESET_ALL}")
|
|
response = self.session.get(
|
|
f"https://api.meetme.com/api/{version}",
|
|
timeout=10
|
|
)
|
|
|
|
if response.status_code == 200:
|
|
logger.info(f"{Fore.GREEN}[SUCCESS] API version {version} is available{Style.RESET_ALL}")
|
|
return version
|
|
elif response.status_code == 503:
|
|
error_data = response.json()
|
|
if error_data.get('errorType') == 'tMaintenanceException':
|
|
logger.warning(f"{Fore.YELLOW}[MAINTENANCE] API version {version} is under maintenance{Style.RESET_ALL}")
|
|
else:
|
|
logger.warning(f"{Fore.YELLOW}[UNAVAILABLE] API version {version} returned {response.status_code}{Style.RESET_ALL}")
|
|
else:
|
|
logger.warning(f"{Fore.YELLOW}[UNAVAILABLE] API version {version} returned {response.status_code}{Style.RESET_ALL}")
|
|
|
|
except requests.exceptions.Timeout:
|
|
logger.warning(f"{Fore.YELLOW}[TIMEOUT] API version {version} timed out{Style.RESET_ALL}")
|
|
except Exception as e:
|
|
logger.warning(f"{Fore.YELLOW}[ERROR] API version {version} error: {str(e)}{Style.RESET_ALL}")
|
|
|
|
logger.warning(f"{Fore.YELLOW}[FALLBACK] Using default API version v1{Style.RESET_ALL}")
|
|
return 'v1'
|
|
|
|
def _handle_maintenance_error(self, response):
|
|
"""Handle API maintenance errors"""
|
|
if response.status_code == 503:
|
|
try:
|
|
error_data = response.json()
|
|
if error_data.get('errorType') == 'tMaintenanceException':
|
|
logger.warning(f"{Fore.YELLOW}[MAINTENANCE] API is under maintenance: {error_data.get('message', 'Unknown')}{Style.RESET_ALL}")
|
|
return True
|
|
except:
|
|
pass
|
|
return False
|
|
|
|
def get_stats(self):
|
|
"""Get current statistics"""
|
|
runtime = datetime.now() - self.stats['start_time']
|
|
return {
|
|
**self.stats,
|
|
'runtime': str(runtime),
|
|
'messages_per_hour': self.stats['messages_sent'] / max(runtime.total_seconds() / 3600, 1)
|
|
}
|
|
|
|
def login(self):
|
|
"""Authenticate with MeetMe API (local or production)"""
|
|
try:
|
|
logger.info(f"{Fore.YELLOW}[LOGIN] ATTEMPTING LOGIN to {'local' if self.use_local_api else 'production'} API...{Style.RESET_ALL}")
|
|
|
|
if self.use_local_api:
|
|
return self._login_local()
|
|
else:
|
|
return self._login_production()
|
|
|
|
except Exception as e:
|
|
logger.error(f"[ERROR] LOGIN ERROR: {str(e)}")
|
|
self.stats['errors'] += 1
|
|
return False
|
|
|
|
def _login_local(self):
|
|
"""Login to local Node.js backend"""
|
|
try:
|
|
username = os.getenv('API_USERNAME')
|
|
password = os.getenv('API_PASSWORD')
|
|
|
|
login_data = {
|
|
'email': username,
|
|
'password': password
|
|
}
|
|
|
|
response = self.session.post(
|
|
f"{self.api_base_url}/auth/login",
|
|
json=login_data,
|
|
timeout=30
|
|
)
|
|
|
|
if response.status_code == 200:
|
|
data = response.json()
|
|
self.auth_token = data.get('token')
|
|
self.my_user_id = data.get('user_id') or data.get('user', {}).get('_id')
|
|
if self.auth_token:
|
|
self.session.headers.update({'Authorization': f'Bearer {self.auth_token}'})
|
|
logger.info(f"{Fore.GREEN}[SUCCESS] LOGIN SUCCESS - Local API as user {self.my_user_id}{Style.RESET_ALL}")
|
|
return True
|
|
else:
|
|
logger.error(f"[ERROR] LOGIN FAILED - Status {response.status_code}: {response.text}")
|
|
self.stats['errors'] += 1
|
|
return False
|
|
|
|
except requests.exceptions.Timeout:
|
|
logger.error("[ERROR] LOGIN TIMEOUT - Server not responding")
|
|
self.stats['errors'] += 1
|
|
return False
|
|
except Exception as e:
|
|
logger.error(f"[ERROR] LOGIN ERROR: {str(e)}")
|
|
self.stats['errors'] += 1
|
|
return False
|
|
|
|
def _login_production(self):
|
|
"""Login to production MeetMe API"""
|
|
try:
|
|
# Detect available API version
|
|
detected_version = self.detect_api_version()
|
|
api_url = f"https://api.meetme.com/api/{detected_version}"
|
|
|
|
username = os.getenv('MM_USERNAME')
|
|
password = os.getenv('MM_PASSWORD')
|
|
|
|
login_data = {
|
|
'email': username,
|
|
'password': password
|
|
}
|
|
|
|
response = self.session.post(
|
|
f"{api_url}/auth/login",
|
|
json=login_data,
|
|
timeout=30
|
|
)
|
|
|
|
# Handle maintenance errors
|
|
if self._handle_maintenance_error(response):
|
|
logger.warning(f"{Fore.YELLOW}[RETRY] Will retry login in {self.api_retry_delay} seconds...{Style.RESET_ALL}")
|
|
time.sleep(self.api_retry_delay)
|
|
return False
|
|
|
|
if response.status_code == 200:
|
|
data = response.json()
|
|
self.my_user_id = data.get('user_id') or data.get('user', {}).get('id')
|
|
logger.info(f"{Fore.GREEN}[SUCCESS] LOGIN SUCCESS - Production API v{detected_version} as user {self.my_user_id}{Style.RESET_ALL}")
|
|
return True
|
|
else:
|
|
logger.error(f"{Fore.RED}[ERROR] LOGIN FAILED - Status {response.status_code}: {response.text}{Style.RESET_ALL}")
|
|
self.stats['errors'] += 1
|
|
return False
|
|
|
|
except requests.exceptions.Timeout:
|
|
logger.error(f"{Fore.RED}[TIMEOUT] LOGIN TIMEOUT - Server not responding{Style.RESET_ALL}")
|
|
self.stats['errors'] += 1
|
|
return False
|
|
except Exception as e:
|
|
logger.error(f"{Fore.RED}[ERROR] LOGIN ERROR: {str(e)}{Style.RESET_ALL}")
|
|
self.stats['errors'] += 1
|
|
return False
|
|
|
|
def get_nearby_users(self, page=1):
|
|
"""Get list of nearby users"""
|
|
try:
|
|
logger.info(f"{Fore.CYAN}[SEARCHING] SEARCHING for nearby users (page {page})...{Style.RESET_ALL}")
|
|
|
|
if self.use_local_api:
|
|
return self._get_nearby_users_local(page)
|
|
else:
|
|
return self._get_nearby_users_production(page)
|
|
|
|
except Exception as e:
|
|
logger.error(f"[ERROR] ERROR getting nearby users: {str(e)}")
|
|
self.stats['errors'] += 1
|
|
return []
|
|
|
|
def _get_nearby_users_local(self, page=1):
|
|
"""Get nearby users from local API"""
|
|
try:
|
|
response = self.session.get(
|
|
f"{self.api_base_url}/users/nearby",
|
|
params={'page': page, 'limit': 20},
|
|
timeout=30
|
|
)
|
|
|
|
if response.status_code == 200:
|
|
data = response.json()
|
|
users = []
|
|
for user in data.get('users', []):
|
|
# Handle different field names between APIs
|
|
user_id = user.get('_id') or user.get('id')
|
|
display_name = user.get('username') or user.get('display_name') or user.get('name')
|
|
bio = user.get('bio') or user.get('description') or ''
|
|
|
|
if user_id and display_name: # Only add valid users
|
|
users.append({
|
|
'id': user_id,
|
|
'display_name': display_name,
|
|
'bio': bio
|
|
})
|
|
logger.info(f"{Fore.GREEN}[SUCCESS] FOUND {len(users)} nearby users from local API{Style.RESET_ALL}")
|
|
return users
|
|
else:
|
|
logger.error(f"[ERROR] FAILED to get nearby users from local API: {response.status_code}")
|
|
self.stats['errors'] += 1
|
|
return []
|
|
|
|
except requests.exceptions.Timeout:
|
|
logger.error("[ERROR] TIMEOUT getting nearby users from local API")
|
|
self.stats['errors'] += 1
|
|
return []
|
|
except Exception as e:
|
|
logger.error(f"[ERROR] ERROR getting nearby users from local API: {str(e)}")
|
|
self.stats['errors'] += 1
|
|
return []
|
|
|
|
def _get_nearby_users_production(self, page=1):
|
|
"""Get nearby users from production API"""
|
|
try:
|
|
# Use detected API version
|
|
detected_version = self.detect_api_version()
|
|
api_url = f"https://api.meetme.com/api/{detected_version}"
|
|
|
|
response = self.session.get(
|
|
f"{api_url}/users/nearby",
|
|
params={'page': page, 'limit': 20},
|
|
timeout=30
|
|
)
|
|
|
|
# Handle maintenance errors
|
|
if self._handle_maintenance_error(response):
|
|
logger.warning(f"{Fore.YELLOW}[RETRY] Will retry getting nearby users in {self.api_retry_delay} seconds...{Style.RESET_ALL}")
|
|
time.sleep(self.api_retry_delay)
|
|
return []
|
|
|
|
if response.status_code == 200:
|
|
data = response.json()
|
|
users = []
|
|
for user in data.get('users', []):
|
|
# Handle different field names between APIs
|
|
user_id = user.get('id') or user.get('_id')
|
|
display_name = user.get('display_name') or user.get('username') or user.get('name')
|
|
bio = user.get('bio') or user.get('description') or ''
|
|
|
|
if user_id and display_name: # Only add valid users
|
|
users.append({
|
|
'id': user_id,
|
|
'display_name': display_name,
|
|
'bio': bio
|
|
})
|
|
logger.info(f"{Fore.GREEN}[SUCCESS] FOUND {len(users)} nearby users from production API v{detected_version}{Style.RESET_ALL}")
|
|
return users
|
|
else:
|
|
logger.error(f"{Fore.RED}[ERROR] FAILED to get nearby users from production API: {response.status_code}{Style.RESET_ALL}")
|
|
self.stats['errors'] += 1
|
|
return []
|
|
|
|
except requests.exceptions.Timeout:
|
|
logger.error(f"{Fore.RED}[TIMEOUT] TIMEOUT getting nearby users from production API{Style.RESET_ALL}")
|
|
self.stats['errors'] += 1
|
|
return []
|
|
except Exception as e:
|
|
logger.error(f"{Fore.RED}[ERROR] ERROR getting nearby users from production API: {str(e)}{Style.RESET_ALL}")
|
|
self.stats['errors'] += 1
|
|
return []
|
|
|
|
def send_message(self, user_id, text):
|
|
"""Send message to a specific user"""
|
|
try:
|
|
logger.info(f"{Fore.BLUE}[SENDING] SENDING MESSAGE to user {user_id}...{Style.RESET_ALL}")
|
|
logger.info(f"{Fore.CYAN}[MESSAGE] MESSAGE CONTENT: {text[:100]}{'...' if len(text) > 100 else ''}{Style.RESET_ALL}")
|
|
|
|
if self.use_local_api:
|
|
return self._send_message_local(user_id, text)
|
|
else:
|
|
return self._send_message_production(user_id, text)
|
|
|
|
except Exception as e:
|
|
logger.error(f"[ERROR] ERROR sending message: {str(e)}")
|
|
self.stats['errors'] += 1
|
|
return False
|
|
|
|
def _send_message_local(self, user_id, text):
|
|
"""Send message via local API"""
|
|
try:
|
|
message_data = {
|
|
'recipient_id': user_id,
|
|
'message': text,
|
|
'timestamp': datetime.now().isoformat()
|
|
}
|
|
|
|
response = self.session.post(
|
|
f"{self.api_base_url}/messages",
|
|
json=message_data,
|
|
timeout=30
|
|
)
|
|
|
|
if response.status_code == 200:
|
|
logger.info(f"{Fore.GREEN}[SUCCESS] MESSAGE SENT SUCCESSFULLY to user {user_id} via local API{Style.RESET_ALL}")
|
|
self.stats['messages_sent'] += 1
|
|
return True
|
|
else:
|
|
logger.error(f"[ERROR] FAILED to send message via local API: {response.status_code}")
|
|
self.stats['errors'] += 1
|
|
return False
|
|
|
|
except requests.exceptions.Timeout:
|
|
logger.error("[ERROR] TIMEOUT sending message via local API")
|
|
self.stats['errors'] += 1
|
|
return False
|
|
except Exception as e:
|
|
logger.error(f"[ERROR] ERROR sending message via local API: {str(e)}")
|
|
self.stats['errors'] += 1
|
|
return False
|
|
|
|
def _send_message_production(self, user_id, text):
|
|
"""Send message via production API"""
|
|
try:
|
|
# Use detected API version
|
|
detected_version = self.detect_api_version()
|
|
api_url = f"https://api.meetme.com/api/{detected_version}"
|
|
|
|
message_data = {
|
|
'recipient_id': user_id,
|
|
'message': text
|
|
}
|
|
|
|
response = self.session.post(
|
|
f"{api_url}/messages/send",
|
|
json=message_data,
|
|
timeout=30
|
|
)
|
|
|
|
# Handle maintenance errors
|
|
if self._handle_maintenance_error(response):
|
|
logger.warning(f"{Fore.YELLOW}[RETRY] Will retry sending message in {self.api_retry_delay} seconds...{Style.RESET_ALL}")
|
|
time.sleep(self.api_retry_delay)
|
|
return False
|
|
|
|
if response.status_code == 200:
|
|
logger.info(f"{Fore.GREEN}[SUCCESS] MESSAGE SENT SUCCESSFULLY to user {user_id} via production API v{detected_version}{Style.RESET_ALL}")
|
|
self.stats['messages_sent'] += 1
|
|
return True
|
|
else:
|
|
logger.error(f"{Fore.RED}[ERROR] FAILED to send message via production API: {response.status_code}{Style.RESET_ALL}")
|
|
self.stats['errors'] += 1
|
|
return False
|
|
|
|
except requests.exceptions.Timeout:
|
|
logger.error(f"{Fore.RED}[TIMEOUT] TIMEOUT sending message via production API{Style.RESET_ALL}")
|
|
self.stats['errors'] += 1
|
|
return False
|
|
except Exception as e:
|
|
logger.error(f"{Fore.RED}[ERROR] ERROR sending message via production API: {str(e)}{Style.RESET_ALL}")
|
|
self.stats['errors'] += 1
|
|
return False
|
|
|
|
def generate_ice_breaker(user):
|
|
"""Generate personalized ice breaker message using Ollama"""
|
|
try:
|
|
my_name = os.getenv('MY_NAME', 'DrJones')
|
|
my_profile = os.getenv('MY_PROFILE', 'water-tech geek, coffee addict')
|
|
ollama_endpoint = os.getenv('OLLAMA_ENDPOINT')
|
|
ollama_model = os.getenv('OLLAMA_MODEL', 'quen3')
|
|
|
|
if not ollama_endpoint:
|
|
logger.error("[ERROR] OLLAMA_ENDPOINT not configured")
|
|
return None
|
|
|
|
logger.info(f"{Fore.YELLOW}[AUTO RESPONDER] AI GENERATING ice breaker for {user['display_name']}...{Style.RESET_ALL}")
|
|
|
|
# Build prompt with context
|
|
prompt = f"""You are {my_name}, a {my_profile}.
|
|
|
|
You're reaching out to {user['display_name']} who has this bio: "{user['bio']}"
|
|
|
|
Generate a friendly, personalized ice breaker message (max 100 words) that:
|
|
- References something from their bio if available
|
|
- Shows genuine interest in getting to know them
|
|
- Is casual and conversational
|
|
- Avoids being overly formal or creepy
|
|
- Includes a question to encourage response
|
|
|
|
Keep it natural and authentic to your personality."""
|
|
|
|
# Prepare request to Ollama
|
|
ollama_request = {
|
|
"model": ollama_model,
|
|
"messages": [
|
|
{"role": "system", "content": "You are a charismatic, thoughtful conversationalist."},
|
|
{"role": "user", "content": prompt}
|
|
]
|
|
}
|
|
|
|
logger.debug(f"Sending prompt to Ollama: {prompt}")
|
|
|
|
response = requests.post(
|
|
ollama_endpoint,
|
|
json=ollama_request,
|
|
headers={'Content-Type': 'application/json'},
|
|
timeout=30
|
|
)
|
|
|
|
if response.status_code == 200:
|
|
data = response.json()
|
|
assistant_reply = data.get('choices', [{}])[0].get('message', {}).get('content', '').strip()
|
|
|
|
if assistant_reply:
|
|
logger.info(f"{Fore.CYAN}[AUTO RESPONDER] AI GENERATED RESPONSE: {assistant_reply}{Style.RESET_ALL}")
|
|
return assistant_reply
|
|
else:
|
|
logger.warning("[WARNING] Empty response from Ollama")
|
|
return None
|
|
else:
|
|
logger.error(f"[ERROR] Ollama API error: {response.status_code}")
|
|
return None
|
|
|
|
except requests.exceptions.Timeout:
|
|
logger.error("[ERROR] TIMEOUT calling Ollama API")
|
|
return None
|
|
except Exception as e:
|
|
logger.error(f"[ERROR] ERROR generating ice breaker: {str(e)}")
|
|
return None
|
|
|
|
def print_banner():
|
|
"""Print startup banner"""
|
|
banner = f"""
|
|
{Fore.CYAN}============================================================
|
|
ICE BREAKER BOT v2.0
|
|
Enhanced Edition
|
|
============================================================{Style.RESET_ALL}
|
|
"""
|
|
print(banner)
|
|
|
|
def print_stats(stats):
|
|
"""Print formatted statistics"""
|
|
print(f"\n{Fore.YELLOW}[STATS] BOT STATISTICS:{Style.RESET_ALL}")
|
|
print(f" Messages Sent: {Fore.GREEN}{stats['messages_sent']}{Style.RESET_ALL}")
|
|
print(f" Users Processed: {Fore.GREEN}{stats['users_processed']}{Style.RESET_ALL}")
|
|
print(f" Errors: {Fore.RED}{stats['errors']}{Style.RESET_ALL}")
|
|
print(f" Runtime: {Fore.CYAN}{stats['runtime']}{Style.RESET_ALL}")
|
|
print(f" Messages/Hour: {Fore.CYAN}{stats['messages_per_hour']:.1f}{Style.RESET_ALL}")
|
|
|
|
def main():
|
|
"""Main function for enhanced ice breaker bot"""
|
|
print_banner()
|
|
logger.info(f"{Fore.CYAN}[STARTING] Enhanced MeetMe Ice Breaker Bot{Style.RESET_ALL}")
|
|
|
|
# Log API configuration
|
|
use_local = os.getenv('USE_LOCAL_API', 'false').lower() == 'true'
|
|
api_url = os.getenv('API_BASE_URL', 'https://api.meetme.com')
|
|
logger.info(f"{Fore.YELLOW}[CONFIG] Using {'local' if use_local else 'production'} API: {api_url}{Style.RESET_ALL}")
|
|
|
|
# Initialize client and login
|
|
client = EnhancedMeetMeClient()
|
|
if not client.login():
|
|
logger.error(f"{Fore.RED}[ERROR] FAILED to login. Exiting.{Style.RESET_ALL}")
|
|
return
|
|
|
|
# Get nearby users
|
|
users = client.get_nearby_users(page=1)
|
|
if not users:
|
|
logger.warning(f"{Fore.YELLOW}[WARNING] No nearby users found{Style.RESET_ALL}")
|
|
return
|
|
|
|
logger.info(f"{Fore.GREEN}[TARGET] Found {len(users)} nearby users to message{Style.RESET_ALL}")
|
|
|
|
# Process each user
|
|
for i, user in enumerate(users, 1):
|
|
try:
|
|
logger.info(f"{Fore.CYAN}[PROCESSING] user {i}/{len(users)}: {user['display_name']}{Style.RESET_ALL}")
|
|
logger.info(f"{Fore.MAGENTA}[USER BIO] {user['bio'][:100]}{'...' if len(user['bio']) > 100 else ''}{Style.RESET_ALL}")
|
|
|
|
# Generate ice breaker message
|
|
ice_breaker = generate_ice_breaker(user)
|
|
|
|
if ice_breaker:
|
|
# Send the message
|
|
if client.send_message(user['id'], ice_breaker):
|
|
logger.info(f"{Fore.GREEN}[SUCCESS] SUCCESS: Sent ice breaker to {user['display_name']}{Style.RESET_ALL}")
|
|
client.stats['users_processed'] += 1
|
|
else:
|
|
logger.error(f"{Fore.RED}[ERROR] FAILED: Could not send message to {user['display_name']}{Style.RESET_ALL}")
|
|
else:
|
|
logger.warning(f"{Fore.YELLOW}[WARNING] SKIPPING {user['display_name']} - no ice breaker generated{Style.RESET_ALL}")
|
|
|
|
# Wait between messages to avoid rate limiting
|
|
if i < len(users): # Don't sleep after the last user
|
|
logger.info(f"{Fore.YELLOW}[WAITING] WAITING 60 seconds before next message...{Style.RESET_ALL}")
|
|
time.sleep(60)
|
|
|
|
except Exception as e:
|
|
logger.error(f"{Fore.RED}[ERROR] ERROR processing user {user['display_name']}: {str(e)}{Style.RESET_ALL}")
|
|
continue
|
|
|
|
# Print final statistics
|
|
final_stats = client.get_stats()
|
|
print_stats(final_stats)
|
|
|
|
logger.info(f"{Fore.GREEN}[COMPLETE] Enhanced ice breaker bot completed!{Style.RESET_ALL}")
|
|
|
|
if __name__ == "__main__":
|
|
main() |