Changed status lookup to only queue okay enemies for attack

This commit is contained in:
2026-01-26 15:51:44 -05:00
parent 7ea6f146e1
commit f45f02501a
4 changed files with 69 additions and 26 deletions

View File

@@ -9,13 +9,8 @@ Features:
ToDo:
- API Key section
- Have user enter their own API key, pass along to the functions that call APIs
- server side config storage
- have multiple managers logged in to make changes
- basic auth
- since control of the Discord bot would also be through there technically
- add status description to member cards
- Log output section on webpage, to see who is being assigned to who, when the hit is complete, if it is missed, how many hits a person has done
- Hit Leaderboard?
For now let's pivot to the Discord Bot functionality. What the bot is going to do is for each battle group it needs to assign a friendly member to an enemy member. That friendly will then get a ping in Discord by pulling the list of Discord users and matching the player id to the user in the Discord server. It will ping them and say "New target for @user , attack (link to enemy profile) in the next 30 seconds!" If the enemies status does not change to "In Hospital" in the next 30 seconds that enemy will be assigned to the next player in the group that has not received a hit yet. We will also need to keep track of how many hits a friendly has completed. That way if a new friendly enters a pool they will get a chance to attack before the ones that have not had a chance. We also need a button on the webpage to start and stop the bot

Binary file not shown.

View File

@@ -102,12 +102,20 @@ class BotAssignmentManager:
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.
Returns None if all enemies are already assigned or not attackable.
"""
for eid in enemy_ids:
key = f"{group_id}:{eid}"
# If enemy is not currently assigned, return it
if key not in self.active_targets:
# If enemy is already assigned, skip them
if key in self.active_targets:
continue
# Check if enemy is attackable (status must be "Okay")
enemy = STATE.enemy.get(eid)
if not enemy or enemy.status.lower() != "okay":
continue
# This enemy is available for assignment
return eid
return None
@@ -176,18 +184,30 @@ class BotAssignmentManager:
print(f"Cannot assign: friendly {friendly_id} or enemy {enemy_id} not found")
return
# Only assign if enemy status is "Okay" (not traveling, hospitalized, etc.)
if enemy.status.lower() != "okay":
print(f"Skipping assignment: {enemy.name} status is '{enemy.status}' (must be 'Okay')")
return
# Get Discord user
discord_id = self.get_discord_id(friendly_id)
if not discord_id:
print(f"No Discord mapping for Torn ID {friendly_id}")
print(f"No Discord mapping for Torn ID {friendly_id} - skipping assignment")
# Record assignment to prevent infinite retries
key = f"{group_id}:{enemy_id}"
self.active_targets[key] = {
"group_id": group_id,
"friendly_id": friendly_id,
"enemy_id": enemy_id,
"discord_id": None,
"assigned_at": datetime.now(),
"reminded": False,
"failed": True
}
return
discord_user = await self.bot.fetch_user(discord_id)
if not discord_user:
print(f"Discord user {discord_id} not found")
return
# Record assignment
# Record assignment BEFORE attempting to send message
# This prevents infinite retries if message sending fails
key = f"{group_id}:{enemy_id}"
self.active_targets[key] = {
"group_id": group_id,
@@ -195,22 +215,32 @@ class BotAssignmentManager:
"enemy_id": enemy_id,
"discord_id": discord_id,
"assigned_at": datetime.now(),
"reminded": False
"reminded": False,
"failed": False
}
# Fetch Discord user and send message
try:
discord_user = await self.bot.fetch_user(discord_id)
if not discord_user:
print(f"Discord user {discord_id} not found")
self.active_targets[key]["failed"] = True
return
# Send Discord message to channel
attack_link = f"https://www.torn.com/loader.php?sid=attack&user2ID={enemy_id}"
message = f"**New target for {discord_user.mention}!**\n\n[**{enemy.name}** (Level {enemy.level})]({attack_link})\n\nYou have {ASSIGNMENT_TIMEOUT} seconds!"
try:
channel = self.bot.get_channel(ALLOWED_CHANNEL_ID)
if channel:
await channel.send(message)
print(f"Assigned {enemy.name} to {friendly.name} (Discord: {discord_user.name})")
else:
print(f"Assignment channel {ALLOWED_CHANNEL_ID} not found")
self.active_targets[key]["failed"] = True
except Exception as e:
print(f"Failed to send Discord message to channel: {e}")
self.active_targets[key]["failed"] = True
async def monitor_active_targets(self):
"""Monitor active targets for status changes or timeouts"""
@@ -220,12 +250,24 @@ class BotAssignmentManager:
for key, data in list(self.active_targets.items()):
elapsed = (now - data["assigned_at"]).total_seconds()
# Remove failed assignments after a short delay (don't reassign them)
if data.get("failed", False):
if elapsed >= 30: # Clean up after 30 seconds
print(f"Removing failed assignment: {key}")
del self.active_targets[key]
continue
# Check enemy status
enemy_id = data["enemy_id"]
enemy = STATE.enemy.get(enemy_id)
if enemy and "hospital" in enemy.status.lower():
# Enemy is hospitalized - success!
if not enemy:
# Enemy no longer exists, remove assignment
del self.active_targets[key]
continue
# Check if enemy is hospitalized (success!)
if "hospital" in enemy.status.lower():
friendly_id = data["friendly_id"]
if friendly_id in STATE.friendly:
# Increment hit count
@@ -236,7 +278,13 @@ class BotAssignmentManager:
del self.active_targets[key]
continue
# Send reminder
# 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")
del self.active_targets[key]
continue
# Send reminder (only for successful assignments)
if elapsed >= ASSIGNMENT_REMINDER and not data["reminded"]:
discord_id = data["discord_id"]
try: