tracer/tracer.py

187 lines
4.8 KiB
Python
Raw Permalink Normal View History

2019-05-28 16:16:58 +00:00
#!/usr/bin/env python3
2021-02-19 04:13:16 +00:00
from irctokens import build, Line
from ircrobots import Bot as BaseBot
from ircrobots import Server as BaseServer
from ircrobots import ConnectionParams, SASLUserPass
2019-01-29 02:33:35 +00:00
from tracery.modifiers import base_english
2021-02-19 04:13:16 +00:00
import asyncio
2020-02-24 15:47:57 +00:00
import configparser
import glob
2019-01-29 02:33:35 +00:00
import json
2020-02-24 15:47:57 +00:00
import os
2019-01-29 02:33:35 +00:00
import random
2020-02-24 15:47:57 +00:00
import traceback
import tracery
2019-01-29 02:33:35 +00:00
2022-05-10 18:15:53 +00:00
HELP_TEXT = "helo i'm a tracery bot that makes cool things from tracery grammars in your ~/.tracery. see " \
"https://tracery.io for more info "
REPO_LINK = "https://tildegit.org/ben/tracer"
2021-02-19 04:31:58 +00:00
2019-01-29 02:33:35 +00:00
DB = {}
2021-02-24 20:06:13 +00:00
# read configuration
2022-05-10 18:15:53 +00:00
if not os.path.isfile("config.ini"):
print("you must create a config.ini file")
exit(1)
2019-01-29 02:33:35 +00:00
2022-05-10 18:15:53 +00:00
parser = configparser.ConfigParser()
parser.read("config.ini")
config = parser["irc"]
account = parser["sasl"]
2020-02-24 16:32:56 +00:00
2019-05-28 17:31:21 +00:00
2019-01-29 02:33:35 +00:00
def grammar(rules):
try:
res = tracery.Grammar(rules)
res.add_modifiers(base_english)
return res
except Exception as e:
print(e)
2019-05-28 17:31:21 +00:00
2019-01-29 02:33:35 +00:00
def load_rules(path):
try:
with open(path) as f:
return json.loads(f.read())
except Exception as e:
print(e)
2019-05-28 17:31:21 +00:00
2019-01-29 02:33:35 +00:00
def populate():
global DB
2021-02-19 04:31:58 +00:00
DB = {}
2020-02-24 15:47:57 +00:00
for p in glob.glob("/home/*/.tracery/*"):
name, ext = os.path.splitext(p)
2020-02-24 16:32:56 +00:00
name = os.path.basename(name)
2021-02-24 20:06:13 +00:00
if name.startswith(".") or ext not in [".json", ""]:
2020-02-24 15:47:57 +00:00
continue
if p in DB:
2021-02-19 04:40:56 +00:00
DB[name].append(p)
2020-02-24 15:47:57 +00:00
else:
2021-02-19 04:40:56 +00:00
DB[name] = [p]
2019-01-29 02:33:35 +00:00
2019-05-28 17:31:21 +00:00
2019-01-29 02:33:35 +00:00
populate()
2019-05-28 17:31:21 +00:00
2019-01-29 02:33:35 +00:00
def generate(rule):
populate()
if rule in DB:
2021-02-24 20:14:06 +00:00
return grammar(load_rules(random.choice(DB[rule]))).flatten("#origin#")
2019-01-29 02:33:35 +00:00
def listify(col):
2021-02-24 20:06:13 +00:00
return col if type(col) == type([]) else [col]
2019-01-29 02:33:35 +00:00
2019-05-28 17:31:21 +00:00
2019-01-29 02:33:35 +00:00
def shuffle(col):
2019-06-25 02:58:42 +00:00
a = random.choice(list(col))
b = random.choice(list(col))
2019-05-28 17:31:21 +00:00
if "origin" in [a, b]:
2019-01-29 02:33:35 +00:00
return col
2019-05-28 17:47:59 +00:00
col[a], col[b] = col[b], col[a]
2019-01-29 02:33:35 +00:00
return col
2019-05-28 17:31:21 +00:00
2019-01-29 02:33:35 +00:00
def fuse(argv):
populate()
raw = {}
for gk in argv:
if gk in DB:
2021-02-19 04:40:56 +00:00
g = grammar(load_rules(random.choice(DB[gk]))).raw
2019-01-29 02:33:35 +00:00
for k in g:
if k in raw:
2019-05-28 17:31:21 +00:00
raw[k] = listify(raw[k]) + listify(g[k])
2019-01-29 02:33:35 +00:00
else:
raw[k] = g[k]
for i in range(20):
raw = shuffle(raw)
return grammar(raw).flatten("#origin#")
2020-03-11 18:10:44 +00:00
def think(line):
2022-05-10 18:15:53 +00:00
command, *words = line.params[1].split(" ")
if command == "!!list":
2021-02-24 20:14:06 +00:00
return " ".join(DB)
2022-05-10 18:15:53 +00:00
elif command == "!!source":
return REPO_LINK
elif command in ["!!help", "!botlist"]:
return HELP_TEXT
elif command == "!!fuse":
2021-02-24 20:14:06 +00:00
if "|" in words:
w = words.index("|")
2022-05-10 18:15:53 +00:00
res = fuse(words[:w])
2021-02-24 20:14:06 +00:00
if res:
2022-05-10 18:15:53 +00:00
return " ".join(words[w + 1:]) + " " + res
2021-02-24 20:14:06 +00:00
else:
2022-05-10 18:15:53 +00:00
res = fuse(words)
2021-02-24 20:14:06 +00:00
if res:
return res
2022-05-10 18:15:53 +00:00
elif command.startswith("!!"):
res = generate(command[2:])
2021-02-24 20:14:06 +00:00
if res:
2019-01-29 02:33:35 +00:00
if "|" in words:
2021-02-24 20:06:13 +00:00
w = words.index("|")
2022-05-10 18:15:53 +00:00
return " ".join(words[w + 1:]) + " " + res
2019-01-29 02:33:35 +00:00
else:
2021-02-24 20:14:06 +00:00
return res
2021-02-19 04:13:16 +00:00
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()}")
2022-05-10 18:15:53 +00:00
2021-02-19 04:13:16 +00:00
if line.command == "001":
await self.send(build("MODE", [self.nickname, "+B"]))
if line.command == "INVITE":
await self.send(build("JOIN", [line.params[1]]))
if (
2022-05-10 18:15:53 +00:00
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 "inspircd.org/bot" not in line.tags
and line.params[1].startswith("!")
2021-02-19 04:13:16 +00:00
):
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():
params = ConnectionParams(
2021-02-24 20:06:13 +00:00
config["nick"],
host=config["server"],
port=config.getint("port"),
tls=config.getboolean("tls"),
2021-02-19 04:13:16 +00:00
sasl=SASLUserPass(account["username"], account["password"]),
2022-05-10 18:15:53 +00:00
autojoin=[config["channels"]]
2021-02-19 04:13:16 +00:00
)
2021-02-24 20:14:06 +00:00
bot = Bot()
2022-05-10 18:15:53 +00:00
await bot.add_server(config["server"], params)
2021-02-24 20:06:13 +00:00
await bot.run()
2019-01-29 02:33:35 +00:00
2019-05-28 17:31:21 +00:00
2019-01-29 02:33:35 +00:00
if __name__ == "__main__":
2021-02-19 04:13:16 +00:00
asyncio.run(main())