@ziplayer/plugin 0.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.
- package/README.md +145 -0
- package/dist/SoundCloudPlugin.d.ts +21 -0
- package/dist/SoundCloudPlugin.d.ts.map +1 -0
- package/dist/SoundCloudPlugin.js +171 -0
- package/dist/SoundCloudPlugin.js.map +1 -0
- package/dist/SpotifyPlugin.d.ts +25 -0
- package/dist/SpotifyPlugin.d.ts.map +1 -0
- package/dist/SpotifyPlugin.js +183 -0
- package/dist/SpotifyPlugin.js.map +1 -0
- package/dist/YouTubePlugin.d.ts +24 -0
- package/dist/YouTubePlugin.d.ts.map +1 -0
- package/dist/YouTubePlugin.js +302 -0
- package/dist/YouTubePlugin.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/package.json +21 -0
- package/src/SoundCloudPlugin.ts +191 -0
- package/src/SpotifyPlugin.ts +204 -0
- package/src/YouTubePlugin.ts +320 -0
- package/src/index.ts +3 -0
- package/tsconfig.json +23 -0
package/README.md
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
|
|
2
|
+
# @zibot/player
|
|
3
|
+
|
|
4
|
+
A modular Discord voice player with plugin system for @discordjs/voice.
|
|
5
|
+
|
|
6
|
+
## Features
|
|
7
|
+
|
|
8
|
+
- 🎵 **Plugin-based architecture** - Easy to extend with new sources
|
|
9
|
+
- 🎶 **Multiple source support** - YouTube, SoundCloud, Spotify (with fallback)
|
|
10
|
+
- 🔊 **Queue management** - Add, remove, shuffle, clear
|
|
11
|
+
- 🎚️ **Volume control** - 0-200% volume range
|
|
12
|
+
- ⏯️ **Playback control** - Play, pause, resume, stop, skip
|
|
13
|
+
- 🔁 **Auto play** - Automatically replay the queue when it ends
|
|
14
|
+
- 📊 **Progress bar** - Display playback progress with customizable icons
|
|
15
|
+
- 🔔 **Event-driven** - Rich event system for all player actions
|
|
16
|
+
- 🎭 **Multi-guild support** - Manage players across multiple Discord servers
|
|
17
|
+
- 🗃️ **User data** - Attach custom data to each player for later use
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @zibot/player @discordjs/voice discord.js
|
|
23
|
+
|
|
24
|
+
# Optional dependencies for plugins:
|
|
25
|
+
npm install ytdl-core youtube-sr # YouTube plugin
|
|
26
|
+
npm install soundcloud-scraper # SoundCloud plugin
|
|
27
|
+
npm install spotify-web-api-node # Spotify plugin
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { PlayerManager, YouTubePlugin, SoundCloudPlugin } from '@zibot/player';
|
|
34
|
+
|
|
35
|
+
const youtubePlugin = new YouTubePlugin();
|
|
36
|
+
const soundCloudPlugin = new SoundCloudPlugin();
|
|
37
|
+
|
|
38
|
+
// Create player manager with YouTube and SoundCloud plugins
|
|
39
|
+
const manager = new PlayerManager({
|
|
40
|
+
plugins: [soundCloudPlugin, youtubePlugin],
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Create player
|
|
44
|
+
const player = manager.create(guildId, {
|
|
45
|
+
leaveOnEnd: true,
|
|
46
|
+
leaveTimeout: 30000,
|
|
47
|
+
userdata: { channel: textChannel }, // store channel for events
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Connect and play
|
|
51
|
+
await player.connect(voiceChannel);
|
|
52
|
+
await player.play('Never Gonna Give You Up', userId);
|
|
53
|
+
|
|
54
|
+
// Play a full YouTube playlist
|
|
55
|
+
await player.play('https://www.youtube.com/playlist?list=PL123', userId);
|
|
56
|
+
|
|
57
|
+
// Enable autoplay
|
|
58
|
+
player.queue.autoPlay(true);
|
|
59
|
+
|
|
60
|
+
// Play a full SoundCloud playlist
|
|
61
|
+
await player.play('https://soundcloud.com/artist/sets/playlist', userId);
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
// Events
|
|
65
|
+
player.on('willPlay', (track) => {
|
|
66
|
+
console.log(`Up next: ${track.title}`);
|
|
67
|
+
});
|
|
68
|
+
player.on('trackStart', (track) => {
|
|
69
|
+
console.log(`Now playing: ${track.title}`);
|
|
70
|
+
player.userdata?.channel?.send(`Now playing: ${track.title}`);
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Available Plugins
|
|
75
|
+
|
|
76
|
+
### YouTubePlugin
|
|
77
|
+
Supports YouTube videos and playlists.
|
|
78
|
+
```typescript
|
|
79
|
+
import { YouTubePlugin } from '@zibot/player';
|
|
80
|
+
const youtube = new YouTubePlugin();
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### SoundCloudPlugin
|
|
84
|
+
Supports SoundCloud tracks and playlists.
|
|
85
|
+
```typescript
|
|
86
|
+
import { SoundCloudPlugin } from '@zibot/player';
|
|
87
|
+
const soundcloud = new SoundCloudPlugin();
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### SpotifyPlugin
|
|
91
|
+
Supports Spotify tracks, albums, and playlists (requires fallback plugin for streaming).
|
|
92
|
+
```typescript
|
|
93
|
+
import { SpotifyPlugin } from '@zibot/player';
|
|
94
|
+
const spotify = new SpotifyPlugin(clientId, clientSecret, youtubePlugin);
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Creating Custom Plugins
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
import { BasePlugin, Track, SearchResult, StreamInfo } from '@zibot/player';
|
|
101
|
+
|
|
102
|
+
export class MyPlugin extends BasePlugin {
|
|
103
|
+
name = 'myplugin';
|
|
104
|
+
version = '1.0.0';
|
|
105
|
+
|
|
106
|
+
canHandle(query: string): boolean {
|
|
107
|
+
return query.includes('mysite.com');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async search(query: string, requestedBy: string): Promise<SearchResult> {
|
|
111
|
+
// Implement search logic
|
|
112
|
+
return { tracks: [/* ... */] };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async getStream(track: Track): Promise<StreamInfo> {
|
|
116
|
+
// Return audio stream
|
|
117
|
+
return { stream, type: 'arbitrary' };
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Events
|
|
123
|
+
|
|
124
|
+
All player events are forwarded through the PlayerManager:
|
|
125
|
+
|
|
126
|
+
- `trackStart` - When a track starts playing
|
|
127
|
+
- `willPlay` - Before a track begins playing
|
|
128
|
+
- `trackEnd` - When a track finishes
|
|
129
|
+
- `queueEnd` - When the queue is empty
|
|
130
|
+
- `playerError` - When an error occurs
|
|
131
|
+
- `queueAdd` - When a track is added
|
|
132
|
+
- `volumeChange` - When volume changes
|
|
133
|
+
- And more...
|
|
134
|
+
|
|
135
|
+
## Progress Bar
|
|
136
|
+
|
|
137
|
+
Display the current playback progress with `getProgressBar`:
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
console.log(player.getProgressBar({ size: 30, barChar: "-", progressChar: "🔘" }));
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## License
|
|
144
|
+
|
|
145
|
+
MIT License
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BasePlugin, Track, SearchResult, StreamInfo } from "ziplayer";
|
|
2
|
+
export declare class SoundCloudPlugin extends BasePlugin {
|
|
3
|
+
name: string;
|
|
4
|
+
version: string;
|
|
5
|
+
private client;
|
|
6
|
+
private ready;
|
|
7
|
+
constructor();
|
|
8
|
+
private init;
|
|
9
|
+
canHandle(query: string): boolean;
|
|
10
|
+
validate(url: string): boolean;
|
|
11
|
+
search(query: string, requestedBy: string): Promise<SearchResult>;
|
|
12
|
+
getStream(track: Track): Promise<StreamInfo>;
|
|
13
|
+
getRelatedTracks(trackURL: string | number, opts?: {
|
|
14
|
+
limit?: number;
|
|
15
|
+
offset?: number;
|
|
16
|
+
history?: Track[];
|
|
17
|
+
}): Promise<Track[]>;
|
|
18
|
+
getFallback(track: Track): Promise<StreamInfo>;
|
|
19
|
+
extractPlaylist(url: string, requestedBy: string): Promise<Track[]>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=SoundCloudPlugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SoundCloudPlugin.d.ts","sourceRoot":"","sources":["../src/SoundCloudPlugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAIvE,qBAAa,gBAAiB,SAAQ,UAAU;IAC9C,IAAI,SAAgB;IACpB,OAAO,SAAW;IAClB,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,KAAK,CAAgB;;YAOf,IAAI;IAKlB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAOjC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIxB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAsEjE,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC;IAmB5C,gBAAgB,CACpB,QAAQ,EAAE,MAAM,GAAG,MAAM,EACzB,IAAI,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAA;KAAO,GAChE,OAAO,CAAC,KAAK,EAAE,CAAC;IAoCb,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC;IAS9C,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;CAsB1E"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SoundCloudPlugin = void 0;
|
|
4
|
+
const ziplayer_1 = require("ziplayer");
|
|
5
|
+
const SoundCloud = require("@zibot/scdl");
|
|
6
|
+
class SoundCloudPlugin extends ziplayer_1.BasePlugin {
|
|
7
|
+
constructor() {
|
|
8
|
+
super();
|
|
9
|
+
this.name = "soundcloud";
|
|
10
|
+
this.version = "1.0.0";
|
|
11
|
+
this.ready = this.init();
|
|
12
|
+
}
|
|
13
|
+
async init() {
|
|
14
|
+
this.client = new SoundCloud({ init: false });
|
|
15
|
+
await this.client.init();
|
|
16
|
+
}
|
|
17
|
+
canHandle(query) {
|
|
18
|
+
return (query.includes("soundcloud.com") ||
|
|
19
|
+
(!query.startsWith("http") && !query.includes("youtube")));
|
|
20
|
+
}
|
|
21
|
+
validate(url) {
|
|
22
|
+
return url.includes("soundcloud.com");
|
|
23
|
+
}
|
|
24
|
+
async search(query, requestedBy) {
|
|
25
|
+
await this.ready;
|
|
26
|
+
try {
|
|
27
|
+
if (query.includes("soundcloud.com")) {
|
|
28
|
+
try {
|
|
29
|
+
const info = await this.client.getTrackDetails(query);
|
|
30
|
+
const track = {
|
|
31
|
+
id: info.id.toString(),
|
|
32
|
+
title: info.title,
|
|
33
|
+
url: info.permalink_url || query,
|
|
34
|
+
duration: info.duration,
|
|
35
|
+
thumbnail: info.artwork_url,
|
|
36
|
+
requestedBy,
|
|
37
|
+
source: this.name,
|
|
38
|
+
metadata: {
|
|
39
|
+
author: info.user?.username,
|
|
40
|
+
plays: info.playback_count,
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
return { tracks: [track] };
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
const playlist = await this.client.getPlaylistDetails(query);
|
|
47
|
+
const tracks = playlist.tracks.map((t) => ({
|
|
48
|
+
id: t.id.toString(),
|
|
49
|
+
title: t.title,
|
|
50
|
+
url: t.permalink_url,
|
|
51
|
+
duration: t.duration,
|
|
52
|
+
thumbnail: t.artwork_url || playlist.artwork_url,
|
|
53
|
+
requestedBy,
|
|
54
|
+
source: this.name,
|
|
55
|
+
metadata: {
|
|
56
|
+
author: t.user?.username,
|
|
57
|
+
plays: t.playback_count,
|
|
58
|
+
playlist: playlist.id?.toString(),
|
|
59
|
+
},
|
|
60
|
+
}));
|
|
61
|
+
return {
|
|
62
|
+
tracks,
|
|
63
|
+
playlist: {
|
|
64
|
+
name: playlist.title,
|
|
65
|
+
url: playlist.permalink_url || query,
|
|
66
|
+
thumbnail: playlist.artwork_url,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const results = await this.client.searchTracks({ query, limit: 15 });
|
|
72
|
+
const tracks = results.slice(0, 10).map((track) => ({
|
|
73
|
+
id: track.id.toString(),
|
|
74
|
+
title: track.title,
|
|
75
|
+
url: track.permalink_url,
|
|
76
|
+
duration: track.duration,
|
|
77
|
+
thumbnail: track.artwork_url,
|
|
78
|
+
requestedBy,
|
|
79
|
+
source: this.name,
|
|
80
|
+
metadata: {
|
|
81
|
+
author: track.user?.username,
|
|
82
|
+
plays: track.playback_count,
|
|
83
|
+
},
|
|
84
|
+
}));
|
|
85
|
+
return { tracks };
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
throw new Error(`SoundCloud search failed: ${error?.message}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async getStream(track) {
|
|
92
|
+
await this.ready;
|
|
93
|
+
try {
|
|
94
|
+
const stream = await this.client.downloadTrack(track.url);
|
|
95
|
+
if (!stream) {
|
|
96
|
+
throw new Error("SoundCloud download returned null");
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
stream,
|
|
100
|
+
type: "arbitrary",
|
|
101
|
+
metadata: track.metadata,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
throw new Error(`Failed to get SoundCloud stream: ${error.message}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
async getRelatedTracks(trackURL, opts = {}) {
|
|
109
|
+
await this.ready;
|
|
110
|
+
try {
|
|
111
|
+
const tracks = await this.client.getRelatedTracks(trackURL, {
|
|
112
|
+
limit: 30,
|
|
113
|
+
filter: "tracks",
|
|
114
|
+
});
|
|
115
|
+
if (!tracks || !tracks?.length) {
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
const relatedfilter = tracks.filter((tr) => !(opts?.history ?? []).some((t) => t.url === tr.permalink_url));
|
|
119
|
+
const related = relatedfilter.slice(0, opts.limit || 1);
|
|
120
|
+
return related.map((t) => ({
|
|
121
|
+
id: t.id.toString(),
|
|
122
|
+
title: t.title,
|
|
123
|
+
url: t.permalink_url,
|
|
124
|
+
duration: t.duration,
|
|
125
|
+
thumbnail: t.artwork_url,
|
|
126
|
+
requestedBy: "auto",
|
|
127
|
+
source: this.name,
|
|
128
|
+
metadata: {
|
|
129
|
+
author: t.user?.username,
|
|
130
|
+
plays: t.playback_count,
|
|
131
|
+
},
|
|
132
|
+
}));
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
async getFallback(track) {
|
|
139
|
+
const trackfall = await this.search(track.title, track.requestedBy);
|
|
140
|
+
const fallbackTrack = trackfall.tracks?.[0];
|
|
141
|
+
if (!fallbackTrack) {
|
|
142
|
+
throw new Error(`No fallback track found for ${track.title}`);
|
|
143
|
+
}
|
|
144
|
+
return await this.getStream(fallbackTrack);
|
|
145
|
+
}
|
|
146
|
+
async extractPlaylist(url, requestedBy) {
|
|
147
|
+
await this.ready;
|
|
148
|
+
try {
|
|
149
|
+
const playlist = await this.client.getPlaylistDetails(url);
|
|
150
|
+
return playlist.tracks.map((t) => ({
|
|
151
|
+
id: t.id.toString(),
|
|
152
|
+
title: t.title,
|
|
153
|
+
url: t.permalink_url,
|
|
154
|
+
duration: t.duration,
|
|
155
|
+
thumbnail: t.artwork_url || playlist.artwork_url,
|
|
156
|
+
requestedBy,
|
|
157
|
+
source: this.name,
|
|
158
|
+
metadata: {
|
|
159
|
+
author: t.user?.username,
|
|
160
|
+
plays: t.playback_count,
|
|
161
|
+
playlist: playlist.id?.toString(),
|
|
162
|
+
},
|
|
163
|
+
}));
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
return [];
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
exports.SoundCloudPlugin = SoundCloudPlugin;
|
|
171
|
+
//# sourceMappingURL=SoundCloudPlugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SoundCloudPlugin.js","sourceRoot":"","sources":["../src/SoundCloudPlugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { BasePlugin, Track, SearchResult, StreamInfo } from "ziplayer";
|
|
2
|
+
/**
|
|
3
|
+
* This minimal Spotify plugin:
|
|
4
|
+
* - Parses Spotify URLs/URIs (track/playlist/album)
|
|
5
|
+
* - Uses Spotify's public oEmbed endpoint to fetch *display metadata* (no auth, no SDK)
|
|
6
|
+
* - Does NOT provide audio streams (player is expected to redirect/fallback upstream)
|
|
7
|
+
* - Does NOT expand playlists/albums (no SDK; oEmbed doesn't enumerate items)
|
|
8
|
+
*/
|
|
9
|
+
export declare class SpotifyPlugin extends BasePlugin {
|
|
10
|
+
name: string;
|
|
11
|
+
version: string;
|
|
12
|
+
canHandle(query: string): boolean;
|
|
13
|
+
validate(url: string): boolean;
|
|
14
|
+
search(query: string, requestedBy: string): Promise<SearchResult>;
|
|
15
|
+
extractPlaylist(_input: string, _requestedBy: string): Promise<Track[]>;
|
|
16
|
+
extractAlbum(_input: string, _requestedBy: string): Promise<Track[]>;
|
|
17
|
+
getStream(_track: Track): Promise<StreamInfo>;
|
|
18
|
+
private identifyKind;
|
|
19
|
+
private extractId;
|
|
20
|
+
private buildTrackFromUrlOrUri;
|
|
21
|
+
private buildHeaderItem;
|
|
22
|
+
private toShareUrl;
|
|
23
|
+
private fetchOEmbed;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=SpotifyPlugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SpotifyPlugin.d.ts","sourceRoot":"","sources":["../src/SpotifyPlugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAO,UAAU,CAAC;AAEvE;;;;;;GAMG;AACH,qBAAa,aAAc,SAAQ,UAAU;IAC3C,IAAI,SAAa;IACjB,OAAO,SAAW;IAElB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAWjC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAUxB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAyBjE,eAAe,CACnB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,KAAK,EAAE,CAAC;IAIb,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAIpE,SAAS,CAAC,MAAM,EAAE,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC;IAInD,OAAO,CAAC,YAAY;IAsBpB,OAAO,CAAC,SAAS;YAeH,sBAAsB;YA6BtB,eAAe;IA8B7B,OAAO,CAAC,UAAU;YAeJ,WAAW;CAkB1B"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SpotifyPlugin = void 0;
|
|
4
|
+
const ziplayer_1 = require("ziplayer");
|
|
5
|
+
/**
|
|
6
|
+
* This minimal Spotify plugin:
|
|
7
|
+
* - Parses Spotify URLs/URIs (track/playlist/album)
|
|
8
|
+
* - Uses Spotify's public oEmbed endpoint to fetch *display metadata* (no auth, no SDK)
|
|
9
|
+
* - Does NOT provide audio streams (player is expected to redirect/fallback upstream)
|
|
10
|
+
* - Does NOT expand playlists/albums (no SDK; oEmbed doesn't enumerate items)
|
|
11
|
+
*/
|
|
12
|
+
class SpotifyPlugin extends ziplayer_1.BasePlugin {
|
|
13
|
+
constructor() {
|
|
14
|
+
super(...arguments);
|
|
15
|
+
this.name = "spotify";
|
|
16
|
+
this.version = "1.1.0";
|
|
17
|
+
}
|
|
18
|
+
canHandle(query) {
|
|
19
|
+
const q = query.toLowerCase().trim();
|
|
20
|
+
if (q.startsWith("spotify:"))
|
|
21
|
+
return true;
|
|
22
|
+
try {
|
|
23
|
+
const u = new URL(q);
|
|
24
|
+
return u.hostname.includes("open.spotify.com");
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
validate(url) {
|
|
31
|
+
if (url.startsWith("spotify:"))
|
|
32
|
+
return true;
|
|
33
|
+
try {
|
|
34
|
+
const u = new URL(url);
|
|
35
|
+
return u.hostname.includes("open.spotify.com");
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async search(query, requestedBy) {
|
|
42
|
+
if (!this.validate(query)) {
|
|
43
|
+
return { tracks: [] };
|
|
44
|
+
}
|
|
45
|
+
const kind = this.identifyKind(query);
|
|
46
|
+
if (kind === "track") {
|
|
47
|
+
const t = await this.buildTrackFromUrlOrUri(query, requestedBy);
|
|
48
|
+
return { tracks: t ? [t] : [] };
|
|
49
|
+
}
|
|
50
|
+
if (kind === "playlist") {
|
|
51
|
+
const t = await this.buildHeaderItem(query, requestedBy, "playlist");
|
|
52
|
+
return { tracks: t ? [t] : [] };
|
|
53
|
+
}
|
|
54
|
+
if (kind === "album") {
|
|
55
|
+
const t = await this.buildHeaderItem(query, requestedBy, "album");
|
|
56
|
+
return { tracks: t ? [t] : [] };
|
|
57
|
+
}
|
|
58
|
+
return { tracks: [] };
|
|
59
|
+
}
|
|
60
|
+
async extractPlaylist(_input, _requestedBy) {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
async extractAlbum(_input, _requestedBy) {
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
async getStream(_track) {
|
|
67
|
+
throw new Error("Spotify streaming is not supported by this plugin");
|
|
68
|
+
}
|
|
69
|
+
identifyKind(input) {
|
|
70
|
+
if (input.startsWith("spotify:")) {
|
|
71
|
+
if (input.includes(":track:"))
|
|
72
|
+
return "track";
|
|
73
|
+
if (input.includes(":playlist:"))
|
|
74
|
+
return "playlist";
|
|
75
|
+
if (input.includes(":album:"))
|
|
76
|
+
return "album";
|
|
77
|
+
return "unknown";
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
const u = new URL(input);
|
|
81
|
+
const parts = u.pathname.split("/").filter(Boolean);
|
|
82
|
+
const kind = parts[0];
|
|
83
|
+
if (kind === "track")
|
|
84
|
+
return "track";
|
|
85
|
+
if (kind === "playlist")
|
|
86
|
+
return "playlist";
|
|
87
|
+
if (kind === "album")
|
|
88
|
+
return "album";
|
|
89
|
+
return "unknown";
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return "unknown";
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
extractId(input) {
|
|
96
|
+
if (!input)
|
|
97
|
+
return null;
|
|
98
|
+
if (input.startsWith("spotify:")) {
|
|
99
|
+
const parts = input.split(":");
|
|
100
|
+
return parts[2] || null;
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
const u = new URL(input);
|
|
104
|
+
const parts = u.pathname.split("/").filter(Boolean);
|
|
105
|
+
return parts[1] || null; // /track/<id>
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
async buildTrackFromUrlOrUri(input, requestedBy) {
|
|
112
|
+
const id = this.extractId(input);
|
|
113
|
+
if (!id)
|
|
114
|
+
return null;
|
|
115
|
+
const url = this.toShareUrl(input, "track", id);
|
|
116
|
+
const meta = await this.fetchOEmbed(url).catch(() => undefined);
|
|
117
|
+
const title = meta?.title || `Spotify Track ${id}`;
|
|
118
|
+
const thumbnail = meta?.thumbnail_url;
|
|
119
|
+
const track = {
|
|
120
|
+
id,
|
|
121
|
+
title,
|
|
122
|
+
url,
|
|
123
|
+
duration: 0,
|
|
124
|
+
thumbnail,
|
|
125
|
+
requestedBy,
|
|
126
|
+
source: this.name,
|
|
127
|
+
metadata: {
|
|
128
|
+
author: meta?.author_name,
|
|
129
|
+
provider: meta?.provider_name,
|
|
130
|
+
spotify_id: id,
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
return track;
|
|
134
|
+
}
|
|
135
|
+
async buildHeaderItem(input, requestedBy, kind) {
|
|
136
|
+
const id = this.extractId(input);
|
|
137
|
+
if (!id)
|
|
138
|
+
return null;
|
|
139
|
+
const url = this.toShareUrl(input, kind, id);
|
|
140
|
+
const meta = await this.fetchOEmbed(url).catch(() => undefined);
|
|
141
|
+
const title = meta?.title || `Spotify ${kind} ${id}`;
|
|
142
|
+
const thumbnail = meta?.thumbnail_url;
|
|
143
|
+
return {
|
|
144
|
+
id,
|
|
145
|
+
title,
|
|
146
|
+
url,
|
|
147
|
+
duration: 0,
|
|
148
|
+
thumbnail,
|
|
149
|
+
requestedBy,
|
|
150
|
+
source: this.name,
|
|
151
|
+
metadata: {
|
|
152
|
+
author: meta?.author_name,
|
|
153
|
+
provider: meta?.provider_name,
|
|
154
|
+
spotify_id: id,
|
|
155
|
+
kind,
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
toShareUrl(input, expectedKind, id) {
|
|
160
|
+
if (input.startsWith("spotify:")) {
|
|
161
|
+
return `https://open.spotify.com/${expectedKind}/${id}`;
|
|
162
|
+
}
|
|
163
|
+
try {
|
|
164
|
+
const u = new URL(input);
|
|
165
|
+
const parts = u.pathname.split("/").filter(Boolean);
|
|
166
|
+
const kind = parts[0] || expectedKind;
|
|
167
|
+
const realId = parts[1] || id;
|
|
168
|
+
return `https://open.spotify.com/${kind}/${realId}`;
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
return `https://open.spotify.com/${expectedKind}/${id}`;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
async fetchOEmbed(pageUrl) {
|
|
175
|
+
const endpoint = `https://open.spotify.com/oembed?url=${encodeURIComponent(pageUrl)}`;
|
|
176
|
+
const res = await fetch(endpoint);
|
|
177
|
+
if (!res.ok)
|
|
178
|
+
throw new Error(`oEmbed HTTP ${res.status}`);
|
|
179
|
+
return res.json();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
exports.SpotifyPlugin = SpotifyPlugin;
|
|
183
|
+
//# sourceMappingURL=SpotifyPlugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SpotifyPlugin.js","sourceRoot":"","sources":["../src/SpotifyPlugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { BasePlugin, Track, SearchResult, StreamInfo } from "ziplayer";
|
|
2
|
+
export declare class YouTubePlugin extends BasePlugin {
|
|
3
|
+
name: string;
|
|
4
|
+
version: string;
|
|
5
|
+
private client;
|
|
6
|
+
private searchClient;
|
|
7
|
+
private ready;
|
|
8
|
+
constructor();
|
|
9
|
+
private init;
|
|
10
|
+
canHandle(query: string): boolean;
|
|
11
|
+
validate(url: string): boolean;
|
|
12
|
+
search(query: string, requestedBy: string): Promise<SearchResult>;
|
|
13
|
+
extractPlaylist(url: string, requestedBy: string): Promise<Track[]>;
|
|
14
|
+
getStream(track: Track): Promise<StreamInfo>;
|
|
15
|
+
getRelatedTracks(trackURL: string, opts?: {
|
|
16
|
+
limit?: number;
|
|
17
|
+
offset?: number;
|
|
18
|
+
history?: Track[];
|
|
19
|
+
}): Promise<Track[]>;
|
|
20
|
+
getFallback(track: Track): Promise<StreamInfo>;
|
|
21
|
+
private extractVideoId;
|
|
22
|
+
private extractListId;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=YouTubePlugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"YouTubePlugin.d.ts","sourceRoot":"","sources":["../src/YouTubePlugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAIvE,qBAAa,aAAc,SAAQ,UAAU;IAC5C,IAAI,SAAa;IACjB,OAAO,SAAW;IAElB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,KAAK,CAAgB;;YAOf,IAAI;IAclB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAMjC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAKxB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAkGjE,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAoCnE,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC;IA8D5C,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAA;KAAO,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IA0BvH,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,UAAU,CAAC;IAWpD,OAAO,CAAC,cAAc;IAmBtB,OAAO,CAAC,aAAa;CAQrB"}
|