discord_rda 0.1.3
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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +398 -0
- data/lib/discord_rda/bot.rb +842 -0
- data/lib/discord_rda/cache/configurable_cache.rb +283 -0
- data/lib/discord_rda/cache/entity_cache.rb +184 -0
- data/lib/discord_rda/cache/memory_store.rb +143 -0
- data/lib/discord_rda/cache/redis_store.rb +136 -0
- data/lib/discord_rda/cache/store.rb +56 -0
- data/lib/discord_rda/connection/gateway_client.rb +383 -0
- data/lib/discord_rda/connection/invalid_bucket.rb +205 -0
- data/lib/discord_rda/connection/rate_limiter.rb +280 -0
- data/lib/discord_rda/connection/request_queue.rb +340 -0
- data/lib/discord_rda/connection/reshard_manager.rb +328 -0
- data/lib/discord_rda/connection/rest_client.rb +316 -0
- data/lib/discord_rda/connection/rest_proxy.rb +165 -0
- data/lib/discord_rda/connection/scalable_rest_client.rb +526 -0
- data/lib/discord_rda/connection/shard_manager.rb +223 -0
- data/lib/discord_rda/core/async_runtime.rb +108 -0
- data/lib/discord_rda/core/configuration.rb +194 -0
- data/lib/discord_rda/core/logger.rb +188 -0
- data/lib/discord_rda/core/snowflake.rb +121 -0
- data/lib/discord_rda/entity/attachment.rb +88 -0
- data/lib/discord_rda/entity/base.rb +103 -0
- data/lib/discord_rda/entity/channel.rb +446 -0
- data/lib/discord_rda/entity/channel_builder.rb +280 -0
- data/lib/discord_rda/entity/color.rb +253 -0
- data/lib/discord_rda/entity/embed.rb +221 -0
- data/lib/discord_rda/entity/emoji.rb +89 -0
- data/lib/discord_rda/entity/factory.rb +99 -0
- data/lib/discord_rda/entity/guild.rb +619 -0
- data/lib/discord_rda/entity/member.rb +263 -0
- data/lib/discord_rda/entity/message.rb +405 -0
- data/lib/discord_rda/entity/message_builder.rb +369 -0
- data/lib/discord_rda/entity/role.rb +157 -0
- data/lib/discord_rda/entity/support.rb +294 -0
- data/lib/discord_rda/entity/user.rb +231 -0
- data/lib/discord_rda/entity/value_objects.rb +263 -0
- data/lib/discord_rda/event/auto_moderation.rb +294 -0
- data/lib/discord_rda/event/base.rb +986 -0
- data/lib/discord_rda/event/bus.rb +225 -0
- data/lib/discord_rda/event/scheduled_event.rb +257 -0
- data/lib/discord_rda/hot_reload_manager.rb +303 -0
- data/lib/discord_rda/interactions/application_command.rb +436 -0
- data/lib/discord_rda/interactions/command_system.rb +484 -0
- data/lib/discord_rda/interactions/components.rb +464 -0
- data/lib/discord_rda/interactions/interaction.rb +553 -0
- data/lib/discord_rda/plugin/analytics_plugin.rb +528 -0
- data/lib/discord_rda/plugin/base.rb +190 -0
- data/lib/discord_rda/plugin/registry.rb +126 -0
- data/lib/discord_rda/version.rb +5 -0
- data/lib/discord_rda.rb +70 -0
- metadata +302 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 53c5128ffda5f61e3d0e5aea868f9e93bafa82d98151d79f7c6739e8d185f1f9
|
|
4
|
+
data.tar.gz: 9d73432141274e3bbc8905fe7ddba98691ea64e7fd2381ffd9de1833a0a733f8
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 568d5fcbb987b97e5ba71f793346d536a6433b22398cdc32f04d2df43ced244f7a8215f818f942313e19a8b95e9c02d31dd99aac39fc1cb557648cbe7783081b
|
|
7
|
+
data.tar.gz: 861a6cbd6e0dba4b88e1ce6fcec261c700541493a0802384321d4bd3975ba64fc952d17c41736e28854e602ea58df9361e048bb148c74fdbd4cc9ea743bbe7ae
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 JΓΊlia Klee
|
|
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.
|
data/README.md
ADDED
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
# DiscordRDA
|
|
2
|
+
|
|
3
|
+
> Modern, scalable Ruby library for Discord bot development with full Slash Commands and Component V2 support
|
|
4
|
+
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://www.ruby-lang.org/)
|
|
7
|
+
|
|
8
|
+
DiscordRDA (Ruby Development API) is a high-performance Ruby library for building Discord bots with modern async patterns, comprehensive Slash Command support, Component V2 architecture, and enterprise-grade scalability features.
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
### Core Capabilities
|
|
13
|
+
- **β‘ Async Runtime**: Built on Ruby 3.0+ Fiber scheduler for true concurrency
|
|
14
|
+
- **π Factory Pattern**: Clean entity creation with `EntityFactory`
|
|
15
|
+
- **π‘ Auto Sharding**: Automatic and manual sharding with zero-downtime resharding
|
|
16
|
+
- **πΎ Pluggable Cache**: Memory or Redis backends with pattern-based invalidation
|
|
17
|
+
- **π Plugin System**: Extensible architecture for commands and features
|
|
18
|
+
- **π Rate Limiting**: Advanced Discord API rate limit handling with queue management
|
|
19
|
+
- **π― Full Documentation**: Every API is fully documented
|
|
20
|
+
|
|
21
|
+
### Slash Commands & Interactions
|
|
22
|
+
- **Full Slash Command API**: Create, edit, delete global and guild commands
|
|
23
|
+
- **Context Menu Commands**: User and Message context menu support
|
|
24
|
+
- **Autocomplete**: Real-time autocomplete with dynamic choices
|
|
25
|
+
- **Modals**: Custom modal forms with text inputs
|
|
26
|
+
- **Component V2**: Latest Discord components (buttons, selects, containers)
|
|
27
|
+
|
|
28
|
+
### Enterprise Features
|
|
29
|
+
- **Zero-Downtime Resharding**: Add shards without stopping the bot
|
|
30
|
+
- **Hot Reload**: File system event-based code reloading
|
|
31
|
+
- **Session Transfer**: Migrate guilds between shards seamlessly
|
|
32
|
+
- **REST Proxy Support**: Horizontal scaling with proxy servers
|
|
33
|
+
- **State Preservation**: Maintain sessions across reloads
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
Add this line to your application's Gemfile:
|
|
38
|
+
|
|
39
|
+
```ruby
|
|
40
|
+
gem 'discord_rda'
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
And then execute:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
bundle install
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Or install it yourself as:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
gem install discord_rda
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Quick Start
|
|
56
|
+
|
|
57
|
+
```ruby
|
|
58
|
+
require 'discord_rda'
|
|
59
|
+
|
|
60
|
+
bot = DiscordRDA::Bot.new(
|
|
61
|
+
token: ENV['DISCORD_TOKEN'],
|
|
62
|
+
intents: [:guilds, :guild_messages, :message_content]
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
bot.on(:message_create) do |event|
|
|
66
|
+
if event.content == '!ping'
|
|
67
|
+
event.message.respond(content: 'Pong!')
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
bot.run
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Table of Contents
|
|
75
|
+
|
|
76
|
+
- [Features](#features)
|
|
77
|
+
- [Installation](#installation)
|
|
78
|
+
- [Quick Start](#quick-start)
|
|
79
|
+
- [Slash Commands](#slash-commands)
|
|
80
|
+
- [Components](#components)
|
|
81
|
+
- [Interactions](#interactions)
|
|
82
|
+
- [Architecture](#architecture)
|
|
83
|
+
- [Configuration](#configuration)
|
|
84
|
+
- [Sharding](#sharding)
|
|
85
|
+
- [Caching](#caching)
|
|
86
|
+
- [Rate Limiting](#rate-limiting)
|
|
87
|
+
- [Plugin System](#plugin-system)
|
|
88
|
+
- [Development](#development)
|
|
89
|
+
- [License](#license)
|
|
90
|
+
|
|
91
|
+
## Slash Commands
|
|
92
|
+
|
|
93
|
+
DiscordRDA provides a comprehensive DSL for building Slash Commands:
|
|
94
|
+
|
|
95
|
+
### Basic Slash Command
|
|
96
|
+
|
|
97
|
+
```ruby
|
|
98
|
+
bot.slash('hello', 'Say hello') do |cmd|
|
|
99
|
+
cmd.string('name', 'Your name', required: true)
|
|
100
|
+
cmd.handler do |interaction|
|
|
101
|
+
name = interaction.option('name')
|
|
102
|
+
interaction.respond(content: "Hello, #{name}!")
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Command with Multiple Options
|
|
108
|
+
|
|
109
|
+
```ruby
|
|
110
|
+
bot.slash('ban', 'Ban a user from the server') do |cmd|
|
|
111
|
+
cmd.user('user', 'User to ban', required: true)
|
|
112
|
+
cmd.string('reason', 'Reason for ban')
|
|
113
|
+
cmd.integer('days', 'Days of messages to delete')
|
|
114
|
+
cmd.default_permissions(:ban_members)
|
|
115
|
+
|
|
116
|
+
cmd.handler do |interaction|
|
|
117
|
+
user = interaction.option('user')
|
|
118
|
+
reason = interaction.option('reason') || 'No reason provided'
|
|
119
|
+
interaction.respond(content: "Banned #{user.username}", ephemeral: true)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Guild-Specific Commands
|
|
125
|
+
|
|
126
|
+
```ruby
|
|
127
|
+
bot.slash('admin', 'Admin only command', guild_id: '123456789') do |cmd|
|
|
128
|
+
cmd.default_permissions(:administrator)
|
|
129
|
+
cmd.handler do |interaction|
|
|
130
|
+
interaction.respond(content: 'Admin command executed!', ephemeral: true)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Context Menu Commands
|
|
136
|
+
|
|
137
|
+
```ruby
|
|
138
|
+
# User context menu
|
|
139
|
+
bot.context_menu(type: :user, name: 'High Five') do |interaction|
|
|
140
|
+
user = interaction.target_user
|
|
141
|
+
interaction.respond(content: "High-fived #{user.username}!")
|
|
142
|
+
end
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Components
|
|
146
|
+
|
|
147
|
+
### Button Components
|
|
148
|
+
|
|
149
|
+
```ruby
|
|
150
|
+
interaction.respond(content: 'Click the button!') do |builder|
|
|
151
|
+
builder.components do |row|
|
|
152
|
+
row.button(style: :primary, label: 'Click Me', custom_id: 'click_button')
|
|
153
|
+
row.button(style: :danger, label: 'Delete', custom_id: 'delete_button')
|
|
154
|
+
row.button(style: :link, label: 'Docs', url: 'https://example.com')
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Handle button clicks
|
|
159
|
+
bot.on(:button_click) do |interaction|
|
|
160
|
+
interaction.respond(content: 'Button clicked!', ephemeral: true)
|
|
161
|
+
end
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Select Menus
|
|
165
|
+
|
|
166
|
+
```ruby
|
|
167
|
+
interaction.respond(content: 'Select your roles:') do |builder|
|
|
168
|
+
builder.components do |row|
|
|
169
|
+
row.string_select(
|
|
170
|
+
custom_id: 'role_select',
|
|
171
|
+
placeholder: 'Choose roles',
|
|
172
|
+
options: [
|
|
173
|
+
{ label: 'Admin', value: 'admin' },
|
|
174
|
+
{ label: 'Mod', value: 'mod' }
|
|
175
|
+
]
|
|
176
|
+
)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Interactions
|
|
182
|
+
|
|
183
|
+
### Deferred Responses
|
|
184
|
+
|
|
185
|
+
```ruby
|
|
186
|
+
bot.slash('slow', 'A slow command') do |cmd|
|
|
187
|
+
cmd.handler do |interaction|
|
|
188
|
+
interaction.defer(ephemeral: true)
|
|
189
|
+
# Do slow work
|
|
190
|
+
sleep(5)
|
|
191
|
+
interaction.edit_original(content: 'Done!')
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Modals
|
|
197
|
+
|
|
198
|
+
```ruby
|
|
199
|
+
bot.slash('feedback', 'Submit feedback') do |cmd|
|
|
200
|
+
cmd.handler do |interaction|
|
|
201
|
+
interaction.modal(custom_id: 'feedback_modal', title: 'Send Feedback') do |modal|
|
|
202
|
+
modal.short(custom_id: 'subject', label: 'Subject', required: true)
|
|
203
|
+
modal.paragraph(custom_id: 'message', label: 'Your feedback', required: true)
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Handle modal submission
|
|
209
|
+
bot.on(:modal_submit) do |interaction|
|
|
210
|
+
subject = interaction.modal_value('subject')
|
|
211
|
+
message = interaction.modal_value('message')
|
|
212
|
+
interaction.respond(content: 'Thank you!', ephemeral: true)
|
|
213
|
+
end
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Documentation
|
|
217
|
+
|
|
218
|
+
- [Getting Started](docs/getting_started.md)
|
|
219
|
+
- [Architecture](docs/architecture.md)
|
|
220
|
+
- [API Reference](https://rubydoc.info/github/juliaklee/discord_rda)
|
|
221
|
+
|
|
222
|
+
## Examples
|
|
223
|
+
|
|
224
|
+
See the [examples](examples/) directory:
|
|
225
|
+
|
|
226
|
+
- `basic_bot.rb` - Simple echo bot
|
|
227
|
+
- `sharded_bot.rb` - Multi-shard example
|
|
228
|
+
- `plugin_bot.rb` - Custom plugin demonstration
|
|
229
|
+
- `slash_command_bot.rb` - Slash command handling
|
|
230
|
+
|
|
231
|
+
## Architecture
|
|
232
|
+
|
|
233
|
+
DiscordRDA follows a layered architecture designed for scalability:
|
|
234
|
+
|
|
235
|
+
```
|
|
236
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
237
|
+
β Application Layer β
|
|
238
|
+
β (Your bot code, commands, event handlers, plugins) β
|
|
239
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
|
|
240
|
+
β Interaction Layer β
|
|
241
|
+
β (Slash commands, components, modals, autocomplete) β
|
|
242
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
|
|
243
|
+
β Entity Layer β
|
|
244
|
+
β (User, Message, Guild, Channel - Factory Pattern) β
|
|
245
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
|
|
246
|
+
β Event System β
|
|
247
|
+
β (EventBus, subscriptions, middleware chain) β
|
|
248
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
|
|
249
|
+
β Connection Layer β
|
|
250
|
+
β (Gateway WebSocket, REST API client) β
|
|
251
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
|
|
252
|
+
β Scalability Layer β
|
|
253
|
+
β (Rate limiting, sharding, hot reload, caching) β
|
|
254
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
|
|
255
|
+
β Core Runtime β
|
|
256
|
+
β (Async scheduler, configuration, logging) β
|
|
257
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Key Design Principles
|
|
261
|
+
|
|
262
|
+
1. **Immutable by Default**: Entities are frozen after creation for thread safety
|
|
263
|
+
2. **Async-First**: All I/O operations are non-blocking using Ruby's Fiber scheduler
|
|
264
|
+
3. **Type Safety**: Full type coercion with attributes system
|
|
265
|
+
4. **Zero-Cost Abstractions**: No unnecessary object allocations
|
|
266
|
+
5. **Extensibility**: Plugin system for modular functionality
|
|
267
|
+
|
|
268
|
+
## Configuration
|
|
269
|
+
|
|
270
|
+
### Basic Configuration
|
|
271
|
+
|
|
272
|
+
```ruby
|
|
273
|
+
bot = DiscordRDA::Bot.new(
|
|
274
|
+
token: ENV['DISCORD_TOKEN'],
|
|
275
|
+
application_id: ENV['DISCORD_APP_ID'],
|
|
276
|
+
shards: :auto,
|
|
277
|
+
cache: :redis,
|
|
278
|
+
intents: [:guilds, :guild_messages, :message_content],
|
|
279
|
+
log_level: :info,
|
|
280
|
+
log_format: :json
|
|
281
|
+
)
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Advanced Configuration
|
|
285
|
+
|
|
286
|
+
```ruby
|
|
287
|
+
bot = DiscordRDA::Bot.new(
|
|
288
|
+
token: ENV['DISCORD_TOKEN'],
|
|
289
|
+
shards: [[0, 4], [1, 4]],
|
|
290
|
+
cache: :redis,
|
|
291
|
+
redis_config: { host: 'localhost', port: 6379 },
|
|
292
|
+
enable_scalable_rest: true,
|
|
293
|
+
intents: [:guilds, :guild_members, :guild_messages, :message_content]
|
|
294
|
+
)
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## Sharding
|
|
298
|
+
|
|
299
|
+
### Automatic Sharding
|
|
300
|
+
|
|
301
|
+
```ruby
|
|
302
|
+
bot = DiscordRDA::Bot.new(token: token, shards: :auto)
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Zero-Downtime Resharding
|
|
306
|
+
|
|
307
|
+
```ruby
|
|
308
|
+
# Enable auto-resharding
|
|
309
|
+
bot.enable_auto_reshard(max_guilds_per_shard: 1000)
|
|
310
|
+
|
|
311
|
+
# Manual resharding
|
|
312
|
+
bot.reshard_to(8)
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## Caching
|
|
316
|
+
|
|
317
|
+
### Memory Cache (Default)
|
|
318
|
+
|
|
319
|
+
```ruby
|
|
320
|
+
bot = DiscordRDA::Bot.new(token: token, cache: :memory, max_cache_size: 10000)
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Redis Cache
|
|
324
|
+
|
|
325
|
+
```ruby
|
|
326
|
+
bot = DiscordRDA::Bot.new(
|
|
327
|
+
token: token,
|
|
328
|
+
cache: :redis,
|
|
329
|
+
redis_config: { host: 'localhost', port: 6379 }
|
|
330
|
+
)
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Cache Invalidation
|
|
334
|
+
|
|
335
|
+
```ruby
|
|
336
|
+
bot.cache.invalidate(:user, user_id)
|
|
337
|
+
bot.cache.invalidate_guild(guild_id)
|
|
338
|
+
bot.cache.clear
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
## Rate Limiting
|
|
342
|
+
|
|
343
|
+
DiscordRDA includes advanced rate limit management:
|
|
344
|
+
|
|
345
|
+
```ruby
|
|
346
|
+
# Enable scalable REST (recommended for production)
|
|
347
|
+
bot.enable_scalable_rest
|
|
348
|
+
|
|
349
|
+
# Check invalid request bucket status
|
|
350
|
+
status = bot.invalid_bucket_status
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
## Plugin System
|
|
354
|
+
|
|
355
|
+
### Creating a Plugin
|
|
356
|
+
|
|
357
|
+
```ruby
|
|
358
|
+
class MusicPlugin < DiscordRDA::Plugin
|
|
359
|
+
def setup(bot)
|
|
360
|
+
@bot = bot
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
def ready(bot)
|
|
364
|
+
bot.logger.info('Music plugin ready')
|
|
365
|
+
end
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
bot.register_plugin(MusicPlugin.new)
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
## Development
|
|
372
|
+
|
|
373
|
+
### Hot Reload
|
|
374
|
+
|
|
375
|
+
```ruby
|
|
376
|
+
bot = DiscordRDA::Bot.new(token: token)
|
|
377
|
+
bot.enable_hot_reload(watch_dir: 'lib')
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
### Running Tests
|
|
381
|
+
|
|
382
|
+
```bash
|
|
383
|
+
bundle exec rspec
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
## Contributing
|
|
387
|
+
|
|
388
|
+
Bug reports and pull requests are welcome on GitHub.
|
|
389
|
+
|
|
390
|
+
## License
|
|
391
|
+
|
|
392
|
+
Licensed under the [MIT License](LICENSE).
|
|
393
|
+
|
|
394
|
+
Copyright (c) 2026 JΓΊlia Klee
|
|
395
|
+
|
|
396
|
+
## Acknowledgments
|
|
397
|
+
|
|
398
|
+
Created by JΓΊlia Klee. Inspired by DiscordJDA and other Discord libraries. Special thanks to the Ruby async community and Discord API documentation contributors.
|