Пример #1
0
def night():
    """Start the second part of the day.  
    The function assumes all polls have been evaluated, and that looking after attacks can begin.  
    The function returns a Mailbox."""
    threat = db.get_kill()
    answer = Mailbox().log("**Results from daily deaths:**")

    if dy.get_stage() == "Night":
        return Mailbox().respond("Sure, man. Whatever.")

    while threat != None:

        answer = roles.attack(threat[1],threat[2],threat[3],answer)
        threat = db.get_kill()

    for player in db.player_list(True):
        # Give potential night uses
        user_role = db_get(player,'role')
        for i in range(len(roles.night_users)):
            if user_role in roles.night_users[i]:
                # Give one-time users their one-time power
                if i == 0:
                    if dy.day_number() == 0:
                        db_set(player,'uses',1)
                    break

                if user_role in ['White Werewolf'] and dy.day_number() % 2 == 0:
                    i = 1

                db_set(player,'uses',i)
                answer.msg(power.power(user_role),db_get(player,'channel'))
                break

    answer.story(evening.evening(db.get_deadies()))
    db.delete_deadies()

    # Add polls
    for player in db.player_list():
        if db_get(player,'role') in pos.wolf_pack:
            for channel_id in db.get_secret_channels('Werewolf'):
                answer.new_poll(channel_id,'wolf',db.random_wolf(),story_text('wolf'))
            break
    for player in db.player_list():
        if db_get(player,'role') == 'Cult Leader':
            for channel_id in db.get_secret_channels('Cult_Leader'):
                answer.new_poll(channel_id,'cult',db.random_cult(),story_text('cult'))
            break
    for channel_id in db.get_secret_channels('Swamp'):
        answer.new_poll(channel_id,'thing','',story_text('thing'))

    answer.log("```Night {}```".format(dy.day_number()))
    dy.set_stage("Night")

    return answer
Пример #2
0
def pight():
    """This function takes care of all properties that need to happen in the first wave of the end of the day.
    The function returns a Mailbox."""

    if dy.get_stage() == "Night":
        return [
            Mailbox().respond(
                "Whaddaya mean, `{}pight`? It already **is** night, bud.".
                format(config.universal_prefix))
        ]

    answer = Mailbox(True)
    for user_id in db.player_list():
        user_role = db_get(user_id, 'role')

        # Remove potential day uses
        for i in range(len(roles.day_users)):
            if user_role in roles.day_users[i]:
                if i > 0:
                    db_set(user_id, 'uses', 0)
                break

        # Give the user their votes back
        db_set(user_id, 'votes', 1)
        if user_role == "Immortal":
            db_set(user_id, 'votes', 3)
        if user_role == "Idiot ":
            db_set(user_id, 'votes', 0)

    return [answer]
def flute_victory():
    """This function returns true if the flute players have won."""
    for user in db.player_list():
        if db.isParticipant(user):
            if db.db_get(user,'role') != 'Flute Player' and db.db_get(user,'enchanted') == 0:
                return False
    return True
Пример #4
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)
def white_wolf_victory():
    """This function returns true if the white werewolf has won."""
    winner = 0
    for user in db.player_list():
        if db.isParticipant(user):
            if winner > 0:
                return False
            if db.db_get(user,'role') != 'White Werewolf':
                return False
            winner += 1
    return True
Пример #6
0
def day():
    """Start the second part of the day.  
    The function assumes all polls have been evaluated, and that looking after attacks can begin.  
    The function returns a Mailbox."""
    threat = db.get_kill()
    answer = Mailbox().log("**Results from night attacks:**")

    if dy.get_stage() == "Day":
        return Mailbox().respond("Sure, man. Whatever.")

    while threat != None:

        answer = roles.attack(threat[1], threat[2], threat[3], answer)
        threat = db.get_kill()

    for player in db.player_list(True):
        # Give potential day uses
        user_role = db_get(player, 'role')
        for i in range(len(roles.day_users)):
            if user_role in roles.day_users[i]:
                # Give one-time users their one-time power
                if i == 0:
                    if dy.day_number() == 0:
                        db_set(player, 'uses', 1)
                    break

                db_set(player, 'uses', i)
                answer.msg(power.power(user_role), db_get(player, 'channel'))
                break

    answer.story(morning.story_time(db.get_deadies()))
    db.delete_deadies()
    db.delete_hookers()

    # Add polls
    if dy.day_number() != 0:
        answer.new_poll(dy.voting_booth(), 'lynch', '', story_text('lynch'))
    if dy.get_mayor() == 0:
        answer.new_poll(dy.voting_booth(), 'Mayor', '', story_text('Mayor'))
    elif dy.get_reporter() == 0:
        answer.new_poll(dy.voting_booth(), 'Reporter', '',
                        story_text('Reporter'))

    dy.next_day()
    dy.set_stage('Day')
    answer.log("```Day {}```".format(dy.day_number()))

    return answer
