User Log and Persistent Faction Information
This commit is contained in:
@@ -6,6 +6,7 @@ from pathlib import Path
|
||||
from typing import Dict, Optional
|
||||
from datetime import datetime
|
||||
from services.server_state import STATE
|
||||
from services.activity_log import activity_logger
|
||||
from config import ASSIGNMENT_TIMEOUT, ASSIGNMENT_REMINDER, ALLOWED_CHANNEL_ID, CHAIN_TIMER_THRESHOLD, TORN_API_KEY
|
||||
|
||||
class BotAssignmentManager:
|
||||
@@ -28,7 +29,7 @@ class BotAssignmentManager:
|
||||
self.load_discord_mapping()
|
||||
|
||||
def load_discord_mapping(self):
|
||||
"""Load Torn ID to Discord ID mapping from JSON file"""
|
||||
#Load Torn ID to Discord ID mapping from JSON file
|
||||
path = Path("data/discord_mapping.json")
|
||||
if not path.exists():
|
||||
print("No discord_mapping.json found")
|
||||
@@ -44,11 +45,11 @@ class BotAssignmentManager:
|
||||
print(f"Error loading discord mapping: {e}")
|
||||
|
||||
def get_discord_id(self, torn_id: int) -> Optional[int]:
|
||||
"""Get Discord user ID for a Torn player ID"""
|
||||
#Get Discord user ID for a Torn player ID#
|
||||
return self.discord_mapping.get(torn_id)
|
||||
|
||||
async def fetch_chain_timer(self) -> Optional[int]:
|
||||
"""Fetch chain timeout from Torn API. Returns seconds remaining, or None if no chain or error."""
|
||||
#Fetch chain timeout from Torn API. Returns seconds remaining, or None if no chain or error.
|
||||
if not STATE.friendly_faction_id:
|
||||
return None
|
||||
|
||||
@@ -69,7 +70,7 @@ class BotAssignmentManager:
|
||||
return None
|
||||
|
||||
async def start(self):
|
||||
"""Start the bot assignment loop"""
|
||||
#Start the bot assignment loop
|
||||
if self.running:
|
||||
print("WARNING: Bot assignment already running")
|
||||
return
|
||||
@@ -94,18 +95,16 @@ class BotAssignmentManager:
|
||||
print("Bot assignment stopped")
|
||||
|
||||
def friendly_has_active_target(self, friendly_id: int) -> bool:
|
||||
"""Check if a friendly player already has an active target assigned"""
|
||||
#Check if a friendly player already has an active target assigned
|
||||
for target_data in self.active_targets.values():
|
||||
if target_data["friendly_id"] == friendly_id:
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_next_friendly_in_group(self, group_id: str, friendly_ids: list) -> Optional[int]:
|
||||
"""
|
||||
Get the next friendly in the group who should receive a target.
|
||||
Prioritizes members with fewer hits.
|
||||
Only returns friendlies who DON'T already have an active assignment.
|
||||
"""
|
||||
#Get the next friendly in the group who should receive a target.
|
||||
#Prioritizes members with fewer hits.
|
||||
#Only returns friendlies who DON'T already have an active assignment.
|
||||
if not friendly_ids:
|
||||
return None
|
||||
|
||||
@@ -130,10 +129,8 @@ class BotAssignmentManager:
|
||||
return friendly_hits[0][0]
|
||||
|
||||
def get_next_enemy_in_group(self, group_id: str, enemy_ids: list) -> Optional[int]:
|
||||
"""
|
||||
Get the next enemy in the group who needs to be assigned.
|
||||
Returns None if all enemies are already assigned or not attackable.
|
||||
"""
|
||||
#Get the next enemy in the group who needs to be assigned.
|
||||
#Returns None if all enemies are already assigned or not attackable.
|
||||
for eid in enemy_ids:
|
||||
key = f"{group_id}:{eid}"
|
||||
# If enemy is already assigned, skip them
|
||||
@@ -150,7 +147,7 @@ class BotAssignmentManager:
|
||||
return None
|
||||
|
||||
async def check_chain_timer(self):
|
||||
"""Check chain timer and update chain state"""
|
||||
#Check chain timer and update chain state
|
||||
timeout = await self.fetch_chain_timer()
|
||||
|
||||
if timeout is None:
|
||||
@@ -173,6 +170,8 @@ class BotAssignmentManager:
|
||||
self.assigned_friendlies.clear()
|
||||
self.current_group_index = 0
|
||||
self.chain_warning_sent = False
|
||||
# Log to activity
|
||||
await activity_logger.log_action("System", "Chain Mode Activated", f"Timer: {timeout}s, Threshold: {threshold_seconds}s")
|
||||
|
||||
# Check if chain expired
|
||||
elif timeout > threshold_seconds and self.chain_active:
|
||||
@@ -181,6 +180,8 @@ class BotAssignmentManager:
|
||||
self.assigned_friendlies.clear()
|
||||
self.current_group_index = 0
|
||||
self.chain_warning_sent = False
|
||||
# Log to activity
|
||||
await activity_logger.log_action("System", "Chain Mode Deactivated", f"Timer: {timeout}s exceeded threshold")
|
||||
|
||||
# Check if chain expired (timeout = 0)
|
||||
elif timeout == 0 and self.chain_active:
|
||||
@@ -189,14 +190,18 @@ class BotAssignmentManager:
|
||||
self.assigned_friendlies.clear()
|
||||
self.current_group_index = 0
|
||||
self.chain_warning_sent = False
|
||||
# Log to activity
|
||||
await activity_logger.log_action("System", "Chain Expired", "Chain timer reached 0")
|
||||
|
||||
# Send 30-second warning
|
||||
if self.chain_active and timeout <= 30 and not self.chain_warning_sent:
|
||||
await self.send_chain_expiration_warning()
|
||||
self.chain_warning_sent = True
|
||||
# Log to activity
|
||||
await activity_logger.log_action("System", "Chain Expiration Warning", "30 seconds remaining")
|
||||
|
||||
async def send_chain_expiration_warning(self):
|
||||
"""Send @here alert that chain is about to expire"""
|
||||
#Send @here alert that chain is about to expire
|
||||
try:
|
||||
channel = self.bot.get_channel(ALLOWED_CHANNEL_ID)
|
||||
if channel and STATE.friendly_faction_id:
|
||||
@@ -208,7 +213,7 @@ class BotAssignmentManager:
|
||||
print(f"Error sending chain warning: {e}")
|
||||
|
||||
async def assign_next_chain_hit(self):
|
||||
"""Assign next hit in round-robin fashion through groups"""
|
||||
#Assign next hit in round-robin fashion through groups
|
||||
# Only assign if there's no active assignment waiting
|
||||
if self.active_targets:
|
||||
return # Wait for current assignment to complete
|
||||
@@ -265,7 +270,7 @@ class BotAssignmentManager:
|
||||
self.current_group_index = 0
|
||||
|
||||
async def assignment_loop(self):
|
||||
"""Main loop that monitors chain timer and assigns targets"""
|
||||
#Main loop that monitors chain timer and assigns targets
|
||||
await self.bot.wait_until_ready()
|
||||
print("Bot is ready, assignment loop running with chain timer monitoring")
|
||||
|
||||
@@ -307,7 +312,7 @@ class BotAssignmentManager:
|
||||
await asyncio.sleep(5)
|
||||
|
||||
async def assign_target(self, group_id: str, friendly_id: int, enemy_id: int):
|
||||
"""Assign an enemy target to a friendly player"""
|
||||
#Assign an enemy target to a friendly player
|
||||
# Get member data
|
||||
friendly = STATE.friendly.get(friendly_id)
|
||||
enemy = STATE.enemy.get(enemy_id)
|
||||
@@ -367,6 +372,8 @@ class BotAssignmentManager:
|
||||
if channel:
|
||||
await channel.send(message)
|
||||
print(f"Assigned {enemy.name} to {friendly.name} (Discord: {discord_user.name})")
|
||||
# Log to activity
|
||||
await activity_logger.log_action("System", "Hit Assigned", f"{friendly.name} -> {enemy.name} (Level {enemy.level})")
|
||||
else:
|
||||
print(f"Assignment channel {ALLOWED_CHANNEL_ID} not found")
|
||||
self.active_targets[key]["failed"] = True
|
||||
@@ -375,7 +382,7 @@ class BotAssignmentManager:
|
||||
self.active_targets[key]["failed"] = True
|
||||
|
||||
async def monitor_active_targets(self):
|
||||
"""Monitor active targets for status changes or timeouts"""
|
||||
#Monitor active targets for status changes or timeouts
|
||||
now = datetime.now()
|
||||
to_reassign = []
|
||||
|
||||
@@ -404,7 +411,11 @@ class BotAssignmentManager:
|
||||
if friendly_id in STATE.friendly:
|
||||
# Increment hit count
|
||||
STATE.friendly[friendly_id].hits += 1
|
||||
print(f"SUCCESS: {STATE.friendly[friendly_id].name} successfully hospitalized {enemy.name}")
|
||||
friendly_name = STATE.friendly[friendly_id].name
|
||||
enemy_name = enemy.name
|
||||
print(f"SUCCESS: {friendly_name} successfully hospitalized {enemy_name}")
|
||||
# Log to activity
|
||||
await activity_logger.log_action("System", "Hit Completed", f"{friendly_name} hospitalized {enemy_name}")
|
||||
|
||||
# Remove from active targets
|
||||
del self.active_targets[key]
|
||||
@@ -412,7 +423,13 @@ class BotAssignmentManager:
|
||||
|
||||
# Check if enemy is no longer attackable (traveling, etc.)
|
||||
if enemy.status.lower() != "okay":
|
||||
print(f"Target {enemy.name} is now '{enemy.status}' - removing assignment")
|
||||
friendly_id = data["friendly_id"]
|
||||
friendly_name = STATE.friendly.get(friendly_id).name if friendly_id in STATE.friendly else "Unknown"
|
||||
enemy_name = enemy.name
|
||||
enemy_status = enemy.status
|
||||
print(f"Target {enemy_name} is now '{enemy_status}' - removing assignment")
|
||||
# Log to activity
|
||||
await activity_logger.log_action("System", "Hit Dropped", f"{friendly_name}'s target {enemy_name} became {enemy_status}")
|
||||
del self.active_targets[key]
|
||||
continue
|
||||
|
||||
@@ -445,7 +462,11 @@ class BotAssignmentManager:
|
||||
friendly_ids = STATE.groups[group_id].get("friendly", [])
|
||||
friendly_id = self.get_next_friendly_in_group(group_id, friendly_ids)
|
||||
if friendly_id:
|
||||
enemy_name = STATE.enemy.get(enemy_id).name if enemy_id in STATE.enemy else f"Enemy {enemy_id}"
|
||||
friendly_name = STATE.friendly.get(friendly_id).name if friendly_id in STATE.friendly else f"Friendly {friendly_id}"
|
||||
print(f"Reassigning enemy {enemy_id} (timeout)")
|
||||
# Log to activity
|
||||
await activity_logger.log_action("System", "Hit Timed Out", f"Reassigning {enemy_name} to {friendly_name} (previous assignee timed out)")
|
||||
await self.assign_target(group_id, friendly_id, enemy_id)
|
||||
|
||||
# Global instance (will be initialized with bot in main.py)
|
||||
|
||||
Reference in New Issue
Block a user