def ooc_cmd_toggleglobal(client, arg): """ Mute global chat. Usage: /toggleglobal """ if len(arg) != 0: raise ArgumentError("This command doesn't take any arguments") client.muted_global = not client.muted_global glob_stat = 'on' if client.muted_global: glob_stat = 'off' client.send_ooc(f'Global chat turned {glob_stat}.')
def ooc_cmd_edit_ambience(client, arg): """ Toggle edit mode for setting ambience. Playing music will set it as the area's ambience. tog can be `on`, `off` or empty. Usage: /edit_ambience [tog] """ if len(arg.split()) > 1: raise ArgumentError("This command can only take one argument ('on' or 'off') or no arguments at all!") if arg: if arg == 'on': client.edit_ambience = True elif arg == 'off': client.edit_ambience = False else: raise ArgumentError("Invalid argument: {}".format(arg)) else: client.edit_ambience = not client.edit_ambience stat = 'no longer' if client.edit_ambience: stat = 'now' client.send_ooc(f'Playing a song will {stat} edit the area\'s ambience.')
def ooc_cmd_getafk(client, arg): """ Show currently AFK-ing players in the current area or in all areas. Usage: /getafk [all] """ if arg == 'all': arg = -1 elif len(arg) == 0: arg = client.area.id else: raise ArgumentError('There is only one optional argument [all].') client.send_area_info(arg, False, afk_check=True)
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_toggleadverts(client, arg): """ Mute advertisements. Usage: /toggleadverts """ if len(arg) != 0: raise ArgumentError("This command doesn't take any arguments") client.muted_adverts = not client.muted_adverts adv_stat = 'on' if client.muted_adverts: adv_stat = 'off' client.send_ooc(f'Advertisements turned {adv_stat}.')
def ooc_cmd_rollp(client, arg): """ Roll a die privately. Usage: /roll [max value] [rolls] """ roll_max = 11037 if len(arg) != 0: try: val = list(map(int, arg.split(' '))) if not 1 <= val[0] <= roll_max: raise ArgumentError( f'Roll value must be between 1 and {roll_max}.') except ValueError: raise ArgumentError( 'Wrong argument. Use /rollp [<max>] [<num of rolls>]') else: val = [6] if len(val) == 1: val.append(1) if len(val) > 2: raise ArgumentError( 'Too many arguments. Use /rollp [<max>] [<num of rolls>]') if val[1] > 20 or val[1] < 1: raise ArgumentError('Num of rolls must be between 1 and 20') roll = '' for _ in range(val[1]): roll += str(random.randint(1, val[0])) + ', ' roll = roll[:-2] if val[1] > 1: roll = '(' + roll + ')' client.send_ooc('{} rolled {} out of {}.'.format( client.char_name, roll, val[0])) client.area.broadcast_ooc('{} rolled in secret.'.format( client.char_name)) for c in client.area.owners: c.send_ooc('[{}]{} secretly rolled {} out of {}.'.format( client.area.abbreviation, client.char_name, roll, val[0])) database.log_room('rollp', client, client.area, message=f'{roll} out of {val[0]}')
def ooc_cmd_force_follow(client, arg): """ Force someone to follow you, or someone else. Follow me! Usage: /force_follow <victim_id> [target_id] """ arg = arg.split() if len(arg) == 0: raise ArgumentError( "You must specify a victim. Usage: /force_follow <victim_id> [target_id]") try: victims = client.server.client_manager.get_targets( client, TargetType.ID, int(arg[0]), False ) except Exception: raise ArgumentError( "You must specify a victim. Usage: /force_follow <victim_id> [target_id]") target = client if len(arg) >= 2: try: target = client.server.client_manager.get_targets( client, TargetType.ID, int(arg[1]), False ) except Exception: raise ArgumentError( "Invalid target! Usage: /force_follow <victim_id> [target_id]") if victims: for c in victims: if client == c: raise ClientError( "You are already forced to follow yourself because you are yourself!" ) c.following = client c.forced_to_follow = True c.send_ooc(f"You've been forced to follow {client.showname}!") if c.area != client.area: c.set_area(client.area) client.send_ooc( f"Forced {len(victims)} client(s) to follow [{target.id}] {target.showname}.") else: client.send_ooc("No targets found.")
def ooc_cmd_cm(client, arg): """ Add a case manager for the current area. Leave id blank to promote yourself if there are no CMs. Usage: /cm <id> """ if not client.area.can_cm: raise ClientError('You can\'t become a CM in this area') if len(client.area.owners) == 0: if len(arg) > 0: raise ArgumentError( 'You cannot \'nominate\' people to be CMs when you are not one.' ) client.area.add_owner(client) database.log_area('cm.add', client, client.area, target=client, message='self-added') elif client in client.area.owners: if len(arg) > 0: arg = arg.split(' ') for id in arg: try: id = int(id) c = client.server.client_manager.get_targets( client, TargetType.ID, id, False)[0] if not c in client.area.clients: raise ArgumentError( 'You can only \'nominate\' people to be CMs when they are in the area.' ) elif c in client.area.owners: client.send_ooc( f'{c.showname} [{c.id}] is already a CM here.') else: client.area.add_owner(c) database.log_area('cm.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 ooc_cmd_blockdj(client, arg): """ Prevent a user from changing music. Usage: /blockdj <id> """ if len(arg) == 0: raise ArgumentError('You must specify a target. Use /blockdj <id>.') try: targets = client.server.client_manager.get_targets( client, TargetType.ID, int(arg), False) except: raise ArgumentError('You must enter a number. Use /blockdj <id>.') if not targets: raise ArgumentError('Target not found. Use /blockdj <id>.') for target in targets: target.is_dj = False target.send_ooc( 'A moderator muted you from changing the music.') database.log_room('blockdj', client, client.area, target=target) target.area.remove_jukebox_vote(target, True) client.send_ooc('blockdj\'d {}.'.format( targets[0].char_name))
def ooc_cmd_unremove_h(client, arg): if not client.is_mod: raise ClientError('You must be authorized to do that.') elif len(arg) == 0: raise ArgumentError('You must specify a target.') try: if len(arg) == 10 and arg.isdigit(): targets = client.server.client_manager.get_targets( client, TargetType.IPID, int(arg), False) elif len(arg) < 10 and arg.isdigit(): targets = client.server.client_manager.get_targets( client, TargetType.ID, int(arg), False) except: raise ArgumentError('You must specify a target. Use /unremove_h <id>.') if targets: for c in targets: logger.log_server('Adding h to {}.'.format(c.get_ip()), client) c.remove_h = False client.send_host_message('Added h to {} existing client(s).'.format( len(targets))) else: client.send_host_message('No targets found.')
def ooc_cmd_removelink(client, arg): """ Remove a specific HTML link from data. Usage: /removelink <choice> """ links_list = client.server.misc_data if len(arg) == 0: raise ArgumentError('You must specify a link to delete.') arg = arg.lower() if arg in links_list: try: del links_list[arg] client.server.save_miscdata() client.send_ooc(f'Deleted link "{arg}".') database.log_room('link.delete', client, client.area, message=arg) except: raise ClientError('Error, link has not been deleted.') else: raise ArgumentError( 'Link not found. Use /link to see possible choices.')
def ooc_cmd_unblockwtce(client, arg): """ Allow a user to use WT/CE again. Usage: /unblockwtce <id> """ if len(arg) == 0: raise ArgumentError( 'You must specify a target. Use /unblockwtce <id>.') try: targets = client.server.client_manager.get_targets( client, TargetType.ID, int(arg), False) except: raise ArgumentError('You must enter a number. Use /unblockwtce <id>.') if not targets: raise ArgumentError('Target not found. Use /unblockwtce <id>.') for target in targets: target.can_wtce = True target.send_ooc( 'A moderator unblocked you from using judge signs.') database.log_room('unblockwtce', client, client.area, target=target) client.send_ooc('unblockwtce\'d {}.'.format( targets[0].char_name))
def ooc_cmd_kick(client, arg): if not client.is_mod: raise ClientError('You must be authorized to do that.') if len(arg) == 0: raise ArgumentError('You must specify a target.') targets = client.server.client_manager.get_targets(client, arg) if targets: for c in targets: logger.log_server('Kicked {}.'.format(c.get_ip()), client) c.disconnect() client.send_host_message("Kicked {} client(s).".format(len(targets))) else: client.send_host_message("No targets found.")
def ooc_cmd_link_evidence(client, arg): """ Make specific link only accessible from evidence ID(s). Pass evidence ID's which you can see by mousing over evidence, or blank to see current evidences. Usage: /link_evidence <id> [evi_id(s)] """ args = arg.split() if len(args) <= 0: raise ArgumentError( "Invalid number of arguments. Use /link_evidence <id> [evi_id(s)]") link = None evidences = [] try: link = client.area.links[args[0]] if len(args) > 1: for evi_id in args[1:]: evi_id = int(evi_id) - 1 client.area.evi_list.evidences[ evi_id] # Test if we can access target evidence evidences.append(evi_id) except IndexError: raise ArgumentError("Evidence not found.") except (ValueError, KeyError): raise ArgumentError("Area ID must be a number.") except (AreaError, ClientError): raise else: if len(evidences) > 0: link["evidence"] = evidences if len(link["evidence"]) > 0: evi_list = ", ".join(str(evi + 1) for evi in link["evidence"]) client.send_ooc( f"Area {client.area.name} link {args[0]} associated evidence IDs: {evi_list}." ) else: client.send_ooc( f"Area {client.area.name} link {args[0]} has no associated evidence." )
def ooc_cmd_unlink(client, arg): """ Remove a two-way link from your current area with targeted area(s). Usage: /unlink <id(s)> """ args = arg.split() if len(args) <= 0: raise ArgumentError("Invalid number of arguments. Use /unlink <aid>") try: links = [] for aid in args: try: area = client.area.area_manager.get_area_by_abbreviation(aid) target_id = area.id except Exception: area = client.area.area_manager.get_area_by_id(int(aid)) target_id = area.id if not client.is_mod and client not in area.owners: client.send_ooc(f"You don't own area [{area.id}] {area.name}.") continue try: client.area.unlink(target_id) # Disconnect the target area from us area.unlink(client.area.id) links.append(target_id) except Exception: continue links = ", ".join(str(link) for link in links) client.send_ooc( f"Area {client.area.name} has been unlinked with {links} (two-way)." ) client.area.broadcast_area_list() area.broadcast_area_list() except ValueError: raise ArgumentError("Area ID must be a number or abbreviation.") except (AreaError, ClientError): raise
def ooc_cmd_load_hub(client, arg): """ Load Hub data from the server's storage/hubs/<name>.yaml file. Usage: /load_hub <name> """ if arg == "" and not client.is_mod: raise ArgumentError("You must be authorized to load the default hub!") try: if arg != "": path = "storage/hubs" arg = f"{path}/{arg}.yaml" if not os.path.isfile(arg): raise ArgumentError(f"File not found: {arg}") with open(arg, "r", encoding="utf-8") as stream: hub = yaml.safe_load(stream) client.area.area_manager.load(hub, ignore=["can_gm", "max_areas"]) client.send_ooc(f"Loading as {arg}...") client.area.area_manager.send_arup_status() client.area.area_manager.send_arup_cms() client.area.area_manager.send_arup_lock() client.server.client_manager.refresh_music( client.area.area_manager.clients) client.send_ooc("Success, sending ARUP and refreshing music...") else: client.server.hub_manager.load() client.send_ooc("Loading all Hubs from areas.yaml...") clients = set() for hub in client.server.hub_manager.hubs: hub.send_arup_status() hub.send_arup_cms() hub.send_arup_lock() clients = clients | hub.clients client.server.client_manager.refresh_music(clients) client.send_ooc("Success, sending ARUP and refreshing music...") except Exception as ex: msg = f"There is a problem: {ex}" msg += "\nContact the server owner for support." client.send_ooc(msg)
def ooc_cmd_rename_hub(client, arg): """ Rename the hub you are currently in to <name>. Usage: /rename_hub <name> """ if arg != "": client.area.area_manager.name = dezalgo(arg)[:64] client.send_ooc( f"Renamed hub [{client.area.area_manager.id}] to {client.area.area_manager.name}." ) else: raise ArgumentError( "Invalid number of arguments. Use /rename_hub <name>.")
def ooc_cmd_getmusic(client, arg): """ Grab the last played track in this area. Usage: /getmusic """ if len(arg) != 0: raise ArgumentError('This command has no arguments.') if client.area.music == '': raise ClientError('There is no music currently playing.') client.send_command('MC', client.area.music, -1, '', client.area.music_looping, 0, client.area.music_effects) client.send_ooc(f'Playing track \'{client.area.music}\'.')
def ooc_cmd_blockwtce(client, arg): """ Prevent a user from using Witness Testimony/Cross Examination buttons as a judge. Usage: /blockwtce <id> """ if len(arg) == 0: raise ArgumentError('You must specify a target. Use /blockwtce <id>.') try: targets = client.server.client_manager.get_targets( client, TargetType.ID, int(arg), False) except: raise ArgumentError('You must enter a number. Use /blockwtce <id>.') if not targets: raise ArgumentError('Target not found. Use /blockwtce <id>.') for target in targets: target.can_wtce = False target.send_ooc( 'A moderator blocked you from using judge signs.') database.log_room('blockwtce', client, client.area, target=target) client.send_ooc('blockwtce\'d {}.'.format( targets[0].char_name))
def ooc_cmd_testimony_clear(client, arg): """ Clear the current testimony. Usage: /testimony_clear """ if len(client.area.testimony) <= 0: client.send_ooc('There is no testimony recorded!') return if len(arg) != 0: raise ArgumentError('This command does not take any arguments.') client.area.testimony.clear() client.area.testimony_title = '' client.area.broadcast_ooc(f'{client.showname} cleared the current testimony.')
def ooc_cmd_time(client, arg): """ Returns the current server time. Usage: /time """ if len(arg) > 0: raise ArgumentError("This command takes no arguments") from time import asctime, gmtime, time msg = "The current time in UTC (aka GMT) is:\n[" msg += asctime(gmtime(time())) msg += "]" client.send_ooc(msg)
def ooc_cmd_testimony_swap(client, arg): """ Swap the two statements by idx. Usage: /testimony_swap <id> <id> """ if len(client.area.testimony) <= 0: client.send_ooc('There is no testimony recorded!') return args = arg.split() if len(args) < 2: raise ArgumentError('Usage: /testimony_remove <id> <id>.') try: idx1 = int(args[0]) - 1 idx2 = int(args[1]) - 1 client.area.testimony[idx2], client.area.testimony[idx1] = client.area.testimony[idx1], client.area.testimony[idx2] client.area.broadcast_ooc(f'{client.showname} has swapped Statements {idx1+1} and {idx2+1}.') except ValueError: raise ArgumentError('Index must be a number!') except IndexError: raise ArgumentError('Index out of bounds!') except ClientError: raise
def ooc_cmd_randomchar(client, arg): if len(arg) != 0: raise ArgumentError('This command has no arguments.') try: free_id = client.area.get_rand_avail_char_id() except AreaError: raise try: client.change_character(free_id) except ClientError: raise client.send_host_message('Randomly switched to {}'.format( client.get_char_name()))
def ooc_cmd_gimp(client, arg): """ Replace a user's message with a random message from a list. Usage: /gimp <id> """ if len(arg) == 0: raise ArgumentError('You must specify a target ID.') try: targets = client.server.client_manager.get_targets( client, TargetType.ID, int(arg), False) except: raise ArgumentError('You must specify a target. Use /gimp <id>.') if targets: for c in targets: database.log_misc('gimp', client, target=c, data=client.area.abbreviation) c.gimp = True client.send_ooc(f'Gimped {len(targets)} existing client(s).') else: client.send_ooc('No targets found.')
def ooc_cmd_8ball(client, arg): """ Answers a question. The result is shown publicly. Usage: /8ball <question> """ arg = arg.strip() if len(arg) == 0: raise ArgumentError('You need to ask a question') rolla_reload(client.area) ability_dice = client.area.ability_dice['8ball'] client.area.broadcast_ooc('{} asked a question: {} and the answer is: {}.'.format( client.char_name, arg, rolla(ability_dice)[2]))
def ooc_cmd_ungimp(client, arg): """ Allow the user to send their own messages again. Usage: /ungimp <id> """ if len(arg) == 0: raise ArgumentError('You must specify a target ID.') try: targets = client.server.client_manager.get_targets( client, TargetType.ID, int(arg), False) except: raise ArgumentError('You must specify a target. Use /ungimp <id>.') if targets: for c in targets: database.log_misc('ungimp', client, target=c, data=client.area.abbreviation) c.gimp = False client.send_ooc(f'Ungimped {len(targets)} existing client(s).') else: client.send_ooc('No targets found.')
def ooc_cmd_baninfo(client, arg): """ Get information about a ban. Usage: /baninfo <id> ['ban_id'|'ipid'|'hdid'] By default, id identifies a ban_id. """ args = arg.split(' ') if len(arg) == 0: raise ArgumentError('You must specify an ID.') elif len(args) == 1: lookup_type = 'ban_id' else: lookup_type = args[1] if lookup_type not in ('ban_id', 'ipid', 'hdid'): raise ArgumentError('Incorrect lookup type.') bans = database.ban_history(**{lookup_type: args[0]}) if bans is None: client.send_ooc('No ban found for this ID.') else: msg = f'Bans for {args[0]}' for ban in bans: msg += f'\nBan ID: {ban.ban_id}\n' msg += 'Affected IPIDs: ' + \ ', '.join([str(ipid) for ipid in ban.ipids]) + '\n' msg += 'Affected HDIDs: ' + ', '.join(ban.hdids) + '\n' msg += f'Reason: "{ban.reason}"\n' msg += f'Unbanned: {bool(ban.unbanned)}\n' msg += f'Banned by: {ban.banned_by_name} ({ban.banned_by})\n' ban_date = arrow.get(ban.ban_date) msg += f'Banned on: {ban_date.format()} ({ban_date.humanize()})\n' if ban.unban_date is not None: unban_date = arrow.get(ban.unban_date) msg += f'Unban date: {unban_date.format()} ({unban_date.humanize()})' else: msg += 'Unban date: N/A' client.send_ooc(msg)
def ooc_cmd_unmute(client, arg): if not client.is_mod: raise ClientError('You must be authorized to do that.') if len(arg) == 0: raise ArgumentError('You must specify a target.') try: c = client.server.client_manager.get_targets(client, TargetType.ID, int(arg), False)[0] c.is_muted = False client.send_host_message('{} existing client(s).'.format( c.get_char_name())) except: client.send_host_message("No targets found. Use /mute <id> for mute")
def ooc_cmd_disconnect(client, arg: str) -> None: """ Removes a one-way connection to an area. """ args = arg.split() if client not in client.area.owners and not client.is_mod: raise ClientError('You must be a CM.') if not client.area.sub: raise ClientError('Must be in a hub subarea.') if len(args) == 0: raise ArgumentError( 'You must specify an area, use /disconnect <abbreviation>') if len(client.area.connections) < 3: for area in client.area.connections: if area != area.hub and area != client.server.area_manager.default_area( ) and area.abbreviation in args: client.area.connections.remove(area) client.send_ooc('Area disconnected!') else: raise ArgumentError( 'No areas to disconnect from, use /clearconnect to unrestrict the area.' )
def net_cmd_casea(self, args): """ Announces a case with a title, and specific set of people to look for. CASEA#<casetitle:string>#<need_cm:int>#<need_def:int>#<need_pro:int>#<need_judge:int>#<need_jury:int>#<need_steno:int>#% Note: Though all but the first arguments are ints, they technically behave as bools of 0 and 1 value. """ if self.client in self.client.area.owners: if not self.client.can_call_case(): raise ClientError( 'Please wait 60 seconds between case announcements!') 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( self.client.get_char_name(), self.client.id, args[0]) lookingfor = [] if args[1] == "1": lookingfor.append("defence") if args[2] == "1": lookingfor.append("prosecutor") if args[3] == "1": lookingfor.append("judge") if args[4] == "1": lookingfor.append("juror") if args[5] == "1": lookingfor.append("stenographer") msg = msg + ', '.join(lookingfor) + '.\r\n==================' self.client.server.send_all_cmd_pred('CASEA', msg, args[1], args[2], args[3], args[4], args[5], '1') self.client.set_case_call_delay() logger.log_server( '[{}][{}][CASE_ANNOUNCEMENT]{}, DEF: {}, PRO: {}, JUD: {}, JUR: {}, STENO: {}.' .format(self.client.area.abbreviation, self.client.get_char_name(), args[0], args[1], args[2], args[3], args[4], args[5]), self.client) else: raise ClientError( 'You cannot announce a case in an area where you are not a CM!' )