猿问

提醒功能:如何使其接受多个时间参数值?

所以,我尝试使用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)。任何输入都会有用。多谢!


繁星淼淼
浏览 93回答 2
2回答

白板的微信

您的用户输入的消息在“某处”被分割成参数,然后调用您发布的异步方法。您显示的代码中未完成用户输入的“拆分” 。如果您想'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 paramsreminder(ctx, "1d 3hours 52sec", *, reminder="Check StackOverflow for answers")如果您无法更改此拆分行为,请禁止用户使用的消息的时间部分内存在空格:看来您的用户文本当前是按空格分割的,第一个文本是提供的time,其余的文本是reminder消息。如果您禁止时间组件内的空格,您可以更改方法以正确解析诸如 之类的输入的时间'1d3hours52sec Check StackOverflow for answers.'。这可能是处理上述消息的方法的非异步实现:一些辅助方法和导入:imort time&nbsp;def format_seconds(secs):&nbsp; &nbsp; # mildly adapted from source: https://stackoverflow.com/a/13756038/7505395&nbsp;&nbsp; &nbsp; # by Adam Jacob Muller&nbsp; &nbsp; """Accepts an integer of seconds and returns a minimal string formatted into&nbsp; &nbsp; 'a years, b months, c days, d hours, e minutes, f seconds' as needed."""&nbsp; &nbsp; periods = [&nbsp; &nbsp; &nbsp; &nbsp; ('year',&nbsp; &nbsp; &nbsp; &nbsp; 60*60*24*365),&nbsp; &nbsp; &nbsp; &nbsp; ('month',&nbsp; &nbsp; &nbsp; &nbsp;60*60*24*30),&nbsp; &nbsp; &nbsp; &nbsp; ('day',&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;60*60*24),&nbsp; &nbsp; &nbsp; &nbsp; ('hour',&nbsp; &nbsp; &nbsp; &nbsp; 60*60),&nbsp; &nbsp; &nbsp; &nbsp; ('minute',&nbsp; &nbsp; &nbsp; 60),&nbsp; &nbsp; &nbsp; &nbsp; ('second',&nbsp; &nbsp; &nbsp; 1)&nbsp; &nbsp; ]&nbsp; &nbsp; strings=[]&nbsp; &nbsp; for period_name, period_seconds in periods:&nbsp; &nbsp; &nbsp; &nbsp; if secs > period_seconds:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; period_value , secs = divmod(secs, period_seconds)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; has_s = 's' if period_value > 1 else ''&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; strings.append("%s %s%s" % (period_value, period_name, has_s))&nbsp; &nbsp; return ", ".join(strings)def convert_timestring_to_seconds(time):&nbsp; &nbsp; """Convert a math expression to integer,only allows [0..9+* ] as chars."""&nbsp; &nbsp; if not all(c in "1234567890+* " for c in time):&nbsp; &nbsp; &nbsp; &nbsp; raise Exception()&nbsp; &nbsp; # this are seconds - using eval as we can be sure nothing harmful can be in it&nbsp; &nbsp; # if you are paranoid, use https://stackoverflow.com/a/33030616/7505395 instead&nbsp; &nbsp; count = eval(time)&nbsp; &nbsp; if type(count) != int:&nbsp; &nbsp; &nbsp; &nbsp; raise Exception()&nbsp; &nbsp; return count方法上下文对象的模拟:class MockContext:&nbsp; &nbsp; def __init__(self):&nbsp; &nbsp; &nbsp; &nbsp; class User:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; def __init__(self):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.id = "mee-id"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; def __str__(self):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return "mee"&nbsp; &nbsp; &nbsp; &nbsp; class Message:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; def __init__(self):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.author = User()&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; self.message = Message()&nbsp; &nbsp; &nbsp; &nbsp; self.send = print&nbsp;以及您更改后的方法(非异步和模拟以实现最小的可重现示例目的):def reminder(ctx, time, *, reminder):&nbsp; &nbsp; user = ctx.message.author&nbsp; &nbsp; if not time:&nbsp; &nbsp; &nbsp; &nbsp; ctx.send("Please, tell me WHEN you want me to remind you!")&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; elif not reminder:&nbsp; &nbsp; &nbsp; &nbsp; ctx.send("Please, tell me WHAT you want me to remind you about!")&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; # order and 3.7+ is important - (else use the sorting one down below)&nbsp; &nbsp; replacer = {"days":24*60*60, "hours":60*60, "minutes":60, "min":60,&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "seconds":1, "sec":1, "d":24*60*60, "h":60, "m":60, "s":1}&nbsp; &nbsp; safe_time = time # for error output we remember the original input for time&nbsp; &nbsp; for unit in replacer: # or sorted(replacer, key=len, reverse=True) below 3.8&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; time = time.replace(unit, f"*{replacer[unit]}+")&nbsp; &nbsp; time = time.rstrip("+")&nbsp; &nbsp; try:&nbsp; &nbsp; &nbsp; &nbsp; count = convert_timestring_to_seconds(time)&nbsp; &nbsp; except Exception as ex:&nbsp; &nbsp; &nbsp; &nbsp; ctx.send(f"Unable to understand the time of '{safe_time}'!", ex)&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; if count == 0:&nbsp; &nbsp; &nbsp; &nbsp; ctx.send("You can't tell me that!")&nbsp;&nbsp; &nbsp; else:&nbsp; &nbsp; &nbsp; &nbsp; counter = format_seconds(count)&nbsp; &nbsp; &nbsp; &nbsp; ctx.send(f"Alright, I will remind you about '{reminder}' in '{counter}'.")&nbsp; &nbsp; &nbsp; &nbsp; import time&nbsp; &nbsp; &nbsp; &nbsp; time.sleep(2)&nbsp; &nbsp; &nbsp; &nbsp; ctx.send(f"Hi, <@{user.id}>, you asked me to remind you about '{reminder}' some '{counter}' ago.")这可以像这样调用:context_mock = MockContext()&nbsp;reminder(context_mock, "1d5min270seconds", reminder = "abouth this")&nbsp;reminder(context_mock, "1d5min270seconds", reminder = "")reminder(context_mock, "", reminder = "")reminder(context_mock, "buffalo", reminder = "abouth this")&nbsp;并产生以下输出:# reminder(context_mock, "1d5min270seconds", reminder = "abouth this")&nbsp;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'!&nbsp;

