From e5adcfef4c59f8b5100fc6bdad85bda42427bb2c Mon Sep 17 00:00:00 2001 From: Al Beano Date: Sun, 11 Aug 2019 21:58:14 +0100 Subject: [PATCH] Rework data structures, storing all front-end network data in Network objects --- .gitignore | 6 ++-- commands/alias.py | 61 --------------------------------------- commands/cmd.py | 14 +++++---- commands/del.py | 30 ++++++++++--------- commands/disable.py | 36 +++++++++++++---------- commands/enable.py | 27 +++++++++-------- commands/join.py | 30 +++++++++++-------- commands/list.py | 13 --------- commands/mod.py | 49 ++++++++++++++----------------- commands/msg.py | 19 +++++++----- commands/network.py | 6 ++-- commands/part.py | 17 ++++++----- commands/relay.py | 36 ++++++++++++----------- commands/stats.py | 3 +- conf/example/alias.json | 1 - conf/example/network.json | 1 - conf/example/pool.json | 1 - conf/example/relay.json | 1 - conf/help.json | 22 +++++++------- core/bot.py | 22 +++++++------- core/helper.py | 27 ----------------- main.py | 49 ++++++++++++++++++++----------- modules/network.py | 57 ++++++++++++++++++++++++++++++++++++ threshold | 8 ++--- 24 files changed, 255 insertions(+), 281 deletions(-) delete mode 100644 commands/alias.py delete mode 100644 commands/list.py delete mode 100644 conf/example/alias.json delete mode 100644 conf/example/network.json delete mode 100644 conf/example/pool.json delete mode 100644 conf/example/relay.json delete mode 100644 core/helper.py create mode 100644 modules/network.py diff --git a/.gitignore b/.gitignore index e23d8a6..08f3657 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,13 @@ *.pyc *.pem +*.swp __pycache__/ conf/config.json -conf/pool.json conf/wholist.json conf/counters.json conf/masterbuf.json conf/monitor.json -conf/alias.json -conf/relay.json -conf/network.json conf/tokens.json +conf/network.dat conf/dist.sh env/ diff --git a/commands/alias.py b/commands/alias.py deleted file mode 100644 index ef5ac6f..0000000 --- a/commands/alias.py +++ /dev/null @@ -1,61 +0,0 @@ -import main -from yaml import dump -import modules.alias as alias - -class AliasCommand: - def __init__(self, *args): - self.alias(*args) - - def alias(self, addr, authed, data, obj, spl, success, failure, info, incUsage, length): - if authed: - if length == 8: - if spl[1] == "add": - if spl[2] in main.alias.keys(): - failure("Alias already exists: %s" % spl[2]) - return - else: - main.alias[spl[2]] = {"nick": spl[3], - "altnick": spl[4], - "ident": spl[5], - "realname": spl[6], - "password": spl[7]} - success("Successfully created alias: %s" % spl[2]) - main.saveConf("alias") - return - else: - incUsage("alias") - return - - elif length == 3: - if spl[1] == "del": - if spl[2] in main.alias.keys(): - del main.alias[spl[2]] - success("Successfully removed alias: %s" % spl[2]) - main.saveConf("alias") - return - else: - failure("No such alias: %s" % spl[2]) - return - elif spl[1] == "add" and spl[2] == "auto": - newalias = alias.generate_alias() - while newalias["nick"] in main.alias.keys(): - newalias = alias.generate_alias() - main.alias[newalias["nick"]] = newalias - success("Successfully created alias: %s" % newalias["nick"]) - main.saveConf("alias") - return - else: - incUsage("alias") - return - elif length == 2: - if spl[1] == "list": - info(dump(main.alias)) - return - else: - incUsage("alias") - return - else: - incUsage("alias") - return - else: - incUsage(None) diff --git a/commands/cmd.py b/commands/cmd.py index 6c75ec5..819789b 100644 --- a/commands/cmd.py +++ b/commands/cmd.py @@ -8,14 +8,16 @@ class CmdCommand: def cmd(self, addr, authed, data, obj, spl, success, failure, info, incUsage, length): if authed: if length > 4: - if not spl[1] in main.relay.keys(): - failure("No such relay: %s" % spl[1]) + if not spl[1] in main.network.keys(): + failure("No such network: %s" % spl[1]) + return + if not int(spl[2]) in main.network[spl[1]].relays.keys(): + failure("No such relay: %s on network: %s" % (spl[2], spl[1])) return - commands = {spl[3]: [" ".join(spl[4:])]} - print(" ".join(spl[4:])) - success("Sending commands to relay %s as user %s" % (spl[1], spl[2])) - deliverRelayCommands(spl[1], commands, user=spl[2]) + commands = {spl[4]: [" ".join(spl[5:])]} + success("Sending commands to relay %s as user %s" % (spl[2], spl[3])) + deliverRelayCommands(main.network[spl[1]].relays[spl[2]], commands, user=spl[3]+"/"+spl[1]) return else: incUsage("cmd") diff --git a/commands/del.py b/commands/del.py index ef6f9ad..eb59eaa 100644 --- a/commands/del.py +++ b/commands/del.py @@ -6,21 +6,25 @@ class DelCommand: def delete(self, addr, authed, data, obj, spl, success, failure, info, incUsage, length): if authed: - if length == 2: - if not spl[1] in main.pool.keys(): - failure("Name does not exist: %s" % spl[1]) + if length == 3: + if not spl[1] in main.network.keys(): + failure("No such network: %s" % spl[1]) return - del main.pool[spl[1]] - if spl[1] in main.ReactorPool.keys(): - if spl[1] in main.FactoryPool.keys(): - main.FactoryPool[spl[1]].stopTrying() - main.ReactorPool[spl[1]].disconnect() - if spl[1] in main.IRCPool.keys(): - del main.IRCPool[spl[1]] - del main.ReactorPool[spl[1]] - del main.FactoryPool[spl[1]] + if not int(spl[2]) in main.network[spl[1]].relays.keys(): + failure("No such relay: %s in network %s" % (spl[2], spl[1])) + return + + main.network[spl[1]].delete_relay(int(spl[2])) + if spl[1]+spl[2] in main.ReactorPool.keys(): + if spl[1]+spl[2] in main.FactoryPool.keys(): + main.FactoryPool[spl[1]+spl[2]].stopTrying() + main.ReactorPool[spl[1]+spl[2]].disconnect() + if spl[1]+spl[2] in main.IRCPool.keys(): + del main.IRCPool[spl[1]+spl[2]] + del main.ReactorPool[spl[1]+spl[2]] + del main.FactoryPool[spl[1]+spl[2]] success("Successfully removed bot: %s" % spl[1]) - main.saveConf("pool") + main.saveConf("network") return else: incUsage("del") diff --git a/commands/disable.py b/commands/disable.py index d9182fd..20ace48 100644 --- a/commands/disable.py +++ b/commands/disable.py @@ -7,26 +7,30 @@ class DisableCommand: def disable(self, addr, authed, data, obj, spl, success, failure, info, incUsage, length): if authed: - if length == 2: - if not spl[1] in main.pool.keys(): - failure("Name does not exist: %s" % spl[1]) + if length == 3: + if not spl[1] in main.network.keys(): + failure("No such network: %s" % spl[1]) return - main.pool[spl[1]]["enabled"] = False - user = main.pool[spl[1]]["alias"] - network = main.pool[spl[1]]["network"] - relay = main.pool[spl[1]]["relay"] + if not int(spl[2]) in main.network[spl[1]].relays.keys(): + failure("No such relay: %s in network %s" % (spl[2], spl[1])) + return + + main.network[spl[1]].relays[int(spl[2])]["enabled"] = False + user = main.network[spl[1]].aliases[int(spl[2])] + network = spl[1] + relay = main.network[spl[1]].relays[int(spl[2])] commands = {"status": ["Disconnect"]} deliverRelayCommands(relay, commands, user=user+"/"+network) - main.saveConf("pool") - if spl[1] in main.ReactorPool.keys(): - if spl[1] in main.FactoryPool.keys(): - main.FactoryPool[spl[1]].stopTrying() - main.ReactorPool[spl[1]].disconnect() + main.saveConf("network") + if spl[1]+spl[2] in main.ReactorPool.keys(): + if spl[1]+spl[2] in main.FactoryPool.keys(): + main.FactoryPool[spl[1]+spl[2]].stopTrying() + main.ReactorPool[spl[1]+spl[2]].disconnect() if spl[1] in main.IRCPool.keys(): - del main.IRCPool[spl[1]] - del main.ReactorPool[spl[1]] - del main.FactoryPool[spl[1]] - success("Successfully disabled bot %s" % spl[1]) + del main.IRCPool[spl[1]+spl[2]] + del main.ReactorPool[spl[1]+spl[2]] + del main.FactoryPool[spl[1]+spl[2]] + success("Successfully disabled bot %s on network %s" % (spl[2], spl[1])) return else: incUsage("disable") diff --git a/commands/enable.py b/commands/enable.py index 81f1139..e25857b 100644 --- a/commands/enable.py +++ b/commands/enable.py @@ -1,5 +1,4 @@ import main -from core.helper import startBot from core.bot import deliverRelayCommands class EnableCommand: @@ -8,22 +7,26 @@ class EnableCommand: def enable(self, addr, authed, data, obj, spl, success, failure, info, incUsage, length): if authed: - if length == 2: - if not spl[1] in main.pool.keys(): - failure("Name does not exist: %s" % spl[1]) + if length == 3: + if not spl[1] in main.network.keys(): + failure("No such network: %s" % spl[1]) return - main.pool[spl[1]]["enabled"] = True - user = main.pool[spl[1]]["alias"] - network = main.pool[spl[1]]["network"] - relay = main.pool[spl[1]]["relay"] + if not int(spl[2]) in main.network[spl[1]].relays.keys(): + failure("No such relay: %s in network %s" % (spl[2], spl[1])) + return + + main.network[spl[1]].relays[int(spl[2])]["enabled"] = True + user = main.network[spl[1]].aliases[int(spl[2])] + network = spl[1] + relay = main.network[spl[1]].relays[int(spl[2])] commands = {"status": ["Connect"]} deliverRelayCommands(relay, commands, user=user+"/"+network) - main.saveConf("pool") - if not spl[1] in main.IRCPool.keys(): - startBot(spl[1]) + main.saveConf("network") + if not spl[1]+spl[2] in main.IRCPool.keys(): + main.network[spl[1]].start_bot(int(spl[2])) else: pass - success("Successfully enabled bot %s" % spl[1]) + success("Successfully enabled bot %s on network %s" % (spl[2], spl[1])) return else: incUsage("enable") diff --git a/commands/join.py b/commands/join.py index edf6577..2f36ab4 100644 --- a/commands/join.py +++ b/commands/join.py @@ -6,25 +6,31 @@ class JoinCommand: def join(self, addr, authed, data, obj, spl, success, failure, info, incUsage, length): if authed: - if length == 3: - if not spl[1] in main.pool.keys(): - failure("Name does not exist: %s" % spl[1]) + if length == 4: + if not spl[1] in main.network.keys(): + failure("Network does not exist: %s" % spl[1]) return - if not spl[1] in main.IRCPool.keys(): + 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]) return - main.IRCPool[spl[1]].join(spl[2]) - success("Joined %s" % spl[2]) + main.IRCPool[spl[1]+spl[2]].join(spl[3]) + success("Joined %s" % spl[3]) return - elif length == 4: - if not spl[1] in main.pool.keys(): - failure("Name does not exist: %s" % spl[1]) + elif length == 5: + if not spl[1] in main.network.keys(): + failure("Network does not exist: %s" % spl[1]) + return + 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] 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]].join(spl[2], spl[3]) - success("Joined %s with key %s" % (spl[2], spl[3])) + main.IRCPool[spl[1]+spl[2]].join(spl[3], spl[4]) + success("Joined %s with key %s" % (spl[3], spl[4])) return else: incUsage("join") diff --git a/commands/list.py b/commands/list.py deleted file mode 100644 index 55ba053..0000000 --- a/commands/list.py +++ /dev/null @@ -1,13 +0,0 @@ -import main -from yaml import dump - -class ListCommand: - def __init__(self, *args): - self.list(*args) - - def list(self, addr, authed, data, obj, spl, success, failure, info, incUsage, length): - if authed: - info(dump(main.pool)) - return - else: - incUsage(None) diff --git a/commands/mod.py b/commands/mod.py index 7f5a822..611ab9b 100644 --- a/commands/mod.py +++ b/commands/mod.py @@ -2,49 +2,42 @@ import main from yaml import dump class ModCommand: + # This could be greatly improved, but not really important right now def __init__(self, *args): self.mod(*args) def mod(self, addr, authed, data, obj, spl, success, failure, info, incUsage, length): if authed: - if length == 2: - if not spl[1] in main.pool.keys(): - failure("Name does not exist: %s" % spl[1]) + if length == 4: + if not spl[1] in main.network.keys(): + failure("Network does not exist: %s" % spl[1]) return - info(dump({spl[1]: main.pool[spl[1]]})) - return - elif length == 3: - if not spl[1] in main.pool.keys(): - failure("Name does not exist: %s" % spl[1]) - return - if not spl[2] in main.pool[spl[1]].keys(): - failure("No such key: %s" % spl[2]) + try: + setattr(main.network[spl[1]], spl[2], spl[3]) + except e: + failure("Something went wrong.") return - info("%s: %s" % (spl[2], main.pool[spl[1]][spl[2]])) + + main.saveConf("network") + success("Successfully set key %s to %s on %s" % (spl[2], spl[3], spl[1])) return - elif length == 4: - if not spl[1] in main.pool.keys(): - failure("Name does not exist: %s" % spl[1]) + elif length == 6: + if not spl[1] in main.network.keys(): + failure("Network does not exist: %s" % spl[1]) return - if not spl[2] in main.pool[spl[1]].keys(): - failure("No such key: %s" % spl[2]) + if not int(spl[3]) in main.network[spl[1]].relays.keys(): + failure("Relay/alias does not exist: %s" % spl[3]) return - if spl[3] == main.pool[spl[1]][spl[2]]: - failure("Value already exists: %s" % spl[3]) + try: + x = getattr(main.network[spl[1]], spl[2]) + x[spl[3]] = spl[4] + except e: + failure("Something went wrong.") return - if spl[2] == "enabled": - failure("Use the enable and disable commands to manage this") - return - - main.pool[spl[1]][spl[2]] = spl[3] - main.saveConf("pool") - success("Successfully set key %s to %s on %s" % (spl[2], spl[3], spl[1])) - return - else: incUsage("mod") return diff --git a/commands/msg.py b/commands/msg.py index 001cbe8..4ea2b2f 100644 --- a/commands/msg.py +++ b/commands/msg.py @@ -6,17 +6,20 @@ class MsgCommand: def msg(self, addr, authed, data, obj, spl, success, failure, info, incUsage, length): if authed: - if length >= 4: - if not spl[1] in main.pool.keys(): - failure("Name does not exist: %s" % spl[1]) + if length >= 5: + if not spl[1] in main.network.keys(): + failure("Network does not exist: %s" % spl[1]) return - if not spl[1] in main.IRCPool.keys(): + 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]) return - if not spl[2] in main.IRCPool[spl[1]].channels: - info("Bot not on channel: %s" % spl[2]) - main.IRCPool[spl[1]].msg(spl[2], " ".join(spl[3:])) - success("Sent %s to %s on %s" % (" ".join(spl[3:]), spl[2], spl[1])) + 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:])) + success("Sent %s to %s on relay %s on network %s" % (" ".join(spl[4:]), spl[3], spl[2], spl[1])) return else: incUsage("msg") diff --git a/commands/network.py b/commands/network.py index 9f0d67a..a4d04f2 100644 --- a/commands/network.py +++ b/commands/network.py @@ -1,5 +1,6 @@ import main from yaml import dump +from modules.network import Network class NetworkCommand: def __init__(self, *args): @@ -22,10 +23,7 @@ class NetworkCommand: failure("Auth must be sasl, ns or none, not %s" % spl[5]) return else: - main.network[spl[2]] = {"host": spl[3], - "port": spl[4], - "security": spl[5].lower(), - "auth": spl[6].lower()} + main.network[spl[2]] = Network(spl[2], spl[3], spl[4], spl[5].lower(), spl[6].lower()) success("Successfully created network: %s" % spl[2]) main.saveConf("network") return diff --git a/commands/part.py b/commands/part.py index a63a20d..e34d7ff 100644 --- a/commands/part.py +++ b/commands/part.py @@ -6,15 +6,18 @@ class PartCommand: def part(self, addr, authed, data, obj, spl, success, failure, info, incUsage, length): if authed: - if length == 3: - if not spl[1] in main.pool.keys(): - failure("Name does not exist: %s" % spl[1]) + if length == 4: + if not spl[1] in main.network.keys(): + failure("Network does not exist: %s" % spl[1]) return - if not spl[1] in main.IRCPool.keys(): - failure("Name has no instance: %s" % spl[1]) + if not int(spl[2]) in main.network[spl[1]].relays.keys(): + failure("Relay % does not exist on network %", (spl[2], spl[1])) return - main.IRCPool[spl[1]].part(spl[2]) - success("Left %s" % 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]) + success("Left %s" % spl[3]) return else: incUsage("part") diff --git a/commands/relay.py b/commands/relay.py index 92ba014..4736950 100644 --- a/commands/relay.py +++ b/commands/relay.py @@ -9,40 +9,42 @@ class RelayCommand: if authed: if length == 7: if spl[1] == "add": - if spl[2] in main.relay.keys(): - failure("Relay already exists: %s" % spl[2]) + if spl[2] not in main.network.keys(): + failure("No such network: %s" % spl[2]) return if not spl[4].isdigit(): failure("Port must be an integer, not %s" % spl[4]) return else: - main.relay[spl[2]] = {"host": spl[3], - "port": spl[4], - "user": spl[5], - "password": spl[6]} - success("Successfully created relay: %s" % spl[2]) - main.saveConf("relay") + id, alias = main.network[spl[2]].add_relay(spl[3], spl[4], spl[5], spl[6]) + success("Successfully created relay %s on network %s with alias %s" % (str(id), spl[2], alias)) + main.saveConf("network") return else: incUsage("relay") return - elif length == 3: + elif length == 4: if spl[1] == "del": - if spl[2] in main.relay.keys(): - del main.relay[spl[2]] - success("Successfully removed relay: %s" % spl[2]) - main.saveConf("relay") + if spl[2] not in main.network.keys(): + failure("No such network: %s" % spl[2]) return - else: - failure("No such relay: %s" % spl[2]) + if int(spl[3]) not in main.network[spl[2]].relays.keys(): + failure("No such relay: %s on network %s" % (spl[3], spl[2])) return + main.network[spl[2]].delete_relay(int(spl[3])) + success("Successfully deleted relay %s on network %s" % (spl[3], spl[2])) + main.saveConf("network") + return else: incUsage("relay") return - elif length == 2: + elif length == 3: if spl[1] == "list": - info(dump(main.relay)) + if spl[2] not in main.network.keys(): + failure("No such network: %s" % spl[2]) + return + info(dump(main.network[spl[2]].relays)) return else: incUsage("relay") diff --git a/commands/stats.py b/commands/stats.py index 3281a19..e205d02 100644 --- a/commands/stats.py +++ b/commands/stats.py @@ -17,8 +17,7 @@ class StatsCommand: numChannels += len(main.IRCPool[i].channels) numWhoEntries += userinfo.getNumTotalWhoEntries() stats.append("Registered servers:") - stats.append(" Total: %s" % len(main.pool.keys())) - stats.append(" Unique: %s" % len(main.nets())) + stats.append(" Total: %s" % len(main.network.keys())) stats.append("Online servers:") stats.append(" Total: %s" % len(main.IRCPool.keys())) stats.append(" Unique: %s" % len(main.liveNets())) diff --git a/conf/example/alias.json b/conf/example/alias.json deleted file mode 100644 index 0967ef4..0000000 --- a/conf/example/alias.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/conf/example/network.json b/conf/example/network.json deleted file mode 100644 index 0967ef4..0000000 --- a/conf/example/network.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/conf/example/pool.json b/conf/example/pool.json deleted file mode 100644 index 0967ef4..0000000 --- a/conf/example/pool.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/conf/example/relay.json b/conf/example/relay.json deleted file mode 100644 index 0967ef4..0000000 --- a/conf/example/relay.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/conf/help.json b/conf/help.json index b4a3205..5fdaab5 100644 --- a/conf/help.json +++ b/conf/help.json @@ -1,29 +1,27 @@ { "pass": "pass ", "logout": "logout", - "del": "del ", - "mod": "mod [] []", - "get": "get ", + "del": "del ", + "mod": "mod ", + "get": "get ", "key": "key [] [] [] []", "who": "who ", - "join": "join []", - "part": "part ", - "enable": "enable ", - "disable": "disable ", - "list": "list", + "join": "join []", + "part": "part ", + "enable": "enable ", + "disable": "disable ", "stats": "stats []", "save": "save <(file)|list|all>", "load": "load <(file)|list|all>", "dist": "dist", "loadmod": "loadmod ", - "msg": "msg ", + "msg": "msg ", "mon": "mon -h", "chans": "chans [ ...]", "users": "users [ ...]", - "alias": "alias [ OR auto]", - "relay": "relay [ ]", + "relay": "relay [ | | ]", "network": "network [
]", "provision": "provision []", - "cmd": "cmd ", + "cmd": "cmd ", "token": "token [] []" } diff --git a/core/bot.py b/core/bot.py index bb91bc7..def9e2a 100644 --- a/core/bot.py +++ b/core/bot.py @@ -20,13 +20,14 @@ from utils.logging.send import * from twisted.internet.ssl import DefaultOpenSSLContextFactory def deliverRelayCommands(relay, relayCommands, user=None, stage2=None): + # where relay is a dictionary extracted from the Network object 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(None, relay, relayCommands, user, stage2) - rct = reactor.connectSSL(main.relay[relay]["host"], - int(main.relay[relay]["port"]), + rct = reactor.connectSSL(relay["host"], + int(relay["port"]), bot, contextFactory) class IRCRelay(IRCClient): @@ -34,10 +35,10 @@ class IRCRelay(IRCClient): self.connected = False self.buffer = "" if user == None: - self.user = main.relay[relay]["user"] + self.user = relay["user"] else: self.user = user - password = main.relay[relay]["password"] + password = relay["password"] self.nickname = self.user self.realname = self.user self.username = self.user @@ -88,7 +89,7 @@ class IRCRelay(IRCClient): return class IRCBot(IRCClient): - def __init__(self, name): + def __init__(self, name, relay): self.connected = False self.channels = [] self.net = "".join([x for x in name if not x in digits]) @@ -96,14 +97,11 @@ class IRCBot(IRCClient): error("Network with all numbers: %s" % name) self.buffer = "" self.name = name - inst = main.pool[name] - alias = main.alias[inst["alias"]] - relay = main.relay[inst["relay"]] - network = main.network[inst["network"]] + alias = relay["alias"] self.nickname = alias["nick"] self.realname = alias["realname"] - self.username = inst["alias"]+"/"+inst["network"] + self.username = alias["nick"]+"/"+relay["net"] self.password = relay["password"] self.userinfo = None self.fingerReply = None @@ -448,7 +446,7 @@ class IRCBotFactory(ReconnectingClientFactory): self.name = name self.net = "".join([x for x in self.name if not x in digits]) else: - self.name = "Relay to "+relay + self.name = "Relay to "+relay["net"]+relay["id"] self.client = None self.maxDelay = main.config["Tweaks"]["Delays"]["MaxDelay"] self.initialDelay = main.config["Tweaks"]["Delays"]["InitialDelay"] @@ -459,7 +457,7 @@ class IRCBotFactory(ReconnectingClientFactory): def buildProtocol(self, addr): if self.relay == None: - entry = IRCBot(self.name) + entry = IRCBot(self.name, self.relay) main.IRCPool[self.name] = entry else: entry = IRCRelay(self.relay, self.relayCommands, self.user, self.stage2) diff --git a/core/helper.py b/core/helper.py deleted file mode 100644 index 3d4dd55..0000000 --- a/core/helper.py +++ /dev/null @@ -1,27 +0,0 @@ -from twisted.internet import reactor -from core.bot import IRCBot, IRCBotFactory -from twisted.internet.ssl import DefaultOpenSSLContextFactory -import main -from utils.logging.log import * - -def startBot(name): - inst = main.pool[name] - relay, alias, network = inst["relay"], inst["alias"], inst["network"] - host = main.relay[relay]["host"] - port = int(main.relay[relay]["port"]) - - log("Started bot %s to %s network %s" % (name, relay, network)) - - 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(name) - rct = reactor.connectSSL(host, - port, - bot, contextFactory) - - main.ReactorPool[name] = rct - main.FactoryPool[name] = bot - return - diff --git a/main.py b/main.py index 67664df..901c191 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,5 @@ -from json import load, dump, loads +import json +import pickle from redis import StrictRedis from string import digits from utils.logging.log import * @@ -7,17 +8,17 @@ configPath = "conf/" certPath = "cert/" filemap = { - "config": ["config.json", "configuration"], - "pool": ["pool.json", "network, alias and relay mappings"], - "help": ["help.json", "command help"], - "counters": ["counters.json", "counters file"], - "masterbuf": ["masterbuf.json", "master buffer"], - "monitor": ["monitor.json", "monitoring database"], - "alias": ["alias.json", "alias details"], - "relay": ["relay.json", "relay list"], - "network": ["network.json", "network list"], - "tokens": ["tokens.json", "authentication tokens"], - "aliasdata": ["aliasdata.json", "data for alias generation"] + # JSON configs + "config": ["config.json", "configuration", "json"], + "help": ["help.json", "command help", "json"], + "counters": ["counters.json", "counters file", "json"], + "masterbuf": ["masterbuf.json", "master buffer", "json"], + "monitor": ["monitor.json", "monitoring database", "json"], + "tokens": ["tokens.json", "authentication tokens", "json"], + "aliasdata": ["aliasdata.json", "data for alias generation", "json"], + + # Binary (pickle) configs + "network": ["network.dat", "network list", "pickle"] } connections = {} @@ -48,13 +49,27 @@ def liveNets(): return networks def saveConf(var): - with open(configPath+filemap[var][0], "w") as f: - dump(globals()[var], f, indent=4) - return + if filemap[var][2] == "json": + 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: + pickle.dump(globals()[var], f) + else: + raise Exception("invalid format") def loadConf(var): - with open(configPath+filemap[var][0], "r") as f: - globals()[var] = load(f) + if filemap[var][2] == "json": + with open(configPath+filemap[var][0], "r") as f: + globals()[var] = json.load(f) + elif filemap[var][2] == "pickle": + try: + 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(): diff --git a/modules/network.py b/modules/network.py new file mode 100644 index 0000000..5a89126 --- /dev/null +++ b/modules/network.py @@ -0,0 +1,57 @@ +import json +import modules.alias as alias +from twisted.internet import reactor +from core.bot import IRCBot, IRCBotFactory +from twisted.internet.ssl import DefaultOpenSSLContextFactory +import main +from utils.logging.log import * + +class Network: + def __init__(self, name, host, port, security, auth): + self.name = name + self.host = host + self.port = port + self.security = security + self.auth = auth + + self.last = 0 + self.relays = {} + self.aliases = {} + + def add_relay(self, host, port, user, password): + self.last += 1 + self.relays[self.last] = { + "host": host, + "port": port, + "user": user, + "password": password, + "enabled": False, + "net": self.name, + "id": self.last + } + self.aliases[self.last] = alias.generate_alias() + return self.last, self.aliases[self.last]["nick"] + + def delete_relay(self, id): + del self.relays[id] + del self.aliases[id] + + def start_bot(self, relay): + # a single name is given to relays in the backend + # e.g. freenode1 for the first relay on freenode network + name = self.name + relay + 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(name) + rct = reactor.connectSSL(k, port, bot, contextFactory) + + main.ReactorPool[name] = rct + main.FactoryPool[name] = bot + + log("Started bot on relay %s on %s", (relay, self.host)) + + def start_bots(self): + for relay in self.relays: + if relay["enabled"]: + start_bot(relay) diff --git a/threshold b/threshold index 5ff3a3f..b073067 100755 --- a/threshold +++ b/threshold @@ -11,7 +11,6 @@ main.initMain() from utils.logging.log import * from utils.loaders.command_loader import loadCommands -from core.helper import startBot from core.server import Server, ServerFactory from core.relay import Relay, RelayFactory import modules.counters @@ -33,10 +32,7 @@ if __name__ == "__main__": else: reactor.listenTCP(main.config["Relay"]["Port"], relay, interface=main.config["Relay"]["Address"]) log("Threshold relay running on %s:%s" % (main.config["Relay"]["Address"], main.config["Relay"]["Port"])) - for i in main.pool.keys(): - if not "enabled" in main.pool[i]: - continue - if main.pool[i]["enabled"] == True: - startBot(i) + for net in main.network.keys(): + main.network[net].start_bots() modules.counters.setupCounterLoop() reactor.run()