Пример #7
0
def start_game():
    """This function is triggered at the start of the game. If successful, the function returns a Mailbox.
    If unsuccessful, the function still returns a Mailbox, but will also confirm the error in the console."""

    # Make sure there isn't already a game going on!
    if dy.get_stage() != "NA":
        print("ERROR: According to " + dy.dynamic_config +
              ", there's already a game going on!")
        return Mailbox().respond(
            "I'm sorry! A game cannot be started while there's another one going on already!"
        )

    # Choose the roles out of the given role-pool
    role_pool = []
    for choice in view_roles():
        for i in range(choice.amount):
            role_pool.append(choice.role)

    if len(db.player_list()) > len(role_pool):
        print(
            "The game cannot be started while there are less roles available than that there are participants signed up."
        )
        return Mailbox().respond("Not enough roles to distribute available!",
                                 True)

    # If there are enough roles available, make a selection, evaluate the selection, and, if accepted, distribute the roles.
    if not pos.valid_distribution(role_pool, True):
        return Mailbox().respond(
            "I am sorry, but I cannot use an invalid distribution to start the game!",
            True)

    answer = Mailbox(True)

    attempts = 0
    while attempts < 1000:
        attempts += 1
        chosen_roles = random.sample(role_pool, len(db.player_list()))

        if pos.valid_distribution(chosen_roles, True) == True:

            answer.create_cc("Graveyard", 0, [], [], True)
            answer.create_cc("Market", 0, [], [], True)
            answer.create_cc("Reporter", 0, [], [], True)

            # Assign the roles to all users.
            user_list = db.player_list()

            for i in range(len(user_list)):
                user_id = user_list[i]
                user_role = chosen_roles[i]

                db_set(user_id, 'role', user_role)
                db_set(user_id, 'fakerole', user_role)
                db_set(user_id, 'channel', config.game_log)

                answer.log(
                    "{} - <@{}> has received the role of the `{}`!".format(
                        db_get(user_id, 'emoji'), user_id, user_role))
                answer.dm(
                    "This message is giving you your role for season `{}` of the *Werewolves* game.\n\n"
                    .format(config.season), user_id)
                answer.dm_add('Your role is `{}`.\n\n'.format(user_role))
                answer.dm_add(
                    "**You are not allowed to share a screenshot of this message!** "
                )
                answer.dm_add(
                    "You can claim whatever you want about your role, but you may under **NO** "
                )
                answer.dm_add(
                    "circumstances show this message in any way to any other participants.\n"
                )
                answer.dm_add(
                    "We hope you are happy with the role you gained, and we hope you'll enjoy the game as much as we do.\n\n"
                )
                answer.dm_add("Good luck... 🌕")

                if user_role in pos.personal_secrets:
                    answer.create_sc(user_id, user_role)
                if user_role in pos.shared_secrets:
                    answer.add_to_sc(user_id, user_role)

                if user_role == "Cult Member":
                    answer.add_to_sc(user_id, "Cult Leader")
                if user_role in pos.wolf_pack:
                    answer.add_to_sc(user_id, "Werewolf")
                if user_role == "Bloody Butcher":
                    answer.add_to_sc(user_id, "Butcher")
                if user_role == "Devil":
                    answer.add_to_sc(user_id, "Demon")
                if user_role == "Vampire":
                    answer.add_to_sc(user_id, "Undead")
                if user_role == "Witch":
                    db_set(user_id, 'uses', 3)

            answer.story(
                'The current distribution is {}'.format(chosen_roles))  # TODO
            answer.story(
                'I know, I know. That looks ugly as hell. We\'re trying to make it look good!'
            )

            if "Flute Player" in chosen_roles:
                answer.create_cc("Flute_Victims", 0, [], [], True)

            # If the four horsemen are part of the game, assign numbers to all players.
            if "Horseman" in chosen_roles:
                nothorse_table = [
                    user_id for user_id in db.player_list()
                    if db_get(user_id, 'role') != 'Horseman'
                ]
                horse_table = [
                    user_id for user_id in db.player_list()
                    if db_get(user_id, 'role') == 'Horseman'
                ]

                nothorse_table.shuffle()
                horse_table.shuffle()

                for i in range(4):
                    db_set(horse_table[i], 'horseman', i + 1)

                for i in range(16):
                    db_set(nothorse_table[i], 'horseman', (i % 4) + 1)

            # Reset the day timer
            dy.reset_day()
            dy.set_stage('Night')

            return answer.respond(
                "Very well! The game will start tomorrow morning.")

    answer.respond("Timeout reached! Your distribution is too crazy!", True)
    return answer
