How to save command cooldown?
How to save command cooldown?
The code below adds a cooldown for command, but when bot restarts, the cooldown resets. So how can I make the bot remember from previous usage? If the cooldown limit is 5 times per day and if the member used 3 times and if bot restarts it should start from where it was left for all members.
token = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
prefix = "?"
import discord
from discord.ext import commands
import pickle, os
bot = commands.Bot(command_prefix=prefix)
@bot.event
async def on_ready():
print('Logged in as')
print(bot.user.name)
print(bot.user.id)
print('------')
cooldown_info_path = "cd.pkl" # the file to store the data
if os.path.exists(cooldown_info_path): # on the initial run where "cd.pkl" file hadn't been created yet
with open(cooldown_info_path, 'rb') as f:
d = pickle.load(f)
for name, func in bot.commands.items():
if name in d: # if the Command name has a CooldownMapping stored in file, override _bucket
bot.commands[name]._buckets = d[name]
class Bot(commands.Bot):
def run(self, *args, cooldown_info_path="cd.pkl", **kwargs):
import os, pickle
if os.path.exists(cooldown_info_path): # on the initial run where "cd.pkl" file hadn't been created yet
with open(cooldown_info_path, 'rb') as f:
d = pickle.load(f)
for name, func in self.commands.items():
if name in d: # if the Command name has a CooldownMapping stored in file, override _bucket
self.commands[name]._buckets = d[name]
super().run(*args, **kwargs)
with open(cooldown_info_path, 'wb') as f:
# dumps a dict of command name to CooldownMapping mapping
pickle.dump({name: func._buckets for name, func in self.commands.items()}, f)
bot = Bot(...)
# everything else as usual
@bot.command(pass_context=True)
@commands.cooldown(1, 3600, commands.BucketType.user)
async def hello(ctx):
msg = "Hello... {0.author.mention}".format(ctx.message)
await bot.say(msg)
bot.run(token)
with open(cooldown_info_path, 'wb') as f:
# dumps a dict of command name to CooldownMapping mapping
pickle.dump({name: func._buckets for name, func in bot.commands.items()}, f)
ping._buckets
ping._buckets
on_ready
pickle
core.py
cooldowns.py
1 Answer
1
Similar to what Patrick Haugh suggested, the cooldown mapping is stored in Command._buckets
. You can pickle the bucket before the bot starts and save it after the bot finishes.
Command._buckets
Add the following before and after bot.run(...)
.
bot.run(...)
import pickle, os
cooldown_info_path = "cd.pkl" # the file to store the data
if os.path.exists(cooldown_info_path): # on the initial run where "cd.pkl" file hadn't been created yet
with open(cooldown_info_path, 'rb') as f:
d = pickle.load(f)
for name, func in bot.commands.items():
if name in d: # if the Command name has a CooldownMapping stored in file, override _bucket
bot.commands[name]._buckets = d[name]
bot.run('TOKEN')
with open(cooldown_info_path, 'wb') as f:
# dumps a dict of command name to CooldownMapping mapping
pickle.dump({name: func._buckets for name, func in bot.commands.items()}, f)
Alternatively, you can place the aforementioned code in the method run(...)
of a subclass of Bot
. Doing so makes a seemingly transparent addition of an additional functionality:
run(...)
Bot
class Bot(commands.Bot):
def run(self, *args, cooldown_info_path="cd.pkl", **kwargs):
import os, pickle
if os.path.exists(cooldown_info_path): # on the initial run where "cd.pkl" file hadn't been created yet
with open(cooldown_info_path, 'rb') as f:
d = pickle.load(f)
for name, func in self.commands.items():
if name in d: # if the Command name has a CooldownMapping stored in file, override _bucket
self.commands[name]._buckets = d[name]
super().run(*args, **kwargs)
with open(cooldown_info_path, 'wb') as f:
# dumps a dict of command name to CooldownMapping mapping
pickle.dump({name: func._buckets for name, func in self.commands.items()}, f)
bot = Bot(...)
# everything else as usual
You hadn't mentioned which database you're using nor how you're connecting to the database so my answer addressed storing to a file.
In case you're still confused, this is how it should be set up:
token = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
prefix = "?"
from discord.ext import commands
class Bot(commands.Bot):
def run(self, *args, cooldown_info_path="cd.pkl", **kwargs):
import os, pickle
if os.path.exists(cooldown_info_path): # on the initial run where "cd.pkl" file hadn't been created yet
with open(cooldown_info_path, 'rb') as f:
d = pickle.load(f)
for name, func in self.commands.items():
if name in d: # if the Command name has a CooldownMapping stored in file, override _bucket
self.commands[name]._buckets = d[name]
try:
super().run(*args, **kwargs)
finally:
with open(cooldown_info_path, 'wb') as f:
# dumps a dict of command name to CooldownMapping mapping
pickle.dump({name: func._buckets for name, func in self.commands.items()}, f)
bot = Bot(prefix)
# everything else as usual
@bot.event
async def on_ready():
print('Logged in as')
print(bot.user.name)
print(bot.user.id)
print('------')
@bot.command(pass_context=True)
@commands.cooldown(1, 3600, commands.BucketType.user)
async def hello(ctx):
msg = "Hello... {0.author.mention}".format(ctx.message)
await bot.say(msg)
bot.run(token)
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
You'd have to save the state of
ping._buckets
, and then load that state back intoping._buckets
in youron_ready
event. I'd trypickle
ing the object first, and if that doesn't work you'll have to dig into the code to understand how it's put together. It looks like all the relevant code is split betweencore.py
andcooldowns.py
.– Patrick Haugh
Jun 30 at 23:13