Home > OS >  checking when a command was last used
checking when a command was last used

Time:06-18

I have a discord bot which has a command that requires a cooldown of a week. I considered using something like @commands.cooldown, but the issue is that if the bot goes offline, that cooldown resets itself. So, a member could simply watch for when the bot goes down and try to exploit it after it returns.

Since I can't keep the bot running 24x7x365, the solution I came up with was to record the date a user last used the command in a database, and when they use the command next, to check if seven days have passed.

For example's sake, this is what the command would look like:

@bot.command()
async def datetest(ctx,date):
  today = datetime.date.today()
  print(today)
  someday = datetime.date.strptime(date,"%y-%m-%d")
  diff = someday - today
  await ctx.send(diff   "days.")

In this example, I'm using "date" as a parameter to just test if the command returns the difference of days.

(in the actual command, rather than take a date argument, it'll get a date stored in the DB)

However, the issue I'm facing is that:

someday = datetime.date.strptime(date,"%y-%m-%d")

doesn't run. What am I doing wrong here?

CodePudding user response:

1: To format a date it's strftime 'f' for 'format' not strptime, 'parse'. strptime is used to turn a string object into a datetime object.

2: If you are working with the object you don't need to also pass that object to the methods of that class. i.e. you don't need to pass date to the object method 'strftime'

This is because, as with all object methods, it's done internally using the implicit 'self' parameter.

3: To get the actual date object you need to call a method of the datetime class which produces that. e.g. datetime.now()

Your code line should simply read something like:

import datetime.datetime as datetime
# or from datetime import datetime
someday = datetime.now().date().strftime("%y-%m-%d")

or

import datetime
someday = datetime.datetime.now().date().strftime("%y-%m-%d")

(Reading your post not sure what your intent is, so adding this for completeness)

Going the other way, getting a value from your database and using that to generate a datetime. I don't know what database interface you are using so this is a general answer, as for many Python DB interfaces this is not necessary as the date field select() call will return a type for that field that is a datetime object.

# Paraphrasing a DB interface
dt_col = db.select("select max(date) from lastrun_dates;").execute()
# returns ["2022-10-3",]

date = datetime.datetime.strptime(dt_col[0], "%Y-m-%d")
# note the uppercase 'Y' for a 4 digit date

However, don't do this!

I don't recommend saving dates/times in a DB (or anywhere else for that matter) as a string as it has a DB schema, geographical, localle and daylight saving interpretation, which results in many ways of creating future issues. Instead it is recommended to use the UTC datetime from the epoch as an integer or float.

datetime.datetime.utcnow().timestamp()
# or
datetime.datetime.utcnow().toordinal()

CodePudding user response:

Ok, so I figured out the issue after digging deeper into how datetime subtractions work.

One is that I needed to use someday = datetime.datetime.strptime().

Two is that I needed to use %Y instead of %y to match the time format passed into the date parameter (yyyy-mm-dd). Console pointed this out after a few tests.

Third is that I needed to extract the number of days out of the timedelta answer, because in the end, I'm trying to see how many days passed from the time the command was last used.

So, the new code looks like:

  someday = datetime.datetime.strptime(date, "%Y-%m-%d")
  diff = someday - today
  print(diff.days)
  • Related