modifyself 0.2.9__tar.gz → 0.3.3__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 (52) hide show
  1. {modifyself-0.2.9 → modifyself-0.3.3}/PKG-INFO +1 -1
  2. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/__init__.py +22 -22
  3. modifyself-0.3.3/modifyself/activity.py +399 -0
  4. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/client.py +1 -73
  5. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/commands/context.py +11 -8
  6. modifyself-0.3.3/modifyself/models/__init__.py +29 -0
  7. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself.egg-info/PKG-INFO +1 -1
  8. {modifyself-0.2.9 → modifyself-0.3.3}/pyproject.toml +1 -1
  9. modifyself-0.2.9/modifyself/activity.py +0 -0
  10. modifyself-0.2.9/modifyself/models/__init__.py +0 -23
  11. {modifyself-0.2.9 → modifyself-0.3.3}/LICENSE +0 -0
  12. {modifyself-0.2.9 → modifyself-0.3.3}/README.md +0 -0
  13. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/commands/__init__.py +0 -0
  14. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/commands/checks.py +0 -0
  15. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/commands/cog.py +0 -0
  16. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/commands/converters.py +0 -0
  17. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/commands/core.py +0 -0
  18. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/components.py +0 -0
  19. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/core/bitfield.py +0 -0
  20. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/core/enums.py +0 -0
  21. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/core/mixins.py +0 -0
  22. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/core/snowflake.py +0 -0
  23. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/errors.py +0 -0
  24. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/gateway/__init__.py +0 -0
  25. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/gateway/dispatcher.py +0 -0
  26. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/gateway/heartbeat.py +0 -0
  27. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/gateway/websocket.py +0 -0
  28. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/headers.py +0 -0
  29. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/http/__init__.py +0 -0
  30. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/http/client.py +0 -0
  31. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/http/ratelimit.py +0 -0
  32. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/http/route.py +0 -0
  33. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/interactions.py +0 -0
  34. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/models/base.py +0 -0
  35. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/models/billing.py +0 -0
  36. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/models/channel.py +0 -0
  37. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/models/guild.py +0 -0
  38. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/models/member.py +0 -0
  39. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/models/message.py +0 -0
  40. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/models/relationship.py +0 -0
  41. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/models/settings.py +0 -0
  42. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/models/user.py +0 -0
  43. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/models/webhook.py +0 -0
  44. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/state.py +0 -0
  45. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/types.py +0 -0
  46. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/utils.py +0 -0
  47. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself/voice.py +0 -0
  48. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself.egg-info/SOURCES.txt +0 -0
  49. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself.egg-info/dependency_links.txt +0 -0
  50. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself.egg-info/requires.txt +0 -0
  51. {modifyself-0.2.9 → modifyself-0.3.3}/modifyself.egg-info/top_level.txt +0 -0
  52. {modifyself-0.2.9 → modifyself-0.3.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modifyself
3
- Version: 0.2.9
3
+ Version: 0.3.3
4
4
  Summary: A clean, pythonic Discord self-bot library
5
5
  Author-email: modifyself <modifyself@example.com>
6
6
  License-Expression: MIT
@@ -1,23 +1,23 @@
1
- \"\"\"
2
- modifyself — a clean, pythonic Discord self-bot library.
3
- \"\"\"
4
-
5
- __version__ = "0.2.9"
6
-
7
- from .client import Client
8
- from .commands.core import command
9
- from .commands.cog import Cog
10
- from .commands.context import Context
11
-
12
- from .models.relationship import Relationship
13
- from .models.billing import PaymentSource, Subscription
14
- from .models.settings import GuildSettings, UserSettings
15
- from .models.webhook import Webhook, WebhookMessage
16
-
17
- from .activity import Activity, ActivityType, ActivityFlags, spotify_activity, youtube_activity, xbox_activity, playstation_activity, crunchyroll_activity, custom_activity, listening_activity, streaming_activity, competing_activity, LOGO_MAP
18
-
19
- from .components import ComponentType, ButtonStyle, TextInputStyle, Button, SelectOption, SelectMenu, ChannelSelect, RoleSelect, MentionableSelect, UserSelect, TextInput, ActionRow, Modal
20
-
21
- from .interactions import Interaction, InteractionType, InteractionCallbackType, InteractionHandler, interaction_handler
22
-
1
+ """
2
+ modifyself ? a clean, pythonic Discord self-bot library.
3
+ """
4
+
5
+ __version__ = "0.3.3"
6
+
7
+ from .client import Client
8
+ from .commands.core import command
9
+ from .commands.cog import Cog
10
+ from .commands.context import Context
11
+
12
+ from .models.relationship import Relationship
13
+ from .models.billing import PaymentSource, Subscription
14
+ from .models.settings import GuildSettings, UserSettings
15
+ from .models.webhook import Webhook, WebhookMessage
16
+
17
+ from .activity import Activity, ActivityType, ActivityFlags, spotify_activity, youtube_activity, xbox_activity, playstation_activity, crunchyroll_activity, custom_activity, listening_activity, streaming_activity, competing_activity, LOGO_MAP
18
+
19
+ from .components import ComponentType, ButtonStyle, TextInputStyle, Button, SelectOption, SelectMenu, ChannelSelect, RoleSelect, MentionableSelect, UserSelect, TextInput, ActionRow, Modal
20
+
21
+ from .interactions import Interaction, InteractionType, InteractionCallbackType, InteractionHandler, interaction_handler
22
+
23
23
  __all__ = ["Client", "command", "Cog", "Context", "Relationship", "PaymentSource", "Subscription", "GuildSettings", "UserSettings", "Webhook", "WebhookMessage", "Activity", "ActivityType", "ActivityFlags", "spotify_activity", "youtube_activity", "xbox_activity", "playstation_activity", "crunchyroll_activity", "custom_activity", "listening_activity", "streaming_activity", "competing_activity", "LOGO_MAP", "ComponentType", "ButtonStyle", "TextInputStyle", "Button", "SelectOption", "SelectMenu", "ChannelSelect", "RoleSelect", "MentionableSelect", "UserSelect", "TextInput", "ActionRow", "Modal", "Interaction", "InteractionType", "InteractionCallbackType", "InteractionHandler", "interaction_handler"]
@@ -0,0 +1,399 @@
1
+ """
2
+ Rich presence and activity types.
3
+ """
4
+
5
+ import time
6
+ from typing import Optional, List, Dict, Any, Union
7
+ from enum import IntEnum
8
+
9
+ class ActivityType(IntEnum):
10
+ PLAYING = 0
11
+ STREAMING = 1
12
+ LISTENING = 2
13
+ WATCHING = 3
14
+ CUSTOM = 4
15
+ COMPETING = 5
16
+
17
+ class ActivityFlags(IntEnum):
18
+ INSTANCE = 1 << 0
19
+ JOIN = 1 << 1
20
+ SPECTATE = 1 << 2
21
+ JOIN_REQUEST = 1 << 3
22
+ SYNC = 1 << 4
23
+ PLAY = 1 << 5
24
+
25
+ class Activity:
26
+ def __init__(
27
+ self,
28
+ type: Union[ActivityType, int] = ActivityType.PLAYING,
29
+ name: str = "",
30
+ url: Optional[str] = None,
31
+ details: Optional[str] = None,
32
+ state: Optional[str] = None,
33
+ timestamps: Optional[Dict[str, int]] = None,
34
+ assets: Optional[Dict[str, str]] = None,
35
+ party: Optional[Dict[str, Any]] = None,
36
+ secrets: Optional[Dict[str, str]] = None,
37
+ instance: bool = False,
38
+ flags: int = 0,
39
+ buttons: Optional[List[str]] = None,
40
+ metadata: Optional[Dict[str, Any]] = None,
41
+ session_id: Optional[str] = None,
42
+ sync_id: Optional[str] = None,
43
+ application_id: Optional[str] = None,
44
+ platform: Optional[str] = None,
45
+ ):
46
+ self.type = type if isinstance(type, ActivityType) else ActivityType(type)
47
+ self.name = name
48
+ self.url = url
49
+ self.details = details
50
+ self.state = state
51
+ self.timestamps = timestamps
52
+ self.assets = assets
53
+ self.party = party
54
+ self.secrets = secrets
55
+ self.instance = instance
56
+ self.flags = flags
57
+ self.buttons = buttons
58
+ self.metadata = metadata
59
+ self.session_id = session_id
60
+ self.sync_id = sync_id
61
+ self.application_id = application_id
62
+ self.platform = platform
63
+
64
+ def to_dict(self) -> dict:
65
+ data = {
66
+ "type": int(self.type),
67
+ "name": self.name[:128],
68
+ }
69
+ if self.url:
70
+ data["url"] = self.url
71
+ if self.details:
72
+ data["details"] = self.details[:128]
73
+ if self.state:
74
+ data["state"] = self.state[:128]
75
+ if self.timestamps:
76
+ data["timestamps"] = self.timestamps
77
+ if self.assets:
78
+ data["assets"] = self.assets
79
+ if self.party:
80
+ data["party"] = self.party
81
+ if self.secrets:
82
+ data["secrets"] = self.secrets
83
+ if self.instance:
84
+ data["instance"] = self.instance
85
+ if self.flags:
86
+ data["flags"] = self.flags
87
+ if self.buttons:
88
+ data["buttons"] = self.buttons[:2]
89
+ if self.metadata:
90
+ data["metadata"] = self.metadata
91
+ if self.session_id:
92
+ data["session_id"] = self.session_id
93
+ if self.sync_id:
94
+ data["sync_id"] = self.sync_id
95
+ if self.application_id:
96
+ data["application_id"] = self.application_id
97
+ if self.platform:
98
+ data["platform"] = self.platform
99
+ return data
100
+
101
+ @classmethod
102
+ def from_dict(cls, data: dict) -> "Activity":
103
+ return cls(
104
+ type=data.get("type", 0),
105
+ name=data.get("name", ""),
106
+ url=data.get("url"),
107
+ details=data.get("details"),
108
+ state=data.get("state"),
109
+ timestamps=data.get("timestamps"),
110
+ assets=data.get("assets"),
111
+ party=data.get("party"),
112
+ secrets=data.get("secrets"),
113
+ instance=data.get("instance", False),
114
+ flags=data.get("flags", 0),
115
+ buttons=data.get("buttons"),
116
+ metadata=data.get("metadata"),
117
+ session_id=data.get("session_id"),
118
+ sync_id=data.get("sync_id"),
119
+ application_id=data.get("application_id"),
120
+ platform=data.get("platform"),
121
+ )
122
+
123
+ def __repr__(self) -> str:
124
+ return f"<Activity type={self.type} name={self.name!r}>"
125
+
126
+
127
+ def spotify_activity(
128
+ song: str,
129
+ artist: str,
130
+ album: str = "",
131
+ duration_minutes: float = 3.5,
132
+ current_position: float = 0,
133
+ image_url: Optional[str] = None,
134
+ track_id: str = None,
135
+ album_id: str = None,
136
+ artist_id: str = None,
137
+ ) -> Activity:
138
+ total_ms = int(duration_minutes * 60 * 1000)
139
+ start_time = int(time.time() * 1000)
140
+ end_time = start_time + total_ms
141
+
142
+ track_id = track_id or "0VjIjW4GlUZAMYd2vXMi3b"
143
+ album_id = album_id or "4yP0hdKOZPNshxUOjY0cZj"
144
+ artist_id = artist_id or "1Xyo4u8uXC1ZmMpatF05PJ"
145
+
146
+ activity = Activity(
147
+ type=ActivityType.LISTENING,
148
+ name="Spotify",
149
+ details=song[:128],
150
+ state=artist[:128],
151
+ timestamps={"start": start_time, "end": end_time},
152
+ application_id="3201606009684",
153
+ sync_id=track_id,
154
+ session_id=f"spotify:{track_id}",
155
+ party={"id": f"spotify:{track_id}", "size": [1, 1]},
156
+ secrets={"join": track_id, "spectate": track_id, "match": track_id},
157
+ instance=True,
158
+ flags=48,
159
+ metadata={
160
+ "context_uri": f"spotify:album:{album_id}",
161
+ "album_id": album_id,
162
+ "artist_ids": [artist_id],
163
+ "track_id": track_id,
164
+ },
165
+ )
166
+
167
+ if image_url:
168
+ activity.assets = {
169
+ "large_image": image_url,
170
+ "large_text": f"{album} on Spotify" if album else "Spotify",
171
+ "small_image": image_url,
172
+ "small_text": album or "Spotify",
173
+ }
174
+ else:
175
+ activity.assets = {"large_image": "spotify", "large_text": "Spotify"}
176
+
177
+ return activity
178
+
179
+
180
+ def youtube_activity(
181
+ video_title: str,
182
+ channel_name: str,
183
+ elapsed_minutes: float = 0,
184
+ duration_minutes: float = 10,
185
+ image_url: Optional[str] = None,
186
+ ) -> Activity:
187
+ cur_ms = int(elapsed_minutes * 60 * 1000)
188
+ tot_ms = int(duration_minutes * 60 * 1000)
189
+ start_time = int(time.time() * 1000)
190
+
191
+ activity = Activity(
192
+ type=ActivityType.WATCHING,
193
+ name="YouTube",
194
+ details=video_title[:128],
195
+ state=channel_name[:128],
196
+ timestamps={"start": start_time - cur_ms, "end": start_time - cur_ms + tot_ms},
197
+ application_id="111299001912",
198
+ )
199
+
200
+ if image_url:
201
+ activity.assets = {"large_image": image_url}
202
+
203
+ return activity
204
+
205
+
206
+ def xbox_activity(
207
+ game_name: str,
208
+ details: Optional[str] = None,
209
+ state: Optional[str] = None,
210
+ image_url: Optional[str] = None,
211
+ party_cur: Optional[int] = None,
212
+ party_max: Optional[int] = None,
213
+ ) -> Activity:
214
+ activity = Activity(
215
+ type=ActivityType.PLAYING,
216
+ name=game_name[:128],
217
+ application_id="622174530214821906",
218
+ platform="xbox",
219
+ timestamps={"start": int(time.time() * 1000)},
220
+ )
221
+
222
+ if details:
223
+ activity.details = details[:128]
224
+ if state:
225
+ activity.state = state[:128]
226
+ if image_url:
227
+ activity.assets = {"large_image": image_url}
228
+ if party_cur and party_max:
229
+ activity.party = {"id": "xbox-party", "size": [party_cur, party_max]}
230
+
231
+ return activity
232
+
233
+
234
+ def playstation_activity(
235
+ game_name: str,
236
+ platform: str = "ps5",
237
+ details: Optional[str] = None,
238
+ state: Optional[str] = None,
239
+ image_url: Optional[str] = None,
240
+ party_cur: Optional[int] = None,
241
+ party_max: Optional[int] = None,
242
+ ) -> Activity:
243
+ activity = Activity(
244
+ type=ActivityType.PLAYING,
245
+ name=game_name[:128],
246
+ application_id="1470539864909943067",
247
+ platform=platform,
248
+ timestamps={"start": int(time.time() * 1000)},
249
+ )
250
+
251
+ if details:
252
+ activity.details = details[:128]
253
+ if state:
254
+ activity.state = state[:128]
255
+ if image_url:
256
+ activity.assets = {"large_image": image_url}
257
+ if party_cur and party_max:
258
+ activity.party = {"id": "ps-party", "size": [party_cur, party_max]}
259
+
260
+ return activity
261
+
262
+
263
+ def crunchyroll_activity(
264
+ anime_title: str,
265
+ episode_title: Optional[str] = None,
266
+ elapsed_minutes: float = 0,
267
+ total_minutes: float = 24,
268
+ image_url: Optional[str] = None,
269
+ ) -> Activity:
270
+ activity = Activity(
271
+ type=ActivityType.WATCHING,
272
+ name="Crunchyroll",
273
+ details=anime_title[:128],
274
+ application_id="981509069309354054",
275
+ timestamps={
276
+ "start": int(time.time() * 1000) - int(elapsed_minutes * 60 * 1000),
277
+ "end": int(time.time() * 1000) - int(elapsed_minutes * 60 * 1000) + int(total_minutes * 60 * 1000),
278
+ },
279
+ )
280
+
281
+ if episode_title:
282
+ activity.state = episode_title[:128]
283
+ if image_url:
284
+ activity.assets = {"large_image": image_url}
285
+
286
+ return activity
287
+
288
+
289
+ def custom_activity(
290
+ name: str,
291
+ activity_type: Union[ActivityType, int] = ActivityType.PLAYING,
292
+ details: Optional[str] = None,
293
+ state: Optional[str] = None,
294
+ url: Optional[str] = None,
295
+ image_url: Optional[str] = None,
296
+ application_id: Optional[str] = None,
297
+ platform: Optional[str] = None,
298
+ ) -> Activity:
299
+ return Activity(
300
+ type=activity_type,
301
+ name=name[:128],
302
+ details=details[:128] if details else None,
303
+ state=state[:128] if state else None,
304
+ url=url,
305
+ assets={"large_image": image_url} if image_url else None,
306
+ application_id=application_id or "1487942541696434337",
307
+ platform=platform,
308
+ timestamps={"start": int(time.time() * 1000)},
309
+ )
310
+
311
+
312
+ def listening_activity(
313
+ name: str,
314
+ details: Optional[str] = None,
315
+ state: Optional[str] = None,
316
+ image_url: Optional[str] = None,
317
+ total_minutes: Optional[float] = None,
318
+ elapsed_minutes: float = 0,
319
+ ) -> Activity:
320
+ activity = Activity(
321
+ type=ActivityType.LISTENING,
322
+ name=name[:128],
323
+ application_id="1487942541696434337",
324
+ )
325
+
326
+ if details:
327
+ activity.details = details[:128]
328
+ if state:
329
+ activity.state = state[:128]
330
+ if image_url:
331
+ activity.assets = {"large_image": image_url}
332
+ if total_minutes:
333
+ activity.timestamps = {
334
+ "start": int(time.time() * 1000) - int(elapsed_minutes * 60 * 1000),
335
+ "end": int(time.time() * 1000) - int(elapsed_minutes * 60 * 1000) + int(total_minutes * 60 * 1000),
336
+ }
337
+ else:
338
+ activity.timestamps = {"start": int(time.time() * 1000)}
339
+
340
+ return activity
341
+
342
+
343
+ def streaming_activity(
344
+ name: str,
345
+ url: str = "https://twitch.tv/kaicenat",
346
+ details: Optional[str] = None,
347
+ state: Optional[str] = None,
348
+ image_url: Optional[str] = None,
349
+ ) -> Activity:
350
+ activity = Activity(
351
+ type=ActivityType.STREAMING,
352
+ name=name[:128],
353
+ url=url,
354
+ application_id="1487942541696434337",
355
+ timestamps={"start": int(time.time() * 1000)},
356
+ )
357
+
358
+ if details:
359
+ activity.details = details[:128]
360
+ if state:
361
+ activity.state = state[:128]
362
+ if image_url:
363
+ activity.assets = {"large_image": image_url}
364
+
365
+ return activity
366
+
367
+
368
+ def competing_activity(
369
+ name: str,
370
+ details: Optional[str] = None,
371
+ state: Optional[str] = None,
372
+ image_url: Optional[str] = None,
373
+ ) -> Activity:
374
+ activity = Activity(
375
+ type=ActivityType.COMPETING,
376
+ name=name[:128],
377
+ application_id="1487942541696434337",
378
+ timestamps={"start": int(time.time() * 1000)},
379
+ )
380
+
381
+ if details:
382
+ activity.details = details[:128]
383
+ if state:
384
+ activity.state = state[:128]
385
+ if image_url:
386
+ activity.assets = {"large_image": image_url}
387
+
388
+ return activity
389
+
390
+
391
+ LOGO_MAP = {
392
+ "xbox": ("622174530214821906", "xbox"),
393
+ "playstation": ("1470539864909943067", "ps5"),
394
+ "ps5": ("1470539864909943067", "ps5"),
395
+ "ps4": ("1470539864909943067", "ps4"),
396
+ "crunchyroll": ("981509069309354054", None),
397
+ "spotify": ("3201606009684", None),
398
+ "youtube": ("111299001912", None),
399
+ }
@@ -26,7 +26,6 @@ from .models.webhook import Webhook, WebhookMessage
26
26
  from .headers import HeaderSpoofer, EMULATION
27
27
  from .utils import send_notification, START_IMAGE, ERROR_IMAGE
28
28
  from .interactions import Interaction, InteractionHandler, interaction_handler
29
- from .voice import VoiceManager, VoiceClient, VoiceState
30
29
 
31
30
  logger = logging.getLogger(__name__)
32
31
 
@@ -91,12 +90,9 @@ class Client:
91
90
 
92
91
  self._interaction_handlers: Dict[str, Callable] = {}
93
92
 
94
- self._voice = VoiceManager(self)
95
-
96
93
  self._dispatcher.on("READY", self._on_ready_internal)
97
94
  self._dispatcher.on("MESSAGE_CREATE", self._on_message_create_internal)
98
95
  self._dispatcher.on("INTERACTION_CREATE", self._on_interaction_create)
99
- self._dispatcher.on("VOICE_STATE_UPDATE", self._on_voice_state_update)
100
96
 
101
97
  if self._notifications:
102
98
  send_notification(
@@ -134,11 +130,6 @@ class Client:
134
130
  def cogs(self) -> List[Cog]:
135
131
  return list(self._cogs.values())
136
132
 
137
- @property
138
- def voice(self) -> VoiceManager:
139
- """Access voice manager."""
140
- return self._voice
141
-
142
133
  def event(self, coro: Callable):
143
134
  if not asyncio.iscoroutinefunction(coro):
144
135
  raise TypeError("Event handlers must be coroutines")
@@ -214,7 +205,6 @@ class Client:
214
205
  return self._cogs.get(name)
215
206
 
216
207
  def interaction_handler(self, custom_id: str):
217
- """Decorator to register an interaction handler."""
218
208
  def decorator(func: Callable):
219
209
  self._interaction_handlers[custom_id] = func
220
210
  return func
@@ -238,7 +228,6 @@ class Client:
238
228
  await self._process_commands(message)
239
229
 
240
230
  async def _on_interaction_create(self, data: dict):
241
- """Handle interaction_create events."""
242
231
  try:
243
232
  interaction = Interaction(self._state, data)
244
233
 
@@ -249,15 +238,6 @@ class Client:
249
238
  except Exception as e:
250
239
  logger.exception(f"Error handling interaction: {e}")
251
240
 
252
- async def _on_voice_state_update(self, data: dict):
253
- """Handle voice state updates."""
254
- guild_id = int(data.get("guild_id", 0))
255
- if not guild_id:
256
- return
257
-
258
- voice_state = data.get("voice_state", {})
259
- self._voice.update_state(guild_id, voice_state)
260
-
261
241
  async def _process_commands(self, message: Message):
262
242
  if not self.user or message.author.id != self.user.id:
263
243
  return
@@ -373,7 +353,6 @@ class Client:
373
353
  self._closed = True
374
354
  self._ready.clear()
375
355
 
376
- await self._voice.disconnect_all()
377
356
  await self._gateway.close()
378
357
  await self._http.close()
379
358
 
@@ -421,9 +400,6 @@ class Client:
421
400
  async def wait_until_ready(self):
422
401
  await self._ready.wait()
423
402
 
424
- # ============================================================
425
- # FETCH METHODS
426
- # ============================================================
427
403
  async def fetch_user(self, user_id: int):
428
404
  data = await self._http.request(Route.user(user_id))
429
405
  return self._state._add_user(data)
@@ -449,9 +425,6 @@ class Client:
449
425
  def get_user(self, user_id: int):
450
426
  return self._state._users.get(user_id)
451
427
 
452
- # ============================================================
453
- # RELATIONSHIPS
454
- # ============================================================
455
428
  async def get_relationships(self) -> List[Relationship]:
456
429
  data = await self._http.request(Route("GET", "/users/@me/relationships"))
457
430
  return [Relationship(state=self._state, data=r) for r in data]
@@ -479,9 +452,6 @@ class Client:
479
452
  Route("DELETE", f"/users/@me/relationships/{user_id}")
480
453
  )
481
454
 
482
- # ============================================================
483
- # BILLING
484
- # ============================================================
485
455
  async def get_payment_sources(self) -> List[PaymentSource]:
486
456
  data = await self._http.request(Route("GET", "/users/@me/billing/payment-sources"))
487
457
  return [PaymentSource(state=self._state, data=s) for s in data]
@@ -496,9 +466,6 @@ class Client:
496
466
  async def get_skus(self) -> List[Dict[str, Any]]:
497
467
  return await self._http.request(Route("GET", "/users/@me/entitlements/skus"))
498
468
 
499
- # ============================================================
500
- # SETTINGS
501
- # ============================================================
502
469
  async def get_user_settings(self) -> UserSettings:
503
470
  data = await self._http.request(Route("GET", "/users/@me/settings"))
504
471
  return UserSettings(data)
@@ -533,9 +500,6 @@ class Client:
533
500
  json=kwargs
534
501
  )