Пример #8
0
def count_votes(voting_table, purpose='lynch', mayor=0):
    """Count votes based on reactions given to """
    user_table = []
    blacklist = []
    blacklist2 = []
    emoji_table = []

    for vote in voting_table:
        # Add new emoji
        if vote[1] not in emoji_table:
            emoji_table.append(vote[1])

        # Filter self-votes and double votes
        if vote[0] in blacklist or vote[0] in blacklist2:
            pass
        elif vote[0] == emoji_to_player(
                vote[1]) and purpose not in ['Mayor', 'Reporter']:
            blacklist2.append(vote[0])
            if vote[0] in user_table:
                user_table.remove(vote[0])
        elif vote[0] in user_table:
            blacklist.append(vote[0])
            user_table.remove(vote[0])
        else:
            user_table.append(vote[0])

    # Evaluate table, filter double votes and continue
    if purpose == 'lynch':
        voting_table = [
            Vote(vote[0], vote[1], int(db_get(vote[0], 'votes')))
            for vote in voting_table if vote[0] in user_table
        ]
    else:
        voting_table = [
            Vote(vote[0], vote[1]) for vote in voting_table
            if vote[0] in user_table
        ]
    blacklist = [Disqualified(user) for user in blacklist]
    blacklist2 = [Disqualified(user, 1) for user in blacklist2]
    blacklist.extend(blacklist2)

    # Add extra (secret) outside lynches, may some special events happen.
    if purpose == 'lynch':
        for user in player_list():
            if int(db_get(user, 'threatened')) > 0:
                voting_table.append(
                    Vote("RAVEN THREAT", db_get(user, 'emoji'),
                         int(db_get(user, 'threatened'))))

                # Add emoji to table
                if db_get(user, 'emoji') not in emoji_table:
                    emoji_table.append(db_get(user, 'emoji'))

    # print([[vote.user,vote.emoji,vote.votes] for vote in voting_table])

    # Create the evaluation messages
    answer = "**__Poll results "
    log = "**__Poll results "

    if purpose == 'wolf':
        answer += "from wolf attack:__**\n\n"
        log += "from wolf attack:__**\n\n"
    elif purpose == 'cult':
        answer += "from cult attack:__**\n\n"
        log += "from cult attack:__**\n\n"
    elif purpose == 'thing':
        answer += "from the swamp:__**\n\n"
        log += "from the swamp:__**\n\n"
    elif purpose == 'lynch':
        answer += "from public execution on day {}:__**\n\n".format(
            day_number())
        log += "from public execution on day {}:__**\n\n".format(day_number())
    elif purpose == 'Mayor':
        answer += "from Mayor election:__**\n\n"
        log += "from Mayor election:__**\n\n"
    elif purpose == 'Reporter':
        answer += "from Reporter election:__**\n\n"
        log += "from Reporter election:__**\n\n"

    max_i = 0
    chosen_emoji = ''

    for emoji in emoji_table:
        emoji_votes = [vote for vote in voting_table if vote.emoji == emoji]

        if emoji_votes != []:
            for vote in emoji_votes:
                if vote.type == 'user':
                    answer += "**{} - VOTES FOR <@{}>:**\n".format(
                        emoji, emoji_to_player(emoji))
                    break
            log += "**{} - VOTES FOR <@{}>:**\n".format(
                emoji, emoji_to_player(emoji))
        i = 0

        for vote in emoji_votes:
            # vote.user
            # vote.type
            # vote.emoji
            # vote.votes
            if vote.type == 'user':
                answer += "<@{}> ".format(vote.user)
                log += "<@{}> ".format(vote.user)
                if vote.user == mayor:
                    vote.votes += 1
                    answer += "- @Mayor "
                    log += "- @Mayor "
                if vote.votes != 1:
                    log += "*({}x)* ".format(vote.votes)
                i += vote.votes
                log += '\n'
                answer += '\n'
            elif vote.type == 'generic':
                log += "{} ".format(vote.user)
                if vote.votes > 1:
                    log += "*({}x)* ".format(vote.votes)
                i += vote.votes
                log += '\n'
            else:
                answer += "*Oops! An error occured on this line!*\n"
                log += "*Oops! An error occured on this line! Looks like we\'ve got an undefined voting type!*\n"

        if i > 0:
            log += "**TOTAL: {} votes**\n\n".format(i)
        else:
            log += '\n\n'

        if i == max_i:
            chosen_emoji = ''
        if i > max_i:
            chosen_emoji = emoji
            max_i = i

    answer += "\n"
    log += "\n"

    for cheater in blacklist:
        if cheater.reason == 0:
            answer += "<@{}>, you have been disqualified for double voting.\n".format(
                cheater.user)
            log += "<@{}> has been disqualified for double voting.\n".format(
                cheater.user)
        if cheater.reason == 1:
            answer += "<@{}>, your vote has been disqualified for you may not vote for yourself on this poll.\n".format(
                cheater.user)
            log += "<@{}> has been disqualified for voting on themselves.\n".format(
                cheater.user)

    if chosen_emoji != '':
        answer += "\nThe emoji {} has the most votes, making <@{}> the winner of this poll!".format(
            chosen_emoji, emoji_to_player(chosen_emoji))
        log += "\nThe emoji {} has the most votes, effectively making <@{}> the winner of this poll.".format(
            chosen_emoji, emoji_to_player(chosen_emoji))
    elif emoji_table != []:
        answer += "\nIt seems like we\'ve reached a tie! No-one will win this poll, I\'m sorry!"
        log += "\nThe poll has reached a tie and will not choose a winner."
    else:
        answer += "\nIt seems like no-one has voted! Well, in that case, there won\'t be a winner either."
        log += "\nNo votes have been registered."

    return log, answer, chosen_emoji
def viliager_victory():
    """This function returns true if the town's win condition has been met."""
    for user in db.player_list():
        if db.isParticipant(user) and user not in villager_team:
            return False
    return True