慕村225694

这就是我最终解决问题的方法:async def reminder(ctx):&nbsp; &nbsp; user = ctx.message.author&nbsp; &nbsp; def check(msg):&nbsp; &nbsp; &nbsp; &nbsp; return msg.author == ctx.author and msg.channel == ctx.channel&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;#and type(msg.content) == int&nbsp; &nbsp; await ctx.send("Oh my! Yes, tell me, what do you need to remember?")&nbsp; &nbsp; reminder = await client.wait_for("message", check=check)&nbsp; &nbsp; 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)")&nbsp; &nbsp; Time = await client.wait_for("message", check=check)&nbsp; &nbsp; times = str(Time.content)&nbsp; &nbsp; Times = times.split()&nbsp; &nbsp; seconds = 0&nbsp; &nbsp; for time in Times:&nbsp; &nbsp; &nbsp; &nbsp; if time.lower().endswith("d"):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; seconds += float(time[:-1]) * 60 * 60 * 24&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; counter = f"{seconds // 60 // 60 // 24} days"&nbsp; &nbsp; &nbsp; &nbsp; if time.lower().endswith("h"):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; seconds += float(time[:-1]) * 60 * 60&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; counter = f"{seconds // 60 // 60} hours"&nbsp; &nbsp; &nbsp; &nbsp; if time.lower().endswith("m"):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; seconds += float(time[:-1]) * 60&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; counter = f"{seconds // 60} minutes"&nbsp; &nbsp; &nbsp; &nbsp; if time.lower().endswith("s"):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; seconds += float(time[:-1])&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; counter = f"{seconds} seconds"&nbsp; &nbsp; &nbsp; &nbsp; if seconds == 0:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; await ctx.send("You can't tell me that!")&nbsp; &nbsp; else:&nbsp; &nbsp; &nbsp; &nbsp; await ctx.send(f"Alright, I will remind you about {reminder.content} in {times}.")&nbsp; &nbsp; &nbsp; &nbsp; await asyncio.sleep(seconds)&nbsp; &nbsp; &nbsp; &nbsp; await ctx.send(f"Hi, <@{user.id}>, you asked me to remind you about {reminder.content} some time ago. "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;f"Don't forget about it!")因此,机器人不会弄乱函数的参数,而是分别向用户询问提醒和时间。
随时随地看视频慕课网APP

相关分类

Python
我要回答