def execute_command(self, executer, cmd): if not executer.is_manager and cmd.cmd in [cpp.DataType.CMD_KICK.value, cpp.DataType.CMD_PROMOTE.value, cpp.DataType.CMD_DEMOTE.value, cpp.DataType.CMD_MUTE.value, cpp.DataType.CMD_UNMUTE.value]: # executer is not a manager but tries to use manager-only commands self.unicast(executer, cpp.ServerMsg("Error - Permission denied.")) elif cmd.cmd == cpp.DataType.CMD_HELP.value: self.execute_help(executer) elif cmd.cmd == cpp.DataType.CMD_QUIT.value: self.execute_quit(executer) elif cmd.cmd == cpp.DataType.CMD_VIEW.value: self.execute_view_managers(executer) elif cmd.name not in self.group: self.unicast(executer, cpp.ServerMsg(f"Error - '{cmd.name}' is not in the group.")) elif cmd.cmd == cpp.DataType.CMD_TELL.value: self.execute_tell(executer, cmd.name, cmd.msg) elif cmd.cmd == cpp.DataType.CMD_KICK.value: self.execute_kick(cmd.name) elif cmd.cmd == cpp.DataType.CMD_PROMOTE.value: self.execute_promote(cmd.name) elif cmd.cmd == cpp.DataType.CMD_DEMOTE.value: self.execute_demote(cmd.name) elif cmd.cmd == cpp.DataType.CMD_MUTE.value: self.execute_mute(cmd.name) elif cmd.cmd == cpp.DataType.CMD_UNMUTE.value: self.execute_unmute(cmd.name) else: self.unicast(executer, cpp.ServerMsg("Error - Invalid input, try /help."))
def unicast(self, member, cpp_msg): """send a CPP message to a specific member. """ try: cpp.ssend(member.conn, self.aeskey, cpp_msg) except socket.error: # connection has likely been closed self.group.kick(member) self.broadcast(cpp.ServerMsg(f"{member.name} left the chat."))
def handle(self, member, cpp_msg): if type(cpp_msg) is cpp.Cmd: self.execute_command(member, cpp_msg) elif type(cpp_msg) is str and not member.is_muted: if cpp_msg.startswith("DOWNLOAD:"): file_descriptor = int(cpp_msg.split(':', 1)[1]) self.send_file(member, file_descriptor) return if cpp_msg.startswith("FILE:"): filepath = cpp_msg.split(':', 1)[1] self.curr_file_desc += 1 cpp_msg = f"FILE:{self.curr_file_desc}:{filepath}" self.broadcast(cpp.ServerMsg(cpp_msg, name=member.name), exclude=[member]) self.unicast(member, cpp.ServerMsg(cpp_msg, name=member.name)) elif type(cpp_msg) is bytes: self.download_file(cpp_msg) elif member.is_muted: self.unicast(member, cpp.ServerMsg("Error - You are muted, message was not sent."))
def add_pending_member(self): try: conn = self.pending_que.get_nowait() except queue.Empty: # no pending members to add return name = self.recv(conn, secure=False) time.sleep(0.05) pubkey = RSA.import_key(self.recv(conn, secure=False)) if type(name) == str and name: name = name.strip() if name in self.group: cpp.send(conn, cpp.ServerMsg("Connection Refused: Name is already taken.")) conn.close() else: enc_aeskey = PKCS1_OAEP.new(pubkey).encrypt(self.aeskey) cpp.send(conn, enc_aeskey) print(f"RECEIVED PUBKEY: {pubkey.export_key()}") color = choice(Server.COLORS) self.group.add(name, pubkey, conn, color, name in self.MANAGER_NAMES) self.broadcast(cpp.ServerMsg(f"{self.group[name]} joined the chat.")) self.unicast(self.group[name], cpp.ServerMsg("Tip: Type /help to display available commands.")) if len(self.group) == 1: # make first member to join the chat a manager self.group[name].is_manager = True print("#DEBUG# added member " + name + " #members = " + str(len(self.group)))
def execute_unmute(self, name): if name in self.group and self.group[name].is_muted: self.unicast(self.group[name], cpp.ServerMsg("You are no longer muted.")) self.group[name].is_muted = False
def execute_mute(self, name): if name in self.group and not self.group[name].is_muted: self.unicast(self.group[name], cpp.ServerMsg("You have been muted by a manager.")) self.group[name].is_muted = True
def execute_demote(self, name): if name in self.group and self.group[name].is_manager: self.unicast(self.group[name], cpp.ServerMsg("You are no longer a manager.")) self.group[name].is_manager = False
def execute_promote(self, name): if name in self.group and not self.group[name].is_manager: self.unicast(self.group[name], cpp.ServerMsg("You are now a manager.")) self.group[name].is_manager = True
def execute_kick(self, name): if name in self.group: self.broadcast(cpp.ServerMsg(f"{self.group[name].name} has been kicked from the group."), exclude=[self.group[name]]) self.unicast(self.group[name], cpp.ServerMsg("You have been kicked from the group.")) self.group.kick(name)
def execute_tell(self, executer, name, msg): if executer.is_muted: self.unicast(executer, cpp.ServerMsg("Error - You are muted, message was not sent.")) elif name in self.group: self.unicast(executer, cpp.ServerMsg(f"{executer.name} -> {self.group[name].name}: {msg}")) self.unicast(self.group[name], cpp.ServerMsg(f"{executer.name} -> {self.group[name].name}: {msg}"))
def execute_view_managers(self, executer): manager_list = map(lambda memb: str(memb), filter(lambda memb: memb.is_manager, self.group)) self.unicast(executer, cpp.ServerMsg("Managers: " + ", ".join(manager_list)))
def execute_quit(self, executer): self.broadcast(cpp.ServerMsg(f"{executer.name} left the chat.")) self.group.kick(executer)
def execute_help(self, executer): self.unicast(executer, cpp.ServerMsg(self.help_html()))