186 lines
No EOL
7 KiB
Python
186 lines
No EOL
7 KiB
Python
import discord
|
|
from discord.ext import commands, tasks
|
|
from datetime import datetime, timedelta
|
|
import json
|
|
import pytz
|
|
import os
|
|
from dotenv import load_dotenv
|
|
|
|
# Load environment variables from .env file
|
|
load_dotenv()
|
|
|
|
# Retrieve the bot token from the environment variable
|
|
TOKEN = os.getenv('DISCORD_BOT_TOKEN')
|
|
|
|
# Set up intents
|
|
intents = discord.Intents.default()
|
|
intents.members = True
|
|
intents.message_content = True
|
|
bot = commands.Bot(command_prefix='/tp ', intents=intents)
|
|
|
|
# File path for tickets data
|
|
TICKETS_FILE = 'tickets.json'
|
|
|
|
# Load or initialize tickets data
|
|
def load_tickets_data():
|
|
if os.path.exists(TICKETS_FILE):
|
|
with open(TICKETS_FILE, 'r') as f:
|
|
try:
|
|
data = json.load(f)
|
|
print("Loaded tickets data:", data) # Debug log
|
|
return data
|
|
except json.JSONDecodeError as e:
|
|
print(f"Error loading JSON data: {e}")
|
|
return {}
|
|
return {}
|
|
|
|
tickets_data = load_tickets_data()
|
|
|
|
# Helper function to save tickets data
|
|
def save_tickets_data():
|
|
with open(TICKETS_FILE, 'w') as f:
|
|
json.dump(tickets_data, f, indent=4)
|
|
print("Saved tickets data:", tickets_data) # Debug log
|
|
|
|
# Helper function to reload tickets data from the file
|
|
def reload_tickets_data():
|
|
global tickets_data
|
|
tickets_data = load_tickets_data()
|
|
|
|
# Command to assign a ticket
|
|
@bot.command()
|
|
@commands.has_permissions(administrator=True)
|
|
async def assign_ticket(ctx, member: discord.Member, email: str, ticket_type: str = "normal"):
|
|
if ticket_type not in ["normal", "golden"]:
|
|
await ctx.send("Invalid ticket type. Use 'normal' or 'golden'.")
|
|
return
|
|
|
|
member_id = str(member.id) # Ensure ID is a string
|
|
if member_id not in tickets_data:
|
|
tickets_data[member_id] = {"email": email, "tickets": []}
|
|
|
|
if ticket_type == "normal":
|
|
# Assign an individual expiration date for the normal ticket
|
|
expiration_date = datetime.utcnow() + timedelta(days=365)
|
|
tickets_data[member_id]["tickets"].append({
|
|
"type": "normal",
|
|
"expiration": expiration_date.isoformat()
|
|
})
|
|
expiration_message = f", which expires on {expiration_date.strftime('%Y-%m-%d %H:%M:%S')} UTC."
|
|
else:
|
|
# Golden tickets do not expire
|
|
tickets_data[member_id]["tickets"].append({
|
|
"type": "golden",
|
|
"expiration": None
|
|
})
|
|
expiration_message = ""
|
|
|
|
save_tickets_data()
|
|
reload_tickets_data() # Reload the tickets data to ensure consistency
|
|
await ctx.send(f"Assigned a {ticket_type} ticket to {member.mention}{expiration_message}.")
|
|
|
|
# Command to redeem a ticket
|
|
@bot.command()
|
|
@commands.has_permissions(administrator=True)
|
|
async def redeem_ticket(ctx, member: discord.Member, ticket_type: str):
|
|
if ticket_type not in ["normal", "golden"]:
|
|
await ctx.send("Invalid ticket type. Use 'normal' or 'golden'.")
|
|
return
|
|
|
|
member_id = str(member.id) # Ensure ID is a string
|
|
if member_id not in tickets_data or not tickets_data[member_id]["tickets"]:
|
|
await ctx.send(f"{member.mention} does not have any tickets.")
|
|
return
|
|
|
|
for i, ticket in enumerate(tickets_data[member_id]["tickets"]):
|
|
if ticket["type"] == ticket_type:
|
|
del tickets_data[member_id]["tickets"][i]
|
|
save_tickets_data()
|
|
reload_tickets_data() # Reload the tickets data to ensure consistency
|
|
await ctx.send(f"Redeemed a {ticket_type} ticket for {member.mention}.")
|
|
return
|
|
|
|
await ctx.send(f"{member.mention} does not have any {ticket_type} tickets to redeem.")
|
|
|
|
# Command to check a user's tickets (admins only)
|
|
@bot.command()
|
|
@commands.has_permissions(administrator=True)
|
|
async def check_ticket(ctx, member: discord.Member):
|
|
member_id = str(member.id) # Ensure ID is a string
|
|
if member_id not in tickets_data or not tickets_data[member_id]["tickets"]:
|
|
await ctx.send(f"{member.mention} does not have any tickets.")
|
|
return
|
|
|
|
ticket_info = tickets_data[member_id]["tickets"]
|
|
normal_tickets = [t for t in ticket_info if t["type"] == "normal"]
|
|
golden_tickets = [t for t in ticket_info if t["type"] == "golden"]
|
|
|
|
# Timezone definitions
|
|
tz_utc = pytz.UTC
|
|
tz_mst = pytz.timezone('America/Edmonton')
|
|
|
|
normal_message = f"{member.mention} has {len(normal_tickets)} normal tickets:\n"
|
|
for ticket in normal_tickets:
|
|
expiration_date_utc = datetime.fromisoformat(ticket["expiration"]).astimezone(tz_utc)
|
|
expiration_date_mst = expiration_date_utc.astimezone(tz_mst)
|
|
normal_message += f"- Expires on {expiration_date_utc.strftime('%Y-%m-%d %H:%M:%S')} UTC / {expiration_date_mst.strftime('%Y-%m-%d %H:%M:%S')} MST\n"
|
|
|
|
golden_message = f"{member.mention} has {len(golden_tickets)} golden tickets."
|
|
|
|
await ctx.send(f"{normal_message}{golden_message}")
|
|
|
|
# Command to check your own tickets (all users)
|
|
@bot.command()
|
|
async def tickets(ctx):
|
|
member_id = str(ctx.author.id) # Ensure ID is a string
|
|
if member_id not in tickets_data or not tickets_data[member_id]["tickets"]:
|
|
# Send a DM if no tickets are found
|
|
await ctx.author.send("You do not have any tickets.")
|
|
await ctx.send("I have sent you a DM with your ticket information.")
|
|
return
|
|
|
|
ticket_info = tickets_data[member_id]["tickets"]
|
|
normal_tickets = [t for t in ticket_info if t["type"] == "normal"]
|
|
golden_tickets = [t for t in ticket_info if t["type"] == "golden"]
|
|
|
|
normal_message = f"You have {len(normal_tickets)} normal tickets:\n"
|
|
for ticket in normal_tickets:
|
|
expiration_date = datetime.fromisoformat(ticket["expiration"])
|
|
normal_message += f"- Expires on {expiration_date.strftime('%Y-%m-%d %H:%M:%S')} UTC\n"
|
|
|
|
golden_message = f"You have {len(golden_tickets)} golden tickets."
|
|
|
|
# Send the result to the user via DM
|
|
await ctx.author.send(f"{normal_message}\n{golden_message}")
|
|
await ctx.send("I have sent you a DM with your ticket information.")
|
|
|
|
# Background task to check and remove expired tickets
|
|
@tasks.loop(hours=24)
|
|
async def check_expired_tickets():
|
|
tz = pytz.UTC
|
|
current_time = datetime.now(tz)
|
|
to_remove = []
|
|
|
|
for member_id, ticket_info in tickets_data.items():
|
|
tickets_data[member_id]["tickets"] = [
|
|
ticket for ticket in ticket_info["tickets"]
|
|
if ticket["type"] == "golden" or current_time < datetime.fromisoformat(ticket["expiration"]).astimezone(tz)
|
|
]
|
|
|
|
# Remove the member if they have no tickets left
|
|
if not tickets_data[member_id]["tickets"]:
|
|
to_remove.append(member_id)
|
|
|
|
for member_id in to_remove:
|
|
print(f"Removing expired tickets for user ID: {member_id}") # Debug log
|
|
del tickets_data[member_id]
|
|
|
|
save_tickets_data()
|
|
|
|
@bot.event
|
|
async def on_ready():
|
|
print(f'Logged in as {bot.user.name}')
|
|
check_expired_tickets.start()
|
|
|
|
# Run the bot
|
|
bot.run(TOKEN) |