torrent server integration

This commit is contained in:
kodjomoustapha 2024-01-24 12:25:33 +01:00
parent 3f108e1c43
commit 7e245e3bc2
5 changed files with 115 additions and 37 deletions

View file

@ -133,6 +133,8 @@ class Source {
'additionalParams': additionalParams,
};
bool get isTorrent => (typeSource?.toLowerCase() ?? "") == "torrent";
MSource toMSource() {
return MSource(
id: id,

View file

@ -92,43 +92,48 @@ const SourceSchema = CollectionSchema(
name: r'isPinned',
type: IsarType.bool,
),
r'lang': PropertySchema(
r'isTorrent': PropertySchema(
id: 15,
name: r'isTorrent',
type: IsarType.bool,
),
r'lang': PropertySchema(
id: 16,
name: r'lang',
type: IsarType.string,
),
r'lastUsed': PropertySchema(
id: 16,
id: 17,
name: r'lastUsed',
type: IsarType.bool,
),
r'name': PropertySchema(
id: 17,
id: 18,
name: r'name',
type: IsarType.string,
),
r'sourceCode': PropertySchema(
id: 18,
id: 19,
name: r'sourceCode',
type: IsarType.string,
),
r'sourceCodeUrl': PropertySchema(
id: 19,
id: 20,
name: r'sourceCodeUrl',
type: IsarType.string,
),
r'typeSource': PropertySchema(
id: 20,
id: 21,
name: r'typeSource',
type: IsarType.string,
),
r'version': PropertySchema(
id: 21,
id: 22,
name: r'version',
type: IsarType.string,
),
r'versionLast': PropertySchema(
id: 22,
id: 23,
name: r'versionLast',
type: IsarType.string,
)
@ -267,14 +272,15 @@ void _sourceSerialize(
writer.writeBool(offsets[12], object.isManga);
writer.writeBool(offsets[13], object.isNsfw);
writer.writeBool(offsets[14], object.isPinned);
writer.writeString(offsets[15], object.lang);
writer.writeBool(offsets[16], object.lastUsed);
writer.writeString(offsets[17], object.name);
writer.writeString(offsets[18], object.sourceCode);
writer.writeString(offsets[19], object.sourceCodeUrl);
writer.writeString(offsets[20], object.typeSource);
writer.writeString(offsets[21], object.version);
writer.writeString(offsets[22], object.versionLast);
writer.writeBool(offsets[15], object.isTorrent);
writer.writeString(offsets[16], object.lang);
writer.writeBool(offsets[17], object.lastUsed);
writer.writeString(offsets[18], object.name);
writer.writeString(offsets[19], object.sourceCode);
writer.writeString(offsets[20], object.sourceCodeUrl);
writer.writeString(offsets[21], object.typeSource);
writer.writeString(offsets[22], object.version);
writer.writeString(offsets[23], object.versionLast);
}
Source _sourceDeserialize(
@ -300,14 +306,14 @@ Source _sourceDeserialize(
isManga: reader.readBoolOrNull(offsets[12]),
isNsfw: reader.readBoolOrNull(offsets[13]),
isPinned: reader.readBoolOrNull(offsets[14]),
lang: reader.readStringOrNull(offsets[15]),
lastUsed: reader.readBoolOrNull(offsets[16]),
name: reader.readStringOrNull(offsets[17]),
sourceCode: reader.readStringOrNull(offsets[18]),
sourceCodeUrl: reader.readStringOrNull(offsets[19]),
typeSource: reader.readStringOrNull(offsets[20]),
version: reader.readStringOrNull(offsets[21]),
versionLast: reader.readStringOrNull(offsets[22]),
lang: reader.readStringOrNull(offsets[16]),
lastUsed: reader.readBoolOrNull(offsets[17]),
name: reader.readStringOrNull(offsets[18]),
sourceCode: reader.readStringOrNull(offsets[19]),
sourceCodeUrl: reader.readStringOrNull(offsets[20]),
typeSource: reader.readStringOrNull(offsets[21]),
version: reader.readStringOrNull(offsets[22]),
versionLast: reader.readStringOrNull(offsets[23]),
);
return object;
}
@ -350,11 +356,11 @@ P _sourceDeserializeProp<P>(
case 14:
return (reader.readBoolOrNull(offset)) as P;
case 15:
return (reader.readStringOrNull(offset)) as P;
return (reader.readBool(offset)) as P;
case 16:
return (reader.readBoolOrNull(offset)) as P;
case 17:
return (reader.readStringOrNull(offset)) as P;
case 17:
return (reader.readBoolOrNull(offset)) as P;
case 18:
return (reader.readStringOrNull(offset)) as P;
case 19:
@ -365,6 +371,8 @@ P _sourceDeserializeProp<P>(
return (reader.readStringOrNull(offset)) as P;
case 22:
return (reader.readStringOrNull(offset)) as P;
case 23:
return (reader.readStringOrNull(offset)) as P;
default:
throw IsarError('Unknown property with id $propertyId');
}
@ -1886,6 +1894,16 @@ extension SourceQueryFilter on QueryBuilder<Source, Source, QFilterCondition> {
});
}
QueryBuilder<Source, Source, QAfterFilterCondition> isTorrentEqualTo(
bool value) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'isTorrent',
value: value,
));
});
}
QueryBuilder<Source, Source, QAfterFilterCondition> langIsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(const FilterCondition.isNull(
@ -3119,6 +3137,18 @@ extension SourceQuerySortBy on QueryBuilder<Source, Source, QSortBy> {
});
}
QueryBuilder<Source, Source, QAfterSortBy> sortByIsTorrent() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'isTorrent', Sort.asc);
});
}
QueryBuilder<Source, Source, QAfterSortBy> sortByIsTorrentDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'isTorrent', Sort.desc);
});
}
QueryBuilder<Source, Source, QAfterSortBy> sortByLang() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'lang', Sort.asc);
@ -3409,6 +3439,18 @@ extension SourceQuerySortThenBy on QueryBuilder<Source, Source, QSortThenBy> {
});
}
QueryBuilder<Source, Source, QAfterSortBy> thenByIsTorrent() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'isTorrent', Sort.asc);
});
}
QueryBuilder<Source, Source, QAfterSortBy> thenByIsTorrentDesc() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'isTorrent', Sort.desc);
});
}
QueryBuilder<Source, Source, QAfterSortBy> thenByLang() {
return QueryBuilder.apply(this, (query) {
return query.addSortBy(r'lang', Sort.asc);
@ -3607,6 +3649,12 @@ extension SourceQueryWhereDistinct on QueryBuilder<Source, Source, QDistinct> {
});
}
QueryBuilder<Source, Source, QDistinct> distinctByIsTorrent() {
return QueryBuilder.apply(this, (query) {
return query.addDistinctBy(r'isTorrent');
});
}
QueryBuilder<Source, Source, QDistinct> distinctByLang(
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
@ -3761,6 +3809,12 @@ extension SourceQueryProperty on QueryBuilder<Source, Source, QQueryProperty> {
});
}
QueryBuilder<Source, bool, QQueryOperations> isTorrentProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'isTorrent');
});
}
QueryBuilder<Source, String?, QQueryOperations> langProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'lang');

