mirror of
https://github.com/kodjodevf/mangayomi-extensions.git
synced 2026-02-14 02:41:39 +00:00
346 lines
14 KiB
Dart
346 lines
14 KiB
Dart
import 'package:mangayomi/bridge_lib.dart';
|
|
import 'dart:convert';
|
|
|
|
class YoMovies extends MProvider {
|
|
YoMovies();
|
|
|
|
final Client client = Client();
|
|
|
|
@override
|
|
bool get supportsLatest => false;
|
|
|
|
@override
|
|
Future<MPages> getPopular(MSource source, int page) async {
|
|
String pageNu = page == 1 ? "" : "page/$page/";
|
|
|
|
final res = (await client.get(Uri.parse(
|
|
"${preferenceBaseUrl(source.id)}/most-favorites/$pageNu")))
|
|
.body;
|
|
final document = parseHtml(res);
|
|
return animeFromElement(
|
|
document.select("div.movies-list > div.ml-item"),
|
|
document.selectFirst("ul.pagination > li.active + li")?.getHref !=
|
|
null);
|
|
}
|
|
|
|
@override
|
|
Future<MPages> getLatestUpdates(MSource source, int page) async {
|
|
return MPages([], false);
|
|
}
|
|
|
|
@override
|
|
Future<MPages> search(
|
|
MSource source, String query, int page, FilterList filterList) async {
|
|
final filters = filterList.filters;
|
|
String url = "";
|
|
String pageNu = page == 1 ? "" : "/page/$page";
|
|
if (query.isNotEmpty) {
|
|
url = "${preferenceBaseUrl(source.id)}$pageNu/?s=$query";
|
|
} else {
|
|
for (var filter in filters) {
|
|
if (filter.type.isNotEmpty) {
|
|
final first = filter.values[filter.state].value;
|
|
if (first.isNotEmpty) {
|
|
url = first;
|
|
}
|
|
}
|
|
}
|
|
url = "${preferenceBaseUrl(source.id)}$url$pageNu";
|
|
}
|
|
final res = (await client.get(Uri.parse(url))).body;
|
|
final document = parseHtml(res);
|
|
return animeFromElement(
|
|
document.select("div.movies-list > div.ml-item"),
|
|
document.selectFirst("ul.pagination > li.active + li")?.getHref !=
|
|
null);
|
|
}
|
|
|
|
@override
|
|
Future<MManga> getDetail(MSource source, String url) async {
|
|
url = Uri.parse(url).path;
|
|
|
|
final res =
|
|
(await client.get(Uri.parse("${preferenceBaseUrl(source.id)}$url")))
|
|
.body;
|
|
final document = parseHtml(res);
|
|
MManga anime = MManga();
|
|
var infoElement = document.selectFirst("div.mvi-content");
|
|
anime.description = infoElement.selectFirst("p.f-desc")?.text ?? "";
|
|
|
|
anime.genre = xpath(res,
|
|
'//div[@class="mvici-left" and contains(text(),"Genre:")]/p/a/text()');
|
|
|
|
List<MChapter> episodeList = [];
|
|
final seasonListElements = document.select("div#seasons > div.tvseason");
|
|
if (seasonListElements.isEmpty) {
|
|
MChapter ep = MChapter();
|
|
ep.name = "Movie";
|
|
ep.url = url;
|
|
episodeList.add(ep);
|
|
} else {
|
|
for (var season in seasonListElements) {
|
|
var seasonText = season.selectFirst("div.les-title").text.trim();
|
|
for (var episode in season.select("div.les-content > a")) {
|
|
var epNumber = substringAfter(episode.text.trim(), "pisode ");
|
|
MChapter ep = MChapter();
|
|
ep.name = "$seasonText Ep. $epNumber";
|
|
ep.url = episode.getHref;
|
|
|
|
episodeList.add(ep);
|
|
}
|
|
}
|
|
}
|
|
|
|
anime.chapters = episodeList.reversed.toList();
|
|
return anime;
|
|
}
|
|
|
|
@override
|
|
Future<List<MVideo>> getVideoList(MSource source, String url) async {
|
|
url = Uri.parse(url).path;
|
|
final res =
|
|
(await client.get(Uri.parse("${preferenceBaseUrl(source.id)}$url")))
|
|
.body;
|
|
final document = parseHtml(res);
|
|
final serverElements = document.select("div.movieplay > iframe");
|
|
List<MVideo> videos = [];
|
|
for (var serverElement in serverElements) {
|
|
var url = serverElement.getSrc;
|
|
List<MVideo> a = [];
|
|
if (url.contains("minoplres")) {
|
|
a = await minoplresExtractor(url);
|
|
}
|
|
videos.addAll(a);
|
|
}
|
|
return sortVideos(videos, source.id);
|
|
}
|
|
|
|
@override
|
|
List<dynamic> getSourcePreferences(MSource source) {
|
|
return [
|
|
EditTextPreference(
|
|
key: "overrideBaseUrl",
|
|
title: "Override BaseUrl",
|
|
summary: "",
|
|
value: "https://yomovies.boo",
|
|
dialogTitle: "Override BaseUrl",
|
|
dialogMessage: "",
|
|
text: "https://yomovies.boo"),
|
|
ListPreference(
|
|
key: "preferred_quality",
|
|
title: "Preferred quality",
|
|
summary: "",
|
|
valueIndex: 0,
|
|
entries: ["1080p", "720p", "480p", "360p"],
|
|
entryValues: ["1080", "720", "480", "360"])
|
|
];
|
|
}
|
|
|
|
Future<List<MVideo>> minoplresExtractor(String url) async {
|
|
List<MVideo> videos = [];
|
|
|
|
final res =
|
|
(await client.get(Uri.parse(url), headers: {"Referer": url})).body;
|
|
final script = xpath(res, '//script[contains(text(),"sources:")]/text()');
|
|
if (script.isEmpty) return [];
|
|
final masterUrl =
|
|
substringBefore(substringAfter(script.first, "file:\""), '"');
|
|
final masterPlaylistRes = (await client.get(Uri.parse(masterUrl))).body;
|
|
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 = "Minoplres - $quality";
|
|
videos.add(video);
|
|
}
|
|
return videos;
|
|
}
|
|
|
|
String preferenceBaseUrl(int sourceId) {
|
|
return getPreferenceValue(sourceId, "overrideBaseUrl");
|
|
}
|
|
|
|
MPages animeFromElement(List<MElement> elements, bool hasNextPage) {
|
|
List<MManga> animeList = [];
|
|
for (var element in elements) {
|
|
MManga anime = MManga();
|
|
anime.name = element.selectFirst("div.qtip-title").text;
|
|
anime.imageUrl =
|
|
element.selectFirst("img[data-original]")?.attr("data-original") ??
|
|
"";
|
|
anime.link = element.selectFirst("a[href]").getHref;
|
|
animeList.add(anime);
|
|
}
|
|
return MPages(animeList, hasNextPage);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
@override
|
|
List<dynamic> getFilterList(MSource source) {
|
|
return [
|
|
HeaderFilter(
|
|
"Note: Only one selection at a time works, and it ignores text search"),
|
|
SeparatorFilter(),
|
|
SelectFilter("BollywoodFilter", "Bollywood", 0, [
|
|
SelectFilterOption("<select>", ""),
|
|
SelectFilterOption("Bollywood", "/genre/bollywood"),
|
|
SelectFilterOption("Trending", "/genre/top-rated"),
|
|
SelectFilterOption("Bollywood (2023)",
|
|
"/account/?ptype=post&tax_category%5B%5D=bollywood&tax_release-year=2023&wpas=1"),
|
|
SelectFilterOption("Bollywood (2022)",
|
|
"/account/?ptype=post&tax_category%5B%5D=bollywood&tax_release-year=2022&wpas=1"),
|
|
SelectFilterOption("Bollywood (2021)",
|
|
"/account/?ptype=post&tax_category%5B%5D=bollywood&tax_release-year=2021&wpas=1"),
|
|
]),
|
|
SelectFilter("DualAudioFilter", "Dual Audio", 0, [
|
|
SelectFilterOption("<select>", ""),
|
|
SelectFilterOption("Dual Audio", "/genre/dual-audio"),
|
|
SelectFilterOption("Hollywood Dubbed",
|
|
"/account/?ptype=post&tax_category%5B%5D=dual-audio&wpas=1"),
|
|
SelectFilterOption("South Dubbed",
|
|
"/account/?ptype=post&tax_category%5B%5D=dual-audio&tax_category%5B%5D=south-special&wpas=1"),
|
|
]),
|
|
SelectFilter("HollywoodFilter", "Hollywood", 0, [
|
|
SelectFilterOption("<select>", ""),
|
|
SelectFilterOption("Hollywood", "/genre/hollywood"),
|
|
SelectFilterOption("Hollywood (2023)",
|
|
"/account/?ptype=post&tax_category%5B%5D=hollywood&tax_release-year=2023&wpas=1"),
|
|
SelectFilterOption("Hollywood (2022)",
|
|
"/account/?ptype=post&tax_category%5B%5D=hollywood&tax_release-year=2022&wpas=1"),
|
|
SelectFilterOption("Hollywood (2021)",
|
|
"/account/?ptype=post&tax_category%5B%5D=hollywood&tax_release-year=2021&wpas=1"),
|
|
]),
|
|
SelectFilter("EnglishSeriesFilter", "Hindi Series", 0, [
|
|
SelectFilterOption("<select>", ""),
|
|
SelectFilterOption("English Series", "/series"),
|
|
]),
|
|
SelectFilter("HindiSeriesFilter", "English Series", 0, [
|
|
SelectFilterOption("<select>", ""),
|
|
SelectFilterOption("Hindi Series", "/genre/web-series"),
|
|
SelectFilterOption("Netflix", "/director/netflix"),
|
|
SelectFilterOption("Amazon", "/director/amazon-prime"),
|
|
SelectFilterOption("Altbalaji", "/director/altbalaji"),
|
|
SelectFilterOption("Zee5", "/director/zee5"),
|
|
SelectFilterOption("Voot", "/director/voot-originals"),
|
|
SelectFilterOption("Mx Player", "/director/mx-player"),
|
|
SelectFilterOption("Hotstar", "/director/hotstar"),
|
|
SelectFilterOption("Viu", "/director/viu-originals"),
|
|
SelectFilterOption("Sony Liv", "/director/sonyliv-original"),
|
|
]),
|
|
SelectFilter("GenreFilter", "Genre", 0, [
|
|
SelectFilterOption("<select>", ""),
|
|
SelectFilterOption("Action", "/genre/action"),
|
|
SelectFilterOption("Adventure", "/genre/adventure"),
|
|
SelectFilterOption("Animation", "/genre/animation"),
|
|
SelectFilterOption("Biography", "/genre/biography"),
|
|
SelectFilterOption("Comedy", "/genre/comedy"),
|
|
SelectFilterOption("Crime", "/genre/crime"),
|
|
SelectFilterOption("Drama", "/genre/drama"),
|
|
SelectFilterOption("Music", "/genre/music"),
|
|
SelectFilterOption("Mystery", "/genre/mystery"),
|
|
SelectFilterOption("Family", "/genre/family"),
|
|
SelectFilterOption("Fantasy", "/genre/fantasy"),
|
|
SelectFilterOption("Horror", "/genre/horror"),
|
|
SelectFilterOption("History", "/genre/history"),
|
|
SelectFilterOption("Romance", "/genre/romantic"),
|
|
SelectFilterOption("Science Fiction", "/genre/science-fiction"),
|
|
SelectFilterOption("Thriller", "/genre/thriller"),
|
|
SelectFilterOption("War", "/genre/war"),
|
|
]),
|
|
SelectFilter("ExtraMoviesFilter", "ExtraMovies", 0, [
|
|
SelectFilterOption("<select>", ""),
|
|
SelectFilterOption("ExtraMovies", "/genre/south-special"),
|
|
SelectFilterOption("Bengali", "/genre/bengali"),
|
|
SelectFilterOption("Marathi", "/genre/marathi"),
|
|
SelectFilterOption("Gujarati", "/genre/gujarati"),
|
|
SelectFilterOption("Punjabi", "/genre/punjabi"),
|
|
SelectFilterOption("Tamil", "/genre/tamil"),
|
|
SelectFilterOption("Telugu", "/genre/telugu"),
|
|
SelectFilterOption("Malayalam", "/genre/malayalam"),
|
|
SelectFilterOption("Kannada", "/genre/kannada"),
|
|
SelectFilterOption("Pakistani", "/genre/pakistani"),
|
|
]),
|
|
SelectFilter("EroticFilter", "Erotic", 0, [
|
|
SelectFilterOption("<select>", ""),
|
|
SelectFilterOption("Erotic", "/genre/erotic-movies"),
|
|
]),
|
|
SelectFilter("HotSeriesFilter", "Hot Series", 0, [
|
|
SelectFilterOption("<select>", ""),
|
|
SelectFilterOption("Hot Series", "/genre/tv-shows"),
|
|
SelectFilterOption("Uncut", "/?s=uncut"),
|
|
SelectFilterOption("Fliz Movies", "/director/fliz-movies"),
|
|
SelectFilterOption("Nuefliks", "/director/nuefliks-exclusive"),
|
|
SelectFilterOption("Hotshots", "/director/hotshots"),
|
|
SelectFilterOption("Ullu Originals", "/?s=ullu"),
|
|
SelectFilterOption("Kooku", "/director/kooku-originals"),
|
|
SelectFilterOption("Gupchup", "/director/gupchup-exclusive"),
|
|
SelectFilterOption("Feneomovies", "/director/feneomovies"),
|
|
SelectFilterOption("Cinemadosti", "/director/cinemadosti"),
|
|
SelectFilterOption("Primeflix", "/director/primeflix"),
|
|
SelectFilterOption("Gemplex", "/director/gemplex"),
|
|
SelectFilterOption("Rabbit", "/director/rabbit-original"),
|
|
SelectFilterOption("HotMasti", "/director/hotmasti-originals"),
|
|
SelectFilterOption("BoomMovies", "/director/boommovies-original"),
|
|
SelectFilterOption("CliffMovies", "/director/cliff-movies"),
|
|
SelectFilterOption("MastiPrime", "/director/masti-prime-originals"),
|
|
SelectFilterOption("Ek Night Show", "/director/ek-night-show"),
|
|
SelectFilterOption("Flixsksmovies", "/director/flixsksmovies"),
|
|
SelectFilterOption("Lootlo", "/director/lootlo-original"),
|
|
SelectFilterOption("Hootzy", "/director/hootzy-channel"),
|
|
SelectFilterOption("Balloons", "/director/balloons-originals"),
|
|
SelectFilterOption(
|
|
"Big Movie Zoo", "/director/big-movie-zoo-originals"),
|
|
SelectFilterOption("Bambooflix", "/director/bambooflix"),
|
|
SelectFilterOption("Piliflix", "/director/piliflix-originals"),
|
|
SelectFilterOption("11upmovies", "/director/11upmovies-originals"),
|
|
SelectFilterOption("Eightshots", "/director/eightshots-originals"),
|
|
SelectFilterOption(
|
|
"I-Entertainment", "/director/i-entertainment-exclusive"),
|
|
SelectFilterOption("Hotprime", "/director/hotprime-originals"),
|
|
SelectFilterOption("BananaPrime", "/director/banana-prime"),
|
|
SelectFilterOption("HotHitFilms", "/director/hothitfilms"),
|
|
SelectFilterOption("Chikooflix", "/director/chikooflix-originals"),
|
|
SelectFilterOption("Glamheart", "/?s=glamheart"),
|
|
SelectFilterOption("Worldprime", "/director/worldprime-originals"),
|
|
]),
|
|
];
|
|
}
|
|
}
|
|
|
|
YoMovies main() {
|
|
return YoMovies();
|
|
}
|