From 530882d32cb328f6a59d891198ae8ee509bc82af Mon Sep 17 00:00:00 2001 From: Test_User Date: Thu, 31 Mar 2022 11:19:15 -0400 Subject: e --- .gitignore | 1 + CoupServ.py | 285 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 286 insertions(+) create mode 100644 .gitignore create mode 100755 CoupServ.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..43b648d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +CoupServConfig.json diff --git a/CoupServ.py b/CoupServ.py new file mode 100755 index 0000000..0bfbb87 --- /dev/null +++ b/CoupServ.py @@ -0,0 +1,285 @@ +#!/usr/bin/env python3 + +import threading +import socket +import json +import math +import time +import ssl +import sys +import os + +def send(msg): + return s.sendall(msg.encode("UTF-8", "surrogateescape")) + +def recv(): + return s.recv(1024).decode("UTF-8", "surrogateescape") + +def save(): + with open("CoupServTmp.json", "w") as config_file: + json.dump(config, config_file, indent='\t', sort_keys=True) + os.replace("CoupServTmp.json", "CoupServConfig.json") + +try: + with open("CoupServConfig.json") as config_file: + config = json.load(config_file) +except FileNotFoundError: + print("No config found! Please make one then try again") + exit() + +s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) + +s.connect(("irc.andrewyu.org", 6666)) + +send("PASS "+config['send_password']+" TS 6 1HC\r\nCAPAB BAN CHW CLUSTER ECHO ENCAP EOPMOD EUID EX IE KLN KNOCK MLOCK QS RSFNC SAVE SERVICES TB UNKLN\r\nSERVER coup.irc.andrewyu.org 0 :Coup Server\r\nSVINFO 6 6 0 :"+str(math.floor(time.time()))+"\r\n") + +msg = "" + +connected_server = "" + +servlist = {} +userlist = {} +chanlist = {} + +def read_and_send(): + for line in sys.stdin: + try: + send(line) + except Exception: + pass + +threading.Thread(target=read_and_send, daemon=True).start() + +try: + while True: + newmsg = recv() + if newmsg == "": + break + msg += newmsg + split_msg = msg.split("\r\n") + if len(split_msg) < 2: + continue + commands = split_msg[0:-1] + msg = split_msg[-1] + for command in commands: + print(command) + + source = "" + if command.startswith(":"): + source = command.split(" ")[0][1:] + command = " ".join(command.split(" ")[1:]) + + lastarg = " :".join(command.split(" :")[1:]) + args = command.split(" :")[0].split(" ")[1:] + args.append(lastarg) + command = command.split(" :")[0].split(" ")[0] + + if command.upper() == "PING": + try: + send(args[1]+" PONG "+args[0]+"\r\n") + except IndexError: + send(":1HC PONG "+args[0]+"\r\n") + elif command.upper() == "PASS": + if source != "": + print("Received PASS from another source!") + continue + if connected_server != "": + print("Received PASS from the server more than once!") + continue + if args[0] != config['accept_password']: + print("Invalid password given by the server!") + exit() + connected_server = args[3] + elif command.upper() == "SERVER": + if source != "": + print("Received SERVER from another source!") + continue + if connected_server == "": + print("Server sent SERVER before PASS!") + exit() + servlist[connected_server] = {"server name": args[0], "hopcount": args[1], "server description": args[2]} + + send("EUID "+config["nick"]+" 0 "+str(math.floor(time.time()))+" +SZio CoupServ hax/CoupServ 127.0.0.1 1HC000001 localhost * :CoupServ\r\n:1HC000001 OPER "+config["nick"]+" admin\r\n") + send("EUID SpamServ 0 "+str(math.floor(time.time()))+" +Zi SpamServ hax/SpamServ 0.0.0.0 1HC000002 0.0.0.0 * :SpamServ\r\n") + for channel in config["channels"]: + send(":1HC000001 JOIN "+str(math.floor(time.time()))+" "+channel+" +\r\n:1HC MODE "+channel+" +ov 1HC000001 1HC000001\r\n") + elif command.upper() == "SID": + servlist[args[2]] = {"server name": args[0], "hopcount": args[1], "server description": args[3]} + elif command.upper() == "EUID": + userlist[args[7]] = {"nickname": args[0], "hopcount": args[1], "nickTS": args[2], "umodes": args[3], "username": args[4], "visible hostname": args[5], "IP address": args[6], "real hostname": args[8], "account name": args[9], "gecos": args[10]} + elif command.upper() == "SJOIN": + chanlist[args[1]] = {"channelTS": args[0], "simple modes": args[2], "mode params": args[3:-1], "nicklist": {}} + for uid in args[-1].split(" "): + mode = {"@": False, "+": False} + if uid.startswith("@"): + mode["@"] = True + uid = uid[1:] + if uid.startswith("+"): + mode["+"] = True + uid = uid[1:] + chanlist[args[1]]["nicklist"][uid] = mode + elif command.upper() == "NICK": + if len(source) == 9: + userlist[source]["nickname"] = args[0] + userlist[source]["nickTS"] = args[1] + elif command.upper() == "QUIT": + try: + del userlist[source] + except KeyError: + continue + for channel in chanlist: + try: + del chanlist[channel]["nicklist"][source] + except KeyError: + pass + elif command.upper() == "KILL": + try: + del userlist[args[0]] + except KeyError: + continue + for channel in chanlist: + try: + del chanlist[channel]["nicklist"][args[0]] + except KeyError: + pass + elif command.upper() == "TMODE": + if int(args[0]) <= int(chanlist[args[1]]["channelTS"]): + modechanges = [] + + dir = "-" + for i in range(0, len(args[2])): + if args[2][i] == "+": + dir = "+" + elif args[2][i] == "-": + dir = "-" + elif args[2][i] == 'o': + if args[3] == "1HC000001" and dir == "-": + modechanges.append(["+", "o", args[3]]) + try: + chanlist[args[1]]["nicklist"][args[3]]['@'] = (dir == "+") + except KeyError: + pass + del args[3] + elif args[2][i] == 'v': + if args[3] == "1HC000001" and dir == "-": + modechanges.append(["+", "v", args[3]]) + try: + chanlist[args[1]]["nicklist"][args[3]]['+'] = (dir == "+") + except KeyError: + pass + del args[3] + elif args[2][i] in ['e', 'I', 'b', 'q', 'k', 'f', 'l', 'j']: + del args[3] + + while len(modechanges) > 0: + modechange = [" "] + dir = "" + for change in modechanges[:4]: + if change[0] != dir: + modechange[0]+=change[0] + dir = change[0] + modechange[0]+=change[1] + modechange.append(change[2]) + send(":1HC000001 MODE "+args[1]+" ".join(modechange)+"\r\n") + modechanges = modechanges[4:] + elif command.upper() == "JOIN": + if len(args) == 1: + if args[0] == '0': + for channel in chanlist: + try: + del chanlist[channel]["nicklist"][source] + except KeyError: + pass + else: + chanlist[args[1]]["nicklist"][source] = {'@': False, '+': False} + elif command.upper() == "PRIVMSG": + if [userlist[source]["username"], userlist[source]["IP address"]] in config["trusted_IDs"]: + if args[0] == "1HC000001" or (args[0].startswith("#") and args[1].startswith("-")): + if args[0] != "1HC000001": + args[1] = args[1][1:] + + if args[1] == "print userlist": + print(userlist) + elif args[1] == "print chanlist": + print(chanlist) + elif args[1] == "print servlist": + print(servlist) + elif args[1].startswith("join "): + chan = args[1].split(" ")[1] + if chan not in config["channels"]: + config["channels"].append(chan) + print("New channel list", config["channels"]) + save() + send(":1HC000001 JOIN "+str(math.floor(time.time()))+" "+chan+" +\r\n") + elif args[1].startswith("part "): + chan = args[1].split(" ")[1] + if chan in config["channels"]: + config["channels"] = [c for c in config["channels"] if c != chan] + save() + send(":1HC000001 PART "+chan+"\r\n") + elif args[1].startswith("sanick "): + current = args[1].split(" ")[1] + target = args[1].split(" ")[2] + for id in userlist: + if userlist[id]["nickname"] == current: + current = id + break + try: + send(":1HC ENCAP * RSFNC "+current+" "+target+" "+str(math.floor(time.time()))+" :"+userlist[current]["nickTS"]+"\r\n") + except KeyError: + continue + elif args[1].startswith("coup "): + chan = args[1].split(" ")[1] + modechanges = [] + for user in chanlist[chan]["nicklist"]: + if [userlist[user]["username"], userlist[user]["IP address"]] in config["trusted_IDs"]: + if not chanlist[chan]["nicklist"][user]["@"]: + chanlist[chan]["nicklist"][user]["@"] = True + modechanges.append(["+", "o", user]) + else: + if chanlist[chan]["nicklist"][user]["@"]: + chanlist[chan]["nicklist"][user]["@"] = False + modechanges.append(["-", "o", user]) + + while len(modechanges) > 0: + modechange = [" "] + dir = "" + for change in modechanges[:4]: + if change[0] != dir: + modechange[0]+=change[0] + dir = change[0] + modechange[0]+=change[1] + modechange.append(change[2]) + send(":1HC000001 MODE "+chan+" ".join(modechange)+"\r\n") + modechanges = modechanges[4:] + elif args[1].startswith("spam "): + chan = args[1].split(" ")[1] + count = int(args[1].split(" ")[2]) + msg = " ".join(args[1].split(" ")[3:]) + send(":1HC000002 JOIN "+str(math.floor(time.time()))+" "+chan+" +\r\n") + for _ in range(count): + send(":1HC000002 PRIVMSG "+chan+" :"+msg+"\r\n") + send(":1HC000002 PART "+chan+"\r\n") + elif args[1].startswith("userspam "): + count = args[1].split(" ")[1] + for i in range(3, max(0, min(int(count), 1000))+3): + send("EUID 1HC"+str(i).zfill(6)+" 0 "+str(math.floor(time.time()))+" +Zi "+str(i)+" hax/SpamServ 0.0.0.0 1HC"+str(i).zfill(6)+" 0.0.0.0 * :SpamServ\r\n:1HC"+str(i).zfill(6)+" JOIN "+str(math.floor(time.time()))+" #spam +\r\n") + elif args[1].startswith("nick "): + nick = args[1].split(" ")[1] + config["nick"] = nick + save() + send(":1HC000001 NICK "+nick+" "+str(math.floor(time.time()))+"\r\n") + elif args[1].startswith("mode "): + send(args[1]+"\r\n") + elif args[1].startswith("echo "): + if args[0] == "1HC000001": + dest = source + else: + dest = args[0] + send(":1HC000001 PRIVMSG "+dest+" :"+" ".join(args[1].split(" ")[1:])+"\r\n") + + elif args[1].startswith(":"): + send(args[1]+"\r\n") +except Exception as e: + config_file.close() + raise e -- cgit v1.2.3