Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ext.pages] Add files parameter to Page object #1300

Merged
merged 3 commits into from
Apr 28, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 69 additions & 7 deletions discord/ext/pages/pagination.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ class Page:
The content of the page. Corresponds to the :class:`discord.Message.content` attribute.
embeds: Optional[List[Union[List[:class:`discord.Embed`], :class:`discord.Embed`]]]
The embeds of the page. Corresponds to the :class:`discord.Message.embeds` attribute.
files: Optional[List[:class:`discord.File`]]
A list of local files to be shown with the page.
custom_view: Optional[:class:`discord.ui.View`]
The custom view shown when the page is visible. Overrides the `custom_view` attribute of the main paginator.
"""
Expand All @@ -135,13 +137,15 @@ def __init__(
content: Optional[str] = None,
embeds: Optional[List[Union[List[discord.Embed], discord.Embed]]] = None,
custom_view: Optional[discord.ui.View] = None,
files: Optional[List[discord.File]] = None,
**kwargs,
):
if content is None and embeds is None:
raise discord.InvalidArgument("A page cannot have both content and embeds equal to None.")
self._content = content
self._embeds = embeds or []
self._custom_view = custom_view
self._files = files or []

async def callback(self, interaction: Optional[discord.Interaction] = None):
"""|coro|
Expand All @@ -155,6 +159,19 @@ async def callback(self, interaction: Optional[discord.Interaction] = None):
"""
pass

def update_files(self) -> Optional[List[discord.File]]:
"""Updates the files associated with the page by re-uploading them.
Typically used when the page is changed."""
for file in self._files:
with open(file.fp.name, "rb") as fp: # type: ignore
self._files[self._files.index(file)] = discord.File(
fp, # type: ignore
filename=file.filename,
description=file.description,
spoiler=file.spoiler,
)
return self._files

@property
def content(self) -> Optional[str]:
"""Gets the content for the page."""
Expand Down Expand Up @@ -185,6 +202,16 @@ def custom_view(self, value: Optional[discord.ui.View]):
"""Assigns a custom view to be shown when the page is displayed."""
self._custom_view = value

@property
def files(self) -> Optional[List[discord.File]]:
"""Gets the files associated with the page."""
return self._files

@files.setter
def files(self, value: Optional[List[discord.File]]):
"""Sets the files associated with the page."""
self._files = value


class PageGroup:
"""Creates a group of pages which the user can switch between.
Expand Down Expand Up @@ -472,7 +499,14 @@ async def on_timeout(self) -> None:
if self.disable_on_timeout:
for item in self.children:
item.disabled = True
await self.message.edit(view=self)
page = self.pages[self.current_page]
page = self.get_page_content(page)
files = page.update_files()
await self.message.edit(
view=self,
files=files or [],
attachments=[],
)

async def disable(
self,
Expand Down Expand Up @@ -561,12 +595,24 @@ async def goto_page(self, page_number: int = 0, *, interaction: Optional[discord
if page.custom_view:
self.update_custom_view(page.custom_view)

files = page.update_files()

if interaction:
await interaction.response.edit_message(content=page.content, embeds=page.embeds, view=self)
await interaction.response.defer() # needed to force webhook message edit route for files kwarg support
await interaction.followup.edit_message(
message_id=self.message.id,
content=page.content,
embeds=page.embeds,
attachments=[],
files=files or [],
view=self,
)
else:
await self.message.edit(
content=page.content,
embeds=page.embeds,
attachments=[],
files=files or [],
view=self,
)
if self.trigger_on_display:
Expand Down Expand Up @@ -729,16 +775,22 @@ def get_page_content(page: Union[Page, str, discord.Embed, List[discord.Embed]])
if isinstance(page, Page):
return page
elif isinstance(page, str):
return Page(content=page, embeds=[])
return Page(content=page, embeds=[], files=[])
elif isinstance(page, discord.Embed):
return Page(content=None, embeds=[page])
return Page(content=None, embeds=[page], files=[])
elif isinstance(page, discord.File):
return Page(content=None, embeds=[], files=[page])
elif isinstance(page, List):
if all(isinstance(x, discord.Embed) for x in page):
return Page(content=None, embeds=page)
return Page(content=None, embeds=page, files=[])
if all(isinstance(x, discord.File) for x in page):
return Page(content=None, embeds=[], files=page)
else:
raise TypeError("All list items must be embeds.")
raise TypeError("All list items must be embeds or files.")
else:
raise TypeError("Page content must be a Page object, string, an embed, or a list of embeds.")
raise TypeError(
"Page content must be a Page object, string, an embed, a list of embeds, a file, or a list of files."
)

async def page_action(self, interaction: Optional[discord.Interaction] = None) -> None:
"""Triggers the callback associated with the current page, if any.
Expand Down Expand Up @@ -832,6 +884,7 @@ async def send(
self.message = await ctx.send(
content=page_content.content,
embeds=page_content.embeds,
files=page_content.files,
view=self,
reference=reference,
allowed_mentions=allowed_mentions,
Expand Down Expand Up @@ -891,10 +944,13 @@ async def edit(
self.update_custom_view(page_content.custom_view)

self.user = message.author

try:
self.message = await message.edit(
content=page_content.content,
embeds=page_content.embeds,
files=page_content.files,
attachments=[],
view=self,
suppress=suppress,
allowed_mentions=allowed_mentions,
Expand Down Expand Up @@ -965,12 +1021,14 @@ async def respond(
msg = await target.send(
content=page_content.content,
embeds=page_content.embeds,
files=page_content.files,
view=self,
)
elif interaction.response.is_done():
msg = await interaction.followup.send(
content=page_content.content,
embeds=page_content.embeds,
files=page_content.files,
view=self,
ephemeral=ephemeral,
)
Expand All @@ -981,6 +1039,7 @@ async def respond(
msg = await interaction.response.send_message(
content=page_content.content,
embeds=page_content.embeds,
files=page_content.files,
view=self,
ephemeral=ephemeral,
)
Expand All @@ -992,18 +1051,21 @@ async def respond(
msg = await ctx.send(
content=page_content.content,
embeds=page_content.embeds,
files=page_content.files,
view=self,
)
else:
msg = await ctx.respond(
content=page_content.content,
embeds=page_content.embeds,
files=page_content.files,
view=self,
)
if isinstance(msg, (discord.Message, discord.WebhookMessage)):
self.message = msg
elif isinstance(msg, discord.Interaction):
self.message = await msg.original_message()

return self.message


Expand Down