ryanlink 1.0.1

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 (60) hide show
  1. package/LICENSE +37 -0
  2. package/README.md +455 -0
  3. package/dist/index.d.mts +1335 -0
  4. package/dist/index.d.ts +1335 -0
  5. package/dist/index.js +4694 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/index.mjs +4604 -0
  8. package/dist/index.mjs.map +1 -0
  9. package/package.json +82 -0
  10. package/src/audio/AudioFilters.ts +316 -0
  11. package/src/audio/AudioQueue.ts +782 -0
  12. package/src/audio/AudioTrack.ts +242 -0
  13. package/src/audio/QueueController.ts +252 -0
  14. package/src/audio/TrackCollection.ts +138 -0
  15. package/src/audio/index.ts +9 -0
  16. package/src/config/defaults.ts +223 -0
  17. package/src/config/endpoints.ts +99 -0
  18. package/src/config/index.ts +9 -0
  19. package/src/config/patterns.ts +55 -0
  20. package/src/config/presets.ts +400 -0
  21. package/src/config/symbols.ts +31 -0
  22. package/src/core/PluginSystem.ts +50 -0
  23. package/src/core/RyanlinkPlayer.ts +403 -0
  24. package/src/core/index.ts +6 -0
  25. package/src/extensions/AutoplayExtension.ts +283 -0
  26. package/src/extensions/FairPlayExtension.ts +154 -0
  27. package/src/extensions/LyricsExtension.ts +187 -0
  28. package/src/extensions/PersistenceExtension.ts +182 -0
  29. package/src/extensions/SponsorBlockExtension.ts +81 -0
  30. package/src/extensions/index.ts +9 -0
  31. package/src/index.ts +19 -0
  32. package/src/lavalink/ConnectionPool.ts +326 -0
  33. package/src/lavalink/HttpClient.ts +316 -0
  34. package/src/lavalink/LavalinkConnection.ts +409 -0
  35. package/src/lavalink/index.ts +7 -0
  36. package/src/metadata.ts +88 -0
  37. package/src/types/api/Rest.ts +949 -0
  38. package/src/types/api/Websocket.ts +463 -0
  39. package/src/types/api/index.ts +6 -0
  40. package/src/types/audio/FilterManager.ts +29 -0
  41. package/src/types/audio/Queue.ts +4 -0
  42. package/src/types/audio/QueueManager.ts +30 -0
  43. package/src/types/audio/index.ts +7 -0
  44. package/src/types/common.ts +63 -0
  45. package/src/types/core/Player.ts +322 -0
  46. package/src/types/core/index.ts +5 -0
  47. package/src/types/index.ts +6 -0
  48. package/src/types/lavalink/Node.ts +173 -0
  49. package/src/types/lavalink/NodeManager.ts +34 -0
  50. package/src/types/lavalink/REST.ts +144 -0
  51. package/src/types/lavalink/index.ts +32 -0
  52. package/src/types/voice/VoiceManager.ts +176 -0
  53. package/src/types/voice/index.ts +5 -0
  54. package/src/utils/helpers.ts +169 -0
  55. package/src/utils/index.ts +6 -0
  56. package/src/utils/validators.ts +184 -0
  57. package/src/voice/RegionSelector.ts +184 -0
  58. package/src/voice/VoiceConnection.ts +451 -0
  59. package/src/voice/VoiceSession.ts +297 -0
  60. package/src/voice/index.ts +7 -0
