@ziplayer/plugin 0.1.41 → 0.1.51
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.
- package/README.md +38 -2
- package/dist/AttachmentsPlugin.d.ts +192 -0
- package/dist/AttachmentsPlugin.d.ts.map +1 -0
- package/dist/AttachmentsPlugin.js +481 -0
- package/dist/AttachmentsPlugin.js.map +1 -0
- package/dist/TTSPlugin.d.ts +17 -0
- package/dist/TTSPlugin.d.ts.map +1 -1
- package/dist/TTSPlugin.js +67 -3
- package/dist/TTSPlugin.js.map +1 -1
- package/dist/index.d.ts +27 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +41 -11
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/src/AttachmentsPlugin.ts +523 -0
- package/src/TTSPlugin.ts +78 -3
- package/src/index.ts +28 -5
- package/src/utils/stream-converter.ts +79 -79
package/README.md
CHANGED
|
@@ -8,6 +8,7 @@ Official plugin bundle for ZiPlayer. It ships a set of ready‑to‑use source p
|
|
|
8
8
|
- SoundCloudPlugin: search + stream SoundCloud tracks and sets
|
|
9
9
|
- SpotifyPlugin: resolve tracks/albums/playlists, stream via fallbacks
|
|
10
10
|
- TTSPlugin: Text‑to‑Speech playback from simple `tts:` queries
|
|
11
|
+
- AttachmentsPlugin: handle Discord attachment URLs and direct audio file URLs
|
|
11
12
|
|
|
12
13
|
ZiPlayer is an audio player built on top of `@discordjs/voice` and `discord.js`. This package provides sources; the core player
|
|
13
14
|
lives in `ziplayer`.
|
|
@@ -28,15 +29,16 @@ npm install @zibot/zitts axios
|
|
|
28
29
|
|
|
29
30
|
```ts
|
|
30
31
|
import { PlayerManager } from "ziplayer";
|
|
31
|
-
import { YouTubePlugin, SoundCloudPlugin, SpotifyPlugin, TTSPlugin } from "@ziplayer/plugin";
|
|
32
|
+
import { YouTubePlugin, SoundCloudPlugin, SpotifyPlugin, TTSPlugin, AttachmentsPlugin } from "@ziplayer/plugin";
|
|
32
33
|
|
|
33
34
|
const manager = new PlayerManager({
|
|
34
35
|
plugins: [
|
|
35
|
-
// Order matters: put more specific handlers first (e.g., TTS)
|
|
36
|
+
// Order matters: put more specific handlers first (e.g., TTS, Attachments)
|
|
36
37
|
new TTSPlugin({ defaultLang: "en" }),
|
|
37
38
|
new YouTubePlugin(),
|
|
38
39
|
new SoundCloudPlugin(),
|
|
39
40
|
new SpotifyPlugin(),
|
|
41
|
+
new AttachmentsPlugin({ maxFileSize: 25 * 1024 * 1024 }), //25mb
|
|
40
42
|
],
|
|
41
43
|
});
|
|
42
44
|
|
|
@@ -53,6 +55,9 @@ await player.play("https://www.youtube.com/playlist?list=...", requestedBy);
|
|
|
53
55
|
// Speak with TTS
|
|
54
56
|
await player.play("tts:en:Hello there!", requestedBy);
|
|
55
57
|
|
|
58
|
+
// Play Discord attachment
|
|
59
|
+
await player.play("https://cdn.discordapp.com/attachments/123/456/audio.mp3", requestedBy);
|
|
60
|
+
|
|
56
61
|
// Handle events via the manager
|
|
57
62
|
manager.on("trackStart", (plr, track) => {
|
|
58
63
|
plr.userdata?.channel?.send?.(`Now playing: ${track.title}`);
|
|
@@ -93,6 +98,7 @@ const sp = new SpotifyPlugin();
|
|
|
93
98
|
### TTSPlugin (Text‑to‑Speech)
|
|
94
99
|
|
|
95
100
|
- Plays spoken audio from text using a lightweight Google TTS wrapper.
|
|
101
|
+
- **Accurate duration analysis**: Generates sample audio to measure actual duration instead of estimating.
|
|
96
102
|
- Supported query formats:
|
|
97
103
|
- `tts: <text>`
|
|
98
104
|
- `tts:<lang>:<text>` (e.g., `tts:vi:xin chao`)
|
|
@@ -101,6 +107,13 @@ const sp = new SpotifyPlugin();
|
|
|
101
107
|
```ts
|
|
102
108
|
import { TTSPlugin } from "@ziplayer/plugin";
|
|
103
109
|
const tts = new TTSPlugin({ defaultLang: "en", slow: false });
|
|
110
|
+
|
|
111
|
+
// The plugin automatically analyzes TTS duration
|
|
112
|
+
const result = await tts.search("tts:en:Hello world", "user123");
|
|
113
|
+
console.log(`Duration: ${result.tracks[0].duration}s`); // Real duration from audio analysis
|
|
114
|
+
console.log(`Language: ${result.tracks[0].metadata.language}`); // "en"
|
|
115
|
+
console.log(`Slow mode: ${result.tracks[0].metadata.slowMode}`); // false
|
|
116
|
+
|
|
104
117
|
await player.play("tts:en:1:good morning", requestedBy);
|
|
105
118
|
```
|
|
106
119
|
|
|
@@ -124,6 +137,29 @@ const tts = new TTSPlugin({
|
|
|
124
137
|
});
|
|
125
138
|
```
|
|
126
139
|
|
|
140
|
+
### AttachmentsPlugin
|
|
141
|
+
|
|
142
|
+
- Handles Discord attachment URLs and direct audio file URLs.
|
|
143
|
+
- Supports various audio formats (mp3, wav, ogg, m4a, flac, etc.).
|
|
144
|
+
- **Audio metadata analysis**: Extracts duration, title, artist, album, bitrate, etc.
|
|
145
|
+
- Includes file size validation and proper error handling.
|
|
146
|
+
- Uses Range requests to efficiently analyze metadata without downloading entire files.
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
import { AttachmentsPlugin } from "@ziplayer/plugin";
|
|
150
|
+
const attachments = new AttachmentsPlugin({
|
|
151
|
+
maxFileSize: 25 * 1024 * 1024, // 25MB
|
|
152
|
+
allowedExtensions: ["mp3", "wav", "ogg", "m4a", "flac"],
|
|
153
|
+
debug: true, // Enable to see metadata analysis process
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// The plugin automatically analyzes audio metadata
|
|
157
|
+
const result = await attachments.search("https://cdn.discordapp.com/attachments/123/456/song.mp3", "user123");
|
|
158
|
+
console.log(`Duration: ${result.tracks[0].duration}s`); // Real duration from metadata
|
|
159
|
+
console.log(`Title: ${result.tracks[0].title}`); // May be extracted from metadata
|
|
160
|
+
console.log(`Artist: ${result.tracks[0].metadata.artist}`); // From metadata
|
|
161
|
+
```
|
|
162
|
+
|
|
127
163
|
## Writing Your Own Plugin
|
|
128
164
|
|
|
129
165
|
Plugins implement the `BasePlugin` contract from `ziplayer`:
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { BasePlugin, Track, SearchResult, StreamInfo } from "ziplayer";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration options for the AttachmentsPlugin.
|
|
4
|
+
*/
|
|
5
|
+
export interface AttachmentsPluginOptions {
|
|
6
|
+
/** Maximum file size in bytes (default: 25MB) */
|
|
7
|
+
maxFileSize?: number;
|
|
8
|
+
/** Allowed audio file extensions */
|
|
9
|
+
allowedExtensions?: string[];
|
|
10
|
+
/** Whether to enable debug logging */
|
|
11
|
+
debug?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A plugin for handling Discord attachment URLs and local audio files.
|
|
15
|
+
*
|
|
16
|
+
* This plugin provides support for:
|
|
17
|
+
* - Discord attachment URLs (cdn.discordapp.com, media.discordapp.net)
|
|
18
|
+
* - Direct audio file URLs
|
|
19
|
+
* - Local file paths (if accessible)
|
|
20
|
+
* - Various audio formats (mp3, wav, ogg, m4a, flac, etc.)
|
|
21
|
+
* - File size validation
|
|
22
|
+
* - Audio metadata analysis (duration, title, artist, album, etc.)
|
|
23
|
+
* - Stream extraction from URLs
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* const attachmentsPlugin = new AttachmentsPlugin({
|
|
27
|
+
* maxFileSize: 25 * 1024 * 1024, // 25MB
|
|
28
|
+
* allowedExtensions: ['mp3', 'wav', 'ogg', 'm4a', 'flac']
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* // Add to PlayerManager
|
|
32
|
+
* const manager = new PlayerManager({
|
|
33
|
+
* plugins: [attachmentsPlugin]
|
|
34
|
+
* });
|
|
35
|
+
*
|
|
36
|
+
* // Search for attachment content
|
|
37
|
+
* const result = await attachmentsPlugin.search(
|
|
38
|
+
* "https://cdn.discordapp.com/attachments/123/456/audio.mp3",
|
|
39
|
+
* "user123"
|
|
40
|
+
* );
|
|
41
|
+
* const stream = await attachmentsPlugin.getStream(result.tracks[0]);
|
|
42
|
+
*
|
|
43
|
+
* @since 1.0.0
|
|
44
|
+
*/
|
|
45
|
+
export declare class AttachmentsPlugin extends BasePlugin {
|
|
46
|
+
name: string;
|
|
47
|
+
version: string;
|
|
48
|
+
private opts;
|
|
49
|
+
private readonly defaultAllowedExtensions;
|
|
50
|
+
/**
|
|
51
|
+
* Creates a new AttachmentsPlugin instance.
|
|
52
|
+
*
|
|
53
|
+
* @param opts - Configuration options for the attachments plugin
|
|
54
|
+
* @param opts.maxFileSize - Maximum file size in bytes (default: 25MB)
|
|
55
|
+
* @param opts.allowedExtensions - Allowed audio file extensions (default: common audio formats)
|
|
56
|
+
* @param opts.debug - Whether to enable debug logging (default: false)
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* // Basic attachments plugin
|
|
60
|
+
* const attachmentsPlugin = new AttachmentsPlugin();
|
|
61
|
+
*
|
|
62
|
+
* // Custom configuration
|
|
63
|
+
* const customPlugin = new AttachmentsPlugin({
|
|
64
|
+
* maxFileSize: 50 * 1024 * 1024, // 50MB
|
|
65
|
+
* allowedExtensions: ['mp3', 'wav', 'ogg'],
|
|
66
|
+
* debug: true
|
|
67
|
+
* });
|
|
68
|
+
*/
|
|
69
|
+
constructor(opts?: AttachmentsPluginOptions);
|
|
70
|
+
/**
|
|
71
|
+
* Determines if this plugin can handle the given query.
|
|
72
|
+
*
|
|
73
|
+
* @param query - The URL or file path to check
|
|
74
|
+
* @returns `true` if the query is a Discord attachment URL or audio file URL, `false` otherwise
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* plugin.canHandle("https://cdn.discordapp.com/attachments/123/456/audio.mp3"); // true
|
|
78
|
+
* plugin.canHandle("https://example.com/song.wav"); // true
|
|
79
|
+
* plugin.canHandle("youtube.com/watch?v=123"); // false
|
|
80
|
+
*/
|
|
81
|
+
canHandle(query: string): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Validates if a URL is a valid Discord attachment URL or audio file URL.
|
|
84
|
+
*
|
|
85
|
+
* @param url - The URL to validate
|
|
86
|
+
* @returns `true` if the URL is valid and points to an audio file, `false` otherwise
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* plugin.validate("https://cdn.discordapp.com/attachments/123/456/audio.mp3"); // true
|
|
90
|
+
* plugin.validate("https://example.com/song.wav"); // true
|
|
91
|
+
* plugin.validate("https://example.com/image.jpg"); // false
|
|
92
|
+
*/
|
|
93
|
+
validate(url: string): boolean;
|
|
94
|
+
/**
|
|
95
|
+
* Creates a track from an attachment URL or file path.
|
|
96
|
+
*
|
|
97
|
+
* This method handles both Discord attachment URLs and direct audio file URLs.
|
|
98
|
+
* It extracts metadata from the URL and creates a track that can be played.
|
|
99
|
+
*
|
|
100
|
+
* @param query - The attachment URL or file path
|
|
101
|
+
* @param requestedBy - The user ID who requested the track
|
|
102
|
+
* @returns A SearchResult containing a single track
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* // Discord attachment
|
|
106
|
+
* const result = await plugin.search(
|
|
107
|
+
* "https://cdn.discordapp.com/attachments/123/456/audio.mp3",
|
|
108
|
+
* "user123"
|
|
109
|
+
* );
|
|
110
|
+
*
|
|
111
|
+
* // Direct audio file URL
|
|
112
|
+
* const result2 = await plugin.search(
|
|
113
|
+
* "https://example.com/song.wav",
|
|
114
|
+
* "user123"
|
|
115
|
+
* );
|
|
116
|
+
*/
|
|
117
|
+
search(query: string, requestedBy: string): Promise<SearchResult>;
|
|
118
|
+
/**
|
|
119
|
+
* Retrieves the audio stream from an attachment URL or file path.
|
|
120
|
+
*
|
|
121
|
+
* This method downloads the audio file from the URL and returns it as a stream.
|
|
122
|
+
* It handles various audio formats and provides proper error handling.
|
|
123
|
+
*
|
|
124
|
+
* @param track - The Track object to get the stream for
|
|
125
|
+
* @returns A StreamInfo object containing the audio stream
|
|
126
|
+
* @throws {Error} If the URL is invalid, file is too large, or download fails
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* const track = {
|
|
130
|
+
* id: "attachment-123",
|
|
131
|
+
* title: "audio.mp3",
|
|
132
|
+
* url: "https://cdn.discordapp.com/attachments/123/456/audio.mp3",
|
|
133
|
+
* ...
|
|
134
|
+
* };
|
|
135
|
+
* const streamInfo = await plugin.getStream(track);
|
|
136
|
+
* console.log(streamInfo.type); // "arbitrary"
|
|
137
|
+
* console.log(streamInfo.stream); // Readable stream
|
|
138
|
+
*/
|
|
139
|
+
getStream(track: Track): Promise<StreamInfo>;
|
|
140
|
+
/**
|
|
141
|
+
* Provides a fallback by attempting to re-download the file.
|
|
142
|
+
*
|
|
143
|
+
* @param track - The Track object to get a fallback stream for
|
|
144
|
+
* @returns A StreamInfo object containing the fallback audio stream
|
|
145
|
+
* @throws {Error} If fallback download fails
|
|
146
|
+
*/
|
|
147
|
+
getFallback(track: Track): Promise<StreamInfo>;
|
|
148
|
+
/**
|
|
149
|
+
* Checks if a file path or URL is an audio file based on extension.
|
|
150
|
+
*/
|
|
151
|
+
private isAudioFile;
|
|
152
|
+
/**
|
|
153
|
+
* Extracts the file extension from a path or URL.
|
|
154
|
+
*/
|
|
155
|
+
private getFileExtension;
|
|
156
|
+
/**
|
|
157
|
+
* Extracts filename from a URL or path.
|
|
158
|
+
*/
|
|
159
|
+
private extractFilename;
|
|
160
|
+
/**
|
|
161
|
+
* Checks if a URL is a Discord attachment URL.
|
|
162
|
+
*/
|
|
163
|
+
private isDiscordAttachment;
|
|
164
|
+
/**
|
|
165
|
+
* Generates a unique track ID for a given URL.
|
|
166
|
+
*/
|
|
167
|
+
private generateTrackId;
|
|
168
|
+
/**
|
|
169
|
+
* Simple hash function for generating IDs.
|
|
170
|
+
*/
|
|
171
|
+
private simpleHash;
|
|
172
|
+
/**
|
|
173
|
+
* Determines the appropriate stream type based on content type and file extension.
|
|
174
|
+
*/
|
|
175
|
+
private getStreamType;
|
|
176
|
+
/**
|
|
177
|
+
* Formats bytes into a human-readable string.
|
|
178
|
+
*/
|
|
179
|
+
private formatBytes;
|
|
180
|
+
/**
|
|
181
|
+
* Analyzes audio metadata to extract duration and other information.
|
|
182
|
+
*
|
|
183
|
+
* @param url - The URL to analyze
|
|
184
|
+
* @returns Promise containing duration in seconds and metadata
|
|
185
|
+
*/
|
|
186
|
+
private analyzeAudioMetadata;
|
|
187
|
+
/**
|
|
188
|
+
* Debug logging helper.
|
|
189
|
+
*/
|
|
190
|
+
private debug;
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=AttachmentsPlugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AttachmentsPlugin.d.ts","sourceRoot":"","sources":["../src/AttachmentsPlugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAKvE;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACxC,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,sCAAsC;IACtC,KAAK,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,qBAAa,iBAAkB,SAAQ,UAAU;IAChD,IAAI,SAAiB;IACrB,OAAO,SAAW;IAElB,OAAO,CAAC,IAAI,CAA2B;IACvC,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAsE;IAE/G;;;;;;;;;;;;;;;;;;OAkBG;gBACS,IAAI,CAAC,EAAE,wBAAwB;IAS3C;;;;;;;;;;OAUG;IACH,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IA8BjC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI9B;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IA0EvE;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC;IA0DlD;;;;;;OAMG;IACG,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC;IAKpD;;OAEG;IACH,OAAO,CAAC,WAAW;IAKnB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAUxB;;OAEG;IACH,OAAO,CAAC,eAAe;IAiBvB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAS3B;;OAEG;IACH,OAAO,CAAC,eAAe;IAMvB;;OAEG;IACH,OAAO,CAAC,UAAU;IAUlB;;OAEG;IACH,OAAO,CAAC,aAAa;IAgBrB;;OAEG;IACH,OAAO,CAAC,WAAW;IAQnB;;;;;OAKG;YACW,oBAAoB;IA2ElC;;OAEG;IACH,OAAO,CAAC,KAAK;CAKb"}
|