From d0ce7765724959d469921ac89b9992e4880d2b6f Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Thu, 18 Feb 2021 15:41:58 -0500 Subject: rewrite with ircrobots --- tooter.py | 166 ++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 85 insertions(+), 81 deletions(-) (limited to 'tooter.py') diff --git a/tooter.py b/tooter.py index 117185f..33b57f8 100644 --- a/tooter.py +++ b/tooter.py @@ -1,16 +1,21 @@ #!/usr/bin/env python3 from mastodon import Mastodon +from irctokens import build, Line +from ircrobots import Bot as BaseBot +from ircrobots import Server as BaseServer +from ircrobots import ConnectionParams, SASLUserPass +import asyncio import emoji -import irctokens +import glob import json import os import re -import socket import sys HELPTEXT = "helo i can send toots from irc: @tildeverse@tilde.zone - from @tildeteam from the #team channel)" + def masto_from_json(conf): conf = json.load(conf) return Mastodon( @@ -21,102 +26,101 @@ def masto_from_json(conf): ) -def _send(line): - print(f"> {line.format()}") - e.push(line) - while e.pending(): - e.pop(s.send(e.pending())) +masto = {} +# load masto creds +for cred in glob.glob("tilde*.json"): + shortname, _ = os.path.splitext(cred) + with open(cred, "r") as f: + masto[shortname] = masto_from_json(f) + +# do setup +path = os.path.dirname(os.path.abspath(__file__)) + +with open(os.path.join(path, "config.json"), "r") as f: + config = json.load(f) +if os.path.isfile(os.path.join(path, "account.json")): + with open(os.path.join(path, "account.json"), "r") as f: + account = json.load(f) -def send(chan, msg): - _send(irctokens.build("PRIVMSG", [chan, msg])) +channels = config["channels"] +if len(sys.argv) > 1: + for c in sys.argv[1:]: + channels.append("#" + c) def think(line): - chan = line.params.pop(0) - words = line.params[0].split(" ") + chan = line.params[0] + words = line.params[1].split(" ") - if len(words) > 0 and line.hostmask.nickname != config["botnick"]: + if len(words) > 0: cmd = words[0].lower() if cmd == "!toot": if len(words) >= 2: status = emoji.emojize(" ".join(words[1:]), use_aliases=True) if chan == "#team": - res = tildeteam.toot(status) + res = masto["tildeteam"].toot(status) + elif chan == "#club": + res = masto["tildeclub"].toot(status) else: - res = tildeverse.toot(status) + res = masto["tildeverse"].toot(status) print(res) - send(chan, "tooted! {}".format(res["url"])) + return "tooted! {}".format(res["url"]) else: - send(chan, HELPTEXT) + return HELPTEXT elif cmd == "!source": - send(chan, "https://tildegit.org/ben/tooter") + return "https://tildegit.org/ben/tooter" elif cmd in ["!botlist", "!toothelp"]: - send(chan, HELPTEXT) - - -# do setup -path = os.path.dirname(os.path.abspath(__file__)) - -with open(os.path.join(path, "config.json"), "r") as f: - config = json.load(f) - -if os.path.isfile(os.path.join(path, "account.json")): - with open(os.path.join(path, "account.json"), "r") as f: - account = json.load(f) - -channels = config["channels"] -if len(sys.argv) > 1: - for c in sys.argv[1:]: - channels.append("#" + c) + return HELPTEXT + + +class Server(BaseServer): + async def line_send(self, line: Line): + print(f"{self.name} > {line.format()}") + + async def line_read(self, line: Line): + print(f"{self.name} < {line.format()}") + if line.command == "001": + print(f"connected to {self.isupport.network}") + await self.send(build("JOIN", [",".join(channels)])) + await self.send(build("MODE", [self.nickname, "+B"])) + + if line.command == "INVITE": + print(f"received invite to {line.params[1:]}") + await self.send(build("JOIN", line.params[1:])) + + if ( + line.command == "PRIVMSG" + and self.has_channel(line.params[0]) + and not line.hostmask is None + and not self.casefold(line.hostmask.nickname) == self.nickname_lower + and not ("batch" in line.tags and line.tags["batch"] == "1") + and self.has_user(line.hostmask.nickname) + ): + response = think(line) + if response is not None: + await self.send(build("PRIVMSG", [line.params[0], response])) + + +class Bot(BaseBot): + def create_server(self, name: str): + return Server(self, name) + + +async def main(): + bot = Bot() + + params = ConnectionParams( + config["botnick"], + host=config["address"], + port=config["port"], + tls=config["tls"], + sasl=SASLUserPass(account["username"], account["password"]), + ) -# read masto creds -with open(os.path.join(path, "tildeverse.json"), "r") as f: - tildeverse = masto_from_json(f) + await bot.add_server("tilde", params) + await bot.run() -with open(os.path.join(path, "tildeteam.json"), "r") as f: - tildeteam = masto_from_json(f) if __name__ == "__main__": - d = irctokens.StatefulDecoder() - e = irctokens.StatefulEncoder() - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.connect((config["address"], config["port"])) - - _send(irctokens.build("USER", [config["botnick"], "0", "*", "mastodon tooter"])) - _send(irctokens.build("NICK", [config["botnick"]])) - - while True: - lines = d.push(s.recv(1024)) - - if lines == None: - print("! disconnected") - break - - for line in lines: - print(f"< {line.format()}") - - if line.command == "PING": - _send(irctokens.build("PONG", line.params)) - - elif line.command == "001": - _send(irctokens.build("MODE", [config["botnick"], "+B"])) - if account is not None: - _send( - irctokens.build( - "SQUERY", - [ - "NickServ", - "IDENTIFY", - account["username"], - account["password"], - ], - ) - ) - _send(irctokens.build("JOIN", [",".join(channels)])) - - elif line.command == "INVITE": - _send(irctokens.build("JOIN", line.params)) - - elif line.command == "PRIVMSG": - think(line) + asyncio.run(main()) -- cgit 1.4.1