diff --git a/config.ini b/config.ini index e17bb24..d4386bb 100644 --- a/config.ini +++ b/config.ini @@ -3,4 +3,5 @@ server = 127.0.0.1 channels = #bots, #meta, #team nick = tracer port = 6667 +tls = false diff --git a/requirements.txt b/requirements.txt index f245902..7776149 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ tracery==0.1.1 -irctokens==1.0.0 +ircrobots==0.3.7 diff --git a/tracer.py b/tracer.py index 8a4e430..4b1ddfe 100644 --- a/tracer.py +++ b/tracer.py @@ -1,18 +1,17 @@ #!/usr/bin/env python3 +from irctokens import build, Line +from ircrobots import Bot as BaseBot +from ircrobots import Server as BaseServer +from ircrobots import ConnectionParams, SASLUserPass from random import randint, choice from tracery.modifiers import base_english +import asyncio import configparser import glob -import irctokens import json import os import random -import re -import socket -import subprocess -import sys -import time import traceback import tracery @@ -49,7 +48,7 @@ def load_rules(path): def populate(): global DB - DB = {} + # DB = {} for p in glob.glob("/home/*/.tracery/*"): name, ext = os.path.splitext(p) name = os.path.basename(name) @@ -103,103 +102,94 @@ def fuse(argv): return grammar(raw).flatten("#origin#") -def _send(line): - print(f"> {line.format()}") - e.push(line) - while e.pending(): - e.pop(s.send(e.pending())) - - -def send(chan, msg): - _send(irctokens.build("PRIVMSG", [chan, msg])) - - 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 != bot["nick"]: + if len(words) > 0: if words[0] == "!!list": res = "" for k in DB: res += k + " " - send(chan, res[:475]) + return res elif words[0] == "!!fuse": if "|" in words: res = fuse(words[1 : words.index("|")]) if res: - send(chan, " ".join(words[words.index("|") + 1 :]) + " " + res) + return " ".join(words[words.index("|") + 1 :]) + " " + res else: res = fuse(words[1:]) if res: - send(chan, res[0:475]) + return res elif words[0] == "!!source": - send(chan, "https://tildegit.org/ben/tracer") + return "https://tildegit.org/ben/tracer" elif words[0] == "!botlist" or words[0] == "!!help": - send( - chan, - "helo i'm a tracery bot that makes cool things from tracery grammars in your ~/.tracery. see http://tracery.io for more info", - ) + return "helo i'm a tracery bot that makes cool things from tracery grammars in your ~/.tracery. see http://tracery.io for more info" elif words[0][0:2] == "!!": print(words) res = generate(words[0][2:]) if res: if len(words) >= 3: if words[1] == "|": - send(chan, " ".join(words[2:]) + " " + res) + return " ".join(words[2:]) + " " + res else: - send(chan, res) + return res else: - send(chan, res) + return res + + +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": + await self.send(build("JOIN", [",".join(bot.getlist("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 not "inspircd.org/bot" in line.tags + and self.has_user(line.hostmask.nickname) + ): + try: + response = think(line) + if response is not None: + await self.send(build("PRIVMSG", [line.params[0], response])) + except Exception as e: + print("ERROR", line) + print(e) + traceback.print_exc() + + +class Bot(BaseBot): + def create_server(self, name: str): + return Server(self, name) + + +async def main(): + ircrobot = Bot() + + params = ConnectionParams( + bot["nick"], + host=bot["server"], + port=int(bot["port"]), + tls=bool(bot["tls"]), + sasl=SASLUserPass(account["username"], account["password"]), + ) + + await ircrobot.add_server("tilde", params) + await ircrobot.run() if __name__ == "__main__": - d = irctokens.StatefulDecoder() - e = irctokens.StatefulEncoder() - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.connect((bot["server"], int(bot["port"]))) - - _send(irctokens.build("USER", [bot["nick"], "0", "*", "tracery bot"])) - _send(irctokens.build("NICK", [bot["nick"]])) - - 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[0]])) - - elif line.command == "001": - _send(irctokens.build("MODE", [bot["nick"], "+B"])) - if account is not None: - _send( - irctokens.build( - "SQUERY", - [ - "NickServ", - "IDENTIFY", - account["username"], - account["password"], - ], - ) - ) - - _send(irctokens.build("JOIN", [",".join(bot.getlist("channels"))])) - - elif line.command == "INVITE": - _send(irctokens.build("JOIN", [line.params[1]])) - - elif line.command == "PRIVMSG": - try: - think(line) - except Exception as e: - print("ERROR", line) - print(e) - traceback.print_exc() - + asyncio.run(main())