123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- #!/usr/bin/env python3
- import socket
- import re
- from random import randint, choice
- import sys, os
- import time
- import subprocess
- import tracery
- import traceback
- from tracery.modifiers import base_english
- import json
- import random
- DB = {}
- def grammar(rules):
- try:
- res = tracery.Grammar(rules)
- res.add_modifiers(base_english)
- return res
- except Exception as e:
- print(e)
- def load_rules(path):
- try:
- with open(path) as f:
- return json.loads(f.read())
- except Exception as e:
- print(e)
- def populate():
- global DB
- DB = {}
- for subdir in os.listdir("/home"):
- d = f"/home/{subdir}/.tracery"
- if os.path.isdir(d):
- for p in os.listdir(d):
- rule = d + "/" + p
- name = p.replace(".json", "")
- # print(p, rule, name)
- if p in DB:
- DB[name].append(grammar(load_rules(rule)))
- else:
- DB[name] = [grammar(load_rules(rule))]
- populate()
- print(DB)
- 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]
- def shuffle(col):
- a = random.choice(list(col))
- b = random.choice(list(col))
- if "origin" in [a, b]:
- print("origin discard")
- return col
- col[a], col[b] = col[b], col[a]
- return col
- 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:
- raw[k] = listify(raw[k]) + listify(g[k])
- else:
- raw[k] = g[k]
- for i in range(20):
- raw = shuffle(raw)
- return grammar(raw).flatten("#origin#")
- server = "127.0.0.1"
- channels = ["#bots", "#meta", "#team"]
- if len(sys.argv) > 1:
- for c in sys.argv[1:]:
- channels.append("#" + c)
- botnick = "tracer"
- def rawsend(msg):
- print(msg)
- ircsock.send(f"{msg}\r\n".encode())
- def send(chan, msg):
- # This is the send message function, it simply sends messages to the channel.
- rawsend(f"PRIVMSG #{chan} :{msg}")
- def think(chan, nick, msg):
- words = re.split("[ \t\s]+", msg)
- if len(words) > 0 and nick != "tracer":
- if words[0] == "!!list":
- res = ""
- for k in DB:
- res += k + " "
- send(chan, res[:475])
- elif words[0] == "!!fuse":
- if "|" in words:
- res = fuse(words[1 : words.index("|")])
- if res:
- send(chan, " ".join(words[words.index("|") + 1 :]) + " " + res)
- else:
- res = fuse(words[1:])
- if res:
- send(chan, res[0:475])
- elif words[0] == "!!source":
- send(chan, "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",
- )
- 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)
- if __name__ == "__main__":
- ircsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- ircsock.connect((server, 6667)) # Here we connect to the server using port 6667
- rawsend(f"NICK {botnick}") # here we actually assign the nick to the bot
- rawsend(f"USER {botnick} 0 * :tracery bot") # user authentication
- while 1:
- msg = ircsock.recv(2048).decode().split("\r\n")
- for ircmsg in msg:
- print(ircmsg)
- if "PING" in ircmsg:
- rawsend(ircmsg.replace("I", "O", 1))
- if "INVITE" in ircmsg:
- chan = ircmsg.split(":")[-1]
- rawsend(f"JOIN {chan}")
- if "001" in ircmsg:
- for c in channels:
- rawsend(f"JOIN {c}")
- rawsend(f"MODE {botnick} +B")
- m = re.match(
- ":(?P<nick>[^ ]+)!.*PRIVMSG #(?P<chan>\w+) :(?P<msg>.*)", ircmsg
- )
- if m and m.groupdict():
- m = m.groupdict()
- try:
- think(m["chan"], m["nick"], m["msg"])
- except Exception as e:
- print("ERROR" + str(m))
- print(e)
- traceback.print_exc()
|