So, I have a discord information bot I am working on and this is one of the commands.
@client.command()
async def rd(ctx):
embed = discord.Embed(title="**[R&D Cost at every level]:**")
embed.add_field(name="**Level//All Units ATK Bonus//March Size Increase//R&D Cost**", value= "|", inline=False)
embed.add_field(name="6 0.6% 0 10", value='.', inline=False)
embed.add_field(name="7 0.7% 0 20", value='.', inline=False)
embed.add_field(name="8 0.8% 0 30", value='.', inline=False)
embed.add_field(name="9 0.9% 0 35", value='.', inline=False)
embed.add_field(name="10 1.0% 0 40", value='.', inline=False)
embed.add_field(name="11 1.2% 0 45", value='.', inline=False)
embed.add_field(name="12 1.5% 0 50", value='.', inline=False)
embed.add_field(name="13 2.0% 0 60", value='.', inline=False)
embed.add_field(name="14 2.5% 0 TBD", value='.', inline=False)
embed.add_field(name="15 3.0% 0 TBD", value='.', inline=False)
embed.add_field(name="16 3.5% 0 TBD", value='.', inline=False)
embed.add_field(name="17 4.0% 0 TBD", value='.', inline=False)
embed.add_field(name="18 4.5% 0 TBD", value='.', inline=False)
embed.add_field(name="19 5.0% 0 TBD", value='.', inline=False)
embed.add_field(name="20 5.5% 0 TBD", value='.', inline=False)
embed.add_field(name="21 6.0% 0 TBD", value='.', inline=False)
embed.add_field(name="22 6.5% 0 TBD", value='.', inline=False)
embed.add_field(name="23 7.0% 0 TBD", value='.', inline=False)
embed.add_field(name="24 7.5% 0 TBD", value='.', inline=False)
embed.add_field(name="25 8.0% 1 TBD", value='.', inline=False)
embed.add_field(name="26 8.5% 1 TBD", value='.', inline=False)
embed.add_field(name="27 9.0% 1 TBD", value='.', inline=False)
embed.add_field(name="28 9.5% 1 TBD", value='.', inline=False)
embed.add_field(name="29 10.0% 1 TBD", value='.', inline=False)
embed.add_field(name="30 10.5% 2 TBD", value='.', inline=False)
embed.add_field(name="31 11.0% 2 TBD", value='.', inline=False)
embed.add_field(name="32 11.5% 2 TBD", value='.', inline=False)
embed.add_field(name="33 12.0% 2 1.27K", value='.', inline=False)
embed.add_field(name="34 12.5% 2 1.46K", value='.', inline=False)
embed.add_field(name="35 13.0% 3 1.87K", value='.', inline=False)
embed.add_field(name="36 13.5% 3 2.02K", value='.', inline=False)
embed.add_field(name="37 14.0% 3 2.18K", value='.', inline=False)
embed.add_field(name="38 14.5% 3 2.36K", value='.', inline=False)
embed.add_field(name="39 15.0% 3 2.54K", value='.', inline=False)
embed.add_field(name="40 15.5% 4 2.73K", value='.', inline=False)
embed.add_field(name="41 16.0% 4 2.87K", value='.', inline=False)
embed.add_field(name="42 16.5% 4 3.07K", value='.', inline=False)
embed.add_field(name="43 17.0% 4 3.29K", value='.', inline=False)
embed.add_field(name="44 17.5% 4 3.51K", value='.', inline=False)
embed.add_field(name="45 18.0% 5 3.74K", value='.', inline=False)
embed.add_field(name="46 18.5% 5 3.99K", value='.', inline=False)
embed.add_field(name="47 19.0% 5 4.09K", value='.', inline=False)
embed.add_field(name="48 19.5% 5 4.34K", value='.', inline=False)
embed.add_field(name="49 20.0% 5 4.44K", value='.', inline=False)
embed.add_field(name="50 20.5% 6 4.54K", value='.', inline=False)
The command works great, except that discord cuts the message off on "embed.add_field(name="29 10.0% 1 TBD", value='.', inline=False)", due to the max character limit in a single message.
How would I go about splitting this message into pages? I have seen where you can have emojis that scroll through information, but I am unsure on how to apply that to this command here.
Or how could I make it to where it posts into multiple messages instead of it attempting to post into one whole message?
Any help is much appreciated!
This is the code I used to work with pagination before I started implementing buttons
async def paginate(
ctx: discord.ext.commands.context.Context,
*embed_pages: typing.Union[discord.Embed, list[discord.Embed]],
content=None,
overwrite_footer=True,
timeout=None,
):
if isinstance(embed_pages[0], list):
embed_pages = embed_pages[0]
every_embed = list()
if overwrite_footer:
for index, each_embed in enumerate(embed_pages):
each_embed.remove_footer()
each_embed.set_footer(text=f"Page {index + 1} of {len(embed_pages)}")
every_embed.append(each_embed)
else:
every_embed = embed_pages[:]
sent_embed = await ctx.send(
content=content, embed=every_embed[0]
) # Send the first page
page_index = 0 # Set the starting index
reactions = ["⬅️", "🔁", "➡️"]
for each_reaction in reactions:
await sent_embed.add_reaction(each_reaction)
while True:
try:
payload = await bot.wait_for(
"raw_reaction_add",
check=lambda payload: payload.message_id == sent_embed.id
and not payload.member == bot.user
and payload.member.id
== ctx.author.id, # Do this if you want it to be author-only
timeout=timeout,
)
except asyncio.TimeoutError:
# timeout has been hit
if overwrite_footer:
every_embed[page_index].remove_footer()
every_embed[page_index].set_footer(
text="Pagination traversal has timed out."
)
await sent_embed.edit(embed=every_embed[page_index])
try:
await every_embed.clear_reactions()
except:
pass
return
else:
try:
await sent_embed.remove_reaction(payload.emoji, payload.member)
except discord.Forbidden:
# Bot does not have permission
pass
if (
str(payload.emoji.name) not in reactions
): # Some user reacted with something else
pass
elif str(payload.emoji.name) == reactions[0]: # Previous page
if not page_index == 0:
page_index -= 1
else:
page_index = len(every_embed) - 1
await sent_embed.edit(embed=every_embed[page_index], content=content)
elif str(payload.emoji.name) == reactions[1]: # Goto page 0
page_index = 0
await sent_embed.edit(embed=every_embed[page_index], content=content)
else:
if not page_index == (len(every_embed) - 1):
page_index += 1
else:
page_index = 0
await sent_embed.edit(embed=every_embed[page_index], content=content)
This function is a coroutine and has to be await
ed, the first argument must be ctx
(context), rest of the arguments may be discord.Embed
objects or a single list that contain instances of aforementioned discord.Embed
.
The rest of the arguments are optional and self-explanatory.
Here's an use-case :
import discord
import os
import asyncio
import typing
import Lorem # Custom module
from discord.ext import commands
from dotenv import load_dotenv
load_dotenv()
bot = commands.Bot(command_prefix=">")
async def paginate(
ctx: discord.ext.commands.context.Context,
*embed_pages: typing.Union[discord.Embed, list[discord.Embed]],
content=None,
overwrite_footer=True,
timeout=None,
):
if isinstance(embed_pages[0], list):
embed_pages = embed_pages[0]
every_embed = list()
if overwrite_footer:
for index, each_embed in enumerate(embed_pages):
each_embed.remove_footer()
each_embed.set_footer(text=f"Page {index + 1} of {len(embed_pages)}")
every_embed.append(each_embed)
else:
every_embed = embed_pages[:]
sent_embed = await ctx.send(
content=content, embed=every_embed[0]
) # Send the first page
page_index = 0 # Set the starting index
reactions = ["⬅️", "🔁", "➡️"]
for each_reaction in reactions:
await sent_embed.add_reaction(each_reaction)
while True:
try:
payload = await bot.wait_for(
"raw_reaction_add",
check=lambda payload: payload.message_id == sent_embed.id
and not payload.member == bot.user
and payload.member.id
== ctx.author.id, # Do this if you want it to be author-only
timeout=timeout,
)
except asyncio.TimeoutError:
# timeout has been hit
if overwrite_footer:
every_embed[page_index].remove_footer()
every_embed[page_index].set_footer(
text="Pagination traversal has timed out."
)
await sent_embed.edit(embed=every_embed[page_index])
try:
await every_embed.clear_reactions()
except:
pass
return
else:
try:
await sent_embed.remove_reaction(payload.emoji, payload.member)
except discord.Forbidden:
# Bot does not have permission
pass
if (
str(payload.emoji.name) not in reactions
): # Some user reacted with something else
pass
elif str(payload.emoji.name) == reactions[0]: # Previous page
if not page_index == 0:
page_index -= 1
else:
page_index = len(every_embed) - 1
await sent_embed.edit(embed=every_embed[page_index], content=content)
elif str(payload.emoji.name) == reactions[1]: # Goto page 0
page_index = 0
await sent_embed.edit(embed=every_embed[page_index], content=content)
else:
if not page_index == (len(every_embed) - 1):
page_index += 1
else:
page_index = 0
await sent_embed.edit(embed=every_embed[page_index], content=content)
@bot.event
async def on_ready():
print(f"Sucessfully logged in as {bot.user}")
@bot.command()
async def start(ctx):
await paginate(
ctx,
[
discord.Embed(title="Answered by Achxy!", description=Lorem.lorem(6))
for _ in range(100)
],
)
# We just generated 100 pages of Lorem Ipsum :D
@bot.command()
async def ping(ctx):
# I made this command just to prove that the while loop earlier isn't blocking.
embed = discord.Embed(
title="Pong! 🏓",
description=f"Current Latency of the bot is {round(bot.latency * 1000)}ms",
)
await ctx.reply(embed=embed)
bot.run(os.getenv("DISCORD_TOKEN"))
This code will bring the following paginated output :