async def removetraveler(self, ctx: Context, traveler: str): """Remove a traveler from the game. traveler: The traveler to remove. """ # convert the traveler traveler_actual = await to_player(ctx, traveler) # check that player is a traveler if not traveler_actual.character_type(ctx) == "traveler": raise commands.BadArgument( f"{traveler_actual.nick} is not a traveler.") # remove them from the seating order ctx.bot.game.seating_order.remove(traveler_actual) # announcement msg = await safe_send( ctx.bot.channel, ("{townsfolk}, {traveler} has left the town. " "Let's wish {pronoun} goodbye!").format( pronoun=load_preferences(traveler_actual).pronouns[1], townsfolk=ctx.bot.player_role.mention, traveler=traveler_actual.nick, ), ) await msg.pin() await safe_send( ctx, f"Successfully removed traveler {traveler_actual.nick}.")
def _permission_to_edit(ctx: Context, idn: int, script: Script): """Determine if the user represented by the ID can edit the script.""" if idn in script.editors: return True else: message_text = f"You do not have permission to edit {script.name}. " if script.editors != []: editors, plural = script.editor_names(ctx) s = "s" if plural else "" verb = "are" if plural else "is" if plural: pronoun = "them" else: pronoun = load_preferences(ctx.bot.get_user( script.editors[0])).pronouns[1] message_text += ( f"Its editor{s} {verb} {editors}. Contact {pronoun} for more info." ) else: message_text += ("If you believe the script is incorrect, " "please contact nihilistkitten#6937 or an admin.") raise commands.BadArgument(message_text)
async def inner_wrapper(*args, **kwargs): if args[0].parent.functioning(args[1]): return await func(*args, **kwargs) if safe_bug_report(args[1]): if args[0].parent.ghost(args[1]): status = "dead" elif args[0].parent.is_status(args[1], "drunk"): status = "drunk" elif args[0].parent.is_status(args[1], "poisoned"): status = "poisoned" else: status = "not functioning" if run_if_drunkpoisoned and status in ("drunk", "poisoned"): kwargs["enabled"] = False kwargs["epithet_string"] = f"({status})" return await func(*args, **kwargs) pronouns = load_preferences(args[0].parent).pronouns await safe_send( args[1], "Skipping {epithet}, as {pronoun} {verb} {status}.".format( epithet=args[0].parent.epithet, pronoun=pronouns[0], verb=("is", "are")[pronouns[5]], status=status, ), ) # this return is hella janky but basically we want this to work for any # of the character methods (ex morning, evening) and they have different # return types so we need to grab whatever the generic return is. # the character initializes with no parent to let us check in the method # if it's actually being called or just being called to get the return # so we can hide side effects in an "if self.parent" block return await getattr(Character(None), func.__name__)(*args[1:], **kwargs)
def nick(self) -> str: """Determine the name the bot will call the player. Their nickname if set in preferences, else server nickname, else discord name. """ return load_preferences( self.member).nick # the preferences object defaults to obj.nick =
async def morning( self, ctx: Context, skip: bool = False ) -> Tuple[List["Player"], List[str]]: """Call at the start of each day. Processes night actions. Parameters ---------- ctx : Context The invocation context. Returns ------- List[Player] Players killed by the character. str A non-kill message to broadcast at the start of the day. """ # check that this isn't a dummy call from a wrapper to figure out the return # see the commenting of tools.if_functioning for more info if self.parent: await safe_send( ctx, ( "Skipping {epithet}, as " "{posessive} ability is not handled by the bot." ).format( epithet=self.parent.epithet, posessive=load_preferences(self.parent).pronouns[2], ), ) return [], []
async def setnick(self, ctx: Context, *, nick: str): """Set your nickname for bot messages. nick: The name you want to use. This input is case-sensitive. """ preferences = load_preferences(ctx.message.author) preferences.nick = nick preferences.save_preferences() await safe_send(ctx, f"Successfully set your nickname to {nick}.")
async def removealias(self, ctx: Context, alias: str): """Remove a personal alias for a command. alias: The alias to remove. """ preferences = load_preferences(ctx.message.author) try: del preferences.aliases[alias] preferences.save_preferences() await safe_send(ctx, f"Successfully deleted your alias {alias}.") except KeyError: raise commands.BadArgument(f"You do not have an alias {alias}.")
async def wrapper(*args, **kwargs): if not args[0].parent.is_status(args[1], "used_ability"): return await func(*args, **kwargs) if safe_bug_report(args[1]): pronouns = load_preferences(args[0].parent).pronouns await safe_send( args[1], ("Skipping {epithet}, as " "{subjective} {verb} used {posessive} ability.").format( epithet=args[0].parent.epithet, subjective=pronouns[0], verb=["has", "have"][pronouns[5]], posessive=pronouns[2], ), ) return await getattr(Character(None), func.__name__)(*args[1:], **kwargs)
async def wrapper(character: Character, ctx: "GameContext", *args, **kwargs): if not character.parent.is_status(ctx.bot.game, "used_ability"): return await func(character, ctx, *args, **kwargs) if safe_bug_report(ctx): pronouns = load_preferences(character.parent).pronouns await safe_send( ctx, ("Skipping {epithet}, as " "{subjective} {verb} used {posessive} ability.").format( epithet=character.parent.epithet, subjective=pronouns[0], verb=["has", "have"][pronouns[5]], posessive=pronouns[2], ), ) return await getattr(Character(None), func.__name__)( # type: ignore ctx, *args, **kwargs)
async def _generate_vote_end_message(self): """Generate the vote end message.""" result = self.votes >= self.majority voters = list_to_plural_string([x.nick for x in self.voted], "no one") result_type = ["executed", "exiled"][self.traveler] pronouns = load_preferences(self.nominee).pronouns message_text = ( "{votes} votes on {nominee_nick} (nominated by {nominator_nick}):" " {voters}. {pronoun_string}{nt} about to be {result_type}.") message_text = message_text.format( nt=[" not", ""][result], voters=voters[0], votes=self.votes, nominee_nick=self.nominee.nick, nominator_nick=self.nominator.nick, result_type=result_type, pronoun_string=pronouns[0].capitalize() + [" is", " are"][pronouns[5]], ) return message_text, result
async def emergencyvote( self, ctx: Context, vote: str, time: int, specific: str = "yes", ): """Change your emergency vote. vote: The vote you want to set, yes or no. time: The time in minutes for the vote to trigger. specific: Whether this emergency is bot-specific, yes or no. Defaults to yes. """ vote_actual = to_bool(vote, "vote") specific_actual = to_bool(specific, "argument") preferences = load_preferences(ctx.message.author) if specific_actual: preferences.specific_emergencys[ctx.bot.user.id] = (vote_actual, time) preferences.save_preferences() await safe_send( ctx, ("Successfully set a emergency vote of {vote} " "in {time} minutes for {botName}.").format( vote=("no", "yes")[vote_actual], time=str(time), botName=ctx.bot.server.get_member( ctx.bot.user.id).display_name, ), ) else: preferences.emergency_vote = (vote_actual, time) preferences.save_preferences() await safe_send( ctx, ("Successfully set a generic emergency vote of " "{vote} in {time} minutes.").format(vote=("no", "yes")[vote_actual], time=str(time)), )
async def removeemergencyvote(self, ctx: Context, specific: str = "yes"): """Remove your emergency vote. specific: Whether to remove the bot-specific emergency vote or the generic one. """ specific_actual = to_bool(specific, "argument") preferences = load_preferences(ctx.message.author) if specific_actual: try: del preferences.specific_emergencys[ctx.bot.user.id] preferences.save_preferences() await safe_send( ctx, ( "Successfully removed your bot-specific emergency vote. " "Please note any generic emergency vote will now apply." ), ) except KeyError: await safe_send( ctx, "You do not have a specific emergency vote with {botName}.".format( botName=ctx.bot.server.get_member(ctx.bot.user.id).display_name ), ) else: if preferences.emergency_vote[1] is not None: preferences.emergency_vote = (0, None) preferences.save_preferences() await safe_send( ctx, ( "Successfully removed your generic emergency vote. " "Please note any bot-specific emergency votes will still apply." ), ) else: await safe_send(ctx, "You do not have a generic emergency vote.")
async def process_commands(self, message: discord.Message): """Process commands registered to the bot. Modified to handle custom aliases. """ if message.author.bot: return if not (message.guild is None or message.channel == self.channel): return ctx = await self.get_context(message) preferences = load_preferences(message.author) if ctx.invoked_with in preferences.aliases: ctx.command = self.all_commands.get( preferences.aliases[ctx.invoked_with].split(" ")[0]) if " " in preferences.aliases[ctx.invoked_with]: for cmd in preferences.aliases[ctx.invoked_with].split( " ")[1:]: ctx.command = ctx.command.get_command(cmd) await self.invoke(ctx)
def _generate_possibilities(argument: str, possibilities: List[Member]) -> List[Member]: """Determine all members with marching nicknames or usernames. Parameters ---------- argument : str The string to be matched. possibilities : List[Member] The possible members to search for matches. Returns ------- List[Member] The matching members. """ out = [] for person in possibilities: if (argument.lower() in load_preferences(person).nick.lower() or argument.lower() in person.display_name.lower() or argument.lower() in person.name.lower()): out.append(person) return out
async def makealias(self, ctx: Context, alias: str, command: str, *, subcommand: str = ""): """Create a personal alias for a command. alias: The alias to be created. command: The command to create the alias for. """ preferences = load_preferences(ctx.message.author) cmd = ctx.bot.all_commands.get(command) if cmd is None: await safe_send( ctx, "Command not found: {command}.".format( command=command + (" " if subcommand else "") + subcommand), ) elif subcommand: if cmd.get_command(subcommand) is None: await safe_send( ctx, "Command not found: {command}.".format(command=command + " " + subcommand), ) else: preferences.aliases[alias] = (command + (" " if subcommand else "") + subcommand) preferences.save_preferences() await safe_send( ctx, "Successfully created alias `{alias}` for command `{command}`." .format(alias=alias, command=preferences.aliases[alias]), )
async def setpronouns( self, ctx: Context, subjective: str, objective: str, adjective: str, posessive: str, reflexive: str, plural: str = "no", ): """Set your pronouns for bot messages. subjective: The subjective pronoun, for instance 'they' or 'she'. objective: The objective pronoun, for instance 'them' or 'her'. adjective: The posessive adjective, for instance 'their' or 'her'. posessive: The posessive pronoun, for instance 'theirs' or 'hers'. reflexive: The reflexive pronoun, for instance 'themselves' or 'herself'. plural: Whether the bot should use plural grammar with your pronouns. For instance, 'they are about to die' or 'she is about to die'. You can also fill in the blank: [subjective] is/are the Imp. The Imp is [objective]. # TODO: this is apparently bad grammar It is [adjective] character. The character is [posessive]. [subjective] made the Minion a Demon by targeting [reflexive]. For example: They are the Imp. The Imp is them. It is their character. The character is theirs. They made the Minion a Demon by targetting themselves. These inputs are case-insensitive. If you use this to mock trans people, I will blacklist you from using the bot. <3 """ plural_actual = to_bool(plural, "argument") preferences = load_preferences(ctx.message.author) preferences.pronouns = ( subjective, objective, adjective, posessive, reflexive, plural_actual, ) preferences.save_preferences() await safe_send( ctx, ("Successfully set your pronouns! " "You are valid and thank you for trusting me with them!\n" "Here's a quick example so you can make sure you got the grammar right:" "\n{subjective} {verb} the Imp." "\nThe Imp is {objective}." "\nIt is {adjective} character." "\nThe character is {posessive}." "\n{subjective} made the Minion a Demon by targeting {reflexive}." ).format( reflexive=reflexive, subjective=subjective.capitalize(), verb=["is", "are"][plural_actual], objective=objective, adjective=adjective, posessive=posessive, ), )
async def addtraveler( self, ctx: Context, traveler: str, upwards_neighbor: str, alignment: str, *, character: str, ): """Add a traveler to the game. traveler: The player to join the game. character: Their traveler character. upwards_neighbor: The player above them in the seating order. alignment: The traveler's alignment; 'good' or 'evil'. """ # convert the traveler traveler_actual = await to_member(ctx, traveler) # check alignment is valid if not alignment.lower() in ["good", "evil"]: raise commands.BadArgument( "The alignment must be 'good' or 'evil' exactly.") # check if person is in the game try: get_player(ctx.bot.game, traveler_actual.id) raise commands.BadArgument( f"{load_preferences(traveler_actual).nick} is already in the game." ) except ValueError as e: if str(e) == "player not found": # find the character character_actual = to_character(ctx, character) # determine the position upwards_neighbor_actual = await to_player( ctx, upwards_neighbor) # make the Player player = Player( traveler_actual, character_actual, upwards_neighbor_actual.position + 1, ) # check that the character is a traveler if not player.character_type(ctx) == "traveler": raise commands.BadArgument( f"{player.character.name} is not a traveler.") # add the alignment if alignment.lower() == "good": player.add_effect(ctx, Good, player) elif alignment.lower() == "evil": player.add_effect(ctx, Evil, player) # add the player role await traveler_actual.add_roles(ctx.bot.player_role) # add them to the seating order ctx.bot.game.seating_order.insert( upwards_neighbor_actual.position + 1, player) # announcement await safe_send( ctx.bot.channel, ("{townsfolk}, {player} has joined the town as the {traveler}. " "Let's tell {pronoun} hello!").format( traveler=player.character.name, pronoun=load_preferences(player).pronouns[1], townsfolk=ctx.bot.player_role.mention, player=player.nick, ), ) # rules msg = await safe_send( ctx.bot.channel, f"\n**{player.character.name}** - {player.character.rules_text}", ) await msg.pin() await safe_send( ctx, f"Successfully added {player.nick} as the {player.character.name}.", ) else: raise