hikari-arc 1.3.2__tar.gz → 1.3.4__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.
Files changed (80) hide show
  1. {hikari_arc-1.3.2/hikari_arc.egg-info → hikari_arc-1.3.4}/PKG-INFO +5 -5
  2. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/abc/client.py +4 -4
  3. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/abc/command.py +2 -9
  4. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/internal/about.py +1 -1
  5. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/utils/hooks/basic.py +1 -3
  6. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/dev_requirements.txt +3 -3
  7. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/doc_requirements.txt +1 -1
  8. {hikari_arc-1.3.2 → hikari_arc-1.3.4/hikari_arc.egg-info}/PKG-INFO +5 -5
  9. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/hikari_arc.egg-info/SOURCES.txt +1 -0
  10. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/hikari_arc.egg-info/requires.txt +4 -4
  11. hikari_arc-1.3.4/tests/test_command.py +319 -0
  12. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/LICENSE +0 -0
  13. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/MANIFEST.in +0 -0
  14. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/README.md +0 -0
  15. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/__init__.py +0 -0
  16. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/__main__.py +0 -0
  17. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/abc/__init__.py +0 -0
  18. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/abc/concurrency_limiting.py +0 -0
  19. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/abc/error_handler.py +0 -0
  20. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/abc/hookable.py +0 -0
  21. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/abc/limiter.py +0 -0
  22. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/abc/option.py +0 -0
  23. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/abc/plugin.py +0 -0
  24. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/client.py +0 -0
  25. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/command/__init__.py +0 -0
  26. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/command/message.py +0 -0
  27. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/command/option/__init__.py +0 -0
  28. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/command/option/attachment.py +0 -0
  29. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/command/option/bool.py +0 -0
  30. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/command/option/channel.py +0 -0
  31. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/command/option/custom/__init__.py +0 -0
  32. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/command/option/custom/color.py +0 -0
  33. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/command/option/custom/member.py +0 -0
  34. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/command/option/float.py +0 -0
  35. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/command/option/int.py +0 -0
  36. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/command/option/mentionable.py +0 -0
  37. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/command/option/role.py +0 -0
  38. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/command/option/str.py +0 -0
  39. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/command/option/user.py +0 -0
  40. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/command/slash.py +0 -0
  41. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/command/user.py +0 -0
  42. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/context/__init__.py +0 -0
  43. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/context/autocomplete.py +0 -0
  44. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/context/base.py +0 -0
  45. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/errors.py +0 -0
  46. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/events.py +0 -0
  47. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/ext/__init__.py +0 -0
  48. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/extension.py +0 -0
  49. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/internal/__init__.py +0 -0
  50. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/internal/deprecation.py +0 -0
  51. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/internal/options.py +0 -0
  52. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/internal/sigparse.py +0 -0
  53. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/internal/sync.py +0 -0
  54. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/internal/types.py +0 -0
  55. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/internal/version.py +0 -0
  56. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/locale.py +0 -0
  57. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/plugin.py +0 -0
  58. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/py.typed +0 -0
  59. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/utils/__init__.py +0 -0
  60. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/utils/concurrency_limiter.py +0 -0
  61. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/utils/hooks/__init__.py +0 -0
  62. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/utils/hooks/limiters.py +0 -0
  63. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/utils/loops.py +0 -0
  64. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/arc/utils/ratelimiter.py +0 -0
  65. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/cron_requirements.txt +0 -0
  66. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/hikari_arc.egg-info/dependency_links.txt +0 -0
  67. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/hikari_arc.egg-info/not-zip-safe +0 -0
  68. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/hikari_arc.egg-info/top_level.txt +0 -0
  69. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/pyproject.toml +0 -0
  70. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/requirements.txt +0 -0
  71. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/rest_requirements.txt +0 -0
  72. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/setup.cfg +0 -0
  73. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/setup.py +0 -0
  74. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/tests/test_client.py +0 -0
  75. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/tests/test_context_command.py +0 -0
  76. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/tests/test_di.py +0 -0
  77. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/tests/test_inheritance.py +0 -0
  78. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/tests/test_options.py +0 -0
  79. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/tests/test_sigparse.py +0 -0
  80. {hikari_arc-1.3.2 → hikari_arc-1.3.4}/tests/test_slash.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hikari-arc
3
- Version: 1.3.2
3
+ Version: 1.3.4
4
4
  Summary: A command handler for hikari with a focus on type-safety and correctness.
