59 lines
1.6 KiB
JavaScript
59 lines
1.6 KiB
JavaScript
/**
|
|
* @typedef {Object} Suggestion
|
|
* @property {string} title
|
|
* @property {string} id
|
|
* @property {number=} duration
|
|
* @property {boolean=} isShort
|
|
* @property {string=} url
|
|
* @property {string=} thumbnail
|
|
* @property {string=} uploaderName
|
|
* @property {string=} type
|
|
*/
|
|
|
|
/** @type {{ id: 'yt', label: string, search: (q: string, opts: { limit: number, page?: number }) => Promise<Suggestion[]> }} */
|
|
const handler = {
|
|
id: 'yt',
|
|
label: 'YouTube',
|
|
async search(q, opts) {
|
|
const { limit = 10 } = opts;
|
|
try {
|
|
const API_KEY = process.env.YOUTUBE_API_KEY;
|
|
if (!API_KEY) {
|
|
throw new Error('YOUTUBE_API_KEY not configured');
|
|
}
|
|
|
|
const response = await fetch(
|
|
`https://www.googleapis.com/youtube/v3/search?` +
|
|
new URLSearchParams({
|
|
part: 'snippet',
|
|
q: q,
|
|
type: 'video',
|
|
maxResults: Math.min(limit, 50).toString(),
|
|
key: API_KEY,
|
|
order: 'relevance'
|
|
})
|
|
);
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`YouTube API error: ${response.status}`);
|
|
}
|
|
|
|
const data = await response.json();
|
|
|
|
return (data.items || []).map(item => ({
|
|
title: item.snippet.title,
|
|
id: item.id.videoId,
|
|
url: `https://www.youtube.com/watch?v=${item.id.videoId}`,
|
|
thumbnail: item.snippet.thumbnails?.medium?.url || item.snippet.thumbnails?.default?.url,
|
|
uploaderName: item.snippet.channelTitle,
|
|
type: 'video'
|
|
}));
|
|
} catch (error) {
|
|
console.error('YouTube search error:', error);
|
|
return [];
|
|
}
|
|
}
|
|
};
|
|
|
|
export default handler;
|