From ff1ee6390056775aac0afb46bc115d7c1c27ba03 Mon Sep 17 00:00:00 2001 From: Mark Veidemanis Date: Thu, 21 Jul 2022 13:39:41 +0100 Subject: [PATCH] Reformat code with pre-commit --- commands/admall.py | 1 + commands/alias.py | 3 +- commands/all.py | 5 +- commands/allc.py | 13 +- commands/authcheck.py | 1 + commands/auto.py | 1 + commands/blacklist.py | 1 + commands/chans.py | 3 +- commands/cmd.py | 1 + commands/confirm.py | 1 + commands/disable.py | 5 +- commands/dist.py | 1 + commands/email.py | 3 +- commands/enable.py | 5 +- commands/exec.py | 1 + commands/help.py | 1 + commands/join.py | 9 +- commands/list.py | 9 +- commands/load.py | 1 + commands/loadmod.py | 1 + commands/logout.py | 1 + commands/mod.py | 3 +- commands/msg.py | 7 +- commands/network.py | 3 +- commands/part.py | 7 +- commands/pass.py | 1 + commands/pending.py | 1 + commands/recheckauth.py | 1 + commands/reg.py | 1 + commands/relay.py | 1 + commands/save.py | 1 + commands/stats.py | 1 + commands/swho.py | 1 + commands/token.py | 12 +- commands/users.py | 3 +- commands/who.py | 3 +- core/bot.py | 224 ++++++++++++++++++++------------ core/logstash.py | 13 +- core/parser.py | 3 +- core/relay.py | 24 +++- core/server.py | 4 +- main.py | 28 ++-- modules/alias.py | 14 +- modules/chankeep.py | 66 ++++++---- modules/counters.py | 4 + modules/monitor.py | 45 +++++-- modules/network.py | 15 ++- modules/provision.py | 35 ++--- modules/regproc.py | 36 +++-- modules/userinfo.py | 102 +++++++++------ requirements.txt | 1 + threshold | 59 +++++++-- utils/cleanup.py | 6 +- utils/dedup.py | 7 +- utils/get.py | 1 + utils/loaders/command_loader.py | 5 +- utils/loaders/single_loader.py | 11 +- utils/logging/debug.py | 2 + utils/logging/log.py | 2 + utils/logging/send.py | 7 + 60 files changed, 548 insertions(+), 279 deletions(-) diff --git a/commands/admall.py b/commands/admall.py index cbbf854..8d74545 100644 --- a/commands/admall.py +++ b/commands/admall.py @@ -1,6 +1,7 @@ import main from core.bot import deliverRelayCommands + class AdmallCommand: def __init__(self, *args): self.admall(*args) diff --git a/commands/alias.py b/commands/alias.py index baccad5..d04cfdf 100644 --- a/commands/alias.py +++ b/commands/alias.py @@ -2,6 +2,7 @@ import main from yaml import dump from modules import alias + class AliasCommand: def __init__(self, *args): self.alias(*args) @@ -21,7 +22,7 @@ class AliasCommand: if len(main.alias.keys()) == 0: nextNum = 1 else: - nextNum = max(main.alias.keys())+1 + nextNum = max(main.alias.keys()) + 1 main.alias[nextNum] = alias.generate_alias() success("Generated new alias: %i" % nextNum) main.saveConf("alias") diff --git a/commands/all.py b/commands/all.py index e59a9fd..a2994e9 100644 --- a/commands/all.py +++ b/commands/all.py @@ -1,6 +1,7 @@ import main from core.bot import deliverRelayCommands + class AllCommand: def __init__(self, *args): self.all(*args) @@ -14,8 +15,8 @@ class AllCommand: net = main.network[i].relays[x]["net"] alias = main.alias[x]["nick"] commands = {spl[1]: [" ".join(spl[2:])]} - success("Sending commands to relay %s as user %s" % (num, alias+"/"+net)) - deliverRelayCommands(num, commands, user=alias+"/"+net) + success("Sending commands to relay %s as user %s" % (num, alias + "/" + net)) + deliverRelayCommands(num, commands, user=alias + "/" + net) return else: incUsage("all") diff --git a/commands/allc.py b/commands/allc.py index 5d1d7cb..7a7b5fd 100644 --- a/commands/allc.py +++ b/commands/allc.py @@ -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 @@ -30,8 +33,8 @@ class AllcCommand: num = i[1] alias = main.alias[num]["nick"] commands = {spl[3]: [" ".join(spl[4:])]} - success("Sending commands to relay %i as user %s" % (num, alias+"/"+net)) - deliverRelayCommands(num, commands, user=alias+"/"+net) + success("Sending commands to relay %i as user %s" % (num, alias + "/" + net)) + deliverRelayCommands(num, commands, user=alias + "/" + net) return else: incUsage("allc") diff --git a/commands/authcheck.py b/commands/authcheck.py index 120adce..26cc14e 100644 --- a/commands/authcheck.py +++ b/commands/authcheck.py @@ -1,5 +1,6 @@ import main + class AuthcheckCommand: def __init__(self, *args): self.authcheck(*args) diff --git a/commands/auto.py b/commands/auto.py index 29bd3a8..ffc6df5 100644 --- a/commands/auto.py +++ b/commands/auto.py @@ -1,6 +1,7 @@ import main from modules import provision + class AutoCommand: def __init__(self, *args): self.auto(*args) diff --git a/commands/blacklist.py b/commands/blacklist.py index 89d25c6..42684a6 100644 --- a/commands/blacklist.py +++ b/commands/blacklist.py @@ -1,6 +1,7 @@ import main from yaml import dump + class BlacklistCommand: def __init__(self, *args): self.blacklist(*args) diff --git a/commands/chans.py b/commands/chans.py index f92482b..1ccf710 100644 --- a/commands/chans.py +++ b/commands/chans.py @@ -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) diff --git a/commands/cmd.py b/commands/cmd.py index 466b197..babdb2d 100644 --- a/commands/cmd.py +++ b/commands/cmd.py @@ -1,6 +1,7 @@ import main from core.bot import deliverRelayCommands + class CmdCommand: def __init__(self, *args): self.cmd(*args) diff --git a/commands/confirm.py b/commands/confirm.py index c7b1552..86d657c 100644 --- a/commands/confirm.py +++ b/commands/confirm.py @@ -1,6 +1,7 @@ import main from modules import regproc + class ConfirmCommand: def __init__(self, *args): self.confirm(*args) diff --git a/commands/disable.py b/commands/disable.py index 62b42df..9c52234 100644 --- a/commands/disable.py +++ b/commands/disable.py @@ -1,6 +1,7 @@ import main from core.bot import deliverRelayCommands + class DisableCommand: def __init__(self, *args): self.disable(*args) @@ -15,7 +16,7 @@ class DisableCommand: failure("Must be a number, not %s" % spl[2]) return relayNum = int(spl[2]) - name = spl[1]+spl[2] + name = spl[1] + spl[2] if not spl[1] in main.IRCPool.keys(): info("Note - instance not running, proceeding anyway") if not relayNum in main.network[spl[1]].relays.keys(): @@ -26,7 +27,7 @@ class DisableCommand: network = spl[1] relay = main.network[spl[1]].relays[relayNum] commands = {"status": ["Disconnect"]} - deliverRelayCommands(relayNum, commands, user=user+"/"+network) + deliverRelayCommands(relayNum, commands, user=user + "/" + network) main.saveConf("network") if name in main.ReactorPool.keys(): if name in main.FactoryPool.keys(): diff --git a/commands/dist.py b/commands/dist.py index d5f6f53..2348e29 100644 --- a/commands/dist.py +++ b/commands/dist.py @@ -1,6 +1,7 @@ import main from subprocess import run, PIPE + class DistCommand: def __init__(self, *args): self.dist(*args) diff --git a/commands/email.py b/commands/email.py index 56388ec..1b0ec5e 100644 --- a/commands/email.py +++ b/commands/email.py @@ -1,6 +1,7 @@ import main from yaml import dump + class EmailCommand: def __init__(self, *args): self.email(*args) @@ -21,7 +22,7 @@ class EmailCommand: else: failure("Domain already exists in default config: %s" % domain) return - + else: num = int(spl[2]) if spl[1] == "add": diff --git a/commands/enable.py b/commands/enable.py index af645cd..439b26c 100644 --- a/commands/enable.py +++ b/commands/enable.py @@ -1,6 +1,7 @@ import main from core.bot import deliverRelayCommands + class EnableCommand: def __init__(self, *args): self.enable(*args) @@ -22,9 +23,9 @@ class EnableCommand: user = main.alias[int(spl[2])]["nick"] network = spl[1] commands = {"status": ["Connect"]} - deliverRelayCommands(int(spl[2]), commands, user=user+"/"+network) + deliverRelayCommands(int(spl[2]), commands, user=user + "/" + network) main.saveConf("network") - if not spl[1]+spl[2] in main.IRCPool.keys(): + if not spl[1] + spl[2] in main.IRCPool.keys(): main.network[spl[1]].start_bot(int(spl[2])) else: pass diff --git a/commands/exec.py b/commands/exec.py index c199aa8..c2a5598 100644 --- a/commands/exec.py +++ b/commands/exec.py @@ -1,5 +1,6 @@ import main + class ExecCommand: def __init__(self, *args): self.exec(*args) diff --git a/commands/help.py b/commands/help.py index bb12aff..6dcf937 100644 --- a/commands/help.py +++ b/commands/help.py @@ -1,5 +1,6 @@ import main + class HelpCommand: def __init__(self, *args): self.help(*args) diff --git a/commands/join.py b/commands/join.py index 02067c7..e6cbc20 100644 --- a/commands/join.py +++ b/commands/join.py @@ -1,6 +1,7 @@ import main import modules.chankeep + class JoinCommand: def __init__(self, *args): self.join(*args) @@ -21,10 +22,10 @@ class JoinCommand: if not int(spl[2]) in main.network[spl[1]].relays.keys(): failure("Relay %s does not exist on network %s" % (spl[2], spl[1])) return - if not spl[1]+spl[2] in main.IRCPool.keys(): + if not spl[1] + spl[2] in main.IRCPool.keys(): failure("Name has no instance: %s" % spl[1]) return - main.IRCPool[spl[1]+spl[2]].join(spl[3]) + main.IRCPool[spl[1] + spl[2]].join(spl[3]) success("Joined %s" % spl[3]) return elif length == 5: @@ -34,10 +35,10 @@ class JoinCommand: if not int(spl[2]) in main.network[spl[1]].relays.keys(): failure("Relay % does not exist on network %", (spl[2], spl[1])) return - if not spl[1]+spl[2] in main.IRCPool.keys(): + if not spl[1] + spl[2] in main.IRCPool.keys(): failure("Name has no instance: %s" % spl[1]) return - main.IRCPool[spl[1]+spl[2]].join(spl[3], spl[4]) + main.IRCPool[spl[1] + spl[2]].join(spl[3], spl[4]) success("Joined %s with key %s" % (spl[3], spl[4])) return else: diff --git a/commands/list.py b/commands/list.py index 3839914..217b051 100644 --- a/commands/list.py +++ b/commands/list.py @@ -1,5 +1,6 @@ import main + class ListCommand: def __init__(self, *args): self.list(*args) @@ -11,10 +12,10 @@ class ListCommand: if not 1 in main.network[i].relays.keys(): info("Network has no first instance: %s" % i) continue - if not i+"1" in main.IRCPool.keys(): + if not i + "1" in main.IRCPool.keys(): info("No IRC instance: %s - 1" % i) continue - main.IRCPool[i+"1"].list() + main.IRCPool[i + "1"].list() success("Requested list with first instance of %s" % i) return elif length == 2: @@ -24,10 +25,10 @@ class ListCommand: if not 1 in main.network[spl[1]].relays.keys(): failure("Network has no first instance") return - if not spl[1]+"1" in main.IRCPool.keys(): + if not spl[1] + "1" in main.IRCPool.keys(): failure("No IRC instance: %s - 1" % spl[1]) return - main.IRCPool[spl[1]+"1"].list() + main.IRCPool[spl[1] + "1"].list() success("Requested list with first instance of %s" % spl[1]) return else: diff --git a/commands/load.py b/commands/load.py index aa6b37d..31e66f4 100644 --- a/commands/load.py +++ b/commands/load.py @@ -1,5 +1,6 @@ import main + class LoadCommand: def __init__(self, *args): self.load(*args) diff --git a/commands/loadmod.py b/commands/loadmod.py index fb542b9..2923fd7 100644 --- a/commands/loadmod.py +++ b/commands/loadmod.py @@ -1,6 +1,7 @@ import main from utils.loaders.single_loader import loadSingle + class LoadmodCommand: def __init__(self, *args): self.loadmod(*args) diff --git a/commands/logout.py b/commands/logout.py index d1dea67..61cb834 100644 --- a/commands/logout.py +++ b/commands/logout.py @@ -1,5 +1,6 @@ import main + class LogoutCommand: def __init__(self, *args): self.logout(*args) diff --git a/commands/mod.py b/commands/mod.py index 0df1ada..10a19e1 100644 --- a/commands/mod.py +++ b/commands/mod.py @@ -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): @@ -23,7 +24,7 @@ class ModCommand: success("Successfully set key %s to %s on %s" % (spl[2], spl[3], spl[1])) return # Find a better way to do this - #elif length == 6: + # elif length == 6: # if not spl[1] in main.network.keys(): # failure("Network does not exist: %s" % spl[1]) # return diff --git a/commands/msg.py b/commands/msg.py index 4ea2b2f..d92494a 100644 --- a/commands/msg.py +++ b/commands/msg.py @@ -1,5 +1,6 @@ import main + class MsgCommand: def __init__(self, *args): self.msg(*args) @@ -13,12 +14,12 @@ class MsgCommand: if not int(spl[2]) in main.network[spl[1]].relays.keys(): failure("Relay % does not exist on network %" % (spl[2], spl[1])) return - if not spl[1]+spl[2] in main.IRCPool.keys(): + if not spl[1] + spl[2] in main.IRCPool.keys(): failure("Name has no instance: %s" % spl[1]) return - if not spl[3] in main.IRCPool[spl[1]+spl[2]].channels: + if not spl[3] in main.IRCPool[spl[1] + spl[2]].channels: info("Bot not on channel: %s" % spl[3]) - main.IRCPool[spl[1]+spl[2]].msg(spl[3], " ".join(spl[4:])) + main.IRCPool[spl[1] + spl[2]].msg(spl[3], " ".join(spl[4:])) success("Sent %s to %s on relay %s on network %s" % (" ".join(spl[4:]), spl[3], spl[2], spl[1])) return else: diff --git a/commands/network.py b/commands/network.py index e88a905..4a6bdf2 100644 --- a/commands/network.py +++ b/commands/network.py @@ -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) @@ -38,7 +39,7 @@ class NetworkCommand: elif length == 3: if spl[1] == "del": if spl[2] in main.network.keys(): - main.network[spl[2]].seppuku() # ;( + main.network[spl[2]].seppuku() # ;( del main.network[spl[2]] success("Successfully removed network: %s" % spl[2]) main.saveConf("network") diff --git a/commands/part.py b/commands/part.py index e34d7ff..249c32a 100644 --- a/commands/part.py +++ b/commands/part.py @@ -1,5 +1,6 @@ import main + class PartCommand: def __init__(self, *args): self.part(*args) @@ -13,10 +14,10 @@ class PartCommand: if not int(spl[2]) in main.network[spl[1]].relays.keys(): failure("Relay % does not exist on network %", (spl[2], spl[1])) return - if not spl[1]+spl[2] in main.IRCPool.keys(): - failure("Name has no instance: %s" % spl[1]+spl[2]) + if not spl[1] + spl[2] in main.IRCPool.keys(): + failure("Name has no instance: %s" % spl[1] + spl[2]) return - main.IRCPool[spl[1]+spl[2]].part(spl[3]) + main.IRCPool[spl[1] + spl[2]].part(spl[3]) success("Left %s" % spl[3]) return else: diff --git a/commands/pass.py b/commands/pass.py index fe3f240..e37a51e 100644 --- a/commands/pass.py +++ b/commands/pass.py @@ -1,5 +1,6 @@ import main + class PassCommand: def __init__(self, *args): self.password(*args) diff --git a/commands/pending.py b/commands/pending.py index a245a52..b65f2ad 100644 --- a/commands/pending.py +++ b/commands/pending.py @@ -1,5 +1,6 @@ import main + class PendingCommand: def __init__(self, *args): self.pending(*args) diff --git a/commands/recheckauth.py b/commands/recheckauth.py index 0c5c11a..ab4b5b0 100644 --- a/commands/recheckauth.py +++ b/commands/recheckauth.py @@ -1,5 +1,6 @@ import main + class RecheckauthCommand: def __init__(self, *args): self.recheckauth(*args) diff --git a/commands/reg.py b/commands/reg.py index 27c0150..41bb5f0 100644 --- a/commands/reg.py +++ b/commands/reg.py @@ -1,6 +1,7 @@ import main from modules import regproc + class RegCommand: def __init__(self, *args): self.reg(*args) diff --git a/commands/relay.py b/commands/relay.py index 49dca97..34bbd70 100644 --- a/commands/relay.py +++ b/commands/relay.py @@ -1,6 +1,7 @@ import main from yaml import dump + class RelayCommand: def __init__(self, *args): self.relay(*args) diff --git a/commands/save.py b/commands/save.py index d61d1c1..12624cd 100644 --- a/commands/save.py +++ b/commands/save.py @@ -1,5 +1,6 @@ import main + class SaveCommand: def __init__(self, *args): self.save(*args) diff --git a/commands/stats.py b/commands/stats.py index 0db414a..a396f12 100644 --- a/commands/stats.py +++ b/commands/stats.py @@ -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) diff --git a/commands/swho.py b/commands/swho.py index 49c71d7..18dbc12 100644 --- a/commands/swho.py +++ b/commands/swho.py @@ -1,5 +1,6 @@ import main + class SwhoCommand: def __init__(self, *args): self.swho(*args) diff --git a/commands/token.py b/commands/token.py index 7e20e5b..7d38eac 100644 --- a/commands/token.py +++ b/commands/token.py @@ -2,6 +2,7 @@ import main from yaml import dump from uuid import uuid4 + class TokenCommand: def __init__(self, *args): self.token(*args) @@ -31,11 +32,12 @@ class TokenCommand: elif length == 4: 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()), - "usage": spl[3], - "counter": str(uuid4()), - } + if spl[3] in ["relay"]: # more to come! + main.tokens[spl[2]] = { + "hello": str(uuid4()), + "usage": spl[3], + "counter": str(uuid4()), + } main.saveConf("tokens") success("Successfully created token %s:" % spl[2]) info(dump(main.tokens[spl[2]])) diff --git a/commands/users.py b/commands/users.py index 30da28e..7d80e84 100644 --- a/commands/users.py +++ b/commands/users.py @@ -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) diff --git a/commands/who.py b/commands/who.py index f19e462..e80f488 100644 --- a/commands/who.py +++ b/commands/who.py @@ -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) diff --git a/core/bot.py b/core/bot.py index bd3743f..b735e96 100644 --- a/core/bot.py +++ b/core/bot.py @@ -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")) + keyFN = main.certPath + main.config["Key"] + certFN = main.certPath + main.config["Certificate"] + 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 @@ -77,7 +82,7 @@ class IRCRelay(IRCClient): self.nickname = "relay" self.realname = "relay" self.username = self.user - self.password = self.user+":"+password + self.password = self.user + ":" + password self.relayCommands = relayCommands self.num = num @@ -109,19 +114,25 @@ class IRCRelay(IRCClient): def signedOn(self): if not self.isconnected: self.isconnected = True - #log("signed on as a relay: %s" % self.num) + # log("signed on as a relay: %s" % self.num) sleeptime = 0 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: reactor.callLater(sleeptime, self.sendStage2) - reactor.callLater(sleeptime+5, self.transport.loseConnection) + reactor.callLater(sleeptime + 5, self.transport.loseConnection) return + class IRCBot(IRCClient): def __init__(self, net, num): self.isconnected = False @@ -135,26 +146,26 @@ class IRCBot(IRCClient): relay = main.network[self.net].relays[num] self.nickname = alias["nick"] self.realname = alias["realname"] - self.username = alias["nick"].lower()+"/"+relay["net"] + self.username = alias["nick"].lower() + "/" + relay["net"] self.password = main.config["Relay"]["Password"] - self.userinfo = None # - self.fingerReply = None # - self.versionName = None # Don't give out information - self.versionNum = None # - self.versionEnv = None # - self.sourceURL = None # - - self._getWho = {} # LoopingCall objects -- needed to be able to stop them - - self._tempWho = {} # temporary storage for gathering WHO info - self._tempNames = {} # temporary storage for gathering NAMES info - self._tempList = ([], []) # temporary storage for gathering LIST info - self.listOngoing = False # we are currently receiving a LIST - self.listRetried = False # we asked and got nothing so asked again - self.listAttempted = False # we asked for a list - self.listSimple = False # after asking again we got the list, so use the simple - # syntax from now on - self.wantList = False # we want to send a LIST, but not all relays are active yet + self.userinfo = None # + self.fingerReply = None # + self.versionName = None # Don't give out information + self.versionNum = None # + self.versionEnv = None # + self.sourceURL = None # + + self._getWho = {} # LoopingCall objects -- needed to be able to stop them + + self._tempWho = {} # temporary storage for gathering WHO info + self._tempNames = {} # temporary storage for gathering NAMES info + self._tempList = ([], []) # temporary storage for gathering LIST info + self.listOngoing = False # we are currently receiving a LIST + self.listRetried = False # we asked and got nothing so asked again + self.listAttempted = False # we asked for a list + self.listSimple = False # after asking again we got the list, so use the simple + # syntax from now on + self.wantList = False # we want to send a LIST, but not all relays are active yet self.chanlimit = 0 self.prefix = {} self.servername = None @@ -214,8 +225,8 @@ class IRCBot(IRCClient): cast["time"] = str(datetime.now().isoformat()) # remove odd stuff - for i in list(cast.keys()): # Make a copy of the .keys() as Python 3 cannot handle iterating over - if cast[i] == "": # a dictionary that changes length with each iteration + for i in list(cast.keys()): # Make a copy of the .keys() as Python 3 cannot handle iterating over + if cast[i] == "": # a dictionary that changes length with each iteration del cast[i] # remove server stuff if "muser" in cast.keys(): @@ -259,11 +270,11 @@ class IRCBot(IRCClient): if "channel" in cast.keys(): if cast["type"] == "mode": if cast["channel"].lower() == self.nickname.lower(): - #castDup = deepcopy(cast) + # castDup = deepcopy(cast) cast["mtype"] = cast["type"] cast["type"] = "self" - #self.event(**castDup) - if cast["modearg"]: # check if modearg is non-NoneType + # self.event(**castDup) + if cast["modearg"]: # check if modearg is non-NoneType if self.nickname.lower() == cast["modearg"].lower(): castDup = deepcopy(cast) castDup["mtype"] = cast["type"] @@ -273,7 +284,7 @@ class IRCBot(IRCClient): if cast["channel"].lower() == self.nickname.lower(): cast["mtype"] = cast["type"] cast["type"] = "query" - #self.event(**castDup) + # self.event(**castDup) # Don't call self.event for this one because queries are not events on a # channel, but we still want to see them @@ -296,7 +307,7 @@ class IRCBot(IRCClient): castDup["type"] = "self" # we have been mentioned in a msg/notice/action/part/quit/topic message - if "msg" in cast.keys(): # Don't highlight queries + if "msg" in cast.keys(): # Don't highlight queries if not cast["msg"] == None: if self.nickname.lower() in cast["msg"].lower(): castDup = deepcopy(cast) @@ -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] @@ -438,7 +461,7 @@ class IRCBot(IRCClient): self._tempList[0].append(d) if self.listSimple: self.sendLine("LIST") - return d # return early if we know what to do + return d # return early if we know what to do if noargs: self.sendLine("LIST") @@ -460,8 +483,8 @@ class IRCBot(IRCClient): return else: if nocheck: - allRelays = True # override the system - if this is - else: # specified, we already did this + allRelays = True # override the system - if this is + else: # specified, we already did this allRelays = chankeep.allRelaysActive(self.net) if not allRelays: self.wantList = True @@ -481,7 +504,7 @@ class IRCBot(IRCClient): self._tempList[1].append([channel, users, topic]) def irc_RPL_LISTEND(self, prefix, params): - if not len(self._tempList[0]) > 0: # there are no callbacks, can't do anything there + if not len(self._tempList[0]) > 0: # there are no callbacks, can't do anything there debug("We didn't ask for this LIST, discarding") self._tempList[0].clear() self._tempList[1].clear() @@ -510,18 +533,18 @@ class IRCBot(IRCClient): self.listSimple = True def got_list(self, listinfo): - if len(listinfo) == 0: # probably ngircd not supporting LIST >0 + if len(listinfo) == 0: # probably ngircd not supporting LIST >0 return chankeep.initialList(self.net, self.num, listinfo, self.chanlimit) def recheckList(self): allRelays = chankeep.allRelaysActive(self.net) if allRelays: - name = self.net+"1" + name = self.net + "1" if main.IRCPool[name].wantList == True: main.IRCPool[name].list(nocheck=True) debug("Asking for a list for %s after final relay %i connected" % (self.net, self.num)) - if self.num == 1: # Only one instance should do a list + if self.num == 1: # Only one instance should do a list if self.chanlimit: if allRelays: self.list() @@ -532,24 +555,26 @@ 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) + # regproc.registerAccount(self.net, self.num) try: self.chanlimit = int(chanlimit) except TypeError: warn("Invalid chanlimit: %s" % i) if self.chanlimit == 0: - self.chanlimit = 200 # don't take the piss if it's not limited - if not regproc.needToRegister(self.net): # if we need to register, only recheck on auth confirmation + self.chanlimit = 200 # don't take the piss if it's not limited + if not regproc.needToRegister(self.net): # if we need to register, only recheck on auth confirmation self.recheckList() def seed_prefix(self, prefix): prefix = prefix.replace(")", "") prefix = prefix.replace("(", "") length = len(prefix) - half = int(length/2) + half = int(length / 2) prefixToMode = dict(zip(prefix[half:], prefix[:half])) self.prefix = prefixToMode @@ -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) @@ -677,7 +711,7 @@ class IRCBot(IRCClient): self._getWho[channel] = lc intrange = main.config["Tweaks"]["Delays"]["WhoRange"] minint = main.config["Tweaks"]["Delays"]["WhoLoop"] - interval = randint(minint, minint+intrange) + interval = randint(minint, minint + intrange) lc.start(interval) def botLeft(self, channel): @@ -687,10 +721,11 @@ class IRCBot(IRCClient): lc = self._getWho[channel] lc.stop() del self._getWho[channel] - 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 + 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) @@ -711,14 +746,14 @@ class IRCBot(IRCClient): def chanlessEvent(self, cast): cast["time"] = str(datetime.now().isoformat()) cast["nick"], cast["ident"], cast["host"] = parsen(cast["muser"]) - if dedup(self.name, cast): # Needs to be kept self.name until the dedup - # function is converted to the new net, num - # format - return # stop right there sir! + if dedup(self.name, cast): # Needs to be kept self.name until the dedup + # function is converted to the new net, num + # format + return # stop right there sir! chans = userinfo.getChanList(self.net, cast["nick"]) if chans == None: error("No channels returned for chanless event: %s" % cast) - # self.event(**cast) -- no, should NEVER happen + # self.event(**cast) -- no, should NEVER happen return # getChansSingle returns all channels of the user, we only want to use # ones we have common with them @@ -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): @@ -747,7 +790,7 @@ class IRCBotFactory(ReconnectingClientFactory): self.name = "relay - %i" % num self.relay = True else: - self.name = net+str(num) + self.name = net + str(num) self.num = num self.net = net self.relay = False @@ -781,9 +824,18 @@ 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) + # ReconnectingClientFactory.clientConnectionLost(self, connector, reason) def clientConnectionFailed(self, connector, reason): if not self.client == None: @@ -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) - + # ReconnectingClientFactory.clientConnectionFailed(self, connector, reason) diff --git a/core/logstash.py b/core/logstash.py index aa5924b..17e8dfd 100644 --- a/core/logstash.py +++ b/core/logstash.py @@ -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: diff --git a/core/parser.py b/core/parser.py index 64270f8..1eb34c5 100644 --- a/core/parser.py +++ b/core/parser.py @@ -2,8 +2,9 @@ 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) + # call command modules with: (addr, authed, data, spl, success, failure, info, incUsage, length) spl = data.split() if addr in main.connections.keys(): obj = main.connections[addr] diff --git a/core/relay.py b/core/relay.py index 7c7e020..66a9830 100644 --- a/core/relay.py +++ b/core/relay.py @@ -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): @@ -108,7 +126,7 @@ class Relay(Protocol): def connectionMade(self): log("Relay connection from %s:%s" % (self.addr.host, self.addr.port)) - #self.send("Greetings.") + # self.send("Greetings.") def connectionLost(self, reason): self.authed = False @@ -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: diff --git a/core/server.py b/core/server.py index e3f125a..94af7a0 100644 --- a/core/server.py +++ b/core/server.py @@ -4,6 +4,7 @@ from utils.logging.log import * from core.parser import parseCommand + class Server(Protocol): def __init__(self, addr): self.addr = addr @@ -18,7 +19,7 @@ class Server(Protocol): def dataReceived(self, data): data = data.decode("utf-8", "replace") - #log("Data received from %s:%s -- %s" % (self.addr.host, self.addr.port, repr(data))) + # log("Data received from %s:%s -- %s" % (self.addr.host, self.addr.port, repr(data))) if "\n" in data: splitData = [x for x in data.split("\n") if x] if "\n" in data: @@ -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) diff --git a/main.py b/main.py index caebef7..a29e1d7 100644 --- a/main.py +++ b/main.py @@ -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,43 +66,45 @@ 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: + with open(configPath + filemap[var][0], "w") as f: json.dump(globals()[var], f, indent=4) elif filemap[var][2] == "pickle": - with open(configPath+filemap[var][0], "wb") as f: + with open(configPath + filemap[var][0], "wb") as f: pickle.dump(globals()[var], f) else: raise Exception("invalid format") + def loadConf(var): if filemap[var][2] == "json": - with open(configPath+filemap[var][0], "r") as f: + with open(configPath + filemap[var][0], "r") as f: globals()[var] = json.load(f) if var == "alias": # This is a workaround to convert all the keys into integers since JSON # turns them into strings... # Dammit Jason! global alias - alias = {int(x):y for x, y in alias.items()} + alias = {int(x): y for x, y in alias.items()} elif filemap[var][2] == "pickle": try: - with open(configPath+filemap[var][0], "rb") as f: + with open(configPath + filemap[var][0], "rb") as f: globals()[var] = pickle.load(f) except FileNotFoundError: globals()[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 - - + r = StrictRedis(unix_socket_path=config["RedisSocket"], db=0) # Ephemeral - flushed on quit + g = StrictRedis(unix_socket_path=config["RedisSocket"], db=1) # Persistent diff --git a/modules/alias.py b/modules/alias.py index 59ef99a..1961ec6 100644 --- a/modules/alias.py +++ b/modules/alias.py @@ -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) @@ -12,8 +14,8 @@ def generate_alias(): nick = nick.capitalize() rand = random.randint(1, 4) while rand == 1: - split = random.randint(0, len(nick)-1) - nick = nick[:split] + nick[split+1:] + split = random.randint(0, len(nick) - 1) + nick = nick[:split] + nick[split + 1 :] rand = random.randint(1, 4) rand = random.randint(1, 3) if rand == 1 or rand == 4: @@ -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": [], + } diff --git a/modules/chankeep.py b/modules/chankeep.py index 1cc70c0..ec43b0f 100644 --- a/modules/chankeep.py +++ b/modules/chankeep.py @@ -6,11 +6,12 @@ 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 for i in main.network[net].relays.keys(): - name = net+str(i) + name = net + str(i) if name in main.IRCPool.keys(): if main.IRCPool[name].authenticated: existNum += 1 @@ -18,20 +19,22 @@ def allRelaysActive(net): return True return False + def getChanFree(net, new): chanfree = {} chanlimits = set() for i in main.network[net].relays.keys(): if i in new: continue - name = net+str(i) - chanfree[i] = main.IRCPool[name].chanlimit-len(main.IRCPool[name].channels) + name = net + str(i) + chanfree[i] = main.IRCPool[name].chanlimit - len(main.IRCPool[name].channels) chanlimits.add(main.IRCPool[name].chanlimit) if not len(chanlimits) == 1: error("Network %s has servers with different CHANLIMIT values" % net) return False return (chanfree, chanlimits.pop()) + def emptyChanAllocate(net, flist, relay, new): chanfree = getChanFree(net, new) if not chanfree: @@ -41,10 +44,10 @@ def emptyChanAllocate(net, flist, relay, new): allocated = {} toalloc = len(flist) if toalloc > sum(chanfree[0].values()): - correction = round(toalloc-sum(chanfree[0].values()) / chanfree[1]) - #print("correction", correction) + correction = round(toalloc - sum(chanfree[0].values()) / chanfree[1]) + # print("correction", correction) warn("Ran out of channel spaces, provisioning additional %i relays for %s" % (correction, net)) - #newNums = modules.provision.provisionMultipleRelays(net, correction) + # newNums = modules.provision.provisionMultipleRelays(net, correction) return False for i in chanfree[0].keys(): for x in range(chanfree[0][i]): @@ -56,8 +59,9 @@ def emptyChanAllocate(net, flist, relay, new): allocated[i] = [flist.pop()] return allocated + def populateChans(net, clist, relay, new): - #divided = array_split(clist, relay) + # divided = array_split(clist, relay) allocated = emptyChanAllocate(net, clist, relay, new) if not allocated: return @@ -67,18 +71,20 @@ 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) + 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) return False for i in main.network[net].relays.keys(): - name = net+str(i) + name = net + str(i) for x in main.IRCPool[name].channels: for y in listinfo: if y[0] == x: @@ -88,29 +94,31 @@ def minifyChans(net, listinfo): return False return listinfo + def keepChannels(net, listinfo, mean, sigrelay, relay): listinfo = minifyChans(net, listinfo) if not listinfo: return - if relay <= main.config["ChanKeep"]["SigSwitch"]: # we can cover all of the channels + if relay <= main.config["ChanKeep"]["SigSwitch"]: # we can cover all of the channels coverAll = True - elif relay > main.config["ChanKeep"]["SigSwitch"]: # we cannot cover all of the channels + elif relay > main.config["ChanKeep"]["SigSwitch"]: # we cannot cover all of the channels coverAll = False if not sigrelay <= main.config["ChanKeep"]["MaxRelay"]: error("Network %s is too big to cover: %i relays required" % (net, sigrelay)) return if coverAll: - needed = relay-len(main.network[net].relays.keys()) + needed = relay - len(main.network[net].relays.keys()) newNums = modules.provision.provisionMultipleRelays(net, needed) flist = [i[0] for i in listinfo] populateChans(net, flist, relay, newNums) else: - needed = sigrelay-len(main.network[net].relays.keys()) + needed = sigrelay - len(main.network[net].relays.keys()) newNums = modules.provision.provisionMultipleRelays(net, needed) siglist = [i[0] for i in listinfo if int(i[1]) > mean] populateChans(net, siglist, sigrelay, newNums) notifyJoin(net) + def joinSingle(net, channel): if allRelaysActive(net): chanfree = getChanFree(net, []) @@ -122,14 +130,16 @@ def joinSingle(net, channel): error("All relays for %s are not active" % net) return False + def nukeNetwork(net): - #purgeRecords(net) - #p = main.g.pipeline() - main.g.delete("analytics.list."+net) - #p.delete("list."+net) - #p.execute() + # purgeRecords(net) + # p = main.g.pipeline() + main.g.delete("analytics.list." + net) + # p.delete("list."+net) + # p.execute() -#def nukeNetwork(net): + +# def nukeNetwork(net): # deferToThread(_nukeNetwork, net) @@ -141,7 +151,7 @@ def _initialList(net, num, listinfo, chanlimit): except TypeError: warn("Bad LIST data received from %s - %i" % (net, num)) return - mean = round(cumul/listlength, 2) + mean = round(cumul / listlength, 2) siglength = 0 insiglength = 0 sigcumul = 0 @@ -154,8 +164,8 @@ def _initialList(net, num, listinfo, chanlimit): insiglength += 1 insigcumul += int(i[1]) - sigrelay = ceil(siglength/chanlimit) - relay = ceil(listlength/chanlimit) + sigrelay = ceil(siglength / chanlimit) + relay = ceil(listlength / chanlimit) netbase = "list.%s" % net abase = "analytics.list.%s" % net p = main.g.pipeline() @@ -163,18 +173,18 @@ def _initialList(net, num, listinfo, chanlimit): p.hset(abase, "total", listlength) p.hset(abase, "sigtotal", siglength) p.hset(abase, "insigtotal", insiglength) - p.hset(abase, "sigperc", round(siglength/listlength*100, 2)) - p.hset(abase, "insigperc", round(insiglength/listlength*100, 2)) + p.hset(abase, "sigperc", round(siglength / listlength * 100, 2)) + p.hset(abase, "insigperc", round(insiglength / listlength * 100, 2)) p.hset(abase, "cumul", cumul) p.hset(abase, "sigcumul", sigcumul) p.hset(abase, "insigcumul", insigcumul) p.hset(abase, "relay", relay) p.hset(abase, "sigrelay", sigrelay) - p.hset(abase, "insigrelay", ceil(insiglength/chanlimit)) + p.hset(abase, "insigrelay", ceil(insiglength / chanlimit)) # Purge existing records before writing - #purgeRecords(net) - #for i in listinfo: + # purgeRecords(net) + # for i in listinfo: # p.rpush(netbase+"."+i[0], i[1]) # p.rpush(netbase+"."+i[0], i[2]) # p.sadd(netbase, i[0]) @@ -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) - diff --git a/modules/counters.py b/modules/counters.py index bb2b518..a088cc3 100644 --- a/modules/counters.py +++ b/modules/counters.py @@ -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) diff --git a/modules/monitor.py b/modules/monitor.py index 2dbfc2e..8c4681d 100644 --- a/modules/monitor.py +++ b/modules/monitor.py @@ -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(): @@ -21,10 +37,16 @@ def parsemeta(numName, c): if c["type"] in ["msg", "notice", "action", "topic", "mode"]: if "muser" in c.keys(): userinfo.editUser(c["net"], c["muser"]) - #if c["type"] == "mode": + # 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,9 +59,16 @@ 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 +def event(numName, c): # yes I'm using a short variable because otherwise it goes off the screen if dedup(numName, c): return @@ -48,7 +77,7 @@ def event(numName, c): # yes I'm using a short variable because otherwise it goe if "muser" in c.keys(): del c["muser"] - sortedKeys = {k: c[k] for k in order if k in c} # Sort dict keys according to order + sortedKeys = {k: c[k] for k in order if k in c} # Sort dict keys according to order sortedKeys["src"] = "irc" sendLogstashNotification(sortedKeys) sendRelayNotification(sortedKeys) diff --git a/modules/network.py b/modules/network.py index 8cff3db..21f1753 100644 --- a/modules/network.py +++ b/modules/network.py @@ -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,20 +38,20 @@ 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(): main.alias[num] = alias.generate_alias() main.saveConf("alias") self.aliases[num] = {"password": password} - #if main.config["ConnectOnCreate"]: -- Done in provision + # if main.config["ConnectOnCreate"]: -- Done in provision # self.start_bot(num) return num, main.alias[num]["nick"] def killAliases(self, aliasList): for i in aliasList: - name = self.net+str(i) + name = self.net + str(i) if name in main.ReactorPool.keys(): if name in main.FactoryPool.keys(): main.FactoryPool[name].stopTrying() @@ -63,7 +64,7 @@ class Network: def delete_relay(self, id): del self.relays[id] del self.aliases[id] - #del main.alias[id] - Aliases are global per num, so don't delete them! + # del main.alias[id] - Aliases are global per num, so don't delete them! self.killAliases([id]) def seppuku(self): @@ -74,11 +75,11 @@ class Network: def start_bot(self, num): # a single name is given to relays in the backend # e.g. freenode1 for the first relay on freenode network - keyFN = main.certPath+main.config["Key"] - certFN = main.certPath+main.config["Certificate"] + keyFN = main.certPath + main.config["Key"] + certFN = main.certPath + main.config["Certificate"] contextFactory = DefaultOpenSSLContextFactory(keyFN.encode("utf-8", "replace"), certFN.encode("utf-8", "replace")) bot = IRCBotFactory(self.net, num) - #host, port = self.relays[num]["host"], self.relays[num]["port"] + # host, port = self.relays[num]["host"], self.relays[num]["port"] host, port = getRelay(num) rct = reactor.connectSSL(host, port, bot, contextFactory) name = self.net + str(num) diff --git a/modules/provision.py b/modules/provision.py index 69fe99e..990db63 100644 --- a/modules/provision.py +++ b/modules/provision.py @@ -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 = {} @@ -17,7 +18,7 @@ def provisionUserNetworkData(num, nick, altnick, ident, realname, network, host, commands["controlpanel"].append("Set Ident %s %s" % (user, ident)) commands["controlpanel"].append("Set RealName %s %s" % (user, realname)) if security == "ssl": - commands["controlpanel"].append("SetNetwork TrustAllCerts %s %s true" % (user, network)) # Don't judge me + commands["controlpanel"].append("SetNetwork TrustAllCerts %s %s true" % (user, network)) # Don't judge me commands["controlpanel"].append("AddServer %s %s %s +%s" % (user, network, host, port)) elif security == "plain": commands["controlpanel"].append("AddServer %s %s %s %s" % (user, network, host, port)) @@ -29,9 +30,9 @@ def provisionUserNetworkData(num, nick, altnick, ident, realname, network, host, inst = modules.regproc.selectInst(network) 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]]) + # stage2commands["perform"].append("add mode %nick% +"+inst["setmode"]) + deliverRelayCommands(num, commands, stage2=[[user + "/" + network, stage2commands]]) + def provisionAuthenticationData(num, nick, network, security, auth, password): commands = {} @@ -48,23 +49,28 @@ def provisionAuthenticationData(num, nick, network, security, auth, password): commands["nickserv"].append("Set %s" % password) inst = modules.regproc.selectInst(network) if "setmode" in inst.keys(): - #commands["status"].append("LoadMod perform") - commands["perform"] = ["add mode %nick% +"+inst["setmode"]] - deliverRelayCommands(num, commands, user=user+"/"+network) + # commands["status"].append("LoadMod perform") + commands["perform"] = ["add mode %nick% +" + inst["setmode"]] + deliverRelayCommands(num, commands, user=user + "/" + network) -def provisionRelay(num, network): # provision user and network data +def provisionRelay(num, network): # provision user and network data aliasObj = main.alias[num] alias = aliasObj["nick"] - 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"]) + 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"] + ) 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 - diff --git a/modules/regproc.py b/modules/regproc.py index 97c330a..26cdae2 100644 --- a/modules/regproc.py +++ b/modules/regproc.py @@ -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,11 +24,12 @@ def selectInst(net): inst = main.irc["_"] return inst + def substitute(net, num, token=None): inst = selectInst(net) alias = main.alias[num] nickname = alias["nick"] - username = nickname+"/"+net + username = nickname + "/" + net password = main.network[net].aliases[num]["password"] inst["email"] = inst["email"].replace("{nickname}", nickname) for i in inst.keys(): @@ -39,29 +42,32 @@ 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) if not sinst["register"]: error("Cannot register for %s: function disabled" % (net)) return False - name = net+str(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) + 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) + name = net + str(num) if name in main.IRCPool.keys(): if not negativepass == None: main.IRCPool[name].regPing(negativepass=negativepass) return - debug("Relay authenticated: %s - %i" %(net, num)) + debug("Relay authenticated: %s - %i" % (net, num)) main.IRCPool[name].authenticated = True main.IRCPool[name].recheckList() if obj.relays[num]["registered"]: @@ -75,21 +81,23 @@ 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"] security = obj.security auth = obj.auth password = obj.aliases[num]["password"] - uname = main.alias[num]["nick"]+"/"+net - provision.provisionAuthenticationData(num, nick, net, security, auth, password) # Set up for auth - main.IRCPool[net+str(num)].msg(main.config["Tweaks"]["ZNC"]["Prefix"]+"status", "Jump") + uname = main.alias[num]["nick"] + "/" + net + provision.provisionAuthenticationData(num, nick, net, security, auth, password) # Set up for auth + main.IRCPool[net + str(num)].msg(main.config["Tweaks"]["ZNC"]["Prefix"] + "status", "Jump") if selectInst(net)["check"] == False: confirmRegistration(net, num) + def registerTest(c): sinst = substitute(c["net"], c["num"]) - name = c["net"]+str(c["num"]) + name = c["net"] + str(c["num"]) if sinst["check"] == False: return if "msg" in c.keys() and not c["msg"] == None: @@ -98,19 +106,19 @@ def registerTest(c): if not main.IRCPool[name]._negativePass == True: if c["type"] == "query" and c["nick"] == sinst["entity"]: if sinst["checknegativemsg"] in c["msg"]: - confirmRegistration(c["net"], c["num"], negativepass=False) # Not passed negative check, report back + confirmRegistration(c["net"], c["num"], negativepass=False) # Not passed negative check, report back return if sinst["checkendnegative"] in c["msg"]: - confirmRegistration(c["net"], c["num"], negativepass=True) # Passed the negative check, report back + confirmRegistration(c["net"], c["num"], negativepass=True) # Passed the negative check, report back return if sinst["ping"]: if sinst["checkmsg2"] in c["msg"] and c["nick"] == sinst["entity"]: confirmRegistration(c["net"], c["num"]) return if sinst["checktype"] == "msg": - if sinst["checkmsg"] in c["msg"]: - confirmRegistration(c["net"], c["num"]) - return + if sinst["checkmsg"] in c["msg"]: + confirmRegistration(c["net"], c["num"]) + return elif sinst["checktype"] == "mode": if c["type"] == "self": if c["mtype"] == "mode": diff --git a/modules/userinfo.py b/modules/userinfo.py index a9104da..1722cb3 100644 --- a/modules/userinfo.py +++ b/modules/userinfo.py @@ -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) + 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,20 +22,23 @@ def getWho(query): result[i] = f return result + def getChansSingle(name, nick): - nick = ["live.chan."+name+"."+i for i in nick] + nick = ["live.chan." + name + "." + i for i in nick] result = main.r.sinter(*nick) if len(result) == 0: return None return (i.decode() for i in result) + def getChanList(name, nick): - chanspace = "live.chan."+name+"."+nick + chanspace = "live.chan." + name + "." + nick result = main.r.smembers(chanspace) if len(result) == 0: return None return (i.decode() for i in result) + def getChans(nick): result = {} for i in main.network.keys(): @@ -42,13 +47,15 @@ def getChans(nick): result[i] = f return result + def getUsersSingle(name, nick): - nick = ("live.who."+name+"."+i for i in nick) + nick = ("live.who." + name + "." + i for i in nick) result = main.r.sinter(*nick) if len(result) == 0: return None return (i.decode() for i in result) + def getUsers(nick): result = {} for i in main.network.keys(): @@ -57,8 +64,10 @@ def getUsers(nick): result[i] = f return result + def getNumWhoEntries(name): - return main.r.scard("live.who."+name) + return main.r.scard("live.who." + name) + def getNumTotalWhoEntries(): total = 0 @@ -66,6 +75,7 @@ def getNumTotalWhoEntries(): total += getNumWhoEntries(i) return total + def getNamespace(name, channel, nick): gnamespace = "live.who.%s" % name namespace = "live.who.%s.%s" % (name, channel) @@ -73,35 +83,40 @@ 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 p = main.r.pipeline() for i in users: - user = i[0]+"!"+i[1]+"@"+i[2] + user = i[0] + "!" + i[1] + "@" + i[2] p.hset(mapspace, i[0], user) 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) + # d.addCallback(testCallback) + def _initialNames(name, channel, names): namespace = "live.who.%s.%s" % (name, channel) p = main.r.pipeline() for mode, nick in names: p.sadd(namespace, nick) - p.sadd("live.chan."+name+"."+nick, channel) + p.sadd("live.chan." + name + "." + nick, channel) if mode: - p.hset("live.prefix."+name+"."+channel, nick, mode) + 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) + # d.addCallback(testCallback) + def editUser(name, user): gnamespace = "live.who.%s" % name @@ -109,9 +124,10 @@ def editUser(name, user): parsed = parsen(user) p = main.r.pipeline() p.sadd(gnamespace, user) - p.hset(mapspace, parsed[0], user) # add nick -> user mapping + 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,40 +137,43 @@ 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() channels = main.r.smembers(chanspace) p.srem(namespace, nick) - if channels == {channel.encode()}: # can we only see them on this channel? - p.delete(chanspace) # remove channel tracking entry - p.hdel("live.prefix."+name+"."+channel, nick) # remove prefix tracking entry - p.hdel(mapspace, nick) # remove nick mapping entry + if channels == {channel.encode()}: # can we only see them on this channel? + p.delete(chanspace) # remove channel tracking entry + p.hdel("live.prefix." + name + "." + channel, nick) # remove prefix tracking entry + p.hdel(mapspace, nick) # remove nick mapping entry if user: - p.srem(gnamespace, user) # remove global userinfo entry + p.srem(gnamespace, user) # remove global userinfo entry else: warn("Attempt to delete nonexistent user: %s" % user) else: - p.srem(chanspace, channel) # keep up - remove the channel from their list + p.srem(chanspace, channel) # keep up - remove the channel from their list p.execute() + def escape(text): chars = ["[", "]", "^", "-", "*", "?"] text = text.replace("\\", "\\\\") for i in chars: - text = text.replace(i, "\\"+i) + text = text.replace(i, "\\" + i) return text + def getUserByNick(name, nick): - gnamespace = "live.who.%s" % name # "nick": "nick!ident@host" + gnamespace = "live.who.%s" % name # "nick": "nick!ident@host" mapspace = "live.map.%s" % name if main.r.hexists(mapspace, nick): return main.r.hget(mapspace, nick) else: warn("Entry doesn't exist: %s on %s - attempting auxiliary lookup" % (nick, mapspace)) - #return False + # return False # legacy code below - remove when map is reliable - usermatch = main.r.sscan(gnamespace, match=escape(nick)+"!*", count=999999999) + usermatch = main.r.sscan(gnamespace, match=escape(nick) + "!*", count=999999999) if usermatch[1] == []: warn("No matches found for user query: %s on %s" % (nick, name)) return False @@ -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) @@ -176,40 +196,43 @@ def renameUser(name, oldnick, olduser, newnick, newuser): p.sadd(gnamespace, newuser) for i in main.r.smembers(chanspace): i = i.decode() - p.srem("live.who."+name+"."+i, oldnick) - p.sadd("live.who."+name+"."+i, newnick) + p.srem("live.who." + name + "." + i, oldnick) + p.sadd("live.who." + name + "." + i, newnick) p.hdel(mapspace, oldnick) p.hset(mapspace, newnick, newuser) - if main.r.exists("live.prefix."+name+"."+i): # if there's a prefix entry for the channel - if main.r.hexists("live.prefix."+name+"."+i, oldnick): # if the old nick is in it - mode = main.r.hget("live.prefix."+name+"."+i, oldnick) # retrieve old modes - p.hset("live.prefix."+name+"."+i, newnick, mode) # set old modes to new nickname + if main.r.exists("live.prefix." + name + "." + i): # if there's a prefix entry for the channel + if main.r.hexists("live.prefix." + name + "." + i, oldnick): # if the old nick is in it + mode = main.r.hget("live.prefix." + name + "." + i, oldnick) # retrieve old modes + p.hset("live.prefix." + name + "." + i, newnick, mode) # set old modes to new nickname if main.r.exists(chanspace): p.rename(chanspace, newchanspace) else: warn("Key doesn't exist: %s" % chanspace) p.execute() -def delUserByNick(name, channel, nick): # kick + +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 + +def delUserByNetwork(name, nick, user): # quit gnamespace = "live.who.%s" % name chanspace = "live.chan.%s.%s" % (name, nick) mapspace = "live.chan.%s" % name p = main.r.pipeline() p.srem(gnamespace, user) for i in main.r.smembers(chanspace): - p.srem("live.who."+name+"."+i.decode(), nick) - p.hdel("live.prefix."+name+"."+i.decode(), nick) + p.srem("live.who." + name + "." + i.decode(), nick) + p.hdel("live.prefix." + name + "." + i.decode(), nick) p.delete(chanspace) p.hdel(mapspace, nick) p.execute() + def _delChannels(net, channels): gnamespace = "live.who.%s" % net mapspace = "live.map.%s" % net @@ -218,23 +241,24 @@ def _delChannels(net, channels): namespace = "live.who.%s.%s" % (net, channel) for i in main.r.smembers(namespace): nick = i.decode() - #user = getUserByNick(net, nick) -- far too many function calls + # user = getUserByNick(net, nick) -- far too many function calls user = main.r.hget(mapspace, nick) if not user: warn("User lookup failed: %s on %s" % (nick, net)) - if main.r.smembers("live.chan."+net+"."+nick) == {channel.encode()}: + if main.r.smembers("live.chan." + net + "." + nick) == {channel.encode()}: if user: p.srem(gnamespace, user) - p.delete("live.chan."+net+"."+nick) - p.hdel(mapspace, nick) # remove map entry + p.delete("live.chan." + net + "." + nick) + p.hdel(mapspace, nick) # remove map entry else: - p.srem("live.chan."+net+"."+nick, channel) + p.srem("live.chan." + net + "." + nick, channel) p.delete(namespace) - p.delete("live.prefix."+net+"."+channel) + p.delete("live.prefix." + net + "." + channel) p.execute() -def delChannels(net, channels): # we have left a channel + +def delChannels(net, channels): # we have left a channel trace("Purging channel %s for %s" % (", ".join(channels), net)) d = deferToThread(_delChannels, net, channels) - #d.addCallback(testCallback) + # d.addCallback(testCallback) diff --git a/requirements.txt b/requirements.txt index 5ff3e80..8d6b25a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +pre-commit twisted pyOpenSSL redis diff --git a/threshold b/threshold index 46c0770..dc186b4 100755 --- a/threshold +++ b/threshold @@ -3,19 +3,23 @@ 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 + +# 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 +# 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 + +signal(SIGINT, handler) # Handle Ctrl-C and run the cleanup routine +if "--debug" in sys.argv: # yes really main.config["Debug"] = True if "--trace" in sys.argv: main.config["Trace"] = 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() diff --git a/utils/cleanup.py b/utils/cleanup.py index 3b818f3..83ed661 100644 --- a/utils/cleanup.py +++ b/utils/cleanup.py @@ -1,15 +1,17 @@ import main from twisted.internet import reactor from utils.logging.debug import debug -from utils.logging.log import * +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() reactor.stop() - #sys.exit(1) + # sys.exit(1) diff --git a/utils/dedup.py b/utils/dedup.py index a5c3c45..f64f26c 100644 --- a/utils/dedup.py +++ b/utils/dedup.py @@ -5,20 +5,21 @@ from json import dumps import main from utils.logging.debug import debug + def dedup(numName, b): c = deepcopy(b) if "time" in c.keys(): del c["time"] - c["approxtime"] = str(datetime.utcnow().timestamp())[:main.config["Tweaks"]["DedupPrecision"]] + c["approxtime"] = str(datetime.utcnow().timestamp())[: main.config["Tweaks"]["DedupPrecision"]] castHash = siphash24(main.hashKey, dumps(c, sort_keys=True).encode("utf-8")) del c["approxtime"] - isDuplicate= any(castHash in main.lastEvents[x] for x in main.lastEvents.keys() if not x == numName) + isDuplicate = any(castHash in main.lastEvents[x] for x in main.lastEvents.keys() if not x == numName) if isDuplicate: debug("Duplicate: %s" % (c)) return True if numName in main.lastEvents.keys(): main.lastEvents[numName].insert(0, castHash) - main.lastEvents[numName] = main.lastEvents[numName][0:main.config["Tweaks"]["MaxHash"]] + main.lastEvents[numName] = main.lastEvents[numName][0 : main.config["Tweaks"]["MaxHash"]] else: main.lastEvents[numName] = [castHash] return False diff --git a/utils/get.py b/utils/get.py index 6843479..f455b6c 100644 --- a/utils/get.py +++ b/utils/get.py @@ -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))) diff --git a/utils/loaders/command_loader.py b/utils/loaders/command_loader.py index bc9ecf4..9c4095b 100644 --- a/utils/loaders/command_loader.py +++ b/utils/loaders/command_loader.py @@ -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" + 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) diff --git a/utils/loaders/single_loader.py b/utils/loaders/single_loader.py index 81e5c76..f5219ac 100644 --- a/utils/loaders/single_loader.py +++ b/utils/loaders/single_loader.py @@ -8,16 +8,17 @@ import commands from main import CommandMap + def loadSingle(commandName): - if commandName+".py" in listdir("commands"): - className = commandName.capitalize()+"Command" + if commandName + ".py" in listdir("commands"): + className = commandName.capitalize() + "Command" try: if commandName in CommandMap.keys(): - reload(sys.modules["commands."+commandName]) - CommandMap[commandName] = getattr(sys.modules["commands."+commandName], className) + reload(sys.modules["commands." + 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 diff --git a/utils/logging/debug.py b/utils/logging/debug.py index 4b8c708..80651f7 100644 --- a/utils/logging/debug.py +++ b/utils/logging/debug.py @@ -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) diff --git a/utils/logging/log.py b/utils/logging/log.py index 67b2148..1fd2a0a 100644 --- a/utils/logging/log.py +++ b/utils/logging/log.py @@ -1,8 +1,10 @@ def log(*data): print("[LOG]", *data) + def warn(*data): print("[WARNING]", *data) + def error(*data): print("[ERROR]", *data) diff --git a/utils/logging/send.py b/utils/logging/send.py index 0f4eeee..0623243 100644 --- a/utils/logging/send.py +++ b/utils/logging/send.py @@ -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")