2022-07-21 12:39:59 +00:00
|
|
|
from json import dumps, loads
|
2022-07-21 12:40:09 +00:00
|
|
|
|
|
|
|
from twisted.internet.protocol import Factory, Protocol
|
|
|
|
|
2019-03-18 21:01:28 +00:00
|
|
|
import main
|
2022-07-21 12:40:05 +00:00
|
|
|
from utils.logging.log import log, warn
|
2019-03-18 21:01:28 +00:00
|
|
|
|
2022-07-21 12:39:41 +00:00
|
|
|
validTypes = [
|
|
|
|
"msg",
|
|
|
|
"notice",
|
|
|
|
"action",
|
|
|
|
"who",
|
|
|
|
"part",
|
|
|
|
"join",
|
|
|
|
"kick",
|
|
|
|
"quit",
|
|
|
|
"nick",
|
|
|
|
"topic",
|
|
|
|
"mode",
|
|
|
|
"conn",
|
|
|
|
"znc",
|
|
|
|
"query",
|
|
|
|
"self",
|
|
|
|
"highlight",
|
|
|
|
]
|
|
|
|
|
2019-08-05 21:51:16 +00:00
|
|
|
|
2019-03-18 21:01:28 +00:00
|
|
|
class Relay(Protocol):
|
|
|
|
def __init__(self, addr):
|
|
|
|
self.addr = addr
|
|
|
|
self.authed = False
|
|
|
|
self.subscriptions = []
|
|
|
|
|
|
|
|
def send(self, data):
|
|
|
|
data += "\r\n"
|
|
|
|
data = data.encode("utf-8", "replace")
|
|
|
|
self.transport.write(data)
|
|
|
|
|
|
|
|
def sendErr(self, data):
|
|
|
|
self.send(dumps({"type": "error", "reason": data}))
|
|
|
|
return
|
|
|
|
|
|
|
|
def sendMsg(self, data):
|
|
|
|
self.send(dumps(data))
|
|
|
|
|
|
|
|
def dataReceived(self, data):
|
|
|
|
data = data.decode("utf-8", "replace")
|
|
|
|
try:
|
|
|
|
parsed = loads(data)
|
2022-07-21 12:40:05 +00:00
|
|
|
except: # noqa: E722
|
2019-03-18 21:01:28 +00:00
|
|
|
self.sendErr("MALFORMED")
|
|
|
|
return
|
2022-07-21 12:40:05 +00:00
|
|
|
if "type" not in parsed.keys():
|
2019-03-18 21:01:28 +00:00
|
|
|
self.sendErr("NOTYPE")
|
|
|
|
return
|
|
|
|
if parsed["type"] == "hello":
|
|
|
|
if set(["key", "hello"]).issubset(set(parsed)):
|
|
|
|
self.handleHello(parsed)
|
|
|
|
else:
|
|
|
|
self.sendErr("WRONGFIELDS")
|
|
|
|
return
|
|
|
|
return
|
|
|
|
elif parsed["type"] == "control":
|
|
|
|
if "subscribe" in parsed.keys():
|
2019-08-05 21:51:16 +00:00
|
|
|
if self.authed:
|
|
|
|
self.handleSubscribe(parsed["subscribe"])
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
self.sendErr("DENIED")
|
|
|
|
return
|
2019-03-18 21:01:28 +00:00
|
|
|
elif "unsubscribe" in parsed.keys():
|
2019-08-05 21:51:16 +00:00
|
|
|
if self.authed:
|
|
|
|
self.handleUnsubscribe(parsed["unsubscribe"])
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
self.sendErr("DENIED")
|
|
|
|
return
|
2019-03-18 21:01:28 +00:00
|
|
|
else:
|
|
|
|
self.sendErr("UNCLEAR")
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
self.sendErr("UNCLEAR")
|
|
|
|
return
|
|
|
|
|
|
|
|
def handleSubscribe(self, lst):
|
|
|
|
if not isinstance(lst, list):
|
|
|
|
self.sendErr("NOTLIST")
|
|
|
|
return
|
|
|
|
for i in lst:
|
2022-07-21 12:40:05 +00:00
|
|
|
if i not in validTypes:
|
2019-03-18 21:01:28 +00:00
|
|
|
self.sendErr("NONEXISTANT")
|
|
|
|
return
|
|
|
|
if i in self.subscriptions:
|
|
|
|
self.sendErr("SUBSCRIBED")
|
|
|
|
return
|
|
|
|
self.subscriptions.append(i)
|
2019-03-23 11:39:28 +00:00
|
|
|
self.sendMsg({"type": "success"})
|
|
|
|
return
|
2019-03-18 21:01:28 +00:00
|
|
|
|
|
|
|
def handleUnubscribe(self, lst):
|
|
|
|
if not isinstance(lst, list):
|
|
|
|
self.sendErr("NOTLIST")
|
|
|
|
return
|
|
|
|
for i in lst:
|
2022-07-21 12:40:05 +00:00
|
|
|
if i not in validTypes:
|
2019-03-18 21:01:28 +00:00
|
|
|
self.sendErr("NONEXISTANT")
|
|
|
|
return
|
2022-07-21 12:40:05 +00:00
|
|
|
if i not in self.subscriptions:
|
2019-03-18 21:01:28 +00:00
|
|
|
self.sendErr("NOTSUBSCRIBED")
|
|
|
|
return
|
2019-03-23 18:22:46 +00:00
|
|
|
del self.subscriptions[i]
|
2019-03-23 11:39:28 +00:00
|
|
|
self.sendMsg({"type": "success"})
|
|
|
|
return
|
2019-03-18 21:01:28 +00:00
|
|
|
|
|
|
|
def handleHello(self, parsed):
|
|
|
|
if parsed["key"] in main.tokens.keys():
|
2022-07-21 12:40:03 +00:00
|
|
|
if (
|
|
|
|
parsed["hello"] == main.tokens[parsed["key"]]["hello"]
|
|
|
|
and main.tokens[parsed["key"]]["usage"] == "relay"
|
|
|
|
):
|
2022-07-21 12:40:01 +00:00
|
|
|
self.sendMsg({"type": "hello", "hello": main.tokens[parsed["key"]]["counter"]})
|
2019-03-18 21:01:28 +00:00
|
|
|
self.authed = True
|
|
|
|
else:
|
|
|
|
self.transport.loseConnection()
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
self.sendErr("NOKEY")
|
|
|
|
return
|
|
|
|
|
|
|
|
def connectionMade(self):
|
2019-08-25 20:29:11 +00:00
|
|
|
log("Relay connection from %s:%s" % (self.addr.host, self.addr.port))
|
2022-07-21 12:39:41 +00:00
|
|
|
# self.send("Greetings.")
|
2019-03-18 21:01:28 +00:00
|
|
|
|
|
|
|
def connectionLost(self, reason):
|
|
|
|
self.authed = False
|
2022-07-21 12:40:01 +00:00
|
|
|
log("Relay connection lost from %s:%s -- %s" % (self.addr.host, self.addr.port, reason.getErrorMessage()))
|
2019-03-18 21:01:28 +00:00
|
|
|
if self.addr in main.relayConnections.keys():
|
|
|
|
del main.relayConnections[self.addr]
|
|
|
|
else:
|
|
|
|
warn("Tried to remove a non-existant relay connection.")
|
|
|
|
|
2022-07-21 12:39:41 +00:00
|
|
|
|
2019-03-18 21:01:28 +00:00
|
|
|
class RelayFactory(Factory):
|
|
|
|
def buildProtocol(self, addr):
|
|
|
|
entry = Relay(addr)
|
|
|
|
main.relayConnections[addr] = entry
|
|
|
|
return entry
|
|
|
|
|
|
|
|
def send(self, addr, data):
|
|
|
|
if addr in main.relayConnections.keys():
|
|
|
|
connection = main.relayConnections[addr]
|
|
|
|
connection.send(data)
|
|
|
|
else:
|
|
|
|
return
|
2019-08-05 21:51:16 +00:00
|
|
|
|
2022-07-21 12:39:41 +00:00
|
|
|
|
2019-08-12 20:03:47 +00:00
|
|
|
def sendRelayNotification(cast):
|
2019-08-05 21:51:16 +00:00
|
|
|
for i in main.relayConnections.keys():
|
|
|
|
if main.relayConnections[i].authed:
|
2019-08-11 19:52:10 +00:00
|
|
|
if cast["type"] in main.relayConnections[i].subscriptions:
|
2020-06-02 20:34:15 +00:00
|
|
|
main.relayConnections[i].send(dumps(cast))
|