YouTube-Gast-Zugang (App-Seite): 5 Downloads/Tag ohne Konto #4
@@ -5,6 +5,7 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
|
|
||||||
import 'baka_auth.dart';
|
import 'baka_auth.dart';
|
||||||
|
import 'gast_zugang.dart';
|
||||||
import 'yt_download_service.dart';
|
import 'yt_download_service.dart';
|
||||||
|
|
||||||
/// Ein Treffer der YouTube-Suche über den Baka-Proxy.
|
/// 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) —
|
/// Durchsucht YouTube über den Baka-Proxy (`/api/search`, yt-dlp-gestützt) —
|
||||||
/// dieselbe Anmeldung wie [YtDownloadService].
|
/// dieselbe Anmeldung wie [YtDownloadService].
|
||||||
class YtSearchService extends ChangeNotifier {
|
class YtSearchService extends ChangeNotifier {
|
||||||
YtSearchService({required this.auth, http.Client? client})
|
YtSearchService({required this.auth, this.gast, http.Client? client})
|
||||||
: _client = client ?? http.Client();
|
: _client = client ?? http.Client();
|
||||||
|
|
||||||
static const proxyUrl = YtDownloadService.proxyUrl;
|
static const proxyUrl = YtDownloadService.proxyUrl;
|
||||||
|
|
||||||
final BakaAuth auth;
|
final BakaAuth auth;
|
||||||
|
final GastZugang? gast;
|
||||||
final http.Client _client;
|
final http.Client _client;
|
||||||
|
|
||||||
bool _laeuft = false;
|
bool _laeuft = false;
|
||||||
@@ -64,7 +66,8 @@ class YtSearchService extends ChangeNotifier {
|
|||||||
final q = query.trim();
|
final q = query.trim();
|
||||||
if (q.isEmpty) return;
|
if (q.isEmpty) return;
|
||||||
|
|
||||||
if (!auth.istAngemeldet) {
|
final gastAktiv = !auth.istAngemeldet && (gast?.hatToken ?? false);
|
||||||
|
if (!auth.istAngemeldet && !gastAktiv) {
|
||||||
_treffer = const [];
|
_treffer = const [];
|
||||||
_fehler = 'Bitte zuerst beim Baka-Konto anmelden';
|
_fehler = 'Bitte zuerst beim Baka-Konto anmelden';
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@@ -80,7 +83,7 @@ class YtSearchService extends ChangeNotifier {
|
|||||||
final http.Response antwort;
|
final http.Response antwort;
|
||||||
try {
|
try {
|
||||||
antwort = await _client
|
antwort = await _client
|
||||||
.get(uri, headers: auth.authHeader)
|
.get(uri, headers: gastAktiv ? gast!.gastHeader : auth.authHeader)
|
||||||
.timeout(const Duration(seconds: 20));
|
.timeout(const Duration(seconds: 20));
|
||||||
} on TimeoutException {
|
} on TimeoutException {
|
||||||
_scheitere('Die Suche braucht zu lange — bitte später erneut versuchen');
|
_scheitere('Die Suche braucht zu lange — bitte später erneut versuchen');
|
||||||
@@ -92,7 +95,10 @@ class YtSearchService extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (antwort.statusCode == 401) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
if (antwort.statusCode != 200) {
|
if (antwort.statusCode != 200) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'package:flutter_test/flutter_test.dart';
|
|||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:http/testing.dart';
|
import 'package:http/testing.dart';
|
||||||
import 'package:melo/services/baka_auth.dart';
|
import 'package:melo/services/baka_auth.dart';
|
||||||
|
import 'package:melo/services/gast_zugang.dart';
|
||||||
import 'package:melo/services/yt_search_service.dart';
|
import 'package:melo/services/yt_search_service.dart';
|
||||||
|
|
||||||
class _MemorySpeicher implements TokenSpeicher {
|
class _MemorySpeicher implements TokenSpeicher {
|
||||||
@@ -200,5 +201,61 @@ void main() {
|
|||||||
await dienst.suchen('zweite suche');
|
await dienst.suchen('zweite suche');
|
||||||
expect(dienst.treffer.single.title, 'Zweites');
|
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<void>.delayed(Duration.zero);
|
||||||
|
|
||||||
|
expect(dienst.fehler, 'Gast-Zugang abgelaufen — bitte erneut versuchen');
|
||||||
|
expect(tokenAufrufe, 1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user