Пример #10
0
def pay():
    """This function takes care of all properties that need to happen in the first wave of the end of the night.
    The function returns a Mailbox."""

    if dy.get_stage() == "Day":
        return [
            Mailbox().respond(
                "Whaddaya mean, `{}pay`? It already **is** day, bud.".format(
                    config.universal_prefix))
        ]

    answer = Mailbox()
    answer_table = [Mailbox(True)]
    for user_id in db.player_list():
        user_role = db_get(user_id, 'role')

        # Remove potential night uses
        for i in range(len(roles.night_users)):
            if user_role in roles.night_users[i]:
                if i > 0:
                    db_set(user_id, 'uses', 0)
                break

        # Force Cupid to fall in love
        if user_role == "Cupid" and db_get(user_id, 'uses') > 0:
            chosen = False
            attempts = 0

            while not chosen and attempts < 1000:
                forced_victim = random.choice(db.player_list(True, True))
                chosen = cupid_kiss(user_id, forced_victim, False)

            answer_table.append(chosen)

        # Force Dog to become Innocent
        if user_role == "Dog" and db_get(user_id, 'uses') > 0:
            db_set(user_id, 'role', "Innocent")
            answer.msg(
                "You haven't chosen a role! That's why you have now become and **Innocent**!",
                db_get(user_id, 'channel'))
            answer.log(
                "The **Dog** <@{}> didn't choose a role last night and turned into an **Innocent**!"
                .format(user_id))

        # Remove hooker effects
        db_set(user_id, 'sleepingover', 0)
        for standoff in db.get_standoff(user_id):
            if standoff[2] == 'Hooker':
                db.delete_standoff(standoff[0])

        # Force Look-Alike to become Innocent
        if user_role == "Look-Alike":
            db_set(user_id, 'role', "Innocent")
            answer.msg(
                "You haven't chosen a role! That's why you have now become an **Innocent**!",
                db_get(user_id, 'channel'))
            answer.log(
                "The **Dog** <@{}> didn't choose a role last night and turned into an **Innocent**!"
                .format(user_id))

        # Remove tanner disguises
        db_set(user_id, 'fakerole', user_role)

        # Remove zombie tag
        db_set(user_id, 'bitten', 0)

    answer_table.append(answer)
    return answer_table
