115 lines
3.2 KiB
Python
115 lines
3.2 KiB
Python
import datetime
|
|
import select
|
|
import threading
|
|
|
|
import channel
|
|
|
|
commchan = None
|
|
commchan_lock = threading.Lock()
|
|
|
|
class Clock(threading.Thread):
|
|
def __init__(self, irc, commchan):
|
|
self.irc = irc
|
|
self.commchan = commchan
|
|
threading.Thread.__init__(self)
|
|
|
|
def send_time(self, hour, half_past):
|
|
# Convert to 12h clock
|
|
hour = hour % 12
|
|
# Deal with the fact that unicode has 1…12
|
|
if hour == 0: hour = 12
|
|
clockface = chr(0x1F550 - 1 + hour + (12 if half_past else 0))
|
|
|
|
for chan in self.irc.get_channels():
|
|
self.irc.bot_response(chan, clockface)
|
|
|
|
def run(self):
|
|
poll = select.poll()
|
|
poll.register(self.commchan, select.POLLIN)
|
|
|
|
last_hour = None
|
|
last_half_past = None
|
|
|
|
quit = False
|
|
while not quit:
|
|
now = datetime.datetime.now()
|
|
half_past = now.minute >= 30
|
|
|
|
if last_hour != now.hour or last_half_past != half_past:
|
|
self.send_time(now.hour, half_past)
|
|
last_hour = now.hour
|
|
last_half_past = half_past
|
|
|
|
# Set poll timeout to when we next need to wake up
|
|
timeout = ((30 - now.minute % 30) * 60 - now.second) * 1000 - now.microsecond // 1000
|
|
|
|
for fd, event in poll.poll(timeout):
|
|
if fd == self.commchan.fileno():
|
|
comm = self.commchan.recv()
|
|
if comm == 'quit':
|
|
quit = True
|
|
|
|
self.commchan.close()
|
|
|
|
def stop_clock():
|
|
global commchan, commchan_lock
|
|
with commchan_lock:
|
|
if commchan is None:
|
|
return
|
|
else:
|
|
commchan.send('quit')
|
|
commchan = None
|
|
|
|
def start_clock(irc):
|
|
global commchan, commchan_lock
|
|
with commchan_lock:
|
|
if commchan is not None:
|
|
return
|
|
else:
|
|
commchan = channel.Channel()
|
|
Clock(irc, commchan).start()
|
|
|
|
# initialize(*, config)
|
|
# Called to initialize the IRC bot
|
|
# Runs before even logger is brought up, and blocks further bringup until it's done
|
|
# config is a configpatser.ConfigParser object containig contents of bot.conf
|
|
def initialize(*, config):
|
|
...
|
|
|
|
# on_connect(*, irc)
|
|
# Called after IRC bot has connected and sent the USER/NICk commands but not yet attempted anything else
|
|
# Called for every reconnect
|
|
# Blocks the bot until it's done, including PING/PONG handling
|
|
# irc is the IRC API object
|
|
def on_connect(*, irc):
|
|
stop_clock()
|
|
start_clock(irc)
|
|
|
|
# on_quit(*, irc)
|
|
# Called just before IRC bot sends QUIT
|
|
# Blocks the bot until it's done, including PING/PONG handling
|
|
# irc is the IRC API object
|
|
def on_quit(*, irc):
|
|
stop_clock()
|
|
|
|
# handle_message(*, prefix, message, nick, channel, irc)
|
|
# Called for PRIVMSGs.
|
|
# prefix is the prefix at the start of the message, without the leading ':'
|
|
# message is the contents of the message
|
|
# nick is who sent the message
|
|
# channel is where you should send the response (note: in queries nick == channel)
|
|
# irc is the IRC API object
|
|
# All strings are bytestrings
|
|
def handle_message(*, prefix, message, nick, channel, irc):
|
|
...
|
|
|
|
# handle_nonmessage(*, prefix, command, arguments, irc)
|
|
# Called for all other commands than PINGs and PRIVMSGs.
|
|
# prefix is the prefix at the start of the message, without the leading ':'
|
|
# command is the command or number code
|
|
# arguments is rest of the arguments of the command, represented as a list. ':'-arguments are handled automatically
|
|
# irc is the IRC API object
|
|
# All strings are bytestrings
|
|
def handle_nonmessage(*, prefix, command, arguments, irc):
|
|
...
|