Merge pull request #288 from Yogesh-S-09/main

Server Problem Fixed
This commit is contained in:
Moustapha Kodjo Amadou
2025-06-17 07:45:44 +01:00
committed by GitHub
2 changed files with 129 additions and 61 deletions

View File

@@ -70,19 +70,19 @@ class DonghuaStream extends MProvider {
@override @override
Future<MManga> getDetail(String url) async { Future<MManga> getDetail(String url) async {
final res = (await client.get(Uri.parse(url))).body; final res = (await client.get(Uri.parse(url))).body;
MManga anime = MManga(); MManga anime = MManga();
var genre = xpath(res,'//div[@class="genxed"]/a/text()'); var genre = xpath(res,'//div[@class="genxed"]/a/text()');
genre.remove('MY FAVOURITE'); genre.remove('MY FAVOURITE');
anime.genre = genre; anime.genre = genre;
anime.description = xpath(res,'//div[@class="entry-content"]/p/text()').join("\n"); anime.description = xpath(res,'//div[@class="entry-content"]/p/text()').join("\n");
final statusList = [{"Status: Ongoing": 0, "Status: Completed": 1}]; final statusList = [{"Status: Ongoing": 0, "Status: Completed": 1}];
final infoContent = xpath(res,'//div[@class="info-content"]/div[@class="spe"]/span/text()'); final infoContent = xpath(res,'//div[@class="info-content"]/div[@class="spe"]/span/text()');
anime.status = parseStatus(infoContent[0], statusList); anime.status = parseStatus(infoContent[0], statusList);
anime.author = infoContent[1].replaceFirst('Network: ','').replaceFirst('Donghua Stream, ',''); anime.author = infoContent[1].replaceFirst('Network: ','').replaceFirst('Donghua Stream, ','');
anime.artist = infoContent[2].replaceFirst('Studio: ',''); anime.artist = infoContent[2].replaceFirst('Studio: ','');
final epElements = parseHtml(res).select('div.eplister > ul > li >a'); final epElements = parseHtml(res).select('div.eplister > ul > li >a');
List<MChapter>? episodesList = []; List<MChapter>? episodesList = [];
for (var epElement in epElements) { for (var epElement in epElements) {
@@ -95,30 +95,42 @@ class DonghuaStream extends MProvider {
episode.dateUpload = parseDates([dateString],"MMMM d, yyyy","en",)[0]; episode.dateUpload = parseDates([dateString],"MMMM d, yyyy","en",)[0];
episodesList.add(episode); episodesList.add(episode);
} }
anime.chapters = episodesList; anime.chapters = episodesList;
return anime; return anime;
} }
// For anime episode video list // For anime episode video list
@override @override
Future<List<MVideo>> getVideoList(String url) async { Future<List<MVideo>> getVideoList(String url) async {
final res = (await client.get(Uri.parse(url))).body; final res = (await client.get(Uri.parse(url))).body;
final servers = parseHtml(res).select('select.mirror > option[data-index]'); var servers = parseHtml(res).select('select.mirror > option[data-index]');
List<MVideo> videos = []; if(servers.length==0){
for (var i = 0; i < servers.length; i++) { final src_data = parseHtml(res).selectFirst('article[id] > script').attr('src').replaceAll ('data:text/javascript;base64,','');
String name = '${servers[i].attr("data-index")}: ${servers[i].text}'; final src_function = utf8.decode(base64Url.decode(src_data));
String valueHtml = utf8.decode(base64Url.decode(servers[i].attr('value'))); final html_data = RegExp(r'"html":"(.*?)","autoplayIndex"').firstMatch(src_function).group(1);
String serverUrl = xpath(valueHtml,'//iframe/@src')[0]; servers = parseHtml(html_data.replaceAll(r'\t', '\t').replaceAll(r'\n', '\n').replaceAll(r'\"', '"').replaceAll(r'\/', '/')).select('select.mirror > option[data-index]');
if(serverUrl.startsWith('https://geo.dailymotion.com/player')){ }
String videoId = RegExp(r'[?&]video=([a-zA-Z0-9]+)').firstMatch(serverUrl).group(1)!; List<MVideo> videos = [];
return dailymotionUrlFetcher(videoId,name); for (var i = 0; i < servers.length; i++) {
String name = '${servers[i].attr("data-index")}: ${servers[i].text}';
String valueHtml = utf8.decode(base64Url.decode(servers[i].attr('value')));
final serverUrlList = xpath(valueHtml,'//iframe/@src');
if (serverUrlList.length>0){
String serverUrl = serverUrlList[0];
if(serverUrl.contains('https://geo.dailymotion.com/player')){
String videoId = RegExp(r'[?&]video=([a-zA-Z0-9]+)').firstMatch(serverUrl).group(1);
videos.addAll(await dailymotionVideosFetcher(videoId,name));
}else if(serverUrl.contains('//play.streamplay.co.in/')){
String videoId = serverUrl.split('/embed/')[1];
videos.addAll(await streamplayVideosFetcher(videoId,name));
} }
} }
return videos; }
return videos;
} }
Future<List<MVideo>> dailymotionUrlFetcher(String videoID, String name) async { Future<List<MVideo>> dailymotionVideosFetcher(String videoID, String name) async {
String metaDataUrl = 'https://www.dailymotion.com/player/metadata/video/$videoID'; String metaDataUrl = 'https://www.dailymotion.com/player/metadata/video/$videoID';
final res = (await client.get(Uri.parse(metaDataUrl))).body; final res = (await client.get(Uri.parse(metaDataUrl))).body;
final jsonRes = json.decode(res); final jsonRes = json.decode(res);
@@ -126,45 +138,101 @@ class DonghuaStream extends MProvider {
return m3u8extractor(masterUrl, name); return m3u8extractor(masterUrl, name);
} }
Future<List<MVideo>> streamplayVideosFetcher(String videoID, String name) async {
String url = 'https://play.streamplay.co.in/embed/'+videoID;
final res = (await client.get(Uri.parse(url))).body;
final match = RegExp(r"eval\(function\(p,a,c,k,e,d\)\{[\s\S]*?\}\((.*?)\)").firstMatch(res);
if (match == null) {
return [];
}
final argsStr = match.group(1);
final argsPattern = RegExp(r"'(.*?)',(.*?),(.*?),'(.*?)'\.split");
final argsMatches = argsPattern.firstMatch(argsStr);
final arg_p = argsMatches.group(1);
final arg_a =int.parse(argsMatches.group(2));
final arg_c =int.parse(argsMatches.group(3));
final arg_k =argsMatches.group(4).split('|').toList();
final unpacked_js = unpack(arg_p,arg_a,arg_c,arg_k);
final kakenMatch = RegExp(r'window\.kaken\s*=\s*"([^"]+)"').firstMatch(unpacked_js);
if (kakenMatch == null) {
return [];
}
final kakenValue = kakenMatch.group(1);
final apiUrl = 'https://play.streamplay.co.in/api/?$kakenValue';
final apiRes = (await client.get(Uri.parse(apiUrl))).body;
final jsonRes = json.decode(apiRes);
String masterUrl = jsonRes['sources'][0]['file'];
List<MTrack> subtitles = [];
for (final track in jsonRes['tracks']){
MTrack subtitle = MTrack();
subtitle.label = name + ' - ' + track['label'];
subtitle.file = track['file'];
subtitles.add(subtitle);
}
List<MVideo> videos = await m3u8extractor(masterUrl, name);
if(videos.length>0){
videos[0].subtitles = subtitles;
}
return videos;
}
String unpack(String p, int a, int c, List<String> k) {
for (int i = c - 1; i >= 0; i--) {
String word = (i < k.length) ? k[i] : baseN(i, a);
String pattern = r'\b' + baseN(i, a) + r'\b';
p = p.replaceAll(RegExp(pattern), word);
}
return p;
}
String baseN(int num, int base) {
const digits = '0123456789abcdefghijklmnopqrstuvwxyz';
if (num == 0) return '0';
String result = '';
while (num > 0) {
result = digits[num % base] + result;
num ~/= base;
}
return result;
}
Future<List<MVideo>> m3u8extractor(String masterUrl, String name) async { Future<List<MVideo>> m3u8extractor(String masterUrl, String name) async {
List<MVideo> videos = []; List<MVideo> videos = [];
List<MTrack> subtitles = []; List<MTrack> subtitles = [];
final masterPlaylistRes = final masterPlaylistRes = (await client.get(Uri.parse(masterUrl), headers: headers)).body;
(await client.get(Uri.parse(masterUrl), headers: headers)).body; final subtitleRegExp = RegExp(r'#EXT-X-MEDIA:TYPE=SUBTITLES.*?NAME="(.*?)".*?URI="(.*?)"', dotAll: true);
for (final match in subtitleRegExp.allMatches(masterPlaylistRes)) {
// Parse Subtitles MTrack subtitle = MTrack();
final subtitleRegExp = RegExp(r'#EXT-X-MEDIA:TYPE=SUBTITLES.*?NAME="(.*?)".*?URI="(.*?)"', dotAll: true); subtitle.label = name + ' - ' + match.group(1) ?? 'Subtitle';
for (final match in subtitleRegExp.allMatches(masterPlaylistRes)) { subtitle.file = match.group(2) ?? '';
MTrack subtitle = MTrack(); subtitles.add(subtitle);
subtitle.label = match.group(1) ?? 'Subtitle'; }
subtitle.file = match.group(2) ?? '';
subtitles.add(subtitle); for (var it in substringAfter(
masterPlaylistRes,
"#EXT-X-STREAM-INF:",
).split("#EXT-X-STREAM-INF:")) {
final quality =
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p";
String videoUrl = substringBefore(substringAfter(it, "\n"), "\n");
if (!videoUrl.startsWith("http")) {
videoUrl =
"${masterUrl.split("/").sublist(0, masterUrl.split("/").length - 1).join("/")}/$videoUrl";
} }
for (var it in substringAfter( MVideo video = MVideo();
masterPlaylistRes, video
"#EXT-X-STREAM-INF:", ..url = videoUrl
).split("#EXT-X-STREAM-INF:")) { ..originalUrl = videoUrl
final quality = ..quality = "$name - $quality";
"${substringBefore(substringBefore(substringAfter(substringAfter(it, "RESOLUTION="), "x"), ","), "\n")}p"; videos.add(video);
}
String videoUrl = substringBefore(substringAfter(it, "\n"), "\n"); if(videos.length>0){
videos[0].subtitles = subtitles;
if (!videoUrl.startsWith("http")) { }
videoUrl = return videos;
"${masterUrl.split("/").sublist(0, masterUrl.split("/").length - 1).join("/")}/$videoUrl";
}
MVideo video = MVideo();
video
..url = videoUrl
..originalUrl = videoUrl
..quality = "$name - $quality"
..subtitles = subtitles
..headers = headers;
videos.add(video);
}
return videos;
} }
} }

View File

@@ -1,7 +1,7 @@
import '../../../../../model/source.dart'; import '../../../../../model/source.dart';
Source get donghuastreamSource => _donghuastreamSource; Source get donghuastreamSource => _donghuastreamSource;
const _donghuastreamVersion = "0.0.1"; const _donghuastreamVersion = "0.0.2";
const _donghuastreamSourceCodeUrl = const _donghuastreamSourceCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/en/donghuastream/donghuastream.dart"; "https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/en/donghuastream/donghuastream.dart";
Source _donghuastreamSource = Source( Source _donghuastreamSource = Source(