Пример #11
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
Пример #12
0
def attack(user_id, role, murderer, answer=Mailbox().log(''), recursive='\n'):
    """This functions attacks the given player with the given role.  
    The effects are immediate, but they can be used in all scenarios, as only\
    standoffs are executed during this attack."""

    if role == 'Inactive':
        answer.log_add(recursive + success + skull +
                       "<@{}> was killed due to inactivity.".format(user_id))
        return instant_death(user_id, role, 'Inactive', answer,
                             recursive + next)

    # Prevent Pyromancer from causing way too long lines
    # No, I didn't add this during debugging.
    # Yes, that means I planned to design it this terribly.
    if role == 'Pyromancer' and int(db_get(user_id, 'powdered')) != 1:
        return answer

    user_role = db_get(user_id, 'role')
    answer.log_add(recursive + failure)

    try:
        demonized = False
        if int(db_get(user_id, 'demonized')) == 1:
            demonized = True

        undead = False
        if int(db_get(user_id, 'undead')) == 1 or user_role == 'Undead':
            undead = True
            demonized = False
    except Exception:
        demonized = False
        undead = False

    # End function if player is dead (exit condition for recursion)
    if user_role in ['Dead', 'Spectator', 'Suspended', None, 'Unknown']:
        return answer.log_add(recursive + success +
                              '<@{}> was already dead!'.format(user_id))

    if role == 'Cupid':
        answer.log_add(recursive + success + skull +
                       '<@{}> committed suicide.'.format(user_id))
        answer = instant_death(user_id, role, 'Cupid', answer,
                               recursive + next)
        if int(db_get(user_id, 'abducted')) != int(db_get(
                murderer, 'abducted')):
            answer.dm("Abducted or not, you know your lover has deceased! ",
                      user_id)
            answer.dm_add(
                "You couldn't handle the pain, and that's why you decided to put an end to it.\n"
            )
            answer.dm_add("Your story ends here.")
        elif int(db_get(user_id, 'frozen')) == 1:
            answer.dm(
                "Even though your heart has become cold from the ice surrounding you, ",
                user_id)
            answer.dm_add(
                "but it got even colder when you saw the dead body of <@{}> being carried away.\n"
                .format(murderer))
            answer.dm_add(
                "It was at this moment where the ice got even colder...")
        else:
            answer.dm(
                "You couldn't bear the sight of your lover, <@{}>, ".format(
                    murderer), user_id)
            answer.dm_add(
                "lying dead in your arms. This is why you have decided to end it all!\n"
            )
            answer.dm_add(
                "Let\'s just hope this isn\'t like Romeo and Juliet...")
        answer.dm_add(
            "**Your lover, <@{}>, has died. In response, you have committed suicide.**"
            .format(murderer))
        return answer

    if role == 'Fortune Teller':
        if not undead:
            answer.dm(
                "Your idol, the fortune teller <@{}>, has deceased. ".format(
                    murderer), db_get(user_id, 'channel'))
            answer.dm_add(
                "They were a great inspiration to you, and that's why ")
            answer.dm_add("you've decided to get in their footsteps!\n")
            answer.dm_add("**You have turned into a Fortune Teller. Find and ")
            answer.dm_add(
                "eliminate all werewolves, solo players and other enemies!**")
            answer.log_add(recursive + success +
                           '<@{}> became a fortune teller.')
        else:
            answer.dm(
                "Your idol, the fortune teller <@{}>, has deceased. ".format(
                    murderer), user_id)
            answer.dm_add("They were a great inspiration to you... ")
            answer.dm_add(
                "back when you were alive, at least. Now, your undead heart is as cold as it has ever been, "
            )
            answer.dm_add("and nothing will happen to you.\n")
            answer.dm_add(
                "**The rules have changed. You will remain Undead.**")
            answer.log_add(recursive + success +
                           '<@{}> failed to become a fortune teller.')
            db_set(user_id, 'role', 'Fortune Teller')
        return answer

    if role == 'Horseman' and user_role == 'Horseman':
        horse_number = db_get(user_id, 'horseman')
        apocalypse_ready = True
        for player in db.player_list():
            if int(db_get(player, 'horseman')) != 0:
                apocalypse_ready = False
            if int(db_get(player, 'horseman')) == horse_number:
                db_set(player, 'horseman', 0)
        answer.log_add(recursive + success +
                       '<@{}> was united.'.format(user_id))

        if horse_number != 0:
            for channel_id in db.get_secret_channels('Horseman'):
                answer.msg(
                    '**Horseman #{} has been united!**'.format(horse_number),
                    channel_id)

        if apocalypse_ready:
            for player in db.player_list():
                if db_get(player, 'role') == 'Horseman':
                    answer.log_add(recursive + next + failure)
                    answer.log_add(recursive + next + success +
                                   '<@{}> has joined the **Apocalypse**!')
                    db_set(player, 'horseman', 5)

                    answer.secret_dm(
                        'All Horsemen are united! This means that the **APOCALYPSE** can be unleashed!',
                        'Horseman')
            answer.story('Oh no! The Apocalypse has been unleashed!')
        return answer

    # End if user is frozen.
    if int(db_get(user_id, 'frozen')) == 1:
        return answer.log_add(
            recursive + success +
            '<@{}> was frozen and thus protected.'.format(user_id))

    if role == "Devil":
        if user_role == 'Devil':
            answer.log_add(recursive + success +
                           '<@{}> did not die to their own wage.')
            return answer
        answer.log_add(recursive + success + skull +
                       '<@{}> was killed by the wager.')
        answer = instant_death(user_id, role, 'Wager', answer,
                               recursive + next)
        return answer

    # Let all zombies kill all other zombies.
    if role == "Zombie":
        answer.log_add(recursive + success + skull +
                       '<@{}> has decayed.'.format(user_id))
        answer = instant_death(user_id, role, 'Zombie', answer,
                               recursive + next)
        return answer

    # Kill abducted players (or The Thing himself)
    if role == "The Thing":
        answer.log_add(recursive + success + skull +
                       '<@{}> drowned in the swamp.'.format(user_id))
        # TODO: kill the player (BUT NOT THROUGH THE SUICIDE FUNCTION)
        return answer

    # End if user is immortal.
    if user_role == "Immortal":
        answer.log_add(recursive + success +
                       '<@{}> is immortal.'.format(user_id))
        return answer

    # End if user is abducted.
    if int(db_get(user_id, 'abducted')) == 1:
        return answer.log_add(
            recursive + success +
            '<@{}> was abucted and thus protected.'.format(user_id))

    # Kill lynch!
    if role == "Innocent":
        replacements = [
            standoff for standoff in db.get_standoff(user_id)
            if standoff[2] == 'Executioner'
        ]

        if replacements == []:
            answer.log_add(recursive + success + skull +
                           '<@{}> was killed by an angry mob.'.format(user_id))
            answer = instant_death(user_id, role, 'Lynch', answer,
                                   recursive + next)

        else:
            answer.log_add(recursive + success +
                           '<@{}> escaped death as the Executioner.')

            if user_role == 'Executioner':
                db_set(user_id, 'role', 'Innocent')

            for standoff in replacements:
                db.delete_standoff(standoff[0])
                answer = instant_death(standoff[1], standoff[2], 'Lynch',
                                       answer, recursive + next)

        return answer

    # Kill whoever stands in the barber's way!
    if role == "Barber":
        if user_role != 'Idiot':
            answer.log_add(recursive + success + skull +
                           '<@{}> was cut to death.'.format(user_id))
            answer = instant_death(user_id, role, 'Barber', answer,
                                   recursive + next)
            answer.story(barber_kill_story(murderer, user_id))

        else:
            msg = "*\"Tomorrow, at noon, right here. You got that?\"* Yup, it definitely seemed like <@{}> ".format(
                user_id)
            msg += "remembered the barber\'s appointment.\nIt was only today that it turned out - they had forgotten "
            msg += "about it! Good thing for them, for <@{}> had the intent to cut a little far below the hairline...\n".format(
                murderer)
            msg += "**<@{0}>, the Barber, has failed to execute <@{1}>, the Idiot! <@{0}> will now continue the game ".format(
                murderer, user_id)
            msg += "as a regular Innocent, and <@{}> as an even better Idiot, as they are no longer allowed to vote.**".format(
                user_id)
            answer.story(msg).log_add(
                recursive + success +
                '<@{}> failed to give <@{}> a \"haircut\".'.format(
                    murderer, user_id))
            db_set(user_id, 'role', 'Idiot ')

        return answer

    # Save users if they have souls to spare.
    souls = int(db_get(user_id, 'souls'))
    if souls > 0:
        db_set(user_id, 'souls', souls - 1)
        answer.log_add(recursive + success +
                       '<@{}> lost a soul.'.format(user_id))
        return answer

    # End if the user sleeps with another.
    if role == "Hooker" and not demonized:
        answer.log_add(recursive + success + skull +
                       '<@{}> was slept with <@{}>.'.format(user_id, murderer))
        answer = instant_death(user_id, role, 'Hooker', answer,
                               recursive + next)
        return answer

    # End if player dies in someone else's place.
    if role == "Executioner":
        answer.log_add(recursive + success + skull +
                       '<@{}> was executed.'.format(user_id))
        answer = instant_death(user_id, role, 'Executioner', answer,
                               recursive + next)
        return answer

    # End if player dies in someone else's place.
    if role == "Huntress" and not demonized:
        answer.log_add(recursive + success + skull +
                       '<@{}> was shot.'.format(user_id))
        answer = instant_death(user_id, role, 'Huntress', answer,
                               recursive + next)
        return answer

    # Check if user has an amulet.
    if db.has_amulet(user_id) and role not in ['Hooker']:
        return answer.log_add(
            recursive + success +
            "<@{}> was protected by their amulet.".format(user_id))

    # Protect apocalypse horsemen
    if int(db_get(user_id, 'horseman')) == 5:
        return answer.log_add(
            '<@{}> was protected by the Apocalypse.'.format(user_id))

    # Kill assassinations
    if role == 'Assassin' and not demonized:
        answer.log_add(recursive + success + skull +
                       '<@{}> was assassinated.'.format(user_id))
        answer = instant_death(user_id, role, 'Assassin', answer,
                               recursive + next)
        return answer
    if role == 'Cult Leader' and not demonized:
        answer.log_add(recursive + success + skull +
                       '<@{}> was killed by the cult.'.format(user_id))
        answer = instant_death(user_id, role, 'Cult', answer, recursive + next)
        return answer
    if role == 'Priest' and not demonized:
        if user_role in pos.wolf_team:
            answer.log_add(recursive + success + skull +
                           '<@{}> was holified.'.format(user_id))
            answer = instant_death(user_id, role, 'Priest', answer,
                                   recursive + next)
        else:
            answer.log_add(recursive + success + skull +
                           '<@{}> holified themselves.'.format(murderer))
            answer = instant_death(user_id, role, 'Priest', answer,
                                   recursive + next)
        return answer
    if role == 'Witch' and not demonized:
        answer.log_add(recursive + success + skull +
                       '<@{}> was poisoned.'.format(user_id))
        answer = instant_death(user_id, role, 'Witch', answer,
                               recursive + next)
        return answer

    # Kill wolf attacked
    if role in ['Werewolf', 'Lone Wolf', 'White Werewolf']:
        if user_role == 'Runner':
            answer.log_add(recursive + success +
                           '<@{}> outran a wolf attack.'.format(user_id))
            answer.dm('You. Are. EXHAUSTED.\n', user_id)
            answer.dm_add(
                'Last night may have been the worst night of your life! ')
            answer.dm_add(
                'You\'re still alive, however. And that\'s what counts. ')
            answer.dm_add(
                'Let\'s hope that, whatever those creatures were, won\'t attack again tomorrow night!\n'
            )
            answer.dm_add(
                '**Last night, you have been attacked by a wolf. You have become a regular Innocent.**'
            )
            db_set(user_id, 'role', 'Innocent')
            return answer
        if user_role == 'Cursed Civilian':
            answer.dm(
                "The curse that went around you, had been a little itchy lately... and it kept getting worse! ",
                user_id)
            answer.dm_add(
                "It got worse and worse, and you couldn't help but notice how hair started growing everywhere!\n"
            )
            answer.dm_add(
                "Last night, you were waking up by the grunts of a what sounded like a wolf! "
            )
            answer.dm_add(
                "You thought your days were over, but the wolf did not attack. Instead, "
            )
            answer.dm_add(
                "the wolf watched as your nails grew longer, your ears became spiky and your smell "
            )
            answer.dm_add(
                "slowly improved... and you looked just like one of the silhouettes in the shadow, "
            )
            answer.dm_add(
                "waiting for you to join them in the beautiful night's sky...\n"
            )
            answer.dm_add(
                "**You have been visited by wolves last night, and your curse made you turn "
            )
            answer.dm_add(
                "into a werewolf. Devour all villagers and win the game!**")

            db_set(user_id, 'role', 'Werewolf')
            answer.log_add(recursive + success +
                           '<@{}> has turned into a Werewolf!'.format(user_id))

            for channel_id in db.get_secret_channels('Werewolf'):
                answer.edit_cc(channel_id, user_id, 1)
                answer.msg("**ARRROOOO!\nWelcome, <@{}>!**".format(user_id),
                           channel_id)
                answer.msg_add(
                    "Last night, the **cursed civilian** <@{}> was attacked by wolves, "
                    .format(user_id))
                answer.msg_add(
                    "and has now become a **werewolf**! Please, welcome this new member "
                )
                answer.msg_add("of the wolf pack!")
            return answer
        if not demonized:
            answer.log_add(recursive + success + skull +
                           '<@{}> was eaten by a werewolf.'.format(user_id))
            answer = instant_death(user_id, role, 'Werewolf', answer,
                                   recursive + next)
            return answer

    # Kill solo attacked
    if role == 'Demon' and not demonized:
        answer.log_add(recursive + success + skull +
                       '<@{}> was sent to hell.'.format(user_id))
        answer = instant_death(user_id, role, 'Demon', answer,
                               recursive + next)
        return answer
    if role == 'Horseman' and not demonized:
        answer.log_add(recursive + success + skull +
                       '<@{}> was apocalypsed.'.format(user_id))
        answer = instant_death(user_id, role, 'Horseman', answer,
                               recursive + next)
        return answer
    if role == 'Pyromancer' and not demonized:
        answer.log_add(recursive + success + skull +
                       '<@{}> went up in flames.'.format(user_id))
        answer = instant_death(user_id, role, 'Pyromancer', answer,
                               recursive + next)
        return answer

    # Assume they were supposed to be killed, but that they are demonized. Let's turn them undead!
    answer.log_add(recursive + success + skull + '<@{}> has become undead.')

    db_set(user_id, 'undead', 1)
    answer.dm(
        "Last night, you didn't feel to well and decided to go out, to take a walk. ",
        user_id)
    answer.dm_add(
        "As soon as you stepped out the door, you felt like it was a bad idea - and it was!\n"
    )
    answer.dm_add(
        "The last thing you can remember is the sound of someone approaching you from behind, "
    )
    answer.dm_add(
        "the sound of a skull cracking open, and then - **NOTHING**.\n\n")
    answer.dm_add("Is this the end?\n\n")
    answer.dm_add(
        "It doesn't appear so. You wake up in a graveyard. A few cold and grim silhouettes "
    )
    answer.dm_add(
        "stand in front of you. You are surrounded, but it feels more... welcoming. "
    )
    answer.dm_add("And then the truth arrives.\n")
    answer.dm_add(
        "The **{}** you once were, is dead. Their soul could not rest, and that is you. "
    )
    answer.dm_add("The remainders of something that wasn't ready to die.\n")
    answer.dm_add(
        "**You have become Undead. Murder everyone that isn't an undead or a vampire."
    )

    for channel_id in db.get_secret_channels('Undead'):
        answer.edit_cc(channel_id, user_id, 1)
        answer.msg(
            "Last night, <@{}>, a **{}** has died! Please welcome them in the realm of the Undead!",
            channel_id)

    if user_role not in pos.pretenders:
        db_set(user_id, 'role', 'Undead')
        answer.dm_add("**")
    else:
        answer.dm_add(
            " Your former teammates do not know you are Undead, so make use of this advantage.**"
        )

    return answer
