Beispiel #1
0
async def main(client, message, params):
    roles = cfg.options["roles_show"]
    info = InfoEmbed(title="Roles")
    desc = 'This server has ' + str(
        client.get_guild(message.guild.id).member_count) + ' members.\n\n'
    for r in roles:
        role = get(message.guild.roles, name=r)
        desc += role.name + ': ' + str(len(role.members)) + '.\n'
    info.description = desc
    await message.channel.send(embed=info)
Beispiel #2
0
def survey_help_embed():
    embed = InfoEmbed(title='Hilfe - BundestagsBot v1')
    embed.set_thumbnail(
        url=
        'https://cdn0.iconfinder.com/data/icons/handdrawn-ui-elements/512/Question_Mark-512.png'
    )

    embed.description = '>survey Titel; Beschreibung; <Anzahl>\n\n'\
                        'Anzahl ist optional und beschreibt die Anzahl an Reactionmöglichkeiten.\n\n'\
                        'So erzeugt >survey; Titel; Beschreibung; 5 eine Umfrage mit 5 Antwortmöglichkeiten, die du\n'\
                        'dann in deiner Beschreibung erklären musst.\n'\
                        'Mit "|" erzeugst du eine neue Zeile in deiner Beschreibung.\n'\
                        '**Beachte bitte die Trennung der Argumente via Semikolon!**'
    return embed
Beispiel #3
0
async def end_poll(args):
    client = args[0]
    data = handleJson.read_json_raw(path)
    if data["arena_status"] == "poll":
        SHL.output("Ended poll")
        channel = client.get_channel(cfg.options["channel_ids"]["arena"])
        results = [0] * data["participant_count"]
        emojis = ['1⃣', '2⃣', '3⃣', '4⃣']

        msg = await channel.fetch_message(data["last_poll_msg"])
        reactions = msg.reactions
        for reaction in reactions:
            if str(reaction) in emojis:
                results[emojis.index(str(reaction))] = reaction.count
        max_votes = max(results)
        embed = SuccessEmbed(title="Arena")
        embed.description = f"{data['participants_name'][results.index(max_votes)]} won."
        if results.count(max_votes) > 1:
            all_max = [e for e, i in enumerate(results) if i == max_votes]
            embed.description = ", ".join([data["participants_name"][x] for x in all_max]) + \
                                f" won with {max_votes} votes."
        # TODO: reputation system?

        await channel.send(embed=embed)
        info = InfoEmbed(title="Arena - Results",
                         description=f'We got a winner! Be sure to check <#{cfg.options["channel_ids"]["arena"]}>')
        for m in data["participants"]:
            try:
                member = channel.guild.get_member(m)
                await member.send(embed=info)
            except:
                pass

        data["arena_status"] = "wait_topic"
        handleJson.saveasjson(path, data)
Beispiel #4
0
async def main(client, message, params):
    to_warn = message.mentions
    if not to_warn:
        except_embed = WarningEmbed(title="No users supplied",
                                   description=f"Usage: {cfg.options.get('invoke_normal')}warn @user")
        await message.channel.send(embed=except_embed)

    for user in to_warn:
        warned = get(message.guild.roles, id=cfg.options.get("warn_role_id", 0)) in user.roles
        if not warned:
            try:
                warn_role = get(message.guild.roles, id=cfg.options.get("warn_role_id", 0))
                await user.add_roles(warn_role)
            except HTTPException:
                if cfg.options.get("warn_role_id", 0):
                    except_embed = WarningEmbed(title="Role-assigment failed",
                                                description=f"Failed to assign role {cfg.options.get('warn_role_id', 0)}!")
                else:
                    except_embed = WarningEmbed(title="Role-assigment failed",
                                                description=f"No 'warn_role_id' defined!")
                await message.channel.send(embed=except_embed)
                return
            return_embed = SuccessEmbed(title="Warn", description=f"Warned {user.display_name}")
            try:
                pm_embed = InfoEmbed(title="Warn",
                                         description=f"You were warned by {message.author.display_name}\n"
                                                     f"Please read our server rules.\n"
                                                     f"If you do not understand this message, please ask a moderator.")
                await user.send(embed=pm_embed)
            except HTTPException:  # if users privacy settings do not allow dm
                pass
            await message.channel.send(embed=return_embed)
        else:
            warned_embed = NoticeEmbed(title="Warn", description=f"User {user.display_name} has already been warned once!")
            await message.channel.send(embed=warned_embed)
