disagreement 0.0.1__py3-none-any.whl → 0.0.2__py3-none-any.whl
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.
- disagreement/__init__.py +1 -1
- disagreement/ext/__init__.py +0 -0
- disagreement/ext/app_commands/__init__.py +46 -0
- disagreement/ext/app_commands/commands.py +513 -0
- disagreement/ext/app_commands/context.py +556 -0
- disagreement/ext/app_commands/converters.py +478 -0
- disagreement/ext/app_commands/decorators.py +569 -0
- disagreement/ext/app_commands/handler.py +627 -0
- disagreement/ext/commands/__init__.py +49 -0
- disagreement/ext/commands/cog.py +155 -0
- disagreement/ext/commands/converters.py +175 -0
- disagreement/ext/commands/core.py +490 -0
- disagreement/ext/commands/decorators.py +150 -0
- disagreement/ext/commands/errors.py +76 -0
- disagreement/ext/commands/help.py +37 -0
- disagreement/ext/commands/view.py +103 -0
- disagreement/ext/loader.py +43 -0
- disagreement/ext/tasks.py +89 -0
- disagreement/gateway.py +11 -8
- {disagreement-0.0.1.dist-info → disagreement-0.0.2.dist-info}/METADATA +39 -32
- {disagreement-0.0.1.dist-info → disagreement-0.0.2.dist-info}/RECORD +24 -7
- {disagreement-0.0.1.dist-info → disagreement-0.0.2.dist-info}/WHEEL +0 -0
- {disagreement-0.0.1.dist-info → disagreement-0.0.2.dist-info}/licenses/LICENSE +0 -0
- {disagreement-0.0.1.dist-info → disagreement-0.0.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,478 @@
|
|
1
|
+
# disagreement/ext/app_commands/converters.py
|
2
|
+
|
3
|
+
"""
|
4
|
+
Converters for transforming application command option values.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from typing import (
|
8
|
+
Any,
|
9
|
+
Awaitable,
|
10
|
+
Callable,
|
11
|
+
Dict,
|
12
|
+
Protocol,
|
13
|
+
TypeVar,
|
14
|
+
Union,
|
15
|
+
TYPE_CHECKING,
|
16
|
+
)
|
17
|
+
from disagreement.enums import ApplicationCommandOptionType
|
18
|
+
from disagreement.errors import (
|
19
|
+
AppCommandOptionConversionError,
|
20
|
+
) # To be created in disagreement/errors.py
|
21
|
+
|
22
|
+
if TYPE_CHECKING:
|
23
|
+
from disagreement.interactions import Interaction # For context if needed
|
24
|
+
from disagreement.models import (
|
25
|
+
User,
|
26
|
+
Member,
|
27
|
+
Role,
|
28
|
+
Channel,
|
29
|
+
Attachment,
|
30
|
+
) # Discord models
|
31
|
+
from disagreement.client import Client # For fetching objects
|
32
|
+
|
33
|
+
T = TypeVar("T", covariant=True)
|
34
|
+
|
35
|
+
|
36
|
+
class Converter(Protocol[T]):
|
37
|
+
"""
|
38
|
+
A protocol for classes that can convert an interaction option value to a specific type.
|
39
|
+
"""
|
40
|
+
|
41
|
+
async def convert(self, interaction: "Interaction", value: Any) -> T:
|
42
|
+
"""
|
43
|
+
Converts the given value to the target type.
|
44
|
+
|
45
|
+
Parameters:
|
46
|
+
interaction (Interaction): The interaction context.
|
47
|
+
value (Any): The raw value from the interaction option.
|
48
|
+
|
49
|
+
Returns:
|
50
|
+
T: The converted value.
|
51
|
+
|
52
|
+
Raises:
|
53
|
+
AppCommandOptionConversionError: If conversion fails.
|
54
|
+
"""
|
55
|
+
...
|
56
|
+
|
57
|
+
|
58
|
+
# Basic Type Converters
|
59
|
+
|
60
|
+
|
61
|
+
class StringConverter(Converter[str]):
|
62
|
+
async def convert(self, interaction: "Interaction", value: Any) -> str:
|
63
|
+
if not isinstance(value, str):
|
64
|
+
raise AppCommandOptionConversionError(
|
65
|
+
f"Expected a string, but got {type(value).__name__}: {value}"
|
66
|
+
)
|
67
|
+
return value
|
68
|
+
|
69
|
+
|
70
|
+
class IntegerConverter(Converter[int]):
|
71
|
+
async def convert(self, interaction: "Interaction", value: Any) -> int:
|
72
|
+
if not isinstance(value, int):
|
73
|
+
try:
|
74
|
+
return int(value)
|
75
|
+
except (ValueError, TypeError):
|
76
|
+
raise AppCommandOptionConversionError(
|
77
|
+
f"Expected an integer, but got {type(value).__name__}: {value}"
|
78
|
+
)
|
79
|
+
return value
|
80
|
+
|
81
|
+
|
82
|
+
class BooleanConverter(Converter[bool]):
|
83
|
+
async def convert(self, interaction: "Interaction", value: Any) -> bool:
|
84
|
+
if not isinstance(value, bool):
|
85
|
+
if isinstance(value, str):
|
86
|
+
if value.lower() == "true":
|
87
|
+
return True
|
88
|
+
elif value.lower() == "false":
|
89
|
+
return False
|
90
|
+
raise AppCommandOptionConversionError(
|
91
|
+
f"Expected a boolean, but got {type(value).__name__}: {value}"
|
92
|
+
)
|
93
|
+
return value
|
94
|
+
|
95
|
+
|
96
|
+
class NumberConverter(Converter[float]): # Discord 'NUMBER' type is float
|
97
|
+
async def convert(self, interaction: "Interaction", value: Any) -> float:
|
98
|
+
if not isinstance(value, (int, float)):
|
99
|
+
try:
|
100
|
+
return float(value)
|
101
|
+
except (ValueError, TypeError):
|
102
|
+
raise AppCommandOptionConversionError(
|
103
|
+
f"Expected a number (float), but got {type(value).__name__}: {value}"
|
104
|
+
)
|
105
|
+
return float(value) # Ensure it's a float even if int is passed
|
106
|
+
|
107
|
+
|
108
|
+
# Discord Model Converters
|
109
|
+
|
110
|
+
|
111
|
+
class UserConverter(Converter["User"]):
|
112
|
+
def __init__(self, client: "Client"):
|
113
|
+
self._client = client
|
114
|
+
|
115
|
+
async def convert(self, interaction: "Interaction", value: Any) -> "User":
|
116
|
+
if isinstance(value, str): # Assume it's a user ID
|
117
|
+
user_id = value
|
118
|
+
# Attempt to get from interaction resolved data first
|
119
|
+
if (
|
120
|
+
interaction.data
|
121
|
+
and interaction.data.resolved
|
122
|
+
and interaction.data.resolved.users
|
123
|
+
):
|
124
|
+
user_object = interaction.data.resolved.users.get(
|
125
|
+
user_id
|
126
|
+
) # This is already a User object
|
127
|
+
if user_object:
|
128
|
+
return user_object # Return the already parsed User object
|
129
|
+
|
130
|
+
# Fallback to fetching if not in resolved or if interaction has no resolved data
|
131
|
+
try:
|
132
|
+
user = await self._client.fetch_user(
|
133
|
+
user_id
|
134
|
+
) # fetch_user now also parses and caches
|
135
|
+
if user:
|
136
|
+
return user
|
137
|
+
raise AppCommandOptionConversionError(
|
138
|
+
f"User with ID '{user_id}' not found.",
|
139
|
+
option_name="user",
|
140
|
+
original_value=value,
|
141
|
+
)
|
142
|
+
except Exception as e: # Catch potential HTTP errors from fetch_user
|
143
|
+
raise AppCommandOptionConversionError(
|
144
|
+
f"Failed to fetch user '{user_id}': {e}",
|
145
|
+
option_name="user",
|
146
|
+
original_value=value,
|
147
|
+
)
|
148
|
+
elif (
|
149
|
+
isinstance(value, dict) and "id" in value
|
150
|
+
): # If it's raw user data dict (less common path now)
|
151
|
+
return self._client.parse_user(value) # parse_user handles dict -> User
|
152
|
+
raise AppCommandOptionConversionError(
|
153
|
+
f"Expected a user ID string or user data dict, got {type(value).__name__}",
|
154
|
+
option_name="user",
|
155
|
+
original_value=value,
|
156
|
+
)
|
157
|
+
|
158
|
+
|
159
|
+
class MemberConverter(Converter["Member"]):
|
160
|
+
def __init__(self, client: "Client"):
|
161
|
+
self._client = client
|
162
|
+
|
163
|
+
async def convert(self, interaction: "Interaction", value: Any) -> "Member":
|
164
|
+
if not interaction.guild_id:
|
165
|
+
raise AppCommandOptionConversionError(
|
166
|
+
"Cannot convert to Member outside of a guild context.",
|
167
|
+
option_name="member",
|
168
|
+
)
|
169
|
+
|
170
|
+
if isinstance(value, str): # Assume it's a user ID
|
171
|
+
member_id = value
|
172
|
+
# Attempt to get from interaction resolved data first
|
173
|
+
if (
|
174
|
+
interaction.data
|
175
|
+
and interaction.data.resolved
|
176
|
+
and interaction.data.resolved.members
|
177
|
+
):
|
178
|
+
# The Member object from resolved.members should already be correctly initialized
|
179
|
+
# by ResolvedData, including its User part.
|
180
|
+
member = interaction.data.resolved.members.get(member_id)
|
181
|
+
if member:
|
182
|
+
return (
|
183
|
+
member # Return the already resolved and parsed Member object
|
184
|
+
)
|
185
|
+
|
186
|
+
# Fallback to fetching if not in resolved
|
187
|
+
try:
|
188
|
+
member = await self._client.fetch_member(
|
189
|
+
interaction.guild_id, member_id
|
190
|
+
)
|
191
|
+
if member:
|
192
|
+
return member
|
193
|
+
raise AppCommandOptionConversionError(
|
194
|
+
f"Member with ID '{member_id}' not found in guild '{interaction.guild_id}'.",
|
195
|
+
option_name="member",
|
196
|
+
original_value=value,
|
197
|
+
)
|
198
|
+
except Exception as e:
|
199
|
+
raise AppCommandOptionConversionError(
|
200
|
+
f"Failed to fetch member '{member_id}': {e}",
|
201
|
+
option_name="member",
|
202
|
+
original_value=value,
|
203
|
+
)
|
204
|
+
elif isinstance(value, dict) and "id" in value.get(
|
205
|
+
"user", {}
|
206
|
+
): # If it's already a member data dict
|
207
|
+
return self._client.parse_member(value, interaction.guild_id)
|
208
|
+
raise AppCommandOptionConversionError(
|
209
|
+
f"Expected a member ID string or member data dict, got {type(value).__name__}",
|
210
|
+
option_name="member",
|
211
|
+
original_value=value,
|
212
|
+
)
|
213
|
+
|
214
|
+
|
215
|
+
class RoleConverter(Converter["Role"]):
|
216
|
+
def __init__(self, client: "Client"):
|
217
|
+
self._client = client
|
218
|
+
|
219
|
+
async def convert(self, interaction: "Interaction", value: Any) -> "Role":
|
220
|
+
if not interaction.guild_id:
|
221
|
+
raise AppCommandOptionConversionError(
|
222
|
+
"Cannot convert to Role outside of a guild context.", option_name="role"
|
223
|
+
)
|
224
|
+
|
225
|
+
if isinstance(value, str): # Assume it's a role ID
|
226
|
+
role_id = value
|
227
|
+
# Attempt to get from interaction resolved data first
|
228
|
+
if (
|
229
|
+
interaction.data
|
230
|
+
and interaction.data.resolved
|
231
|
+
and interaction.data.resolved.roles
|
232
|
+
):
|
233
|
+
role_object = interaction.data.resolved.roles.get(
|
234
|
+
role_id
|
235
|
+
) # Should be a Role object
|
236
|
+
if role_object:
|
237
|
+
return role_object
|
238
|
+
|
239
|
+
# Fallback to fetching from guild if not in resolved
|
240
|
+
# This requires Client to have a fetch_role method or similar
|
241
|
+
try:
|
242
|
+
# Assuming Client.fetch_role(guild_id, role_id) will be implemented
|
243
|
+
role = await self._client.fetch_role(interaction.guild_id, role_id)
|
244
|
+
if role:
|
245
|
+
return role
|
246
|
+
raise AppCommandOptionConversionError(
|
247
|
+
f"Role with ID '{role_id}' not found in guild '{interaction.guild_id}'.",
|
248
|
+
option_name="role",
|
249
|
+
original_value=value,
|
250
|
+
)
|
251
|
+
except Exception as e:
|
252
|
+
raise AppCommandOptionConversionError(
|
253
|
+
f"Failed to fetch role '{role_id}': {e}",
|
254
|
+
option_name="role",
|
255
|
+
original_value=value,
|
256
|
+
)
|
257
|
+
elif (
|
258
|
+
isinstance(value, dict) and "id" in value
|
259
|
+
): # If it's already role data dict
|
260
|
+
if (
|
261
|
+
not interaction.guild_id
|
262
|
+
): # Should have been caught earlier, but as a safeguard
|
263
|
+
raise AppCommandOptionConversionError(
|
264
|
+
"Guild context is required to parse role data.",
|
265
|
+
option_name="role",
|
266
|
+
original_value=value,
|
267
|
+
)
|
268
|
+
return self._client.parse_role(value, interaction.guild_id)
|
269
|
+
# This path is reached if value is not a string (role ID) and not a dict (role data)
|
270
|
+
# or if it's a string but all fetching/lookup attempts failed.
|
271
|
+
# The final raise AppCommandOptionConversionError should be outside the if/elif for string values.
|
272
|
+
# If value was a string, an error should have been raised within the 'if isinstance(value, str)' block.
|
273
|
+
# If it wasn't a string or dict, this is the correct place to raise.
|
274
|
+
# The previous structure was slightly off, as the final raise was inside the string check block.
|
275
|
+
# Let's ensure the final raise is at the correct scope.
|
276
|
+
# The current structure seems to imply that if it's not a string, it must be a dict or error.
|
277
|
+
# If it's a string and all lookups fail, an error is raised within that block.
|
278
|
+
# If it's a dict and parsing fails (or guild_id missing), error raised.
|
279
|
+
# If it's neither, this final raise is correct.
|
280
|
+
# The "Function with declared return type "Role" must return value on all code paths"
|
281
|
+
# error suggests a path where no return or raise happens.
|
282
|
+
# This happens if `isinstance(value, str)` is true, but then all internal paths
|
283
|
+
# (resolved check, fetch try/except) don't lead to a return or raise *before*
|
284
|
+
# falling out of the `if isinstance(value, str)` block.
|
285
|
+
# The `raise AppCommandOptionConversionError` at the end of the `if isinstance(value, str)` block
|
286
|
+
# (line 156 in previous version) handles the case where a role ID is given but not found.
|
287
|
+
# The one at the very end (line 164 in previous) handles cases where value is not str/dict.
|
288
|
+
|
289
|
+
# Corrected structure for the final raise:
|
290
|
+
# It should be at the same level as the initial `if isinstance(value, str):`
|
291
|
+
# to catch cases where `value` is neither a str nor a dict.
|
292
|
+
# However, the current logic within the `if isinstance(value, str):` block
|
293
|
+
# ensures a raise if the role ID is not found.
|
294
|
+
# The `elif isinstance(value, dict)` handles the dict case.
|
295
|
+
# The final `raise` (line 164) is for types other than str or dict.
|
296
|
+
# The Pylance error "Function with declared return type "Role" must return value on all code paths"
|
297
|
+
# implies that if `value` is a string, and `interaction.data.resolved.roles.get(role_id)` is None,
|
298
|
+
# AND `self._client.fetch_role` returns None (which it can), then the
|
299
|
+
# `raise AppCommandOptionConversionError` on line 156 is correctly hit.
|
300
|
+
# The issue might be that Pylance doesn't see `AppCommandOptionConversionError` as definitively terminating.
|
301
|
+
# This is unlikely. Let's re-verify the logic flow.
|
302
|
+
|
303
|
+
# The `raise` on line 156 is correct if role_id is not found after fetching.
|
304
|
+
# The `raise` on line 164 is for when `value` is not a str and not a dict.
|
305
|
+
# This seems logically sound. The Pylance error might be a misinterpretation or a subtle issue.
|
306
|
+
# For now, the duplicated `except` is the primary syntax error.
|
307
|
+
# The "must return value on all code paths" often occurs if an if/elif chain doesn't
|
308
|
+
# exhaust all possibilities or if a path through a try/except doesn't guarantee a return/raise.
|
309
|
+
# In this case, if `value` is a string, it either returns a Role or raises an error.
|
310
|
+
# If `value` is a dict, it either returns a Role or raises an error.
|
311
|
+
# If `value` is neither, it raises an error. All paths seem covered.
|
312
|
+
# The syntax error from the duplicated `except` is the most likely culprit for Pylance's confusion.
|
313
|
+
raise AppCommandOptionConversionError(
|
314
|
+
f"Expected a role ID string or role data dict, got {type(value).__name__}",
|
315
|
+
option_name="role",
|
316
|
+
original_value=value,
|
317
|
+
)
|
318
|
+
|
319
|
+
|
320
|
+
class ChannelConverter(Converter["Channel"]):
|
321
|
+
def __init__(self, client: "Client"):
|
322
|
+
self._client = client
|
323
|
+
|
324
|
+
async def convert(self, interaction: "Interaction", value: Any) -> "Channel":
|
325
|
+
if isinstance(value, str): # Assume it's a channel ID
|
326
|
+
channel_id = value
|
327
|
+
# Attempt to get from interaction resolved data first
|
328
|
+
if (
|
329
|
+
interaction.data
|
330
|
+
and interaction.data.resolved
|
331
|
+
and interaction.data.resolved.channels
|
332
|
+
):
|
333
|
+
# Resolved channels are PartialChannel. Client.fetch_channel will get the full typed one.
|
334
|
+
partial_channel = interaction.data.resolved.channels.get(channel_id)
|
335
|
+
if partial_channel:
|
336
|
+
# Client.fetch_channel should handle fetching and parsing to the correct Channel subtype
|
337
|
+
full_channel = await self._client.fetch_channel(partial_channel.id)
|
338
|
+
if full_channel:
|
339
|
+
return full_channel
|
340
|
+
# If fetch_channel returns None even with a resolved ID, it's an issue.
|
341
|
+
raise AppCommandOptionConversionError(
|
342
|
+
f"Failed to fetch full channel for resolved ID '{channel_id}'.",
|
343
|
+
option_name="channel",
|
344
|
+
original_value=value,
|
345
|
+
)
|
346
|
+
|
347
|
+
# Fallback to fetching directly if not in resolved or if resolved fetch failed
|
348
|
+
try:
|
349
|
+
channel = await self._client.fetch_channel(
|
350
|
+
channel_id
|
351
|
+
) # fetch_channel handles parsing
|
352
|
+
if channel:
|
353
|
+
return channel
|
354
|
+
raise AppCommandOptionConversionError(
|
355
|
+
f"Channel with ID '{channel_id}' not found.",
|
356
|
+
option_name="channel",
|
357
|
+
original_value=value,
|
358
|
+
)
|
359
|
+
except Exception as e:
|
360
|
+
raise AppCommandOptionConversionError(
|
361
|
+
f"Failed to fetch channel '{channel_id}': {e}",
|
362
|
+
option_name="channel",
|
363
|
+
original_value=value,
|
364
|
+
)
|
365
|
+
# Raw channel data dicts are not typically provided for slash command options.
|
366
|
+
raise AppCommandOptionConversionError(
|
367
|
+
f"Expected a channel ID string, got {type(value).__name__}",
|
368
|
+
option_name="channel",
|
369
|
+
original_value=value,
|
370
|
+
)
|
371
|
+
|
372
|
+
|
373
|
+
class AttachmentConverter(Converter["Attachment"]):
|
374
|
+
def __init__(
|
375
|
+
self, client: "Client"
|
376
|
+
): # Client might be needed for future enhancements or consistency
|
377
|
+
self._client = client
|
378
|
+
|
379
|
+
async def convert(self, interaction: "Interaction", value: Any) -> "Attachment":
|
380
|
+
if isinstance(value, str): # Value is the attachment ID
|
381
|
+
attachment_id = value
|
382
|
+
if (
|
383
|
+
interaction.data
|
384
|
+
and interaction.data.resolved
|
385
|
+
and interaction.data.resolved.attachments
|
386
|
+
):
|
387
|
+
attachment_object = interaction.data.resolved.attachments.get(
|
388
|
+
attachment_id
|
389
|
+
) # This is already an Attachment object
|
390
|
+
if attachment_object:
|
391
|
+
return (
|
392
|
+
attachment_object # Return the already parsed Attachment object
|
393
|
+
)
|
394
|
+
raise AppCommandOptionConversionError(
|
395
|
+
f"Attachment with ID '{attachment_id}' not found in resolved data.",
|
396
|
+
option_name="attachment",
|
397
|
+
original_value=value,
|
398
|
+
)
|
399
|
+
raise AppCommandOptionConversionError(
|
400
|
+
f"Expected an attachment ID string, got {type(value).__name__}",
|
401
|
+
option_name="attachment",
|
402
|
+
original_value=value,
|
403
|
+
)
|
404
|
+
|
405
|
+
|
406
|
+
# Converters can be registered dynamically using
|
407
|
+
# :meth:`disagreement.ext.app_commands.handler.AppCommandHandler.register_converter`.
|
408
|
+
|
409
|
+
# Mapping from ApplicationCommandOptionType to default converters
|
410
|
+
# This will be used by the AppCommandHandler to automatically apply converters
|
411
|
+
# if no explicit converter is specified for a command option's type hint.
|
412
|
+
DEFAULT_CONVERTERS: Dict[
|
413
|
+
ApplicationCommandOptionType, Callable[..., Converter[Any]]
|
414
|
+
] = { # Changed Callable signature
|
415
|
+
ApplicationCommandOptionType.STRING: StringConverter,
|
416
|
+
ApplicationCommandOptionType.INTEGER: IntegerConverter,
|
417
|
+
ApplicationCommandOptionType.BOOLEAN: BooleanConverter,
|
418
|
+
ApplicationCommandOptionType.NUMBER: NumberConverter,
|
419
|
+
ApplicationCommandOptionType.USER: UserConverter,
|
420
|
+
ApplicationCommandOptionType.CHANNEL: ChannelConverter,
|
421
|
+
ApplicationCommandOptionType.ROLE: RoleConverter,
|
422
|
+
# ApplicationCommandOptionType.MENTIONABLE: MentionableConverter, # Special case, can be User or Role
|
423
|
+
ApplicationCommandOptionType.ATTACHMENT: AttachmentConverter, # Added
|
424
|
+
}
|
425
|
+
|
426
|
+
|
427
|
+
async def run_converters(
|
428
|
+
interaction: "Interaction",
|
429
|
+
param_type: Any, # The type hint of the parameter
|
430
|
+
option_type: ApplicationCommandOptionType, # The Discord option type
|
431
|
+
value: Any,
|
432
|
+
client: "Client", # Needed for model converters
|
433
|
+
) -> Any:
|
434
|
+
"""
|
435
|
+
Runs the appropriate converter for a given parameter type and value.
|
436
|
+
This function will be more complex, handling custom converters, unions, optionals etc.
|
437
|
+
For now, a basic lookup.
|
438
|
+
"""
|
439
|
+
converter_class_factory = DEFAULT_CONVERTERS.get(option_type)
|
440
|
+
if converter_class_factory:
|
441
|
+
# Check if the factory needs the client instance
|
442
|
+
# This is a bit simplistic; a more robust way might involve inspecting __init__ signature
|
443
|
+
# or having converters register their needs.
|
444
|
+
if option_type in [
|
445
|
+
ApplicationCommandOptionType.USER,
|
446
|
+
ApplicationCommandOptionType.CHANNEL, # Anticipating these
|
447
|
+
ApplicationCommandOptionType.ROLE,
|
448
|
+
ApplicationCommandOptionType.MENTIONABLE,
|
449
|
+
ApplicationCommandOptionType.ATTACHMENT,
|
450
|
+
]:
|
451
|
+
converter_instance = converter_class_factory(client=client)
|
452
|
+
else:
|
453
|
+
converter_instance = converter_class_factory()
|
454
|
+
|
455
|
+
return await converter_instance.convert(interaction, value)
|
456
|
+
|
457
|
+
# Fallback for unhandled types or if direct type matching is needed
|
458
|
+
if param_type is str and isinstance(value, str):
|
459
|
+
return value
|
460
|
+
if param_type is int and isinstance(value, int):
|
461
|
+
return value
|
462
|
+
if param_type is bool and isinstance(value, bool):
|
463
|
+
return value
|
464
|
+
if param_type is float and isinstance(value, (float, int)):
|
465
|
+
return float(value)
|
466
|
+
|
467
|
+
# If no specific converter, and it's not a basic type match, raise error or return raw
|
468
|
+
# For now, let's raise if no converter found for a specific option type
|
469
|
+
if option_type in DEFAULT_CONVERTERS: # Should have been handled
|
470
|
+
pass # This path implies a logic error above or missing converter in DEFAULT_CONVERTERS
|
471
|
+
|
472
|
+
# If it's a model type but no converter yet, this will need to be handled
|
473
|
+
# e.g. if param_type is User and option_type is ApplicationCommandOptionType.USER
|
474
|
+
|
475
|
+
raise AppCommandOptionConversionError(
|
476
|
+
f"No suitable converter found for option type {option_type.name} "
|
477
|
+
f"with value '{value}' to target type {param_type.__name__ if hasattr(param_type, '__name__') else param_type}"
|
478
|
+
)
|