Пример #13
0
async def check_time():
    print('   | > Waiting for client to be ready')
    await client.wait_until_ready()
    print('   | > Event loop triggered')
    await asyncio.sleep(1)

    while True:
        time = datetime.datetime.now()
        current_hour = str(time.hour - 1)

        # Give the hour signal
        if str(time.hour) != current_hour:
            print("--> We've reached the hour! It's now %s00 hours." %
                  (time.hour))
            current_hour = str(time.hour)

            # Set each user's activity one up.
            for user in db.player_list():
                activity = db.db_get(user, 'activity')
                db.db_set(user, 'activity', activity + 1)

                if db.isParticipant(user):
                    if activity_hours - activity == 24:
                        await client.get_channel(bot_spam).send(
                            prefix + "warn <@{}>".format(user))
                    elif activity >= activity_hours:
                        await client.get_channel(bot_spam).send(
                            prefix + "idle <@{}>".format(user))

            # Set each shop's age one up.
            age_shop()

            # Purge activity
            purge_activity()

            # Give free credits in the middle of the night.
            if str(time.hour) == "0":
                await client.get_channel(welcome_channel).send(
                    'Gonna send some credits! Get ready!')
                deal_credits()

            # Give the day signal
            if str(time.hour) == "8":
                if dy.get_stage() != "NA":
                    print('Another day has started!')
                    await client.get_channel(bot_spam).send(prefix + "pay")
                else:
                    await client.get_channel(bot_spam).send(
                        "Beep boop! Another day has begun!")

            # Give the night signal
            if str(time.hour) == "21":
                if dy.get_stage() != "NA":
                    print('Another night has begun!')
                    await client.get_channel(bot_spam).send(prefix + "pight")
                else:
                    await client.get_channel(bot_spam).send(
                        "Beep boop! The night has started!")

            # Make a backup of the database
            newpath = 'backup/{}_{}/{}_{}h/'.format(time.year, time.month,
                                                    time.day, time.hour)
            if not os.path.exists(newpath):
                os.makedirs(newpath)
            open(
                'backup/{}_{}/{}_{}h/{}_backup_game.db'.format(
                    time.year, time.month, time.day, time.hour, time.minute),
                'a').close()
            open(
                'backup/{}_{}/{}_{}h/{}_backup_general.db'.format(
                    time.year, time.month, time.day, time.hour, time.minute),
                'a').close()
            open(
                'backup/{}_{}/{}_{}h/{}_backup_stats.json'.format(
                    time.year, time.month, time.day, time.hour, time.minute),
                'a').close()
            open(
                'backup/{}_{}/{}_{}h/{}_backup_dynamic.json'.format(
                    time.year, time.month, time.day, time.hour, time.minute),
                'a').close()
            open(
                'backup/{}_{}/{}_{}h/{}_backup_config.py'.format(
                    time.year, time.month, time.day, time.hour, time.minute),
                'a').close()
            copy(
                config.database,
                'backup/{}_{}/{}_{}h/{}_backup_game.db'.format(
                    time.year, time.month, time.day, time.hour, time.minute))
            copy(
                config.general_database,
                'backup/{}_{}/{}_{}h/{}_backup_general.db'.format(
                    time.year, time.month, time.day, time.hour, time.minute))
            copy(
                config.stats_file,
                'backup/{}_{}/{}_{}h/{}_backup_stats.json'.format(
                    time.year, time.month, time.day, time.hour, time.minute))
            copy(
                config.dynamic_config,
                'backup/{}_{}/{}_{}h/{}_backup_dynamic.json'.format(
                    time.year, time.month, time.day, time.hour, time.minute))
            copy(
                'config.py', 'backup/{}_{}/{}_{}h/{}_backup_config.py'.format(
                    time.year, time.month, time.day, time.hour, time.minute))

            await asyncio.sleep(75)

        await asyncio.sleep(10)
