mangayomi/lib/services/torrent_server.dart
kodjomoustapha a086e918b6 Update
2024-02-08 20:39:35 +01:00

117 lines
3.7 KiB
Dart

import 'dart:convert';
import 'dart:io';
import 'dart:isolate';
import 'package:flutter/services.dart';
import 'package:http_interceptor/http_interceptor.dart';
import 'package:mangayomi/main.dart';
import 'package:mangayomi/models/settings.dart';
import 'package:mangayomi/models/video.dart';
import 'package:mangayomi/providers/storage_provider.dart';
import 'package:mangayomi/services/http/interceptor.dart';
import 'package:mangayomi/utils/extensions/string_extensions.dart';
import 'package:mangayomi/ffi/torrent_server_ffi.dart' as libmtorrentserver_ffi;
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'torrent_server.g.dart';
class MTorrentServer {
final http = MInterceptor.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;
try {
final res = await http.get(Uri.parse("$_baseUrl/"));
if (res.statusCode == 200) {
return true;
}
return false;
} catch (_) {
return false;
}
}
Future<String> getInfohash(String url) async {
try {
final torrentByte = (await http.get(Uri.parse(url))).bodyBytes;
var request =
MultipartRequest('POST', Uri.parse('$_baseUrl/torrent/add'));
request.files.add(MultipartFile.fromBytes('file', torrentByte,
filename: 'file.torrent'));
StreamedResponse response = await request.send();
return await response.stream.bytesToString();
} catch (e) {
rethrow;
}
}
Future<(List<Video>, String?)> getTorrentPlaylist(String url) async {
final isRunning = await check();
if (!isRunning) {
final path = (await StorageProvider().getBtDirectory())!.path;
final config = jsonEncode({"path": path, "address": "127.0.0.1:0"});
int port = 0;
if (Platform.isAndroid || Platform.isIOS) {
const channel =
MethodChannel('com.kodjodevf.mangayomi.libmtorrentserver');
port = await channel.invokeMethod('start', {"config": config});
} else {
port = await Isolate.run(() async {
return libmtorrentserver_ffi.start(config);
});
}
_setBtServerPort(port);
}
bool isMagnet = !url.startsWith("http");
String finalUrl = "";
String? infohash;
if (!isMagnet) {
infohash = await getInfohash(url);
finalUrl = "$_baseUrl/torrent/play?infohash=$infohash";
} else {
finalUrl = "$_baseUrl/torrent/play?magnet=$url";
}
final masterPlaylist = (await http.get(Uri.parse(finalUrl))).body;
final videoList = <Video>[];
const separator = "#EXTINF:";
for (var e in masterPlaylist.substringAfter(separator).split(separator)) {
final fileName = e.substringAfter("0,").substringBefore("\n");
if (fileName.isMediaVideo()) {
var videoUrl = e.substringAfter("\n").substringBefore("\n");
videoList.add(Video(videoUrl, fileName, videoUrl));
}
}
return (videoList, infohash);
}
}
String get _baseUrl {
final settings = isar.settings.getSync(227);
final port = settings!.btServerPort ?? 0;
final address = settings.btServerAddress ?? "127.0.0.1";
return "http://$address:$port";
}
void _setBtServerPort(int newPort) {
isar.writeTxnSync(() => isar.settings
.putSync(isar.settings.getSync(227)!..btServerPort = newPort));
}
@riverpod
Future<bool> mTorrentIsRunning(MTorrentIsRunningRef ref) async {
return await MTorrentServer().check();
}