import { HttpClient, HttpParams } from '@angular/common/http'; import { firstValueFrom } from 'rxjs'; import type { ProviderAdapter, ProviderSearchParams, SearchResult } from '../models'; import { VideoItem } from 'src/app/shared/models/video-item.model'; import { withFilterParams } from './filter-params'; export class OdAdapter implements ProviderAdapter { key = 'od' as const; label = 'Odysee'; constructor(private http: HttpClient) {} async search(params: ProviderSearchParams, _signal: AbortSignal): Promise> { let httpParams = new HttpParams().set('q', params.q).set('providers', 'od'); if (params.pageToken) httpParams = httpParams.set('page', params.pageToken); if (params.sort) httpParams = httpParams.set('sort', params.sort); // Filtres (type / durée / période) : appliqués côté serveur quand le provider // le sait, affinés en post-traitement sinon. httpParams = withFilterParams(httpParams, params.filters); const res = await firstValueFrom(this.http.get(`/api/search`, { params: httpParams })); const providerError = typeof res?.errors?.od?.message === 'string' ? res.errors.od.message : undefined; const items: VideoItem[] = (res?.groups?.od || []).map((it: any) => { let slug: string | undefined; try { const url: string | undefined = it?.url; if (url && /^https?:\/\/odysee\.com\//i.test(url)) { slug = url.replace(/^https?:\/\/odysee\.com\//i, '').replace(/^\//, ''); } } catch {} return { id: it.id, provider: 'odysee', title: it.title, channelName: it.uploaderName, durationSec: it.duration, thumbnailUrl: it.thumbnail, viewCount: undefined, publishedAt: undefined, slug, // Nom de chaîne LBRY (ex. @MaChaine) : le backend /api/channels/od // sait le résoudre avec ou sans préfixe @. channelExternalId: it.uploaderName || undefined, // Signaux de type pour le raffinement client des filtres. type: typeof it.type === 'string' ? it.type : undefined, isShort: it.isShort === true ? true : undefined, } as VideoItem; }); return { items, total: Array.isArray(res?.groups?.od) ? res.groups.od.length : 0, providerError }; } }