mirror of
https://github.com/kodjodevf/mangayomi-extensions.git
synced 2026-02-16 11:50:30 +00:00
New source UHDMovies (EN)
This commit is contained in:
@@ -8,6 +8,7 @@ import 'src/ar/okanime/source.dart';
|
|||||||
import 'src/en/aniwave/source.dart';
|
import 'src/en/aniwave/source.dart';
|
||||||
import 'src/en/gogoanime/source.dart';
|
import 'src/en/gogoanime/source.dart';
|
||||||
import 'src/en/kisskh/source.dart';
|
import 'src/en/kisskh/source.dart';
|
||||||
|
import 'src/en/uhdmovies/source.dart';
|
||||||
import 'src/fr/animesultra/source.dart';
|
import 'src/fr/animesultra/source.dart';
|
||||||
import 'src/fr/franime/source.dart';
|
import 'src/fr/franime/source.dart';
|
||||||
import 'src/fr/otakufr/source.dart';
|
import 'src/fr/otakufr/source.dart';
|
||||||
@@ -16,7 +17,6 @@ import 'src/id/oploverz/source.dart';
|
|||||||
import 'src/id/otakudesu/source.dart';
|
import 'src/id/otakudesu/source.dart';
|
||||||
import 'src/it/animesaturn/source.dart';
|
import 'src/it/animesaturn/source.dart';
|
||||||
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
List<Source> _sourcesList = [
|
List<Source> _sourcesList = [
|
||||||
gogoanimeSource,
|
gogoanimeSource,
|
||||||
@@ -31,7 +31,8 @@ void main() {
|
|||||||
oploverz,
|
oploverz,
|
||||||
aniwave,
|
aniwave,
|
||||||
...dopeflixSourcesList,
|
...dopeflixSourcesList,
|
||||||
animesaturn
|
animesaturn,
|
||||||
|
uhdmoviesSource
|
||||||
];
|
];
|
||||||
final List<Map<String, dynamic>> jsonList =
|
final List<Map<String, dynamic>> jsonList =
|
||||||
_sourcesList.map((source) => source.toJson()).toList();
|
_sourcesList.map((source) => source.toJson()).toList();
|
||||||
|
|||||||
BIN
anime/src/en/uhdmovies/icon.png
Normal file
BIN
anime/src/en/uhdmovies/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
16
anime/src/en/uhdmovies/source.dart
Normal file
16
anime/src/en/uhdmovies/source.dart
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import '../../../../model/source.dart';
|
||||||
|
|
||||||
|
Source get uhdmoviesSource => _uhdmoviesSource;
|
||||||
|
const _uhdmoviesVersion = "0.0.1";
|
||||||
|
const _uhdmoviesSourceCodeUrl =
|
||||||
|
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/en/uhdmovies/uhdmovies-v$_uhdmoviesVersion.dart";
|
||||||
|
Source _uhdmoviesSource = Source(
|
||||||
|
name: "uhdmovies",
|
||||||
|
baseUrl: "https://uhdmovies.zip",
|
||||||
|
lang: "en",
|
||||||
|
typeSource: "single",
|
||||||
|
iconUrl:
|
||||||
|
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/en/uhdmovies/icon.png",
|
||||||
|
sourceCodeUrl: _uhdmoviesSourceCodeUrl,
|
||||||
|
version: _uhdmoviesVersion,
|
||||||
|
isManga: false);
|
||||||
236
anime/src/en/uhdmovies/uhdmovies-v0.0.1.dart
Normal file
236
anime/src/en/uhdmovies/uhdmovies-v0.0.1.dart
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
import 'package:mangayomi/bridge_lib.dart';
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
class UHDMovies extends MProvider {
|
||||||
|
UHDMovies();
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get supportsLatest => false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<MPages> getPopular(MSource source, int page) async {
|
||||||
|
final data = {"url": "${preferenceBaseUrl(source.id)}/page/$page"};
|
||||||
|
final res = await http('GET', json.encode(data));
|
||||||
|
return animeFromElement(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 url =
|
||||||
|
'${preferenceBaseUrl(source.id)}/page/$page/?s=${query.replaceAll(" ", "+")}';
|
||||||
|
final data = {"url": url};
|
||||||
|
final res = await http('GET', json.encode(data));
|
||||||
|
return animeFromElement(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<MManga> getDetail(MSource source, String url) async {
|
||||||
|
url = Uri.parse(url).path;
|
||||||
|
final data = {"url": "${preferenceBaseUrl(source.id)}${url}"};
|
||||||
|
String res = await http('GET', json.encode(data));
|
||||||
|
MManga anime = MManga();
|
||||||
|
final description = xpath(res, '//pre/span/text()');
|
||||||
|
if (description.isNotEmpty) {
|
||||||
|
anime.description = description.first;
|
||||||
|
}
|
||||||
|
anime.status = MStatus.ongoing;
|
||||||
|
final episodesTitles = xpath(res,
|
||||||
|
'//*[contains(@style, "center") or contains(@class, "maxbutton")]/a[contains(@class, "maxbutton") or contains(@href, "?sid=")]/text()');
|
||||||
|
final episodesUrls = xpath(res,
|
||||||
|
'//*[contains(@style, "center") or contains(@class, "maxbutton")]/a[contains(@class, "maxbutton") or contains(@href, "?sid=")]/@href');
|
||||||
|
bool isSeries = false;
|
||||||
|
if (episodesTitles.first.contains("Episode") ||
|
||||||
|
episodesTitles.first.contains("Zip") ||
|
||||||
|
episodesTitles.first.contains("Pack")) {
|
||||||
|
isSeries = true;
|
||||||
|
}
|
||||||
|
List<MChapter>? episodesList = [];
|
||||||
|
if (!isSeries) {
|
||||||
|
final moviesTitles = xpath(res,
|
||||||
|
'//*[contains(@style, "center") or contains(@class, "maxbutton")]/parent::p//preceding-sibling::p[contains(@style, "center")]/text()');
|
||||||
|
List<String> titles = [];
|
||||||
|
for (var title in moviesTitles) {
|
||||||
|
if (title.isNotEmpty && !title.contains('Download')) {
|
||||||
|
titles.add(title.split('[').first.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var i = 0; i < titles.length; i++) {
|
||||||
|
final title = titles[i];
|
||||||
|
final url = episodesUrls[i];
|
||||||
|
MChapter ep = MChapter();
|
||||||
|
ep.name = title;
|
||||||
|
ep.url = url;
|
||||||
|
episodesList.add(ep);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
List<String> seasonTitles = [];
|
||||||
|
final episodeTitles = xpath(res,
|
||||||
|
'//*[contains(@style, "center") or contains(@class, "maxbutton")]/parent::p//preceding-sibling::p[contains(@style, "center") and not(text()^="Episode")]/text()');
|
||||||
|
List<String> titles = [];
|
||||||
|
for (var title in episodeTitles) {
|
||||||
|
if (title.isNotEmpty) {
|
||||||
|
titles.add(title.split('[').first.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int number = 0;
|
||||||
|
for (var i = 0; i < episodesTitles.length; i++) {
|
||||||
|
final episode = episodesTitles[i];
|
||||||
|
final episodeUrl = episodesUrls[i];
|
||||||
|
if (!episode.contains("Zip") || !episode.contains("Pack")) {
|
||||||
|
if (episode == "Episode 1" && seasonTitles.contains("Episode 1")) {
|
||||||
|
number++;
|
||||||
|
} else if (episode == "Episode 1") {
|
||||||
|
seasonTitles.add(episode);
|
||||||
|
}
|
||||||
|
final season =
|
||||||
|
RegExp(r'S(\d{2})').firstMatch(titles[number]).group(1);
|
||||||
|
final quality =
|
||||||
|
RegExp(r'\d{3,4}p').firstMatch(titles[number]).group(0);
|
||||||
|
MChapter ep = MChapter();
|
||||||
|
ep.name = "Season $season $episode $quality";
|
||||||
|
ep.url = episodeUrl;
|
||||||
|
episodesList.add(ep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
anime.chapters = episodesList.reversed.toList();
|
||||||
|
return anime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<MVideo>> getVideoList(MSource source, String url) async {
|
||||||
|
final res = await getMediaUrl(url);
|
||||||
|
return await extractVideos(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<dynamic> getSourcePreferences(MSource source) {
|
||||||
|
return [
|
||||||
|
EditTextPreference(
|
||||||
|
key: "pref_domain",
|
||||||
|
title: "Currently used domain",
|
||||||
|
summary: "",
|
||||||
|
value: "https://uhdmovies.zip",
|
||||||
|
dialogTitle: "Currently used domain",
|
||||||
|
dialogMessage: "",
|
||||||
|
text: "https://uhdmovies.zip"),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
String preferenceBaseUrl(int sourceId) {
|
||||||
|
return getPreferenceValue(sourceId, "pref_domain");
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<MVideo>> extractVideos(String url) async {
|
||||||
|
List<MVideo> videos = [];
|
||||||
|
for (int type = 1; type < 3; type++) {
|
||||||
|
url = url.replaceAll("/file/", "/wfile/") + "?type=$type";
|
||||||
|
final res = await http('GET', json.encode({"url": url}));
|
||||||
|
final links = xpath(res, '//div[@class="mb-4"]/a/@href');
|
||||||
|
for (int i = 0; i < links.length; i++) {
|
||||||
|
final link = links[i];
|
||||||
|
String decodedLink = link;
|
||||||
|
if (!link.contains("workers.dev")) {
|
||||||
|
decodedLink = utf8
|
||||||
|
.decode(base64Url.decode(substringAfter(link, "download?url=")));
|
||||||
|
}
|
||||||
|
MVideo video = MVideo();
|
||||||
|
video
|
||||||
|
..url = decodedLink
|
||||||
|
..originalUrl = decodedLink
|
||||||
|
..quality = "CF $type Worker ${i + 1}";
|
||||||
|
videos.add(video);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return videos;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> getMediaUrl(String url) async {
|
||||||
|
String res = "";
|
||||||
|
String host = "";
|
||||||
|
if (url.contains("?sid=")) {
|
||||||
|
final finalUrl = await redirectorBypasser(url);
|
||||||
|
host = Uri.parse(finalUrl).host;
|
||||||
|
res = await http('GET', json.encode({"url": finalUrl}));
|
||||||
|
} else if (url.contains("r?key=")) {
|
||||||
|
res = await http('GET', json.encode({"url": url}));
|
||||||
|
host = Uri.parse(url).host;
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
final path = substringBefore(substringAfter(res, "replace(\""), "\"");
|
||||||
|
if (path == "/404") return "";
|
||||||
|
return "https://$host$path";
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> redirectorBypasser(String url) async {
|
||||||
|
final res = await http('GET', json.encode({"url": url}));
|
||||||
|
String lastDoc = await recursiveDoc(url, res);
|
||||||
|
final js = xpath(lastDoc, '//script[contains(text(), "/?go=")]/text()');
|
||||||
|
if (js.isEmpty) return "";
|
||||||
|
String script = js.first;
|
||||||
|
String nextUrl =
|
||||||
|
substringBefore(substringAfter(script, "\"href\",\""), '"');
|
||||||
|
if (!nextUrl.contains("http")) return "";
|
||||||
|
String cookieName = substringAfter(nextUrl, "go=");
|
||||||
|
String cookieValue =
|
||||||
|
substringBefore(substringAfter(script, "'$cookieName', '"), "'");
|
||||||
|
final response = await http(
|
||||||
|
'GET',
|
||||||
|
json.encode({
|
||||||
|
"url": nextUrl,
|
||||||
|
"headers": {"referer": url, "Cookie": "$cookieName=$cookieValue"}
|
||||||
|
}));
|
||||||
|
final lastRes = querySelectorAll(response,
|
||||||
|
selector: "meta[http-equiv]",
|
||||||
|
typeElement: 3,
|
||||||
|
attributes: "content",
|
||||||
|
typeRegExp: 0)
|
||||||
|
.first;
|
||||||
|
return substringAfter(lastRes, "url=");
|
||||||
|
}
|
||||||
|
|
||||||
|
MPages animeFromElement(String res) {
|
||||||
|
List<MManga> animeList = [];
|
||||||
|
final urls = xpath(res, '//*[@class="entry-image"]/a/@href');
|
||||||
|
final names = xpath(res, '//*[@class="entry-image"]/a/@title');
|
||||||
|
final images = xpath(res, '//*[@class="entry-image"]/a/img/@src');
|
||||||
|
|
||||||
|
for (var i = 0; i < names.length; i++) {
|
||||||
|
MManga anime = MManga();
|
||||||
|
anime.name = names[i].replaceAll("Download", "");
|
||||||
|
anime.imageUrl = images[i];
|
||||||
|
anime.link = urls[i];
|
||||||
|
animeList.add(anime);
|
||||||
|
}
|
||||||
|
final nextPage = xpath(res, '//a[@class="next page-numbers"]/@href');
|
||||||
|
return MPages(animeList, nextPage.isNotEmpty);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> recursiveDoc(String url, String html) async {
|
||||||
|
final urlR = xpath(html, '//form[@id="landing"]/@action');
|
||||||
|
if (urlR.isEmpty) return html;
|
||||||
|
final name = xpath(html, '//input/@name').first;
|
||||||
|
final value = xpath(html, '//input/@value').first;
|
||||||
|
final body = {"$name": value};
|
||||||
|
final response = await http(
|
||||||
|
'POST',
|
||||||
|
json.encode({
|
||||||
|
"useFormBuilder": true,
|
||||||
|
"body": body,
|
||||||
|
"url": urlR.first,
|
||||||
|
"headers": {"referer": url}
|
||||||
|
}));
|
||||||
|
return recursiveDoc(url, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UHDMovies main() {
|
||||||
|
return UHDMovies();
|
||||||
|
}
|
||||||
@@ -6,11 +6,8 @@ class OtakuFr extends MProvider {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<MPages> getPopular(MSource source, int page) async {
|
Future<MPages> getPopular(MSource source, int page) async {
|
||||||
final data = {
|
final data = {"url": "${source.baseUrl}/en-cours/page/$page"};
|
||||||
"url": "${source.baseUrl}/toute-la-liste-affiches/page/$page/?q=."
|
|
||||||
};
|
|
||||||
final res = await http('GET', json.encode(data));
|
final res = await http('GET', json.encode(data));
|
||||||
|
|
||||||
List<MManga> animeList = [];
|
List<MManga> animeList = [];
|
||||||
final urls =
|
final urls =
|
||||||
xpath(res, '//*[@class="list"]/article/div/div/figure/a/@href');
|
xpath(res, '//*[@class="list"]/article/div/div/figure/a/@href');
|
||||||
@@ -285,7 +282,7 @@ class OtakuFr extends MProvider {
|
|||||||
return [
|
return [
|
||||||
ListPreference(
|
ListPreference(
|
||||||
key: "preferred_quality",
|
key: "preferred_quality",
|
||||||
title: "Preferred Quality",
|
title: "Qualité préférée",
|
||||||
summary: "",
|
summary: "",
|
||||||
valueIndex: 1,
|
valueIndex: 1,
|
||||||
entries: ["1080p", "720p", "480p", "360p"],
|
entries: ["1080p", "720p", "480p", "360p"],
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import '../../../../model/source.dart';
|
import '../../../../model/source.dart';
|
||||||
|
|
||||||
Source get otakufr => _otakufr;
|
Source get otakufr => _otakufr;
|
||||||
const otakufrVersion = "0.0.5";
|
const otakufrVersion = "0.0.55";
|
||||||
const otakufrCodeUrl =
|
const otakufrCodeUrl =
|
||||||
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/fr/otakufr/otakufr-v$otakufrVersion.dart";
|
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/fr/otakufr/otakufr-v$otakufrVersion.dart";
|
||||||
Source _otakufr = Source(
|
Source _otakufr = Source(
|
||||||
|
|||||||
Reference in New Issue
Block a user