103 lines
3.2 KiB
Python
103 lines
3.2 KiB
Python
import random
|
|
from datetime import datetime, timedelta
|
|
|
|
from edmond.plugin import Plugin
|
|
from edmond.utils import proc
|
|
|
|
|
|
class SleepPlugin(Plugin):
|
|
"""Handle sleep state of the bot, snore a little bit."""
|
|
|
|
REQUIRED_CONFIGS = [
|
|
"commands", "sleep_time", "wakeup_time", "snore", "sleep_messages",
|
|
"wakeup_messages", "snore_rate"
|
|
]
|
|
|
|
def __init__(self, bot):
|
|
super().__init__(bot)
|
|
|
|
def on_welcome(self, event):
|
|
self.set_runtime_value("awake", True)
|
|
|
|
def on_ping(self, event):
|
|
awake = self.get_runtime_value("awake")
|
|
in_sleep_hours = self.is_sleep_time(datetime.now())
|
|
if awake and in_sleep_hours:
|
|
self.fall_asleep()
|
|
elif not awake:
|
|
if not in_sleep_hours:
|
|
self.wake_up()
|
|
else:
|
|
# Maybe snore.
|
|
if proc(self.config["snore_rate"]):
|
|
for channel in self.bot.channels:
|
|
self.bot.say(channel, self.config["snore"])
|
|
|
|
def on_pubmsg(self, event):
|
|
if not self.should_handle_command(
|
|
event.arguments[0],
|
|
no_content=True,
|
|
exclude_conditions=["sleep"],
|
|
):
|
|
return False
|
|
|
|
# "sleep" command.
|
|
if self.command.ident == self.config["commands"][0]:
|
|
self.fall_asleep()
|
|
return True
|
|
|
|
# "wake up" command.
|
|
if self.command.ident == self.config["commands"][1]:
|
|
self.wake_up()
|
|
return True
|
|
|
|
return False
|
|
|
|
def fall_asleep(self):
|
|
if not self.get_runtime_value("awake"):
|
|
return
|
|
for channel in self.bot.channels:
|
|
self.bot.say(channel, random.choice(self.config["sleep_messages"]))
|
|
self.set_runtime_value("awake", False)
|
|
|
|
def wake_up(self):
|
|
if self.get_runtime_value("awake"):
|
|
return
|
|
self.set_runtime_value("awake", True)
|
|
for channel in self.bot.channels:
|
|
self.bot.say(channel, random.choice(self.config["wakeup_messages"]))
|
|
|
|
def is_sleep_time(self, now):
|
|
"""Return True if the bot should be sleeping by now.
|
|
|
|
The sleep range can span over 2 days (e.g. 23 to 7) or be contained in a
|
|
day (e.g. 0 to 8).
|
|
"""
|
|
sleep_time = self.config["sleep_time"]
|
|
wakeup_time = self.config["wakeup_time"]
|
|
current_hour = now.hour
|
|
# If we're before the sleep hour, check that we are not in the
|
|
# previous sleep range. Else just check today's range.
|
|
if current_hour < sleep_time:
|
|
ref_dt = now - timedelta(days=1)
|
|
else:
|
|
ref_dt = now
|
|
sleep_dt, wakeup_dt = self._get_sleep_range(
|
|
ref_dt,
|
|
sleep_time,
|
|
wakeup_time
|
|
)
|
|
return sleep_dt <= now < wakeup_dt
|
|
|
|
@staticmethod
|
|
def _get_sleep_range(now, sleep_time, wakeup_time):
|
|
"""Return the (start, end) datetime tuple using config values.
|
|
|
|
Properly accounts for a sleep range going around midnight.
|
|
"""
|
|
sleep_dt = now.replace(hour=sleep_time, minute=0, second=0)
|
|
wakeup_dt = now.replace(hour=wakeup_time, minute=0, second=0)
|
|
if wakeup_time < sleep_time:
|
|
wakeup_dt += timedelta(days=1)
|
|
return sleep_dt, wakeup_dt
|