535
502
 
536
- # ============================================================
537
- # PROFILE
538
- # ============================================================
539
503
  async def get_profile(self, user_id: int = None) -> Dict[str, Any]:
540
504
  endpoint = f"/users/{user_id}/profile" if user_id else "/users/@me/profile"
541
505
  return await self._http.request(Route("GET", endpoint))
@@ -567,16 +531,11 @@ class Client:
567
531
  async def get_connections(self) -> List[Dict[str, Any]]:
568
532
  return await self._http.request(Route("GET", "/users/@me/connections"))
569
533
 
570
- # ============================================================
571
- # WEBHOOKS
572
- # ============================================================
573
534
  async def get_webhook(self, webhook_id: int) -> Webhook:
574
- """Get a webhook by ID."""
575
535
  data = await self._http.request(Route("GET", f"/webhooks/{webhook_id}"))
576
536
  return Webhook(state=self._state, data=data)
577
537
 
578
538
  async def get_webhook_with_token(self, webhook_id: int, token: str) -> Webhook:
579
- """Get a webhook by ID and token."""
580
539
  data = await self._http.request(
581
540
  method="GET",
582
541
  url=f"/webhooks/{webhook_id}/{token}",
@@ -584,12 +543,10 @@ class Client:
584
543
  return Webhook(state=self._state, data=data)
585
544
 
586
545
  async def get_channel_webhooks(self, channel_id: int) -> List[Webhook]:
587
- """Get all webhooks in a channel."""
588
546
  data = await self._http.request(Route("GET", f"/channels/{channel_id}/webhooks"))
589
547
  return [Webhook(state=self._state, data=w) for w in data]
590
548
 
591
549
  async def get_guild_webhooks(self, guild_id: int) -> List[Webhook]:
592
- """Get all webhooks in a guild."""
593
550
  data = await self._http.request(Route("GET", f"/guilds/{guild_id}/webhooks"))
594
551
  return [Webhook(state=self._state, data=w) for w in data]
595
552
 
@@ -599,7 +556,6 @@ class Client:
599
556
  name: str,
600
557
  avatar: Optional[str] = None,
601
558
  ) -> Webhook:
