modifyself 0.2.4__tar.gz → 0.2.5__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 (51) hide show
  1. {modifyself-0.2.4 → modifyself-0.2.5}/PKG-INFO +1 -1
  2. modifyself-0.2.5/modifyself/interactions.py +216 -0
  3. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself.egg-info/PKG-INFO +1 -1
  4. {modifyself-0.2.4 → modifyself-0.2.5}/pyproject.toml +1 -1
  5. modifyself-0.2.4/modifyself/interactions.py +0 -0
  6. {modifyself-0.2.4 → modifyself-0.2.5}/LICENSE +0 -0
  7. {modifyself-0.2.4 → modifyself-0.2.5}/README.md +0 -0
  8. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/__init__.py +0 -0
  9. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/activity.py +0 -0
  10. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/client.py +0 -0
  11. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/commands/__init__.py +0 -0
  12. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/commands/checks.py +0 -0
  13. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/commands/cog.py +0 -0
  14. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/commands/context.py +0 -0
  15. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/commands/converters.py +0 -0
  16. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/commands/core.py +0 -0
  17. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/components.py +0 -0
  18. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/core/bitfield.py +0 -0
  19. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/core/enums.py +0 -0
  20. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/core/mixins.py +0 -0
  21. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/core/snowflake.py +0 -0
  22. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/errors.py +0 -0
  23. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/gateway/__init__.py +0 -0
  24. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/gateway/dispatcher.py +0 -0
  25. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/gateway/heartbeat.py +0 -0
  26. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/gateway/websocket.py +0 -0
  27. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/headers.py +0 -0
  28. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/http/__init__.py +0 -0
  29. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/http/client.py +0 -0
  30. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/http/ratelimit.py +0 -0
  31. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/http/route.py +0 -0
  32. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/models/__init__.py +0 -0
  33. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/models/base.py +0 -0
  34. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/models/billing.py +0 -0
  35. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/models/channel.py +0 -0
  36. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/models/guild.py +0 -0
  37. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/models/member.py +0 -0
  38. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/models/message.py +0 -0
  39. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/models/relationship.py +0 -0
  40. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/models/settings.py +0 -0
  41. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/models/user.py +0 -0
  42. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/models/webhook.py +0 -0
  43. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/state.py +0 -0
  44. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/types.py +0 -0
  45. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/utils.py +0 -0
  46. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself/voice.py +0 -0
  47. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself.egg-info/SOURCES.txt +0 -0
  48. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself.egg-info/dependency_links.txt +0 -0
  49. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself.egg-info/requires.txt +0 -0
  50. {modifyself-0.2.4 → modifyself-0.2.5}/modifyself.egg-info/top_level.txt +0 -0
  51. {modifyself-0.2.4 → modifyself-0.2.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modifyself
3
- Version: 0.2.4
3
+ Version: 0.2.5
4
4
  Summary: A clean, pythonic Discord self-bot library
5
5
  Author-email: modifyself <modifyself@example.com>
6
6
  License-Expression: MIT
@@ -0,0 +1,216 @@
1
+ """
2
+ Interaction handling (buttons, selects, modals).
3
+ """
4
+
5
+ import json
6
+ from typing import Optional, Dict, Any, List, Union, Callable, Awaitable
7
+ from enum import IntEnum
8
+ from dataclasses import dataclass, field
9
+
10
+ from .models.message import Message
11
+ from .models.user import User
12
+ from .models.member import Member
13
+ from .components import ComponentType, ButtonStyle, TextInputStyle, ActionRow, Component
14
+
15
+ class InteractionType(IntEnum):
16
+ PING = 1
17
+ APPLICATION_COMMAND = 2
18
+ MESSAGE_COMPONENT = 3
19
+ APPLICATION_COMMAND_AUTOCOMPLETE = 4
20
+ MODAL_SUBMIT = 5
21
+
22
+ class InteractionCallbackType(IntEnum):
23
+ PONG = 1
24
+ CHANNEL_MESSAGE_WITH_SOURCE = 4
25
+ DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE = 5
26
+ DEFERRED_UPDATE_MESSAGE = 6
27
+ UPDATE_MESSAGE = 7
28
+ APPLICATION_COMMAND_AUTOCOMPLETE_RESULT = 8
29
+ MODAL = 9
30
+
31
+ class Interaction:
32
+ """Represents a Discord interaction."""
33
+
34
+ def __init__(self, state, data: dict):
35
+ self._state = state
36
+ self.id = int(data["id"])
37
+ self.application_id = int(data["application_id"])
38
+ self.type = InteractionType(data["type"])
39
+ self.token = data["token"]
40
+ self.version = data["version"]
41
+ self.guild_id = int(data["guild_id"]) if data.get("guild_id") else None
42
+ self.channel_id = int(data["channel_id"]) if data.get("channel_id") else None
43
+
44
+ # Message
45
+ self.message = None
46
+ if data.get("message"):
47
+ self.message = Message(state=self._state, data=data["message"])
48
+
49
+ # Member/User
50
+ self.member = None
51
+ self.user = None
52
+ if data.get("member"):
53
+ self.member = Member(state=self._state, data=data["member"], guild_id=self.guild_id)
54
+ self.user = self.member.user
55
+ elif data.get("user"):
56
+ self.user = User(state=self._state, data=data["user"])
57
+
58
+ # Data
59
+ self.data = data.get("data", {})
60
+ self.custom_id = self.data.get("custom_id")
61
+
62
+ # Values (for selects)
63
+ self.values = self.data.get("values")
64
+
65
+ # Component type
66
+ self.component_type = self.data.get("component_type")
67
+
68
+ @property
69
+ def author(self):
70
+ """The user who triggered the interaction."""
71
+ return self.user or (self.member.user if self.member else None)
72
+
73
+ async def respond(
74
+ self,
75
+ content: Optional[str] = None,
76
+ embeds: Optional[List[Dict[str, Any]]] = None,
77
+ components: Optional[List[ActionRow]] = None,
78
+ **kwargs,
79
+ ) -> Dict[str, Any]:
80
+ """Respond to the interaction."""
81
+ payload = {
82
+ "type": InteractionCallbackType.CHANNEL_MESSAGE_WITH_SOURCE,
83
+ "data": {},
84
+ }
85
+ if content is not None:
86
+ payload["data"]["content"] = content
87
+ if embeds is not None:
88
+ payload["data"]["embeds"] = embeds
89
+ if components is not None:
90
+ payload["data"]["components"] = [c.to_dict() for c in components]
91
+ payload["data"].update(kwargs)
92
+
93
+ await self._state.http.request(
94
+ method="POST",
95
+ url=f"/interactions/{self.id}/{self.token}/callback",
96
+ json=payload,
97
+ )
98
+ return payload
99
+
100
+ async def update(
101
+ self,
102
+ content: Optional[str] = None,
103
+ embeds: Optional[List[Dict[str, Any]]] = None,
104
+ components: Optional[List[ActionRow]] = None,
105
+ **kwargs,
106
+ ) -> Dict[str, Any]:
107
+ """Update the message that the interaction was triggered from."""
108
+ payload = {
109
+ "type": InteractionCallbackType.UPDATE_MESSAGE,
110
+ "data": {},
111
+ }
112
+ if content is not None:
113
+ payload["data"]["content"] = content
114
+ if embeds is not None:
115
+ payload["data"]["embeds"] = embeds
116
+ if components is not None:
117
+ payload["data"]["components"] = [c.to_dict() for c in components]
118
+ payload["data"].update(kwargs)
119
+
120
+ await self._state.http.request(
121
+ method="POST",
122
+ url=f"/interactions/{self.id}/{self.token}/callback",
123
+ json=payload,
124
+ )
125
+ return payload
126
+
127
+ async def defer(self, ephemeral: bool = False) -> None:
128
+ """Defer the interaction response."""
129
+ payload = {
130
+ "type": InteractionCallbackType.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE,
131
+ "data": {"flags": 64 if ephemeral else 0},
132
+ }
133
+ await self._state.http.request(
134
+ method="POST",
135
+ url=f"/interactions/{self.id}/{self.token}/callback",
136
+ json=payload,
137
+ )
138
+
139
+ async def defer_update(self) -> None:
140
+ """Defer the interaction response for message updates."""
141
+ payload = {
142
+ "type": InteractionCallbackType.DEFERRED_UPDATE_MESSAGE,
143
+ "data": {},
144
+ }
145
+ await self._state.http.request(
146
+ method="POST",
147
+ url=f"/interactions/{self.id}/{self.token}/callback",
148
+ json=payload,
149
+ )
150
+
151
+ async def show_modal(self, modal) -> None:
152
+ """Show a modal to the user."""
153
+ payload = {
154
+ "type": InteractionCallbackType.MODAL,
155
+ "data": modal.to_dict(),
156
+ }
157
+ await self._state.http.request(
158
+ method="POST",
159
+ url=f"/interactions/{self.id}/{self.token}/callback",
160
+ json=payload,
161
+ )
162
+
163
+ async def edit_original_response(
164
+ self,
165
+ content: Optional[str] = None,
166
+ embeds: Optional[List[Dict[str, Any]]] = None,
167
+ components: Optional[List[ActionRow]] = None,
168
+ **kwargs,
169
+ ) -> Dict[str, Any]:
170
+ """Edit the original response message."""
171
+ payload = {}
172
+ if content is not None:
173
+ payload["content"] = content
174
+ if embeds is not None:
175
+ payload["embeds"] = embeds
176
+ if components is not None:
177
+ payload["components"] = [c.to_dict() for c in components]
178
+ payload.update(kwargs)
179
+
180
+ return await self._state.http.request(
181
+ method="PATCH",
182
+ url=f"/webhooks/{self.application_id}/{self.token}/messages/@original",
183
+ json=payload,
184
+ )
185
+
186
+ async def delete_original_response(self) -> None:
187
+ """Delete the original response message."""
188
+ await self._state.http.request(
189
+ method="DELETE",
190
+ url=f"/webhooks/{self.application_id}/{self.token}/messages/@original",
191
+ )
192
+
193
+
194
+ class InteractionHandler:
195
+ """Manages interaction callbacks."""
196
+
197
+ def __init__(self):
198
+ self._handlers: Dict[str, Callable] = {}
199
+
200
+ def on(self, custom_id: str):
201
+ """Decorator to register a handler for a specific custom_id."""
202
+ def decorator(func: Callable[[Interaction], Awaitable[None]]):
203
+ self._handlers[custom_id] = func
204
+ return func
205
+ return decorator
206
+
207
+ async def handle(self, interaction: Interaction) -> bool:
208
+ """Handle an interaction."""
209
+ if interaction.custom_id in self._handlers:
210
+ await self._handlers[interaction.custom_id](interaction)
211
+ return True
212
+ return False
213
+
214
+
215
+ # Global interaction handler instance
216
+ interaction_handler = InteractionHandler()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modifyself
3
- Version: 0.2.4
3
+ Version: 0.2.5
4
4
  Summary: A clean, pythonic Discord self-bot library
5
5
  Author-email: modifyself <modifyself@example.com>
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "modifyself"
7
- version = "0.2.4"
7
+ version = "0.2.5"
8
8
  description = "A clean, pythonic Discord self-bot library"
9
9
  readme = "README.md"
10
10
  license = "MIT"
File without changes
File without changes
File without changes
File without changes