package/LICENSE ADDED
@@ -0,0 +1,37 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ 2. Grant of Copyright License.
10
+
11
+ 3. Grant of Patent License.
12
+
13
+ 4. Redistribution.
14
+
15
+ 5. Submission of Contributions.
16
+
17
+ 6. Trademarks.
18
+
19
+ 7. Disclaimer of Warranty.
20
+
21
+ 8. Limitation of Liability.
22
+
23
+ 9. Accepting Warranty or Additional Liability.
24
+
25
+ Copyright 2026 RY4N
26
+
27
+ Licensed under the Apache License, Version 2.0 (the "License");
28
+ you may not use this file except in compliance with the License.
29
+ You may obtain a copy of the License at
30
+
31
+ http://www.apache.org/licenses/LICENSE-2.0
32
+
33
+ Unless required by applicable law or agreed to in writing, software
34
+ distributed under the License is distributed on an "AS IS" BASIS,
35
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
36
+ See the License for the specific language governing permissions and
37
+ limitations under the License.
package/README.md ADDED
@@ -0,0 +1,455 @@
1
+ <div align="center">
2
+ <img alt="Ryanlink" src="assets/ryanlink.jpeg" width="120" />
3
+
4
+ # Ryanlink
5
+
6
+ A modern, feature-rich Lavalink client for Node.js with TypeScript support
7
+
8
+ <br/>
9
+
10
+ [![NPM Version](https://img.shields.io/npm/v/ryanlink?style=flat&logo=npm)](https://www.npmjs.com/package/ryanlink)
11
+ [![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
12
+ [![Node Version](https://img.shields.io/node/v/ryanlink)](https://nodejs.org)
13
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.3+-blue.svg?logo=typescript)](https://www.typescriptlang.org/)
14
+ [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/ryanwtf7/ryanlink/coverage.yml?branch=master&label=tests)](https://github.com/ryanwtf7/ryanlink/actions)
15
+
16
+ [Documentation](https://ryanwtf7.github.io/ryanlink) • [NPM Package](https://www.npmjs.com/package/ryanlink) • [GitHub](https://github.com/ryanwtf7/ryanlink)
17
+
18
+ </div>
19
+
20
+ ---
21
+
22
+ ## Overview
23
+
24
+ Ryanlink is a powerful Lavalink client library designed to simplify music bot development for Discord. Built with modern TypeScript and featuring a unique architecture, it provides an intuitive interface for managing audio playback, queues, and advanced audio processing.
25
+
26
+ ### Key Features
27
+
28
+ - **Modern Lavalink v4 Support** - Full compatibility with the latest Lavalink API
29
+ - **Cross-Runtime Compatibility** - Works seamlessly with Node.js, Bun, and Deno
30
+ - **Professional Audio Processing** - 17 built-in EQ presets for instant audio enhancement
31
+ - **Advanced Queue Management** - Sort, filter, search, and manipulate tracks with ease
32
+ - **Powerful Extensions System** - Autoplay, Lyrics, SponsorBlock, FairPlay, and Persistence
33
+ - **Type-Safe** - Complete TypeScript definitions with full IntelliSense support
34
+ - **Production Ready** - Comprehensive error handling, automatic reconnection, and session management
35
+ - **Flexible Architecture** - Feature-based organization for better maintainability
36
+
37
+ ### Supported Platforms
38
+
39
+ Ryanlink supports audio from 20+ streaming platforms through LavaSrc integration:
40
+
41
+ <div align="center">
42
+
43
+ | Platform | Support | Platform | Support | Platform | Support |
44
+ | ------------ | ------- | --------- | ------- | ------------ | ------- |
45
+ | YouTube | ✓ | Spotify | ✓ | Apple Music | ✓ |
46
+ | SoundCloud | ✓ | Deezer | ✓ | Tidal | ✓ |
47
+ | Bandcamp | ✓ | Twitch | ✓ | Amazon Music | ✓ |
48
+ | Yandex Music | ✓ | JioSaavn | ✓ | Pandora | ✓ |
49
+ | Qobuz | ✓ | Audiomack | ✓ | Mixcloud | ✓ |
50
+ | Anghami | ✓ | Audius | ✓ | Gaana | ✓ |
51
+ | Instagram | ✓ | Shazam | ✓ | Direct URLs | ✓ |
52
+
53
+ </div>
54
+
55
+ ## Installation
56
+
57
+ ```bash
58
+ # npm
59
+ npm install ryanlink
60
+
61
+ # yarn
62
+ yarn add ryanlink
63
+
64
+ # pnpm
65
+ pnpm add ryanlink
66
+
67
+ # bun
68
+ bun add ryanlink
69
+ ```
70
+
71
+ ### Deno
72
+
73
+ ```typescript
74
+ import { RyanlinkPlayer } from "npm:ryanlink@latest";
75
+ ```
76
+
77
+ ## Quick Start
78
+
79
+ ```typescript
80
+ import { Client } from "discord.js";
81
+ import { RyanlinkPlayer } from "ryanlink";
82
+
83
+ const client = new Client({ intents: ["Guilds", "GuildVoiceStates"] });
84
+
85
+ const player = new RyanlinkPlayer({
86
+ nodes: [
87
+ {
88
+ name: "main",
89
+ host: "localhost",
90
+ port: 2333,
91
+ password: "youshallnotpass",
92
+ secure: false,
93
+ },
94
+ ],
95
+ forwardVoiceUpdate: async (guildId, payload) => {
96
+ const guild = client.guilds.cache.get(guildId);
97
+ if (guild) guild.shard.send(payload);
98
+ },
99
+ });
100
+
101
+ client.on("ready", async () => {
102
+ await player.init(client.user.id);
103
+ console.log(`${client.user.tag} is ready!`);
104
+ });
105
+
106
+ client.on("raw", (packet) => {
107
+ player.voices.handleDispatch(packet);
108
+ });
109
+
110
+ client.login("YOUR_BOT_TOKEN");
111
+ ```
112
+
113
+ ## Core Concepts
114
+
115
+ ### Playing Music
116
+
117
+ ```typescript
118
+ // Play from URL or search query
119
+ const queue = await player.play("Never Gonna Give You Up", {
120
+ guildId: interaction.guildId,
121
+ voiceId: interaction.member.voice.channelId,
122
+ textId: interaction.channelId,
123
+ });
124
+
125
+ // Play from direct URL
126
+ await player.play("https://open.spotify.com/track/...", {
127
+ guildId: interaction.guildId,
128
+ voiceId: interaction.member.voice.channelId,
129
+ });
130
+
131
+ // Search with specific source
132
+ const results = await player.search("ytsearch:Rick Astley");
133
+ ```
134
+
135
+ ### Queue Management
136
+
137
+ ```typescript
138
+ const queue = player.getQueue(guildId);
139
+
140
+ // Basic controls
141
+ await queue.pause();
142
+ await queue.resume();
143
+ await queue.stop();
144
+ await queue.skip();
145
+ await queue.previous();
146
+
147
+ // Volume control
148
+ await queue.setVolume(0.5); // 50%
149
+
150
+ // Repeat modes
151
+ await queue.setRepeatMode("track"); // Repeat current track
152
+ await queue.setRepeatMode("queue"); // Repeat entire queue
153
+ await queue.setRepeatMode("off"); // No repeat
154
+
155
+ // Shuffle
156
+ await queue.shuffle();
157
+ await queue.shuffle(true); // Include previous tracks
158
+
159
+ // Seek
160
+ await queue.seek(60000); // Seek to 1 minute
161
+ ```
162
+
163
+ ### Advanced Queue Operations
164
+
165
+ ```typescript
166
+ // Sort tracks
167
+ await queue.sortBy("duration", "desc");
168
+ await queue.sortBy("title", "asc");
169
+ await queue.sortBy((a, b) => a.duration - b.duration);
170
+
171
+ // Filter tracks
172
+ const longTracks = queue.filterTracks({
173
+ duration: { min: 180000 }, // 3+ minutes
174
+ });
175
+
176
+ const rockTracks = queue.filterTracks({
177
+ title: "rock",
178
+ });
179
+
180
+ // Find specific track
181
+ const track = queue.findTrack({ title: "Never Gonna" });
182
+
183
+ // Move tracks
184
+ await queue.move(5, 0); // Move track at index 5 to front
185
+
186
+ // Remove tracks
187
+ await queue.remove(3); // Remove track at index 3
188
+
189
+ // Get track range
190
+ const nextTen = queue.getTracks(0, 10);
191
+ ```
192
+
193
+ ### Audio Filters
194
+
195
+ ```typescript
196
+ // Apply EQ preset
197
+ await queue.filters.setEQPreset("BassboostHigh");
198
+ await queue.filters.setEQPreset("Rock");
199
+ await queue.filters.setEQPreset("Nightcore");
200
+
201
+ // Get available presets
202
+ const presets = queue.filters.getEQPresetNames();
203
+ // ["BassboostEarrape", "BassboostHigh", "BassboostMedium", "BassboostLow",
204
+ // "Rock", "Classic", "Pop", "Electronic", "Gaming", "Nightcore",
205
+ // "Vaporwave", "TrebleBass", "HighQuality", "BetterMusic", "FullSound",
206
+ // "Soft", "TV", "Radio", "Normalization"]
207
+
208
+ // Custom filters
209
+ await queue.filters.apply({
210
+ equalizer: [
211
+ { band: 0, gain: 0.2 },
212
+ { band: 1, gain: 0.15 },
213
+ ],
214
+ timescale: { speed: 1.5, pitch: 1.2 },
215
+ volume: 1.0,
216
+ });
217
+
218
+ // Individual filter control
219
+ await queue.filters.set("timescale", { speed: 1.5 });
220
+ await queue.filters.delete("timescale");
221
+ await queue.filters.clear();
222
+ ```
223
+
224
+ ## Extensions
225
+
226
+ ### Autoplay Extension
227
+
228
+ Automatically plays related tracks when the queue ends.
229
+
230
+ ```typescript
231
+ import { AutoplayExtension } from "ryanlink";
232
+
233
+ const player = new RyanlinkPlayer({
234
+ plugins: [
235
+ new AutoplayExtension({
236
+ enabled: true,
237
+ maxHistory: 50,
238
+ sources: {
239
+ spotify: true,
240
+ youtube: true,
241
+ youtubemusic: true,
242
+ soundcloud: false,
243
+ },
244
+ }),
245
+ ],
246
+ });
247
+ ```
248
+
249
+ ### Lyrics Extension
250
+
251
+ Fetch synchronized lyrics from multiple sources.
252
+
253
+ ```typescript
254
+ import { LyricsExtension } from "ryanlink";
255
+
256
+ const player = new RyanlinkPlayer({
257
+ plugins: [
258
+ new LyricsExtension({
259
+ sources: ["lrclib", "genius", "musixmatch"],
260
+ cache: true,
261
+ }),
262
+ ],
263
+ });
264
+
265
+ // Get lyrics
266
+ const lyrics = await queue.getLyrics();
267
+ ```
268
+
269
+ ### SponsorBlock Extension
270
+
271
+ Skip sponsored segments in YouTube videos.
272
+
273
+ ```typescript
274
+ import { SponsorBlockExtension } from "ryanlink";
275
+
276
+ const player = new RyanlinkPlayer({
277
+ plugins: [
278
+ new SponsorBlockExtension({
279
+ categories: ["sponsor", "intro", "outro", "selfpromo"],
280
+ autoSkip: true,
281
+ }),
282
+ ],
283
+ });
284
+ ```
285
+
286
+ ### FairPlay Extension
287
+
288
+ Limit tracks per user for fair queue distribution.
289
+
290
+ ```typescript
291
+ import { FairPlayExtension } from "ryanlink";
292
+
293
+ const player = new RyanlinkPlayer({
294
+ plugins: [
295
+ new FairPlayExtension({
296
+ maxPerUser: 3,
297
+ enforceLimit: true,
298
+ }),
299
+ ],
300
+ });
301
+ ```
302
+
303
+ ### Persistence Extension
304
+
305
+ Save and restore queues across bot restarts.
306
+
307
+ ```typescript
308
+ import { PersistenceExtension } from "ryanlink";
309
+
310
+ const player = new RyanlinkPlayer({
311
+ plugins: [
312
+ new PersistenceExtension({
313
+ autoSave: true,
314
+ saveInterval: 60000, // 1 minute
315
+ }),
316
+ ],
317
+ });
318
+ ```
319
+
320
+ ## Events
321
+
322
+ ```typescript
323
+ // Track events
324
+ player.on("trackStart", (queue, track) => {
325
+ console.log(`Now playing: ${track.title}`);
326
+ });
327
+
328
+ player.on("trackFinish", (queue, track, reason) => {
329
+ console.log(`Finished: ${track.title} (${reason})`);
330
+ });
331
+
332
+ player.on("trackError", (queue, track, error) => {
333
+ console.error(`Error: ${error.message}`);
334
+ });
335
+
336
+ player.on("trackStuck", (queue, track, threshold) => {
337
+ console.warn(`Track stuck: ${track.title}`);
338
+ });
339
+
340
+ // Queue events
341
+ player.on("queueCreate", (queue) => {
342
+ console.log(`Queue created for guild ${queue.guildId}`);
343
+ });
344
+
345
+ player.on("queueFinish", (queue) => {
346
+ console.log("Queue finished!");
347
+ });
348
+
349
+ player.on("queueDestroy", (queue, reason) => {
350
+ console.log(`Queue destroyed: ${reason}`);
351
+ });
352
+
353
+ // Node events
354
+ player.on("nodeConnect", (node, reconnects) => {
355
+ console.log(`Node ${node.name} connected`);
356
+ });
357
+
358
+ player.on("nodeReady", (node, resumed, sessionId) => {
359
+ console.log(`Node ${node.name} ready`);
360
+ });
361
+
362
+ player.on("nodeDisconnect", (node, code, reason) => {
363
+ console.log(`Node ${node.name} disconnected`);
364
+ });
365
+
366
+ player.on("nodeError", (node, error) => {
367
+ console.error(`Node error: ${error.message}`);
368
+ });
369
+ ```
370
+
371
+ ## TypeScript Support
372
+
373
+ Ryanlink is built with TypeScript and provides complete type definitions.
374
+
375
+ ### Module Augmentation
376
+
377
+ Extend types for custom data:
378
+
379
+ ```typescript
380
+ declare module "ryanlink" {
381
+ interface QueueContext {
382
+ textChannelId: string;
383
+ requesterId: string;
384
+ }
385
+
386
+ interface CommonUserData {
387
+ id: string;
388
+ username: string;
389
+ requestedAt: number;
390
+ }
391
+
392
+ interface CommonPluginInfo {
393
+ customField?: string;
394
+ }
395
+ }
396
+ ```
397
+
398
+ ## Requirements
399
+
400
+ - **Node.js**: 18.0.0 or higher
401
+ - **Bun**: 1.0.0 or higher
402
+ - **Deno**: 1.30.0 or higher
403
+ - **Lavalink**: 4.0.0 or higher
404
+
405
+ ## Architecture
406
+
407
+ Ryanlink uses a feature-based architecture for better organization:
408
+
409
+ ```
410
+ src/
411
+ ├── core/ # Player and plugin system
412
+ ├── lavalink/ # Lavalink connection and HTTP client
413
+ ├── audio/ # Queue, tracks, and filters
414
+ ├── voice/ # Voice connection management
415
+ ├── extensions/ # Built-in extensions
416
+ ├── config/ # Configuration and constants
417
+ ├── utils/ # Utility functions
418
+ └── types/ # TypeScript definitions
419
+ ```
420
+
421
+ ## Performance
422
+
423
+ - **Efficient Memory Usage** - Optimized data structures and caching
424
+ - **Fast Track Loading** - Parallel track resolution
425
+ - **Minimal Overhead** - Native fetch API, no unnecessary dependencies
426
+ - **Smart Reconnection** - Automatic recovery with exponential backoff
427
+
428
+ ## Contributing
429
+
430
+ Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.
431
+
432
+ ## License
433
+
434
+ This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
435
+
436
+ ## Acknowledgements
437
+
438
+ Ryanlink was inspired by and builds upon concepts from:
439
+
440
+ - [distube](https://github.com/skick1234/DisTube) - Player-queue design patterns
441
+ - [discord.js](https://github.com/discordjs/discord.js) - Manager-cache architecture
442
+ - [Hoshimi](https://github.com/Ganyu-Studios/Hoshimi) - Module augmentation patterns
443
+ - [discolink](https://github.com/execaman/discolink) - Modern Lavalink client design
444
+
445
+ ## Support
446
+
447
+ - [Documentation](https://ryanwtf7.github.io/ryanlink)
448
+ - [GitHub Issues](https://github.com/ryanwtf7/ryanlink/issues)
449
+ - [GitHub Discussions](https://github.com/ryanwtf7/ryanlink/discussions)
450
+
451
+ ---
452
+
453
+ <div align="center">
454
+ Made with ❤️ by RY4N
455
+ </div>