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!")
因此,機器人不會弄亂函數的參數,而是分別向用戶詢問提醒和時間。
添加回答
舉報