DiscordPYComponents 1.3.1__tar.gz → 1.3.2__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.
- {discordpycomponents-1.3.1 → discordpycomponents-1.3.2}/DiscordPYComponents.egg-info/PKG-INFO +1 -1
- {discordpycomponents-1.3.1 → discordpycomponents-1.3.2}/PKG-INFO +1 -1
- {discordpycomponents-1.3.1 → discordpycomponents-1.3.2}/py_components/__init__.py +1 -1
- {discordpycomponents-1.3.1 → discordpycomponents-1.3.2}/py_components/ui.py +31 -15
- {discordpycomponents-1.3.1 → discordpycomponents-1.3.2}/pyproject.toml +1 -1
- {discordpycomponents-1.3.1 → discordpycomponents-1.3.2}/DiscordPYComponents.egg-info/SOURCES.txt +0 -0
- {discordpycomponents-1.3.1 → discordpycomponents-1.3.2}/DiscordPYComponents.egg-info/dependency_links.txt +0 -0
- {discordpycomponents-1.3.1 → discordpycomponents-1.3.2}/DiscordPYComponents.egg-info/requires.txt +0 -0
- {discordpycomponents-1.3.1 → discordpycomponents-1.3.2}/DiscordPYComponents.egg-info/top_level.txt +0 -0
- {discordpycomponents-1.3.1 → discordpycomponents-1.3.2}/README.md +0 -0
- {discordpycomponents-1.3.1 → discordpycomponents-1.3.2}/py_components/components.py +0 -0
- {discordpycomponents-1.3.1 → discordpycomponents-1.3.2}/py_components/enums.py +0 -0
- {discordpycomponents-1.3.1 → discordpycomponents-1.3.2}/py_components/http.py +0 -0
- {discordpycomponents-1.3.1 → discordpycomponents-1.3.2}/py_components/ids.py +0 -0
- {discordpycomponents-1.3.1 → discordpycomponents-1.3.2}/py_components/modal.py +0 -0
- {discordpycomponents-1.3.1 → discordpycomponents-1.3.2}/py_components/registry.py +0 -0
- {discordpycomponents-1.3.1 → discordpycomponents-1.3.2}/py_components/view.py +0 -0
- {discordpycomponents-1.3.1 → discordpycomponents-1.3.2}/setup.cfg +0 -0
|
@@ -42,7 +42,7 @@ from .registry import Registry, default_registry
|
|
|
42
42
|
from .http import send_message, edit_message, respond_interaction, open_modal
|
|
43
43
|
from .ids import assign_ids, find_by_id, replace_by_id
|
|
44
44
|
|
|
45
|
-
__version__ = "1.3.
|
|
45
|
+
__version__ = "1.3.2"
|
|
46
46
|
__all__ = [
|
|
47
47
|
"ButtonStyle",
|
|
48
48
|
"ComponentType",
|
|
@@ -73,6 +73,9 @@ class UI:
|
|
|
73
73
|
|
|
74
74
|
if _is_interaction(target):
|
|
75
75
|
return await self._send_interaction(target, payload, files=files, **kwargs)
|
|
76
|
+
|
|
77
|
+
# User/Member → open DM channel so we never POST to /channels/{user.id}
|
|
78
|
+
target = await _ensure_messageable(target)
|
|
76
79
|
return await self._send_channel(target, payload, files=files, **kwargs)
|
|
77
80
|
|
|
78
81
|
async def reply(
|
|
@@ -181,7 +184,6 @@ class UI:
|
|
|
181
184
|
send_method = target.channel.send
|
|
182
185
|
|
|
183
186
|
if send_method is not None:
|
|
184
|
-
# discord.py Messageable.send — try with flags first (needed for V2)
|
|
185
187
|
attempts = [
|
|
186
188
|
dict(components=payload["components"], flags=payload.get("flags", IS_COMPONENTS_V2), files=files or [], **kwargs),
|
|
187
189
|
dict(components=payload["components"], flags=payload.get("flags", IS_COMPONENTS_V2), **kwargs),
|
|
@@ -196,7 +198,6 @@ class UI:
|
|
|
196
198
|
last_err = e
|
|
197
199
|
continue
|
|
198
200
|
except Exception as e:
|
|
199
|
-
# real API error — don't keep retrying silently
|
|
200
201
|
last_err = e
|
|
201
202
|
break
|
|
202
203
|
if last_err is not None and not isinstance(last_err, TypeError):
|
|
@@ -220,14 +221,36 @@ def _is_interaction(obj: Any) -> bool:
|
|
|
220
221
|
return False
|
|
221
222
|
|
|
222
223
|
|
|
224
|
+
def _is_user_like(obj: Any) -> bool:
|
|
225
|
+
"""User/Member — has create_dm, not a guild channel."""
|
|
226
|
+
if obj is None:
|
|
227
|
+
return False
|
|
228
|
+
if callable(getattr(obj, "create_dm", None)):
|
|
229
|
+
return True
|
|
230
|
+
# duck type: no guild attribute path for pure User
|
|
231
|
+
cls_name = type(obj).__name__
|
|
232
|
+
return cls_name in ("User", "Member", "ClientUser")
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
async def _ensure_messageable(target: Any) -> Any:
|
|
236
|
+
if _is_user_like(target):
|
|
237
|
+
dm = getattr(target, "dm_channel", None)
|
|
238
|
+
if dm is not None:
|
|
239
|
+
return dm
|
|
240
|
+
if callable(getattr(target, "create_dm", None)):
|
|
241
|
+
return await target.create_dm()
|
|
242
|
+
return target
|
|
243
|
+
|
|
244
|
+
|
|
223
245
|
def _resolve_channel_and_token(obj: Any) -> tuple[Any, str]:
|
|
224
246
|
channel_id = None
|
|
225
247
|
|
|
226
|
-
#
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
248
|
+
# Prefer explicit channel objects (have recipients or guild, or type name)
|
|
249
|
+
name = type(obj).__name__
|
|
250
|
+
if name in ("TextChannel", "Thread", "DMChannel", "GroupChannel", "VoiceChannel", "StageChannel"):
|
|
251
|
+
channel_id = getattr(obj, "id", None)
|
|
252
|
+
elif getattr(obj, "id", None) is not None and callable(getattr(obj, "send", None)) and not _is_user_like(obj):
|
|
253
|
+
channel_id = obj.id
|
|
231
254
|
|
|
232
255
|
if channel_id is None and hasattr(obj, "channel") and obj.channel is not None:
|
|
233
256
|
channel_id = getattr(obj.channel, "id", None)
|
|
@@ -243,7 +266,6 @@ def _resolve_channel_and_token(obj: Any) -> tuple[Any, str]:
|
|
|
243
266
|
|
|
244
267
|
|
|
245
268
|
def _resolve_token(obj: Any) -> str:
|
|
246
|
-
# common discord.py paths
|
|
247
269
|
for attr in ("bot", "client", "_state"):
|
|
248
270
|
owner = getattr(obj, attr, None)
|
|
249
271
|
if owner is None:
|
|
@@ -253,13 +275,7 @@ def _resolve_token(obj: Any) -> str:
|
|
|
253
275
|
tok = getattr(http, "token", None)
|
|
254
276
|
if tok:
|
|
255
277
|
return tok
|
|
256
|
-
# bot.http.token
|
|
257
|
-
tok = getattr(owner, "token", None)
|
|
258
|
-
if tok and isinstance(tok, str) and not tok.startswith("Bot "):
|
|
259
|
-
# sometimes the raw token is stored; http.token is preferred
|
|
260
|
-
pass
|
|
261
278
|
|
|
262
|
-
# channel._state.http.token
|
|
263
279
|
state = getattr(obj, "_state", None)
|
|
264
280
|
if state is not None:
|
|
265
281
|
http = getattr(state, "http", None)
|
|
@@ -268,7 +284,7 @@ def _resolve_token(obj: Any) -> str:
|
|
|
268
284
|
if tok:
|
|
269
285
|
return tok
|
|
270
286
|
|
|
271
|
-
if hasattr(obj, "channel"):
|
|
287
|
+
if hasattr(obj, "channel") and obj.channel is not None:
|
|
272
288
|
return _resolve_token(obj.channel)
|
|
273
289
|
|
|
274
290
|
raise ValueError("could not resolve bot token")
|
{discordpycomponents-1.3.1 → discordpycomponents-1.3.2}/DiscordPYComponents.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{discordpycomponents-1.3.1 → discordpycomponents-1.3.2}/DiscordPYComponents.egg-info/requires.txt
RENAMED
|
File without changes
|
{discordpycomponents-1.3.1 → discordpycomponents-1.3.2}/DiscordPYComponents.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|