- tests: server/tests/api_coverage2.test.mjs (23 cas offline-safe) : oauth (status/url/connections/preview), channels (validations), subscriptions batch + groupes CRUD, transcripts history, likes/history DELETE, playlists public/view/reorder, telemetry summary, downloads 401/403/400, ai 503, twitch-token, config.js, rumble 400 - mcp v1.1.0 : 4 outils authentifies (list_playlists/likes/ subscriptions/watch_history, NEWTUBE_TOKEN) + tests stub - openapi.json v1.1 : 15 chemins documentes (sante, recherche, details, trending, transcript, auth, prefs, likes, subs, downloads, oauth, playlists) ; guide maj (11 outils)
This commit is contained in:
+71
-2
@@ -3779,12 +3779,81 @@ r.put('/playlists/:id/reorder', authMiddlewareCookieAware, (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// --- OpenAPI (minimal for playlists) ---
|
||||
// --- OpenAPI (référence machine : lecture publique + espace utilisateur) ---
|
||||
r.get('/openapi.json', (_req, res) => {
|
||||
const bearer = [{ bearerAuth: [] }];
|
||||
const doc = {
|
||||
openapi: '3.0.0',
|
||||
info: { title: 'NewTube API', version: '1.0.0' },
|
||||
info: { title: 'NewTube API', version: '1.1.0' },
|
||||
paths: {
|
||||
'/healthz': {
|
||||
get: { summary: 'Santé API (mode YT, yt-dlp, cache, quota)', responses: { 200: { description: 'ok' } } },
|
||||
},
|
||||
'/search': {
|
||||
get: { summary: 'Recherche unifiée multi-providers', parameters: [
|
||||
{ name: 'q', in: 'query', required: true, schema: { type: 'string', minLength: 2 } },
|
||||
{ name: 'providers', in: 'query', schema: { type: 'string', example: 'yt,dm' } },
|
||||
{ name: 'page', in: 'query', schema: { type: 'integer', default: 1 } },
|
||||
{ name: 'pageSize', in: 'query', schema: { type: 'integer', maximum: 50 } },
|
||||
{ name: 'sort', in: 'query', schema: { type: 'string', enum: ['relevance', 'date', 'views'] } },
|
||||
], responses: { 200: { description: '{ q, providers, groups, errors, page, pageSize, sort }' } } },
|
||||
},
|
||||
'/search/suggest': {
|
||||
get: { summary: 'Typeahead groupé par provider', parameters: [
|
||||
{ name: 'q', in: 'query', required: true, schema: { type: 'string', minLength: 2 } },
|
||||
{ name: 'providers', in: 'query', schema: { type: 'string' } },
|
||||
{ name: 'limit', in: 'query', schema: { type: 'integer', maximum: 20 } },
|
||||
], responses: { 200: { description: '{ q, groups }' } } },
|
||||
},
|
||||
'/details/{provider}/{videoId}': {
|
||||
get: { summary: 'Métadonnées vidéo + connexes YouTube', parameters: [
|
||||
{ name: 'provider', in: 'path', required: true, schema: { type: 'string' } },
|
||||
{ name: 'videoId', in: 'path', required: true, schema: { type: 'string' } },
|
||||
{ name: 'instance', in: 'query', schema: { type: 'string' } },
|
||||
{ name: 'related', in: 'query', schema: { type: 'string', enum: ['0'] } },
|
||||
], responses: { 200: { description: 'video + related[]' } } },
|
||||
},
|
||||
'/trending': {
|
||||
get: { summary: 'Tendances YouTube sans clé (phase 1 : yt)', parameters: [
|
||||
{ name: 'provider', in: 'query', schema: { type: 'string', default: 'yt' } },
|
||||
{ name: 'limit', in: 'query', schema: { type: 'integer', maximum: 50 } },
|
||||
], responses: { 200: { description: '{ provider, items }' } } },
|
||||
},
|
||||
'/transcript/{provider}/{videoId}': {
|
||||
get: { summary: 'Transcript { lang, available, languages, lines }', parameters: [
|
||||
{ name: 'provider', in: 'path', required: true, schema: { type: 'string' } },
|
||||
{ name: 'videoId', in: 'path', required: true, schema: { type: 'string' } },
|
||||
{ name: 'lang', in: 'query', schema: { type: 'string', default: 'fr' } },
|
||||
{ name: 'instance', in: 'query', schema: { type: 'string' } },
|
||||
], responses: { 200: { description: '200 available:true|false ; 502 retryable:true si 429 YouTube' } } },
|
||||
},
|
||||
'/auth/register': {
|
||||
post: { summary: 'Créer un compte', responses: { 201: { description: '{ user, accessToken }' } } },
|
||||
},
|
||||
'/auth/login': {
|
||||
post: { summary: 'Connexion (retourne accessToken + cookies)', responses: { 200: { description: '{ user, accessToken }' } } },
|
||||
},
|
||||
'/user/me': {
|
||||
get: { summary: 'Profil courant', security: bearer, responses: { 200: { description: 'user' } } },
|
||||
},
|
||||
'/user/preferences': {
|
||||
get: { summary: 'Lire préférences', security: bearer, responses: { 200: { description: 'prefs' } } },
|
||||
patch: { summary: 'Modifier préférences (defaultProviders…)', security: bearer, responses: { 200: { description: 'prefs' } } },
|
||||
},
|
||||
'/user/likes': {
|
||||
get: { summary: 'Vidéos likées', security: bearer, responses: { 200: { description: 'likes[]' } } },
|
||||
post: { summary: 'Liker', security: bearer, responses: { 201: { description: 'like' } } },
|
||||
},
|
||||
'/subscriptions': {
|
||||
get: { summary: 'Abonnements { items, ttl }', security: bearer, responses: { 200: { description: 'subs' } } },
|
||||
post: { summary: 'S abonner (résolution chaîne)', security: bearer, responses: { 201: { description: 'sub' } } },
|
||||
},
|
||||
'/download/{provider}/{videoId}/formats': {
|
||||
get: { summary: 'Formats téléchargeables (cache 10 min)', security: bearer, responses: { 200: { description: '{ url, formats }' } } },
|
||||
},
|
||||
'/oauth/status': {
|
||||
get: { summary: 'Connecteurs OAuth configurés', responses: { 200: { description: '{ google, twitch }' } } },
|
||||
},
|
||||
'/playlists': {
|
||||
get: { summary: 'List user playlists', security: [{ bearerAuth: [] }], parameters: [
|
||||
{ name: 'limit', in: 'query', schema: { type: 'integer' } },
|
||||
|
||||
Reference in New Issue
Block a user