コード例 #1
0
def ignite(user_id):
    """This function ignites all powdered players that aren't pyromancer.
    The function assumes the player is a participant and has the correct role, so make sure to have filtered this out already.
    The function returns a Mailbox.

    user_id -> the player who ignites all powdered players"""

    uses = int(db_get(user_id,'uses'))
    if uses < 1:
        return Mailbox().respond("I am sorry! You currently cannot ignite anyone!",True)
    db_set(user_id,'uses',uses - 1)

    user_role = db_get(user_id,'role')
    user_channel = db_get(user_id,'channel')
    user_undead = int(db_get(user_id,'undead'))

    if user_undead == 1:
        answer = Mailbox().log("<@{}>, an undead **{}**, has pretended to ignite all powdered players.".format(user_id,user_role))
        answer.dm("Hey, you are undead, so your power won\'t work. But at least this won\'t blow your cover!",user_id)
        return answer.msg("Okay! All powdered players will die tomorrow.",user_channel)

    # Ignite all living players.
    for user in db.player_list(True,True):
        if db.isParticipant(user) and db_get(user,'role') != 'Pyromancer':
            db.add_kill(int(user),'Pyromancer',user_id)

    answer = Mailbox().log("The **{}** <@{}> has ignited all powdered players!".format(user_role,user_id))
    return answer.msg("Okay! All powdered players will die tomorrow.",user_channel)
コード例 #2
0
def nightly_kill(user_id,victim_id):
    """This function adds a kill to the kill queue based on the user's role.  
    This function is applicable for roles like the assassin, the lone wolf, the priest, the thing and the white werewolf.  
    NOTICE: This function is meant for people who kill solo! Teams should receive a poll.
    Evaluating whether the kill should actually be applied isn't needed, as this is evaluated at the start of the day.
    The function assumes the player is a participant and has the correct role, so make sure to have filtered this out already.  
    The function returns a Mailbox.

    user_id -> the player who will initiate the attack
    victim_id -> the player who shall be \"attacked\""""

    uses = int(db_get(user_id,'uses'))
    if uses < 1:
        return Mailbox().respond("I am sorry! You currently don't have this ability available!",True)

    if user_id == victim_id:
        return Mailbox().respond("I am sorry, but you cannot attempt suicide!\nNot because it's not an option, no, just because we want to see you SUFFER!",True)

    # TODO: Prevent targeting of abducted/frozen players.
    if int(db_get(user_id,'undead')) == 1 or db_get(user_id,'role') == 'Undead':
        return Mailbox().respond("I am sorry! Now that you are Undead, you can no longer use this power.",True)
    if int(db_get(victim_id,'abducted')) == 1:
        return Mailbox().respond("You attempted to attack <@{}>... but they don't seem to be around in town! That is strange.".format(victim_id),True)
    if int(db_get(user_id,'frozen')) == 1:
        return Mailbox().respond("You wanted to pay a visit to <@{}>... but it seems they were frozen! Try again, please.".format(victim_id),True)

    user_role = db_get(user_id,'role')
    user_channel = int(db_get(user_id,'channel'))

    db_set(user_id,'uses',uses - 1)
    db.add_kill(victim_id,user_role,user_id)

    answer = Mailbox().msg(ctory.kill_acceptance(victim_id),user_channel)
    return answer.log("The **{}** <@{}> has chosen to pay <@{}> a visit tonight.".format(user_role,user_id,victim_id))
コード例 #3
0
ファイル: test_main.py プロジェクト: abdulrabiu/Werewolf_Bot
def kill_queue_test():
  db.add_kill(12738912739821,"Barber")
  db.add_kill(12347892374923,"White Werewolf","7289347983274")
  assert db.get_kill() == [1,u'12738912739821',u'Barber',u'']
  assert db.get_kill() == [2,u'12347892374923',u'White Werewolf',u'7289347983274']
  assert db.get_kill() == None
  reset.reset(True)
  return True
コード例 #4
0
def nightly_kill(user_id,victim_id):
    """This function adds a kill to the kill queue based on the user's role.
    This function is applicable for roles like the assassin, the lone wolf, the priest, the thing and the white werewolf.
    Evaluating whether the kill should actually be applied isn't needed, as this is evaluated at the start of the day.  
    The function assumes the player is a participant and has the correct role, so make sure to have filtered this out already.  
    The function returns a Mailbox.  
    
    user_id -> the player who will initiate the attack
    victim_id -> the player who shall be \"attacked\""""

    uses = int(db_get(user_id,'uses'))
    if uses < 1:
        return Mailbox().respond("I am sorry! You currently don't have this ability available!",True)
    db_set(user_id,'uses',uses - 1)

    user_role = db_get(user_id,'role')
    user_channel = int(db_get(user_id,'channel'))

    # Add kill to the kill queue
    db.add_kill(victim_id,user_role,user_id)

    answer = Mailbox().msg(ctory.kill_acceptance(victim_id),user_channel)
    return answer.log("The **{}** <@{}> has chosen to pay a visit to <@{}> tonight.".format(user_role,user_id,victim_id))
