问题
I'm making a Twitch Bot using Pthon. I want to create a cooldown on the commands so you can only call the command once every (x) seconds. Eg:
Rustie: test
Bot: Testing command
*Imediately after*
Rustie: test
*5 seconds later*
Rustie: test
Bot: Testing command
I have tried this code but it doesn't work (Also I want to get rid of time.sleep as during that time I can't use other commands):
used = []
if "test" in message:
if "test" in used:
time.sleep(5)
del(used[:])
else:
sendMessage(s, "Testing command")
used.append("test")
break
回答1:
My advice would be to restructure your code to use modular MessageHandler
classes that can each handle a particular type of message (i.e. have a single responsibility), with the bot's overall behaviour being determined by the type and order of these message handlers within a chain of responsibility:
Among several other benefits, this makes it easy to implement cooldowns between command invocations (in the implementation below, you can customise different duration cooldowns for different types of message).
from abc import ABC, abstractmethod
from datetime import datetime, timedelta
from time import sleep
class MessageHandler(ABC):
def __init__(self, command_cooldown):
self._command_cooldown = command_cooldown
self._last_command_usage = datetime.min
def try_handle_message(self, message):
if self._can_handle_message(message) and not self.__on_cooldown:
self._last_command_usage = datetime.now()
return self._handle_message(message)
else:
return None
@property
def __on_cooldown(self):
return datetime.now() - self._last_command_usage <= self._command_cooldown
@abstractmethod
def _can_handle_message(self, s):
pass
@abstractmethod
def _handle_message(self, s):
pass
class TestMessageHandler(MessageHandler):
def __init__(self):
super().__init__(timedelta(seconds=5))
def _can_handle_message(self, s):
return 'test' in s
def _handle_message(self, s):
return 'Testing command'
class Bot(object):
def __init__(self):
self._message_handlers = [TestMessageHandler()]
def receive_message(self, message):
print('Received:', message)
for message_handler in self._message_handlers:
response = message_handler.try_handle_message(message)
if response:
self.send_response(response)
def send_response(self, response):
print('Responding:', response)
if __name__ == '__main__':
bot = Bot()
bot.receive_message('test')
for i in range(6):
bot.receive_message('test')
print('Sleep 1 second...')
sleep(1)
Output
Received: test
Responding: Testing command
Received: test
Sleep 1 second...
Received: test
Sleep 1 second...
Received: test
Sleep 1 second...
Received: test
Sleep 1 second...
Received: test
Sleep 1 second...
Received: test
Responding: Testing command
Sleep 1 second...
回答2:
You need to keep track of the time passed since the last invocation of each command. You can do it with the time
module.
import time
min_call_freq = 5
used = {}
def call_command(command):
print('Calling command `%s`.' % command)
# do whatever
def cooldown(command):
print('You have used command `%s` in the last %u seconds.' % (command, min_call_freq))
def process_command(command):
if (
command not in used or
time.time() - used[command] > min_call_freq
):
used[command] = time.time()
call_command(command)
else:
cooldown(command)
来源:https://stackoverflow.com/questions/41902252/command-cooldown-for-a-python-twitch-bot