Beispiel #5
0
async def main(client, message, params):
    try:
        last_id = save_json(message)
    except:
        SHL.output(f"Something went wrong while handling a submit.")
        error = WarningEmbed(
            title="Submit",
            description="Something went wrong. Please contact an admin.")
        await message.channel.send(embed=error)
        return

    if not cfg.options["channel_ids"].get("suggestions", 0):
        error = WarningEmbed(
            title="Submit",
            description=
            "Your submit got saved. But could not be send.\nPlease contact an admin."
        )
        await message.channel.send(embed=error)
    else:
        embed = InfoEmbed(title=f"Submit #{last_id}",
                          description=' '.join(params))
        channel = get(client.get_all_channels(),
                      id=cfg.options["channel_ids"]["submits"])
        await channel.send(embed=embed)
        return_embed = SuccessEmbed(
            title=f"Submit #{last_id}",
            description="Thank your for your submission.\n"
            "If a team member answers it, I will forward the message :)")
        await message.channel.send(embed=return_embed)
Beispiel #6
0
async def on_message(message: discord.Message):
    if not await check_message(
            client, message
    ):  # check basic conditions like length and not responding to himself
        return

    if message.channel.id in cfg.get("channel_ids",
                                     dict()).get("suggestions", []):
        await message.delete()
        info = InfoEmbed(f"Suggestion by {message.author.display_name}")
        info.description = message.content
        info.set_author(name=message.author.display_name,
                        icon_url=message.author.avatar_url_as(format="webp"))
        info.set_footer(text=f"UserID: {message.author.id}")
        new_message = await message.channel.send(embed=info)
        await new_message.add_reaction('👍')
        await new_message.add_reaction('👎')
        return

    if message.content.lower().startswith(
            str(cfg.options["invoke_normal"]).lower()):
        params = commands.parse(message.content, False)
        if params:
            if params[0].lower() in commands.commands.keys():
                await commands.commands[params[0].lower()](client, message,
                                                           params[1:])

    elif message.content.lower().startswith(
            str(cfg.options["invoke_mod"]).lower()):
        params = commands.parse(message.content, True)
        if params:
            if params[0].lower() in commands.mod_commands.keys():
                await commands.mod_commands[params[0].lower()](client, message,
                                                               params[1:])
Beispiel #7
0
async def main(client, message, params):
    error = NoticeEmbed(title="Resolve")
    info = InfoEmbed(title="Resolve")
    if len(str(message.content).split(' ')) == 2:
        submit_id = params[0][1:]
        if submit_id.isdigit():
            data = handleJson.read_json_raw(path)
            if submit_id in data.keys():
                info.description = f"Anfrage #{submit_id} ist von:\n" \
                                   f"{data[submit_id]['author']}\n" \
                                   f"{data[submit_id]['authorID']}"
                await message.channel.send(embed=info)
            else:
                error.description = f"#{submit_id} could not be assigned to a submit."
                await message.channel.send(embed=error)
        else:
            error.description = f"{submit_id} is an invalid ID."
            await message.channel.send(embed=error)
    else:
        error.description = f"Invalid syntax.\nPlease use {cfg.options['invoke_mod']}resolve #id"
        await message.channel.send(embed=error)
async def reaction_add(client, payload):
    if payload.channel_id == cfg.options["channel_ids"]["roles"]:
        if str(payload.emoji.id) in cfg.options["roles"].keys():
            role = get(client.get_guild(payload.guild_id).roles, name=cfg.options["roles"][str(payload.emoji.id)])
            user = client.get_guild(payload.guild_id).get_member(payload.user_id)
            if role not in user.roles:
                await user.add_roles(role)
                try:
                    info_embed = InfoEmbed(title=role.name, description=f"Assigned role {role.name}")
                    await user.send(embed=info_embed)
                except:  # if users privacy settings do not allow dm
                    pass