602
- """Create a webhook in a channel."""
603
559
  payload = {"name": name}
604
560
  if avatar:
605
561
  payload["avatar"] = avatar
@@ -607,32 +563,4 @@ class Client:
607
563
  Route("POST", f"/channels/{channel_id}/webhooks"),
608
564
  json=payload,
609
565
  )
610
- return Webhook(state=self._state, data=data)
611
-
612
- # ============================================================
613
- # VOICE
614
- # ============================================================
615
- async def create_voice_client(
616
- self,
617
- channel_id: int,
618
- guild_id: int,
619
- endpoint: str,
620
- token: str,
621
- session_id: str,
622
- ) -> VoiceClient:
623
- """Create and connect a voice client."""
624
- return await self._voice.connect(
625
- channel_id,
626
- guild_id,
627
- endpoint,
628
- token,
629
- session_id,
630
- )
631
-
632
- def get_voice_client(self, guild_id: int) -> Optional[VoiceClient]:
633
- """Get the voice client for a guild."""
634
- return self._voice.get_client(guild_id)
635
-
636
- async def disconnect_voice(self, guild_id: int) -> None:
637
- """Disconnect voice client for a guild."""
638
- await self._voice.disconnect(guild_id)
566
+ return Webhook(state=self._state, data=data)
@@ -43,7 +43,7 @@ class Context:
43
43
  @property
