2 回答
TA贡献1883条经验 获得超3个赞
您的用户输入的消息在“某处”被分割成参数,然后调用您发布的异步方法。您显示的代码中未完成用户输入的“拆分” 。
如果您想'1d 3hours 52sec Check StackOverflow for answers.'作为用户输入进行处理,则需要在使用拆分参数调用之前更改此消息的方式。split 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消息。
如果您禁止时间组件内的空格,您可以更改方法以正确解析诸如 之类的输入的时间'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
方法上下文对象的模拟:
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")
并产生以下输出:
# reminder(context_mock, "1d5min270seconds", reminder = "abouth this")
Alright, I will remind you about 'abouth this' in '1 day, 9 minutes, 30 seconds'.
<2s delay>
Hi, <@mee-id>, you asked me to remind you about 'abouth this' some '1 day, 9 minutes, 30 seconds' ago.
# reminder(context_mock, "1d5min270seconds", reminder = "")
Please, tell me WHAT you want me to remind you about!
# reminder(context_mock, "", reminder = "")
Please, tell me WHEN you want me to remind you!
# reminder(context_mock, "buffalo", reminder = "abouth this")
Unable to understand the time of 'buffalo'!
TA贡献1880条经验 获得超4个赞
这就是我最终解决问题的方法:
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!")
因此,机器人不会弄乱函数的参数,而是分别向用户询问提醒和时间。
添加回答
举报