Initial commit

This commit is contained in:
Vassili Minaev 2026-05-05 20:26:54 -06:00
commit bed95c3111
2 changed files with 323 additions and 0 deletions

186
bot.py Normal file
View file

@ -0,0 +1,186 @@
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)

137
tickets.json Normal file
View file

@ -0,0 +1,137 @@
{
"272518615356538887": {
"email": "seifer.moringa@gmail.com",
"tickets": [
{
"type": "golden",
"expiration": null
}
]
},
"928079996403212429": {
"email": "metalarms127@gmail.com",
"tickets": [
{
"type": "golden",
"expiration": null
},
{
"type": "golden",
"expiration": null
}
]
},
"526179144967520257": {
"email": "nyrvaan@gmail.com",
"tickets": [
{
"type": "normal",
"expiration": "2026-10-28T01:04:21.726082"
},
{
"type": "normal",
"expiration": "2026-10-28T01:05:18.289342"
}
]
},
"865708915924533248": {
"email": "romangraham07@gmail.com",
"tickets": [
{
"type": "normal",
"expiration": "2026-05-30T01:40:52.106310"
},
{
"type": "normal",
"expiration": "2027-04-07T00:09:45.822523"
}
]
},
"1131710863343091722": {
"email": "atomiccryo@gmail.com",
"tickets": [
{
"type": "normal",
"expiration": "2026-05-30T01:41:46.157234"
},
{
"type": "normal",
"expiration": "2026-11-01T20:06:20.779733"
},
{
"type": "normal",
"expiration": "2027-04-07T00:17:19.067922"
}
]
},
"348204092709142538": {
"email": "micahelacostapsyd@gmail.com",
"tickets": [
{
"type": "normal",
"expiration": "2026-06-01T05:00:16.756179"
}
]
},
"267100324127440907": {
"email": "mskintner@gmail.com",
"tickets": [
{
"type": "golden",
"expiration": null
},
{
"type": "normal",
"expiration": "2027-05-01T20:40:03.987511"
},
{
"type": "normal",
"expiration": "2027-05-01T20:40:08.497594"
},
{
"type": "normal",
"expiration": "2027-05-01T20:40:10.222346"
},
{
"type": "normal",
"expiration": "2027-05-01T20:40:11.817248"
}
]
},
"1097655473337016481": {
"email": "spectre1kj@gmail.com",
"tickets": [
{
"type": "normal",
"expiration": "2026-10-25T02:02:36.677040"
}
]
},
"265268782455324692": {
"email": "hansthelarson@gmail.com",
"tickets": [
{
"type": "normal",
"expiration": "2026-10-28T00:46:43.282249"
}
]
},
"171471851590123520": {
"email": "cartmachine@gmail.com",
"tickets": [
{
"type": "normal",
"expiration": "2026-10-29T08:30:40.170348"
}
]
},
"928442689874165771": {
"email": "Limdul3000@gmail.com",
"tickets": [
{
"type": "normal",
"expiration": "2027-02-21T22:17:34.693537"
}
]
}
}