cascade-discord 0.1.0__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.
- cascade_discord-0.1.0/LICENSE +21 -0
- cascade_discord-0.1.0/MANIFEST.in +5 -0
- cascade_discord-0.1.0/PKG-INFO +248 -0
- cascade_discord-0.1.0/README.md +224 -0
- cascade_discord-0.1.0/cascade/__init__.py +84 -0
- cascade_discord-0.1.0/cascade/api/__init__.py +0 -0
- cascade_discord-0.1.0/cascade/api/ratelimit.py +62 -0
- cascade_discord-0.1.0/cascade/api/rest.py +774 -0
- cascade_discord-0.1.0/cascade/api/routes.py +82 -0
- cascade_discord-0.1.0/cascade/api/typing.py +46 -0
- cascade_discord-0.1.0/cascade/core/__init__.py +0 -0
- cascade_discord-0.1.0/cascade/core/cache.py +88 -0
- cascade_discord-0.1.0/cascade/core/dispatch.py +62 -0
- cascade_discord-0.1.0/cascade/core/events.py +89 -0
- cascade_discord-0.1.0/cascade/core/session.py +139 -0
- cascade_discord-0.1.0/cascade/entities/__init__.py +0 -0
- cascade_discord-0.1.0/cascade/entities/application.py +56 -0
- cascade_discord-0.1.0/cascade/entities/channel.py +212 -0
- cascade_discord-0.1.0/cascade/entities/connection.py +59 -0
- cascade_discord-0.1.0/cascade/entities/emoji.py +100 -0
- cascade_discord-0.1.0/cascade/entities/guild.py +134 -0
- cascade_discord-0.1.0/cascade/entities/member.py +78 -0
- cascade_discord-0.1.0/cascade/entities/message.py +138 -0
- cascade_discord-0.1.0/cascade/entities/presence.py +77 -0
- cascade_discord-0.1.0/cascade/entities/role.py +77 -0
- cascade_discord-0.1.0/cascade/entities/settings.py +63 -0
- cascade_discord-0.1.0/cascade/entities/user.py +107 -0
- cascade_discord-0.1.0/cascade/entities/webhook.py +45 -0
- cascade_discord-0.1.0/cascade/examples/advanced.py +89 -0
- cascade_discord-0.1.0/cascade/examples/basic.py +40 -0
- cascade_discord-0.1.0/cascade/examples/commands.py +57 -0
- cascade_discord-0.1.0/cascade/examples/moderation.py +117 -0
- cascade_discord-0.1.0/cascade/ext/__init__.py +0 -0
- cascade_discord-0.1.0/cascade/ext/commands/__init__.py +9 -0
- cascade_discord-0.1.0/cascade/ext/commands/bot.py +47 -0
- cascade_discord-0.1.0/cascade/ext/commands/context.py +21 -0
- cascade_discord-0.1.0/cascade/ext/commands/decorators.py +8 -0
- cascade_discord-0.1.0/cascade/gateway/__init__.py +0 -0
- cascade_discord-0.1.0/cascade/gateway/heartbeat.py +49 -0
- cascade_discord-0.1.0/cascade/gateway/opcodes.py +11 -0
- cascade_discord-0.1.0/cascade/gateway/shard.py +380 -0
- cascade_discord-0.1.0/cascade/py.typed +0 -0
- cascade_discord-0.1.0/cascade/types/__init__.py +0 -0
- cascade_discord-0.1.0/cascade/types/enums.py +105 -0
- cascade_discord-0.1.0/cascade/types/payloads.py +106 -0
- cascade_discord-0.1.0/cascade/utils/__init__.py +0 -0
- cascade_discord-0.1.0/cascade/utils/backoff.py +55 -0
- cascade_discord-0.1.0/cascade/utils/checks.py +37 -0
- cascade_discord-0.1.0/cascade/utils/chunker.py +42 -0
- cascade_discord-0.1.0/cascade/utils/color.py +84 -0
- cascade_discord-0.1.0/cascade/utils/embed.py +152 -0
- cascade_discord-0.1.0/cascade/utils/formatting.py +70 -0
- cascade_discord-0.1.0/cascade/utils/intents.py +41 -0
- cascade_discord-0.1.0/cascade/utils/markdown.py +104 -0
- cascade_discord-0.1.0/cascade/utils/permissions.py +115 -0
- cascade_discord-0.1.0/cascade/utils/snowflake.py +51 -0
- cascade_discord-0.1.0/cascade/utils/validator.py +36 -0
- cascade_discord-0.1.0/cascade_discord.egg-info/PKG-INFO +248 -0
- cascade_discord-0.1.0/cascade_discord.egg-info/SOURCES.txt +63 -0
- cascade_discord-0.1.0/cascade_discord.egg-info/dependency_links.txt +1 -0
- cascade_discord-0.1.0/cascade_discord.egg-info/requires.txt +2 -0
- cascade_discord-0.1.0/cascade_discord.egg-info/top_level.txt +1 -0
- cascade_discord-0.1.0/pyproject.toml +34 -0
- cascade_discord-0.1.0/setup.cfg +4 -0
- cascade_discord-0.1.0/setup.py +8 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Cascade Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cascade-discord
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: High-performance Discord selfbot library for Python
|
|
5
|
+
Author: Cascade Contributors
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/4f2b/cascade
|
|
8
|
+
Project-URL: Repository, https://github.com/4f2b/cascade
|
|
9
|
+
Project-URL: Issues, https://github.com/4f2b/cascade/issues
|
|
10
|
+
Keywords: discord,api,selfbot,async,websocket
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Framework :: AsyncIO
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: aiohttp>=3.9.0
|
|
22
|
+
Requires-Dist: websockets>=12.0
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# Cascade
|
|
26
|
+
|
|
27
|
+
High-performance Discord selfbot library for Python. Built for speed, stealth, and reliability.
|
|
28
|
+
|
|
29
|
+
## Features
|
|
30
|
+
|
|
31
|
+
- **Blazing Fast**: Optimized for maximum performance with async/await
|
|
32
|
+
- **Stealthy**: Mimics official Discord client behavior to avoid detection
|
|
33
|
+
- **Full-Featured**: Complete gateway, REST API, and event system
|
|
34
|
+
- **Smart Caching**: Intelligent caching system for optimal memory usage
|
|
35
|
+
- **Type-Safe**: Full type hints throughout the codebase
|
|
36
|
+
- **Extensible**: Plugin system for custom commands and features
|
|
37
|
+
|
|
38
|
+
## Quick Start
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
import asyncio
|
|
42
|
+
import cascade
|
|
43
|
+
|
|
44
|
+
async def main():
|
|
45
|
+
session = cascade.Session('YOUR_TOKEN')
|
|
46
|
+
|
|
47
|
+
@session.event
|
|
48
|
+
async def on_ready(user):
|
|
49
|
+
print(f'Logged in as {user.username}')
|
|
50
|
+
|
|
51
|
+
@session.event
|
|
52
|
+
async def on_message(message):
|
|
53
|
+
if message.content == '!ping':
|
|
54
|
+
await session.rest.send_message(message.channel_id, 'Pong!')
|
|
55
|
+
|
|
56
|
+
await session.start()
|
|
57
|
+
|
|
58
|
+
asyncio.run(main())
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Advanced Usage
|
|
62
|
+
|
|
63
|
+
### Commands Framework
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
from cascade.ext.commands import Bot
|
|
67
|
+
|
|
68
|
+
bot = Bot(command_prefix='!', self_bot=True)
|
|
69
|
+
|
|
70
|
+
@bot.command()
|
|
71
|
+
async def ping(ctx):
|
|
72
|
+
await ctx.send(f'Pong! {bot.session.gateway.latency:.2f}ms')
|
|
73
|
+
|
|
74
|
+
await bot.start('YOUR_TOKEN')
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Smart Features
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
async with cascade.TypingIndicator(session.rest, channel_id):
|
|
81
|
+
await process_long_task()
|
|
82
|
+
await session.rest.send_message(channel_id, 'Done!')
|
|
83
|
+
|
|
84
|
+
results = await session.rest.search_channel_messages(
|
|
85
|
+
channel_id,
|
|
86
|
+
query='keyword',
|
|
87
|
+
author_id=user_id
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
profile = await session.rest.get_user_profile(user_id)
|
|
91
|
+
connections = await session.rest.get_user_connections()
|
|
92
|
+
settings = await session.rest.get_user_settings()
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Permissions & Safety
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
from cascade import Permission, Permissions
|
|
99
|
+
|
|
100
|
+
perms = Permissions()
|
|
101
|
+
perms.add(Permission.SEND_MESSAGES, Permission.READ_MESSAGE_HISTORY)
|
|
102
|
+
|
|
103
|
+
if perms.has(Permission.ADMINISTRATOR):
|
|
104
|
+
print('User has admin')
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Installation
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
pip install cascade
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Performance
|
|
114
|
+
|
|
115
|
+
- **Gateway**: Sub-millisecond message handling
|
|
116
|
+
- **REST**: Smart rate limiting with automatic retry
|
|
117
|
+
- **Cache**: LRU caching with TTL support
|
|
118
|
+
- **Memory**: Optimized for low memory footprint
|
|
119
|
+
|
|
120
|
+
## Architecture
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
cascade/
|
|
124
|
+
├── core/ # Core session, cache, events
|
|
125
|
+
├── gateway/ # WebSocket gateway handling
|
|
126
|
+
├── api/ # REST API client
|
|
127
|
+
├── entities/ # Discord entities (User, Guild, Message, etc.)
|
|
128
|
+
├── types/ # Enums and type definitions
|
|
129
|
+
├── utils/ # Utilities (permissions, formatting, validation)
|
|
130
|
+
└── ext/ # Extensions (commands framework)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Capabilities
|
|
134
|
+
|
|
135
|
+
- Full gateway connection with auto-reconnect
|
|
136
|
+
- Complete REST API coverage (100+ endpoints)
|
|
137
|
+
- User account features (notes, relationships, settings)
|
|
138
|
+
- Guild management (roles, channels, members)
|
|
139
|
+
- Message handling (send, edit, delete, search, reactions)
|
|
140
|
+
- Thread support (create, join, manage)
|
|
141
|
+
- Voice state updates
|
|
142
|
+
- Stage instances and scheduled events
|
|
143
|
+
- Webhooks and integrations
|
|
144
|
+
- Rich presence and activities
|
|
145
|
+
- Advanced search and filtering
|
|
146
|
+
- Bulk operations
|
|
147
|
+
- Smart markdown processing
|
|
148
|
+
- Permission calculations
|
|
149
|
+
|
|
150
|
+
## Examples
|
|
151
|
+
|
|
152
|
+
Check the `examples/` directory for:
|
|
153
|
+
- `basic.py` - Simple bot setup
|
|
154
|
+
- `commands.py` - Command framework usage
|
|
155
|
+
- `advanced.py` - Advanced features
|
|
156
|
+
- `moderation.py` - Moderation utilities
|
|
157
|
+
|
|
158
|
+
## Warning
|
|
159
|
+
|
|
160
|
+
Selfbots are against Discord's Terms of Service. Use at your own risk.
|
|
161
|
+
|
|
162
|
+
## License
|
|
163
|
+
|
|
164
|
+
MIT.
|
|
165
|
+
|
|
166
|
+
## ⚠️ Warning
|
|
167
|
+
|
|
168
|
+
**Automating user accounts violates Discord's Terms of Service and can result in account termination.** This library is for educational purposes only. Use at your own risk.
|
|
169
|
+
|
|
170
|
+
## Features
|
|
171
|
+
|
|
172
|
+
- Async/await with aiohttp and websockets
|
|
173
|
+
- Full gateway connection with automatic reconnection
|
|
174
|
+
- Event-driven architecture
|
|
175
|
+
- REST API with intelligent rate limiting
|
|
176
|
+
- Built-in caching system
|
|
177
|
+
- Complete entity models (User, Guild, Channel, Message, etc.)
|
|
178
|
+
- Command framework
|
|
179
|
+
- Type hints throughout
|
|
180
|
+
- Zero comments, clean professional code
|
|
181
|
+
|
|
182
|
+
## Installation
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
pip install -e .
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Quick Start
|
|
189
|
+
|
|
190
|
+
```python
|
|
191
|
+
import cascade
|
|
192
|
+
|
|
193
|
+
client = cascade.Session('your_token_here')
|
|
194
|
+
|
|
195
|
+
@client.event
|
|
196
|
+
async def on_ready():
|
|
197
|
+
print(f'Logged in as {client.user.name}')
|
|
198
|
+
|
|
199
|
+
@client.event
|
|
200
|
+
async def on_message(message):
|
|
201
|
+
if message.content == '!ping':
|
|
202
|
+
await message.channel.send('Pong!')
|
|
203
|
+
|
|
204
|
+
client.run()
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Command Framework
|
|
208
|
+
|
|
209
|
+
```python
|
|
210
|
+
from cascade.ext.commands import Bot
|
|
211
|
+
|
|
212
|
+
bot = Bot('your_token_here', command_prefix='!')
|
|
213
|
+
|
|
214
|
+
@bot.command()
|
|
215
|
+
async def hello(ctx):
|
|
216
|
+
await ctx.send(f'Hello {ctx.author.name}!')
|
|
217
|
+
|
|
218
|
+
@bot.command()
|
|
219
|
+
async def say(ctx, *args):
|
|
220
|
+
await ctx.send(' '.join(args))
|
|
221
|
+
|
|
222
|
+
bot.run()
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Examples
|
|
226
|
+
|
|
227
|
+
### Change Presence
|
|
228
|
+
|
|
229
|
+
```python
|
|
230
|
+
from cascade import Activity, ActivityType
|
|
231
|
+
|
|
232
|
+
activity = Activity.playing('with Python')
|
|
233
|
+
await client.change_presence(status='dnd', activity=activity)
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Message Formatting
|
|
237
|
+
|
|
238
|
+
```python
|
|
239
|
+
from cascade.utils.formatting import bold, code, codeblock
|
|
240
|
+
|
|
241
|
+
await channel.send(bold('Bold text'))
|
|
242
|
+
await channel.send(code('inline code'))
|
|
243
|
+
await channel.send(codeblock('print("hello")', 'python'))
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## License
|
|
247
|
+
|
|
248
|
+
MIT
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# Cascade
|
|
2
|
+
|
|
3
|
+
High-performance Discord selfbot library for Python. Built for speed, stealth, and reliability.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Blazing Fast**: Optimized for maximum performance with async/await
|
|
8
|
+
- **Stealthy**: Mimics official Discord client behavior to avoid detection
|
|
9
|
+
- **Full-Featured**: Complete gateway, REST API, and event system
|
|
10
|
+
- **Smart Caching**: Intelligent caching system for optimal memory usage
|
|
11
|
+
- **Type-Safe**: Full type hints throughout the codebase
|
|
12
|
+
- **Extensible**: Plugin system for custom commands and features
|
|
13
|
+
|
|
14
|
+
## Quick Start
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
import asyncio
|
|
18
|
+
import cascade
|
|
19
|
+
|
|
20
|
+
async def main():
|
|
21
|
+
session = cascade.Session('YOUR_TOKEN')
|
|
22
|
+
|
|
23
|
+
@session.event
|
|
24
|
+
async def on_ready(user):
|
|
25
|
+
print(f'Logged in as {user.username}')
|
|
26
|
+
|
|
27
|
+
@session.event
|
|
28
|
+
async def on_message(message):
|
|
29
|
+
if message.content == '!ping':
|
|
30
|
+
await session.rest.send_message(message.channel_id, 'Pong!')
|
|
31
|
+
|
|
32
|
+
await session.start()
|
|
33
|
+
|
|
34
|
+
asyncio.run(main())
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Advanced Usage
|
|
38
|
+
|
|
39
|
+
### Commands Framework
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from cascade.ext.commands import Bot
|
|
43
|
+
|
|
44
|
+
bot = Bot(command_prefix='!', self_bot=True)
|
|
45
|
+
|
|
46
|
+
@bot.command()
|
|
47
|
+
async def ping(ctx):
|
|
48
|
+
await ctx.send(f'Pong! {bot.session.gateway.latency:.2f}ms')
|
|
49
|
+
|
|
50
|
+
await bot.start('YOUR_TOKEN')
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Smart Features
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
async with cascade.TypingIndicator(session.rest, channel_id):
|
|
57
|
+
await process_long_task()
|
|
58
|
+
await session.rest.send_message(channel_id, 'Done!')
|
|
59
|
+
|
|
60
|
+
results = await session.rest.search_channel_messages(
|
|
61
|
+
channel_id,
|
|
62
|
+
query='keyword',
|
|
63
|
+
author_id=user_id
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
profile = await session.rest.get_user_profile(user_id)
|
|
67
|
+
connections = await session.rest.get_user_connections()
|
|
68
|
+
settings = await session.rest.get_user_settings()
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Permissions & Safety
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from cascade import Permission, Permissions
|
|
75
|
+
|
|
76
|
+
perms = Permissions()
|
|
77
|
+
perms.add(Permission.SEND_MESSAGES, Permission.READ_MESSAGE_HISTORY)
|
|
78
|
+
|
|
79
|
+
if perms.has(Permission.ADMINISTRATOR):
|
|
80
|
+
print('User has admin')
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Installation
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
pip install cascade
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Performance
|
|
90
|
+
|
|
91
|
+
- **Gateway**: Sub-millisecond message handling
|
|
92
|
+
- **REST**: Smart rate limiting with automatic retry
|
|
93
|
+
- **Cache**: LRU caching with TTL support
|
|
94
|
+
- **Memory**: Optimized for low memory footprint
|
|
95
|
+
|
|
96
|
+
## Architecture
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
cascade/
|
|
100
|
+
├── core/ # Core session, cache, events
|
|
101
|
+
├── gateway/ # WebSocket gateway handling
|
|
102
|
+
├── api/ # REST API client
|
|
103
|
+
├── entities/ # Discord entities (User, Guild, Message, etc.)
|
|
104
|
+
├── types/ # Enums and type definitions
|
|
105
|
+
├── utils/ # Utilities (permissions, formatting, validation)
|
|
106
|
+
└── ext/ # Extensions (commands framework)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Capabilities
|
|
110
|
+
|
|
111
|
+
- Full gateway connection with auto-reconnect
|
|
112
|
+
- Complete REST API coverage (100+ endpoints)
|
|
113
|
+
- User account features (notes, relationships, settings)
|
|
114
|
+
- Guild management (roles, channels, members)
|
|
115
|
+
- Message handling (send, edit, delete, search, reactions)
|
|
116
|
+
- Thread support (create, join, manage)
|
|
117
|
+
- Voice state updates
|
|
118
|
+
- Stage instances and scheduled events
|
|
119
|
+
- Webhooks and integrations
|
|
120
|
+
- Rich presence and activities
|
|
121
|
+
- Advanced search and filtering
|
|
122
|
+
- Bulk operations
|
|
123
|
+
- Smart markdown processing
|
|
124
|
+
- Permission calculations
|
|
125
|
+
|
|
126
|
+
## Examples
|
|
127
|
+
|
|
128
|
+
Check the `examples/` directory for:
|
|
129
|
+
- `basic.py` - Simple bot setup
|
|
130
|
+
- `commands.py` - Command framework usage
|
|
131
|
+
- `advanced.py` - Advanced features
|
|
132
|
+
- `moderation.py` - Moderation utilities
|
|
133
|
+
|
|
134
|
+
## Warning
|
|
135
|
+
|
|
136
|
+
Selfbots are against Discord's Terms of Service. Use at your own risk.
|
|
137
|
+
|
|
138
|
+
## License
|
|
139
|
+
|
|
140
|
+
MIT.
|
|
141
|
+
|
|
142
|
+
## ⚠️ Warning
|
|
143
|
+
|
|
144
|
+
**Automating user accounts violates Discord's Terms of Service and can result in account termination.** This library is for educational purposes only. Use at your own risk.
|
|
145
|
+
|
|
146
|
+
## Features
|
|
147
|
+
|
|
148
|
+
- Async/await with aiohttp and websockets
|
|
149
|
+
- Full gateway connection with automatic reconnection
|
|
150
|
+
- Event-driven architecture
|
|
151
|
+
- REST API with intelligent rate limiting
|
|
152
|
+
- Built-in caching system
|
|
153
|
+
- Complete entity models (User, Guild, Channel, Message, etc.)
|
|
154
|
+
- Command framework
|
|
155
|
+
- Type hints throughout
|
|
156
|
+
- Zero comments, clean professional code
|
|
157
|
+
|
|
158
|
+
## Installation
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
pip install -e .
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Quick Start
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
import cascade
|
|
168
|
+
|
|
169
|
+
client = cascade.Session('your_token_here')
|
|
170
|
+
|
|
171
|
+
@client.event
|
|
172
|
+
async def on_ready():
|
|
173
|
+
print(f'Logged in as {client.user.name}')
|
|
174
|
+
|
|
175
|
+
@client.event
|
|
176
|
+
async def on_message(message):
|
|
177
|
+
if message.content == '!ping':
|
|
178
|
+
await message.channel.send('Pong!')
|
|
179
|
+
|
|
180
|
+
client.run()
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Command Framework
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
from cascade.ext.commands import Bot
|
|
187
|
+
|
|
188
|
+
bot = Bot('your_token_here', command_prefix='!')
|
|
189
|
+
|
|
190
|
+
@bot.command()
|
|
191
|
+
async def hello(ctx):
|
|
192
|
+
await ctx.send(f'Hello {ctx.author.name}!')
|
|
193
|
+
|
|
194
|
+
@bot.command()
|
|
195
|
+
async def say(ctx, *args):
|
|
196
|
+
await ctx.send(' '.join(args))
|
|
197
|
+
|
|
198
|
+
bot.run()
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Examples
|
|
202
|
+
|
|
203
|
+
### Change Presence
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
from cascade import Activity, ActivityType
|
|
207
|
+
|
|
208
|
+
activity = Activity.playing('with Python')
|
|
209
|
+
await client.change_presence(status='dnd', activity=activity)
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Message Formatting
|
|
213
|
+
|
|
214
|
+
```python
|
|
215
|
+
from cascade.utils.formatting import bold, code, codeblock
|
|
216
|
+
|
|
217
|
+
await channel.send(bold('Bold text'))
|
|
218
|
+
await channel.send(code('inline code'))
|
|
219
|
+
await channel.send(codeblock('print("hello")', 'python'))
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## License
|
|
223
|
+
|
|
224
|
+
MIT
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
__title__ = 'cascade'
|
|
2
|
+
__version__ = '0.1.0'
|
|
3
|
+
__license__ = 'MIT'
|
|
4
|
+
|
|
5
|
+
from .core.session import Session
|
|
6
|
+
from .core.cache import Cache
|
|
7
|
+
from .core.events import EventManager
|
|
8
|
+
from .gateway.shard import GatewayShard
|
|
9
|
+
from .api.rest import RestClient
|
|
10
|
+
from .api.typing import TypingIndicator
|
|
11
|
+
from .entities.message import Message
|
|
12
|
+
from .entities.user import User, ClientUser
|
|
13
|
+
from .entities.guild import Guild
|
|
14
|
+
from .entities.channel import Channel, TextChannel, DMChannel, VoiceChannel, GroupChannel
|
|
15
|
+
from .entities.member import Member
|
|
16
|
+
from .entities.role import Role
|
|
17
|
+
from .entities.emoji import Emoji, PartialEmoji
|
|
18
|
+
from .entities.presence import Activity, Presence
|
|
19
|
+
from .entities.webhook import Webhook
|
|
20
|
+
from .entities.connection import Connection
|
|
21
|
+
from .entities.settings import UserSettings
|
|
22
|
+
from .entities.application import Application
|
|
23
|
+
from .types.enums import ChannelType, MessageType, ActivityType, StatusType, WebhookType
|
|
24
|
+
from .utils.formatting import *
|
|
25
|
+
from .utils.snowflake import *
|
|
26
|
+
from .utils.permissions import Permission, Permissions
|
|
27
|
+
from .utils.intents import Intents
|
|
28
|
+
from .utils.color import Color
|
|
29
|
+
from .utils.validator import is_valid_username, extract_invite_code, parse_message_link
|
|
30
|
+
from .utils.markdown import MarkdownProcessor, bold, italic, underline, strikethrough, code, code_block, spoiler
|
|
31
|
+
from .utils.embed import Embed
|
|
32
|
+
from .ext.commands import Bot, Context, command
|
|
33
|
+
|
|
34
|
+
__all__ = (
|
|
35
|
+
'Session',
|
|
36
|
+
'Cache',
|
|
37
|
+
'EventManager',
|
|
38
|
+
'GatewayShard',
|
|
39
|
+
'RestClient',
|
|
40
|
+
'TypingIndicator',
|
|
41
|
+
'Message',
|
|
42
|
+
'User',
|
|
43
|
+
'ClientUser',
|
|
44
|
+
'Guild',
|
|
45
|
+
'Channel',
|
|
46
|
+
'TextChannel',
|
|
47
|
+
'DMChannel',
|
|
48
|
+
'VoiceChannel',
|
|
49
|
+
'GroupChannel',
|
|
50
|
+
'Member',
|
|
51
|
+
'Role',
|
|
52
|
+
'Emoji',
|
|
53
|
+
'PartialEmoji',
|
|
54
|
+
'Activity',
|
|
55
|
+
'Presence',
|
|
56
|
+
'Webhook',
|
|
57
|
+
'Connection',
|
|
58
|
+
'UserSettings',
|
|
59
|
+
'Application',
|
|
60
|
+
'ChannelType',
|
|
61
|
+
'MessageType',
|
|
62
|
+
'ActivityType',
|
|
63
|
+
'StatusType',
|
|
64
|
+
'WebhookType',
|
|
65
|
+
'Permission',
|
|
66
|
+
'Permissions',
|
|
67
|
+
'Intents',
|
|
68
|
+
'Color',
|
|
69
|
+
'is_valid_username',
|
|
70
|
+
'extract_invite_code',
|
|
71
|
+
'parse_message_link',
|
|
72
|
+
'MarkdownProcessor',
|
|
73
|
+
'bold',
|
|
74
|
+
'italic',
|
|
75
|
+
'underline',
|
|
76
|
+
'strikethrough',
|
|
77
|
+
'code',
|
|
78
|
+
'code_block',
|
|
79
|
+
'spoiler',
|
|
80
|
+
'Embed',
|
|
81
|
+
'Bot',
|
|
82
|
+
'Context',
|
|
83
|
+
'command',
|
|
84
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import time
|
|
3
|
+
from typing import Dict, Optional
|
|
4
|
+
from collections import defaultdict
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class RateLimitBucket:
|
|
8
|
+
def __init__(self):
|
|
9
|
+
self.remaining: int = 1
|
|
10
|
+
self.limit: int = 1
|
|
11
|
+
self.reset_after: float = 0.0
|
|
12
|
+
self.reset: float = 0.0
|
|
13
|
+
self._lock = asyncio.Lock()
|
|
14
|
+
|
|
15
|
+
async def acquire(self) -> None:
|
|
16
|
+
async with self._lock:
|
|
17
|
+
now = time.time()
|
|
18
|
+
|
|
19
|
+
if self.remaining == 0:
|
|
20
|
+
wait_time = self.reset - now
|
|
21
|
+
if wait_time > 0:
|
|
22
|
+
await asyncio.sleep(wait_time)
|
|
23
|
+
self.remaining = self.limit
|
|
24
|
+
|
|
25
|
+
self.remaining -= 1
|
|
26
|
+
|
|
27
|
+
def update(self, headers: Dict[str, str]) -> None:
|
|
28
|
+
self.limit = int(headers.get('X-RateLimit-Limit', 1))
|
|
29
|
+
self.remaining = int(headers.get('X-RateLimit-Remaining', 1))
|
|
30
|
+
self.reset = float(headers.get('X-RateLimit-Reset', 0))
|
|
31
|
+
reset_after = headers.get('X-RateLimit-Reset-After')
|
|
32
|
+
if reset_after:
|
|
33
|
+
self.reset_after = float(reset_after)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class RateLimiter:
|
|
37
|
+
def __init__(self):
|
|
38
|
+
self.buckets: Dict[str, RateLimitBucket] = defaultdict(RateLimitBucket)
|
|
39
|
+
self.global_lock = asyncio.Lock()
|
|
40
|
+
self.global_reset: float = 0.0
|
|
41
|
+
|
|
42
|
+
def get_bucket(self, route: str, method: str) -> RateLimitBucket:
|
|
43
|
+
key = f'{method}:{route}'
|
|
44
|
+
return self.buckets[key]
|
|
45
|
+
|
|
46
|
+
async def acquire(self, route: str, method: str) -> None:
|
|
47
|
+
if self.global_reset > 0:
|
|
48
|
+
now = time.time()
|
|
49
|
+
if now < self.global_reset:
|
|
50
|
+
await asyncio.sleep(self.global_reset - now)
|
|
51
|
+
self.global_reset = 0.0
|
|
52
|
+
|
|
53
|
+
bucket = self.get_bucket(route, method)
|
|
54
|
+
await bucket.acquire()
|
|
55
|
+
|
|
56
|
+
def update_bucket(self, route: str, method: str, headers: Dict[str, str]) -> None:
|
|
57
|
+
bucket = self.get_bucket(route, method)
|
|
58
|
+
bucket.update(headers)
|
|
59
|
+
|
|
60
|
+
if headers.get('X-RateLimit-Global'):
|
|
61
|
+
retry_after = float(headers.get('Retry-After', 0))
|
|
62
|
+
self.global_reset = time.time() + retry_after
|