#3 New Anime Extensions (Indonesia)

This commit is contained in:
kodjomoustapha
2023-11-09 18:31:51 +01:00
parent b8351a1739
commit bd66eb533f
10 changed files with 578 additions and 1 deletions

View File

@@ -9,6 +9,9 @@ import 'src/en/kisskh/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';
import 'src/id/nimegami/source.dart';
import 'src/id/oploverz/source.dart';
import 'src/id/otakudesu/source.dart';
void main() { void main() {
List<Source> _sourcesList = [ List<Source> _sourcesList = [
@@ -18,7 +21,10 @@ void main() {
animesultraSource, animesultraSource,
...zorothemeSourcesList, ...zorothemeSourcesList,
kisskhSource, kisskhSource,
okanimeSource okanimeSource,
otakudesu,
nimegami,
oploverz
]; ];
final List<Map<String, dynamic>> jsonList = final List<Map<String, dynamic>> jsonList =
_sourcesList.map((source) => source.toJson()).toList(); _sourcesList.map((source) => source.toJson()).toList();

View File

@@ -0,0 +1,179 @@
import 'package:mangayomi/bridge_lib.dart';
import 'dart:convert';
class NimeGami extends MProvider {
NimeGami();
@override
Future<MPages> getPopular(MSource source, int page) async {
final data = {"url": "${source.baseUrl}/page/$page"};
final res = await http('GET', json.encode(data));
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(MSource source, int page) async {
final data = {"url": "${source.baseUrl}/page/$page"};
final res = await http('GET', json.encode(data));
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(MSource source, String query, int page) async {
final data = {
"url": "${source.baseUrl}/page/$page/?s=$query&post_type=post"
};
final res = await http('GET', json.encode(data));
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(MSource source, String url) async {
final data = {"url": url};
final res = await http('GET', json.encode(data));
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(base64(epUrls[i], 0))
});
episodesList.add(episode);
}
anime.chapters = episodesList;
return anime;
}
@override
Future<List<MVideo>> getVideoList(MSource source, 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 = [];
List<MVideo> a = [];
if (url.contains("video.nimegami.id")) {
final realUrl =
base64(substringBefore(substringAfter(url, "url="), "&"), 0);
final a = await extractHXFileVideos(realUrl, quality);
videos.addAll(a);
} else if (url.contains("berkasdrive") || url.contains("drive.nimegami")) {
final res = await http('GET', json.encode({"url": url}));
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 http('GET', json.encode({"url": url}));
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(evalJs(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() {
return NimeGami();
}

View File

@@ -0,0 +1,17 @@
import '../../../../model/source.dart';
import '../../../../utils/utils.dart';
Source get nimegami => _nimegami;
const nimegamiVersion = "0.0.1";
const nimegamiCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/id/nimegami/nimegami-v$nimegamiVersion.dart";
Source _nimegami = Source(
name: "NimeGami",
baseUrl: "https://nimegami.id",
lang: "id",
typeSource: "single",
iconUrl: getIconUrl("nimegami", "id"),
sourceCodeUrl: nimegamiCodeUrl,
version: nimegamiVersion,
appMinVerReq: "0.0.7",
isManga: false);

View File

@@ -0,0 +1,157 @@
import 'package:mangayomi/bridge_lib.dart';
import 'dart:convert';
class OploVerz extends MProvider {
OploVerz();
@override
Future<MPages> getPopular(MSource source, int page) async {
final data = {
"url": "${source.baseUrl}/anime-list/page/$page/?order=popular"
};
final res = await http('GET', json.encode(data));
return parseAnimeList(res);
}
@override
Future<MPages> getLatestUpdates(MSource source, int page) async {
final data = {
"url": "${source.baseUrl}/anime-list/page/$page/?order=latest"
};
final res = await http('GET', json.encode(data));
return parseAnimeList(res);
}
@override
Future<MPages> search(MSource source, String query, int page) async {
final data = {
"url": "${source.baseUrl}/anime-list/page/$page/?title=$query"
};
final res = await http('GET', json.encode(data));
return parseAnimeList(res);
}
@override
Future<MManga> getDetail(MSource source, String url) async {
final statusList = [
{"ongoing": 0, "completed": 1}
];
final data = {"url": url};
final res = await http('GET', json.encode(data));
MManga anime = MManga();
final status = xpath(res, '//*[@class="alternati"]/span[2]/text()');
print(status);
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(MSource source, String url) async {
final res = await http('GET', json.encode({"url": url}));
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 body = {
"action": "player_ajax",
"post": dataPost,
"nume": dataNume,
"type": dataType
};
final ress = await http(
'POST',
json.encode({
"useFormBuilder": true,
"body": body,
"url": "${source.baseUrl}/wp-admin/admin-ajax.php"
}));
final playerLink =
xpath(ress, '//iframe[@class="playeriframe"]/@src').first;
print(playerLink);
final resPlayer = await http('GET', json.encode({"url": playerLink}));
var resJson = substringBefore(substringAfter(resPlayer, "= "), "<");
var streams = json.decode(resJson)["streams"] as List;
List<MVideo> videos = [];
for (var stream in streams) {
print(stream["play_url"]);
final videoUrl = stream["play_url"];
final quality = getQuality(stream["format_id"]);
MVideo video = MVideo();
video
..url = videoUrl
..originalUrl = videoUrl
..quality = quality
..subtitles = [];
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() {
return OploVerz();
}

View File

@@ -0,0 +1,17 @@
import '../../../../model/source.dart';
import '../../../../utils/utils.dart';
Source get oploverz => _oploverz;
const oploverzVersion = "0.0.1";
const oploverzCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/id/oploverz/oploverz-v$oploverzVersion.dart";
Source _oploverz = Source(
name: "Oploverz",
baseUrl: "https://oploverz.red",
lang: "id",
typeSource: "single",
iconUrl: getIconUrl("oploverz", "id"),
sourceCodeUrl: oploverzCodeUrl,
version: oploverzVersion,
appMinVerReq: "0.0.7",
isManga: false);

View File

@@ -0,0 +1,184 @@
import 'package:mangayomi/bridge_lib.dart';
import 'dart:convert';
class OtakuDesu extends MProvider {
OtakuDesu();
@override
Future<MPages> getPopular(MSource source, int page) async {
final data = {"url": "${source.baseUrl}/complete-anime/page/$page"};
final res = await http('GET', json.encode(data));
return parseAnimeList(res);
}
@override
Future<MPages> getLatestUpdates(MSource source, int page) async {
final data = {"url": "${source.baseUrl}/ongoing-anime/page/$page"};
final res = await http('GET', json.encode(data));
return parseAnimeList(res);
}
@override
Future<MPages> search(MSource source, String query, int page) async {
final data = {"url": "${source.baseUrl}/?s=$query&post_type=anime"};
final res = await http('GET', json.encode(data));
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(MSource source, String url) async {
final statusList = [
{"Ongoing": 0, "Completed": 1}
];
final data = {"url": url};
final res = await http('GET', json.encode(data));
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(MSource source, String url) async {
List<MVideo> videos = [];
final res = await http('GET', json.encode({"url": url}));
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 http(
'POST',
json.encode({
"useFormBuilder": true,
"body": {"action": nonceAction},
"url": "${source.baseUrl}/wp-admin/admin-ajax.php"
}));
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(base64(stream, 0));
final q = decodedData["q"];
final id = decodedData["id"];
final i = decodedData["i"];
final body = {"i": i, "id": id, "q": q, "nonce": nonce, "action": action};
final res = await http(
'POST',
json.encode({
"useFormBuilder": true,
"body": body,
"url": "${source.baseUrl}/wp-admin/admin-ajax.php"
}));
final html = base64(substringBefore(substringAfter(res, ":\""), '"'), 0);
final 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 res = await http('GET', json.encode({"url": url}));
final script =
xpath(res, '//script[contains(text(), "sources")]/text()').first;
final videoUrl = substringBefore(
substringAfter(substringAfter(script, "sources:[{"), "file':'"),
"'");
MVideo video = MVideo();
video
..url = videoUrl
..originalUrl = videoUrl
..quality = "DesuStream - $q"
..subtitles = [];
videos.add(video);
} else if (url.contains("mp4upload")) {
final res = await http('GET', json.encode({"url": url}));
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"
..subtitles = [];
videos.add(video);
}
videos.addAll(a);
}
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);
}
}
OtakuDesu main() {
return OtakuDesu();
}

View File

@@ -0,0 +1,17 @@
import '../../../../model/source.dart';
import '../../../../utils/utils.dart';
Source get otakudesu => _otakudesu;
const otakudesuVersion = "0.0.1";
const otakudesuCodeUrl =
"https://raw.githubusercontent.com/kodjodevf/mangayomi-extensions/main/anime/src/id/otakudesu/otakudesu-v$otakudesuVersion.dart";
Source _otakudesu = Source(
name: "OtakuDesu",
baseUrl: "https://otakudesu.cam",
lang: "id",
typeSource: "single",
iconUrl: getIconUrl("otakudesu", "id"),
sourceCodeUrl: otakudesuCodeUrl,
version: otakudesuVersion,
appMinVerReq: "0.0.7",
isManga: false);

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB