Implement indexing into Apache Druid #1

Closed
m wants to merge 263 commits from druid into master
60 changed files with 547 additions and 278 deletions
Showing only changes of commit 7c855e09c0 - Show all commits

View File

@ -1,6 +1,7 @@
import main
from core.bot import deliverRelayCommands
class AdmallCommand:
def __init__(self, *args):
self.admall(*args)

View File

@ -2,6 +2,7 @@ import main
from yaml import dump
from modules import alias
class AliasCommand:
def __init__(self, *args):
self.alias(*args)

View File

@ -1,6 +1,7 @@
import main
from core.bot import deliverRelayCommands
class AllCommand:
def __init__(self, *args):
self.all(*args)

View File

@ -1,6 +1,7 @@
import main
from core.bot import deliverRelayCommands
class AllcCommand:
def __init__(self, *args):
self.allc(*args)
@ -16,9 +17,11 @@ class AllcCommand:
targets.append((i, x))
elif spl[1] == "alias":
for i in main.network.keys():
[targets.append((i, x)) for x in main.alias.keys() if
main.alias[x]["nick"] == spl[2] and
x in main.network[i].aliases.keys()]
[
targets.append((i, x))
for x in main.alias.keys()
if main.alias[x]["nick"] == spl[2] and x in main.network[i].aliases.keys()
]
else:
incUsage("allc")
return

View File

@ -1,5 +1,6 @@
import main
class AuthcheckCommand:
def __init__(self, *args):
self.authcheck(*args)

View File

@ -1,6 +1,7 @@
import main
from modules import provision
class AutoCommand:
def __init__(self, *args):
self.auto(*args)

View File

@ -1,6 +1,7 @@
import main
from yaml import dump
class BlacklistCommand:
def __init__(self, *args):
self.blacklist(*args)

View File

@ -1,6 +1,7 @@
import main
import modules.userinfo as userinfo
class ChansCommand:
def __init__(self, *args):
self.chans(*args)
@ -16,7 +17,7 @@ class ChansCommand:
rtrn += "Matches from: %s" % i
rtrn += "\n"
for x in result[i]:
rtrn += (x)
rtrn += x
rtrn += "\n"
rtrn += "\n"
info(rtrn)

View File

@ -1,6 +1,7 @@
import main
from core.bot import deliverRelayCommands
class CmdCommand:
def __init__(self, *args):
self.cmd(*args)

View File

@ -1,6 +1,7 @@
import main
from modules import regproc
class ConfirmCommand:
def __init__(self, *args):
self.confirm(*args)

View File

@ -1,6 +1,7 @@
import main
from core.bot import deliverRelayCommands
class DisableCommand:
def __init__(self, *args):
self.disable(*args)

View File

@ -1,6 +1,7 @@
import main
from subprocess import run, PIPE
class DistCommand:
def __init__(self, *args):
self.dist(*args)

View File

@ -1,6 +1,7 @@
import main
from yaml import dump
class EmailCommand:
def __init__(self, *args):
self.email(*args)

View File

@ -1,6 +1,7 @@
import main
from core.bot import deliverRelayCommands
class EnableCommand:
def __init__(self, *args):
self.enable(*args)

View File

@ -1,5 +1,6 @@
import main
class ExecCommand:
def __init__(self, *args):
self.exec(*args)

View File

@ -1,5 +1,6 @@
import main
class HelpCommand:
def __init__(self, *args):
self.help(*args)

View File

@ -1,6 +1,7 @@
import main
import modules.chankeep
class JoinCommand:
def __init__(self, *args):
self.join(*args)

View File

@ -1,5 +1,6 @@
import main
class ListCommand:
def __init__(self, *args):
self.list(*args)

View File

@ -1,5 +1,6 @@
import main
class LoadCommand:
def __init__(self, *args):
self.load(*args)

View File

@ -1,6 +1,7 @@
import main
from utils.loaders.single_loader import loadSingle
class LoadmodCommand:
def __init__(self, *args):
self.loadmod(*args)

View File

@ -1,5 +1,6 @@
import main
class LogoutCommand:
def __init__(self, *args):
self.logout(*args)

View File

@ -1,6 +1,7 @@
import main
from yaml import dump
class ModCommand:
# This could be greatly improved, but not really important right now
def __init__(self, *args):

View File

@ -1,5 +1,6 @@
import main
class MsgCommand:
def __init__(self, *args):
self.msg(*args)

View File

@ -3,6 +3,7 @@ from yaml import dump
from modules.network import Network
from string import digits
class NetworkCommand:
def __init__(self, *args):
self.network(*args)

View File

@ -1,5 +1,6 @@
import main
class PartCommand:
def __init__(self, *args):
self.part(*args)

View File

@ -1,5 +1,6 @@
import main
class PassCommand:
def __init__(self, *args):
self.password(*args)

View File

@ -1,5 +1,6 @@
import main
class PendingCommand:
def __init__(self, *args):
self.pending(*args)

View File

@ -1,5 +1,6 @@
import main
class RecheckauthCommand:
def __init__(self, *args):
self.recheckauth(*args)

View File

@ -1,6 +1,7 @@
import main
from modules import regproc
class RegCommand:
def __init__(self, *args):
self.reg(*args)

View File

