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:
BIN
dart/anime/src/id/nimegami/icon.png
Normal file
BIN
dart/anime/src/id/nimegami/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
182
dart/anime/src/id/nimegami/nimegami.dart
Normal file
182
dart/anime/src/id/nimegami/nimegami.dart
Normal file
@@ -0,0 +1,182 @@
|
||||
import 'package:mangayomi/bridge_lib.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
class NimeGami extends MProvider {
|
||||
NimeGami({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}/page/$page"))).body;
|
||||
List<MManga> animeList = [];
|
||||
final urls = xpath(res, '//div[@class="wrapper-2-a"]/article/a/@href');
|
||||
final names = xpath(res, '//div[@class="wrapper-2-a"]/article/a/@title');
|
||||
final images =
|
||||
xpath(res, '//div[@class="wrapper-2-a"]/article/a/div/img/@src');
|
||||
|
||||
for (var i = 0; i < names.length; i++) {
|
||||
MManga anime = MManga();
|
||||
anime.name = names[i];
|
||||
anime.imageUrl = images[i];
|
||||
anime.link = urls[i];
|
||||
animeList.add(anime);
|
||||
}
|
||||
return MPages(animeList, true);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<MPages> getLatestUpdates(int page) async {
|
||||
final res =
|
||||
(await client.get(Uri.parse("${source.baseUrl}/page/$page"))).body;
|
||||
List<MManga> animeList = [];
|
||||
final urls = xpath(res, '//div[@class="post-article"]/article/div/a/@href');
|
||||
final names =
|
||||
xpath(res, '//div[@class="post-article"]/article/div/a/@title');
|
||||
final images =
|
||||
xpath(res, '//div[@class="post-article"]/article/div/a/img/@src');
|
||||
|
||||
for (var i = 0; i < names.length; i++) {
|
||||
MManga anime = MManga();
|
||||
anime.name = names[i];
|
||||
anime.imageUrl = images[i];
|
||||
anime.link = urls[i];
|
||||
animeList.add(anime);
|
||||
}
|
||||
return MPages(animeList, true);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<MPages> search(String query, int page, FilterList filterList) async {
|
||||
final res = (await client.get(
|
||||
Uri.parse("${source.baseUrl}/page/$page/?s=$query&post_type=post")))
|
||||
.body;
|
||||
List<MManga> animeList = [];
|
||||
final urls = xpath(res, '//div[@class="archive-a"]/article/div/a/@href');
|
||||
final names = xpath(res, '//div[@class="archive-a"]/article/h2/a/@title');
|
||||
final images =
|
||||
xpath(res, '//div[@class="archive-a"]/article/div/a/img/@src');
|
||||
|
||||
for (var i = 0; i < names.length; i++) {
|
||||
MManga anime = MManga();
|
||||
anime.name = names[i];
|
||||
anime.imageUrl = images[i];
|
||||
anime.link = urls[i];
|
||||
animeList.add(anime);
|
||||
}
|
||||
return MPages(animeList, true);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<MManga> getDetail(String url) async {
|
||||
final res = (await client.get(Uri.parse(url))).body;
|
||||
MManga anime = MManga();
|
||||
final description = xpath(res, '//*[@id="Sinopsis"]/p/text()');
|
||||
if (description.isNotEmpty) {
|
||||
anime.description = description.first;
|
||||
}
|
||||
|
||||
final author = xpath(res, '//tbody/tr[5]/td[2]/text()');
|
||||
if (author.isNotEmpty) {
|
||||
anime.author = author.first;
|
||||
}
|
||||
anime.genre = xpath(res, '//tr/td[@class="info_a"]/a/text()');
|
||||
final epUrls = xpath(res, '//div[@class="list_eps_stream"]/li/@data')
|
||||
.reversed
|
||||
.toList();
|
||||
final epNums =
|
||||
xpath(res, '//div[@class="list_eps_stream"]/li/@id').reversed.toList();
|
||||
final names = xpath(res, '//div[@class="list_eps_stream"]/li/text()')
|
||||
.reversed
|
||||
.toList();
|
||||
List<MChapter>? episodesList = [];
|
||||
for (var i = 0; i < epUrls.length; i++) {
|
||||
MChapter episode = MChapter();
|
||||
episode.name = names[i];
|
||||
episode.url = json.encode({
|
||||
"episodeIndex": int.parse(substringAfterLast(epNums[i], '_')),
|
||||
'urls': json.decode(utf8.decode(base64Url.decode(epUrls[i])))
|
||||
});
|
||||
episodesList.add(episode);
|
||||
}
|
||||
anime.chapters = episodesList;
|
||||
return anime;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<MVideo>> getVideoList(String url) async {
|
||||
final resJson = json.decode(url);
|
||||
final urls = resJson["urls"];
|
||||
List<MVideo> videos = [];
|
||||
List<MVideo> a = [];
|
||||
for (var data in urls) {
|
||||
final quality = data["format"];
|
||||
for (var url in data["url"]) {
|
||||
a = await extractVideos(quality, url);
|
||||
videos.addAll(a);
|
||||
}
|
||||
}
|
||||
return videos;
|
||||
}
|
||||
|
||||
Future<List<MVideo>> extractVideos(String quality, String url) async {
|
||||
List<MVideo> videos = [];
|
||||
if (url.contains("video.nimegami.id")) {
|
||||
final realUrl = utf8.decode(
|
||||
base64Url.decode(substringBefore(substringAfter(url, "url="), "&")));
|
||||
final a = await extractHXFileVideos(realUrl, quality);
|
||||
videos.addAll(a);
|
||||
} else if (url.contains("berkasdrive") || url.contains("drive.nimegami")) {
|
||||
final res = (await client.get(Uri.parse(url))).body;
|
||||
final source = xpath(res, '//source/@src');
|
||||
if (source.isNotEmpty) {
|
||||
videos.add(toVideo(source.first, "Berkasdrive - $quality"));
|
||||
}
|
||||
} else if (url.contains("hxfile.co")) {
|
||||
final a = await extractHXFileVideos(url, quality);
|
||||
videos.addAll(a);
|
||||
}
|
||||
|
||||
return videos;
|
||||
}
|
||||
|
||||
Future<List<MVideo>> extractHXFileVideos(String url, String quality) async {
|
||||
if (!url.contains("embed-")) {
|
||||
url = url.replaceAll(".co/", ".co/embed-") + ".html";
|
||||
}
|
||||
final res = (await client.get(Uri.parse(url))).body;
|
||||
final script = xpath(res,
|
||||
'//script[contains(text(), "eval") and contains(text(), "p,a,c,k,e,d")]/text()');
|
||||
if (script.isNotEmpty) {
|
||||
final videoUrl = substringBefore(
|
||||
substringAfter(
|
||||
substringAfter(unpackJs(script.first), "sources:[", ""),
|
||||
"file\":\"",
|
||||
""),
|
||||
'"');
|
||||
if (videoUrl.isNotEmpty) {
|
||||
return [toVideo(videoUrl, "HXFile - $quality")];
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
MVideo toVideo(String videoUrl, String quality) {
|
||||
MVideo video = MVideo();
|
||||
video
|
||||
..url = videoUrl
|
||||
..originalUrl = videoUrl
|
||||
..quality = quality
|
||||
..subtitles = [];
|
||||
|
||||
return video;
|
||||
}
|
||||
}
|
||||
|
||||
NimeGami main(MSource source) {
|
||||
return NimeGami(source: source);
|
||||
}
|
||||
16
dart/anime/src/id/nimegami/source.dart
Normal file
16
dart/anime/src/id/nimegami/source.dart
Normal file
@@ -0,0 +1,16 @@
|
||||
import '../../../../../model/source.dart';
|
||||
|
||||
Source get nimegami => _nimegami;
|
||||
const _nimegamiVersion = "0.0.55";
|
||||
const _nimegamiCodeUrl =
|
||||
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/id/nimegami/nimegami.dart";
|
||||
Source _nimegami = Source(
|
||||
name: "NimeGami",
|
||||
baseUrl: "https://nimegami.id",
|
||||
lang: "id",
|
||||
typeSource: "single",
|
||||
iconUrl:
|
||||
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/id/nimegami/icon.png",
|
||||
sourceCodeUrl: _nimegamiCodeUrl,
|
||||
version: _nimegamiVersion,
|
||||
isManga: false);
|
||||
BIN
dart/anime/src/id/oploverz/icon.png
Normal file
BIN
dart/anime/src/id/oploverz/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
154
dart/anime/src/id/oploverz/oploverz.dart
Normal file
154
dart/anime/src/id/oploverz/oploverz.dart
Normal file
@@ -0,0 +1,154 @@
|
||||
import 'package:mangayomi/bridge_lib.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
class OploVerz extends MProvider {
|
||||
OploVerz({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}/anime-list/page/$page/?order=popular")))
|
||||
.body;
|
||||
return parseAnimeList(res);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<MPages> getLatestUpdates(int page) async {
|
||||
final res = (await client.get(
|
||||
Uri.parse("${source.baseUrl}/anime-list/page/$page/?order=latest")))
|
||||
.body;
|
||||
return parseAnimeList(res);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<MPages> search(String query, int page, FilterList filterList) async {
|
||||
final res = (await client.get(
|
||||
Uri.parse("${source.baseUrl}/anime-list/page/$page/?title=$query")))
|
||||
.body;
|
||||
return parseAnimeList(res);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<MManga> getDetail(String url) async {
|
||||
final statusList = [
|
||||
{"ongoing": 0, "completed": 1}
|
||||
];
|
||||
|
||||
final res = (await client.get(Uri.parse(url))).body;
|
||||
MManga anime = MManga();
|
||||
final status = xpath(res, '//*[@class="alternati"]/span[2]/text()');
|
||||
if (status.isNotEmpty) {
|
||||
anime.status = parseStatus(status.first, statusList);
|
||||
}
|
||||
anime.description = xpath(res, '//*[@class="desc"]/div/text()').first;
|
||||
|
||||
anime.genre = xpath(res, '//*[@class="genre-info"]/a/text()');
|
||||
final epUrls =
|
||||
xpath(res, '//div[@class="epsleft")]/span[@class="lchx"]/a/@href');
|
||||
final names =
|
||||
xpath(res, '//div[@class="epsleft")]/span[@class="lchx"]/a/text()');
|
||||
final dates =
|
||||
xpath(res, '//div[@class="epsleft")]/span[@class="date"]/text()');
|
||||
final dateUploads = parseDates(dates, "dd/MM/yyyy", "id");
|
||||
List<MChapter>? episodesList = [];
|
||||
for (var i = 0; i < epUrls.length; i++) {
|
||||
MChapter episode = MChapter();
|
||||
episode.name = names[i];
|
||||
episode.dateUpload = dateUploads[i];
|
||||
episode.url = epUrls[i];
|
||||
episodesList.add(episode);
|
||||
}
|
||||
|
||||
anime.chapters = episodesList;
|
||||
return anime;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<MVideo>> getVideoList(String url) async {
|
||||
final res = (await client.get(Uri.parse(url))).body;
|
||||
final dataPost = xpath(res,
|
||||
'//*[@id="server"]/ul/li/div[contains(@id,"player-option")]/@data-post')
|
||||
.first;
|
||||
final dataNume = xpath(res,
|
||||
'//*[@id="server"]/ul/li/div[contains(@id,"player-option")]/@data-nume')
|
||||
.first;
|
||||
final dataType = xpath(res,
|
||||
'//*[@id="server"]/ul/li/div[contains(@id,"player-option")]/@data-type')
|
||||
.first;
|
||||
|
||||
final ress = (await client.post(
|
||||
Uri.parse("${source.baseUrl}/wp-admin/admin-ajax.php"),
|
||||
headers: {
|
||||
"_": "_"
|
||||
},
|
||||
body: {
|
||||
"action": "player_ajax",
|
||||
"post": dataPost,
|
||||
"nume": dataNume,
|
||||
"type": dataType
|
||||
}))
|
||||
.body;
|
||||
|
||||
final playerLink =
|
||||
xpath(ress, '//iframe[@class="playeriframe"]/@src').first;
|
||||
final resPlayer = (await client.get(Uri.parse(playerLink))).body;
|
||||
var resJson = substringBefore(substringAfter(resPlayer, "= "), "<");
|
||||
var streams = json.decode(resJson)["streams"] as List<Map<String, dynamic>>;
|
||||
List<MVideo> videos = [];
|
||||
for (var stream in streams) {
|
||||
String videoUrl = stream["play_url"];
|
||||
final quality = getQuality(stream["format_id"]);
|
||||
|
||||
MVideo video = MVideo();
|
||||
video
|
||||
..url = videoUrl
|
||||
..originalUrl = videoUrl
|
||||
..quality = quality;
|
||||
videos.add(video);
|
||||
}
|
||||
|
||||
return videos;
|
||||
}
|
||||
|
||||
String getQuality(int formatId) {
|
||||
if (formatId == 18) {
|
||||
return "Google - 360p";
|
||||
} else if (formatId == 22) {
|
||||
return "Google - 720p";
|
||||
}
|
||||
return "Unknown Resolution";
|
||||
}
|
||||
|
||||
MPages parseAnimeList(String res) {
|
||||
List<MManga> animeList = [];
|
||||
final urls = xpath(res, '//div[@class="relat"]/article/div/div/a/@href');
|
||||
final names = xpath(res, '//div[@class="relat"]/article/div/div/a/@title');
|
||||
final images =
|
||||
xpath(res, '//div[@class="relat"]/article/div/div/a/div/img/@src');
|
||||
|
||||
for (var i = 0; i < names.length; i++) {
|
||||
MManga anime = MManga();
|
||||
anime.name = names[i];
|
||||
anime.imageUrl = images[i];
|
||||
anime.link = urls[i];
|
||||
animeList.add(anime);
|
||||
}
|
||||
final pages = xpath(res, '//div[@class="pagination"]/a/@href');
|
||||
final pageNumberCurrent = xpath(res,
|
||||
'//div[@class="pagination"]/span[@class="page-numbers current"]/text()');
|
||||
|
||||
bool hasNextPage = true;
|
||||
if (pageNumberCurrent.isNotEmpty && pages.isNotEmpty) {
|
||||
hasNextPage = !(pages.length == int.parse(pageNumberCurrent.first));
|
||||
}
|
||||
return MPages(animeList, hasNextPage);
|
||||
}
|
||||
}
|
||||
|
||||
OploVerz main(MSource source) {
|
||||
return OploVerz(source: source);
|
||||
}
|
||||
16
dart/anime/src/id/oploverz/source.dart
Normal file
16
dart/anime/src/id/oploverz/source.dart
Normal file
@@ -0,0 +1,16 @@
|
||||
import '../../../../../model/source.dart';
|
||||
|
||||
Source get oploverz => _oploverz;
|
||||
const _oploverzVersion = "0.0.5";
|
||||
const _oploverzCodeUrl =
|
||||
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/id/oploverz/oploverz.dart";
|
||||
Source _oploverz = Source(
|
||||
name: "Oploverz",
|
||||
baseUrl: "https://oploverz.gold",
|
||||
lang: "id",
|
||||
typeSource: "single",
|
||||
iconUrl:
|
||||
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/id/oploverz/icon.png",
|
||||
sourceCodeUrl: _oploverzCodeUrl,
|
||||
version: _oploverzVersion,
|
||||
isManga: false);
|
||||
BIN
dart/anime/src/id/otakudesu/icon.png
Normal file
BIN
dart/anime/src/id/otakudesu/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.3 KiB |
241
dart/anime/src/id/otakudesu/otakudesu.dart
Normal file
241
dart/anime/src/id/otakudesu/otakudesu.dart
Normal file
@@ -0,0 +1,241 @@
|
||||
import 'package:mangayomi/bridge_lib.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
class OtakuDesu extends MProvider {
|
||||
OtakuDesu({required this.source});
|
||||
|
||||
MSource source;
|
||||
|
||||
final Client client = Client(source);
|
||||
|
||||
@override
|
||||
String get baseUrl => getPreferenceValue(source.id, "overrideBaseUrl");
|
||||
|
||||
@override
|
||||
Future<MPages> getPopular(int page) async {
|
||||
final res =
|
||||
(await client.get(Uri.parse("$baseUrl/complete-anime/page/$page")))
|
||||
.body;
|
||||
return parseAnimeList(res);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<MPages> getLatestUpdates(int page) async {
|
||||
final res =
|
||||
(await client.get(Uri.parse("$baseUrl/ongoing-anime/page/$page"))).body;
|
||||
return parseAnimeList(res);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<MPages> search(String query, int page, FilterList filterList) async {
|
||||
final res =
|
||||
(await client.get(Uri.parse("$baseUrl/?s=$query&post_type=anime")))
|
||||
.body;
|
||||
List<MManga> animeList = [];
|
||||
final images = xpath(res, '//ul[@class="chivsrc"]/li/img/@src');
|
||||
final names = xpath(res, '//ul[@class="chivsrc"]/li/h2/a/text()');
|
||||
final urls = xpath(res, '//ul[@class="chivsrc"]/li/h2/a/@href');
|
||||
|
||||
for (var i = 0; i < names.length; i++) {
|
||||
MManga anime = MManga();
|
||||
anime.name = names[i];
|
||||
anime.imageUrl = images[i];
|
||||
anime.link = urls[i];
|
||||
animeList.add(anime);
|
||||
}
|
||||
return MPages(animeList, false);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<MManga> getDetail(String url) async {
|
||||
final statusList = [
|
||||
{"Ongoing": 0, "Completed": 1}
|
||||
];
|
||||
final res = (await client.get(Uri.parse(url))).body;
|
||||
MManga anime = MManga();
|
||||
final status = xpath(
|
||||
res, '//*[@class="infozingle"]/p[contains(text(), "Status")]/text()');
|
||||
if (status.isNotEmpty) {
|
||||
anime.status = parseStatus(status.first.split(':').last, statusList);
|
||||
}
|
||||
final description = xpath(res, '//*[@class="sinopc"]/text()');
|
||||
if (description.isNotEmpty) {
|
||||
anime.description = description.first;
|
||||
}
|
||||
|
||||
final genre = xpath(
|
||||
res, '//*[@class="infozingle"]/p[contains(text(), "Genre")]/text()');
|
||||
if (genre.isNotEmpty) {
|
||||
anime.genre = genre.first.split(':').last.split(',');
|
||||
}
|
||||
|
||||
final epUrls = xpath(res, '//div[@class="episodelist"]/ul/li/span/a/@href');
|
||||
final names = xpath(res, '//div[@class="episodelist"]/ul/li/span/a/text()');
|
||||
|
||||
final dates = xpath(
|
||||
res, '//div[@class="episodelist"]/ul/li/span[@class="zeebr"]/text()');
|
||||
final dateUploads = parseDates(dates, "d MMMM,yyyy", "id");
|
||||
List<MChapter>? episodesList = [];
|
||||
for (var i = 1; i < epUrls.length; i++) {
|
||||
MChapter episode = MChapter();
|
||||
episode.name = names[i];
|
||||
episode.dateUpload = dateUploads[i];
|
||||
episode.url = epUrls[i];
|
||||
episodesList.add(episode);
|
||||
}
|
||||
anime.chapters = episodesList;
|
||||
return anime;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<MVideo>> getVideoList(String url) async {
|
||||
List<MVideo> videos = [];
|
||||
final res = (await client.get(Uri.parse(url))).body;
|
||||
final script =
|
||||
xpath(res, '//script[contains(text(), "{action:")]/text()').first;
|
||||
final nonceAction =
|
||||
substringBefore(substringAfter(script, "{action:\""), '"');
|
||||
final action = substringBefore(substringAfter(script, "action:\""), '"');
|
||||
|
||||
final resNonceAction = (await client.post(
|
||||
Uri.parse("$baseUrl/wp-admin/admin-ajax.php"),
|
||||
headers: {"_": "_"},
|
||||
body: {"action": nonceAction}))
|
||||
.body;
|
||||
final nonce = substringBefore(substringAfter(resNonceAction, ":\""), '"');
|
||||
final mirrorstream =
|
||||
xpath(res, '//*[@class="mirrorstream"]/ul/li/a/@data-content');
|
||||
for (var stream in mirrorstream) {
|
||||
List<MVideo> a = [];
|
||||
final decodedData = json.decode(utf8.decode(base64Url.decode(stream)));
|
||||
final q = decodedData["q"];
|
||||
final id = decodedData["id"];
|
||||
final i = decodedData["i"];
|
||||
|
||||
final res = (await client
|
||||
.post(Uri.parse("$baseUrl/wp-admin/admin-ajax.php"), headers: {
|
||||
"_": "_"
|
||||
}, body: {
|
||||
"i": i,
|
||||
"id": id,
|
||||
"q": q,
|
||||
"nonce": nonce,
|
||||
"action": action
|
||||
}))
|
||||
.body;
|
||||
final html = utf8.decode(
|
||||
base64Url.decode(substringBefore(substringAfter(res, ":\""), '"')));
|
||||
String url = xpath(html, '//iframe/@src').first;
|
||||
if (url.contains("yourupload")) {
|
||||
final id = substringBefore(substringAfter(url, "id="), "&");
|
||||
url = "https://yourupload.com/embed/$id";
|
||||
a = await yourUploadExtractor(url, null, "YourUpload - $q", null);
|
||||
} else if (url.contains("filelions")) {
|
||||
a = await streamWishExtractor(url, "FileLions");
|
||||
} else if (url.contains("desustream")) {
|
||||
final response = (await Client().get(Uri.parse(url)));
|
||||
final res = response.body;
|
||||
final script =
|
||||
xpath(res, '//script[contains(text(), "sources")]/text()').first;
|
||||
final videoUrl = substringBefore(
|
||||
substringAfter(substringAfter(script, "sources:[{"), "file':'"),
|
||||
"'");
|
||||
if (videoUrl.endsWith(".mp4")) {
|
||||
MVideo video = MVideo();
|
||||
video
|
||||
..url = videoUrl
|
||||
..originalUrl = videoUrl
|
||||
..quality = "DesuStream - $q";
|
||||
videos.add(video);
|
||||
}
|
||||
} else if (url.contains("mp4upload")) {
|
||||
final res = (await client.get(Uri.parse(url))).body;
|
||||
final script =
|
||||
xpath(res, '//script[contains(text(), "player.src")]/text()').first;
|
||||
final videoUrl =
|
||||
substringBefore(substringAfter(script, "src: \""), '"');
|
||||
MVideo video = MVideo();
|
||||
video
|
||||
..url = videoUrl
|
||||
..originalUrl = videoUrl
|
||||
..quality = "Mp4upload - $q";
|
||||
videos.add(video);
|
||||
}
|
||||
videos.addAll(a);
|
||||
}
|
||||
|
||||
return sortVideos(videos);
|
||||
}
|
||||
|
||||
List<MVideo> sortVideos(List<MVideo> videos) {
|
||||
String quality = getPreferenceValue(source.id, "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;
|
||||
}
|
||||
|
||||
MPages parseAnimeList(String res) {
|
||||
List<MManga> animeList = [];
|
||||
final urls =
|
||||
xpath(res, '//div[@class="detpost"]/div[@class="thumb"]/a/@href');
|
||||
final names = xpath(res,
|
||||
'//div[@class="detpost"]/div[@class="thumb"]/a/div[@class="thumbz"]/h2/text()');
|
||||
final images = xpath(res,
|
||||
'//div[@class="detpost"]/div[@class="thumb"]/a/div[@class="thumbz"]/img/@src');
|
||||
|
||||
for (var i = 0; i < names.length; i++) {
|
||||
MManga anime = MManga();
|
||||
anime.name = names[i];
|
||||
anime.imageUrl = images[i];
|
||||
anime.link = urls[i];
|
||||
animeList.add(anime);
|
||||
}
|
||||
final pages = xpath(
|
||||
res, '//div[@class="pagenavix"]/a[@class="next page-numbers"]/@href');
|
||||
return MPages(animeList, pages.isNotEmpty);
|
||||
}
|
||||
|
||||
List<dynamic> getSourcePreferences() {
|
||||
return [
|
||||
EditTextPreference(
|
||||
key: "overrideBaseUrl",
|
||||
title: "Override BaseUrl",
|
||||
summary: "",
|
||||
value: "https://otakudesu.cloud",
|
||||
dialogTitle: "Override BaseUrl",
|
||||
dialogMessage: "",
|
||||
text: "https://otakudesu.cloud"),
|
||||
ListPreference(
|
||||
key: "preferred_quality",
|
||||
title: "Preferred quality",
|
||||
summary: "",
|
||||
valueIndex: 1,
|
||||
entries: ["1080p", "720p", "480p", "360p"],
|
||||
entryValues: ["1080", "720", "480", "360"])
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
OtakuDesu main(MSource source) {
|
||||
return OtakuDesu(source: source);
|
||||
}
|
||||
16
dart/anime/src/id/otakudesu/source.dart
Normal file
16
dart/anime/src/id/otakudesu/source.dart
Normal file
@@ -0,0 +1,16 @@
|
||||
import '../../../../../model/source.dart';
|
||||
|
||||
Source get otakudesu => _otakudesu;
|
||||
const _otakudesuVersion = "0.0.55";
|
||||
const _otakudesuCodeUrl =
|
||||
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/id/otakudesu/otakudesu.dart";
|
||||
Source _otakudesu = Source(
|
||||
name: "OtakuDesu",
|
||||
baseUrl: "https://otakudesu.cloud",
|
||||
lang: "id",
|
||||
typeSource: "single",
|
||||
iconUrl:
|
||||
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/$branchName/dart/anime/src/id/otakudesu/icon.png",
|
||||
sourceCodeUrl: _otakudesuCodeUrl,
|
||||
version: _otakudesuVersion,
|
||||
isManga: false);
|
||||
Reference in New Issue
Block a user