コード例 #5
0
async def process_message(message,result):
    #if "<@&{}>".format(config.game_master) in message.content:
        #stats.increment_stat("game_master_pings", 1)
        #stats.increment_user_stat(message.author.id, "game_master_pings", 1)

    if db.isParticipant(message.author.id,True,True,True):
        db_set(message.author.id,'activity',0)

    gamelog_channel = client.get_channel(int(config.game_log))
    botspam_channel = client.get_channel(int(config.bot_spam))
    storytime_channel = client.get_channel(int(config.story_time))

    # The temp_msg list is for keeping track of temporary messages for deletion.
    temp_msg = []

    for mailbox in result:

        # If a Mailbox says so, all existing polls will be evaluated.
        if mailbox.evaluate_polls == True:
            for poll in db.get_all_polls():
                # poll.msg_table -> list of message ids
                # poll.blamed -> name of killer
                # poll.purpose -> the reason of the kill

                poll_channel = client.get_channel(int(poll.channel))
                if poll_channel == None:
                    await botspam_channel.send("We got a problem! Could you send these results to the appropriate channel, please?")
                    poll_channel = botspam_channel

                user_table = []
                for msg in poll.msg_table:
                    poll_msg = await poll_channel.get_message(msg)
                    for emoji in poll_msg.reactions:
                        users = await emoji.users().flatten()

                        for person in users:
                            if db.isParticipant(person.id):
                                user_table.append([person.id,emoji.emoji])

                log, result, chosen_emoji = count_votes(user_table,poll.purpose,dy.get_mayor())

                await botspam_channel.send(log)
                await poll_channel.send(result)
                for graveyard in db.get_secret_channels("Graveyard"):
                    await client.get_channel(graveyard).send(result)

                chosen_one = db.emoji_to_player(chosen_emoji)

                if chosen_emoji != '' and chosen_one != None:
                    chosen_one = int(chosen_one)
                    if poll.purpose == 'lynch':
                        db.add_kill(chosen_one,'Innocent')
                    elif poll.purpose == 'Mayor':
                        dy.set_mayor(chosen_one)
                        member = gamelog_channel.guild.get_member(int(chosen_one))
                        if member != None:
                            await member.add_roles(get_role(gamelog_channel.guild.roles, config.mayor), reason="Promoting {} to Mayor".format(member.display_name))
                    elif poll.purpose == 'Reporter':
                        dy.set_reporter(chosen_one)
                        for channel_id in db.get_secret_channels("Reporter"):
                            mailbox.edit_cc(channel_id,chosen_one,1)
                        member = gamelog_channel.guild.get_member(int(chosen_one))
                        if member != None:
                            await member.add_roles(get_role(gamelog_channel.guild.roles, config.reporter), reason="Promoting {} to Reporter".format(member.display_name))
                    elif poll.purpose == 'wolf':
                        db.add_kill(chosen_one,'Werewolf',db.random_wolf())
                    elif poll.purpose == 'cult':
                        db.add_kill(chosen_one,'Cult Leader',db.random_cult())
                    elif poll.purpose == 'thing':
                        db.add_kill(chosen_one,'The Thing','')

        for user_id in mailbox.demotions:
            if user_id == message.author.id and message.guild == gamelog_channel.guild:
                member = message.author
            else:
                member = gamelog_channel.guild.get_member(int(user_id))

            if member != None:
                for role in member.roles:
                    if role.id == config.mayor:
                        await member.remove_roles(role, reason="Demoting the Mayor")
                    if role.id == config.reporter:
                        await member.remove_roles(role, reason="Demoting the Reporter")

        # Create a new shop instance
        for element in mailbox.shops:
            shop_data = db_shop.get_shop_config(element.shop_config)
            i = 1
            j = 0
            emoji_table = []
            page_amount = int(len(shop_data["items"])-1/20)+1


            for item in shop_data["items"]:
                if j % 20 == 0:
                    embed = discord.Embed(title="Shop (Page {}/{})".format(i,page_amount), description=shop_data["shop_description"], color=0x00ff00)

                embed.add_field(name="[{}] {}".format(item["emoji"], item["name"]), value="{} {}\n*{}*\n".format(item["price"], shop_data["currency"], item["description"]), inline=False) # Add item to shop
                emoji_table.append(emojize(item["emoji"]))
                j += 1

                if j % 20 == 0:
                    i += 1
                    response = await client.get_channel(int(element.destination)).send(embed=embed)
                    db_shop.add_shop(response.id)

                    for item in emoji_table:
                        await response.add_reaction(item)
                    emoji_table = []

            if j % 20 != 0:
                response = await client.get_channel(int(element.destination)).send(embed=embed)
                db_shop.add_shop(response.id)

                for item in emoji_table:
                    await response.add_reaction(item)

        # If the Mailbox has a message for the gamelog, this is where it's sent.
        for element in mailbox.gamelog:
            msg = await gamelog_channel.send(element.content)
            for emoji in element.reactions:
                await msg.add_reaction(emoji)
            if element.temporary == True:
                temp_msg.append(msg)

        # If the Mailbox has a message for the botspam, this is where it's sent.
        for element in mailbox.botspam:
            msg = await botspam_channel.send(element.content)
            for emoji in element.reactions:
                await msg.add_reaction(emoji)
            if element.temporary == True:
                temp_msg.append(msg)

        # If the Mailbox has a message for the storytime (in-game announcements) channel, this is where it's sent.
        for element in mailbox.storytime:
            msg = await storytime_channel.send(element.content)
            for emoji in element.reactions:
                await msg.add_reaction(emoji)
            if element.temporary == True:
                temp_msg.append(msg)

        # The messages are sent here if they are a direct message to the one sending a command.
        for element in mailbox.answer:
            msg = await message.channel.send(element.content)
            for emoji in element.reactions:
                await msg.add_reaction(emoji)
            if element.temporary == True:
                temp_msg.append(msg)

        # The messages that are destined for a specific channel, are sent here.
        for element in mailbox.channel:

            # The following code is sent if the message is an embed.
            if element.embed:
                if element.destination == "spam":
                    msg = await botspam_channel.send(embed=element.content)
                    for emoji in element.reactions:
                        await msg.add_reaction(emoji)
                    if element.temporary == True:
                        temp_msg.append(msg)
                else:
                    msg = await client.get_channel(int(element.destination)).send(embed=element.content)
                    for emoji in element.reactions:
                        await msg.add_reaction(emoji)
                    if element.temporary == True:
                        temp_msg.append(msg)
            # The following code is sent if the message is a regular message.
            else:
                msg = await client.get_channel(int(element.destination)).send(element.content)
                for emoji in element.reactions:
                    await msg.add_reaction(emoji)
                if element.temporary == True:
                    temp_msg.append(msg)

        # DMs are sent here.
        for element in mailbox.player:
            member = client.get_user(int(element.destination))
            main_guild = botspam_channel.guild
            if member == None:
                member = main_guild.get_member(int(element.destination))
            if member == None:
                await message.channel.send("Couldn't send a DM to <@{}>!".format(element.destination))
                await botspam_channel.send(
                    "<@{}> has attempted to send a DM to <@{}>, but failed, because we couldn't find the specified user via `client.get_user`.".format(
                        message.author.id, element.destination))
            else:
                try:
                    msg = await member.send(element.content)
                    for emoji in element.reactions:
                        await msg.add_reaction(emoji)
                    if element.temporary == True:
                        temp_msg.append(msg)
                except discord.errors.Forbidden:
                    botspam_channel.send('I wasn\'t allowed to send a DM to <@{}>! Here\'s the content:'.format(member.id))
                    botspam_channel.send(element.content)
                except Exception:
                    botspam_channel.send('I failed to send a DM to <@{}>! Could somebody send this, please?'.format(member.id))
                    botspam_channel.send(element.content)

        # Settings of existing channels are altered here.
        for element in mailbox.oldchannels:
            # element.channel - channel to be edited;
            # element.victim - person's permission to be changed;
            # element.number - type of setting to set to: see issue #83 for more info.

            print('Editing permissions of {} for channel {}...'.format(element.victim,element.channel))
            channel = client.get_channel(element.channel)
            user = client.get_user(int(element.victim))
            main_guild = botspam_channel.guild
            member = main_guild.get_member(int(element.victim))
            if member == None:
                if user == None:
                    await botspam_channel.send("That\'s problematic! I couldn\'t edit the cc info of <@{0}> *(<#{0}> <@&{0}> ?)*".format(element.victim))
                    print('Unable to locate member {}.'.format(element.victim))
                member = user
            if channel == None:
                await botspam_channel.send('Unable to edit channel <#{0}> *(<@{0}> <@&{0}> ?)*'.format(int(element.victim)))
            elif member != None:
                await remove_all_game_roles(member)
                if element.number == 0:
                    await channel.set_permissions(user, read_messages=False, send_messages=False)
                    try:
                        if int(db_get(member.id,'frozen')) == 0:
                            raise NotImplementedError("This is a purposeful error raise!")
                    except Exception:
                        if db.isParticipant(member.id):
                            await member.add_roles(get_role(main_guild.roles, config.participant), reason="Updating CC Permissions")
                        elif db.isParticipant(member.id,True,True):
                            await member.add_roles(get_role(main_guild.roles, config.dead_participant), reason="Updating CC Permissions")
                        elif db.isParticipant(member.id,True,True,True):
                            await member.add_roles(get_role(main_guild.roles, config.suspended), reason="Updating CC Permissions")
                    else:
                        await member.add_roles(get_role(main_guild.roles, config.frozen_participant), reason="Updating CC Permissions")
                elif element.number == 1:
                    await channel.set_permissions(user, read_messages=True, send_messages=True)
                    await member.add_roles(get_role(main_guild.roles, config.participant), reason="Updating CC Permissions")
                elif element.number == 2:
                    await channel.set_permissions(user, read_messages=True, send_messages=False)
                    await member.add_roles(get_role(main_guild.roles, config.frozen_participant), reason="Updating CC Permissions")
                elif element.number == 3:
                    await channel.set_permissions(user, read_messages=False, send_messages=False)
                    await member.add_roles(get_role(main_guild.roles, config.participant), reason="Updating CC Permissions")
                elif element.number == 4:
                    await channel.set_permissions(user, read_messages=True, send_messages=False)
                    if db.isParticipant(member.id,False,True):
                        await member.add_roles(get_role(main_guild.roles, config.dead_participant), reason="Updating CC Permissions")
                elif element.number == 5:
                    await channel.set_permissions(user, read_messages=True, send_messages=False)
                    await member.add_roles(get_role(main_guild.roles, config.participant), reason="Updating CC Permissions")
                elif element.number == 6:
                    await channel.set_permissions(user, read_messages=False, send_messages=False)
                    await member.add_roles(get_role(main_guild.roles, config.participant), reason="Updating CC Permissions")
                elif element.number == 7:
                    await channel.set_permissions(user, read_messages=False, send_messages=False)
                    await member.add_roles(get_role(main_guild.roles, config.participant), reason="Updating CC Permissions")
                elif element.number == 8:
                    await channel.set_permissions(user, read_messages=False, send_messages=False)
                    await member.add_roles(get_role(main_guild.roles, config.suspended), reason="Updating CC Permissions")
                else:
                    await msg.channel.send('Something went wrong! Please contact a Game Master.')
                    return
                if db.isParticipant(element.victim,True,True):
                    db.set_user_in_channel(element.channel,element.victim,element.number)


        # New channels are created here.
        for element in mailbox.newchannels:
            # element.name - name of the channel;
            # element.owner - owner of the channel;
            # element.members - members of the channel
            # element.settlers - members for whom this shall become their home channel
            # element.secret - boolean if the channel is a secret channel

            if element.secret:
                element.owner = client.user.id

            if ' ' not in element.name:

                main_guild = botspam_channel.guild # Find the guild we're in

                if element.owner not in element.members:
                    element.members.append(element.owner)
                for buddy in element.settlers:
                    if buddy not in element.members:
                        msg = """**Warning:** I'm adding settlers to a channel!\nThis is should not be a problem, \
                        but it does at least indicate a flaw in the bot's code. Please, report this to the Game Masters!"""
                        await client.get_channel(message.channel).send(msg)
                        element.members.append(buddy)

                viewers = []
                frozones = []
                abductees = []
                deadies = []

                # Add dead people & spectators to cc
                if not element.secret:
                    for user in [dead_buddy for dead_buddy in db.player_list() if dead_buddy not in db.player_list(True)]:
                        element.members.append(user)

                # Categorize all players
                for user in element.members:
                    member = main_guild.get_member(user)

                    if member == None:
                        await botspam_channel.send("That\'s problematic! I couldn\'t add <@{0}> to a cc. *(<#{0}> <@&{0}> ?)*".format(element.victim))
                        await message.author.send("It doesn't seem like <@{}> is part of the server! I am sorry, I can't add them to your **conspiracy channel**.".format(user))
                    elif db.isParticipant(user,False,True) == True:
                        if int(db_get(user,'abducted')) == 1:
                            abductees.append(member)
                        elif int(db_get(user,'frozen')) == 1:
                            frozones.append(member)
                        elif db.isParticipant(user,False,False) == False:
                            deadies.append(member)
                        else:
                            viewers.append(member)
                    elif db_get(user,'role') == 'Suspended':
                        pass
                    else:
                        deadies.append(member)

                # Delete any potential duplicates
                viewers = list(set(viewers))
                frozones = list(set(frozones))
                abductees = list(set(abductees))
                deadies = list(set(deadies))

                # Role objects (based on ID)
                roles = main_guild.roles # Roles from the guild
                game_master_role = discord.utils.find(lambda r: r.id == game_master, roles)
                # TODO: Add read permissions for spectators if element.secret == False
                default_permissions = {
                    main_guild.default_role: discord.PermissionOverwrite(read_messages=False,send_messages=False),
                    game_master_role: discord.PermissionOverwrite(read_messages=True,send_messages=True),
                    client.user: discord.PermissionOverwrite(read_messages=True,send_messages=True),
                    **{
                        member: discord.PermissionOverwrite(read_messages=True,send_messages=True) for member in viewers
                    },
                    **{
                        member: discord.PermissionOverwrite(read_messages=True,send_messages=False) for member in frozones
                    },
                    **{
                        member: discord.PermissionOverwrite(read_messages=True,send_messages=False) for member in deadies
                    }
                }

                if not element.secret:
                    intro_msg = creation_messages.cc_intro([v.id for v in viewers])
                    reason_msg = 'CC requested by ' + message.author.name
                    title = "s{}_cc_{}".format(config.season,element.name)
                    category_name = 'S{} CCs PART {}'.format(config.season,db.count_categories(element.secret) + 1)
                else:
                    intro_msg = secret_messages.creation(element.name,[v.id for v in viewers])
                    reason_msg = 'Secret {} channel created.'.format(element.name)
                    title = "s{}_{}".format(config.season,element.name)
                    category_name = 'S{} Secret Channels Part {}'.format(config.season,db.count_categories(element.secret) + 1)

                # Create a new category if needed
                if db.get_category(element.secret) == None:
                    category = await main_guild.create_category(category_name, reason='It seems like we couldn\'t use our previous category! Don\'t worry, I just created a new one.')
                    db.add_category(category.id,element.secret)
                else:
                    category = main_guild.get_channel(db.get_category(element.secret))

                try:
                    # Create the text channel
                    channel = await main_guild.create_text_channel(
                        name=title,
                        category=category,
                        overwrites=default_permissions,
                        reason=reason_msg)
                    db.add_channel(channel.id,element.owner,element.secret)
                    if element.secret:
                        db.add_secret_channel(channel.id,element.name)

                        # If the channel is meant for an amulet holder, assign the amulet holder.
                        if element.name == 'Amulet_Holder':
                            for member in viewers:
                                if db_get(member.id,'role') == 'Amulet Holder':
                                    db_set(member.id,'amulet',channel.id)
                    if element.trashy:
                        db.add_trash_channel(channel.id)

                    await channel.send(intro_msg)

                    # Set all access rules in the database
                    for member in viewers:
                        db.set_user_in_channel(channel.id,member.id,1)
                    for member in frozones:
                        db.set_user_in_channel(channel.id,member.id,2)
                    for member in abductees:
                        db.set_user_in_channel(channel.id,member.id,3)
                    for member in deadies:
                        if db.isParticipant(member.id,True,True) == True:
                            db.set_user_in_channel(channel.id,member.id,4)


                except Exception as e: # Catch any thrown exceptions and send an error to the user.
                    await message.channel.send('It seems like I\'ve encountered an error! Please let the Game Masters know about this!')
                    await botspam_channel.send("Oi, Game Masters! I got a problem concerning channel creation for ya to fix.")
                    await botspam_channel.send(e)
                    raise e # Send the full log to Buddy1913 and his sketchy VM.

                # Give the settlers their own happy little residence
                for buddy in element.settlers:
                    db_set(buddy,"channel",channel.id)

            else:
                """This should not happen, but we'll use it, to prevent the bot from purposely causing an error
                everytime someone attempts to create a channel that contains spaces. 'cause believe me,
                that happens ALL the time."""
                msg = await message.channel.send("I\'m terribly sorry, but you can\'t use spaces in your channel name. Try again!")
                temp_msg.append(msg)


        # Polls are created here.
        for element in mailbox.polls:
            # element.channel
            # element.purpose
            # element.user_id
            # element.description

            msg = element.description + '\n'
            emoji_table = []
            msg_table = []
            i = 0

            for user in db.poll_list():
                if db.isParticipant(int(user[0])):
                    i += 1
                    msg += user[1] + " - <@" + str(user[0]) + "> "

                    if int(user[2]) + int(user[3]) > 0:
                        if int(user[2]) == 1:
                            msg += "**[FROZEN]** "
                        if int(user[3]) == 1:
                            msg += "**[ABDUCTED] **"
                    else:
                        emoji_table.append(user[1])

                    if i % 20 == 19:
                        if client.get_channel(int(element.channel)) == None:
                            await botspam_channel.send("Failed to send message in correct channel. ({})".format(element.channel))
                            msg = await botspam_channel.send(element.content)
                        else:
                            msg = await client.get_channel(int(element.channel)).send(msg)
                        for emoji in emoji_table:
                            await msg.add_reaction(emoji)
                        msg_table.append(msg)
                        emoji_table = []
                        msg = ''
                    else:
                        msg += '\n'

            if msg != '':
                msg = await client.get_channel(element.channel).send(msg)
                for emoji in emoji_table:
                    await msg.add_reaction(emoji)
                msg_table.append(msg)
            db.add_poll(msg_table,element.purpose,element.channel,element.user_id)
            await botspam_channel.send("A poll has been created in <#{}>!".format(element.channel))


        # Categories are deleted here.
        for element in mailbox.deletecategories:
            id = element.channel
            category = client.get_channel(id)
            if category != None:
                bot_message = await message.channel.send('Please react with 👍 to confirm deletion of category `' + category.name + '`.\n\nNote: This action will irreversibly delete all channels contained within the specified category. Please use with discretion.')
                await bot_message.add_reaction('👍')
                def check(reaction, user):
                    return user == message.author and str(reaction.emoji) == '👍'
                try:
                    reaction, user = await client.wait_for('reaction_add', timeout=30.0, check=check)
                except asyncio.TimeoutError:
                    await message.channel.send('Confirmation timed out.')
                    try:
                        await bot_message.delete()
                    except Exception:
                        pass
                else:
                    await message.channel.send('Ok, I\'ll get right on that.\n\n*This might take some time.*')
                    for channel in category.channels:
                        await channel.delete()
                    await category.delete()
                    await message.channel.send('\n:thumbsup: Channels and category deleted')
            else:
                await message.channel.send('Sorry, I couldn\'t find that category.')

        clean_time = len(mailbox.cleaners)
        if clean_time > 0:
            await botspam_channel.send("Cleaning up {} channels! This may take some time.".format(clean_time))

        for channel in mailbox.cleaners:

            trash_channel = client.get_channel(int(channel))

            if trash_channel != None:
                for message_id in db.empty_trash_channel(channel):
                    message = await trash_channel.get_message(int(message_id))
                    if message != None:
                        await message.delete()

    # Delete all temporary messages after about two minutes.
    await asyncio.sleep(120)
    for msg in temp_msg:
        try:
            await msg.delete()
        except Exception:
            # Unable to delete the message.
            # It was probaly already deleted or something.
            pass