Beispiel #9
0
async def end_discussion(args):
    client = args[0]
    data = handleJson.read_json_raw(path)
    if data["arena_status"] == "running":
        SHL.output("Ended discussion")
        SHL.output("Started poll")
        channel = client.get_channel(cfg.options["channel_ids"]["arena"])
        role = get(channel.guild.roles, id=cfg.options["arena_role"])
        embed = InfoEmbed(title="Arena - End",
                          description="Arena stopped. Thank you for your participation")
        for m in data["participants"]:
            try:
                member = channel.guild.get_member(m)
                await member.remove_roles(role)
                await member.send(embed=embed)
            except:
                pass

        embed = SuccessEmbed(title="Arena - End")
        if len(data["participants"]) == 2:
            embed.description = "Ended discussion.\n Please vote for:\n"\
                                f"1⃣  {data['participants_name'][0]}\n" \
                                f"2⃣  {data['participants_name'][1]}\n"
            emojis = ['1⃣', '2⃣']
        elif len(data["participants"]) == 4:
            embed.description = "Ended discussion.\n Please vote for:\n" \
                                f"1⃣  {data['participants_name'][0]}\n" \
                                f"2⃣  {data['participants_name'][1]}\n" \
                                f"3⃣  {data['participants_name'][2]}\n" \
                                f"4⃣  {data['participants_name'][3]}\n"
            emojis = ['1⃣', '2⃣', '3⃣', '4⃣']
        close = await channel.send(embed=embed)
        data["last_poll_msg"] = close.id
        for e in emojis:
            await close.add_reaction(e)

        data["arena_status"] = "poll"
        handleJson.saveasjson(path, data)
Beispiel #10
0
async def announce_topic(args):
    client = args[0]
    data = handleJson.read_json_raw(path)
    if data["arena_status"] == "wait_topic" and cfg.options.get("enable_arena", False) and data["topics"]:
        SHL.output("Announced topic")
        SHL.output("Started queue")

        channel = client.get_channel(cfg.options["channel_ids"]["arena"])
        topic = data['topics'].pop(0)
        info = InfoEmbed(title="Arena - Topic",
                         description=f"Next topic will be:\n{topic}\n\n"
                                     f"Use {cfg.options['invoke_normal']}queue to enter the queue.")
        await channel.send(embed=info)
        await channel.edit(topic="test1")

        data["arena_status"] = "wait_queue"
        handleJson.saveasjson(path, data)
Beispiel #11
0
async def start_discussion(args):
    client = args[0]
    data = handleJson.read_json_raw(path)
    if data["arena_status"] == "wait_start":
        SHL.output("Started discussion")
        channel = client.get_channel(cfg.options["channel_ids"]["arena"])

        role = get(channel.guild.roles, id=cfg.options["arena_role"])
        embed = InfoEmbed(title="Arena",
                          description="Arena started. Be sure to participate in the discussion!")
        for m in data["participants"]:
            member = channel.guild.get_member(m)
            await member.add_roles(role)
            await member.send(embed=embed)

        data["arena_status"] = "running"
        handleJson.saveasjson(path, data)
Beispiel #12
0
async def announce_participant(args):
    client = args[0]
    data = handleJson.read_json_raw(path)
    if data["arena_status"] == "wait_queue":
        SHL.output("Announced participant")
        channel = client.get_channel(cfg.options["channel_ids"]["arena"])

        embed = InfoEmbed(title="Arena - Participation",
                          description="You are participating in the next discussion!")
        count = 0
        data["participants"] = []
        data["participants_name"] = []
        shuffle(data["queue"])
        for m in set(data["queue"]):
            if count >= data["participant_count"]:
                break
            try:
                member = channel.guild.get_member(m)
                await member.send(embed=embed)
                count += 1
                data["participants"].append(member.id)
                data["participants_name"].append(member.display_name)
            except:  # not a valid participant as he declined dm
                continue

        if len(data["participants"]) < data["participant_count"]:
            error = NoticeEmbed(title="Arena - Queue",
                                description="Could not find enough members in queue.")
            channel.send(error)
            return
        data["queue"] = []
        embed = SuccessEmbed(title="Arena - Participants",
                             description="Participants:\n" + ",\n".join(data["participants_name"]) +
                                         "\n\nStart: Saturday 17:00")
        await channel.send(embed=embed)

        data["arena_status"] = "wait_start"
        handleJson.saveasjson(path, data)
