|
9 | 9 | from ...api.models.guild import Guild
|
10 | 10 | from ...api.models.member import Member
|
11 | 11 | from ...api.models.message import Attachment
|
12 |
| -from ...api.models.misc import File, Image, Snowflake |
| 12 | +from ...api.models.misc import Snowflake |
13 | 13 | from ...api.models.role import Role
|
14 | 14 | from ...api.models.user import User
|
15 | 15 | from ..enums import ApplicationCommandType, Locale, OptionType, PermissionType
|
@@ -215,66 +215,73 @@ class ApplicationCommand(DictSerializerMixin):
|
215 | 215 |
|
216 | 216 |
|
217 | 217 | def option(
|
218 |
| - option_type: OptionType, |
| 218 | + description: str = "No description set", |
219 | 219 | /,
|
220 |
| - name: str, |
221 |
| - description: Optional[str] = "No description set", |
222 | 220 | **kwargs,
|
223 | 221 | ) -> Callable[[Callable[..., Awaitable]], Callable[..., Awaitable]]:
|
224 | 222 | r"""
|
225 | 223 | A decorator for adding options to a command.
|
226 | 224 |
|
| 225 | + The ``type`` and ``name`` of the option are defaulted to the parameter's typehint and name. |
| 226 | +
|
| 227 | + When the ``name`` of the option differs from the parameter name, |
| 228 | + the ``converter`` field will default to the name of the parameter. |
| 229 | +
|
227 | 230 | The structure of an option:
|
228 | 231 |
|
229 | 232 | .. code-block:: python
|
230 | 233 |
|
231 | 234 | @client.command()
|
232 |
| - @interactions.option(str, name="opt", ...) |
| 235 | + @interactions.option("description (optional)") # kwargs are optional, same as Option |
233 | 236 | async def my_command(ctx, opt: str):
|
234 | 237 | ...
|
235 | 238 |
|
236 |
| - :param option_type: The type of the option. |
237 |
| - :type option_type: OptionType |
238 |
| - :param name: The name of the option. |
239 |
| - :type name: str |
240 |
| - :param description?: The description of the option. Defaults to ``"No description set"``. |
| 239 | + :param description?: The description of the option. Defaults to "No description set". |
241 | 240 | :type description?: str
|
242 |
| - :param \**kwargs: The keyword arguments of the option, same as :class:`Option`. |
243 |
| - :type \**kwargs: dict |
| 241 | + :param \**kwargs?: The keyword arguments of the option, same as :class:`Option`. |
| 242 | + :type \**kwargs?: dict |
244 | 243 | """
|
245 |
| - if option_type in (str, int, float, bool): |
246 |
| - if option_type is str: |
247 |
| - option_type = OptionType.STRING |
248 |
| - elif option_type is int: |
249 |
| - option_type = OptionType.INTEGER |
250 |
| - elif option_type is float: |
251 |
| - option_type = OptionType.NUMBER |
252 |
| - elif option_type is bool: |
253 |
| - option_type = OptionType.BOOLEAN |
254 |
| - elif option_type in (Member, User): |
255 |
| - option_type = OptionType.USER |
256 |
| - elif option_type is Channel: |
257 |
| - option_type = OptionType.CHANNEL |
258 |
| - elif option_type is Role: |
259 |
| - option_type = OptionType.ROLE |
260 |
| - elif option_type in (Attachment, File, Image): |
261 |
| - option_type = OptionType.ATTACHMENT |
262 |
| - |
263 |
| - option: Option = Option( |
264 |
| - type=option_type, |
265 |
| - name=name, |
266 |
| - description=description, |
267 |
| - **kwargs, |
268 |
| - ) |
269 | 244 |
|
270 | 245 | def decorator(coro: Callable[..., Awaitable]) -> Callable[..., Awaitable]:
|
271 |
| - nonlocal option |
| 246 | + parameters = list(signature(coro).parameters.values()) |
| 247 | + |
| 248 | + if not hasattr(coro, "_options") or not isinstance(coro._options, list): |
| 249 | + coro._options = [] |
| 250 | + |
| 251 | + param = parameters[-1 - len(coro._options)] |
272 | 252 |
|
273 |
| - if hasattr(coro, "_options") and isinstance(coro._options, list): |
274 |
| - coro._options.insert(0, option) |
275 |
| - else: |
276 |
| - coro._options = [option] |
| 253 | + option_type = kwargs.get("type", param.annotation) |
| 254 | + name = kwargs.pop("name", param.name) |
| 255 | + if name != param.name: |
| 256 | + kwargs["converter"] = param.name |
277 | 257 |
|
| 258 | + if option_type is param.empty: |
| 259 | + raise LibraryException( |
| 260 | + code=12, |
| 261 | + message=f"No type specified for option '{name}'.", |
| 262 | + ) |
| 263 | + |
| 264 | + option_types = { |
| 265 | + str: OptionType.STRING, |
| 266 | + int: OptionType.INTEGER, |
| 267 | + bool: OptionType.BOOLEAN, |
| 268 | + User: OptionType.USER, |
| 269 | + Member: OptionType.USER, |
| 270 | + Channel: OptionType.CHANNEL, |
| 271 | + Role: OptionType.ROLE, |
| 272 | + float: OptionType.NUMBER, |
| 273 | + Attachment: OptionType.ATTACHMENT, |
| 274 | + } |
| 275 | + option_type = option_types.get(option_type, option_type) |
| 276 | + |
| 277 | + _option = Option( |
| 278 | + type=option_type, |
| 279 | + name=name, |
| 280 | + description=kwargs.pop("description", description), |
| 281 | + required=kwargs.pop("required", param.default is param.empty), |
| 282 | + **kwargs, |
| 283 | + ) |
| 284 | + coro._options.insert(0, _option) |
278 | 285 | return coro
|
279 | 286 |
|
280 | 287 | return decorator
|
|
0 commit comments