Files
aw-bot/aw.py
2024-07-08 12:50:21 +02:00

259 lines
8.0 KiB
Python

import datetime
import json
import os
import re
from typing import Literal
import discord
import requests
from discord import app_commands
from discord.ext import commands, tasks
GUILD_ID = 1110531063161299074
BOT_LOG = 1112049391482703873
# Define the channel IDs where auto responds are allowed
ALLOWED_CHANNELS = [
1110531063744303138,
1112048063448617142,
1145458108190163014,
1145456435518525611,
1145469136919613551,
1145459788151537804,
1145469106133401682,
1117540484085194833,
]
GENERAL_CHANNEL = 1110531063744303138
# Load existing patterns from file
try:
with open("patterns.json", "r") as f:
patterns = json.load(f)
except FileNotFoundError:
patterns = []
bot = commands.Bot(command_prefix="!", intents=discord.Intents.all())
tree = bot.tree
def fetch_api_data():
response = requests.get("https://api.getserve.rs/v1/servers/alterware")
if response.status_code == 200:
return response.json()
return {}
async def fetch_game_stats(game: str):
url = f"https://api.getserve.rs/v1/servers/alterware/{game}"
response = requests.get(url)
if response.status_code == 200:
return response.json()
else:
return None
async def compile_stats():
games = ["iw4", "s1", "iw6"]
stats_message = "**Stats for all games:**\n"
for game in games:
data = await fetch_game_stats(game)
if data:
count_servers = data.get("countServers", "N/A")
count_players = data.get("countPlayers", "N/A")
stats_message += f"**{game.upper()}:** Total Servers: {count_servers}, Total Players: {count_players}\n" # noqa
else:
stats_message += f"**{game.upper()}:** Failed to fetch stats.\n"
return stats_message
async def perform_search(query: str):
data = fetch_api_data()
servers = data.get("servers", [])
matching_servers = [
server
for server in servers
if query.lower() in server.get("hostnameDisplay", "").lower()
or query.lower() in server.get("ip", "").lower()
]
if not matching_servers:
return "No servers found matching your query."
max_results = 5
message = f'Top {min(len(matching_servers), max_results)} servers matching "{query}":\n' # noqa
for server in matching_servers[:max_results]:
message += (
f"- **{server['hostnameDisplay']}** | {server['gameDisplay']} | "
f"**Gametype**: {server['gametypeDisplay']} | **Map**: {server['mapDisplay']} | " # noqa
f"**Players**: {server['realClients']}/{server['maxplayers']}\n"
)
return message
@tree.command(
name="search",
description="Search for servers by hostname or IP.",
guild=discord.Object(id=GUILD_ID),
)
async def slash_search(interaction: discord.Interaction, query: str):
results = await perform_search(query)
await interaction.response.send_message(results)
@app_commands.checks.cooldown(1, 60, key=lambda i: (i.guild_id, i.user.id))
@tree.command(
name="stats",
description="Get stats for a specific game or all games",
guild=discord.Object(id=GUILD_ID),
)
async def stats(
interaction: discord.Interaction, game: Literal["iw4", "s1", "iw6", "all"]
):
if game == "all":
stats_message = await compile_stats()
else:
data = await fetch_game_stats(game)
if data:
stats_message = f"**Stats for {game.upper()}:**\n"
count_servers = data.get("countServers", "N/A")
count_players = data.get("countPlayers", "N/A")
stats_message += f"Total Servers: {count_servers}\n" # noqa
stats_message += f"Total Players: {count_players}\n" # noqa
else:
stats_message = (
"Failed to fetch game stats. Please try again later." # noqa
)
await interaction.response.send_message(stats_message, ephemeral=True)
# await interaction.delete_original_response()
async def on_tree_error(
interaction: discord.Interaction, error: app_commands.AppCommandError
):
if isinstance(error, app_commands.CommandOnCooldown):
return await interaction.response.send_message(
f"Command is currently on cooldown! Try again in **{error.retry_after:.2f}** seconds!" # noqa
)
elif isinstance(error, app_commands.MissingPermissions):
return await interaction.response.send_message(
"You are missing permissions to use that"
)
else:
raise error
bot.tree.on_error = on_tree_error
@bot.event
async def on_message_delete(message):
channel = bot.get_channel(BOT_LOG)
if channel:
embed = discord.Embed(
title="Deleted Message",
description="A message was deleted.",
color=0xDD2E44,
)
embed.add_field(
name="Author", value=message.author.mention, inline=True
) # noqa
embed.add_field(
name="Channel", value=message.channel.mention, inline=True
) # noqa
if message.content:
embed.add_field(name="Content", value=message.content, inline=False) # noqa
embed.set_footer(
text=f"Message ID: {message.id} | Author ID: {message.author.id}"
)
await channel.send(embed=embed)
@bot.event
async def on_bulk_message_delete(messages):
channel = bot.get_channel(BOT_LOG)
if channel:
for message in messages:
embed = discord.Embed(
title="Deleted Message",
description="A message was deleted.",
color=0xDD2E44,
)
embed.add_field(
name="Author", value=message.author.mention, inline=True
) # noqa
embed.add_field(
name="Channel", value=message.channel.mention, inline=True
) # noqa
if message.content:
embed.add_field(
name="Content", value=message.content, inline=False
) # noqa
embed.set_footer(
text=f"Message ID: {message.id} | Author ID: {message.author.id}" # noqa
)
await channel.send(embed=embed)
@bot.event
async def on_message(message):
if message.author == bot.user:
return
# Too many mentions
if len(message.mentions) >= 3:
await message.delete()
member = message.guild.get_member(message.author.id)
if member:
# Timeout the member for 60 seconds
await member.timeout_for(
discord.utils.utcnow() + datetime.timedelta(seconds=60)
)
return
# Auto delete torrent if post in chat.
for file in message.attachments:
if file.filename.endswith((".torrent", ".TORRENT")):
await message.delete()
# Check if the message is in an allowed channel
if message.channel.id not in ALLOWED_CHANNELS:
return
# Check if any of the patterns match the message
# print('Checking for patterns...')
for pattern in patterns:
if re.search(pattern["regex"], message.content, re.IGNORECASE):
# print('Checking message content:', message.content, re.IGNORECASE) # noqa
# print('Matching pattern regex:', pattern['regex']) # noqa
# print('Pattern match:', re.search(pattern['regex'], message.content, re.IGNORECASE)) # noqa
response = pattern["response"]
await message.channel.send(response)
break
# Update Player Counts from API
@tasks.loop(minutes=10)
async def update_status():
data = fetch_api_data()
countPlayers = data.get("countPlayers", 0)
countServers = data.get("countServers", 0)
activity = discord.Game(
name=f"with {countPlayers} players on {countServers} servers"
)
await bot.change_presence(activity=activity)
@bot.event
async def on_ready():
print(f"{bot.user.name} has connected to Discord!")
await tree.sync(
guild=discord.Object(id=GUILD_ID)
) # Sync commands for a specific guild.
update_status.start()
bot.run(os.getenv("BOT_TOKEN"))