async def main(client, message, params):
    if not len(message.mentions):
        embed = NoticeEmbed(title="Reactions", description=message.author.mention + 'Bitte einen Nutzer angeben')
        await message.channel.send(embed=embed)
        return

    data = DB.get_specific_user(message.mentions[0].id)
    if data:
        header = 'Reaktionen zu Nachrichten von ' + message.mentions[0].display_name + '\n'
        content = ''
        # skip name and id
        for i, role in enumerate(cfg.options["roles_stats"].items(), 1):
            if data[i] > 0:
                emoji_id = role[0]
                emoji_obj = await message.guild.fetch_emoji(emoji_id)
                emoji_str = "<:" + emoji_obj.name + ":" + emoji_id + ">"
                content += "" + emoji_str + ": " + str(data[i]) + "\n"
        embed = InfoEmbed(title=header, description=content)
        await message.channel.send(embed=embed)
    else:
        embed = NoticeEmbed(title="Reactions",
                            description=message.author.mention + 'Dieser Benutzer hat noch keine Reaktionen erhalten.')
        await message.channel.send(embed=embed)
Beispiel #14
0
async def main(client, message, params):
    try:
        target_channel = message.channel_mentions[0]
        text = " ".join(params[1:])
    except IndexError:
        embed = ErrorEmbed(
            "Post", description="Syntax error\nUse `+post <#channel_id> text`")
        await message.channel.send(embed=embed)
        return

    embed = InfoEmbed(title="Moderation",
                      description=f"{text}\n\n{suffix_text}")
    msg = await message.channel.send(
        content=f"Message will be sent to {target_channel.mention}",
        embed=embed)
    await msg.add_reaction('✅')
    await msg.add_reaction('❌')

    def reaction_check(reaction, user):
        e = str(reaction.emoji)
        return user == message.author and e.startswith(
            ('✅', '❌')) and reaction.message.id == msg.id

    reaction, user = await client.wait_for('reaction_add',
                                           timeout=180.0,
                                           check=reaction_check)

    if not str(reaction.emoji).startswith('✅'):
        return

    try:
        await target_channel.send(embed=embed)
    except:
        embed = ErrorEmbed(
            "Post",
            description="Error while sending message to target channel.")
        await message.channel.send(embed=embed)
Beispiel #15
0
def help_embed():
    embed = InfoEmbed(title='Hilfe - BundestagsBot v1')
    embed.set_thumbnail(
        url=
        'https://cdn0.iconfinder.com/data/icons/handdrawn-ui-elements/512/Question_Mark-512.png'
    )
    embed.description = '-Benutze >survey Titel; Beschreibung; <Anzahl>\n' \
                        'um eine Umfrage zu erstellen. >help survey für mehr Details\n\n'\
                        '-Benutze >iam [Politik] um dir diese Rolle zuzuweisen.\n\n'\
                        '-Benutze >roles für eine Übersicht der Rollenverteilung.\n\n'\
                        '-Benutze >answer #id answer um auf eine Umfrage zu antworten.\n\n' \
                        '-Benutze >result #id um Ergebnisse einer Umfrage einzusehen.\n\n' \
                        '-Benutze >sub False um keine weiteren Umfragen mehr zu erhalten.\n\n' \
                        '-Benutze >submit Text um Anfragen ans Serverteam zu stellen.\n\n' \
                        '-Benutze >umfrage [Parlamentsnummer]\nKeine Nummer für Bundestag'\

    embed.add_field(
        name='Liste:',
        value=
        '0: Bundestag\n1: Baden-Württemberg\n2: Bayern\n3: Berlin\n4: Brandeburg\n5: Bremen\n'
        '6: Hamburg\n7: Hessen\n8: Mecklenburg-Vorpommern\n9: Niedersachsen\n10: NRW\n'
        '11: Rheinland-Pfalz\n12: Saarland\n13: Sachsen\n14: Sachsen-Anhalt\n'
        '15: Schleswig-Holstein\n16: Thüringen\n17: Europäisches Parlament')
    return embed
Beispiel #16
0
from bt_utils.get_content import content_dir
from bt_utils.embed_templates import InfoEmbed, SuccessEmbed

SHL = Console("BundestagsBot Analyze"
              )  # Use SHL.output(text) for all console based output!

settings = {
    'name': 'analyze',  # name/invoke of your command
    'mod_cmd':
    False,  # if this cmd is only useable for users with the teamrole
    'channels':
    ['all'],  # allowed channels: [dm, bot, team, all]; use !dm to blacklist dm
    'log': True,  # if this cmd should be logged to the console, default: True
}

