#!/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 glob import json import os import sys HELP_TEXT = "helo i can send toots from irc: @tildeverse@tilde.zone - from @tildeteam from the #team channel)" masto = {} assigned_channels = {} # load masto creds for cred in glob.glob("tilde*.json"): shortname, _ = os.path.splitext(cred) with open(cred, "r") as f: conf = json.load(f) if "channel" in conf: assigned_channels[conf["channel"]] = shortname masto[shortname] = Mastodon( client_id=conf["client_id"], client_secret=conf["client_secret"], access_token=conf["access_token"], api_base_url=conf["base_url"], ) if "tildeverse" not in masto: print("you must populate tildeverse.json with mastodon credentials") exit(1) # do setup with open("config.json", "r") as f: config = json.load(f) with open("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) def think(line): chan = line.params[0] cmd, *words = line.params[1].split(" ") cmd = cmd.lower()[1:] if cmd == "source": return "https://tildegit.org/ben/tooter" elif cmd in ["botlist", "toothelp"]: return HELP_TEXT elif cmd == "toot": if len(words) >= 2: status = emoji.emojize(" ".join(words[1:]), use_aliases=True) author = line.tags.get("account", line.hostmask.nickname) res = masto[ assigned_channels[chan] if chan in assigned_channels else "tildeverse" ].toot(f"{status}\n~{author}") return "tooted! {}".format(res["url"]) else: return HELP_TEXT 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(channels)])) await self.send(build("MODE", [self.nickname, "+B"])) if line.command == "INVITE": await self.send(build("JOIN", line.params[1:])) if ( line.command == "PRIVMSG" and self.has_channel(line.params[0]) and self.has_user(line.hostmask.nickname) and len(line.params[1].split(" ")) > 0 and line.hostmask is not None and not self.casefold(line.hostmask.nickname) == self.nickname_lower and not ("batch" in line.tags and line.tags["batch"] == "1") and line.params[1].startswith("!") ): 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(): params = ConnectionParams( config["botnick"], host=config["address"], port=config["port"], tls=config["tls"], sasl=SASLUserPass(account["username"], account["password"]), ) bot = Bot() await bot.add_server("tilde", params) await bot.run() if __name__ == "__main__": asyncio.run(main())