View file

@ -18,6 +18,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';
@ -33,6 +34,13 @@ class AnimePlayerView extends riv.ConsumerStatefulWidget {
}
class _AnimePlayerViewState extends riv.ConsumerState<AnimePlayerView> {
String? _infoHash;
@override
void dispose() {
MTorrentServer().removeTorrent(_infoHash);
super.dispose();
}
@override
Widget build(BuildContext context) {
final serversData = ref.watch(getVideoListProvider(
@ -41,6 +49,7 @@ class _AnimePlayerViewState extends riv.ConsumerState<AnimePlayerView> {
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
return serversData.when(
data: (data) {
_infoHash = data.$3;
if (data.$1.isEmpty &&
!(widget.episode.manga.value!.isLocalArchive ?? false)) {
return Scaffold(

View file

@ -6,13 +6,14 @@ import 'package:mangayomi/models/chapter.dart';
import 'package:mangayomi/models/video.dart';
import 'package:mangayomi/eval/runtime/runtime.dart';
import 'package:mangayomi/providers/storage_provider.dart';
import 'package:mangayomi/services/torrent_server.dart';
import 'package:mangayomi/sources/utils/utils.dart';
import 'package:mangayomi/sources/source_test.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'get_video_list.g.dart';
@riverpod
Future<(List<Video>, bool)> getVideoList(
Future<(List<Video>, bool, String?)> getVideoList(
GetVideoListRef ref, {
required Chapter episode,
}) async {
@ -20,13 +21,21 @@ Future<(List<Video>, bool)> getVideoList(
final mangaDirectory = await storageProvider.getMangaMainDirectory(episode);
final isLocalArchive = episode.manga.value!.isLocalArchive!;
final mp4animePath = "${mangaDirectory!.path}${episode.name}.mp4";
if (await File(mp4animePath).exists() || isLocalArchive) {
final path = isLocalArchive ? episode.archivePath : mp4animePath;
return ([Video(path!, episode.name!, path, subtitles: [])], true);
return ([Video(path!, episode.name!, path, subtitles: [])], true, null);
}
final source =
getSource(episode.manga.value!.lang!, episode.manga.value!.source!)!;
if (source.isTorrent) {
final (videos, infohash) =
await MTorrentServer().getTorrentPlaylist(episode.url!);
return (videos, false, infohash);
}
final bytecode =
compilerEval(useTestSourceCode ? testSourceCode : source.sourceCode!);
@ -35,5 +44,5 @@ Future<(List<Video>, bool)> getVideoList(
var res = runtime.executeLib('package:mangayomi/main.dart', 'main');
final dd =
(await (res as MProvider).getVideoList(source.toMSource(), episode.url!));
return (dd, false);
return (dd, false, null);
}

View file

@ -6,7 +6,7 @@ part of 'get_video_list.dart';
// RiverpodGenerator
// **************************************************************************
String _$getVideoListHash() => r'924c2961d148f9ebb0952239c0528d5269a4526a';
String _$getVideoListHash() => r'd1e21cd01a2d2eda2050c199f255eb0502d67fad';
/// Copied from Dart SDK
class _SystemHash {
@ -34,7 +34,8 @@ class _SystemHash {
const getVideoListProvider = GetVideoListFamily();
/// See also [getVideoList].
class GetVideoListFamily extends Family<AsyncValue<(List<Video>, bool)>> {
class GetVideoListFamily
extends Family<AsyncValue<(List<Video>, bool, String?)>> {
/// See also [getVideoList].
const GetVideoListFamily();
@ -73,7 +74,7 @@ class GetVideoListFamily extends Family<AsyncValue<(List<Video>, bool)>> {
/// See also [getVideoList].
class GetVideoListProvider
extends AutoDisposeFutureProvider<(List<Video>, bool)> {
extends AutoDisposeFutureProvider<(List<Video>, bool, String?)> {
/// See also [getVideoList].
GetVideoListProvider({
required Chapter episode,
@ -108,7 +109,8 @@ class GetVideoListProvider
@override
Override overrideWith(
FutureOr<(List<Video>, bool)> Function(GetVideoListRef provider) create,
FutureOr<(List<Video>, bool, String?)> Function(GetVideoListRef provider)
create,
) {
return ProviderOverride(
origin: this,
@ -125,7 +127,8 @@ class GetVideoListProvider
}
@override
AutoDisposeFutureProviderElement<(List<Video>, bool)> createElement() {
AutoDisposeFutureProviderElement<(List<Video>, bool, String?)>
createElement() {
return _GetVideoListProviderElement(this);
}
@ -143,13 +146,14 @@ class GetVideoListProvider
}
}
mixin GetVideoListRef on AutoDisposeFutureProviderRef<(List<Video>, bool)> {
mixin GetVideoListRef
on AutoDisposeFutureProviderRef<(List<Video>, bool, String?)> {
/// The parameter `episode` of this provider.
Chapter get episode;
}
class _GetVideoListProviderElement
extends AutoDisposeFutureProviderElement<(List<Video>, bool)>
extends AutoDisposeFutureProviderElement<(List<Video>, bool, String?)>
with GetVideoListRef {
_GetVideoListProviderElement(super.provider);