diff --git a/lib/services/yt_search_service.dart b/lib/services/yt_search_service.dart index 69ee99a..0c08bd9 100644 --- a/lib/services/yt_search_service.dart +++ b/lib/services/yt_search_service.dart @@ -5,6 +5,7 @@ import 'package:flutter/foundation.dart'; import 'package:http/http.dart' as http; import 'baka_auth.dart'; +import 'gast_zugang.dart'; import 'yt_download_service.dart'; /// Ein Treffer der YouTube-Suche über den Baka-Proxy. @@ -44,12 +45,13 @@ String? youtubeVideoId(String url) { /// Durchsucht YouTube über den Baka-Proxy (`/api/search`, yt-dlp-gestützt) — /// dieselbe Anmeldung wie [YtDownloadService]. class YtSearchService extends ChangeNotifier { - YtSearchService({required this.auth, http.Client? client}) + YtSearchService({required this.auth, this.gast, http.Client? client}) : _client = client ?? http.Client(); static const proxyUrl = YtDownloadService.proxyUrl; final BakaAuth auth; + final GastZugang? gast; final http.Client _client; bool _laeuft = false; @@ -64,7 +66,8 @@ class YtSearchService extends ChangeNotifier { final q = query.trim(); if (q.isEmpty) return; - if (!auth.istAngemeldet) { + final gastAktiv = !auth.istAngemeldet && (gast?.hatToken ?? false); + if (!auth.istAngemeldet && !gastAktiv) { _treffer = const []; _fehler = 'Bitte zuerst beim Baka-Konto anmelden'; notifyListeners(); @@ -80,7 +83,7 @@ class YtSearchService extends ChangeNotifier { final http.Response antwort; try { antwort = await _client - .get(uri, headers: auth.authHeader) + .get(uri, headers: gastAktiv ? gast!.gastHeader : auth.authHeader) .timeout(const Duration(seconds: 20)); } on TimeoutException { _scheitere('Die Suche braucht zu lange — bitte später erneut versuchen'); @@ -92,7 +95,10 @@ class YtSearchService extends ChangeNotifier { } if (antwort.statusCode == 401) { - _scheitere('Anmeldung abgelaufen — bitte neu anmelden'); + if (gastAktiv) unawaited(gast!.holeToken()); + _scheitere(gastAktiv + ? 'Gast-Zugang abgelaufen — bitte erneut versuchen' + : 'Anmeldung abgelaufen — bitte neu anmelden'); return; } if (antwort.statusCode != 200) { diff --git a/test/services/yt_search_service_test.dart b/test/services/yt_search_service_test.dart index 181fd24..f033673 100644 --- a/test/services/yt_search_service_test.dart +++ b/test/services/yt_search_service_test.dart @@ -5,6 +5,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:http/http.dart' as http; import 'package:http/testing.dart'; import 'package:melo/services/baka_auth.dart'; +import 'package:melo/services/gast_zugang.dart'; import 'package:melo/services/yt_search_service.dart'; class _MemorySpeicher implements TokenSpeicher { @@ -200,5 +201,61 @@ void main() { await dienst.suchen('zweite suche'); expect(dienst.treffer.single.title, 'Zweites'); }); + + test('Mit Gast-Token statt Anmeldung wird trotzdem gesucht', () async { + final speicher = _MemorySpeicher(); + speicher.werte['guest_token'] = 'gast-xyz'; + final gast = GastZugang( + client: MockClient((_) async => http.Response('', 500)), + speicher: speicher, + ); + await gast.laden(); + + final dienst = YtSearchService( + auth: BakaAuth( + client: MockClient((_) async => http.Response('', 500)), + speicher: _MemorySpeicher()), + gast: gast, + client: MockClient((req) async { + expect(req.headers['X-Guest-Token'], 'gast-xyz'); + expect(req.headers.containsKey('Authorization'), isFalse); + return http.Response('[]', 200); + }), + ); + + await dienst.suchen('roses'); + + expect(dienst.fehler, isNull); + }); + + test('401 bei Gast-Zugang holt automatisch einen neuen Gast-Token', + () async { + var tokenAufrufe = 0; + final speicher = _MemorySpeicher(); + speicher.werte['guest_token'] = 'alter-token'; + final gast = GastZugang( + client: MockClient((_) async { + tokenAufrufe++; + return http.Response( + jsonEncode({'guest_token': 'neuer-token'}), 200); + }), + speicher: speicher, + ); + await gast.laden(); + + final dienst = YtSearchService( + auth: BakaAuth( + client: MockClient((_) async => http.Response('', 500)), + speicher: _MemorySpeicher()), + gast: gast, + client: MockClient((_) async => http.Response('Unauthorized', 401)), + ); + + await dienst.suchen('roses'); + await Future.delayed(Duration.zero); + + expect(dienst.fehler, 'Gast-Zugang abgelaufen — bitte erneut versuchen'); + expect(tokenAufrufe, 1); + }); }); }