因此,我正在尝试使用discord.py创建提醒功能。这是我的代码:
@client.command(name = "reminder", brief = "I'll send a message to the future.",
description = "State what I have to remind you, as well as when and in which channel and I'll do it! "
"Write d for days, h for hours, m for minutes and s for seconds after the number and then "
"what you want to be remided of. For example: >reminder 1h 30m eat chocolate",
aliases = ["remind", "remindme", "remindto"])
async def reminder(ctx, time, *, reminder):
user = ctx.message.author
seconds = 0
if reminder is None:
ctx.send("Please, tell me what you want me to remind you about!")
if time.lower().endswith("d"):
seconds += float(time[:-1]) * 60 * 60 * 24
counter = f"{seconds // 60 // 60 // 24} days"
if time.lower().endswith("h"):
seconds += float(time[:-1]) * 60 * 60
counter = f"{seconds // 60 // 60} hours"
if time.lower().endswith("m"):
seconds += float(time[:-1]) * 60
counter = f"{seconds // 60} minutes"
if time.lower().endswith("s"):
seconds += float(time[:-1])
counter = f"{seconds} seconds"
if seconds == 0:
await ctx.send("You can't tell me that!")
else:
await ctx.send(f"Alright, I will remind you about {reminder} in {counter}.")
await asyncio.sleep(seconds)
await ctx.send(f"Hi, <@{user.id}>, you asked me to remind you about {reminder} {counter} ago.")
return
我的问题是,当有人为“时间”写多个参数时,我不知道如何使它工作。因此,例如,如果我调用函数>reminder 1h 30min eat chocolate
,它将在1小时内提醒我“ 30分钟吃巧克力”,而不是在1小时30分钟内提醒我。我不知道是否有办法解决此问题(除了编写1.5h)。任何输入都是有用的。非常感谢!
答案 0 :(得分:0)
您的用户输入的消息被“某处”拆分为参数,然后调用您发布的异步方法。用户输入的“拆分”操作不是在显示的代码中完成。
如果您要处理'1d 3hours 52sec Check StackOverflow for answers.'
作为用户输入,则需要更改此消息的split
方式 在呼叫{{1}之前}和分割参数。
您需要对其进行更改,以便以async def reminder(ctx, time, *, reminder)
的形式提供time
,以'1d 3hours 52sec'
的形式提供reminder
:
'Check StackOverflow for answers.'
如果您无法更改此拆分行为,请在用户使用的消息的时间范围内禁止空格:
您的用户文本当前似乎在空格处分隔,第一个文本提供给# correctly proivided params
reminder(ctx, "1d 3hours 52sec", *, reminder="Check StackOverflow for answers")
,其余部分作为time
消息提供。
如果您禁止在时间分量内部使用空格,则可以更改方法以正确解析reminder
之类的输入的时间。
这可能是处理上述消息的方法的-non async-实现:
一些辅助方法和导入:
'1d3hours52sec Check StackOverflow for answers.'
方法上下文对象的模拟:
imort time
def format_seconds(secs):
# mildly adapted from source: https://stackoverflow.com/a/13756038/7505395
# by Adam Jacob Muller
"""Accepts an integer of seconds and returns a minimal string formatted into
'a years, b months, c days, d hours, e minutes, f seconds' as needed."""
periods = [
('year', 60*60*24*365),
('month', 60*60*24*30),
('day', 60*60*24),
('hour', 60*60),
('minute', 60),
('second', 1)
]
strings=[]
for period_name, period_seconds in periods:
if secs > period_seconds:
period_value , secs = divmod(secs, period_seconds)
has_s = 's' if period_value > 1 else ''
strings.append("%s %s%s" % (period_value, period_name, has_s))
return ", ".join(strings)
def convert_timestring_to_seconds(time):
"""Convert a math expression to integer,only allows [0..9+* ] as chars."""
if not all(c in "1234567890+* " for c in time):
raise Exception()
# this are seconds - using eval as we can be sure nothing harmful can be in it
# if you are paranoid, use https://stackoverflow.com/a/33030616/7505395 instead
count = eval(time)
if type(count) != int:
raise Exception()
return count
和更改后的方法(出于minimal reproducible example的目的而进行了异步和模拟):
class MockContext:
def __init__(self):
class User:
def __init__(self):
self.id = "mee-id"
def __str__(self):
return "mee"
class Message:
def __init__(self):
self.author = User()
self.message = Message()
self.send = print
可以这样调用:
def reminder(ctx, time, *, reminder):
user = ctx.message.author
if not time:
ctx.send("Please, tell me WHEN you want me to remind you!")
return
elif not reminder:
ctx.send("Please, tell me WHAT you want me to remind you about!")
return
# order and 3.7+ is important - (else use the sorting one down below)
replacer = {"days":24*60*60, "hours":60*60, "minutes":60, "min":60,
"seconds":1, "sec":1, "d":24*60*60, "h":60, "m":60, "s":1}
safe_time = time # for error output we remember the original input for time
for unit in replacer: # or sorted(replacer, key=len, reverse=True) below 3.8
time = time.replace(unit, f"*{replacer[unit]}+")
time = time.rstrip("+")
try:
count = convert_timestring_to_seconds(time)
except Exception as ex:
ctx.send(f"Unable to understand the time of '{safe_time}'!", ex)
return
if count == 0:
ctx.send("You can't tell me that!")
else:
counter = format_seconds(count)
ctx.send(f"Alright, I will remind you about '{reminder}' in '{counter}'.")
import time
time.sleep(2)
ctx.send(f"Hi, <@{user.id}>, you asked me to remind you about '{reminder}' some '{counter}' ago.")
并产生以下输出:
context_mock = MockContext()
reminder(context_mock, "1d5min270seconds", reminder = "abouth this")
reminder(context_mock, "1d5min270seconds", reminder = "")
reminder(context_mock, "", reminder = "")
reminder(context_mock, "buffalo", reminder = "abouth this")
答案 1 :(得分:0)
这就是我最终解决此问题的方式:
async def reminder(ctx):
user = ctx.message.author
def check(msg):
return msg.author == ctx.author and msg.channel == ctx.channel
#and type(msg.content) == int
await ctx.send("Oh my! Yes, tell me, what do you need to remember?")
reminder = await client.wait_for("message", check=check)
await ctx.send("Okay! When do you want me to remind you that? (d for days, h for hours, m for minutes, s for seconds)")
Time = await client.wait_for("message", check=check)
times = str(Time.content)
Times = times.split()
seconds = 0
for time in Times:
if time.lower().endswith("d"):
seconds += float(time[:-1]) * 60 * 60 * 24
counter = f"{seconds // 60 // 60 // 24} days"
if time.lower().endswith("h"):
seconds += float(time[:-1]) * 60 * 60
counter = f"{seconds // 60 // 60} hours"
if time.lower().endswith("m"):
seconds += float(time[:-1]) * 60
counter = f"{seconds // 60} minutes"
if time.lower().endswith("s"):
seconds += float(time[:-1])
counter = f"{seconds} seconds"
if seconds == 0:
await ctx.send("You can't tell me that!")
else:
await ctx.send(f"Alright, I will remind you about {reminder.content} in {times}.")
await asyncio.sleep(seconds)
await ctx.send(f"Hi, <@{user.id}>, you asked me to remind you about {reminder.content} some time ago. "
f"Don't forget about it!")
因此,僵尸程序不会混乱函数的参数,而是会分别询问用户提示和时间。