44
44
  def channel(self) -> "Channel | None":
45
45
  if self._cs_channel is None:
46
- self._cs_channel = self.message.channel
46
+ self._cs_channel = self.bot.get_channel(self.message.channel_id)
47
47
  return self._cs_channel
48
48
 
49
49
  @property
@@ -72,8 +72,9 @@ class Context:
72
72
 
73
73
  async def send(self, content: str | None = None, **kwargs):
74
74
  """Send a message to the current channel."""
75
- if self.channel:
76
- return await self.channel.send(content, **kwargs)
75
+ ch = self.channel
76
+ if ch:
77
+ return await ch.send(content, **kwargs)
77
78
  raise RuntimeError("Cannot send: no channel available")
78
79
 
79
80
  async def reply(self, content: str | None = None, **kwargs):
@@ -82,16 +83,18 @@ class Context:
82
83
 
83
84
  async def trigger_typing(self):
84
85
  """Trigger typing in the current channel."""
85
- if self.channel:
86
- await self.channel.typing()
86
+ ch = self.channel
87
+ if ch:
88
+ await ch.typing()
87
89
 
88
90
  async def fetch_message(self, message_id: int):
89
91
  """Fetch a message from the current channel."""
90
- if self.channel:
92
+ ch = self.channel
93
+ if ch:
91
94
  data = await self.bot._state.http.get_messages(
92
- self.channel.id, limit=1, before=message_id + 1
95
+ ch.id, limit=1, before=message_id + 1
93
96
  )
