3131JUMP_LAST_LABEL = " \u276f \u276f " # >>
3232STOP_PAGINATE_EMOJI = "\u274c " # [:x:] This is an emoji, which is treated differently from the above
3333
34+ NO_EMBED_FOOTER_BUMP = 15
35+
36+ _AUTOGENERATE = object ()
37+
38+
3439logger : ModmailLogger = logging .getLogger (__name__ )
3540
3641
@@ -57,13 +62,14 @@ def __init__(
5762 contents : Union [List [str ], str ],
5863 / ,
5964 source_message : Optional [discord .Message ] = None ,
60- embed : Embed = None ,
65+ embed : Union [ Embed , bool , None ] = _AUTOGENERATE ,
6166 timeout : float = 180 ,
6267 * ,
6368 footer_text : str = None ,
6469 prefix : str = "```" ,
6570 suffix : str = "```" ,
6671 max_size : int = 2000 ,
72+ title : str = None ,
6773 linesep : str = "\n " ,
6874 only_users : Optional [List [Union [discord .Object , discord .abc .User ]]] = None ,
6975 only_roles : Optional [List [Union [discord .Object , discord .Role ]]] = None ,
@@ -75,14 +81,33 @@ def __init__(
7581 If source message is provided and only_users is NOT provided, the paginator will respond
7682 to the author of the source message. To override this, pass an empty list to `only_users`.
7783
84+ By default, an embed is created. However, a custom embed can
85+ be passed, or None can be passed to not use an embed.
7886 """
7987 self .index = 0
8088 self ._pages : List [str ] = []
8189 self .prefix = prefix
8290 self .suffix = suffix
8391 self .max_size = max_size
8492 self .linesep = linesep
85- self .embed = embed or Embed ()
93+ if embed is _AUTOGENERATE or embed is True :
94+ self .embed = Embed ()
95+ else :
96+ if embed is False :
97+ embed = None
98+ self .embed = embed
99+
100+ # used if embed is None
101+ self .content = ""
102+ if self .embed is None :
103+ self .title = title
104+ # need to set the max_size down a few to be able to set a "footer"
105+ # page indicator is "page xx of xx"
106+ self .max_size -= NO_EMBED_FOOTER_BUMP + len (self .title or "" )
107+ if self .title is not None :
108+ self .max_size -= len (title )
109+ if footer_text is not None :
110+ self .max_size -= len (footer_text ) + 1
86111
87112 # temporary to support strings as contents. This will be changed when we added wrapping.
88113 if isinstance (contents , str ):
@@ -116,8 +141,8 @@ def __init__(
116141
117142 # set footer to embed.footer if embed is set
118143 # this is because we will be modifying the footer of this embed
119- if embed is not None :
120- if not isinstance (embed .footer , EmbedProxy ) and footer_text is None :
144+ if self . embed is not None :
145+ if not isinstance (self . embed .footer , EmbedProxy ) and footer_text is None :
121146 footer_text = embed .footer
122147 self .footer_text = footer_text
123148 self .clear ()
@@ -140,7 +165,7 @@ async def paginate(
140165 source_message : discord .Message = None ,
141166 / ,
142167 timeout : float = 180 ,
143- embed : Embed = None ,
168+ embed : Embed = _AUTOGENERATE ,
144169 * ,
145170 footer_text : str = None ,
146171 only : Optional [discord .abc .User ] = None ,
@@ -149,6 +174,7 @@ async def paginate(
149174 prefix : str = "" ,
150175 suffix : str = "" ,
151176 max_size : int = 4000 ,
177+ title : str = None ,
152178 linesep : str = "\n " ,
153179 only_users : Optional [List [Union [discord .Object , discord .abc .User ]]] = None ,
154180 only_roles : Optional [List [Union [discord .Object , discord .abc .Role ]]] = None ,
@@ -167,6 +193,7 @@ async def paginate(
167193 prefix = prefix ,
168194 suffix = suffix ,
169195 max_size = max_size ,
196+ title = title ,
170197 linesep = linesep ,
171198 only_users = only_users ,
172199 only_roles = only_roles ,
@@ -178,18 +205,24 @@ async def paginate(
178205 channel = source_message .channel
179206
180207 paginator .update_states ()
181- paginator .embed .description = paginator .pages [paginator .index ]
182208 # if there's only one page, don't send the view
183209 if len (paginator .pages ) < 2 :
184- await channel .send (embeds = [paginator .embed ])
210+ if paginator .embed :
211+ await channel .send (embeds = [paginator .embed ])
212+ else :
213+ await channel .send (content = paginator .content )
214+
185215 return
186216
187217 if len (paginator .pages ) < (show_jump_buttons_min_pages or 3 ):
188218 for item in paginator .children :
189219 if getattr (item , "custom_id" , None ) in ["pag_jump_first" , "pag_jump_last" ]:
190220 paginator .remove_item (item )
191221
192- msg : discord .Message = await channel .send (embeds = [paginator .embed ], view = paginator )
222+ if paginator .embed is None :
223+ msg : discord .Message = await channel .send (content = paginator .content , view = paginator )
224+ else :
225+ msg : discord .Message = await channel .send (embeds = [paginator .embed ], view = paginator )
193226
194227 await paginator .wait ()
195228 await msg .edit (view = None )
@@ -212,15 +245,6 @@ async def interaction_check(self, interaction: Interaction) -> bool:
212245 )
213246 return False
214247
215- def get_footer (self ) -> str :
216- """Returns the footer text."""
217- self .embed .description = self ._pages [self .index ]
218- page_indicator = f"Page { self .index + 1 } /{ len (self ._pages )} "
219- footer_txt = (
220- f"{ self .footer_text } ({ page_indicator } )" if self .footer_text is not None else page_indicator
221- )
222- return footer_txt
223-
224248 def update_states (self ) -> None :
225249 """
226250 Disable specific components depending on paginator page and length.
@@ -230,7 +254,20 @@ def update_states(self) -> None:
230254 if the paginator is on the last page, the jump last/move forward buttons will be disabled.
231255 """
232256 # update the footer
233- self .embed .set_footer (text = self .get_footer ())
257+ page_indicator = f"Page { self .index + 1 } /{ len (self ._pages )} "
258+ if self .footer_text :
259+ footer_text = f"{ self .footer_text } ({ page_indicator } )"
260+ else :
261+ footer_text = page_indicator
262+
263+ if self .embed is None :
264+ self .content = (self .title or "" ) + "\n "
265+ self .content += self ._pages [self .index ]
266+ self .content += "\n " + footer_text
267+
268+ else :
269+ self .embed .description = self ._pages [self .index ]
270+ self .embed .set_footer (text = footer_text )
234271
235272 # determine if the jump buttons should be enabled
236273 more_than_two_pages = len (self ._pages ) > 2
@@ -264,7 +301,10 @@ async def send_page(self, interaction: Interaction) -> None:
264301 """Send new page to discord, after updating the view to have properly disabled buttons."""
265302 self .update_states ()
266303
267- await interaction .message .edit (embed = self .embed , view = self )
304+ if self .embed :
305+ await interaction .message .edit (embed = self .embed , view = self )
306+ else :
307+ await interaction .message .edit (content = self .content , view = self )
268308
269309 @ui .button (label = JUMP_FIRST_LABEL , custom_id = "pag_jump_first" , style = ButtonStyle .primary )
270310 async def go_first (self , _ : Button , interaction : Interaction ) -> None :
0 commit comments