def ooc_cmd_desc(client, arg): """ Set an area description that appears to the user any time they enter the area. Usage: /desc [desc] """ if client.blinded: raise ClientError("You are blinded!") if len(arg) == 0: desc = client.area.desc if client.area.dark: desc = client.area.desc_dark client.send_ooc(f"Description: {desc}") database.log_area("desc.request", client, client.area) else: if client.area.cannot_ic_interact(client): raise ClientError("You are not on the area's invite list!") if (not client.is_mod and not (client in client.area.owners) and client.char_id == -1): raise ClientError("You may not do that while spectating!") if client.area.dark: if not client.is_mod and not (client in client.area.owners): raise ClientError("You must be authorized to do that.") client.area.desc_dark = arg.strip() else: client.area.desc = arg.strip() desc = arg[:128] if len(arg) > len(desc): desc += "... Use /desc to read the rest." client.area.broadcast_ooc( f"{client.showname} changed the area description to: {desc}.") database.log_area("desc.change", client, client.area, message=arg)
def ooc_cmd_status(client, arg): """ Show or modify the current status of an area. Usage: /status <idle|rp|casing|looking-for-players|lfp|recess|gaming> """ if not client.area.area_manager.arup_enabled: raise AreaError("This hub does not use the /status system.") if len(arg) == 0: client.send_ooc(f"Current status: {client.area.status}") else: if (not client.area.can_change_status and not client.is_mod and client not in client.area.owners): raise AreaError( "This area's status cannot be changed by anyone who's not a CM or mod!" ) if client.area.cannot_ic_interact(client): raise AreaError("You are not on the area's invite list!") if (not client.is_mod and client not in client.area.owners and client.char_id == -1): raise ClientError("You may not do that while spectating!") try: client.area.change_status(arg) client.area.broadcast_ooc("{} changed status to {}.".format( client.showname, client.area.status)) database.log_area("status", client, client.area, message=arg) except AreaError: raise
def ooc_cmd_bg(client, arg): """ Set the background of an area. Usage: /bg <background> """ if len(arg) == 0: pos_lock = "" if len(client.area.pos_lock) > 0: pos = ", ".join(str(lpos) for lpos in client.area.pos_lock) pos_lock = f"\nAvailable positions: {pos}." client.send_ooc( f"Current background is {client.area.background}.{pos_lock}") return if client not in client.area.owners and not client.is_mod and client.area.bg_lock: raise AreaError("This area's background is locked!") if client.area.cannot_ic_interact(client): raise AreaError("You are not on the area's invite list!") if (not client.is_mod and not (client in client.area.owners) and client.char_id == -1): raise ClientError("You may not do that while spectating!") if client.area.dark and not client.is_mod and not (client in client.area.owners): raise ClientError("You must be authorized to do that.") try: client.area.change_background(arg) except AreaError: raise client.area.broadcast_ooc( f"{client.showname} changed the background to {arg}.") database.log_area("bg", client, client.area, message=arg)
def ooc_cmd_bg(client, arg): """ Set the background of an area. Usage: /bg <background> """ if len(arg) == 0: pos_lock = '' if len(client.area.pos_lock) > 0: pos = ' '.join(str(l) for l in client.area.pos_lock) pos_lock = f'\nAvailable positions: {pos}.' client.send_ooc(f'Current background is {client.area.background}.{pos_lock}') return if not client in client.area.owners and not client.is_mod and client.area.bg_lock: raise AreaError("This area's background is locked!") if client.area.cannot_ic_interact(client): raise AreaError("You are not on the area's invite list!") if not client.is_mod and not (client in client.area.owners) and client.char_id == -1: raise ClientError("You may not do that while spectating!") try: client.area.change_background(arg) except AreaError: raise client.area.broadcast_ooc( f'{client.showname} changed the background to {arg}.') database.log_area('bg', client, client.area, message=arg)
def ooc_cmd_uninvite(client, arg): """ Revoke an invitation for a particular user. ID can be * to uninvite everyone in the area. Usage: /uninvite <id> """ if not arg: raise ClientError('You must specify a target. Use /uninvite <id>') args = arg.split(' ') try: if args[0] == '*': targets = [c for c in client.area.clients if c != client and c != client.area.owners] else: targets = client.server.client_manager.get_targets(client, TargetType.ID, int(args[0]), False) except ValueError: raise ArgumentError('Area ID must be a number or *.') if targets: try: for c in targets: client.send_ooc( "You have removed {} from the whitelist.".format( c.showname)) c.send_ooc( "You were removed from the area whitelist.") database.log_area('uninvite', client, client.area, target=c) client.area.invite_list.discard(c.id) except AreaError: raise except ClientError: raise else: client.send_ooc("No targets found.")
def remove_client(self, client): """Remove a disconnected client from the area.""" if client.hidden_in != None: client.hide(False, hidden=True) if self.area_manager.single_cm: # Remove their owner status due to single_cm pref. remove_owner will unlock the area if they were the last CM. if client in self.owners: self.remove_owner(client) client.send_ooc( 'You can only be a CM of a single area in this hub.') if self.locking_allowed: # Since anyone can lock/unlock, unlock if we were the last client in this area and it was locked. if len(self.clients) - 1 <= 0: if self.locked: self.unlock() self.clients.remove(client) if client in self.afkers: self.afkers.remove(client) self.server.client_manager.toggle_afk(client) if self.jukebox: self.remove_jukebox_vote(client, True) if len(self.clients) == 0: self.change_status('IDLE') database.log_area('area.leave', client, self) if not client.hidden: self.area_manager.send_arup_players()
def ooc_cmd_uncharcurse(client, arg): """ Remove the character choice restrictions from a user. Usage: /uncharcurse <id> """ if len(arg) == 0: raise ArgumentError("You must specify a target (an ID).") args = arg.split() try: targets = client.server.client_manager.get_targets( client, TargetType.ID, int(args[0]), False) except Exception: raise ArgumentError( "You must specify a valid target! Make sure it is a valid ID.") if targets: for c in targets: if len(c.charcurse) > 0: c.charcurse = [] database.log_area("uncharcurse", client, client.area, target=c) client.send_ooc(f"Uncharcursed [{c.id}].") c.char_select() else: client.send_ooc(f"[{c.id}] is not charcursed.") else: client.send_ooc("No targets found.")
def ooc_cmd_ungm(client, arg): """ Remove a game master from the current Hub. If blank, demote yourself from being a GM. Usage: /ungm <id> """ if len(arg) > 0: arg = arg.split() else: arg = [client.id] for _id in arg: try: _id = int(_id) c = client.server.client_manager.get_targets( client, TargetType.ID, _id, False)[0] if c in client.area.area_manager.owners: client.area.area_manager.remove_owner(c) database.log_area('gm.remove', client, client.area, target=c) else: client.send_ooc( 'You cannot remove someone from GMing when they aren\'t a GM.' ) except (ValueError, IndexError): client.send_ooc( f'{id} does not look like a valid ID.') except (ClientError, ArgumentError): raise
def ooc_cmd_invite(client, arg): """ Allow a particular user to join a locked or speak in spectator-only area. ID can be * to invite everyone in the current area. Usage: /invite <id> """ if not arg: msg = 'Current invite list:\n' msg += '\n'.join([f'[{c.id}] {c.showname}' for c in client.server.client_manager.clients if c.id in client.area.invite_list]) msg += '\nUse /invite <id> to invite someone.' client.send_ooc(msg) return args = arg.split(' ') try: if args[0] == '*': targets = [c for c in client.area.clients if c != client and c != client.area.owners] else: targets = client.server.client_manager.get_targets(client, TargetType.ID, int(args[0]), False) except ValueError: raise ArgumentError('Area ID must be a number or *.') try: for c in targets: client.area.invite_list.add(c.id) client.send_ooc(f'{c.showname} is invited to your area.') c.send_ooc( f'You were invited and given access to {client.area.name}.') database.log_area('invite', client, client.area, target=c) except: raise ClientError('You must specify a target. Use /invite <id>')
def ooc_cmd_evidence_add(client, arg): """ Add a piece of evidence. For sentences with spaces the arg should be surrounded in ""'s, for example /evidence_add Chair "It's a chair." chair.png Usage: /evidence_add [name] [desc] [image] """ try: max_args = 3 # Get the user input args = shlex.split(arg) if len(args) > 3: raise ArgumentError( f"Too many arguments! Make sure to surround your args in \"\"'s if there's spaces. (/evidence_add {arg})" ) # fill the rest of it with asterisk to fill to max_args args = args + ([""] * (max_args - len(args))) if args[0] == "": args[0] = "<name>" if args[1] == "": args[1] = "<description>" if args[2] == "": args[2] = "empty.png" except ValueError as ex: client.send_ooc(f'{ex} (/evidence_add {arg})') return client.area.evi_list.add_evidence(client, args[0], args[1], args[2], "all") database.log_area("evidence.add", client, client.area) client.area.broadcast_evidence_list() client.send_ooc(f"You have added evidence '{args[0]}'.")
def ooc_cmd_evidence_mod(client, arg): """ Change the evidence privilege mode. Refer to the documentation for more information on the function of each mode. Usage: /evidence_mod <FFA|Mods|CM|HiddenCM> """ if not arg or arg == client.area.evidence_mod: client.send_ooc(f"current evidence mod: {client.area.evidence_mod}") elif arg in ["FFA", "Mods", "CM", "HiddenCM"]: if not client.is_mod: if client.area.evidence_mod == "Mods": raise ClientError( "You must be authorized to change this area's evidence mod from Mod-only." ) if arg == "Mods": raise ClientError( "You must be authorized to set the area's evidence to Mod-only." ) client.area.evidence_mod = arg client.area.broadcast_evidence_list() client.send_ooc(f"current evidence mod: {client.area.evidence_mod}") database.log_area("evidence_mod", client, client.area, message=arg) else: raise ArgumentError( "Wrong Argument. Use /evidence_mod <MOD>. Possible values: FFA, CM, Mods, HiddenCM" )
def ooc_cmd_uncm(client, arg): """ Remove a case manager from the current area. Usage: /uncm <id> """ if len(arg) > 0: arg = arg.split() else: arg = [client.id] for _id in arg: try: _id = int(_id) c = client.server.client_manager.get_targets( client, TargetType.ID, _id, False)[0] if c in client.area._owners: client.area.remove_owner(c) database.log_area("cm.remove", client, client.area, target=c) else: client.send_ooc( "You cannot remove someone from CMing when they aren't a CM." ) except (ValueError, IndexError): client.send_ooc(f"{_id} does not look like a valid ID.") except (ClientError, ArgumentError): raise
def ooc_cmd_chardesc_get(client, arg): """ Get someone else's character description. Usage: /chardesc_get <id> """ try: if arg.isnumeric(): target = client.server.client_manager.get_targets( client, TargetType.ID, int(arg), False) if target: target = target[0].char_id else: if arg != "-1" and (int(arg) in client.area.area_manager.char_list): target = int(arg) else: try: target = client.area.area_manager.get_char_id_by_name(arg) except (ServerError): raise desc = client.area.area_manager.get_character_data(target, "desc", "") target = client.area.area_manager.char_list[target] client.send_ooc(f"{target} Description: {desc}") database.log_area("chardesc.get", client, client.area, message=f"{target}: {desc}") except Exception: raise ArgumentError("Target not found.")
def ooc_cmd_evidence_remove(client, arg): """ Remove a piece of evidence. Usage: /evidence_remove <evi_name/id> """ if arg == "": raise ArgumentError( "Use /evidence_remove <evi_name/id> to remove that piece of evidence." ) try: evi_list = client.area.get_evidence_list(client) evidence = None for i, evi in enumerate(evi_list): if (arg.isnumeric() and int(arg) - 1 == i) or arg.lower() == evi[0].lower(): evidence = evi break if evidence is None: raise AreaError( f"Target evidence not found! (/evidence_remove {arg})") evi_name = evidence[0] client.area.evi_list.del_evidence(client, i) database.log_area("evidence.del", client, client.area) client.area.broadcast_evidence_list() client.send_ooc(f"You have removed evidence '{evi_name}'.") except ValueError: raise except (AreaError, ClientError): raise
def ooc_cmd_rolla_reload(client, arg): """ Reload ability dice sets from a configuration file. Usage: /rolla_reload """ rolla_reload(client.area) client.send_ooc("Reloaded ability dice configuration.") database.log_area("rolla_reload", client, client.area)
def ooc_cmd_chardesc_clear(client, arg): """ Clear your chardesc. Usage: /chardesc_clear """ client.area.area_manager.set_character_data(client.char_id, "desc", "") client.area.broadcast_ooc( f"{client.showname} cleared their character description.") database.log_area("chardesc.clear", client, client.area)
def ooc_cmd_gm(client, arg): """ Add a game master for the current Hub. If providing an *, GM all clients belonging to self. Usage: /gm <id(s)> """ if not client.is_mod and not client.area.area_manager.can_gm: raise ClientError("You can't become a GM in this Hub!") if len(client.area.area_manager.owners) == 0 or client.is_mod or client in client.area.area_manager.owners: # Client is trying to make someone else a GM if arg != "": # GM all self clients if arg == "*": arg = [c.id for c in client.server.client_manager.get_multiclients( client.ipid, client.hdid)] # GM the targets else: arg = arg.split(" ") # Client is not a mod and not a GM, meaning they're trying to nominate someone without being /gm first if not client.is_mod and client not in client.area.area_manager.owners: raise ArgumentError( "You cannot 'nominate' people to be GMs when you are not one." ) else: # Self GM arg = [client.id] # Loop through the ID's provided for id in arg: try: id = int(id) c = client.server.client_manager.get_targets( client, TargetType.ID, id, False )[0] if c not in client.area.area_manager.clients: raise ArgumentError( "You can only 'nominate' people to be GMs when they are in the hub." ) elif c in client.area.area_manager.owners: client.send_ooc( f"{c.showname} [{c.id}] is already a GM here.") else: for mc in c.server.client_manager.get_multiclients(c.ipid, c.hdid): if ( mc in mc.area.area_manager.owners and mc.area.area_manager != c.area.area_manager ): raise ClientError( f"One of {c.showname} [{c.id}]'s clients is already a GM in another hub!" ) client.area.area_manager.add_owner(c) database.log_area("gm.add", client, client.area, target=c) except (ValueError, IndexError): client.send_ooc(f"{id} does not look like a valid ID.") except (ClientError, ArgumentError): raise else: raise ClientError("You must be authorized to do that.")
def message_areas_cm(client, areas, message): for a in areas: if client not in a.owners: client.send_ooc(f"You are not a CM in {a.name}!") return name = f"[CM] {client.name}" a.send_command("CT", name, message) a.send_owner_command("CT", name, message) database.log_area("chat.cm", client, a, message=message)
def message_areas_cm(client, areas, message): for a in areas: if not client in a.owners: client.send_ooc(f'You are not a CM in {a.name}!') return name = f'[CM] {client.name}' a.send_command('CT', name, message) a.send_owner_command('CT', name, message) database.log_area('chat.cm', client, a, message=message)
def ooc_cmd_m(client, arg): """ Send a message to all online moderators. Usage: /m <message> """ if len(arg) == 0: raise ArgumentError("You can't send an empty message.") client.server.send_modchat(client, arg) database.log_area('chat.mod', client, client.area, message=arg)
def ooc_cmd_lm(client, arg): """ Send a message to everyone in the current area, speaking officially. Usage: /lm <message> """ if len(arg) == 0: raise ArgumentError("Can't send an empty message.") client.area.send_command( 'CT', f'<dollar>MOD|{client.name}', arg) database.log_area('chat.local-mod', client, client.area, message=arg)
def ooc_cmd_play_once(client, arg): """ Play a track without looping it. See /play for this command with looping. Usage: /play_once <name> """ if len(arg) == 0: raise ArgumentError("You must specify a song.") client.change_music(arg, client.char_id, "", 2, False) # non-looped change music database.log_area("play", client, client.area, message=arg)
def ooc_cmd_notecard_clear(client, arg): """ Clear all notecards as a CM. Usage: /notecard_clear """ client.area.cards.clear() client.area.broadcast_ooc( f"[{client.id}] {client.showname} has cleared all the note cards in this area." ) database.log_area("notecard_clear", client, client.area)
def ooc_cmd_play_once(client, arg): """ Play a track without looping it. See /play for this command with looping. Usage: /play_once <name> """ if len(arg) == 0: raise ArgumentError('You must specify a song.') client.area.play_music(arg, client.char_id, 0) #don't loop it client.area.add_music_playing(client, arg) database.log_area('play', client, client.area, message=arg)
def ooc_cmd_g(client, arg): """ Broadcast a server-wide message. Usage: /g <message> """ if client.muted_global: raise ClientError('Global chat toggled off.') if len(arg) == 0: raise ArgumentError("You can't send an empty message.") client.server.broadcast_global(client, arg, client.is_mod) database.log_area('chat.global', client, client.area, message=arg)
def ooc_cmd_need(client, arg): """ Broadcast a server-wide advertisement for your role-play or case. Usage: /need <message> """ if client.muted_adverts: raise ClientError('You have advertisements muted.') if len(arg) == 0: raise ArgumentError("You must specify what you need.") client.server.broadcast_need(client, arg) database.log_area('chat.announce.need', client, client.area, message=arg)
def ooc_cmd_announce(client, arg): """ Make a server-wide announcement. Usage: /announce <message> """ if len(arg) == 0: raise ArgumentError("Can't send an empty message.") client.server.send_all_cmd_pred( 'CT', client.server.config['hostname'], f'=== Announcement ===\r\n{arg}\r\n==================', '1') database.log_area('chat.announce', client, client.area, message=arg)
def ooc_cmd_anncase(client, arg): """ Announce that a case is currently taking place in this area, needing a certain list of positions to be filled up. Usage: /anncase <message> <def> <pro> <jud> <jur> <steno> """ # XXX: Merge with aoprotocol.net_cmd_casea if client in client.area.owners: if not client.can_call_case(): raise ClientError( "Please wait 60 seconds between case announcements!") args = re.findall(r'(?:[^\s,"]|"(?:\\.|[^"])*")+', arg) if len(args) == 0: raise ArgumentError("Please do not call this command manually!") elif len(args) == 1: raise ArgumentError( "You should probably announce the case to at least one person." ) else: if (not args[1] == "1" and not args[2] == "1" and not args[3] == "1" and not args[4] == "1" and not args[5] == "1"): raise ArgumentError( "You should probably announce the case to at least one person." ) msg = "=== Case Announcement ===\r\n{} [{}] is hosting {}, looking for ".format( client.showname, client.id, args[0]) lookingfor = [ p for p, q in zip( [ "defense", "prosecutor", "judge", "juror", "stenographer" ], args[1:], ) if q == "1" ] msg += ", ".join(lookingfor) + ".\r\n==================" client.server.send_all_cmd_pred("CASEA", msg, args[1], args[2], args[3], args[4], args[5], "1") client.set_case_call_delay() log_data = { k: v for k, v in zip(("message", "def", "pro", "jud", "jur", "steno"), args) } database.log_area("case", client, client.area, message=log_data) else: raise ClientError( "You cannot announce a case in an area where you are not a CM!")
def ooc_cmd_coinflip(client, arg): """ Flip a coin. The result is shown publicly. Usage: /coinflip """ if len(arg) != 0: raise ArgumentError('This command has no arguments.') coin = ['heads', 'tails'] flip = random.choice(coin) client.area.broadcast_ooc('{} flipped a coin and got {}.'.format( client.showname, flip)) database.log_area('coinflip', client, client.area, message=flip)
def ooc_cmd_vote_reveal(client, arg): """ Reveal the number of votes, the voters and those with the highest amount of votes. Usage: /vote_reveal """ if len(client.area.votes) == 0: raise ClientError("There are no votes to reveal in this area.") msg = "Votes have been revealed:" msg += get_vote_results(client.area.votes) client.area.broadcast_ooc(msg) client.send_ooc("Use /vote_clear for clearing.") database.log_area("vote_reveal", client, client.area)