|
|
@@ -18,150 +18,165 @@ PICKLE_DB = "meetbot.pickle"
|
|
|
# TODO: while this is nice to support, it would perhaps be better to do it
|
|
|
# all over the same connection rather than opening a socket for each channel.
|
|
|
async def channel_listen(host, port, nick, chan):
|
|
|
- logging.info("%s: Connecting to %s:%s", chan, host, port)
|
|
|
- reader, writer = await asyncio.open_connection(host, port)
|
|
|
-
|
|
|
- logging.debug("%s: Send CAP msg", chan)
|
|
|
- msg = "CAP REQ : no-history\r\n"
|
|
|
- writer.write(msg.encode("utf-8"))
|
|
|
-
|
|
|
- logging.debug("%s: Send NICK msg", chan)
|
|
|
- msg = f"NICK {nick}\r\n"
|
|
|
- writer.write(msg.encode("utf-8"))
|
|
|
-
|
|
|
- logging.debug("%s: Send CAP END msg", chan)
|
|
|
- msg = "CAP END\r\n"
|
|
|
- writer.write(msg.encode("utf-8"))
|
|
|
-
|
|
|
- logging.debug("%s: Send JOIN msg", chan)
|
|
|
- msg = f"JOIN {chan}\r\n"
|
|
|
- writer.write(msg.encode("utf-8"))
|
|
|
-
|
|
|
- logging.info("%s: Listening to channel", chan)
|
|
|
- while True:
|
|
|
- msg = await reader.readline()
|
|
|
- msg = msg.decode("utf8")
|
|
|
- if not msg:
|
|
|
- continue
|
|
|
-
|
|
|
- split_msg = msg.split(" ")
|
|
|
- command = split_msg[1]
|
|
|
- nick = split_msg[0][1:].rsplit("!", 1)[0]
|
|
|
- logging.debug("%s: Recv: %s", chan, msg.rstrip())
|
|
|
-
|
|
|
- if command == "PRIVMSG":
|
|
|
- msg_title = msg.split(" ")[3][1:].rstrip()
|
|
|
- if not msg_title:
|
|
|
- logging.info("%s: Recv empty PRIVMSG, ignoring", chan)
|
|
|
+ try:
|
|
|
+ logging.info("%s: Connecting to %s:%s", chan, host, port)
|
|
|
+ reader, writer = await asyncio.open_connection(host, port)
|
|
|
+
|
|
|
+ logging.debug("%s: Send CAP msg", chan)
|
|
|
+ msg = "CAP REQ : no-history\r\n"
|
|
|
+ writer.write(msg.encode("utf-8"))
|
|
|
+
|
|
|
+ logging.debug("%s: Send NICK msg", chan)
|
|
|
+ msg = f"NICK {nick}\r\n"
|
|
|
+ writer.write(msg.encode("utf-8"))
|
|
|
+
|
|
|
+ logging.debug("%s: Send CAP END msg", chan)
|
|
|
+ msg = "CAP END\r\n"
|
|
|
+ writer.write(msg.encode("utf-8"))
|
|
|
+
|
|
|
+ logging.debug("%s: Send JOIN msg", chan)
|
|
|
+ msg = f"JOIN {chan}\r\n"
|
|
|
+ writer.write(msg.encode("utf-8"))
|
|
|
+
|
|
|
+ logging.info("%s: Listening to channel", chan)
|
|
|
+ while True:
|
|
|
+ msg = await reader.readline()
|
|
|
+ msg = msg.decode("utf8")
|
|
|
+ if not msg:
|
|
|
continue
|
|
|
|
|
|
- if msg_title == "!start":
|
|
|
- logging.info("%s: Got !start", chan)
|
|
|
- topics = CHANS[chan]["topics"]
|
|
|
- reply = f"PRIVMSG {chan} :Meeting started"
|
|
|
- logging.info("%s: Send: %s", chan, reply)
|
|
|
- writer.write((reply + "\r\n").encode("utf-8"))
|
|
|
- await writer.drain()
|
|
|
+ split_msg = msg.split(" ")
|
|
|
+ command = split_msg[1]
|
|
|
+ nick_c = split_msg[0][1:].rsplit("!", 1)[0]
|
|
|
+ logging.debug("%s: Recv: %s", chan, msg.rstrip())
|
|
|
+
|
|
|
+ if command == "PRIVMSG":
|
|
|
+ msg_title = msg.split(" ")[3][1:].rstrip()
|
|
|
+ if not msg_title:
|
|
|
+ logging.info("%s: Recv empty PRIVMSG, ignoring", chan)
|
|
|
+ continue
|
|
|
|
|
|
- if len(topics) == 0:
|
|
|
- reply = f"PRIVMSG {chan} :No topics"
|
|
|
+ if msg_title == "!start":
|
|
|
+ logging.info("%s: Got !start", chan)
|
|
|
+ topics = CHANS[chan]["topics"]
|
|
|
+ reply = f"PRIVMSG {chan} :Meeting started"
|
|
|
logging.info("%s: Send: %s", chan, reply)
|
|
|
writer.write((reply + "\r\n").encode("utf-8"))
|
|
|
await writer.drain()
|
|
|
- continue
|
|
|
|
|
|
- reply = f"PRIVMSG {chan} :Topics:"
|
|
|
- logging.info("%s: Send: %s", chan, reply)
|
|
|
- writer.write((reply + "\r\n").encode("utf-8"))
|
|
|
- await writer.drain()
|
|
|
+ if len(topics) == 0:
|
|
|
+ reply = f"PRIVMSG {chan} :No topics"
|
|
|
+ logging.info("%s: Send: %s", chan, reply)
|
|
|
+ writer.write((reply + "\r\n").encode("utf-8"))
|
|
|
+ await writer.drain()
|
|
|
+ continue
|
|
|
|
|
|
- for i, topic in enumerate(topics):
|
|
|
- reply = f"PRIVMSG {chan} :{i+1}. {topic}"
|
|
|
+ reply = f"PRIVMSG {chan} :Topics:"
|
|
|
logging.info("%s: Send: %s", chan, reply)
|
|
|
writer.write((reply + "\r\n").encode("utf-8"))
|
|
|
await writer.drain()
|
|
|
|
|
|
- cur_topic = topics.pop(0)
|
|
|
- reply = f"PRIVMSG {chan} :Current topic: {cur_topic}\r\n"
|
|
|
- CHANS[chan]["topics"] = topics
|
|
|
- writer.write(reply.encode("utf-8"))
|
|
|
- await writer.drain()
|
|
|
- continue
|
|
|
-
|
|
|
- if msg_title == "!end":
|
|
|
- logging.info("%s: Got !end", chan)
|
|
|
- reply = f"PRIVMSG {chan} :Meeting ended"
|
|
|
- logging.info("%s: Send: %s", chan, reply)
|
|
|
- writer.write((reply + "\r\n").encode("utf-8"))
|
|
|
- await writer.drain()
|
|
|
- continue
|
|
|
+ for i, topic in enumerate(topics):
|
|
|
+ reply = f"PRIVMSG {chan} :{i+1}. {topic}"
|
|
|
+ logging.info("%s: Send: %s", chan, reply)
|
|
|
+ writer.write((reply + "\r\n").encode("utf-8"))
|
|
|
+ await writer.drain()
|
|
|
|
|
|
- if msg_title == "!topic":
|
|
|
- logging.info("%s: Got !topic", chan)
|
|
|
- topic = msg.split(" ", 4)
|
|
|
+ cur_topic = topics.pop(0)
|
|
|
+ reply = f"PRIVMSG {chan} :Current topic: {cur_topic}\r\n"
|
|
|
+ CHANS[chan]["topics"] = topics
|
|
|
+ writer.write(reply.encode("utf-8"))
|
|
|
+ await writer.drain()
|
|
|
+ continue
|
|
|
|
|
|
- if len(topic) != 5:
|
|
|
- logging.debug("%s: Topic msg len not 5, skipping", chan)
|
|
|
+ if msg_title == "!end":
|
|
|
+ logging.info("%s: Got !end", chan)
|
|
|
+ reply = f"PRIVMSG {chan} :Meeting ended"
|
|
|
+ logging.info("%s: Send: %s", chan, reply)
|
|
|
+ writer.write((reply + "\r\n").encode("utf-8"))
|
|
|
+ await writer.drain()
|
|
|
continue
|
|
|
|
|
|
- topic = topic[4].rstrip() + f" (by {nick})"
|
|
|
+ if msg_title == "!topic":
|
|
|
+ logging.info("%s: Got !topic", chan)
|
|
|
+ topic = msg.split(" ", 4)
|
|
|
+
|
|
|
+ if len(topic) != 5:
|
|
|
+ logging.debug("%s: Topic msg len not 5, skipping",
|
|
|
+ chan)
|
|
|
+ continue
|
|
|
+
|
|
|
+ topic = topic[4].rstrip() + f" (by {nick_c})"
|
|
|
+
|
|
|
+ if topic == "":
|
|
|
+ logging.debug("%s: Topic message empty, skipping",
|
|
|
+ chan)
|
|
|
+ continue
|
|
|
+
|
|
|
+ topics = CHANS[chan]["topics"]
|
|
|
+ if topic not in topics:
|
|
|
+ topics.append(topic)
|
|
|
+ CHANS[chan]["topics"] = topics
|
|
|
+ logging.debug("%s: Appended topic to channel topics",
|
|
|
+ chan)
|
|
|
+ reply = f"PRIVMSG {chan} :Added topic: {topic}"
|
|
|
+ logging.info("%s: Send: %s", chan, reply)
|
|
|
+ else:
|
|
|
+ logging.debug("%s: Topic already in list of topics",
|
|
|
+ chan)
|
|
|
+ reply = f"PRIVMSG {chan} :Topic already in list"
|
|
|
+ logging.info("%s: Send: %s", chan, reply)
|
|
|
|
|
|
- if topic == "":
|
|
|
- logging.debug("%s: Topic message empty, skipping", chan)
|
|
|
+ writer.write((reply + "\r\n").encode("utf-8"))
|
|
|
+ await writer.drain()
|
|
|
continue
|
|
|
|
|
|
- topics = CHANS[chan]["topics"]
|
|
|
- if topic not in topics:
|
|
|
- topics.append(topic)
|
|
|
- CHANS[chan]["topics"] = topics
|
|
|
- logging.debug("%s: Appended topic to channel topics", chan)
|
|
|
- reply = f"PRIVMSG {chan} :Added topic: {topic}"
|
|
|
- logging.info("%s: Send: %s", chan, reply)
|
|
|
- else:
|
|
|
- logging.debug("%s: Topic already in list of topics", chan)
|
|
|
- reply = f"PRIVMSG {chan} :Topic already in list"
|
|
|
+ if msg_title == "!list":
|
|
|
+ logging.info("%s: Got !list", chan)
|
|
|
+ topics = CHANS[chan]["topics"]
|
|
|
+ if len(topics) == 0:
|
|
|
+ reply = f"PRIVMSG {chan} :No topics"
|
|
|
+ else:
|
|
|
+ reply = f"PRIVMSG {chan} :Topics:"
|
|
|
+
|
|
|
logging.info("%s: Send: %s", chan, reply)
|
|
|
+ writer.write((reply + "\r\n").encode("utf-8"))
|
|
|
+ await writer.drain()
|
|
|
|
|
|
- writer.write((reply + "\r\n").encode("utf-8"))
|
|
|
- await writer.drain()
|
|
|
- continue
|
|
|
+ for i, topic in enumerate(topics):
|
|
|
+ reply = f"PRIVMSG {chan} :{i+1}. {topic}"
|
|
|
+ logging.info("%s: Send: %s", chan, reply)
|
|
|
+ writer.write((reply + "\r\n").encode("utf-8"))
|
|
|
+ await writer.drain()
|
|
|
|
|
|
- if msg_title == "!list":
|
|
|
- logging.info("%s: Got !list", chan)
|
|
|
- topics = CHANS[chan]["topics"]
|
|
|
- if len(topics) == 0:
|
|
|
- reply = f"PRIVMSG {chan} :No topics"
|
|
|
- else:
|
|
|
- reply = f"PRIVMSG {chan} :Topics:"
|
|
|
+ continue
|
|
|
|
|
|
- logging.info("%s: Send: %s", chan, reply)
|
|
|
- writer.write((reply + "\r\n").encode("utf-8"))
|
|
|
- await writer.drain()
|
|
|
+ if msg_title == "!next":
|
|
|
+ logging.info("%s: Got !next", chan)
|
|
|
+ topics = CHANS[chan]["topics"]
|
|
|
+ if len(topics) == 0:
|
|
|
+ reply = f"PRIVMSG {chan} :No further topics"
|
|
|
+ else:
|
|
|
+ cur_topic = topics.pop(0)
|
|
|
+ CHANS[chan]["topics"] = topics
|
|
|
+ reply = f"PRIVMSG {chan} :Current topic: {cur_topic}"
|
|
|
|
|
|
- for i, topic in enumerate(topics):
|
|
|
- reply = f"PRIVMSG {chan} :{i+1}. {topic}"
|
|
|
logging.info("%s: Send: %s", chan, reply)
|
|
|
writer.write((reply + "\r\n").encode("utf-8"))
|
|
|
await writer.drain()
|
|
|
+ continue
|
|
|
|
|
|
- continue
|
|
|
-
|
|
|
- if msg_title == "!next":
|
|
|
- logging.info("%s: Got !next", chan)
|
|
|
- topics = CHANS[chan]["topics"]
|
|
|
- if len(topics) == 0:
|
|
|
- reply = f"PRIVMSG {chan} :No further topics"
|
|
|
- else:
|
|
|
- cur_topic = topics.pop(0)
|
|
|
- CHANS[chan]["topics"] = topics
|
|
|
- reply = f"PRIVMSG {chan} :Current topic: {cur_topic}"
|
|
|
-
|
|
|
- logging.info("%s: Send: %s", chan, reply)
|
|
|
- writer.write((reply + "\r\n").encode("utf-8"))
|
|
|
- await writer.drain()
|
|
|
- continue
|
|
|
-
|
|
|
- return
|
|
|
+ except KeyboardInterrupt:
|
|
|
+ pass
|
|
|
+ except ConnectionRefusedError:
|
|
|
+ logging.warning("%s: Connection refused, trying again in 3s...", chan)
|
|
|
+ await asyncio.sleep(3)
|
|
|
+ await channel_listen(host, port, nick, chan)
|
|
|
+ except Exception as e:
|
|
|
+ logging.error("EXCEPTION: %s", e)
|
|
|
+ logging.warn("%s: Connection interrupted. Reconnecting in 3s...", chan)
|
|
|
+ await asyncio.sleep(3)
|
|
|
+ await channel_listen(host, port, nick, chan)
|
|
|
|
|
|
|
|
|
async def main(debug=False):
|
|
|
@@ -223,7 +238,7 @@ if __name__ == "__main__":
|
|
|
|
|
|
try:
|
|
|
asyncio.run(main(debug=DBG))
|
|
|
- except:
|
|
|
+ except KeyboardInterrupt:
|
|
|
print("\rCaught ^C, saving pickle and exiting")
|
|
|
|
|
|
with open(PICKLE_DB, "wb") as fdesc:
|