94
97
  if data:
95
98
  from ..models.message import Message
96
99
  return Message(state=self.bot._state, data=data[0])
97
- return None
100
+ return None
@@ -0,0 +1,29 @@
1
+ from .user import User
2
+ from .guild import Guild
3
+ from .channel import Channel, DMChannel, GroupChannel, channel_factory
4
+ from .message import Message
5
+ from .member import Member
6
+ from .base import DiscordObject
7
+ from .relationship import Relationship
8
+ from .billing import PaymentSource, Subscription
9
+ from .settings import GuildSettings, UserSettings
10
+ from .webhook import Webhook, WebhookMessage
11
+
12
+ __all__ = [
13
+ "User",
14
+ "Guild",
15
+ "Channel",
16
+ "DMChannel",
17
+ "GroupChannel",
18
+ "channel_factory",
19
+ "Message",
20
+ "Member",
21
+ "DiscordObject",
22
+ "Relationship",
23
+ "PaymentSource",
24
+ "Subscription",
25
+ "GuildSettings",
26
+ "UserSettings",
27
+ "Webhook",
28
+ "WebhookMessage",
29
+ ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modifyself
3
- Version: 0.2.9
3
+ Version: 0.3.3
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.9"
7
+ version = "0.3.3"
8
8
  description = "A clean, pythonic Discord self-bot library"
9
9
  readme = "README.md"
10
10
  license = "MIT"
File without changes
@@ -1,23 +0,0 @@
1
- """
2
- Discord entity models.
3
- """
4
-
5
- from .base import DiscordObject
6
- from .user import User
7
- from .guild import Guild
8
- from .channel import Channel, TextChannel, DMChannel, VoiceChannel, CategoryChannel
9
- from .message import Message
10
- from .member import Member
11
-
12
- __all__ = [
13
- "DiscordObject",
14
- "User",
15
- "Guild",
16
- "Channel",
17
- "TextChannel",
18
- "DMChannel",
19
- "VoiceChannel",
20
- "CategoryChannel",
21
- "Message",
22
- "Member",
23
- ]
File without changes
File without changes
File without changes