mirror of
https://github.com/kodjodevf/mangayomi-extensions.git
synced 2026-02-14 10:51:17 +00:00
Reorganize folders
This commit is contained in:
395
dart/anime/src/all/animeworldindia/animeworldindia.dart
Normal file
395
dart/anime/src/all/animeworldindia/animeworldindia.dart
Normal file
@@ -0,0 +1,395 @@
|
||||
import 'package:mangayomi/bridge_lib.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
class AnimeWorldIndia extends MProvider {
|
||||
AnimeWorldIndia({required this.source});
|
||||
|
||||
MSource source;
|
||||
|
||||
final Client client = Client(source);
|
||||
|
||||
@override
|
||||
Future<MPages> getPopular(int page) async {
|
||||
final res = (await client.get(Uri.parse(
|
||||
"${source.baseUrl}/advanced-search/page/$page/?s_lang=${source.lang}&s_orderby=viewed")))
|
||||
.body;
|
||||
|
||||
return parseAnimeList(res);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<MPages> getLatestUpdates(int page) async {
|
||||
final res = (await client.get(Uri.parse(
|
||||
"${source.baseUrl}/advanced-search/page/$page/?s_lang=${source.lang}&s_orderby=update")))
|
||||
.body;
|
||||
|
||||
return parseAnimeList(res);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<MPages> search(String query, int page, FilterList filterList) async {
|
||||
final filters = filterList.filters;
|
||||
String url =
|
||||
"${source.baseUrl}/advanced-search/page/$page/?s_keyword=$query&s_lang=${source.lang}";
|
||||
for (var filter in filters) {
|
||||
if (filter.type == "TypeFilter") {
|
||||
final type = filter.values[filter.state].value;
|
||||
url += "${ll(url)}s_type=$type";
|
||||
} else if (filter.type == "StatusFilter") {
|
||||
final status = filter.values[filter.state].value;
|
||||
url += "${ll(url)}s_status=$status";
|
||||
} else if (filter.type == "StyleFilter") {
|
||||
final style = filter.values[filter.state].value;
|
||||
url += "${ll(url)}s_sub_type=$style";
|
||||
} else if (filter.type == "YearFilter") {
|
||||
final year = filter.values[filter.state].value;
|
||||
url += "${ll(url)}s_year=$year";
|
||||
} else if (filter.type == "SortFilter") {
|
||||
final sort = filter.values[filter.state].value;
|
||||
url += "${ll(url)}s_orderby=$sort";
|
||||
} else if (filter.type == "GenresFilter") {
|
||||
final genre = (filter.state as List).where((e) => e.state).toList();
|
||||
url += "${ll(url)}s_genre=";
|
||||
if (genre.isNotEmpty) {
|
||||
for (var st in genre) {
|
||||
url += "${st.value}".toLowerCase().replaceAll(" ", "-");
|
||||
if (genre.length > 1) {
|
||||
url += "%2C";
|
||||
}
|
||||
}
|
||||
if (genre.length > 1) {
|
||||
url = substringBeforeLast(url, '%2C');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final res = (await client.get(Uri.parse(url))).body;
|
||||
return parseAnimeList(res);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<MManga> getDetail(String url) async {
|
||||
final res = (await client.get(Uri.parse(url))).body;
|
||||
MManga anime = MManga();
|
||||
final document = parseHtml(res);
|
||||
final isMovie =
|
||||
document.xpath('//li/a[contains(text(),"Movie")]/text()').isNotEmpty;
|
||||
if (isMovie) {
|
||||
anime.status = MStatus.completed;
|
||||
} else {
|
||||
final eps = xpath(
|
||||
res, '//ul/li/a[contains(@href,"${source.baseUrl}/watch")]/text()');
|
||||
if (eps.isNotEmpty) {
|
||||
final epParts = eps.first
|
||||
.substring(3)
|
||||
.replaceAll(" ", "")
|
||||
.replaceAll("\n", "")
|
||||
.split('/');
|
||||
if (epParts.length == 2) {
|
||||
if (epParts[0].compareTo(epParts[1]) == 0) {
|
||||
anime.status = MStatus.completed;
|
||||
} else {
|
||||
anime.status = MStatus.ongoing;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
anime.description = document.selectFirst("div[data-synopsis]")?.text ?? "";
|
||||
anime.author = document
|
||||
.xpath('//li[contains(text(),"Producers:")]/span/a/text()')
|
||||
.join(', ');
|
||||
anime.genre = document.xpath(
|
||||
'//span[@class="leading-6"]/a[contains(@class,"border-opacity-30")]/text()');
|
||||
final seasonsJson = json.decode(substringBeforeLast(
|
||||
substringBefore(
|
||||
substringAfter(res, "var season_list = "), "var season_label ="),
|
||||
";")) as List<Map<String, dynamic>>;
|
||||
bool isSingleSeason = seasonsJson.length == 1;
|
||||
List<MChapter>? episodesList = [];
|
||||
for (var i = 0; i < seasonsJson.length; i++) {
|
||||
final seasonJson = seasonsJson[i];
|
||||
final seasonName = isSingleSeason ? "" : "Season ${i + 1}";
|
||||
final episodesJson =
|
||||
(seasonJson["episodes"]["all"] as List<Map<String, dynamic>>)
|
||||
.reversed
|
||||
.toList();
|
||||
for (var j = 0; j < episodesJson.length; j++) {
|
||||
final episodeJson = episodesJson[j];
|
||||
final episodeTitle = episodeJson["metadata"]["title"] ?? "";
|
||||
String episodeName = "";
|
||||
if (isMovie) {
|
||||
episodeName = "Movie";
|
||||
} else {
|
||||
if (seasonName.isNotEmpty) {
|
||||
episodeName = "$seasonName - ";
|
||||
}
|
||||
episodeName += "Episode ${j + 1} ";
|
||||
if (episodeTitle.isNotEmpty) {
|
||||
episodeName += "- $episodeTitle";
|
||||
}
|
||||
}
|
||||
MChapter episode = MChapter();
|
||||
episode.name = episodeName;
|
||||
|
||||
episode.dateUpload =
|
||||
"${int.parse(episodeJson["metadata"]["released"] ?? "0") * 1000}";
|
||||
episode.url = "/wp-json/kiranime/v1/episode?id=${episodeJson["id"]}";
|
||||
episodesList.add(episode);
|
||||
}
|
||||
}
|
||||
|
||||
anime.chapters = episodesList.reversed.toList();
|
||||
return anime;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<MVideo>> getVideoList(String url) async {
|
||||
final res = (await client.get(Uri.parse("${source.baseUrl}$url"))).body;
|
||||
var resJson = substringBefore(
|
||||
substringAfterLast(res, "\"players\":"), ",\"noplayer\":");
|
||||
var streams = (json.decode(resJson) as List<Map<String, dynamic>>)
|
||||
.where((e) =>
|
||||
(e["type"] == "stream" ? true : false) &&
|
||||
(e["url"] as String).isNotEmpty)
|
||||
.toList()
|
||||
.where((e) => language(source.lang).isEmpty ||
|
||||
language(source.lang) == e["language"]
|
||||
? true
|
||||
: false)
|
||||
.toList();
|
||||
List<MVideo> videos = [];
|
||||
for (var stream in streams) {
|
||||
String videoUrl = stream["url"];
|
||||
final language = stream["language"];
|
||||
final video = await mystreamExtractor(videoUrl, language);
|
||||
videos.addAll(video);
|
||||
}
|
||||
|
||||
return sortVideos(videos, source.id);
|
||||
}
|
||||
|
||||
MPages parseAnimeList(String res) {
|
||||
List<MManga> animeList = [];
|
||||
final document = parseHtml(res);
|
||||
|
||||
for (var element in document.select("div.col-span-1")) {
|
||||
MManga anime = MManga();
|
||||
anime.name =
|
||||
element.selectFirst("div.font-medium.line-clamp-2.mb-3").text;
|
||||
anime.link = element.selectFirst("a").getHref;
|
||||
anime.imageUrl =
|
||||
"${source.baseUrl}${getUrlWithoutDomain(element.selectFirst("img").getSrc)}";
|
||||
animeList.add(anime);
|
||||
}
|
||||
final hasNextPage = xpath(res,
|
||||
'//li/span[@class="page-numbers current"]/parent::li//following-sibling::li/a/@href')
|
||||
.isNotEmpty;
|
||||
return MPages(animeList, hasNextPage);
|
||||
}
|
||||
|
||||
String language(String lang) {
|
||||
final languages = {
|
||||
"all": "",
|
||||
"bn": "bengali",
|
||||
"en": "english",
|
||||
"hi": "hindi",
|
||||
"ja": "japanese",
|
||||
"ml": "malayalam",
|
||||
"mr": "marathi",
|
||||
"ta": "tamil",
|
||||
"te": "telugu"
|
||||
};
|
||||
return languages[lang] ?? "";
|
||||
}
|
||||
|
||||
Future<List<MVideo>> mystreamExtractor(String url, String language) async {
|
||||
List<MVideo> videos = [];
|
||||
final res = (await client.get(Uri.parse(url))).body;
|
||||
final streamCode = substringBefore(
|
||||
substringAfter(substringAfter(res, "sniff("), ", \""), '"');
|
||||
|
||||
final streamUrl =
|
||||
"${substringBefore(url, "/watch")}/m3u8/$streamCode/master.txt?s=1&cache=1";
|
||||
final masterPlaylistRes = (await client.get(Uri.parse(streamUrl))).body;
|
||||
|
||||
List<MTrack> audios = [];
|
||||
for (var it in substringAfter(masterPlaylistRes, "#EXT-X-MEDIA:TYPE=AUDIO")
|
||||
.split("#EXT-X-MEDIA:TYPE=AUDIO")) {
|
||||
final line =
|
||||
substringBefore(substringAfter(it, "#EXT-X-MEDIA:TYPE=AUDIO"), "\n");
|
||||
final audioUrl = substringBefore(substringAfter(line, "URI=\""), "\"");
|
||||
MTrack audio = MTrack();
|
||||
audio
|
||||
..label = substringBefore(substringAfter(line, "NAME=\""), "\"")
|
||||
..file = audioUrl;
|
||||
audios.add(audio);
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
MVideo video = MVideo();
|
||||
video
|
||||
..url = videoUrl
|
||||
..originalUrl = videoUrl
|
||||
..quality = "[$language] MyStream - $quality"
|
||||
..audios = audios;
|
||||
videos.add(video);
|
||||
}
|
||||
return videos;
|
||||
}
|
||||
|
||||
@override
|
||||
List<dynamic> getFilterList() {
|
||||
return [
|
||||
SelectFilter("TypeFilter", "Type", 0, [
|
||||
SelectFilterOption("Any", "all"),
|
||||
SelectFilterOption("TV", "tv"),
|
||||
SelectFilterOption("Movie", "movies"),
|
||||
]),
|
||||
SelectFilter("StatusFilter", "Status", 0, [
|
||||
SelectFilterOption("Any", "all"),
|
||||
SelectFilterOption("Currently Airing", "airing"),
|
||||
SelectFilterOption("Finished Airing", "completed"),
|
||||
]),
|
||||
SelectFilter("StyleFilter", "Style", 0, [
|
||||
SelectFilterOption("Any", "all"),
|
||||
SelectFilterOption("Anime", "anime"),
|
||||
SelectFilterOption("Cartoon", "cartoon"),
|
||||
]),
|
||||
SelectFilter("YearFilter", "Year", 0, [
|
||||
SelectFilterOption("Any", "all"),
|
||||
SelectFilterOption("2024", "2024"),
|
||||
SelectFilterOption("2023", "2023"),
|
||||
SelectFilterOption("2022", "2022"),
|
||||
SelectFilterOption("2021", "2021"),
|
||||
SelectFilterOption("2020", "2020"),
|
||||
SelectFilterOption("2019", "2019"),
|
||||
SelectFilterOption("2018", "2018"),
|
||||
SelectFilterOption("2017", "2017"),
|
||||
SelectFilterOption("2016", "2016"),
|
||||
SelectFilterOption("2015", "2015"),
|
||||
SelectFilterOption("2014", "2014"),
|
||||
SelectFilterOption("2013", "2013"),
|
||||
SelectFilterOption("2012", "2012"),
|
||||
SelectFilterOption("2011", "2011"),
|
||||
SelectFilterOption("2010", "2010"),
|
||||
SelectFilterOption("2009", "2009"),
|
||||
SelectFilterOption("2008", "2008"),
|
||||
SelectFilterOption("2007", "2007"),
|
||||
SelectFilterOption("2006", "2006"),
|
||||
SelectFilterOption("2005", "2005"),
|
||||
SelectFilterOption("2004", "2004"),
|
||||
SelectFilterOption("2003", "2003"),
|
||||
SelectFilterOption("2002", "2002"),
|
||||
SelectFilterOption("2001", "2001"),
|
||||
SelectFilterOption("2000", "2000"),
|
||||
SelectFilterOption("1999", "1999"),
|
||||
SelectFilterOption("1998", "1998"),
|
||||
SelectFilterOption("1997", "1997"),
|
||||
SelectFilterOption("1996", "1996"),
|
||||
SelectFilterOption("1995", "1995"),
|
||||
SelectFilterOption("1994", "1994"),
|
||||
SelectFilterOption("1993", "1993"),
|
||||
SelectFilterOption("1992", "1992"),
|
||||
SelectFilterOption("1991", "1991"),
|
||||
SelectFilterOption("1990", "1990")
|
||||
]),
|
||||
SelectFilter("SortFilter", "Sort", 0, [
|
||||
SelectFilterOption("Default", "default"),
|
||||
SelectFilterOption("Ascending", "title_a_z"),
|
||||
SelectFilterOption("Descending", "title_z_a"),
|
||||
SelectFilterOption("Updated", "update"),
|
||||
SelectFilterOption("Published", "date"),
|
||||
SelectFilterOption("Most Viewed", "viewed"),
|
||||
SelectFilterOption("Favourite", "favorite"),
|
||||
]),
|
||||
GroupFilter("GenresFilter", "Genres", [
|
||||
CheckBoxFilter("Action", "Action"),
|
||||
CheckBoxFilter("Adult Cast", "Adult Cast"),
|
||||
CheckBoxFilter("Adventure", "Adventure"),
|
||||
CheckBoxFilter("Animation", "Animation"),
|
||||
CheckBoxFilter("Comedy", "Comedy"),
|
||||
CheckBoxFilter("Detective", "Detective"),
|
||||
CheckBoxFilter("Drama", "Drama"),
|
||||
CheckBoxFilter("Ecchi", "Ecchi"),
|
||||
CheckBoxFilter("Family", "Family"),
|
||||
CheckBoxFilter("Fantasy", "Fantasy"),
|
||||
CheckBoxFilter("Isekai", "Isekai"),
|
||||
CheckBoxFilter("Kids", "Kids"),
|
||||
CheckBoxFilter("Martial Arts", "Martial Arts"),
|
||||
CheckBoxFilter("Mecha", "Mecha"),
|
||||
CheckBoxFilter("Military", "Military"),
|
||||
CheckBoxFilter("Mystery", "Mystery"),
|
||||
CheckBoxFilter("Otaku Culture", "Otaku Culture"),
|
||||
CheckBoxFilter("Reality", "Reality"),
|
||||
CheckBoxFilter("Romance", "Romance"),
|
||||
CheckBoxFilter("School", "School"),
|
||||
CheckBoxFilter("Sci-Fi", "Sci-Fi"),
|
||||
CheckBoxFilter("Seinen", "Seinen"),
|
||||
CheckBoxFilter("Shounen", "Shounen"),
|
||||
CheckBoxFilter("Slice of Life", "Slice of Life"),
|
||||
CheckBoxFilter("Sports", "Sports"),
|
||||
CheckBoxFilter("Super Power", "Super Power"),
|
||||
CheckBoxFilter("SuperHero", "SuperHero"),
|
||||
CheckBoxFilter("Supernatural", "Supernatural"),
|
||||
CheckBoxFilter("TV Movie", "TV Movie"),
|
||||
]),
|
||||
];
|
||||
}
|
||||
|
||||
@override
|
||||
List<dynamic> getSourcePreferences() {
|
||||
return [
|
||||
ListPreference(
|
||||
key: "preferred_quality",
|
||||
title: "Preferred Quality",
|
||||
summary: "",
|
||||
valueIndex: 0,
|
||||
entries: ["1080p", "720p", "480p", "360p", "240p"],
|
||||
entryValues: ["1080", "720", "480", "360", "240"]),
|
||||
];
|
||||
}
|
||||
|
||||
List<MVideo> sortVideos(List<MVideo> videos, int sourceId) {
|
||||
String quality = getPreferenceValue(sourceId, "preferred_quality");
|
||||
videos.sort((MVideo a, MVideo b) {
|
||||
int qualityMatchA = 0;
|
||||
|
||||
if (a.quality.contains(quality)) {
|
||||
qualityMatchA = 1;
|
||||
}
|
||||
int qualityMatchB = 0;
|
||||
if (b.quality.contains(quality)) {
|
||||
qualityMatchB = 1;
|
||||
}
|
||||
if (qualityMatchA != qualityMatchB) {
|
||||
return qualityMatchB - qualityMatchA;
|
||||
}
|
||||
|
||||
final regex = RegExp(r'(\d+)p');
|
||||
final matchA = regex.firstMatch(a.quality);
|
||||
final matchB = regex.firstMatch(b.quality);
|
||||
final int qualityNumA = int.tryParse(matchA?.group(1) ?? '0') ?? 0;
|
||||
final int qualityNumB = int.tryParse(matchB?.group(1) ?? '0') ?? 0;
|
||||
return qualityNumB - qualityNumA;
|
||||
});
|
||||
return videos;
|
||||
}
|
||||
|
||||
String ll(String url) {
|
||||
if (url.contains("?")) {
|
||||
return "&";
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
AnimeWorldIndia main(MSource source) {
|
||||
return AnimeWorldIndia(source: source);
|
||||
}
|
||||
BIN
dart/anime/src/all/animeworldindia/icon.png
Normal file
BIN
dart/anime/src/all/animeworldindia/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.4 KiB |
33
dart/anime/src/all/animeworldindia/sources.dart
Normal file
33
dart/anime/src/all/animeworldindia/sources.dart
Normal file
@@ -0,0 +1,33 @@
|
||||
import '../../../../../model/source.dart';
|
||||
|
||||
const _animeworldindiaVersion = "0.0.25";
|
||||
const _animeworldindiaSourceCodeUrl =
|
||||
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/all/animeworldindia/animeworldindia.dart";
|
||||
|
||||
String _iconUrl =
|
||||
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/all/animeworldindia/icon.png";
|
||||
|
||||
List<String> _languages = [
|
||||
"all",
|
||||
"en",
|
||||
"bn",
|
||||
"hi",
|
||||
"ja",
|
||||
"ml",
|
||||
"mr",
|
||||
"ta",
|
||||
"te",
|
||||
];
|
||||
|
||||
List<Source> get animeworldindiaSourcesList => _animeworldindiaSourcesList;
|
||||
List<Source> _animeworldindiaSourcesList = _languages
|
||||
.map((e) => Source(
|
||||
name: 'AnimeWorld India',
|
||||
baseUrl: "https://anime-world.in",
|
||||
lang: e,
|
||||
typeSource: "multiple",
|
||||
iconUrl: _iconUrl,
|
||||
version: _animeworldindiaVersion,
|
||||
isManga: false,
|
||||
sourceCodeUrl: _animeworldindiaSourceCodeUrl))
|
||||
.toList();
|
||||
Reference in New Issue
Block a user