コード例 #6
0
def use_item(item_code, message):
    user_id = message.author.id
    if not inventory.has_item(user_id, item_code):
        return Mailbox().dm(
            "I'm sorry. You do not have the correct item in your inventory!",
            user_id, True)

    # Invisibility cloak
    if item_code == 100:
        if not db.isParticipant(user_id):
            return Mailbox().dm(
                "You are not a participant! You cannot protect yourself if you're not playing.",
                user_id, True)

        db.db_set(user_id, 'sleepingover', 1)
        inventory.give_item(user_id, 100, -1)
        return Mailbox().dm(
            "You are protected for the night. No-one should be able to find you...",
            user_id
        ).log(
            "<@{}> has used an invisibility cloak to protect themselves for the night!"
            .format(user_id))

    # Bucket of water
    if item_code == 101:
        if not db.isParticipant(user_id):
            return Mailbox().dm(
                "You are not a participant! You cannot unpowder yourself if you're not playing.",
                user_id)

        inventory.give_item(user_id, 101, -1)
        answer = Mailbox().dm(
            "The bucket of water refreshed your senses. If you were powdered, this effect has been undone!",
            user_id)
        if int(db.db_get(user_id, 'powdered')) == 1:
            answer.log(
                "<@{}> has used a bucket of water. They are no longer powdered!"
                .format(user_id))
        else:
            answer.log(
                "<@{}> has used a bucket of water - they weren't powdered, however."
                .format(user_id))
        db.db_set(user_id, 'powdered', 0)
        return answer

    # Royal sword
    if item_code == 102:
        # TODO
        return todo(user_id)

    # Disguise
    if item_code == 103:
        if not db.isParticipant(user_id):
            return Mailbox().dm(
                "You are not a participant! You cannot disguise anyone if you're not playing.",
                user_id, True)

        role = check.roles(message, 1)
        if not role:
            return Mailbox().dm(
                "**INVALID SYNTAX:** No role provided! Please provide a role!",
                user_id, True)

        victim_id = check.users(message, 1, True, True)
        if not victim_id:
            victim_id = [user_id]
        victim_id = victim_id[0]

        user_role = db.db_get(user_id, 'role')

        victim_role = db.db_get(victim_id, 'role')
        victim_frozen = int(db.db_get(victim_id, 'frozen'))
        victim_abducted = int(db.db_get(victim_id, 'abducted'))

        if victim_abducted == 1:
            return Mailbox().dm(
                "After having finished your great disguise, it seems like you couldn\'t find your target! Where have they gone off to?",
                user_id, True)
        if victim_frozen == 1:
            return Mailbox().dm(
                "I am sorry, but <@{}> is too cold for that! You\'ll need a lot more than warm suit to get \'em warmed up."
                .format(victim_id), user_id, True)

        db.db_set(victim_id, 'fakerole', role)
        inventory.give_item(user_id, 103, -1)
        answer = Mailbox().dm(
            "You have successfully disguised <@{}> as the **{}**!".format(
                victim_id, role), user_id)

        answer.log(
            "With a disguise from their inventory, **{}** <@{}> has disguised <@{}>, the **{}**, as the **{}**!"
            .format(user_role, user_id, victim_id, victim_role, role))
        if victim_role == role:
            answer.log_add(
                "\n...does that sound stupid? *Of course!* But how are they supposed to know?"
            )
        return answer

    # Name tag
    if item_code == 104:
        # TODO
        return todo(user_id)

    # Med kit
    if item_code == 105:
        pass

    # Dagger
    if item_code == 106:
        if not db.isParticipant(user_id):
            return Mailbox().dm(
                "You are not a participant! You cannot attack anyone if you're not playing.",
                user_id, True)

        if user_id == victim_id:
            return Mailbox().respond(
                "I am sorry, but you cannot attempt suicide!\nNot because it's not an option, no, just because we want to see you SUFFER!",
                True)

        if int(db.db_get(victim_id, 'abducted')) == 1:
            return Mailbox().respond(
                "You attempted to attack <@{}>... but they don't seem to be around in town! That is strange."
                .format(victim_id), True)
        if int(db.db_get(victim_id, 'frozen')) == 1:
            return Mailbox().respond(
                "You wanted to pay a visit to <@{}>... but it seems they were frozen! Try again, please."
                .format(victim_id), True)

        inventory.give_item(user_id, 106, -1)
        db.add_kill(victim_id, 'Assassin', user_id)

        answer = Mailbox().dm(
            "You have successfully used a **Dagger** to assasinate <@{}>. They will die when the time shifts!",
            user_id, True)
        return answer.log(
            "<@{}> has used a **Dagger** to assassinate <@{}>.".format(
                user_id, victim_id))