5
5
  Home-page: https://github.com/hypergonial/hikari-arc
6
6
  Author: hypergonial
@@ -28,17 +28,17 @@ Requires-Dist: alluka<0.4,>=0.3.0
28
28
  Requires-Dist: attrs>=23.1
29
29
  Requires-Dist: colorama; sys_platform == "win32"
30
30
  Provides-Extra: docs
31
- Requires-Dist: mkdocs-material[imaging]~=9.5.24; extra == "docs"
31
+ Requires-Dist: mkdocs-material[imaging]~=9.5.25; extra == "docs"
32
32
  Requires-Dist: mkdocs~=1.6.0; extra == "docs"
33
33
  Requires-Dist: mkdocstrings-python~=1.10.3; extra == "docs"
34
34
  Requires-Dist: black~=24.4.2; extra == "docs"
35
35
  Requires-Dist: griffe-inherited-docstrings~=1.0.0; extra == "docs"
36
36
  Requires-Dist: mkdocs-glightbox~=0.4.0; extra == "docs"
37
37
  Provides-Extra: dev
38
- Requires-Dist: ruff==0.4.5; extra == "dev"
39
- Requires-Dist: pyright==1.1.364; extra == "dev"
38
+ Requires-Dist: ruff==0.4.6; extra == "dev"
39
+ Requires-Dist: pyright==1.1.365; extra == "dev"
40
40
  Requires-Dist: nox==2024.4.15; extra == "dev"
41
- Requires-Dist: typing_extensions==4.11.0; extra == "dev"
41
+ Requires-Dist: typing_extensions==4.12.0; extra == "dev"
42
42
  Requires-Dist: pytest==8.2.1; extra == "dev"
43
43
  Requires-Dist: pytest-asyncio==0.23.7; extra == "dev"
44
44
  Requires-Dist: slotscheck==0.19.0; extra == "dev"
@@ -333,10 +333,10 @@ class Client(t.Generic[AppT], abc.ABC):
333
333
  inj_ctx = alluka.OverridingContext.from_client(self.injector)
334
334
 
335
335
  for hook in self._injection_hooks:
336
- if inspect.iscoroutinefunction(hook):
337
- await hook(ctx, inj_ctx)
338
- else:
339
- hook(ctx, inj_ctx)
336
+ res = hook(ctx, inj_ctx)
337
+
338
+ if inspect.isawaitable(res):
339
+ await res
340
340
  return inj_ctx
341
341
 
342
342
  def _provide_command_locale(self, request: CommandLocaleRequest) -> LocaleResponse:
@@ -2,7 +2,6 @@ from __future__ import annotations
2
2
 
3
3
  import abc
4
4
  import asyncio
5
- import inspect
6
5
  import typing as t
7
6
 
8
7
  import attr