Пример #14
0
def devil_victory():
    for user in db.player_list():
        if db.isParticipant(user) and db.db_get(user,'role') not in ['Devil','Demon']:
            if db.db_get(user,'souls') < 0:
                return False
    return True
Пример #15
0
def wolf_victory():
    """This function returns true if the wolves' win condition has been met."""
    for user in db.player_list():
        if db.isParticipant(user) and user not in wolf_team:
            return False
    return True
Пример #16
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.author.roles]:
            isGameMaster = True

    result = process(message, isGameMaster)

    temp_msg = []

    for mailbox in result:

        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:
                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?)

            # TODO
            pass

        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 = []
                abductees = []
                for member in db.player_list():
                    if db_get(member,
                              'abducted') == 1 and member in element.members:
                        abductees.append(member)
                    elif member in element.members or db_get(
                            member, 'role') in [
                                'Dead', 'Spectator'
                            ] or int(member) == int(element.owner):
                        if main_guild.get_member(int(member)) != None:
                            viewers.append(main_guild.get_member(int(member)))
                        else:
                            sorry = await message.channel.send(
                                "It doesn't seem like <@{}> is part of this server! I am sorry, I can't add them to your channel."
                                .format(member))
                            temp_msg.append(sorry)

                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)
                dead_participant_role = discord.utils.find(
                    lambda r: r.id == dead_participant, roles)
                frozen_participant_role = discord.utils.find(
                    lambda r: r.id == frozen_participant, roles)
                default_permissions = {
                    main_guild.default_role:
                    discord.PermissionOverwrite(read_messages=False),
                    frozen_participant_role:
                    discord.PermissionOverwrite(send_messages=False),
                    dead_participant_role:
                    discord.PermissionOverwrite(read_messages=True,
                                                send_messages=False),
                    game_master_role:
                    discord.PermissionOverwrite(read_messages=True),
                    client.user:
                    discord.PermissionOverwrite(read_messages=True,
                                                send_messages=True),
                    **{
                        member: discord.PermissionOverwrite(read_messages=True)
                        for member in viewers
                    },
                }

                # 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 victim in abductees:
                        db.set_user_in_channel(channel.id, victim, 3)
                    for user in viewers:
                        if db_get(user.id, 'role') in ['Dead', 'Spectator']:
                            db.set_user_in_channel(channel.id, user.id, 4)
                        elif db_get(user.id, 'frozen') == 1:
                            db.set_user_in_channel(channel.id, user.id, 2)
                        else:
                            db.set_user_in_channel(channel.id, user.id, 1)

                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)

    # Delete all temporary messages after "five" seconds.
    await asyncio.sleep(5)
    for msg in temp_msg:
        await msg.delete()
Пример #17
0
def ice_victory():
    """This function returns true if the ice kings have won."""
    for user in db.player_list():
        if db.isParticipant(user) and db.db_get(user,'frozen') == 0 and db.db_get(user,'role') != 'Ice King':
            return False
    return True