コード例 #7
0
async def on_message(message):
    # we do not want the bot to reply to itself
    if message.author == client.user:
        return

    gamelog_channel = client.get_channel(int(config.game_log))
    botspam_channel = client.get_channel(int(config.bot_spam))
    storytime_channel = client.get_channel(int(config.story_time))

    # Check if the message author has the Game Master role
    isGameMaster = False
    if message.guild == gamelog_channel.guild:
        if game_master in [y.id for y in message.guild.get_member(message.author.id).roles]:
            isGameMaster = True

    isAdmin = False
    if message.guild == gamelog_channel.guild:
        if administrator in [y.id for y in message.guild.get_member(message.author.id).roles]:
            isAdmin = True

    result = process(message,isGameMaster,isAdmin)

    temp_msg = []

    for mailbox in result:

        if mailbox.evaluate_polls == True:
            for poll in db.get_all_polls():
                # poll.msg_table -> list of message ids
                # poll.blamed -> name of killer
                # poll.purpose -> the reason of the kill

                poll_channel = client.get_channel(int(poll.channel))
                if poll_channel == None:
                    await botspam_channel.send("We got a problem! Could you send these results to the appropriate channel, please?")
                    poll_channel = botspam_channel

                user_table = []
                for msg in poll.msg_table:
                    poll_msg = await poll_channel.get_message(msg)
                    for emoji in poll_msg.reactions:
                        users = await emoji.users().flatten()

                        for person in users:
                            if db.isParticipant(person.id):
                                user_table.append([person.id,emoji.emoji])

                log, result, chosen_emoji = count_votes(user_table,poll.purpose)

                await gamelog_channel.send(log)
                await poll_channel.send(result)

                chosen_one = db.emoji_to_player(chosen_emoji)

                if chosen_emoji != '' and chosen_one != None:
                    if poll.purpose == 'lynch':
                        db.add_kill(chosen_one,'Innocent')
                    elif poll.purpose == 'Mayor':
                        # TODO: give Mayor role and add data to dynamic.json
                        pass
                    elif poll.purpose == 'Reporter':
                        # TODO: give Reporter role and add data to dynamic.json
                        pass
                    elif poll.purpose == 'wolf':
                        db.add_kill(chosen_one,'Werewolf',db.random_wolf())
                    elif poll.purpose == 'cult':
                        db.add_kill(chosen_one,'Cult Leader',db.random_cult())
                    elif poll.purpose == 'thing':
                        # TODO: kill poor victim
                        pass


        for element in mailbox.gamelog:
            msg = await gamelog_channel.send(element.content)
            for emoji in element.reactions:
                await msg.add_reaction(emoji)
            if element.temporary == True:
                temp_msg.append(msg)

        for element in mailbox.botspam:
            msg = await botspam_channel.send(element.content)
            for emoji in element.reactions:
                await msg.add_reaction(emoji)
            if element.temporary == True:
                temp_msg.append(msg)

        for element in mailbox.storytime:
            msg = await storytime_channel.send(element.content)
            for emoji in element.reactions:
                await msg.add_reaction(emoji)
            if element.temporary == True:
                temp_msg.append(msg)

        for element in mailbox.answer:
            msg = await message.channel.send(element.content)
            for emoji in element.reactions:
                await msg.add_reaction(emoji)
            if element.temporary == True:
                temp_msg.append(msg)

        for element in mailbox.channel:
            if element.embed:
                if element.destination == "spam":
                    msg = await botspam_channel.send(embed=element.content)
                    for emoji in element.reactions:
                        await msg.add_reaction(emoji)
                    if element.temporary == True:
                        temp_msg.append(msg)
                else:
                    msg = await client.get_channel(int(element.destination)).send(embed=element.content)
                    for emoji in element.reactions:
                        await msg.add_reaction(emoji)
                    if element.temporary == True:
                        temp_msg.append(msg)
            else:
                msg = await client.get_channel(int(element.destination)).send(element.content)
                for emoji in element.reactions:
                    await msg.add_reaction(emoji)
                if element.temporary == True:
                    temp_msg.append(msg)

        for element in mailbox.player:
            member = client.get_user(element.destination)
            if member == None:
                await message.channel.send("Couldn't send a DM to <@{}>!".format(element.destination))
                await botspam_channel.send("<@{}> has attempted to send a DM to <@{}>, but failed, because we couldn't find the specified user via `get_user`.".format(message.author.id,element.destination))
            else:
                msg = await member.send(element.content)
                for emoji in element.reactions:
                    await msg.add_reaction(emoji)
                if element.temporary == True:
                    temp_msg.append(msg)

        for element in mailbox.oldchannels:
            # element.channel - channel to be edited;
            # element.victim - person's permission to be changed;
            # element.number - type of setting to set to:
                # 0 - no access     (no view, no type)
                # 1 - access        (view + type)
                # 2 - frozen        (view, no type)
                # 3 - abducted      (no view, no type)
                # 4 - dead          (dead role?)

            # 0 -> read = False
            # 1 -> read = True
            # 2 -> give frozen (if they don't have it yet)
            # 3 -> read = False
            # 4 -> give dead role + remove participant role
            # 5 -> mute
            # 6 -> also mute, no read

            channel = client.get_channel(element.channel)
            user = client.get_user(element.victim)
            main_guild = botspam_channel.guild
            member = main_guild.get_member(element.victim)
            await remove_all_game_roles(member)
            if element.number == 0:
                await channel.set_permissions(user, read_messages=False, send_messages=False)
                await member.add_roles(get_role(main_guild.roles, config.participant), reason="Updating CC Permissions")
            elif element.number == 1:
                await channel.set_permissions(user, read_messages=True, send_messages=True)
                await member.add_roles(get_role(main_guild.roles, config.participant), reason="Updating CC Permissions")
            elif element.number == 2:
                await channel.set_permissions(user, read_messages=True, send_messages=False)
                await member.add_roles(get_role(main_guild.roles, config.frozen_participant), reason="Updating CC Permissions")
            elif element.number == 3:
                await channel.set_permissions(user, read_messages=False, send_messages=False)
                await member.add_roles(get_role(main_guild.roles, config.participant), reason="Updating CC Permissions")
            elif element.number == 4:
                await channel.set_permissions(user, read_messages=True, send_messages=False)
                await member.add_roles(get_role(main_guild.roles, config.dead_participant), reason="Updating CC Permissions")
            elif element.number == 5:
                await channel.set_permissions(user, read_messages=True, send_messages=False)
                await member.add_roles(get_role(main_guild.roles, config.participant), reason="Updating CC Permissions")
            elif element.number == 6:
                await channel.set_permissions(user, read_messages=False, send_messages=False)
                await member.add_roles(get_role(main_guild.roles, config.participant), reason="Updating CC Permissions")
            elif element.number == 7:
                await channel.set_permissions(user, read_messages=False, send_messages=False)
                await member.add_roles(get_role(main_guild.roles, config.dead_participant), reason="Updating CC Permissions")
            elif element.number == 8:
                await channel.set_permissions(user, read_messages=False, send_messages=False)
                await member.add_roles(get_role(main_guild.roles, config.suspended), reason="Updating CC Permissions")
            else:
                await msg.channel.send('Something went wrong! Please contact a Game Master.')
                return
            if db.isParticipant(element.victim,True,True):
                db.set_user_in_channel(element.channel,element.victim,element.number)


        for element in mailbox.newchannels:
            # element.name - name of the channel;
            # element.owner - owner of the channel;
            # element.members - members of the channel
            # element.settlers - members for whom this shall become their home channel
            #
            # @Participant      - no view + type
            # @dead Participant - view + no type
            # @everyone         - no view + no type

            # All you need to do is create a channel where only the channel owner has access.
            # The other members are given access through another Mailbox.
            # You could make the work easier if you also posted a cc channel message already over here.

            if ' ' not in element.name:

                main_guild = botspam_channel.guild # Find the guild we're in

                if element.owner not in element.members:
                    element.members.append(element.owner)
                for buddy in element.settlers:
                    if buddy not in element.members:
                        msg = """**Warning:** I'm adding settlers to a channel!\nThis is should not be a problem, \
                        but it does at least indicate a flaw in the bot's code. Please, report this to the Game Masters!"""
                        await client.get_channel(message.channel).send(msg)
                        element.members.append(buddy)

                viewers = []
                frozones = []
                abductees = []
                deadies = []
                for user in element.members:
                    member = main_guild.get_member(user)

                    if member == None:
                        await message.author.send("It doesn't seem like <@{}> is part of the server! I am sorry, I can't add them to your **conspiracy channel**.".format(user))
                    elif db.isParticipant(user,False,True) == True:
                        if int(db_get(user,'abducted')) == 1:
                            abductees.append(member)
                        elif int(db_get(user,'frozen')) == 1:
                            frozones.append(member)
                        elif db.isParticipant(user,False,False) == False:
                            deadies.append(member)
                        else:
                            viewers.append(member)
                    else:
                        deadies.append(member)

                intro_msg = creation_messages.cc_intro([v.id for v in viewers])

                # Role objects (based on ID)
                roles = main_guild.roles # Roles from the guild
                game_master_role = discord.utils.find(lambda r: r.id == game_master, roles)
                default_permissions = {
                    main_guild.default_role: discord.PermissionOverwrite(read_messages=False,send_messages=False),
                    game_master_role: discord.PermissionOverwrite(read_messages=True,send_messages=True),
                    client.user: discord.PermissionOverwrite(read_messages=True,send_messages=True),
                    **{
                        member: discord.PermissionOverwrite(read_messages=True,send_messages=True) for member in viewers
                    },
                    **{
                        member: discord.PermissionOverwrite(read_messages=True,send_messages=False) for member in frozones
                    },
                    **{
                        member: discord.PermissionOverwrite(read_messages=True,send_messages=False) for member in deadies
                    }
                }

                # Create a new category if needed
                if db.get_category() == None:
                    category = await main_guild.create_category('CC part {}'.format(db.count_categories()), reason='It seems like we couldn\'t use our previous category! Don\'t worry, I just created a new one.')
                    db.add_category(category.id)
                else:
                    category = main_guild.get_channel(db.get_category())

                try:
                    # Create the text channel
                    reason_msg = 'CC requested by ' + message.author.name
                    channel = await main_guild.create_text_channel(
                        name="s{}_{}".format(config.season,element.name),
                        category=category,
                        overwrites=default_permissions,
                        reason=reason_msg)
                    db.add_channel(channel.id,element.owner)
                    await channel.send(intro_msg)

                    # Set all access rules in the database
                    for member in viewers:
                        db.set_user_in_channel(channel.id,member.id,1)
                    for member in frozones:
                        db.set_user_in_channel(channel.id,member.id,2)
                    for member in abductees:
                        db.set_user_in_channel(channel.id,member.id,3)
                    for member in deadies:
                        if db.isParticipant(member.id,True,True) == True:
                            db.set_user_in_channel(channel.id,member.id,4)


                except Exception as e: # Catch any thrown exceptions and send an error to the user.
                    await message.channel.send('It seems like I\'ve encountered an error! Please let the Game Masters know about this!')
                    await botspam_channel.send("Oi, Game Masters! I got a problem concerning channel creation for ya to fix.")
                    await botspam_channel.send(e)
                    raise e # Send the full log to Buddy1913 and his sketchy VM.

                # Give the settlers their own happy little residence
                for buddy in element.settlers:
                    db_set(buddy,"channel",channel.id)

            else:
                """This should not happen, but we'll use it, to prevent the bot from purposely causing an error
                everytime someone attempts to create a channel that contains spaces. 'cause believe me,
                that happens ALL the time."""
                msg = await message.channel.send("I\'m terribly sorry, but you can\'t use spaces in your channel name. Try again!")
                temp_msg.append(msg)

        for element in mailbox.polls:
            # element.channel
            # element.purpose
            # element.user_id
            # element.description

            msg = element.description + '\n'
            emoji_table = []
            msg_table = []
            i = 0

            for user in db.poll_list():
                if db.isParticipant(int(user[0])):
                    i += 1
                    msg += user[1] + " - <@" + str(user[0]) + "> "

                    if int(user[2]) + int(user[3]) > 0:
                        if int(user[2]) == 1:
                            msg += "**[FROZEN]** "
                        if int(user[3]) == 1:
                            msg += "**[ABDUCTED] **"
                    else:
                        emoji_table.append(user[1])

                    if i % 20 == 19:
                        msg = await client.get_channel(element.channel).send(msg)
                        for emoji in emoji_table:
                            await msg.add_reaction(emoji)
                        msg_table.append(msg)
                        msg = ''
                    else:
                        msg += '\n'

            if msg != '':
                msg = await client.get_channel(element.channel).send(msg)
                for emoji in emoji_table:
                    await msg.add_reaction(emoji)
                msg_table.append(msg)
            db.add_poll(msg_table,element.purpose,element.channel,element.user_id)
            await botspam_channel.send("A poll has been created in <#{}>!".format(element.channel))

        for element in mailbox.deletecategories:
            id = element.channel
            category = client.get_channel(id)
            if category != None:
                bot_message = await message.channel.send('Please react with 👍 to confirm deletion of category `' + category.name + '`.\n\nNote: This action will irrevirsibly delete all channels contained within the specified category. Please use with discretion.')
                await bot_message.add_reaction('👍')
                def check(reaction, user):
                    return user == message.author and str(reaction.emoji) == '👍'
                try:
                    reaction, user = await client.wait_for('reaction_add', timeout=30.0, check=check)
                except asyncio.TimeoutError:
                    await message.channel.send('Confirmation timed out.')
                else:
                    await message.channel.send('Ok, I\'ll get right on that.\n\n*This might take some time.*')
                    for channel in category.channels:
                        await channel.delete()
                    await category.delete()
                    await message.channel.send('\n:thumbsup: Channels and category deleted')
            else:
                await message.channel.send('Sorry, I couldn\'t find that category.')

    # Delete all temporary messages after "five" seconds.
    await asyncio.sleep(120)
    for msg in temp_msg:
        await msg.delete()