about_embed = InfoEmbed(title="Help")
with open(os.path.join("static", "info.txt"), "r", encoding="utf-8") as fh:
    about_embed.description = fh.read()


async def main(client, message, params):
    if any([
            x in message.content.lower()
            for x in ["help", "info", "details", "about"]
    ]):
        await message.channel.send(embed=about_embed)
        return

    if "true" in message.content.lower():
        with open(os.path.join(content_dir, "unsubs.json"), "r") as fh:
            data = json.load(fh)
Beispiel #17
0
async def main(client, message, params):
    if __msg is not None:
        embed = InfoEmbed(title="Version", description=__msg)
    else:
        embed = ErrorEmbed(title="Version", description="Error fetching version.")
    await message.channel.send(embed=embed)
Beispiel #18
0
def create_embed(survey_id):
    try:
        data = handleJson.read_json_raw(path)
    except FileNotFoundError:
        SHL.output('Survey file not found. Creating it.')
        file_dir = os.path.join(handleJson.BASE_PATH, os.path.dirname(path))
        if not os.path.exists(file_dir):
            os.makedirs(file_dir)
        handleJson.saveasjson(path, {})
        data = handleJson.read_json_raw(path)

    title = data[survey_id]['title']
    text = data[survey_id]['text']
    author = data[survey_id]['author']
    url = data[survey_id]['url']
    votes = len(data[survey_id]['voted'])
    answers = data[survey_id]['answers']
    results = data[survey_id]['results']
    answers_text = []

    for e in sorted(results, key=lambda x: results[x])[::-1]:
        if sum(results.values()):
            answer_pct = round(results[e] * 100 / sum(results.values()), 1)
            answer_pct = str(answer_pct).replace(".", ",")
        else:
            answer_pct = "0"
        answers_text.append(f'{answer_pct}% ({results[e]}): {answers[e]}')
    answers_text = '\n'.join(answers_text)

    embed = InfoEmbed(title='Umfrage #' + str(survey_id) + ': ' + title)
    embed.url = url
    embed.add_field(name='Frage:', value=text, inline=False)
    embed.add_field(
        name='Information:',
        value=
        f'Diskutiere über diese Umfrage in <#{cfg.get("channel_ids", dict()).get("main", 0)}>.',
        inline=False)
    embed.add_field(name='Ergebnis:', value=answers_text)
    embed.add_field(name='Beteiligung: ',
                    value='Insgesamt abgestimmt haben: ' + str(votes))
    embed.set_footer(text='Umfrage von ' + author)

    return embed
async def assign_active_member(*args):
    SHL.info("Fetching last messages.")
    client = args[0]
    guild = await client.fetch_guild(cfg.get("guild_id"))
    SHL.debug(f"Guild: {guild}")

    # Remove all "active" members
    SHL.info("Remove active role from all users.")
    for role in cfg.get("apply_roles"):
        role = guild.get_role(role)
        async for member in guild.fetch_members():
            if role not in member.roles:
                continue
            SHL.debug(f"Remove {role} from {member}")
            try:
                await member.remove_roles(role)
            except:
                SHL.debug(f"Failed for {member}")

    # Find new active members
    channels = await guild.fetch_channels()

    announcement_channel = await client.fetch_channel(cfg.get("announce_channel"))
    log_channel = await client.fetch_channel(cfg.get("log_channel"))

    users = {}
    before = datetime.now()
    after = datetime.now() - timedelta(days=31)

    with open(os.path.join(content_dir, "unsubs.json"), "r") as fh:
        unsubs = json.load(fh)["unsub_ids"]

    SHL.debug(f"{len(unsubs)} users unsubbed.")

    for channel in channels:
        if not isinstance(channel, discord.TextChannel):
            continue
        if channel.id in cfg.get("exclude_channels"):
            continue

        SHL.debug(f"Fetching {channel.name}")
        async for message in channel.history(limit=None, before=before, after=after):
            uid = message.author.id
            if uid in unsubs:  # filter opt-out user
                continue
            if uid in users:
                users[uid].count += 1
            else:
                users[uid] = UserStat(message.author)

    sorted_list = sorted([x for x in users.values() if x.count >= cfg.get("needed_messages")],
                         key=lambda item: item.count, reverse=True)
    SHL.debug(f"{len(sorted_list)} users sent enough messages.")

    log_embed = InfoEmbed(title="Aktivste User", description="Für die Auswahl der Stammmitglieder.\n"
                                                             "Anzahl an Nachrichten in den letzten 31 Tagen.\n")
    for stat in sorted_list:  # active user
        try:
            member = await guild.fetch_member(stat.user_obj.id)
        except:  # if user left or got banned
            continue
        SHL.debug(f"Apply roles for {member}")
        log_embed.description += f"{member.mention}  {stat.count} Nachrichten.\n"
        for role in cfg.get("apply_roles"):
            assign_role = get(guild.roles, id=role)
            try:
                await member.add_roles(assign_role)
            except:
                SHL.debug(f"Failed for {stat.user_obj}")
                break

    await log_channel.send(embed=log_embed)
    await announcement_channel.send(embed=log_embed)
    SHL.info("Done.")
