tracer/tracer.py

206 lines
5.3 KiB
Python
Raw Normal View History

2019-05-28 16:16:58 +00:00
#!/usr/bin/env python3
2019-01-29 02:33:35 +00:00
from random import randint, choice
from tracery.modifiers import base_english
2020-02-24 15:47:57 +00:00
import configparser
import glob
2020-03-11 18:10:44 +00:00
import irctokens
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 re
import socket
import subprocess
import sys
import time
import traceback
import tracery
2019-01-29 02:33:35 +00:00
DB = {}
2020-02-24 15:47:57 +00:00
config = configparser.ConfigParser(
converters={"list": lambda x: [i.strip() for i in x.split(",")]}
)
config.read("config.ini")
bot = config["irc"]
2019-01-29 02:33:35 +00:00
2020-02-24 16:32:56 +00:00
# read account info if it exists
if os.path.isfile("account.ini"):
account = configparser.ConfigParser()
account.read("account.ini")
account = account["nickserv"]
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
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)
2020-02-24 15:47:57 +00:00
if name.startswith(".") or ext not in (".json", ""):
continue
if p in DB:
DB[name].append(grammar(load_rules(p)))
else:
DB[name] = [grammar(load_rules(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:
g = random.choice(DB[rule])
return g.flatten("#origin#")
def listify(col):
if type(col) == type([]):
return col
else:
return [col]
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:
g = random.choice(DB[gk]).raw
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 _send(line):
print(f"> {line.format()}")
e.push(line)
while e.pending():
e.pop(s.send(e.pending()))
2019-01-29 02:33:35 +00:00
2019-05-28 17:31:21 +00:00
def send(chan, msg):
2020-05-01 17:15:15 +00:00
_send(irctokens.build("PRIVMSG", [chan, msg]))
2019-01-29 02:33:35 +00:00
2020-03-11 18:10:44 +00:00
def think(line):
chan = line.params.pop(0)
words = line.params[0].split(" ")
2020-03-12 05:06:05 +00:00
if len(words) > 0 and line.hostmask.nickname != bot["nick"]:
2019-01-29 02:33:35 +00:00
if words[0] == "!!list":
res = ""
for k in DB:
2019-05-28 17:31:21 +00:00
res += k + " "
2019-05-28 16:16:58 +00:00
send(chan, res[:475])
2019-01-29 02:33:35 +00:00
elif words[0] == "!!fuse":
if "|" in words:
2019-05-28 17:31:21 +00:00
res = fuse(words[1 : words.index("|")])
2019-01-29 02:33:35 +00:00
if res:
2019-05-28 17:31:21 +00:00
send(chan, " ".join(words[words.index("|") + 1 :]) + " " + res)
2019-01-29 02:33:35 +00:00
else:
res = fuse(words[1:])
if res:
2019-05-28 17:31:21 +00:00
send(chan, res[0:475])
2019-05-28 17:40:51 +00:00
elif words[0] == "!!source":
send(chan, "https://tildegit.org/ben/tracer")
2019-05-28 17:47:59 +00:00
elif words[0] == "!botlist" or words[0] == "!!help":
2019-05-28 17:40:51 +00:00
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",
)
2019-01-29 02:33:35 +00:00
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)
else:
send(chan, res)
else:
send(chan, res)
2019-05-28 17:31:21 +00:00
2019-01-29 02:33:35 +00:00
if __name__ == "__main__":
2020-03-11 18:10:44 +00:00
d = irctokens.StatefulDecoder()
e = irctokens.StatefulEncoder()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((bot["server"], int(bot["port"])))
2020-05-01 17:15:15 +00:00
_send(irctokens.build("USER", [bot["nick"], "0", "*", "tracery bot"]))
_send(irctokens.build("NICK", [bot["nick"]]))
2019-05-28 16:16:58 +00:00
2020-03-11 18:10:44 +00:00
while True:
lines = d.push(s.recv(1024))
2019-05-28 17:31:21 +00:00
2020-03-11 18:10:44 +00:00
if lines == None:
print("! disconnected")
break
2019-05-28 17:31:21 +00:00
2020-03-11 18:10:44 +00:00
for line in lines:
print(f"< {line.format()}")
2019-05-28 18:09:43 +00:00
2020-03-11 18:10:44 +00:00
if line.command == "PING":
2020-05-01 17:15:15 +00:00
_send(irctokens.build("PONG", [line.params[0]]))
2020-03-11 18:10:44 +00:00
elif line.command == "001":
2020-05-01 17:15:15 +00:00
_send(irctokens.build("MODE", [bot["nick"], "+B"]))
2020-02-24 16:32:56 +00:00
if account is not None:
2020-03-11 18:10:44 +00:00
_send(
2020-05-01 17:15:15 +00:00
irctokens.build(
2020-03-11 18:10:44 +00:00
"SQUERY",
[
"NickServ",
"IDENTIFY",
account["username"],
account["password"],
],
)
2020-02-24 16:32:56 +00:00
)
2020-03-12 14:00:33 +00:00
2020-05-01 17:15:15 +00:00
_send(irctokens.build("JOIN", [",".join(bot.getlist("channels"))]))
2020-03-11 18:10:44 +00:00
elif line.command == "INVITE":
2020-05-01 17:15:15 +00:00
_send(irctokens.build("JOIN", [line.params[1]]))
2019-05-28 17:31:21 +00:00
2020-03-11 18:10:44 +00:00
elif line.command == "PRIVMSG":
2019-05-28 17:31:21 +00:00
try:
2020-03-11 18:10:44 +00:00
think(line)
2019-05-28 17:31:21 +00:00
except Exception as e:
2020-03-11 18:10:44 +00:00
print("ERROR", line)
2019-05-28 17:31:21 +00:00
print(e)
2019-06-25 02:58:42 +00:00
traceback.print_exc()
2020-03-12 14:00:33 +00:00