From beafa34b547336deeb4cf930ca218943b3adf166 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juhani=20Krekel=C3=A4?= Date: Fri, 24 Apr 2020 03:26:16 +0300 Subject: [PATCH] Kellobotti --- README.md | 11 ++++--- bot.conf.example | 6 ++-- botcmd.py | 76 ++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 82 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index b83dcc5..226c10d 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,13 @@ o3-base ======= -This project seeks to replace o2-base as an easy python base to build IRC bots -on. It is not related to the failed oonbotti3 project, but is rather based on -the IRC bot framework of HynneFlip. +Posts a Unicode clock emoji corresponding to the current time twice an hour. Setup ===== -Copy `bot.conf.example` to `bot.conf` and run `python3 ircbot.py` to bring up -the bot skeleton, which can be used as a very quick and dirty IRC client. User -code goes in `botcmd.py`. +Copy `bot.conf.example` to `bot.conf` and run `python3 ircbot.py` to bring +up the bot. + +Edit `bot.conf` to configure the bot. License ------- diff --git a/bot.conf.example b/bot.conf.example index accc678..e52f31f 100644 --- a/bot.conf.example +++ b/bot.conf.example @@ -1,7 +1,7 @@ [server] host = irc.freenode.net port = 6667 -nick = o3-base -username = o3-base -realname = IRC bot based on o3-base +nick = kellobotti +username = kellobotti +realname = Tick tock channels = ##ingsoc diff --git a/botcmd.py b/botcmd.py index 217ab41..05102c7 100644 --- a/botcmd.py +++ b/botcmd.py @@ -1,3 +1,74 @@ +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 @@ -11,14 +82,15 @@ def initialize(*, config): # 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.