fix get torrent video list

This commit is contained in:
kodjomoustapha 2024-12-02 17:01:10 +01:00
parent 792f6547ef
commit 11dea6dfaf
8 changed files with 107 additions and 47 deletions

View file

@ -1,7 +1,9 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter_qjs/flutter_qjs.dart';
import 'package:http_interceptor/http_interceptor.dart';
import 'package:mangayomi/services/http/m_client.dart';
import 'package:http/http.dart' as http;
class JsHttpClient {
late JavascriptRuntime runtime;
@ -14,33 +16,19 @@ class JsHttpClient {
}
runtime.onMessage('http_get', (dynamic args) async {
return jsonEncode((await client(args[1]).get(Uri.parse(args[2]),
headers: (args[3] as Map?)?.toMapStringString))
.toJson());
return await _toHttpResponse(client(args[1]), "GET", args);
});
runtime.onMessage('http_post', (dynamic args) async {
return jsonEncode((await client(args[1]).post(Uri.parse(args[2]),
headers: (args[3] as Map?)?.toMapStringString,
body: (args[4] as Map?)?.toMapStringString))
.toJson());
return await _toHttpResponse(client(args[1]), "POST", args);
});
runtime.onMessage('http_put', (dynamic args) async {
return (await client(args[1]).put(Uri.parse(args[2]),
headers: (args[3] as Map?)?.toMapStringString, body: args[4]))
.toJson();
return await _toHttpResponse(client(args[1]), "PUT", args);
});
runtime.onMessage('http_delete', (dynamic args) async {
return jsonEncode((await client(args[1]).delete(Uri.parse(args[2]),
headers: (args[3] as Map?)?.map(
(key, value) => MapEntry(key.toString(), value.toString())),
body: (args[4] as Map?)?.toMapStringString))
.toJson());
return await _toHttpResponse(client(args[1]), "DELETE", args);
});
runtime.onMessage('http_patch', (dynamic args) async {
return jsonEncode((await client(args[1]).patch(Uri.parse(args[2]),
headers: (args[3] as Map?)?.toMapStringString,
body: (args[4] as Map?)?.toMapStringString))
.toJson());
return await _toHttpResponse(client(args[1]), "PATCH", args);
});
runtime.evaluate('''
class Client {
@ -92,6 +80,38 @@ class Client {
}
}
Future<String> _toHttpResponse(Client client, String method, List args) async {
final url = args[2] as String;
final headers = (args[3] as Map?)?.toMapStringString;
final body = args.length >= 5 ? (args[4] as Map?)?.toMapStringDynamic : null;
var request = http.Request(method, Uri.parse(url));
request.headers.addAll(headers ?? {});
if ((request.headers[HttpHeaders.contentTypeHeader]
?.contains("application/json")) ??
false) {
request.body = json.encode(body);
request.headers.addAll(headers ?? {});
http.StreamedResponse response = await client.send(request);
final res = Response("", response.statusCode,
request: response.request,
headers: response.headers,
isRedirect: response.isRedirect,
persistentConnection: response.persistentConnection,
reasonPhrase: response.reasonPhrase);
Map<String, dynamic> resMap = res.toJson();
resMap["body"] = await response.stream.bytesToString();
return jsonEncode(resMap);
}
final future = switch (method) {
"GET" => client.get(Uri.parse(url), headers: headers),
"POST" => client.post(Uri.parse(url), headers: headers, body: body),
"PUT" => client.put(Uri.parse(url), headers: headers, body: body),
"DELETE" => client.delete(Uri.parse(url), headers: headers, body: body),
_ => client.patch(Uri.parse(url), headers: headers, body: body),
};
return jsonEncode((await future).toJson());
}
extension ResponseExtexsion on Response {
Map<String, dynamic> toJson() => {
'body': body,

View file

@ -21,6 +21,7 @@ import 'package:mangayomi/modules/widgets/progress_center.dart';
import 'package:mangayomi/providers/l10n_providers.dart';
import 'package:mangayomi/services/aniskip.dart';
import 'package:mangayomi/services/get_video_list.dart';
import 'package:mangayomi/services/torrent_server.dart';
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
import 'package:media_kit/media_kit.dart';
import 'package:media_kit_video/media_kit_video.dart';
@ -38,9 +39,12 @@ class AnimePlayerView extends riv.ConsumerStatefulWidget {
}
class _AnimePlayerViewState extends riv.ConsumerState<AnimePlayerView> {
String? _infoHash;
List<String> _infoHashList = [];
@override
void dispose() {
for (var infoHash in _infoHashList) {
MTorrentServer().removeTorrent(infoHash);
}
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
overlays: SystemUiOverlay.values);
super.dispose();
@ -53,8 +57,8 @@ class _AnimePlayerViewState extends riv.ConsumerState<AnimePlayerView> {
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
return serversData.when(
data: (data) {
final (videos, isLocal, infoHash) = data;
_infoHash = infoHash;
final (videos, isLocal, infoHashList) = data;
_infoHashList = infoHashList;
if (videos.isEmpty &&
!(widget.episode.manga.value!.isLocalArchive ?? false)) {
return Scaffold(
@ -77,7 +81,7 @@ class _AnimePlayerViewState extends riv.ConsumerState<AnimePlayerView> {
episode: widget.episode,
videos: videos,
isLocal: isLocal,
isTorrent: _infoHash != null);
isTorrent: _infoHashList.isNotEmpty);
},
error: (error, stackTrace) => Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,

View file

@ -7,7 +7,7 @@ part of 'add_torrent.dart';
// **************************************************************************
String _$addTorrentFromUrlOrFromFileHash() =>
r'8102259b30765a5c5cc57870f5c583bd5d421eee';
r'a159635689b8f8ac22bb9faa10407f09c8008f71';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -14,7 +14,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
part 'get_video_list.g.dart';
@riverpod
Future<(List<Video>, bool, String?)> getVideoList(Ref ref,
Future<(List<Video>, bool, List<String>)> getVideoList(Ref ref,
{required Chapter episode}) async {
final storageProvider = StorageProvider();
final mangaDirectory = await storageProvider.getMangaMainDirectory(episode);
@ -22,18 +22,40 @@ Future<(List<Video>, bool, String?)> getVideoList(Ref ref,
episode.manga.value!.source != "torrent";
final mp4animePath =
"${mangaDirectory!.path}${episode.name!.replaceForbiddenCharacters(' ')}.mp4";
List<String> infoHashes = [];
if (await File(mp4animePath).exists() || isLocalArchive) {
final path = isLocalArchive ? episode.archivePath : mp4animePath;
return ([Video(path!, episode.name!, path, subtitles: [])], true, null);
return (
[Video(path!, episode.name!, path, subtitles: [])],
true,
infoHashes
);
}
final source =
getSource(episode.manga.value!.lang!, episode.manga.value!.source!);
if (source?.isTorrent ?? false || episode.manga.value!.source == "torrent") {
final (videos, infohash) = await MTorrentServer()
.getTorrentPlaylist(episode.url, episode.archivePath);
return (videos, false, infohash);
List<Video> list = [];
List<Video> torrentList = [];
if (source?.sourceCodeLanguage == SourceCodeLanguage.dart) {
list = await DartExtensionService(source).getVideoList(episode.url!);
} else {
list = await JsExtensionService(source).getVideoList(episode.url!);
}
for (var v in list) {
final (videos, infohash) =
await MTorrentServer().getTorrentPlaylist(v.url, episode.archivePath);
for (var video in videos) {
torrentList
.add(video..quality = video.quality.substringBeforeLast("."));
if (infohash != null) {
infoHashes.add(infohash);
}
}
}
return (torrentList, false, infoHashes);
}
List<Video> list = [];
@ -48,5 +70,5 @@ Future<(List<Video>, bool, String?)> getVideoList(Ref ref,
videos.add(video);
}
}
return (videos, false, null);
return (videos, false, infoHashes);
}

View file

@ -6,7 +6,7 @@ part of 'get_video_list.dart';
// RiverpodGenerator
// **************************************************************************
String _$getVideoListHash() => r'1c62b1a5bef8b55a73ba7a436f23609ec8270436';
String _$getVideoListHash() => r'490d0a1fc3d0367e5386104f6cdfec69bd0e079a';
/// Copied from Dart SDK
class _SystemHash {
@ -35,7 +35,7 @@ const getVideoListProvider = GetVideoListFamily();
/// See also [getVideoList].
class GetVideoListFamily
extends Family<AsyncValue<(List<Video>, bool, String?)>> {
extends Family<AsyncValue<(List<Video>, bool, List<String>)>> {
/// See also [getVideoList].
const GetVideoListFamily();
@ -74,7 +74,7 @@ class GetVideoListFamily
/// See also [getVideoList].
class GetVideoListProvider
extends AutoDisposeFutureProvider<(List<Video>, bool, String?)> {
extends AutoDisposeFutureProvider<(List<Video>, bool, List<String>)> {
/// See also [getVideoList].
GetVideoListProvider({
required Chapter episode,
@ -109,7 +109,8 @@ class GetVideoListProvider
@override
Override overrideWith(
FutureOr<(List<Video>, bool, String?)> Function(GetVideoListRef provider)
FutureOr<(List<Video>, bool, List<String>)> Function(
GetVideoListRef provider)
create,
) {
return ProviderOverride(
@ -127,7 +128,7 @@ class GetVideoListProvider
}
@override
AutoDisposeFutureProviderElement<(List<Video>, bool, String?)>
AutoDisposeFutureProviderElement<(List<Video>, bool, List<String>)>
createElement() {
return _GetVideoListProviderElement(this);
}
@ -149,13 +150,13 @@ class GetVideoListProvider
@Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element
mixin GetVideoListRef
on AutoDisposeFutureProviderRef<(List<Video>, bool, String?)> {
on AutoDisposeFutureProviderRef<(List<Video>, bool, List<String>)> {
/// The parameter `episode` of this provider.
Chapter get episode;
}
class _GetVideoListProviderElement
extends AutoDisposeFutureProviderElement<(List<Video>, bool, String?)>
extends AutoDisposeFutureProviderElement<(List<Video>, bool, List<String>)>
with GetVideoListRef {
_GetVideoListProviderElement(super.provider);

View file

@ -13,6 +13,19 @@ import 'package:mangayomi/ffi/torrent_server_ffi.dart' as libmtorrentserver_ffi;
class MTorrentServer {
final http = MClient.init();
Future<bool> removeTorrent(String? inforHash) async {
if (inforHash == null || inforHash.isEmpty) return false;
try {
final res = await http
.delete(Uri.parse("$_baseUrl/torrent/remove?infohash=$inforHash"));
if (res.statusCode == 200) {
return true;
}
return false;
} catch (_) {
return false;
}
}
Future<bool> check() async {
if (_baseUrl == "http://127.0.0.1:0") return false;

View file

@ -355,10 +355,10 @@ packages:
dependency: transitive
description:
name: equatable
sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2
sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7"
url: "https://pub.dev"
source: hosted
version: "2.0.5"
version: "2.0.7"
exception_templates:
dependency: transitive
description:
@ -672,10 +672,10 @@ packages:
dependency: "direct main"
description:
name: go_router
sha256: "8ae664a70174163b9f65ea68dd8673e29db8f9095de7b5cd00e167c621f4fef5"
sha256: "8660b74171fafae4aa8202100fa2e55349e078281dadc73a241eb8e758534d9d"
url: "https://pub.dev"
source: hosted
version: "14.6.0"
version: "14.6.1"
google_fonts:
dependency: "direct main"
description:
@ -1107,10 +1107,10 @@ packages:
dependency: transitive
description:
name: path_provider_android
sha256: c464428172cb986b758c6d1724c603097febb8fb855aa265aeecc9280c294d4a
sha256: "8c4967f8b7cb46dc914e178daa29813d83ae502e0529d7b0478330616a691ef7"
url: "https://pub.dev"
source: hosted
version: "2.2.12"
version: "2.2.14"
path_provider_foundation:
dependency: transitive
description:
@ -1434,10 +1434,10 @@ packages:
dependency: transitive
description:
name: shelf_web_socket
sha256: "073c147238594ecd0d193f3456a5fe91c4b0abbcc68bf5cd95b36c4e194ac611"
sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67
url: "https://pub.dev"
source: hosted
version: "2.0.0"
version: "2.0.1"
sky_engine:
dependency: transitive
description: flutter

View file

@ -26,7 +26,7 @@ dependencies:
url_launcher: ^6.3.0
package_info_plus: ^8.0.0
permission_handler: ^11.3.1
flutter_inappwebview: ^6.2.0-beta.1
flutter_inappwebview: ^6.2.0-beta.2
draggable_menu: ^4.4.1
isar: 3.1.0+1
isar_flutter_libs: 3.1.0+1