mirror of
https://github.com/kodjodevf/mangayomi-extensions.git
synced 2026-02-14 02:41:39 +00:00
@@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
Reference in New Issue
Block a user