PycordViews 1.0.0__tar.gz → 1.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pycordviews-1.0.0 → pycordviews-1.0.1}/PKG-INFO +1 -1
- {pycordviews-1.0.0 → pycordviews-1.0.1}/PycordViews.egg-info/PKG-INFO +1 -1
- pycordviews-1.0.1/PycordViews.egg-info/SOURCES.txt +23 -0
- pycordviews-1.0.1/PycordViews.egg-info/top_level.txt +3 -0
- pycordviews-1.0.1/pycordViews/pagination/__init__.py +2 -0
- pycordviews-1.0.1/pycordViews/pagination/errors.py +13 -0
- pycordviews-1.0.1/pycordViews/pagination/pagination_view.py +120 -0
- pycordviews-1.0.1/pycordViews/views/__init__.py +2 -0
- pycordviews-1.0.1/pycordViews/views/easy_modified_view.py +260 -0
- pycordviews-1.0.1/pycordViews/views/errors.py +9 -0
- {pycordviews-1.0.0 → pycordviews-1.0.1}/setup.py +2 -2
- pycordviews-1.0.0/PycordViews.egg-info/SOURCES.txt +0 -11
- pycordviews-1.0.0/PycordViews.egg-info/top_level.txt +0 -1
- {pycordviews-1.0.0 → pycordviews-1.0.1}/LICENSE +0 -0
- {pycordviews-1.0.0 → pycordviews-1.0.1}/PycordViews.egg-info/dependency_links.txt +0 -0
- {pycordviews-1.0.0 → pycordviews-1.0.1}/PycordViews.egg-info/requires.txt +0 -0
- {pycordviews-1.0.0 → pycordviews-1.0.1}/README.md +0 -0
- {pycordviews-1.0.0 → pycordviews-1.0.1}/pycordViews/__init__.py +0 -0
- {pycordviews-1.0.0 → pycordviews-1.0.1}/pycordViews/typeViews.py +0 -0
- {pycordviews-1.0.0 → pycordviews-1.0.1}/pyproject.toml +0 -0
- {pycordviews-1.0.0 → pycordviews-1.0.1}/setup.cfg +0 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
LICENSE
|
2
|
+
README.md
|
3
|
+
pyproject.toml
|
4
|
+
setup.py
|
5
|
+
PycordViews.egg-info/PKG-INFO
|
6
|
+
PycordViews.egg-info/SOURCES.txt
|
7
|
+
PycordViews.egg-info/dependency_links.txt
|
8
|
+
PycordViews.egg-info/requires.txt
|
9
|
+
PycordViews.egg-info/top_level.txt
|
10
|
+
pycordViews/__init__.py
|
11
|
+
pycordViews/typeViews.py
|
12
|
+
pycordViews/pagination/__init__.py
|
13
|
+
pycordViews/pagination/errors.py
|
14
|
+
pycordViews/pagination/pagination_view.py
|
15
|
+
pycordViews/views/__init__.py
|
16
|
+
pycordViews/views/easy_modified_view.py
|
17
|
+
pycordViews/views/errors.py
|
18
|
+
pycordViews/pagination/__init__.py
|
19
|
+
pycordViews/pagination/errors.py
|
20
|
+
pycordViews/pagination/pagination_view.py
|
21
|
+
pycordViews/views/__init__.py
|
22
|
+
pycordViews/views/easy_modified_view.py
|
23
|
+
pycordViews/views/errors.py
|
@@ -0,0 +1,13 @@
|
|
1
|
+
from typing import Union
|
2
|
+
|
3
|
+
class Py_cordPagination(Exception):
|
4
|
+
"""
|
5
|
+
Main class exception
|
6
|
+
"""
|
7
|
+
|
8
|
+
class PageNumberNotFound(Py_cordPagination):
|
9
|
+
"""
|
10
|
+
If the page number is not found
|
11
|
+
"""
|
12
|
+
def __init__(self, number: Union[int, str]):
|
13
|
+
super().__init__(f"Page {number} not found !")
|
@@ -0,0 +1,120 @@
|
|
1
|
+
from ..views.easy_modified_view import EasyModifiedViews
|
2
|
+
from discord import ButtonStyle, Interaction, TextChannel, Member, ApplicationContext
|
3
|
+
from discord.ui import Button
|
4
|
+
from .errors import PageNumberNotFound
|
5
|
+
|
6
|
+
from typing import Union, Any
|
7
|
+
|
8
|
+
|
9
|
+
class Pagination:
|
10
|
+
"""
|
11
|
+
Class
|
12
|
+
-------------
|
13
|
+
Allows you to easily setup a view pagination
|
14
|
+
"""
|
15
|
+
|
16
|
+
def __init__(self, timeout: Union[float, None] = None, disabled_on_timeout:bool = False):
|
17
|
+
"""
|
18
|
+
Initialisation for pagination
|
19
|
+
:param timeout: The time before disable items on the view
|
20
|
+
:param disabled_on_timeout: If timeout is done, disable all items
|
21
|
+
"""
|
22
|
+
self.__view = EasyModifiedViews(timeout, disabled_on_timeout=disabled_on_timeout)
|
23
|
+
|
24
|
+
self.__view.add_items(Button(label='⏮', row=0, custom_id='back+', style=ButtonStyle.blurple))
|
25
|
+
self.__view.add_items(Button(label='◀', row=0, custom_id='back', style=ButtonStyle.blurple))
|
26
|
+
self.__view.add_items(Button(label='▶', row=0, custom_id='forward', style=ButtonStyle.blurple))
|
27
|
+
self.__view.add_items(Button(label='⏭', row=0, custom_id='forward+', style=ButtonStyle.blurple))
|
28
|
+
self.__view.set_callable('back+', 'back', 'forward', 'forward+', coroutine=self.__turn_page)
|
29
|
+
|
30
|
+
self.__pages: list[tuple[tuple, dict]] = []
|
31
|
+
self.__current_page: int = 0
|
32
|
+
|
33
|
+
def add_page(self, *args, **kwargs) -> None:
|
34
|
+
"""
|
35
|
+
Adds a page (in a list) as if this function directly sent the message
|
36
|
+
Pages are just modified and not reset ! Don't forget to disable embeds or content if the page don't need this.
|
37
|
+
|
38
|
+
add_page(content="my message", embeds=[embed1, embed2], ...)
|
39
|
+
"""
|
40
|
+
self.__pages.append((args, kwargs))
|
41
|
+
|
42
|
+
def delete_pages(self, *page_numbers: Union[str, int]):
|
43
|
+
"""
|
44
|
+
Deletes pages in the order in which they were added
|
45
|
+
**Start to 0 !**
|
46
|
+
|
47
|
+
delete_pages(1,2,3,...)
|
48
|
+
"""
|
49
|
+
nbr_pages = len(self.__pages)-1
|
50
|
+
for page_number in page_numbers:
|
51
|
+
|
52
|
+
if page_number < 0 or page_number > nbr_pages:
|
53
|
+
raise PageNumberNotFound(page_number)
|
54
|
+
|
55
|
+
del self.__pages[page_number]
|
56
|
+
|
57
|
+
async def __turn_page(self, interaction: Interaction):
|
58
|
+
"""
|
59
|
+
Turn the page when button is pressed
|
60
|
+
"""
|
61
|
+
page_count = len(self.__pages)
|
62
|
+
|
63
|
+
if page_count <= 1:
|
64
|
+
await self.__view.shutdown()
|
65
|
+
await interaction.response.defer(invisible=True)
|
66
|
+
return
|
67
|
+
|
68
|
+
# Update the current page based on the button pressed
|
69
|
+
|
70
|
+
if interaction.custom_id == 'back+': # Go to the first page
|
71
|
+
self.__current_page = 0
|
72
|
+
|
73
|
+
elif interaction.custom_id == 'back': # Go to the previous page
|
74
|
+
self.__current_page = max(0, self.__current_page - 1)
|
75
|
+
|
76
|
+
elif interaction.custom_id == 'forward': # Go to the next page
|
77
|
+
self.__current_page = min(page_count-1, self.__current_page + 1)
|
78
|
+
|
79
|
+
elif interaction.custom_id == 'forward+': # Go to the last page
|
80
|
+
self.__current_page = page_count-1
|
81
|
+
|
82
|
+
|
83
|
+
await interaction.message.edit(
|
84
|
+
|
85
|
+
*self.__pages[self.__current_page][0],
|
86
|
+
|
87
|
+
**self.__pages[self.__current_page][1]
|
88
|
+
|
89
|
+
)
|
90
|
+
|
91
|
+
# Acknowledge the interaction
|
92
|
+
await interaction.response.defer(invisible=True)
|
93
|
+
|
94
|
+
async def send(self, send_to: Union[Member, TextChannel]) -> None:
|
95
|
+
"""
|
96
|
+
Send pagination without introduction message.
|
97
|
+
:param send_to: The member or channel to send the pagination
|
98
|
+
"""
|
99
|
+
|
100
|
+
await send_to.send(*self.__pages[0][0], **self.__pages[0][1], view=self.get_view)
|
101
|
+
|
102
|
+
async def respond(self, ctx: ApplicationContext) -> None:
|
103
|
+
"""
|
104
|
+
Respond to the command call
|
105
|
+
"""
|
106
|
+
await ctx.respond(*self.__pages[0][0], **self.__pages[0][1], view=self.get_view)
|
107
|
+
|
108
|
+
@property
|
109
|
+
def get_view(self) -> EasyModifiedViews:
|
110
|
+
"""
|
111
|
+
Get the view of pagination
|
112
|
+
"""
|
113
|
+
return self.__view
|
114
|
+
|
115
|
+
@property
|
116
|
+
def get_page(self) -> int:
|
117
|
+
"""
|
118
|
+
Get the number of showed page
|
119
|
+
"""
|
120
|
+
return self.__current_page
|
@@ -0,0 +1,260 @@
|
|
1
|
+
from discord import Interaction, ApplicationContext, Message
|
2
|
+
from discord.ui import View, Item
|
3
|
+
from typing import Union, Callable, Coroutine, Iterable
|
4
|
+
|
5
|
+
from ..typeViews import T_views
|
6
|
+
from .errors import CustomIDNotFound
|
7
|
+
|
8
|
+
|
9
|
+
class EasyModifiedViews(View):
|
10
|
+
"""
|
11
|
+
Class
|
12
|
+
-------------
|
13
|
+
Allows you to easily modify and replace an ui.
|
14
|
+
"""
|
15
|
+
|
16
|
+
def __init__(self, timeout: Union[float, None] = None, disabled_on_timeout: bool = False, *items: Item):
|
17
|
+
"""
|
18
|
+
Init a Class view for Discord UI
|
19
|
+
:param timeout: The time before ui disable
|
20
|
+
"""
|
21
|
+
super().__init__(*items, timeout=timeout)
|
22
|
+
self.__timeout: Union[float, None] = timeout
|
23
|
+
self.__disabled_on_timeout: bool = disabled_on_timeout
|
24
|
+
self.__callback: dict[str, dict[str, Union[Callable[[Interaction], None], T_views]]] = {}
|
25
|
+
self.__ctx: Union[Message, Interaction] = None
|
26
|
+
|
27
|
+
def __check_custom_id(self, custom_id: str) -> None:
|
28
|
+
"""
|
29
|
+
Check if the custom_id is alive
|
30
|
+
:param custom_id: ID to find
|
31
|
+
:raise: CustomIDNotFound
|
32
|
+
"""
|
33
|
+
if custom_id not in self.__callback.keys():
|
34
|
+
raise CustomIDNotFound()
|
35
|
+
|
36
|
+
async def respond(self, ctx: ApplicationContext, *args, **kwargs) -> None:
|
37
|
+
"""
|
38
|
+
Respond at the ApplicationContext
|
39
|
+
"""
|
40
|
+
self.__ctx = await ctx.respond(*args, **kwargs)
|
41
|
+
|
42
|
+
def add_items(self,
|
43
|
+
*items: T_views) -> "EasyModifiedViews":
|
44
|
+
"""
|
45
|
+
Add all items in the View.
|
46
|
+
custom_id REQUIRED !
|
47
|
+
"""
|
48
|
+
|
49
|
+
for ui in items:
|
50
|
+
|
51
|
+
self.__callback[ui.custom_id] = {'ui': ui, 'func': None}
|
52
|
+
self.add_item(ui)
|
53
|
+
|
54
|
+
return self
|
55
|
+
|
56
|
+
async def update_items(self, *items: T_views) -> "EasyModifiedViews":
|
57
|
+
"""
|
58
|
+
Update all views.
|
59
|
+
Append items if custom_ids not in the view
|
60
|
+
Update items if custom_ids in the view
|
61
|
+
:param items: items to update
|
62
|
+
"""
|
63
|
+
|
64
|
+
for item in items:
|
65
|
+
|
66
|
+
try:
|
67
|
+
self.__check_custom_id(item.custom_id)
|
68
|
+
self.__callback[item.custom_id]['ui'] = item
|
69
|
+
|
70
|
+
except CustomIDNotFound:
|
71
|
+
self.add_items(item)
|
72
|
+
|
73
|
+
await self._update()
|
74
|
+
return self
|
75
|
+
|
76
|
+
def set_callable_decorator(self, custom_id: str):
|
77
|
+
"""
|
78
|
+
Decorator to set up a coroutine for the item
|
79
|
+
|
80
|
+
**Interaction parameter is required in coroutine function !**
|
81
|
+
|
82
|
+
view = EasyModifiedViews(None)
|
83
|
+
view.add_view(discord.ui.Button(label='coucou', custom_id='test_ID'))
|
84
|
+
|
85
|
+
@view.set_callable_decorator(custom_id='test_ID')
|
86
|
+
|
87
|
+
async def rep(**interaction**):
|
88
|
+
await interaction.response.send_message('coucou !!!')
|
89
|
+
|
90
|
+
await ctx.respond('coucou', view=view)
|
91
|
+
|
92
|
+
:param custom_id: item ID of the view
|
93
|
+
"""
|
94
|
+
|
95
|
+
def decorator(coroutine: Coroutine):
|
96
|
+
self.__check_custom_id(custom_id)
|
97
|
+
|
98
|
+
self.__callback[custom_id]['func'] = coroutine
|
99
|
+
return coroutine
|
100
|
+
|
101
|
+
return decorator
|
102
|
+
|
103
|
+
def set_callable(self, *custom_ids: str, coroutine: Coroutine):
|
104
|
+
"""
|
105
|
+
set up a coroutine for items
|
106
|
+
:param custom_ids: items IDs of the view
|
107
|
+
:param coroutine: The coroutine linked
|
108
|
+
|
109
|
+
**Interaction parameter is required in coroutine function !**
|
110
|
+
|
111
|
+
view = EasyModifiedViews(None)
|
112
|
+
|
113
|
+
view.add_view(discord.ui.Button(label='coucou', custom_id='test_ID'))
|
114
|
+
|
115
|
+
async def rep(**interaction**):
|
116
|
+
await interaction.response.send_message('coucou !!!')
|
117
|
+
|
118
|
+
view.set_callable(custom_id='test_ID', coroutine=rep)
|
119
|
+
await ctx.respond('coucou', view=view)
|
120
|
+
"""
|
121
|
+
for custom_id in custom_ids:
|
122
|
+
self.__check_custom_id(custom_id)
|
123
|
+
|
124
|
+
self.__callback[custom_id]['func'] = coroutine
|
125
|
+
|
126
|
+
async def interaction_check(self, interaction: Interaction) -> bool:
|
127
|
+
"""
|
128
|
+
Func to apply items
|
129
|
+
"""
|
130
|
+
func = self.__callback[interaction.custom_id]['func']
|
131
|
+
|
132
|
+
if func is not None:
|
133
|
+
await func(interaction)
|
134
|
+
|
135
|
+
else:
|
136
|
+
await interaction.response.defer(invisible=True)
|
137
|
+
|
138
|
+
return True
|
139
|
+
|
140
|
+
async def shutdown(self) -> None:
|
141
|
+
"""
|
142
|
+
Disable all items (ui) in the view
|
143
|
+
"""
|
144
|
+
self.disable_all_items()
|
145
|
+
await self._update()
|
146
|
+
|
147
|
+
async def disable_items(self, *custom_ids: str) -> None:
|
148
|
+
"""
|
149
|
+
Disable partial items in the view
|
150
|
+
:param custom_ids: custom ids of all items to deactivate
|
151
|
+
"""
|
152
|
+
|
153
|
+
self.disable_all_items(exclusions=[self.get_item(id_) for id_ in self.__callback.keys() if id_ not in custom_ids])
|
154
|
+
await self._update()
|
155
|
+
|
156
|
+
async def enable_items(self, *custom_ids: str) -> None:
|
157
|
+
"""
|
158
|
+
Enabl partial items in the view
|
159
|
+
:param custom_ids: custom ids of all items to activate
|
160
|
+
"""
|
161
|
+
self.enable_all_items(
|
162
|
+
exclusions=[self.get_item(id_) for id_ in self.__callback.keys() if id_ not in custom_ids])
|
163
|
+
await self._update()
|
164
|
+
|
165
|
+
async def full_enable_items(self) -> None:
|
166
|
+
"""
|
167
|
+
Enable all items in the view
|
168
|
+
"""
|
169
|
+
self.enable_all_items()
|
170
|
+
await self._update()
|
171
|
+
|
172
|
+
|
173
|
+
async def switch_status_items(self):
|
174
|
+
"""
|
175
|
+
Switch status for all items
|
176
|
+
Enable -> Disable
|
177
|
+
Disable -> Enable
|
178
|
+
"""
|
179
|
+
|
180
|
+
for key, in self.__callback.keys():
|
181
|
+
self.__callback[key]['ui'].disabled = not self.__callback[key]['ui'].disabled
|
182
|
+
|
183
|
+
await self._update()
|
184
|
+
|
185
|
+
|
186
|
+
def is_items_disabled(self, *custom_ids: str) -> bool:
|
187
|
+
"""
|
188
|
+
Return True if all items are disabled
|
189
|
+
"""
|
190
|
+
|
191
|
+
for custom_id in custom_ids:
|
192
|
+
self.__check_custom_id(custom_id)
|
193
|
+
if not self.__callback[custom_id]['ui'].disabled:
|
194
|
+
return False
|
195
|
+
|
196
|
+
return True
|
197
|
+
|
198
|
+
|
199
|
+
def is_items_enabled(self, *custom_ids: str) -> bool:
|
200
|
+
"""
|
201
|
+
Return True il aff items are enabled
|
202
|
+
"""
|
203
|
+
|
204
|
+
for custom_id in custom_ids:
|
205
|
+
self.__check_custom_id(custom_id)
|
206
|
+
if self.__callback[custom_id]['ui'].disabled:
|
207
|
+
return False
|
208
|
+
|
209
|
+
return True
|
210
|
+
|
211
|
+
|
212
|
+
async def delete_items(self, clear_all: bool = False, *custom_ids: str) -> None:
|
213
|
+
"""
|
214
|
+
Delete an item on the view
|
215
|
+
:param custom_ids: IDs of items to delete
|
216
|
+
:param clear_all: Clear all items in the view
|
217
|
+
:raise: CustomIDNotFound
|
218
|
+
"""
|
219
|
+
if clear_all:
|
220
|
+
self.clear_items()
|
221
|
+
|
222
|
+
else:
|
223
|
+
|
224
|
+
for custom_id in custom_ids:
|
225
|
+
self.__check_custom_id(custom_id)
|
226
|
+
self.remove_item(self.get_item(custom_id))
|
227
|
+
|
228
|
+
await self._update()
|
229
|
+
|
230
|
+
def on_timeout(self) -> None:
|
231
|
+
"""
|
232
|
+
Called if timeout view is finished
|
233
|
+
"""
|
234
|
+
if self.__disabled_on_timeout:
|
235
|
+
self.shutdown()
|
236
|
+
|
237
|
+
async def _update(self) -> None:
|
238
|
+
"""
|
239
|
+
Update the View on the attached message.
|
240
|
+
"""
|
241
|
+
if self.message:
|
242
|
+
await self.message.edit(view=self)
|
243
|
+
|
244
|
+
else:
|
245
|
+
await self.__ctx.edit(view=self)
|
246
|
+
|
247
|
+
@property
|
248
|
+
def get_uis(self) -> list[T_views]:
|
249
|
+
"""
|
250
|
+
Get all uis in the view
|
251
|
+
"""
|
252
|
+
return [i['ui'] for i in self.__callback.values()]
|
253
|
+
|
254
|
+
def get_ui(self, custom_id: str) -> T_views:
|
255
|
+
"""
|
256
|
+
Get an ui in the view
|
257
|
+
:raise: CustomIDNotFound
|
258
|
+
"""
|
259
|
+
self.__check_custom_id(custom_id)
|
260
|
+
return self.__callback[custom_id]['ui']
|
@@ -5,7 +5,7 @@ with open("README.md") as file:
|
|
5
5
|
|
6
6
|
setup(
|
7
7
|
name="PycordViews",
|
8
|
-
version="1.0.
|
8
|
+
version="1.0.1",
|
9
9
|
url="https://github.com/BOXERRMD/Py-cord_Views",
|
10
10
|
author="Chronos (alias BOXERRMD)",
|
11
11
|
author_email="vagabonwalybi@gmail.com",
|
@@ -27,6 +27,6 @@ setup(
|
|
27
27
|
install_requires=[
|
28
28
|
"py-cord==2.6.1"
|
29
29
|
],
|
30
|
-
packages=['pycordViews'],
|
30
|
+
packages=['pycordViews', 'pycordViews/pagination', 'pycordViews/views'],
|
31
31
|
python_requires='>=3.9'
|
32
32
|
)
|
@@ -1,11 +0,0 @@
|
|
1
|
-
LICENSE
|
2
|
-
README.md
|
3
|
-
pyproject.toml
|
4
|
-
setup.py
|
5
|
-
PycordViews.egg-info/PKG-INFO
|
6
|
-
PycordViews.egg-info/SOURCES.txt
|
7
|
-
PycordViews.egg-info/dependency_links.txt
|
8
|
-
PycordViews.egg-info/requires.txt
|
9
|
-
PycordViews.egg-info/top_level.txt
|
10
|
-
pycordViews/__init__.py
|
11
|
-
pycordViews/typeViews.py
|
@@ -1 +0,0 @@
|
|
1
|
-
pycordViews
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|