@@ -549,10 +548,7 @@ class CommandBase(
549
548
  try:
550
549
  hooks = command._resolve_hooks()
551
550
  for hook in hooks:
552
- if inspect.iscoroutinefunction(hook):
553
- res = await ctx._injection_ctx.call_with_async_di(hook, ctx)
554
- else:
555
- res = ctx._injection_ctx.call_with_di(hook, ctx)
551
+ res = await ctx._injection_ctx.call_with_async_di(hook, ctx)
556
552
 
557
553
  res = t.cast(HookResult | None, res)
558
554
 
@@ -569,10 +565,7 @@ class CommandBase(
569
565
  try:
570
566
  post_hooks = command._resolve_post_hooks()
571
567
  for hook in post_hooks:
572
- if inspect.iscoroutinefunction(hook):
573
- await ctx._injection_ctx.call_with_async_di(hook, ctx)
574
- else:
575
- ctx._injection_ctx.call_with_di(hook, ctx)
568
+ await ctx._injection_ctx.call_with_async_di(hook, ctx)
576
569
  except Exception as e:
577
570
  await command._handle_exception(ctx, e)
578
571
  finally:
@@ -5,7 +5,7 @@ __author_email__: t.Final[str] = "git@hypergonial.com"
5
5
  __maintainer__: t.Final[str] = "hypergonial"
6
6
  __license__: t.Final[str] = "MIT"
7
7
  __url__: t.Final[str] = "https://github.com/hypergonial/hikari-arc"
8
- __version__: t.Final[str] = "1.3.2"
8
+ __version__: t.Final[str] = "1.3.4"
9
9
 
10
10
  # MIT License
11
11
  #
@@ -5,6 +5,7 @@ import typing as t
5
5
  import hikari
6
6
 
7
7
  from arc.abc.hookable import HookResult
8
+ from arc.context import Context # noqa: TCH001 Needed for DI to work
8
9
  from arc.errors import (
9
10
  BotMissingPermissionsError,
10
11
  DMOnlyError,
@@ -13,9 +14,6 @@ from arc.errors import (
13
14
  NotOwnerError,
14
15
  )
15
16
 
16
- if t.TYPE_CHECKING:
17
- from arc.context import Context
18
-
19
17
 
20
18
  def guild_only(ctx: Context[t.Any]) -> HookResult:
21
19
  """A pre-execution hook that aborts the execution of a command if it is invoked outside of a guild.
@@ -1,7 +1,7 @@
1
- ruff==0.4.5
2
- pyright==1.1.364
1
+ ruff==0.4.6
2
+ pyright==1.1.365
3
3
  nox==2024.4.15
4
- typing_extensions==4.11.0
4
+ typing_extensions==4.12.0
5
5
  pytest==8.2.1
6
6
  pytest-asyncio==0.23.7
7
7
  slotscheck==0.19.0
@@ -1,4 +1,4 @@
1
- mkdocs-material[imaging]~=9.5.24
1
+ mkdocs-material[imaging]~=9.5.25
2
2
  mkdocs~=1.6.0
3
3
  mkdocstrings-python~=1.10.3
4
4
  black~=24.4.2
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hikari-arc
3
- Version: 1.3.2
3
+ Version: 1.3.4
4
4
  Summary: A command handler for hikari with a focus on type-safety and correctness.
5
5
  Home-page: https://github.com/hypergonial/hikari-arc
6
6
  Author: hypergonial
@@ -28,17 +28,17 @@ Requires-Dist: alluka<0.4,>=0.3.0
28
28
  Requires-Dist: attrs>=23.1
29
29
  Requires-Dist: colorama; sys_platform == "win32"
30
30
  Provides-Extra: docs
31
- Requires-Dist: mkdocs-material[imaging]~=9.5.24; extra == "docs"
31
+ Requires-Dist: mkdocs-material[imaging]~=9.5.25; extra == "docs"
32
32
  Requires-Dist: mkdocs~=1.6.0; extra == "docs"
33
33
  Requires-Dist: mkdocstrings-python~=1.10.3; extra == "docs"
34
34
  Requires-Dist: black~=24.4.2; extra == "docs"
35
35
  Requires-Dist: griffe-inherited-docstrings~=1.0.0; extra == "docs"
36
36
  Requires-Dist: mkdocs-glightbox~=0.4.0; extra == "docs"
37
37
  Provides-Extra: dev
38
- Requires-Dist: ruff==0.4.5; extra == "dev"
39
- Requires-Dist: pyright==1.1.364; extra == "dev"
38
+ Requires-Dist: ruff==0.4.6; extra == "dev"
39
+ Requires-Dist: pyright==1.1.365; extra == "dev"
40
40
  Requires-Dist: nox==2024.4.15; extra == "dev"
41
- Requires-Dist: typing_extensions==4.11.0; extra == "dev"
41
+ Requires-Dist: typing_extensions==4.12.0; extra == "dev"
42
42
  Requires-Dist: pytest==8.2.1; extra == "dev"
43
43
  Requires-Dist: pytest-asyncio==0.23.7; extra == "dev"
44
44
  Requires-Dist: slotscheck==0.19.0; extra == "dev"
@@ -69,6 +69,7 @@ hikari_arc.egg-info/not-zip-safe
69
69
  hikari_arc.egg-info/requires.txt
70
70
  hikari_arc.egg-info/top_level.txt
71
71
  tests/test_client.py
72
+ tests/test_command.py
72
73
  tests/test_context_command.py
73
74
  tests/test_di.py
74
75
  tests/test_inheritance.py
@@ -10,16 +10,16 @@ croniter==2.0.5
10
10
  types-croniter==2.0.0.20240423
11
11
 
12
12
  [dev]
13
- ruff==0.4.5
14
- pyright==1.1.364
13
+ ruff==0.4.6
14
+ pyright==1.1.365
15
15
  nox==2024.4.15
16
- typing_extensions==4.11.0
16
+ typing_extensions==4.12.0
17
17
  pytest==8.2.1
18
18
  pytest-asyncio==0.23.7
19
19
  slotscheck==0.19.0
20
20
 
21
21
  [docs]
22
- mkdocs-material[imaging]~=9.5.24
22
+ mkdocs-material[imaging]~=9.5.25
23
23
  mkdocs~=1.6.0
24
24
  mkdocstrings-python~=1.10.3
25
25
  black~=24.4.2
@@ -0,0 +1,319 @@
1
+ import datetime
2
+
3
+ import hikari
4
+ import pytest
5
+ from hikari.users import UserImpl
6
+ from mock_client import MockClient, MockContext, MockPlugin
7
+
8
+ import arc
9
+
10
+ client = MockClient(hikari.GatewayBot(token="amongus"))
11
+
12
+
13
+ @pytest.fixture
14
+ def app() -> hikari.GatewayBot:
15
+ return build_app()
16
+
17
+
18
+ def build_app() -> hikari.GatewayBot:
19
+ return hikari.GatewayBot(token="amongus")
20
+
21
+
22
+ def build_user(app: hikari.GatewayBot, id: hikari.Snowflakeish = 123456789) -> hikari.User:
23
+ return UserImpl(
24
+ app=app,
25
+ id=hikari.Snowflake(id),
26
+ avatar_hash=None,
27
+ banner_hash=None,
28
+ global_name="Padoru",
29
+ accent_color=None,
30
+ flags=hikari.UserFlag.NONE,
31
+ discriminator="1234",
32
+ is_bot=False,
33
+ is_system=False,
34
+ username="Padoru",
35
+ )
36
+
37
+
38
+ def build_member(
39
+ app: hikari.GatewayBot,
40
+ id: hikari.Snowflakeish = 123456789,
41
+ *,
42
+ role_ids: list[hikari.Snowflake] | None = None,
43
+ permissions: hikari.Permissions | None = None,
44
+ ) -> hikari.InteractionMember:
45
+ return hikari.InteractionMember(
46
+ guild_id=hikari.Snowflake(123456789),
47
+ is_deaf=hikari.UNDEFINED,
48
+ is_mute=hikari.UNDEFINED,
49
+ is_pending=False,
50
+ nickname=None,
51
+ raw_communication_disabled_until=None,
52
+ role_ids=role_ids or [],
53
+ guild_avatar_hash=None,
54
+ joined_at=datetime.datetime(2021, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc),
55
+ permissions=permissions or hikari.Permissions.NONE,
56
+ premium_since=None,
57
+ user=build_user(app, id),
58
+ )
59
+
60
+
61
+ def build_inter(
62
+ app: hikari.GatewayBot,
63
+ *,
64
+ cmd_name: str,
65
+ options: list[hikari.CommandInteractionOption] | None = None,
66
+ resolved: hikari.ResolvedOptionData | None = None,
67
+ author_id: hikari.Snowflakeish = 123456789,
68
+ author_role_ids: list[hikari.Snowflake] | None = None,
69
+ author_perms: hikari.Permissions | None = None,
70
+ ) -> hikari.CommandInteraction:
71
+ parts = cmd_name.split(" ")
72
+
73
+ match len(parts):
74
+ case 1:
75
+ pass
76
+ case 2:
77
+ options = [
78
+ hikari.CommandInteractionOption(
79
+ name=parts[1], type=hikari.OptionType.SUB_COMMAND, value=None, options=options
80
+ )
81
+ ]
82
+ case 3:
83
+ options = [
84
+ hikari.CommandInteractionOption(
85
+ name=parts[1],
86
+ type=hikari.OptionType.SUB_COMMAND_GROUP,
87
+ value=None,
88
+ options=[
89
+ hikari.CommandInteractionOption(
90
+ name=parts[2], type=hikari.OptionType.SUB_COMMAND, value=None, options=options
91
+ )
92
+ ],
93
+ )
94
+ ]
95
+ case _:
96
+ raise ValueError("Invalid command name")
97
+
98
+ return hikari.CommandInteraction(
99
+ app=app,
100
+ id=hikari.Snowflake(123456789),
101
+ application_id=hikari.Snowflake(123456789),
102
+ command_id=hikari.Snowflake(123456789),
103
+ command_name=parts[0],
104
+ command_type=hikari.CommandType.SLASH,
105
+ entitlements=[],
106
+ app_permissions=hikari.Permissions.all_permissions(),
107
+ options=options,
108
+ resolved=resolved,
109
+ type=hikari.InteractionType.APPLICATION_COMMAND,
110
+ token="padoru padoru",
111
+ version=1,
112
+ channel_id=hikari.Snowflake(123456789),
113
+ guild_id=hikari.Snowflake(123456789),
114
+ guild_locale="en-US",
115
+ user=build_user(app, author_id),
116
+ member=build_member(app, author_id, role_ids=author_role_ids, permissions=author_perms),
117
+ locale="en-US",
118
+ )
119
+
120
+
121
+ class PluginCanHandleError(Exception):
122
+ pass
123
+
124
+
125
+ class GroupCanHandleError(Exception):
126
+ pass
127
+
128
+
129
+ class SubgroupCanHandleError(Exception):
130
+ pass
131
+
132
+
133
+ class CommandCanHandleError(Exception):
134
+ pass
135
+
136
+
137
+ @client.include
138
+ @arc.slash_command("ping")
139
+ async def ping(ctx: MockContext) -> None:
140
+ await ctx.respond("Pong!")
141
+
142
+
143
+ @client.include
144
+ @arc.with_hook(arc.owner_only)
145
+ @arc.slash_command("admin_ping")
146
+ async def ping_with_hook(ctx: MockContext) -> None:
147
+ await ctx.respond("Pong!")
148
+
149
+
150
+ @client.include
151
+ @arc.with_hook(arc.owner_only)
152
+ @arc.slash_command("admin_ping_err")
153
+ async def ping_with_hook_err(ctx: MockContext) -> None:
154
+ await ctx.respond("Pong!")
155
+
156
+
157
+ @ping_with_hook_err.set_error_handler
158
+ async def ping_with_hook_err_handler(ctx: MockContext, error: Exception) -> None:
159
+ if isinstance(error, arc.NotOwnerError):
160
+ await ctx.respond("❌ You are not the owner of the bot.")
161
+
162
+
163
+ @client.include
164
+ @arc.slash_command("sum")
165
+ async def sum(ctx: MockContext, a: arc.Option[int, arc.IntParams()], b: arc.Option[int, arc.IntParams()]) -> None:
166
+ await ctx.respond(f"Sum: {a + b}")
167
+
168
+
169
+ plugin = MockPlugin("test")
170
+ group = plugin.include_slash_group("group")
171
+ subgroup = group.include_subgroup("subgroup")
172
+
173
+ client.add_plugin(plugin)
174
+
175
+
176
+ @subgroup.include
177
+ @arc.slash_subcommand("nested")
178
+ async def nested(ctx: MockContext) -> None:
179
+ match ctx.author.id:
180
+ case 1:
181
+ raise CommandCanHandleError
182
+ case 2:
183
+ raise SubgroupCanHandleError
184
+ case 3:
185
+ raise GroupCanHandleError
186
+ case 4:
187
+ raise PluginCanHandleError
188
+ case 5:
189
+ raise Exception
190
+ case _:
191
+ await ctx.respond("Nested command!")
192
+
193
+
194
+ @nested.set_error_handler
195
+ async def nested_error_handler(ctx: MockContext, error: Exception) -> None:
196
+ if isinstance(error, CommandCanHandleError):
197
+ await ctx.respond("Command handled error")
198
+ return
199
+ raise error
200
+
201
+
202
+ @subgroup.set_error_handler
203
+ async def subgroup_error_handler(ctx: MockContext, error: Exception) -> None:
204
+ if isinstance(error, SubgroupCanHandleError):
205
+ await ctx.respond("Subgroup handled error")
206
+ return
207
+ raise error
208
+
209
+
210
+ @group.set_error_handler
211
+ async def group_error_handler(ctx: MockContext, error: Exception) -> None:
212
+ if isinstance(error, GroupCanHandleError):
213
+ await ctx.respond("Group handled error")
214
+ return
215
+ raise error
216
+
217
+
218
+ @plugin.set_error_handler
219
+ async def plugin_error_handler(ctx: MockContext, error: Exception) -> None:
220
+ if isinstance(error, PluginCanHandleError):
221
+ await ctx.respond("Plugin handled error")
222
+ return
223
+ raise error
224
+
225
+
226
+ @pytest.mark.asyncio
227
+ async def test_ping(app: hikari.GatewayBot) -> None:
228
+ response = await client.push_inter(build_inter(app, cmd_name="ping"))
229
+ assert isinstance(response, hikari.impl.InteractionMessageBuilder)
230
+ assert response.content == "Pong!"
231
+
232
+
233
+ @pytest.mark.asyncio
234
+ async def test_sum(app: hikari.GatewayBot) -> None:
235
+ inter = build_inter(
236
+ app,
237
+ cmd_name="sum",
238
+ options=[
239
+ hikari.CommandInteractionOption(name="a", type=hikari.OptionType.INTEGER, value=3, options=None),
240
+ hikari.CommandInteractionOption(name="b", type=hikari.OptionType.INTEGER, value=2, options=None),
241
+ ],
242
+ )
243
+ response = await client.push_inter(inter)
244
+ assert isinstance(response, hikari.impl.InteractionMessageBuilder)
245
+ assert response.content == "Sum: 5"
246
+
247
+
248
+ @pytest.mark.asyncio
249
+ async def test_admin_ping(app: hikari.GatewayBot) -> None:
250
+ inter = build_inter(app, cmd_name="admin_ping")
251
+ response = await client.push_inter(inter)
252
+ assert isinstance(response, hikari.impl.InteractionMessageBuilder)
253
+ assert response.content == "Pong!"
254
+
255
+
256
+ @pytest.mark.asyncio
257
+ async def test_admin_ping_unprivileged(app: hikari.GatewayBot) -> None:
258
+ inter = build_inter(app, author_id=987654321, cmd_name="admin_ping")
259
+ response = await client.push_inter(inter)
260
+ assert isinstance(response, hikari.impl.InteractionMessageBuilder)
261
+ # Unhandled error
262
+ assert response.content == "❌ Something went wrong. Please contact the bot developer."
263
+
264
+
265
+ @pytest.mark.asyncio
266
+ async def test_admin_ping_errhandler(app: hikari.GatewayBot) -> None:
267
+ inter = build_inter(app, author_id=987654321, cmd_name="admin_ping_err")
268
+ response = await client.push_inter(inter)
269
+ assert isinstance(response, hikari.impl.InteractionMessageBuilder)
270
+ # Handled error
271
+ assert response.content == "❌ You are not the owner of the bot."
272
+
273
+
274
+ @pytest.mark.asyncio
275
+ async def test_nested_errhandler_ok(app: hikari.GatewayBot) -> None:
276
+ inter = build_inter(app, author_id=0, cmd_name="group subgroup nested")
277
+ response = await client.push_inter(inter)
278
+ assert isinstance(response, hikari.impl.InteractionMessageBuilder)
279
+ assert response.content == "Nested command!"
280
+
281
+
282
+ @pytest.mark.asyncio
283
+ async def test_nested_errhandler_cmdhandler(app: hikari.GatewayBot) -> None:
284
+ inter = build_inter(app, author_id=1, cmd_name="group subgroup nested")
285
+ response = await client.push_inter(inter)
286
+ assert isinstance(response, hikari.impl.InteractionMessageBuilder)
287
+ assert response.content == "Command handled error"
288
+
289
+
290
+ @pytest.mark.asyncio
291
+ async def test_nested_errhandler_subghandler(app: hikari.GatewayBot) -> None:
292
+ inter = build_inter(app, author_id=2, cmd_name="group subgroup nested")
293
+ response = await client.push_inter(inter)
294
+ assert isinstance(response, hikari.impl.InteractionMessageBuilder)
295
+ assert response.content == "Subgroup handled error"
296
+
297
+
298
+ @pytest.mark.asyncio
299
+ async def test_nested_errhandler_grphandler(app: hikari.GatewayBot) -> None:
300
+ inter = build_inter(app, author_id=3, cmd_name="group subgroup nested")
301
+ response = await client.push_inter(inter)
302
+ assert isinstance(response, hikari.impl.InteractionMessageBuilder)
303
+ assert response.content == "Group handled error"
304
+
305
+
306
+ @pytest.mark.asyncio
307
+ async def test_nested_errhandler_plghandler(app: hikari.GatewayBot) -> None:
308
+ inter = build_inter(app, author_id=4, cmd_name="group subgroup nested")
309
+ response = await client.push_inter(inter)
310
+ assert isinstance(response, hikari.impl.InteractionMessageBuilder)
311
+ assert response.content == "Plugin handled error"
312
+
313
+
314
+ @pytest.mark.asyncio
315
+ async def test_nested_errhandler_unhandled(app: hikari.GatewayBot) -> None:
316
+ inter = build_inter(app, author_id=5, cmd_name="group subgroup nested")
317
+ response = await client.push_inter(inter)
318
+ assert isinstance(response, hikari.impl.InteractionMessageBuilder)
319
+ assert response.content == "❌ Something went wrong. Please contact the bot developer."
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
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