about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--config.json.example1
-rw-r--r--requirements.txt2
-rw-r--r--tooter.py166
4 files changed, 88 insertions, 82 deletions
diff --git a/.gitignore b/.gitignore
index a86389a..728b360 100644
--- a/.gitignore
+++ b/.gitignore
@@ -58,6 +58,7 @@ docs/_build/
 # PyBuilder
 target/
 
+tildeclub.json
 tildeteam.json
 tildeverse.json
 config.json
diff --git a/config.json.example b/config.json.example
index a980886..4eeeff2 100644
--- a/config.json.example
+++ b/config.json.example
@@ -2,6 +2,7 @@
     "channels": [],
     "address": "127.0.0.1",
     "port": 6667,
+    "tls": false,
     "botnick", "tooter"
 }
 
diff --git a/requirements.txt b/requirements.txt
index 74ea545..a3e9998 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,3 @@
 Mastodon.py==1.5.0
 emoji==0.5.4
-irctokens==1.0.0
+ircrobots==0.3.7
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())