如何在discord.py中实现每个成员24小时固定、每日刷新的趣味IQ命令
Great question! Your current code works, but since it generates a new random IQ on every command call, it doesn't hold that value for 24 hours. We need to track each user's IQ alongside an expiration timestamp to keep it consistent for a full day, then regenerate it automatically. Let's break down the solution:
Core Idea
We'll store two pieces of info for each user:
- Their current IQ value
- A timestamp indicating when that IQ expires (24 hours after it was generated)
Every time the iq command is run, we'll check if the user has an unexpired IQ. If yes, we use that value; if not, we generate a new one and update the expiration time.
Basic Implementation (In-Memory Storage)
This version keeps data in the bot's memory (note: data resets if the bot restarts):
from datetime import datetime, timedelta import random import discord from discord.ext import commands client = commands.Bot(command_prefix='!', intents=discord.Intents.all()) # Store user IQ data: key = user ID (unique, even if username changes), value = (IQ, expiration datetime) user_iq_tracker = {} @client.command() async def iq(ctx): user_id = ctx.author.id now = datetime.now() # Check if user has a valid, unexpired IQ if user_id in user_iq_tracker: stored_iq, expire_time = user_iq_tracker[user_id] if now < expire_time: await ctx.send(f"IQ of {ctx.author.name} is {stored_iq} today") return # Generate new IQ and set expiration (24 hours from now) new_iq = random.randint(0, 200) new_expire = now + timedelta(hours=24) user_iq_tracker[user_id] = (new_iq, new_expire) await ctx.send(f"IQ of {ctx.author.name} is {new_iq} today")
Key Notes for This Version
- We use the user's ID instead of their username because usernames can change, but user IDs are permanent and unique across Discord.
timedelta(hours=24)calculates exactly when the IQ should expire.- The bot checks first for an existing valid entry before generating a new IQ.
Persistent Storage (Keep Data After Bot Restarts)
The in-memory version loses all data when the bot restarts. To fix this, we can save the data to a JSON file (simple and great for small bots):
from datetime import datetime, timedelta import random import json import discord from discord.ext import commands client = commands.Bot(command_prefix='!', intents=discord.Intents.all()) IQ_STORAGE_FILE = "user_iq_data.json" # Load saved IQ data from file def load_iq_data(): try: with open(IQ_STORAGE_FILE, "r") as f: data = json.load(f) # Convert stored string timestamps back to datetime objects for user_id in data: data[user_id]["expire_time"] = datetime.fromisoformat(data[user_id]["expire_time"]) return data except FileNotFoundError: # Return empty dict if file doesn't exist yet return {} # Save IQ data to file def save_iq_data(data): # Convert datetime objects to strings (JSON can't store datetime directly) saveable_data = {} for user_id, info in data.items(): saveable_data[user_id] = { "iq": info["iq"], "expire_time": info["expire_time"].isoformat() } with open(IQ_STORAGE_FILE, "w") as f: json.dump(saveable_data, f, indent=4) # Initialize the tracker with saved data user_iq_tracker = load_iq_data() @client.command() async def iq(ctx): user_id = str(ctx.author.id) # JSON requires string keys now = datetime.now() # Check for valid existing IQ if user_id in user_iq_tracker: stored_iq = user_iq_tracker[user_id]["iq"] expire_time = user_iq_tracker[user_id]["expire_time"] if now < expire_time: await ctx.send(f"IQ of {ctx.author.name} is {stored_iq} today") return # Generate new IQ and expiration new_iq = random.randint(0, 200) new_expire = now + timedelta(hours=24) user_iq_tracker[user_id] = { "iq": new_iq, "expire_time": new_expire } # Save immediately after updating save_iq_data(user_iq_tracker) await ctx.send(f"IQ of {ctx.author.name} is {new_iq} today")
Key Notes for Persistent Version
- We convert the user ID to a string because JSON doesn't support integer keys.
isoformat()andfromisoformat()handle converting between datetime objects and strings (since JSON can't store datetime objects natively).- The bot loads saved data on startup and saves updates every time a new IQ is generated.
Bonus: Clean Up Old Data
Over time, the JSON file might fill up with expired entries. You can add a function to clean these periodically (e.g., on bot startup):
def clean_expired_iq_data(data): now = datetime.now() # Keep only entries where expiration time is in the future cleaned_data = { user_id: info for user_id, info in data.items() if info["expire_time"] > now } return cleaned_data # Initialize tracker with cleaned data user_iq_tracker = clean_expired_iq_data(load_iq_data())
This removes any IQ entries that have already expired, keeping your storage efficient.
内容的提问来源于stack exchange,提问作者Raghuvanshi

