MosswartLurker/bottenstats.py
2025-04-13 00:04:10 +02:00

399 lines
7.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import discord
import asyncio
import shutil
import os
import re
import json
from datetime import datetime, timedelta
# === CONFIGURATION ===
TOKEN = 'MTM0OTgwNTE1NzY5MjYwNDUwNg.Gv_jgN.GyvpdRHS95UrzCHapfHm94_4bzvIS1g5g9uq54'
CHANNEL_ID_ACLOG = 1349649482786275328
CHANNEL_ID_COMMON_RARES = 1355328792184226014
CHANNEL_ID_GREAT_RARES = 1353676584334131211
COMMON_RARE_KEYWORDS = ["Crystal", "Jewel", "Pearl", "Elixir", "Kit"]
LOG_FILE = 'C:/Users/acbot/Documents/Decal Plugins/UtilityBelt/Coldeve/Dunking Rares/chat.txt'
TEMP_FILE = 'C:/Users/acbot/Documents/bot/chat_copy.txt'
STATS_FILE = 'C:/Users/acbot/Documents/bot/rares_stats.json'
# === DISCORD SETUP ===
intents = discord.Intents.default()
intents.guilds = True
intents.messages = True
intents.message_content = True
client = discord.Client(intents=intents)
# === STATS STORAGE ===
rares_stats = {}
def load_stats():
global rares_stats
if os.path.exists(STATS_FILE):
with open(STATS_FILE, 'r') as f:
rares_stats = json.load(f)
else:
rares_stats = {}
def save_stats():
try:
with open(STATS_FILE, 'w') as f:
json.dump(rares_stats, f, indent=2)
print(f"✅ Stats saved to: {STATS_FILE}")
except Exception as e:
print(f"❌ Failed to save stats: {e}")
# === PARSE ===
def parse_line(line):
match = re.search(r'^(.*?)\|.*?<Tell:IIDString:\d+:(.+?)>.+?<\\Tell> says, "(.*?)"', line)
if match:
timestamp_full = match.group(1)
name = match.group(2)
message = match.group(3)
time_match = re.search(r'T(\d{2}:\d{2}:\d{2})', timestamp_full)
if time_match:
short_time = time_match.group(1)
else:
short_time = "Unknown"
return short_time, name, message
return None
def track_rare(name, rare_type):
print(f"Tracking Rare: {name} found {rare_type}")
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M")
if name not in rares_stats:
rares_stats[name] = {"total": 0, "rares": []}
rares_stats[name]["total"] += 1
rares_stats[name]["rares"].append({"type": rare_type, "timestamp": timestamp})
save_stats()
def summary_for_range(label, days):
cutoff = datetime.now() - timedelta(days=days)
output = f"**Rare Summary {label}**\n"
found_any = False
for name, data in rares_stats.items():
count = 0
for r in data['rares']:
try:
ts = datetime.strptime(r['timestamp'], "%Y-%m-%d %H:%M")
if ts >= cutoff:
count += 1
except:
continue
if count > 0:
output += f"{name} {count}\n"
found_any = True
return output if found_any else f"No rares found in the last {label.lower()}."
# === BOT EVENTS ===
@client.event
async def on_ready():
print(f'✅ Inloggad som {client.user}')
load_stats()
ch_aclog = client.get_channel(CHANNEL_ID_ACLOG)
ch_common = client.get_channel(CHANNEL_ID_COMMON_RARES)
ch_great = client.get_channel(CHANNEL_ID_GREAT_RARES)
if not all([ch_aclog, ch_common, ch_great]):
print("❌ Kunde inte hitta alla kanaler.")
await client.close()
return
asyncio.create_task(monitor_file(ch_aclog, ch_common, ch_great))
@client.event
async def on_message(message):
if message.author == client.user:
return
content = message.content.lower()
if content.startswith('!help'):
reply = (
"**Available Commands:**\n"
"!stats Show total rare count per player\n"
"!stats_<name> Show rare types and timestamps for a player\n"
"!top Show top 3 players with most rares\n"
"!daily Rares found in the last 24h\n"
"!weekly Rares found in the last 7 days\n"
"!monthly Rares found in the last 30 days\n"
"!yearly Rares found in the last 365 days"
)
await message.channel.send(reply)
elif content.startswith('!stats_'):
name = message.content[len('!stats_'):].strip()
if name in rares_stats:
reply = f"**{name}** has found the following rares:\n"
for r in rares_stats[name]['rares']:
reply += f"{r['type']} {r['timestamp']}\n"
else:
reply = f"No rares found for {name}."
await message.channel.send(reply)
elif content.startswith('!stats'):
if not rares_stats:
await message.channel.send("No rares recorded yet.")
return
reply = "**Rares per player:**\n"
sorted_players = sorted(rares_stats.items(), key=lambda x: x[1]['total'], reverse=True)
for name, data in sorted_players.items():
reply += f"{name} {data['total']} rares\n"
await message.channel.send(reply)
elif content.startswith('!top'):
top = sorted(rares_stats.items(), key=lambda x: x[1]['total'], reverse=True)[:3]
if not top:
await message.channel.send("No rare data yet.")
return
reply = "**Top Rare Hunters:**\n"
for i, (name, data) in enumerate(top, 1):
reply += f"{i}. {name} {data['total']} rares\n"
await message.channel.send(reply)
elif content.startswith('!daily'):
await message.channel.send(summary_for_range("Daily", 1))
elif content.startswith('!weekly'):
await message.channel.send(summary_for_range("Weekly", 7))
elif content.startswith('!monthly'):
await message.channel.send(summary_for_range("Monthly", 30))
elif content.startswith('!yearly'):
await message.channel.send(summary_for_range("Yearly", 365))
# === FILE MONITORING ===
async def monitor_file(ch_aclog, ch_common, ch_great):
last_position = None
while True:
try:
shutil.copyfile(LOG_FILE, TEMP_FILE)
with open(TEMP_FILE, 'r', encoding='utf-8') as file:
if last_position is None:
file.seek(0, 2)
last_position = file.tell()
else:
file.seek(last_position)
new_lines = file.readlines()
last_position = file.tell()
for line in new_lines:
line = line.strip()
if line:
parsed = parse_line(line)
if parsed:
timestamp, name, message = parsed
embed = discord.Embed(
title=timestamp,
description=f'**{name}**\n"{message}"',
color=discord.Color.green()
)
if "has discovered the" in message:
if any(k in message for k in COMMON_RARE_KEYWORDS) and "Frore Crystal" not in message:
await ch_common.send(embed=embed)
else:
await ch_great.send(embed=embed)
rare_name_match = re.search(r'has discovered the (.+?)!', message)
if rare_name_match:
rare_name = rare_name_match.group(1)
track_rare(name, rare_name)
else:
await ch_aclog.send(embed=embed)
except Exception as e:
print(f"⚠️ Fel: {e}")
await asyncio.sleep(1)
client.run(TOKEN)