@ -1,6 +1,7 @@
import main
from yaml import dump
class RelayCommand:
def __init__(self, *args):
self.relay(*args)

View File

@ -1,5 +1,6 @@
import main
class SaveCommand:
def __init__(self, *args):
self.save(*args)

View File

@ -3,6 +3,7 @@ import modules.counters as count
import modules.userinfo as userinfo
from string import digits
class StatsCommand:
def __init__(self, *args):
self.stats(*args)

View File

@ -1,5 +1,6 @@
import main
class SwhoCommand:
def __init__(self, *args):
self.swho(*args)

View File

@ -2,6 +2,7 @@ import main
from yaml import dump
from uuid import uuid4
class TokenCommand:
def __init__(self, *args):
self.token(*args)
@ -32,7 +33,8 @@ class TokenCommand:
if spl[1] == "add":
if not spl[2] in main.tokens.keys():
if spl[3] in ["relay"]: # more to come!
main.tokens[spl[2]] = {"hello": str(uuid4()),
main.tokens[spl[2]] = {
"hello": str(uuid4()),
"usage": spl[3],
"counter": str(uuid4()),
}

View File

@ -1,6 +1,7 @@
import main
import modules.userinfo as userinfo
class UsersCommand:
def __init__(self, *args):
self.users(*args)
@ -16,7 +17,7 @@ class UsersCommand:
rtrn += "Matches from: %s" % i
rtrn += "\n"
for x in result[i]:
rtrn += (x)
rtrn += x
rtrn += "\n"
rtrn += "\n"
info(rtrn)

View File

@ -1,6 +1,7 @@
import main
import modules.userinfo as userinfo
class WhoCommand:
def __init__(self, *args):
self.who(*args)
@ -14,7 +15,7 @@ class WhoCommand:
rtrn += "Matches from: %s" % i
rtrn += "\n"
for x in result[i]:
rtrn += (x)
rtrn += x
rtrn += "\n"
rtrn += "\n"
info(rtrn)

View File

@ -3,7 +3,12 @@ from twisted.words.protocols.irc import IRCClient
from twisted.internet.defer import Deferred
from twisted.internet.task import LoopingCall
from twisted.internet import reactor, task
from twisted.words.protocols.irc import symbolic_to_numeric, numeric_to_symbolic, lowDequote, IRCBadMessage
from twisted.words.protocols.irc import (
symbolic_to_numeric,
numeric_to_symbolic,
lowDequote,
IRCBadMessage,
)
import sys
from string import digits
@ -29,16 +34,15 @@ from utils.parsing import parsen
from twisted.internet.ssl import DefaultOpenSSLContextFactory
def deliverRelayCommands(num, relayCommands, user=None, stage2=None):
keyFN = main.certPath + main.config["Key"]
certFN = main.certPath + main.config["Certificate"]
contextFactory = DefaultOpenSSLContextFactory(keyFN.encode("utf-8", "replace"),
certFN.encode("utf-8", "replace"))
contextFactory = DefaultOpenSSLContextFactory(keyFN.encode("utf-8", "replace"), certFN.encode("utf-8", "replace"))
bot = IRCBotFactory(net=None, num=num, relayCommands=relayCommands, user=user, stage2=stage2)
host, port = getRelay(num)
rct = reactor.connectSSL(host,
port,
bot, contextFactory)
rct = reactor.connectSSL(host, port, bot, contextFactory)
# Copied from the Twisted source so we can fix a bug
def parsemsg(s):
@ -50,21 +54,22 @@ def parsemsg(s):
@return: A tuple of (prefix, command, args).
@rtype: L{tuple}
"""
prefix = ''
prefix = ""
trailing = []
if not s:
raise IRCBadMessage("Empty line.")
if s[0:1] == ':':
prefix, s = s[1:].split(' ', 1)
if s.find(' :') != -1:
s, trailing = s.split(' :', 1)
args = s.split(' ') # Twisted bug fixed by adding an argument to split()
if s[0:1] == ":":
prefix, s = s[1:].split(" ", 1)
if s.find(" :") != -1:
s, trailing = s.split(" :", 1)
args = s.split(" ") # Twisted bug fixed by adding an argument to split()
args.append(trailing)
else:
args = s.split(' ') # And again
args = s.split(" ") # And again
command = args.pop(0)
return prefix, command, args
class IRCRelay(IRCClient):
def __init__(self, num, relayCommands, user, stage2):
self.isconnected = False
@ -114,7 +119,12 @@ class IRCRelay(IRCClient):
increment = 0.8
for i in self.relayCommands.keys():
for x in self.relayCommands[i]:
reactor.callLater(sleeptime, self.msg, main.config["Tweaks"]["ZNC"]["Prefix"]+i, x)
reactor.callLater(
sleeptime,
self.msg,
main.config["Tweaks"]["ZNC"]["Prefix"] + i,
x,
)
sleeptime += increment
increment += 0.8
if not self.stage2 == None:
@ -122,6 +132,7 @@ class IRCRelay(IRCClient):
reactor.callLater(sleeptime + 5, self.transport.loseConnection)
return
class IRCBot(IRCClient):
def __init__(self, net, num):
self.isconnected = False
@ -373,7 +384,16 @@ class IRCBot(IRCClient):
return
n = self._tempWho[channel][1]
n.append([nick, nick, host, server, status, realname])
self.event(type="who", nick=nick, ident=ident, host=host, realname=realname, channel=channel, server=server, status=status)
self.event(
type="who",
nick=nick,
ident=ident,
host=host,
realname=realname,
channel=channel,
server=server,
status=status,
)
def irc_RPL_ENDOFWHO(self, prefix, params):
channel = params[1]
@ -390,7 +410,10 @@ class IRCBot(IRCClient):
def sanit(self, data):
if len(data) >= 1:
if data[0] in self.prefix.keys():
return (self.prefix[data[0]], data[1:]) # would use a set but it's possible these are the same
return (
self.prefix[data[0]],
data[1:],
) # would use a set but it's possible these are the same
return (None, data)
else:
return (None, False)
@ -405,7 +428,7 @@ class IRCBot(IRCClient):
def irc_RPL_NAMREPLY(self, prefix, params):
channel = params[2]
nicklist = params[3].split(' ')
nicklist = params[3].split(" ")
if channel not in self._tempNames:
return
n = self._tempNames[channel][1]
@ -532,7 +555,9 @@ class IRCBot(IRCClient):
self.checkChannels()
def seed_chanlimit(self, chanlimit):
if not main.network[self.net].relays[self.num]["registered"]: #TODO: add check for register request sent, only send it once
if not main.network[self.net].relays[self.num][
"registered"
]: # TODO: add check for register request sent, only send it once
if main.config["AutoReg"]:
self._regAttempt = reactor.callLater(5, regproc.registerAccount, self.net, self.num)
# regproc.registerAccount(self.net, self.num)
@ -585,7 +610,7 @@ class IRCBot(IRCClient):
# the hostname and other useful information in the functions
# that these call by default
def irc_JOIN(self, prefix, params):
nick = prefix.split('!')[0]
nick = prefix.split("!")[0]
channel = params[-1]
if nick == self.nickname:
self.joined(channel)
@ -593,7 +618,7 @@ class IRCBot(IRCClient):
self.userJoined(prefix, channel)
def irc_PART(self, prefix, params):
nick = prefix.split('!')[0]
nick = prefix.split("!")[0]
channel = params[0]
if len(params) >= 2:
message = params[1]
@ -605,11 +630,11 @@ class IRCBot(IRCClient):
self.userLeft(prefix, channel, message)
def irc_QUIT(self, prefix, params):
nick = prefix.split('!')[0]
nick = prefix.split("!")[0]
self.userQuit(prefix, params[0])
def irc_NICK(self, prefix, params):
nick = prefix.split('!', 1)[0]
nick = prefix.split("!", 1)[0]
if nick == self.nickname:
self.nickChanged(prefix, params[0])
else:
@ -626,6 +651,7 @@ class IRCBot(IRCClient):
channel = params[0]
newtopic = params[1]
self.topicUpdated(prefix, channel, newtopic)
# End of Twisted hackery
def regPing(self, negativepass=None):
@ -664,7 +690,15 @@ class IRCBot(IRCClient):
def signedOn(self):
log("signed on: %s - %i" % (self.net, self.num))
ctime = str(datetime.now().isoformat())
sendRelayNotification({"type": "conn", "net": self.net, "num": self.num, "status": "signedon", "time": ctime})
sendRelayNotification(
{
"type": "conn",
"net": self.net,
"num": self.num,
"status": "signedon",
"time": ctime,
}
)
if not self.authenticated:
reactor.callLater(10, self.regPing)
@ -690,6 +724,7 @@ class IRCBot(IRCClient):
userinfo.delChannels(self.net, [channel]) # < we do not need to deduplicate this
# log("Can no longer cover %s, removing records" % channel)# as it will only be matched once --
# other bots have different nicknames so
def left(self, user, channel, message): # even if they saw it, they wouldn't react
self.event(type="part", muser=user, channel=channel, msg=message)
self.botLeft(channel)
@ -737,7 +772,15 @@ class IRCBot(IRCClient):
argList = list(args)
modeList = [i for i in modes]
for a, m in zip(argList, modeList):
self.event(type="mode", muser=user, channel=channel, mode=m, status=toset, modearg=a)
self.event(
type="mode",
muser=user,
channel=channel,
mode=m,
status=toset,
modearg=a,
)
class IRCBotFactory(ReconnectingClientFactory):
def __init__(self, net, num=None, relayCommands=None, user=None, stage2=None):
@ -781,7 +824,16 @@ class IRCBotFactory(ReconnectingClientFactory):
log("%s - %i: connection lost: %s" % (self.net, self.num, error))
sendAll("%s - %i: connection lost: %s" % (self.net, self.num, error))
ctime = str(datetime.now().isoformat())
sendRelayNotification({"type": "conn", "net": self.net, "num": self.num, "status": "lost", "message": error, "time": ctime})
sendRelayNotification(
{
"type": "conn",
"net": self.net,
"num": self.num,
"status": "lost",
"message": error,
"time": ctime,
}
)
self.retry(connector)
# ReconnectingClientFactory.clientConnectionLost(self, connector, reason)
@ -795,7 +847,15 @@ class IRCBotFactory(ReconnectingClientFactory):
if not self.relay:
sendAll("%s - %s: connection failed: %s" % (self.net, self.num, error))
ctime = str(datetime.now().isoformat())
sendRelayNotification({"type": "conn", "net": self.net, "num": self.num, "status": "failed", "message": error, "time": ctime})
sendRelayNotification(
{
"type": "conn",
"net": self.net,
"num": self.num,
"status": "failed",
"message": error,
"time": ctime,
}
)
self.retry(connector)
# ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)

View File

@ -6,11 +6,20 @@ import main
from utils.logging.log import *
logger = None
def init_logstash():
global logger
logger = logging.getLogger('ingest')
logger = logging.getLogger("ingest")
logger.setLevel(logging.INFO)
logger.addHandler(logstash.TCPLogstashHandler(main.config["Logstash"]["Host"], int(main.config["Logstash"]["Port"]), version=1))
logger.addHandler(
logstash.TCPLogstashHandler(
main.config["Logstash"]["Host"],
int(main.config["Logstash"]["Port"]),
version=1,
)
)
def sendLogstashNotification(text):
if not logger == None:

View File

@ -2,6 +2,7 @@ import main
from utils.logging.log import *
from utils.logging.send import *
def parseCommand(addr, authed, data):
# call command modules with: (addr, authed, data, spl, success, failure, info, incUsage, length)
spl = data.split()

View File

@ -5,7 +5,25 @@ from copy import deepcopy
import main
from utils.logging.log import *
validTypes = ["msg", "notice", "action", "who", "part", "join", "kick", "quit", "nick", "topic", "mode", "conn", "znc", "query", "self", "highlight"]
validTypes = [
"msg",
"notice",
"action",
"who",
"part",
"join",
"kick",
"quit",
"nick",
"topic",
"mode",
"conn",
"znc",
"query",
"self",
"highlight",
]
class Relay(Protocol):
def __init__(self, addr):
@ -118,6 +136,7 @@ class Relay(Protocol):
else:
warn("Tried to remove a non-existant relay connection.")
class RelayFactory(Factory):
def buildProtocol(self, addr):
entry = Relay(addr)
@ -131,6 +150,7 @@ class RelayFactory(Factory):
else:
return
def sendRelayNotification(cast):
for i in main.relayConnections.keys():
if main.relayConnections[i].authed:

View File

@ -4,6 +4,7 @@ from utils.logging.log import *
from core.parser import parseCommand
class Server(Protocol):
def __init__(self, addr):
self.addr = addr
@ -39,6 +40,7 @@ class Server(Protocol):
else:
warn("Tried to remove a non-existant connection.")
class ServerFactory(Factory):
def buildProtocol(self, addr):
entry = Server(addr)

14
main.py
View File

@ -7,10 +7,7 @@ from os import urandom
from utils.logging.log import *
# List of errors ZNC can give us
ZNCErrors = ["Error:",
"Unable to load",
"does not exist",
"doesn't exist"]
ZNCErrors = ["Error:", "Unable to load", "does not exist", "doesn't exist"]
configPath = "conf/"
certPath = "cert/"
@ -25,9 +22,8 @@ filemap = {
"alias": ["alias.json", "provisioned alias data", "json"],
"irc": ["irc.json", "IRC network definitions", "json"],
"blacklist": ["blacklist.json", "IRC channel blacklist", "json"],
# Binary (pickle) configs
"network": ["network.dat", "network list", "pickle"]
"network": ["network.dat", "network list", "pickle"],
}
# Connections to the plain-text interface
@ -70,6 +66,7 @@ def liveNets():
networks.add("".join([x for x in i if not x in digits]))
return networks
def saveConf(var):
if filemap[var][2] == "json":
with open(configPath + filemap[var][0], "w") as f:
@ -80,6 +77,7 @@ def saveConf(var):
else:
raise Exception("invalid format")
def loadConf(var):
if filemap[var][2] == "json":
with open(configPath + filemap[var][0], "r") as f:
@ -99,14 +97,14 @@ def loadConf(var):
else:
raise Exception("invalid format")
def initConf():
for i in filemap.keys():
loadConf(i)
def initMain():
global r, g
initConf()
r = StrictRedis(unix_socket_path=config["RedisSocket"], db=0) # Ephemeral - flushed on quit
g = StrictRedis(unix_socket_path=config["RedisSocket"], db=1) # Persistent

View File

@ -2,9 +2,11 @@ import main
import random
import re
def generate_password():
return "".join([chr(random.randint(0, 74) + 48) for i in range(32)])
def generate_alias():
nick = random.choice(main.aliasdata["stubs"])
rand = random.randint(1, 2)
@ -63,4 +65,10 @@ def generate_alias():
if rand == 3 or rand == 4:
realname = realname.capitalize()
return {"nick": nick, "altnick": altnick, "ident": ident, "realname": realname, "emails": []}
return {
"nick": nick,
"altnick": altnick,
"ident": ident,
"realname": realname,
"emails": [],
}

View File

@ -6,6 +6,7 @@ from math import ceil
import modules.provision
from twisted.internet.threads import deferToThread
def allRelaysActive(net):
relayNum = len(main.network[net].relays.keys())
existNum = 0
@ -18,6 +19,7 @@ def allRelaysActive(net):
return True
return False
def getChanFree(net, new):
chanfree = {}
chanlimits = set()
@ -32,6 +34,7 @@ def getChanFree(net, new):
return False
return (chanfree, chanlimits.pop())
def emptyChanAllocate(net, flist, relay, new):
chanfree = getChanFree(net, new)
if not chanfree:
@ -56,6 +59,7 @@ def emptyChanAllocate(net, flist, relay, new):
allocated[i] = [flist.pop()]
return allocated
def populateChans(net, clist, relay, new):
# divided = array_split(clist, relay)
allocated = emptyChanAllocate(net, clist, relay, new)
@ -67,12 +71,14 @@ def populateChans(net, clist, relay, new):
else:
main.TempChan[net] = {i: allocated[i]}
def notifyJoin(net):
for i in main.network[net].relays.keys():
name = net + str(i)
if name in main.IRCPool.keys():
main.IRCPool[name].checkChannels()
def minifyChans(net, listinfo):
if not allRelaysActive(net):
error("All relays for %s are not active, cannot minify list" % net)
@ -88,6 +94,7 @@ def minifyChans(net, listinfo):
return False
return listinfo
def keepChannels(net, listinfo, mean, sigrelay, relay):
listinfo = minifyChans(net, listinfo)
if not listinfo:
@ -111,6 +118,7 @@ def keepChannels(net, listinfo, mean, sigrelay, relay):
populateChans(net, siglist, sigrelay, newNums)
notifyJoin(net)
def joinSingle(net, channel):
if allRelaysActive(net):
chanfree = getChanFree(net, [])
@ -122,6 +130,7 @@ def joinSingle(net, channel):
error("All relays for %s are not active" % net)
return False
def nukeNetwork(net):
# purgeRecords(net)
# p = main.g.pipeline()
@ -129,6 +138,7 @@ def nukeNetwork(net):
# p.delete("list."+net)
# p.execute()
# def nukeNetwork(net):
# deferToThread(_nukeNetwork, net)
@ -183,6 +193,6 @@ def _initialList(net, num, listinfo, chanlimit):
debug("List parsing completed on %s" % net)
keepChannels(net, listinfo, mean, sigrelay, relay)
def initialList(net, num, listinfo, chanlimit):
deferToThread(_initialList, net, num, deepcopy(listinfo), chanlimit)

View File

@ -1,6 +1,7 @@
import main
from twisted.internet.task import LoopingCall
def event(name, eventType):
if not "local" in main.counters.keys():
main.counters["local"] = {}
@ -18,6 +19,7 @@ def event(name, eventType):
main.counters["global"][eventType] += 1
main.runningSample += 1
def getEvents(name=None):
if name == None:
if "global" in main.counters.keys():
@ -30,10 +32,12 @@ def getEvents(name=None):
else:
return None
def takeSample():
main.lastMinuteSample = main.runningSample
main.runningSample = 0
def setupCounterLoop():
lc = LoopingCall(takeSample)
lc.start(60)

View File

@ -8,9 +8,25 @@ from modules import userinfo
from modules import regproc
from utils.dedup import dedup
order = ["type", "net", "num", "channel", "msg", "nick",
"ident", "host", "mtype", "user", "mode", "modearg",
"realname", "server", "status", "time"]
order = [
"type",
"net",
"num",
"channel",
"msg",
"nick",
"ident",
"host",
"mtype",
"user",
"mode",
"modearg",
"realname",
"server",
"status",
"time",
]
def parsemeta(numName, c):
if not "channel" in c.keys():
@ -24,7 +40,13 @@ def parsemeta(numName, c):
# if c["type"] == "mode":
# userinfo.updateMode(c)
elif c["type"] == "nick":
userinfo.renameUser(c["net"], c["nick"], c["muser"], c["user"], c["user"]+"!"+c["ident"]+"@"+c["host"])
userinfo.renameUser(
c["net"],
c["nick"],
c["muser"],
c["user"],
c["user"] + "!" + c["ident"] + "@" + c["host"],
)
elif c["type"] == "kick":
userinfo.editUser(c["net"], c["muser"])
userinfo.delUserByNick(c["net"], c["channel"], c["user"])
@ -37,7 +59,14 @@ def parsemeta(numName, c):
if "mtype" in c.keys():
if c["mtype"] == "nick":
userinfo.renameUser(c["net"], c["nick"], c["muser"], c["user"], c["user"]+"!"+c["ident"]+"@"+c["host"])
userinfo.renameUser(
c["net"],
c["nick"],
c["muser"],
c["user"],
c["user"] + "!" + c["ident"] + "@" + c["host"],
)
def event(numName, c): # yes I'm using a short variable because otherwise it goes off the screen
if dedup(numName, c):

View File

@ -10,6 +10,7 @@ import main
from utils.logging.log import *
from utils.get import getRelay
class Network:
def __init__(self, net, host, port, security, auth):
self.net = net
@ -37,7 +38,7 @@ class Network:
"enabled": main.config["ConnectOnCreate"],
"net": self.net,
"id": num,
"registered": registered
"registered": registered,
}
password = alias.generate_password()
if not num in main.alias.keys():

View File

@ -4,6 +4,7 @@ from utils.logging.log import *
from twisted.internet import reactor
import modules.regproc
def provisionUserNetworkData(num, nick, altnick, ident, realname, network, host, port, security, auth, password):
commands = {}
stage2commands = {}
@ -30,8 +31,8 @@ def provisionUserNetworkData(num, nick, altnick, ident, realname, network, host,
if "setmode" in inst.keys():
stage2commands["status"].append("LoadMod perform")
# stage2commands["perform"].append("add mode %nick% +"+inst["setmode"])
deliverRelayCommands(num, commands,
stage2=[[user+"/"+network, stage2commands]])
deliverRelayCommands(num, commands, stage2=[[user + "/" + network, stage2commands]])
def provisionAuthenticationData(num, nick, network, security, auth, password):
commands = {}
@ -56,15 +57,20 @@ def provisionAuthenticationData(num, nick, network, security, auth, password):
def provisionRelay(num, network): # provision user and network data
aliasObj = main.alias[num]
alias = aliasObj["nick"]
provisionUserNetworkData(num, *aliasObj.values(), network,
provisionUserNetworkData(
num,
*aliasObj.values(),
network,
main.network[network].host,
main.network[network].port,
main.network[network].security,
main.network[network].auth,
main.network[network].aliases[num]["password"])
main.network[network].aliases[num]["password"]
)
if main.config["ConnectOnCreate"]:
reactor.callLater(10, main.network[network].start_bot, num)
def provisionMultipleRelays(net, relaysNeeded):
numsProvisioned = []
for i in range(relaysNeeded):
@ -73,4 +79,3 @@ def provisionMultipleRelays(net, relaysNeeded):
provisionRelay(num, net)
main.saveConf("network")
return numsProvisioned

View File

@ -4,6 +4,7 @@ from utils.logging.log import *
from utils.logging.debug import *
from copy import deepcopy
def needToRegister(net):
inst = selectInst(net)
if "register" in inst.keys():
@ -12,6 +13,7 @@ def needToRegister(net):
else:
return False
def selectInst(net):
if net in main.irc.keys():
inst = deepcopy(main.irc[net])
@ -22,6 +24,7 @@ def selectInst(net):
inst = main.irc["_"]
return inst
def substitute(net, num, token=None):
inst = selectInst(net)
alias = main.alias[num]
@ -39,6 +42,7 @@ def substitute(net, num, token=None):
inst[i] = inst[i].replace("{token}", token)
return inst
def registerAccount(net, num):
debug("Attempting to register: %s - %i" % (net, num))
sinst = substitute(net, num)
@ -48,12 +52,14 @@ def registerAccount(net, num):
name = net + str(num)
main.IRCPool[name].msg(sinst["entity"], sinst["registermsg"])
def confirmAccount(net, num, token):
sinst = substitute(net, num, token=token)
name = net + str(num)
main.IRCPool[name].msg(sinst["entity"], sinst["confirm"])
enableAuthentication(net, num)
def confirmRegistration(net, num, negativepass=None):
obj = main.network[net]
name = net + str(num)
@ -75,6 +81,7 @@ def confirmRegistration(net, num, negativepass=None):
obj.relays[num]["registered"] = True
main.saveConf("network")
def enableAuthentication(net, num):
obj = main.network[net]
nick = main.alias[num]["nick"]
@ -87,6 +94,7 @@ def enableAuthentication(net, num):
if selectInst(net)["check"] == False:
confirmRegistration(net, num)
def registerTest(c):
sinst = substitute(c["net"], c["num"])
name = c["net"] + str(c["num"])

View File

@ -6,12 +6,14 @@ from utils.logging.log import *
from utils.logging.debug import debug, trace
from utils.parsing import parsen
def getWhoSingle(name, query):
result = main.r.sscan("live.who." + name, 0, query, count=999999)
if result[1] == []:
return None
return (i.decode() for i in result[1])
def getWho(query):
result = {}
for i in main.network.keys():
@ -20,6 +22,7 @@ def getWho(query):
result[i] = f
return result
def getChansSingle(name, nick):
nick = ["live.chan." + name + "." + i for i in nick]
result = main.r.sinter(*nick)
@ -27,6 +30,7 @@ def getChansSingle(name, nick):
return None
return (i.decode() for i in result)
def getChanList(name, nick):
chanspace = "live.chan." + name + "." + nick
result = main.r.smembers(chanspace)
@ -34,6 +38,7 @@ def getChanList(name, nick):
return None
return (i.decode() for i in result)
def getChans(nick):
result = {}
for i in main.network.keys():
@ -42,6 +47,7 @@ def getChans(nick):
result[i] = f
return result
def getUsersSingle(name, nick):
nick = ("live.who." + name + "." + i for i in nick)
result = main.r.sinter(*nick)
@ -49,6 +55,7 @@ def getUsersSingle(name, nick):
return None
return (i.decode() for i in result)
def getUsers(nick):
result = {}
for i in main.network.keys():
@ -57,15 +64,18 @@ def getUsers(nick):
result[i] = f
return result
def getNumWhoEntries(name):
return main.r.scard("live.who." + name)
def getNumTotalWhoEntries():
total = 0
for i in main.network.keys():
total += getNumWhoEntries(i)
return total
def getNamespace(name, channel, nick):
gnamespace = "live.who.%s" % name
namespace = "live.who.%s.%s" % (name, channel)
@ -73,6 +83,7 @@ def getNamespace(name, channel, nick):
mapspace = "live.map.%s" % name
return (gnamespace, namespace, chanspace, mapspace)
def _initialUsers(name, channel, users):
gnamespace = "live.who.%s" % name
mapspace = "live.map.%s" % name
@ -83,11 +94,13 @@ def _initialUsers(name, channel, users):
p.sadd(gnamespace, user)
p.execute()
def initialUsers(name, channel, users):
trace("Initialising WHO records for %s on %s" % (channel, name))
d = deferToThread(_initialUsers, name, channel, users)
# d.addCallback(testCallback)
def _initialNames(name, channel, names):
namespace = "live.who.%s.%s" % (name, channel)
p = main.r.pipeline()
@ -98,11 +111,13 @@ def _initialNames(name, channel, names):
p.hset("live.prefix." + name + "." + channel, nick, mode)
p.execute()
def initialNames(name, channel, names):
trace("Initialising NAMES records for %s on %s" % (channel, name))
d = deferToThread(_initialNames, name, channel, names)
# d.addCallback(testCallback)
def editUser(name, user):
gnamespace = "live.who.%s" % name
mapspace = "live.map.%s" % name
@ -112,6 +127,7 @@ def editUser(name, user):
p.hset(mapspace, parsed[0], user) # add nick -> user mapping
p.execute()
def addUser(name, channel, nick, user):
gnamespace, namespace, chanspace, mapspace = getNamespace(name, channel, nick)
p = main.r.pipeline()
@ -121,6 +137,7 @@ def addUser(name, channel, nick, user):
p.hset(mapspace, nick, user)
p.execute()
def delUser(name, channel, nick, user):
gnamespace, namespace, chanspace, mapspace = getNamespace(name, channel, nick)
p = main.r.pipeline()
@ -138,6 +155,7 @@ def delUser(name, channel, nick, user):
p.srem(chanspace, channel) # keep up - remove the channel from their list
p.execute()
def escape(text):
chars = ["[", "]", "^", "-", "*", "?"]
text = text.replace("\\", "\\\\")
@ -145,6 +163,7 @@ def escape(text):
text = text.replace(i, "\\" + i)
return text
def getUserByNick(name, nick):
gnamespace = "live.who.%s" % name # "nick": "nick!ident@host"
mapspace = "live.map.%s" % name
@ -166,6 +185,7 @@ def getUserByNick(name, nick):
warn("Auxiliary lookup failed: %s on %s" % (nick, gnamespace))
return False
def renameUser(name, oldnick, olduser, newnick, newuser):
gnamespace = "live.who.%s" % name
chanspace = "live.chan.%s.%s" % (name, oldnick)
@ -190,12 +210,14 @@ def renameUser(name, oldnick, olduser, newnick, newuser):
warn("Key doesn't exist: %s" % chanspace)
p.execute()
def delUserByNick(name, channel, nick): # kick
user = getUserByNick(name, nick)
if not user:
return
delUser(name, channel, nick, user)
def delUserByNetwork(name, nick, user): # quit
gnamespace = "live.who.%s" % name
chanspace = "live.chan.%s.%s" % (name, nick)
@ -210,6 +232,7 @@ def delUserByNetwork(name, nick, user): # quit
p.hdel(mapspace, nick)
p.execute()
def _delChannels(net, channels):
gnamespace = "live.who.%s" % net
mapspace = "live.map.%s" % net
@ -234,6 +257,7 @@ def _delChannels(net, channels):
p.delete("live.prefix." + net + "." + channel)
p.execute()
def delChannels(net, channels): # we have left a channel
trace("Purging channel %s for %s" % (", ".join(channels), net))
d = deferToThread(_delChannels, net, channels)

View File

@ -1,3 +1,4 @@
pre-commit
twisted
pyOpenSSL
redis

View File

@ -3,17 +3,21 @@ from twisted.internet import reactor
from twisted.internet.ssl import DefaultOpenSSLContextFactory
import sys
from signal import signal, SIGINT
# from twisted.python import log
# from sys import stdout
# log.startLogging(stdout)
from sys import stdout, stderr # Import again because we want to override
from codecs import getwriter # fix printing odd shit to the terminal
stdout = getwriter("utf8")(stdout) # this is a generic fix but we all know
stderr = getwriter("utf8")(stderr) # it's just for the retards on Rizon using
# unicode quit messages for no reason
import main
main.initMain()
from utils.cleanup import handler
signal(SIGINT, handler) # Handle Ctrl-C and run the cleanup routine
if "--debug" in sys.argv: # yes really
main.config["Debug"] = True
@ -24,25 +28,54 @@ from utils.loaders.command_loader import loadCommands
from core.server import Server, ServerFactory
from core.relay import Relay, RelayFactory
import modules.counters
loadCommands()
import core.logstash
core.logstash.init_logstash()
if __name__ == "__main__":
listener = ServerFactory()
if main.config["Listener"]["UseSSL"] == True:
reactor.listenSSL(main.config["Listener"]["Port"], listener, DefaultOpenSSLContextFactory(main.certPath+main.config["Key"], main.certPath+main.config["Certificate"]), interface=main.config["Listener"]["Address"])
reactor.listenSSL(
main.config["Listener"]["Port"],
listener,
DefaultOpenSSLContextFactory(
main.certPath + main.config["Key"],
main.certPath + main.config["Certificate"],
),
interface=main.config["Listener"]["Address"],
)
log("Threshold running with SSL on %s:%s" % (main.config["Listener"]["Address"], main.config["Listener"]["Port"]))
else:
reactor.listenTCP(main.config["Listener"]["Port"], listener, interface=main.config["Listener"]["Address"])
reactor.listenTCP(
main.config["Listener"]["Port"],
listener,
interface=main.config["Listener"]["Address"],
)
log("Threshold running on %s:%s" % (main.config["Listener"]["Address"], main.config["Listener"]["Port"]))
if main.config["RelayAPI"]["Enabled"]:
relay = RelayFactory()
if main.config["RelayAPI"]["UseSSL"] == True:
reactor.listenSSL(main.config["RelayAPI"]["Port"], relay, DefaultOpenSSLContextFactory(main.certPath+main.config["Key"], main.certPath+main.config["Certificate"]), interface=main.config["RelayAPI"]["Address"])
log("Threshold relay running with SSL on %s:%s" % (main.config["RelayAPI"]["Address"], main.config["RelayAPI"]["Port"]))
reactor.listenSSL(
main.config["RelayAPI"]["Port"],
relay,
DefaultOpenSSLContextFactory(
main.certPath + main.config["Key"],
main.certPath + main.config["Certificate"],
),
interface=main.config["RelayAPI"]["Address"],
)
log(
"Threshold relay running with SSL on %s:%s"
% (main.config["RelayAPI"]["Address"], main.config["RelayAPI"]["Port"])
)
else:
reactor.listenTCP(main.config["RelayAPI"]["Port"], relay, interface=main.config["RelayAPI"]["Address"])
reactor.listenTCP(
main.config["RelayAPI"]["Port"],
relay,
interface=main.config["RelayAPI"]["Address"],
)
log("Threshold relay running on %s:%s" % (main.config["RelayAPI"]["Address"], main.config["RelayAPI"]["Port"]))
for net in main.network.keys():
main.network[net].start_bots()

View File

@ -4,10 +4,12 @@ from utils.logging.debug import debug
from utils.logging.log import *
import sys
def handler(sig, frame):
log("Received SIGINT, cleaning up")
cleanup()
def cleanup():
debug("Flushing Redis database")
main.r.flushdb()

View File

@ -5,6 +5,7 @@ from json import dumps
import main
from utils.logging.debug import debug
def dedup(numName, b):
c = deepcopy(b)
if "time" in c.keys():

View File

@ -1,5 +1,6 @@
import main
def getRelay(num):
host = main.config["Relay"]["Host"].replace("x", str(num))
port = int(str(main.config["Relay"]["Port"]).replace("x", str(num).zfill(2)))

View File

@ -6,13 +6,14 @@ import commands
from main import CommandMap
def loadCommands(allowDup=False):
for filename in listdir("commands"):
if filename.endswith(".py") and filename != "__init__.py":
commandName = filename[0:-3]
className = commandName.capitalize() + "Command"
try:
module = __import__('commands.%s' % commandName)
module = __import__("commands.%s" % commandName)
if not commandName in CommandMap:
CommandMap[commandName] = getattr(getattr(module, commandName), className)
debug("Registered command: %s" % commandName)

View File

@ -8,6 +8,7 @@ import commands
from main import CommandMap
def loadSingle(commandName):
if commandName + ".py" in listdir("commands"):
className = commandName.capitalize() + "Command"
@ -17,7 +18,7 @@ def loadSingle(commandName):
CommandMap[commandName] = getattr(sys.modules["commands." + commandName], className)
debug("Reloaded command: %s" % commandName)
return "RELOAD"
module = __import__('commands.%s' % commandName)
module = __import__("commands.%s" % commandName)
CommandMap[commandName] = getattr(getattr(module, commandName), className)
debug("Registered command: %s" % commandName)
return True

View File

@ -1,10 +1,12 @@
import main
# we need a seperate module to log.py, as log.py is imported by main.py, and we need to access main
# to read the setting
def debug(*data):
if main.config["Debug"]:
print("[DEBUG]", *data)
def trace(*data):
if main.config["Trace"]:
print("[TRACE]", *data)

View File

@ -1,8 +1,10 @@
def log(*data):
print("[LOG]", *data)
def warn(*data):
print("[WARNING]", *data)
def error(*data):
print("[ERROR]", *data)

View File

@ -1,29 +1,36 @@
import main
def sendData(addr, data):
main.connections[addr].send(data)
def sendWithPrefix(addr, data, prefix):
toSend = ""
for i in data.split("\n"):
toSend += prefix + " " + i + "\n"
sendData(addr, toSend)
def sendSuccess(addr, data):
sendWithPrefix(addr, data, "[y]")
def sendFailure(addr, data):
sendWithPrefix(addr, data, "[n]")
def sendInfo(addr, data):
sendWithPrefix(addr, data, "[i]")
def sendAll(data):
for i in main.connections:
if main.connections[i].authed:
main.connections[i].send(data)
return
def incorrectUsage(addr, mode):
if mode == None:
sendFailure(addr, "Incorrect usage")