@sriinnu/harmon-youtube 0.1.0
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/.chitragupta-ecosystem/.profile.json +103 -0
- package/LICENSE +661 -0
- package/README.md +57 -0
- package/SKILL.md +46 -0
- package/dist/auth-cli.d.ts +5 -0
- package/dist/auth-cli.d.ts.map +1 -0
- package/dist/auth-cli.js +287 -0
- package/dist/auth-cli.js.map +1 -0
- package/dist/index.d.ts +107 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +347 -0
- package/dist/index.js.map +1 -0
- package/logo.svg +15 -0
- package/package.json +52 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harmon YouTube - YouTube Music integration
|
|
3
|
+
*
|
|
4
|
+
* I keep this adapter on the official YouTube Data API.
|
|
5
|
+
* That means I can support search, owned playlists, liked-library tracks,
|
|
6
|
+
* playlist tracks, and related-track recommendations without pulling in
|
|
7
|
+
* private YouTube Music endpoints that would make the runtime brittle.
|
|
8
|
+
*/
|
|
9
|
+
const YT_DATA_API_BASE = 'https://www.googleapis.com/youtube/v3';
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Implementation
|
|
12
|
+
// ============================================================================
|
|
13
|
+
class YouTubeMusicClientImpl {
|
|
14
|
+
config;
|
|
15
|
+
constructor(config) {
|
|
16
|
+
if (!config.accessToken && !config.apiKey) {
|
|
17
|
+
throw new Error('YouTube Music requires an access token or API key. Cookies-only mode is not implemented in this build.');
|
|
18
|
+
}
|
|
19
|
+
this.config = config;
|
|
20
|
+
}
|
|
21
|
+
isConnected() {
|
|
22
|
+
return !!(this.config.accessToken || this.config.apiKey);
|
|
23
|
+
}
|
|
24
|
+
async search(query, types = ['songs'], options = {}) {
|
|
25
|
+
const result = {
|
|
26
|
+
songs: [], albums: [], artists: [], playlists: [],
|
|
27
|
+
};
|
|
28
|
+
if (types.includes('songs')) {
|
|
29
|
+
const data = await this.ytDataRequest('/search', {
|
|
30
|
+
q: query,
|
|
31
|
+
type: 'video',
|
|
32
|
+
videoCategoryId: '10',
|
|
33
|
+
maxResults: (options.limit || 20).toString(),
|
|
34
|
+
part: 'snippet',
|
|
35
|
+
});
|
|
36
|
+
result.songs = (data.items || [])
|
|
37
|
+
.map(mapYtSearchToSong)
|
|
38
|
+
.filter((song) => song !== null);
|
|
39
|
+
}
|
|
40
|
+
if (types.includes('artists')) {
|
|
41
|
+
const data = await this.ytDataRequest('/search', {
|
|
42
|
+
q: query,
|
|
43
|
+
type: 'channel',
|
|
44
|
+
maxResults: (options.limit || 20).toString(),
|
|
45
|
+
part: 'snippet',
|
|
46
|
+
});
|
|
47
|
+
result.artists = (data.items || [])
|
|
48
|
+
.map(mapYtSearchToArtist)
|
|
49
|
+
.filter((artist) => artist !== null);
|
|
50
|
+
}
|
|
51
|
+
if (types.includes('playlists')) {
|
|
52
|
+
const data = await this.ytDataRequest('/search', {
|
|
53
|
+
q: query,
|
|
54
|
+
type: 'playlist',
|
|
55
|
+
maxResults: (options.limit || 20).toString(),
|
|
56
|
+
part: 'snippet',
|
|
57
|
+
});
|
|
58
|
+
result.playlists = (data.items || [])
|
|
59
|
+
.map(mapYtSearchToPlaylist)
|
|
60
|
+
.filter((playlist) => playlist !== null);
|
|
61
|
+
}
|
|
62
|
+
if (types.includes('albums')) {
|
|
63
|
+
const data = await this.ytDataRequest('/search', {
|
|
64
|
+
q: `${query} album`,
|
|
65
|
+
type: 'playlist',
|
|
66
|
+
maxResults: (options.limit || 20).toString(),
|
|
67
|
+
part: 'snippet',
|
|
68
|
+
});
|
|
69
|
+
result.albums = (data.items || [])
|
|
70
|
+
.map(mapYtSearchToAlbum)
|
|
71
|
+
.filter((album) => album !== null);
|
|
72
|
+
}
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
async getSong(videoId) {
|
|
76
|
+
const data = await this.ytDataRequest('/videos', {
|
|
77
|
+
id: videoId,
|
|
78
|
+
part: 'snippet,contentDetails',
|
|
79
|
+
});
|
|
80
|
+
const item = data.items?.[0];
|
|
81
|
+
if (!item)
|
|
82
|
+
return null;
|
|
83
|
+
return {
|
|
84
|
+
id: item.id,
|
|
85
|
+
name: item.snippet.title,
|
|
86
|
+
artistName: item.snippet.channelTitle.replace(/ - Topic$/, ''),
|
|
87
|
+
durationMs: parseDuration(item.contentDetails?.duration),
|
|
88
|
+
thumbnailUrl: item.snippet.thumbnails?.medium?.url,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
async getLibrarySongs(_options = {}) {
|
|
92
|
+
const likesPlaylistId = await this.getLikesPlaylistId();
|
|
93
|
+
return this.getPlaylistTracks(likesPlaylistId, _options);
|
|
94
|
+
}
|
|
95
|
+
async getPlaylists(options = {}) {
|
|
96
|
+
this.requireAuthorizedUserSurface('YouTube Music playlist listing');
|
|
97
|
+
const data = await this.ytDataRequest('/playlists', {
|
|
98
|
+
mine: 'true',
|
|
99
|
+
maxResults: Math.min(options.limit || 20, 50).toString(),
|
|
100
|
+
part: 'snippet,contentDetails',
|
|
101
|
+
});
|
|
102
|
+
return (data.items || [])
|
|
103
|
+
.map(mapPlaylistListItem)
|
|
104
|
+
.filter((playlist) => playlist !== null);
|
|
105
|
+
}
|
|
106
|
+
async getPlaylistTracks(playlistId, options = {}) {
|
|
107
|
+
const data = await this.ytDataRequest('/playlistItems', {
|
|
108
|
+
playlistId,
|
|
109
|
+
maxResults: Math.min(options.limit || 20, 50).toString(),
|
|
110
|
+
part: 'snippet,contentDetails',
|
|
111
|
+
});
|
|
112
|
+
return (data.items || [])
|
|
113
|
+
.map(mapPlaylistItemToSong)
|
|
114
|
+
.filter((song) => song !== null);
|
|
115
|
+
}
|
|
116
|
+
async getRecommendations(options = {}) {
|
|
117
|
+
const seedSong = (await this.getLibrarySongs({ limit: 1 }))[0];
|
|
118
|
+
if (!seedSong) {
|
|
119
|
+
return [];
|
|
120
|
+
}
|
|
121
|
+
return this.getWatchPlaylist(seedSong.id, options);
|
|
122
|
+
}
|
|
123
|
+
async getWatchPlaylist(videoId, options = {}) {
|
|
124
|
+
const data = await this.ytDataRequest('/search', {
|
|
125
|
+
relatedToVideoId: videoId,
|
|
126
|
+
type: 'video',
|
|
127
|
+
videoCategoryId: '10',
|
|
128
|
+
maxResults: Math.min(options.limit || 20, 50).toString(),
|
|
129
|
+
part: 'snippet',
|
|
130
|
+
});
|
|
131
|
+
return (data.items || [])
|
|
132
|
+
.map(mapYtSearchToSong)
|
|
133
|
+
.filter((song) => song !== null && song.id !== videoId);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* I keep user-library surfaces behind OAuth because API-key access cannot
|
|
137
|
+
* read a signed-in user's playlists or likes.
|
|
138
|
+
*/
|
|
139
|
+
requireAuthorizedUserSurface(surface) {
|
|
140
|
+
if (!this.config.accessToken) {
|
|
141
|
+
throw new Error(`${surface} requires YOUTUBE_MUSIC_ACCESS_TOKEN or GOOGLE_ACCESS_TOKEN.`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
async getLikesPlaylistId() {
|
|
145
|
+
this.requireAuthorizedUserSurface('YouTube Music library access');
|
|
146
|
+
const data = await this.ytDataRequest('/channels', {
|
|
147
|
+
mine: 'true',
|
|
148
|
+
part: 'contentDetails',
|
|
149
|
+
maxResults: '1',
|
|
150
|
+
});
|
|
151
|
+
const likesPlaylistId = data.items?.[0]?.contentDetails?.relatedPlaylists?.likes;
|
|
152
|
+
if (!likesPlaylistId) {
|
|
153
|
+
throw new Error('YouTube Music liked tracks playlist was not available for the authenticated user.');
|
|
154
|
+
}
|
|
155
|
+
return likesPlaylistId;
|
|
156
|
+
}
|
|
157
|
+
async ytDataRequest(path, query) {
|
|
158
|
+
const url = new URL(`${YT_DATA_API_BASE}${path}`);
|
|
159
|
+
for (const [key, value] of Object.entries(query)) {
|
|
160
|
+
url.searchParams.set(key, value);
|
|
161
|
+
}
|
|
162
|
+
const headers = {};
|
|
163
|
+
if (this.config.accessToken) {
|
|
164
|
+
headers.Authorization = `Bearer ${this.config.accessToken}`;
|
|
165
|
+
}
|
|
166
|
+
else if (this.config.apiKey) {
|
|
167
|
+
url.searchParams.set('key', this.config.apiKey);
|
|
168
|
+
}
|
|
169
|
+
const response = await fetch(url, { headers });
|
|
170
|
+
if (response.status === 429) {
|
|
171
|
+
const retryAfter = parseInt(response.headers.get('Retry-After') || '5', 10);
|
|
172
|
+
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
|
|
173
|
+
const retry = await fetch(url, { headers });
|
|
174
|
+
if (!retry.ok) {
|
|
175
|
+
throw new Error(`YouTube API error: ${retry.status} ${await retry.text()}`);
|
|
176
|
+
}
|
|
177
|
+
return (await retry.json());
|
|
178
|
+
}
|
|
179
|
+
if (!response.ok) {
|
|
180
|
+
throw new Error(`YouTube API error: ${response.status} ${await response.text()}`);
|
|
181
|
+
}
|
|
182
|
+
return (await response.json());
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// ============================================================================
|
|
186
|
+
// Mappers
|
|
187
|
+
// ============================================================================
|
|
188
|
+
function mapYtSearchToSong(item) {
|
|
189
|
+
const videoId = item.id.videoId;
|
|
190
|
+
if (!videoId || !item.snippet.title || !item.snippet.channelTitle) {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
id: videoId,
|
|
195
|
+
name: item.snippet.title,
|
|
196
|
+
artistName: item.snippet.channelTitle.replace(/ - Topic$/, ''),
|
|
197
|
+
thumbnailUrl: item.snippet.thumbnails?.medium?.url,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
function mapYtSearchToArtist(item) {
|
|
201
|
+
const artistId = item.id.channelId;
|
|
202
|
+
if (!artistId || !item.snippet.title) {
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
id: artistId,
|
|
207
|
+
name: item.snippet.title,
|
|
208
|
+
thumbnailUrl: item.snippet.thumbnails?.medium?.url,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
function mapYtSearchToPlaylist(item) {
|
|
212
|
+
const playlistId = item.id.playlistId;
|
|
213
|
+
if (!playlistId || !item.snippet.title) {
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
return {
|
|
217
|
+
id: playlistId,
|
|
218
|
+
name: item.snippet.title,
|
|
219
|
+
author: item.snippet.channelTitle,
|
|
220
|
+
thumbnailUrl: item.snippet.thumbnails?.medium?.url,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
function mapYtSearchToAlbum(item) {
|
|
224
|
+
const playlist = mapYtSearchToPlaylist(item);
|
|
225
|
+
if (!playlist) {
|
|
226
|
+
return null;
|
|
227
|
+
}
|
|
228
|
+
return {
|
|
229
|
+
id: playlist.id,
|
|
230
|
+
name: playlist.name,
|
|
231
|
+
artistName: playlist.author || 'YouTube Music',
|
|
232
|
+
thumbnailUrl: playlist.thumbnailUrl,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
function mapPlaylistListItem(item) {
|
|
236
|
+
if (!item.id || !item.snippet?.title) {
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
return {
|
|
240
|
+
id: item.id,
|
|
241
|
+
name: item.snippet.title,
|
|
242
|
+
author: item.snippet.channelTitle,
|
|
243
|
+
trackCount: item.contentDetails?.itemCount,
|
|
244
|
+
thumbnailUrl: item.snippet.thumbnails?.medium?.url,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
function mapPlaylistItemToSong(item) {
|
|
248
|
+
const videoId = item.contentDetails?.videoId || item.snippet?.resourceId?.videoId;
|
|
249
|
+
const title = item.snippet?.title;
|
|
250
|
+
const channelTitle = item.snippet?.channelTitle;
|
|
251
|
+
if (!videoId || !title || !channelTitle || title === 'Deleted video' || title === 'Private video') {
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
return {
|
|
255
|
+
id: videoId,
|
|
256
|
+
name: title,
|
|
257
|
+
artistName: channelTitle.replace(/ - Topic$/, ''),
|
|
258
|
+
thumbnailUrl: item.snippet?.thumbnails?.medium?.url,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
/** Convert YouTube Music song to provider-agnostic TrackInfo */
|
|
262
|
+
export function mapSongToTrackInfo(song) {
|
|
263
|
+
return {
|
|
264
|
+
id: song.id,
|
|
265
|
+
name: song.name,
|
|
266
|
+
artist: song.artistName,
|
|
267
|
+
artistIds: song.artistId ? [song.artistId] : undefined,
|
|
268
|
+
album: song.albumName || '',
|
|
269
|
+
durationMs: song.durationMs || 0,
|
|
270
|
+
uri: `youtube:video:${song.id}`,
|
|
271
|
+
provider: 'youtube',
|
|
272
|
+
imageUrl: song.thumbnailUrl,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
/** Parse ISO 8601 duration (PT3M45S) to milliseconds */
|
|
276
|
+
function parseDuration(iso) {
|
|
277
|
+
if (!iso)
|
|
278
|
+
return undefined;
|
|
279
|
+
const m = iso.match(/PT(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?/);
|
|
280
|
+
if (!m)
|
|
281
|
+
return undefined;
|
|
282
|
+
return ((parseInt(m[1] || '0') * 3600) + (parseInt(m[2] || '0') * 60) + parseInt(m[3] || '0')) * 1000;
|
|
283
|
+
}
|
|
284
|
+
// ============================================================================
|
|
285
|
+
// Provider Adapter
|
|
286
|
+
// ============================================================================
|
|
287
|
+
/**
|
|
288
|
+
* Adapts YouTubeMusicClient to the MusicProvider interface.
|
|
289
|
+
*/
|
|
290
|
+
export class YouTubeMusicProvider {
|
|
291
|
+
name = 'youtube';
|
|
292
|
+
client;
|
|
293
|
+
constructor(client) {
|
|
294
|
+
this.client = client;
|
|
295
|
+
}
|
|
296
|
+
isConnected() {
|
|
297
|
+
return this.client.isConnected();
|
|
298
|
+
}
|
|
299
|
+
async search(query, limit) {
|
|
300
|
+
const result = await this.client.search(query, ['songs'], { limit });
|
|
301
|
+
return result.songs.map(mapSongToTrackInfo);
|
|
302
|
+
}
|
|
303
|
+
async getLibraryTracks(options) {
|
|
304
|
+
const songs = await this.client.getLibrarySongs(options);
|
|
305
|
+
return songs.map(mapSongToTrackInfo);
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* I reject synthetic top-track semantics so the YouTube provider stays
|
|
309
|
+
* aligned with what the official API actually exposes.
|
|
310
|
+
*/
|
|
311
|
+
async getTopTracks(options) {
|
|
312
|
+
void options;
|
|
313
|
+
throw new Error('YouTube Music top tracks are not available from the official provider contract. Use recently played or library tracks instead.');
|
|
314
|
+
}
|
|
315
|
+
async getRecentlyPlayed(options) {
|
|
316
|
+
return this.getLibraryTracks(options);
|
|
317
|
+
}
|
|
318
|
+
async getPlaylistTracks(playlistId, options) {
|
|
319
|
+
const songs = await this.client.getPlaylistTracks(playlistId, options);
|
|
320
|
+
return songs.map(mapSongToTrackInfo);
|
|
321
|
+
}
|
|
322
|
+
async getRecommendations(options) {
|
|
323
|
+
if (options.seedTrackIds && options.seedTrackIds.length > 0) {
|
|
324
|
+
const songs = await this.client.getWatchPlaylist(options.seedTrackIds[0], { limit: options.limit });
|
|
325
|
+
return songs.map(mapSongToTrackInfo);
|
|
326
|
+
}
|
|
327
|
+
const songs = await this.client.getRecommendations({ limit: options.limit });
|
|
328
|
+
return songs.map(mapSongToTrackInfo);
|
|
329
|
+
}
|
|
330
|
+
async getTrackFeatures(trackIds) {
|
|
331
|
+
return trackIds.map(() => null); // YouTube has no audio features
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
export function createYouTubeMusicProvider(client) {
|
|
335
|
+
return new YouTubeMusicProvider(client);
|
|
336
|
+
}
|
|
337
|
+
// ============================================================================
|
|
338
|
+
// Factory
|
|
339
|
+
// ============================================================================
|
|
340
|
+
/**
|
|
341
|
+
* I create a YouTube Music client for the currently supported Data API
|
|
342
|
+
* surface: song search and individual song lookup.
|
|
343
|
+
*/
|
|
344
|
+
export function createYouTubeMusicClient(config) {
|
|
345
|
+
return new YouTubeMusicClientImpl(config);
|
|
346
|
+
}
|
|
347
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/logo.svg
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64" fill="none">
|
|
2
|
+
<!-- I am the YouTube mark: a browser frame, a play symbol, and handoff motion. -->
|
|
3
|
+
<rect width="64" height="64" rx="16" fill="#F3E7D4"/>
|
|
4
|
+
<g stroke="#171513" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
|
|
5
|
+
<rect x="16" y="18" width="32" height="20" rx="8"/>
|
|
6
|
+
<path d="M29 24L38 28L29 32V24Z"/>
|
|
7
|
+
<path d="M43 14L49 18"/>
|
|
8
|
+
<path d="M18 49L20 38"/>
|
|
9
|
+
<path d="M29 46C35 43 42 43 48 47"/>
|
|
10
|
+
</g>
|
|
11
|
+
<g fill="#171513">
|
|
12
|
+
<circle cx="18" cy="34" r="5"/>
|
|
13
|
+
<path d="M13 46C15 41 22 41 24 46V51H13V46Z"/>
|
|
14
|
+
</g>
|
|
15
|
+
</svg>
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sriinnu/harmon-youtube",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "YouTube Music integration for Harmon",
|
|
5
|
+
"license": "AGPL-3.0-only",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/sriinnu/harmon.git",
|
|
9
|
+
"directory": "packages/harmon-youtube"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/sriinnu/harmon/tree/main/packages/harmon-youtube#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/sriinnu/harmon/issues"
|
|
14
|
+
},
|
|
15
|
+
"type": "module",
|
|
16
|
+
"main": "./dist/index.js",
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"files": [
|
|
19
|
+
"dist/",
|
|
20
|
+
".chitragupta-ecosystem/",
|
|
21
|
+
"README.md",
|
|
22
|
+
"SKILL.md",
|
|
23
|
+
"logo.svg"
|
|
24
|
+
],
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"import": "./dist/index.js"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"access": "public"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@sriinnu/harmon-protocol": "0.1.0",
|
|
36
|
+
"@sriinnu/harmon-core": "0.1.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/node": "^25.0.8",
|
|
40
|
+
"typescript": "^5.9.3"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"auth": "node ./dist/auth-cli.js bootstrap",
|
|
44
|
+
"auth:refresh": "node ./dist/auth-cli.js refresh",
|
|
45
|
+
"auth:status": "node ./dist/auth-cli.js status",
|
|
46
|
+
"build": "node --experimental-strip-types ../../scripts/clean-build.ts ./dist ./tsconfig.tsbuildinfo && tsc",
|
|
47
|
+
"dev": "tsc --watch",
|
|
48
|
+
"lint": "tsc --noEmit",
|
|
49
|
+
"test": "vitest --root ../.. packages/harmon-youtube/src/index.test.ts",
|
|
50
|
+
"test:run": "vitest --root ../.. run packages/harmon-youtube/src/index.test.ts"
|
|
51
|
+
}
|
|
52
|
+
}
|