async def main(client, message, params):
    data = handleJson.read_json_raw(path)

    if not len(message.mentions):
        error = NoticeEmbed(title="Challenge",
                            description="Please mention someone.")
        await message.channel.send(embed=error)
        return

    if message.mentions[0].id == message.author.id:
        error = NoticeEmbed(title="Challenge",
                            description="You cannot challenge yourself.")
        await message.channel.send(embed=error)
        return

    if data["arena_status"]:
        notice = NoticeEmbed(title="Challenge", description="There is already a discussion running!")
        await message.channel.send(embed=notice)
        return

    data["participants"] = []
    try:
        participants = message.mentions
        challenge = InfoEmbed(title="Challenge",
                              description=f"Hey {participants[0].mention}"
                                          f"\n{message.author.mention} challenged you!")
        msg = await message.channel.send(embed=challenge)
    except:
        error = NoticeEmbed(title="Challenge",
                            description="Something went wrong. Please contact an admin.")
        await message.channel.send(embed=error)
        return

    await msg.add_reaction('✅')
    await msg.add_reaction('❌')

    def check(reaction, user):
        e = str(reaction.emoji)
        return user == participants[0] and e.startswith(('✅', '❌')) and reaction.message.id == msg.id

    try:
        reaction, user = await client.wait_for('reaction_add', timeout=30.0, check=check)
    except TimeoutError:
        return

    if str(reaction.emoji).startswith('❌'): return

    data["arena_status"] = 1
    try:
        info = InfoEmbed(title="Challenge",
                         description=f"{participants[0].display_name} accepted your challenge!\n" +
                                     f'Discuss here: <#{cfg.options["channel_ids"]["1v1"]}>\n'
                                     f"Channel will be closed in {cfg.options['1v1_time_minutes']} minutes.")
        await message.author.send(embed=info)
    except:
        pass
    try:
        info = InfoEmbed(title="Challenge",
                         description=f"You accepted {message.author.mention}s challenge.!\n" +
                                     f'Discuss here: <#{cfg.options["channel_ids"]["1v1"]}>\n'
                                     f"Channel will be closed in {cfg.options['1v1_time_minutes']} minutes.")
        await participants[0].send(embed=info)
    except:
        pass

    SHL.output(f"{participants[0].display_name} accepted {message.author.display_name}s challenge!")
    channel = client.get_channel(cfg.options["channel_ids"]["1v1"])
    role = get(channel.guild.roles, id=cfg.options["1v1_role"])

    await message.author.add_roles(role)
    await participants[0].add_roles(role)
    announce = SuccessEmbed(title="Challenge",
                            description="Discussion duel started!\n"
                                        f"Battle between {message.author.mention} - {message.mentions[0].mention}\n"
                                        f"Channel will be closed in {cfg.options['1v1_time_minutes']} minutes.")
    await channel.send(embed=announce)

    data["participants"] = [message.author.id, participants[0].id]
    handleJson.saveasjson(path, data)

    await channel.edit(topic=f"Battle between: {message.author.mention} - {message.mentions[0].mention}")
    schedule_job(close_channel, cfg.options["1v1_time_minutes"], "challenge", client)
Beispiel #21
0
def create_embed(submit_id, author, params):
    info = InfoEmbed(title=f"Answer Submit #{submit_id}")
    info.description = ' '.join(params[1:]).strip()
    info.set_footer(text=f'Answer by {author}')
    return info