add latest updates mangas

This commit is contained in:
kodjomoustapha 2023-05-27 18:09:07 +01:00
parent 46707fd32b
commit bc47bf00f0
17 changed files with 487 additions and 342 deletions

View file

@ -1,4 +1,3 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:mangayomi/utils/lang.dart';

View file

@ -1,4 +1,3 @@
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
@ -7,7 +6,6 @@ import 'package:isar/isar.dart';
import 'package:mangayomi/main.dart';
import 'package:mangayomi/models/manga_type.dart';
import 'package:mangayomi/models/source.dart';
import 'package:mangayomi/utils/headers.dart';
import 'package:mangayomi/utils/lang.dart';
import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart';

View file

@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:mangayomi/models/manga_type.dart';
import 'package:mangayomi/services/get_latest_updates_manga.dart';
import 'package:mangayomi/services/get_manga_detail.dart';
import 'package:mangayomi/services/get_popular_manga.dart';
import 'package:mangayomi/services/search_manga.dart';
@ -54,7 +55,10 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
if (_selectedIndex == 2 && _isSearch && _query.isNotEmpty) {
_getManga = ref.watch(
searchMangaProvider(source: widget.mangaType.source!, query: _query));
} else {
} else if (_selectedIndex == 1 && !_isSearch && _query.isEmpty) {
_getManga = ref.watch(
getLatestUpdatesMangaProvider(source: widget.mangaType.source!, page: 1));
} else if (_selectedIndex == 0 && !_isSearch && _query.isEmpty) {
_getManga = ref.watch(
getPopularMangaProvider(source: widget.mangaType.source!, page: 1));
}

View file

@ -0,0 +1,85 @@
import 'dart:async';
import 'package:mangayomi/models/source.dart';
import 'package:mangayomi/sources/multisrc/heancms/heancms.dart';
import 'package:mangayomi/sources/multisrc/madara/src/madara.dart';
import 'package:mangayomi/sources/service.dart';
import 'package:mangayomi/sources/src/all/comick/src/comick.dart';
import 'package:mangayomi/sources/src/en/mangahere/src/mangahere.dart';
import 'package:mangayomi/sources/src/fr/japscan/src/japscan.dart';
import 'package:mangayomi/sources/src/fr/mangakawaii/src/mangakawaii.dart';
import 'package:mangayomi/sources/multisrc/mangathemesia/src/mangathemesia.dart';
import 'package:mangayomi/sources/multisrc/mmrcms/src/mmrcms.dart';
import 'package:mangayomi/sources/utils/utils.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'get_latest_updates_manga.g.dart';
@riverpod
Future<List<GetManga?>> getLatestUpdatesManga(GetLatestUpdatesMangaRef ref,
{required String source, required int page}) async {
List<GetManga?>? latestUpdatesManga;
source = source.toLowerCase();
/*********/
/*comick*/
/*******/
if (getMangaTypeSource(source) == TypeSource.comick) {
latestUpdatesManga =
await Comick().getLatestUpdatesManga(source: source, page: page, ref: ref);
}
/***************/
/*mangathemesia*/
/**************/
if (getMangaTypeSource(source) == TypeSource.mangathemesia) {
latestUpdatesManga = await MangaThemeSia()
.getLatestUpdatesManga(source: source, page: page, ref: ref);
}
/***********/
/*mangakawaii*/
/***********/
if (source == "mangakawaii") {
latestUpdatesManga = await MangaKawaii()
.getLatestUpdatesManga(source: source, page: page, ref: ref);
}
/***********/
/*mmrcms*/
/***********/
else if (getMangaTypeSource(source) == TypeSource.mmrcms) {
latestUpdatesManga =
await Mmrcms().getLatestUpdatesManga(source: source, page: page, ref: ref);
}
/***********/
/*mangahere*/
/***********/
else if (source == "mangahere") {
latestUpdatesManga =
await Mangahere().getLatestUpdatesManga(source: source, page: page, ref: ref);
}
/***********/
/*japscan*/
/***********/
else if (source == "japscan") {
latestUpdatesManga =
await Japscan().getLatestUpdatesManga(source: source, page: page, ref: ref);
}
/***********/
/*heancms*/
/***********/
else if (getMangaTypeSource(source) == TypeSource.heancms) {
latestUpdatesManga =
await HeanCms().getLatestUpdatesManga(source: source, page: page, ref: ref);
}
/***********/
/*madara*/
/***********/
else if (getMangaTypeSource(source) == TypeSource.madara) {
latestUpdatesManga =
await Madara().getLatestUpdatesManga(source: source, page: page, ref: ref);
}
return latestUpdatesManga!;
}

View file

@ -0,0 +1,124 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'get_latest_updates_manga.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
String _$getLatestUpdatesMangaHash() =>
r'2f6c7714feca588ada6c6dd98ad62849042e9bae';
/// Copied from Dart SDK
class _SystemHash {
_SystemHash._();
static int combine(int hash, int value) {
// ignore: parameter_assignments
hash = 0x1fffffff & (hash + value);
// ignore: parameter_assignments
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
return hash ^ (hash >> 6);
}
static int finish(int hash) {
// ignore: parameter_assignments
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
// ignore: parameter_assignments
hash = hash ^ (hash >> 11);
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
}
}
typedef GetLatestUpdatesMangaRef
= AutoDisposeFutureProviderRef<List<GetManga?>>;
/// See also [getLatestUpdatesManga].
@ProviderFor(getLatestUpdatesManga)
const getLatestUpdatesMangaProvider = GetLatestUpdatesMangaFamily();
/// See also [getLatestUpdatesManga].
class GetLatestUpdatesMangaFamily extends Family<AsyncValue<List<GetManga?>>> {
/// See also [getLatestUpdatesManga].
const GetLatestUpdatesMangaFamily();
/// See also [getLatestUpdatesManga].
GetLatestUpdatesMangaProvider call({
required String source,
required int page,
}) {
return GetLatestUpdatesMangaProvider(
source: source,
page: page,
);
}
@override
GetLatestUpdatesMangaProvider getProviderOverride(
covariant GetLatestUpdatesMangaProvider provider,
) {
return call(
source: provider.source,
page: provider.page,
);
}
static const Iterable<ProviderOrFamily>? _dependencies = null;
@override
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
@override
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
_allTransitiveDependencies;
@override
String? get name => r'getLatestUpdatesMangaProvider';
}
/// See also [getLatestUpdatesManga].
class GetLatestUpdatesMangaProvider
extends AutoDisposeFutureProvider<List<GetManga?>> {
/// See also [getLatestUpdatesManga].
GetLatestUpdatesMangaProvider({
required this.source,
required this.page,
}) : super.internal(
(ref) => getLatestUpdatesManga(
ref,
source: source,
page: page,
),
from: getLatestUpdatesMangaProvider,
name: r'getLatestUpdatesMangaProvider',
debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product')
? null
: _$getLatestUpdatesMangaHash,
dependencies: GetLatestUpdatesMangaFamily._dependencies,
allTransitiveDependencies:
GetLatestUpdatesMangaFamily._allTransitiveDependencies,
);
final String source;
final int page;
@override
bool operator ==(Object other) {
return other is GetLatestUpdatesMangaProvider &&
other.source == source &&
other.page == page;
}
@override
int get hashCode {
var hash = _SystemHash.combine(0, runtimeType.hashCode);
hash = _SystemHash.combine(hash, source.hashCode);
hash = _SystemHash.combine(hash, page.hashCode);
return _SystemHash.finish(hash);
}
}
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions

View file

@ -182,4 +182,52 @@ class HeanCms extends MangaYomiServices {
}
return mangaRes();
}
@override
Future<List<GetManga?>> getLatestUpdatesManga(
{required String source,
required int page,
required AutoDisposeFutureProviderRef ref}) async {
var request = http.Request(
'POST', Uri.parse('${getMangaAPIUrl(source)}series/querysearch'));
request.body = json.encode({
"page": page,
"order": "desc",
"order_by": "latest",
"series_status": "Ongoing",
"series_type": "Comic"
});
request.headers.addAll(_headers(source));
http.StreamedResponse response = await request.send();
final res = await response.stream.bytesToString();
List<Data>? data;
if (res.startsWith("{")) {
var popularManga = jsonDecode(res) as Map<String, dynamic>;
var popularMangaList = HeanCmsSearchModel.fromJson(popularManga);
data = popularMangaList.data!;
} else {
var popularManga = jsonDecode(res) as List;
data = popularManga.map((e) => Data.fromJson(e)).toList();
}
for (var a in data) {
final status = (switch (a.status) {
"Ongoing" => Status.ongoing,
"Hiatus" => Status.onHiatus,
"Dropped" => Status.canceled,
"Completed" => Status.completed,
"Finished" => Status.completed,
_ => Status.unknown,
});
statusList.add(status);
image.add(a.thumbnail!.startsWith("https://")
? a.thumbnail
: "${getMangaAPIUrl(source)}cover/${a.thumbnail}");
name.add(a.title);
url.add("/series/${a.seriesSlug!.replaceAll(timeStampRegex, '')}");
}
return mangaRes();
}
}

View file

@ -179,7 +179,6 @@ class Madara extends MangaYomiServices {
.attrs) {
chapterUrl.add(url!);
}
log(chapterUrl.toString());
for (var title in xpath
.query("//*[@id='manga-chapters-holder']/div[2]/div/ul/li/a/text()")
.attrs) {
@ -239,12 +238,8 @@ class Madara extends MangaYomiServices {
}
final xpath = xpathSelector(html!);
name = xpath.query('//*[@id^="manga-item"]/a/@title').attrs;
// log(name.toString());
url = xpath.query('//*[@class^="post-title"]/h3/a/@href').attrs;
// log(url.toString());
image = xpath.query('//*[@id^="manga-item"]/a/img/@data-src=').attrs;
// log(image.toString());
return mangaRes();
}
@ -259,14 +254,29 @@ class Madara extends MangaYomiServices {
source: source,
resDom: false)
.future) as String?;
log(html!);
final xpath = xpathSelector(html);
final xpath = xpathSelector(html!);
name = xpath.query('//*[@class^="post-title"]/h3/a/text()').attrs;
log(name.toString());
url = xpath.query('//*[@class^="post-title"]/h3/a/@href').attrs;
log(url.toString());
image = name;
return mangaRes();
}
@override
Future<List<GetManga?>> getLatestUpdatesManga(
{required String source,
required int page,
required AutoDisposeFutureProviderRef ref}) async {
String? html;
html = await ref.watch(httpGetProvider(
url:
'${getMangaBaseUrl(source)}/manga/page/$page/?m_orderby=latest',
source: source,
resDom: false)
.future) as String?;
final xpath = xpathSelector(html!);
name = xpath.query('//*[@id^="manga-item"]/a/@title').attrs;
url = xpath.query('//*[@class^="post-title"]/h3/a/@href').attrs;
image = xpath.query('//*[@id^="manga-item"]/a/img/@data-src=').attrs;
return mangaRes();
}
}

View file

@ -1,295 +0,0 @@
// import 'dart:developer';
// import 'dart:io';
// import 'package:desktop_webview_window/desktop_webview_window.dart';
// import 'package:flutter/material.dart';
// import 'package:flutter_inappwebview/flutter_inappwebview.dart';
// import 'package:flutter_riverpod/flutter_riverpod.dart';
// import 'package:html/dom.dart';
// import 'package:html/parser.dart';
// import 'package:mangayomi/models/chapter.dart';
// import 'package:mangayomi/modules/webview/webview.dart';
// import 'package:mangayomi/services/http_service/http_service.dart';
// import 'package:mangayomi/sources/service.dart';
// import 'package:mangayomi/sources/utils/utils.dart';
// import 'package:mangayomi/utils/constant.dart';
// import 'package:mangayomi/utils/reg_exp_matcher.dart';
// // import 'package:mangayomi/utils/xpath_selector.dart';
// class Madara extends MangaYomiServices {
// @override
// Future<List<String>> getChapterUrl(
// {required Chapter chapter,
// required AutoDisposeFutureProviderRef ref}) async {
// final dom = await await ref.watch(httpGetProvider(
// useUserAgent: true,
// url: chapter.url!,
// source: chapter.manga.value!.source!.toLowerCase(),
// resDom: true)
// .future) as Document?;
// final res = dom!.querySelector(
// "div.page-break, li.blocks-gallery-item, .reading-content, .text-left img");
// final imgs = res!
// .querySelectorAll('img')
// .map((i) => regSrcMatcher(i.outerHtml).trim().trimLeft().trimRight())
// .toList();
// if (imgs.isNotEmpty && imgs.length == 1) {
// final pagesNumber = dom
// .querySelector("#single-pager")!
// .querySelectorAll("option")
// .map((e) => e.outerHtml)
// .toList();
// for (var i = 0; i < pagesNumber.length; i++) {
// if (i.toString().length == 1) {
// pageUrls.add(
// imgs.first.replaceAll("01", '0${int.parse(i.toString()) + 1}'));
// } else if (i.toString().length == 2) {
// pageUrls.add(
// imgs.first.replaceAll("01", '${int.parse(i.toString()) + 1}'));
// } else if (i.toString().length == 3) {
// pageUrls.add(
// imgs.first.replaceAll("01", '${int.parse(i.toString()) + 1}'));
// }
// }
// } else {
// pageUrls = imgs;
// }
// log(pageUrls.toString());
// return pageUrls;
// }
// @override
// Future<GetManga?> getMangaDetail(
// {required GetManga manga,
// required String lang,
// required String source,
// required AutoDisposeFutureProviderRef ref}) async {
// final dom = await ref.watch(
// httpGetProvider(url: manga.url!, source: source, resDom: true)
// .future) as Document?;
// author = dom!
// .querySelectorAll("div.author-content > a")
// .map((e) => e.text)
// .toList()
// .join(', ');
// description = dom
// .querySelectorAll(
// "div.description-summary div.summary__content, div.summary_content div.post-content_item > h5 + div, div.summary_content div.manga-excerpt, div.sinopsis div.contenedor")
// .map((e) => e.text)
// .toList()
// .first;
// status = dom
// .querySelectorAll("div.summary-content")
// .map((e) => e.text.trim().trimLeft().trimRight())
// .toList()
// .last;
// manga.imageUrl = dom
// .querySelectorAll("div.summary_image img")
// .map((e) => regSrcMatcher(e.outerHtml))
// .toList()
// .first;
// genre = dom
// .querySelectorAll("div.genres-content a")
// .map((e) => e.text)
// .toList();
// bool isOk = false;
// String? html;
// if (Platform.isWindows || Platform.isLinux) {
// final webview = await WebviewWindow.create(
// configuration: CreateConfiguration(
// windowHeight: 500,
// windowWidth: 500,
// userDataFolderWindows: await getWebViewPath(),
// ),
// );
// webview
// ..setBrightness(Brightness.dark)
// ..setApplicationNameForUserAgent(defaultUserAgent)
// ..launch(manga.url!);
// await Future.doWhile(() async {
// await Future.delayed(const Duration(seconds: 10));
// html = await decodeHtml(webview);
// if (parse(html!)
// .querySelector("div[id^=manga-chapters-holder]")!
// .querySelectorAll("li.wp-manga-chapter")
// .isEmpty) {
// html = await decodeHtml(webview);
// return true;
// }
// return false;
// });
// html = await decodeHtml(webview);
// isOk = true;
// await Future.doWhile(() async {
// await Future.delayed(const Duration(seconds: 1));
// if (isOk == true) {
// return false;
// }
// return true;
// });
// html = await decodeHtml(webview);
// webview.close();
// } else {
// HeadlessInAppWebView? headlessWebViewJapScan;
// headlessWebViewJapScan = HeadlessInAppWebView(
// onLoadStop: (controller, u) async {
// html = await controller.evaluateJavascript(
// source:
// "window.document.getElementsByTagName('html')[0].outerHTML;");
// await Future.doWhile(() async {
// html = await controller.evaluateJavascript(
// source:
// "window.document.getElementsByTagName('html')[0].outerHTML;");
// if (parse(html!)
// .querySelector("div[id^=manga-chapters-holder]")!
// .querySelectorAll("li.wp-manga-chapter")
// .isEmpty) {
// html = await controller.evaluateJavascript(
// source:
// "window.document.getElementsByTagName('html')[0].outerHTML;");
// return true;
// }
// return false;
// });
// html = await controller.evaluateJavascript(
// source:
// "window.document.getElementsByTagName('html')[0].outerHTML;");
// isOk = true;
// headlessWebViewJapScan!.dispose();
// },
// initialUrlRequest: URLRequest(
// url: WebUri.uri(Uri.parse(manga.url!)),
// ),
// );
// headlessWebViewJapScan.run();
// await Future.doWhile(() async {
// await Future.delayed(const Duration(seconds: 1));
// if (isOk == true) {
// return false;
// }
// return true;
// });
// }
// // final xpath = xpathSelector(html!);
// // // log(parse(html!)
// // // .querySelector("div[id^=manga-chapters-holder]")!
// // // .querySelectorAll("li.wp-manga-chapter")
// // // .map((e) => e.text)
// // // .toList()
// // // .toString());
// // for (var url in xpath
// // .query("//*[@id='manga-chapters-holder']/div[2]/div/ul/li/a/@href")
// // .attrs) {
// // chapterUrl.add(url!);
// // }
// chapterUrl = parse(html!)
// .querySelector("div[id^=manga-chapters-holder]")!
// .querySelectorAll("li.wp-manga-chapter")
// .map((e) => regHrefMatcher(e.outerHtml))
// .toList();
// // for (var title in xpath
// // .query("//*[@id='manga-chapters-holder']/div[2]/div/ul/li/a/text()")
// // .attrs) {
// // chapterTitle.add(title!.trim().trimLeft().trimRight());
// // }
// // log(chapterUrl.toString());
// chapterTitle = parse(html!)
// .querySelector("div[id^=manga-chapters-holder]")!
// .querySelectorAll("li.wp-manga-chapter a")
// .map((e) => e.text.trim().trimLeft().trimRight())
// .toList();
// // log(chapterTitle.toString());
// final dateF = parse(html!)
// .querySelector("div[id^=manga-chapters-holder]")!
// .querySelectorAll("li.wp-manga-chapter span")
// .map((e) => e.text.trim().trimLeft().trimRight())
// .toList();
// log(dateF.toString());
// // xpath
// // .query(
// // "//*[@id='manga-chapters-holder']/div[2]/div/ul/li/span/i/text()")
// // .attrs;
// if (dateF.length == chapterUrl.length) {
// for (var date in dateF) {
// chapterDate.add(parseDate(date, source));
// }
// } else if (dateF.length < chapterUrl.length) {
// final length = chapterUrl.length - dateF.length;
// for (var i = 0; i < length; i++) {
// chapterDate.add(DateTime.now().millisecondsSinceEpoch.toString());
// }
// for (var date in dateF) {
// chapterDate.add(parseDate(date!, source));
// }
// }
// return mangadetailRes(manga: manga, source: source);
// }
// @override
// Future<List<GetManga?>> getPopularManga(
// {required String source,
// required int page,
// required AutoDisposeFutureProviderRef ref}) async {
// String? html;
// html = await ref.watch(httpGetProvider(
// url: '${getMangaBaseUrl(source)}/manga/page/$page/?m_orderby=views',
// source: source,
// resDom: false)
// .future) as String?;
// if (parse(html!)
// .querySelectorAll('div.post-title a')
// .map((e) => e.text)
// .toList()
// .isEmpty) {
// html = await ref.watch(httpGetProvider(
// url:
// '${getMangaBaseUrl(source)}/manga/page/$page/?m_orderby=trending',
// source: source,
// resDom: false)
// .future) as String?;
// if (parse(html!)
// .querySelectorAll('div.post-title a')
// .map((e) => e.text)
// .toList()
// .isEmpty) {
// html = await ref.watch(httpGetProvider(
// url: getMangaBaseUrl(source), source: source, resDom: false)
// .future) as String?;
// }
// }
// final dom = parse(html!);
// name = dom.querySelectorAll('div.post-title a').map((e) => e.text).toList();
// image = name;
// url = dom
// .querySelectorAll('div.post-title a')
// .map((e) => regHrefMatcher(e.outerHtml))
// .toList();
// return mangaRes();
// }
// @override
// Future<List<GetManga?>> searchManga(
// {required String source,
// required String query,
// required AutoDisposeFutureProviderRef ref}) async {
// final html = await ref.watch(httpGetProvider(
// url: '${getMangaBaseUrl(source)}/?s=$query&post_type=wp-manga',
// source: source,
// resDom: false)
// .future) as String?;
// final dom = parse(html!);
// name = dom.querySelectorAll('div.post-title a').map((e) => e.text).toList();
// image = name;
// url = dom
// .querySelectorAll('div.post-title a')
// .map((e) => regHrefMatcher(e.outerHtml))
// .toList();
// return mangaRes();
// }
// }

View file

@ -277,6 +277,56 @@ class MangaThemeSia extends MangaYomiServices {
}
return pageUrls;
}
@override
Future<List<GetManga?>> getLatestUpdatesManga(
{required String source,
required int page,
required AutoDisposeFutureProviderRef ref}) async {
source = source.toLowerCase();
final dom = await ref.watch(httpGetProvider(
useUserAgent: true,
url:
'${getMangaBaseUrl(source)}/manga/?title=&page=$page&order=update',
source: source,
resDom: true)
.future) as Document?;
if (dom!
.querySelectorAll(
'.utao .uta .imgu, .listupd .bs .bsx, .listo .bs .bsx')
.isNotEmpty) {
url = dom
.querySelectorAll(
'.utao .uta .imgu, .listupd .bs .bsx, .listo .bs .bsx')
.map((e) {
RegExp exp = RegExp(r'href="([^"]+)"');
Iterable<Match> matches = exp.allMatches(e.innerHtml);
String? firstMatch = matches.first.group(1);
return firstMatch;
}).toList();
image = dom
.querySelectorAll(
'.utao .uta .imgu, .listupd .bs .bsx, .listo .bs .bsx')
.map((e) {
RegExp exp = RegExp(r'src="([^"]+)"');
Iterable<Match> matches = exp.allMatches(e.innerHtml);
String? firstMatch = matches.first.group(1);
return firstMatch;
}).toList();
name = dom
.querySelectorAll(
'.utao .uta .imgu, .listupd .bs .bsx, .listo .bs .bsx ')
.map((e) {
RegExp exp = RegExp(r'title="([^"]+)"');
Iterable<Match> matches = exp.allMatches(e.innerHtml);
String? firstMatch = matches.first.group(1);
return firstMatch;
}).toList();
}
return mangaRes();
}
}
mangathemesiaStatusParser(String status) {

View file

@ -1,4 +1,5 @@
import 'dart:convert';
import 'dart:developer';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:html/dom.dart';
@ -193,4 +194,28 @@ class Mmrcms extends MangaYomiServices {
}
return pageUrls;
}
@override
Future<List<GetManga?>> getLatestUpdatesManga(
{required String source,
required int page,
required AutoDisposeFutureProviderRef ref}) async {
final dom = await ref.watch(httpGetProvider(
url: '${getMangaBaseUrl(source)}/latest-release?page=$page',
source: source,
resDom: true)
.future) as Document?;
final urlElement = dom!.querySelectorAll("div.mangalist div.manga-item");
for (var e in urlElement) {
RegExp exp = RegExp(r'href="([^"]+)"');
Iterable<Match> matches = exp.allMatches(e.querySelector("a")!.outerHtml);
String? firstMatch = matches.first.group(1);
url.add(firstMatch);
name.add(e.querySelector("a")!.text);
image.add(
"${getMangaBaseUrl(source)}/uploads/manga/${firstMatch!.split('/').last}/cover/cover_250x350.jpg");
}
return mangaRes();
}
}

View file

@ -67,6 +67,10 @@ abstract class MangaYomiServices {
{required String source,
required int page,
required AutoDisposeFutureProviderRef ref});
Future<List<GetManga?>> getLatestUpdatesManga(
{required String source,
required int page,
required AutoDisposeFutureProviderRef ref});
Future<GetManga?> getMangaDetail(
{required GetManga manga,
required String lang,

View file

@ -3,14 +3,13 @@ import 'package:mangayomi/sources/multisrc/heancms/heancms_source_list.dart';
import 'package:mangayomi/sources/src/all/comick/comick_source_list.dart';
import 'package:mangayomi/sources/src/en/mangahere/mangahere_source.dart';
import 'package:mangayomi/sources/src/fr/japscan/japscan_source.dart';
import 'package:mangayomi/sources/src/fr/mangakawaii/mangakawaii_source.dart';
import 'package:mangayomi/sources/multisrc/mangathemesia/mangathemesia_source_list.dart';
import 'package:mangayomi/sources/multisrc/mmrcms/mmrcms_source_list.dart';
import 'package:mangayomi/sources/multisrc/madara/madara_source_list.dart';
List<Source> get sourcesList => _sourcesList;
List<Source> _sourcesList = [
mangahereSource,
mangakawaiiSource,
// mangakawaiiSource,
...mangathemesiaSourcesList,
...comickSourcesList,
...mmrcmsSourcesList,

View file

@ -1,7 +1,6 @@
import 'dart:convert';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:mangayomi/models/chapter.dart';
import 'package:mangayomi/models/manga.dart';
import 'package:mangayomi/sources/src/all/comick/src/model/chapter_page_comick.dart';
import 'package:mangayomi/sources/src/all/comick/src/model/manga_chapter_detail.dart';
import 'package:mangayomi/sources/src/all/comick/src/model/manga_detail_comick.dart';
@ -11,8 +10,6 @@ import 'package:mangayomi/services/http_service/http_service.dart';
import 'package:mangayomi/sources/service.dart';
import 'package:mangayomi/sources/src/all/comick/src/utils/utils.dart';
import 'package:mangayomi/sources/utils/utils.dart';
import 'package:http/http.dart' as http;
import 'package:mangayomi/utils/headers.dart';
class Comick extends MangaYomiServices {
@override
@ -146,12 +143,37 @@ class Comick extends MangaYomiServices {
Future<String> paginatedChapterListRequest(AutoDisposeFutureProviderRef ref,
String mangaUrl, int page, String source, String lang) async {
final url = Uri.parse(
"${getMangaAPIUrl(source)}$mangaUrl/chapters?${lang != "all" ? 'lang=$lang' : ''}&tachiyomi=true&page=$page");
var request = http.Request('GET', url);
request.headers.addAll(ref.watch(headersProvider(source: source)));
http.StreamedResponse response = await request.send();
final response = await ref.watch(httpGetProvider(
url:
"${getMangaAPIUrl(source)}$mangaUrl/chapters?${lang != "all" ? 'lang=$lang' : ''}&tachiyomi=true&page=$page",
source: source,
resDom: false)
.future) as String?;
return response!;
}
return response.stream.bytesToString();
@override
Future<List<GetManga?>> getLatestUpdatesManga(
{required String source,
required int page,
required AutoDisposeFutureProviderRef ref}) async {
source = source.toLowerCase();
final response = await ref.watch(httpGetProvider(
url:
'${getMangaAPIUrl(source)}/v1.0/search?sort=uploaded&page=$page&tachiyomi=true',
source: source,
resDom: false)
.future) as String?;
var popularManga = jsonDecode(response!) as List;
var popularMangaList =
popularManga.map((e) => PopularMangaModelComick.fromJson(e)).toList();
for (var popular in popularMangaList) {
url.add("/comic/${popular.hid}#");
name.add(popular.title);
image.add(popular.coverUrl);
}
return mangaRes();
}
}

View file

@ -8,7 +8,6 @@ Source _mangahereSource = Source(
lang: "en",
typeSource: TypeSource.single,
logoUrl: 'http://static.mangahere.cc/v20210106/mangahere/images/logo.png',
isFullData: true,
dateFormat: "MMM dd,yyyy",
dateFormatLocale: "en",
);

View file

@ -18,7 +18,7 @@ class Mangahere extends MangaYomiServices {
required String source,
required AutoDisposeFutureProviderRef ref}) async {
final dom = await ref.watch(httpGetProvider(
url: "http://www.mangahere.cc${manga.url}",
url: "${getMangaBaseUrl(source)}/${manga.url}",
source: source,
resDom: true)
.future) as Document?;
@ -120,32 +120,26 @@ class Mangahere extends MangaYomiServices {
required int page,
required AutoDisposeFutureProviderRef ref}) async {
final dom = await ref.watch(httpGetProvider(
url: 'https://www.mangahere.cc/ranking/',
url: '${getMangaBaseUrl(source)}/directory/$page.htm',
source: source,
resDom: true)
.future) as Document?;
if (dom!
.querySelectorAll(
'body > div.container.weekrank.ranking > div > div > ul > li > a')
.isNotEmpty) {
if (dom!.querySelectorAll('.manga-list-1-list li').isNotEmpty) {
url = dom
.querySelectorAll(
'body > div.container.weekrank.ranking > div > div > ul > li > a ')
.querySelectorAll('.manga-list-1-list li > a ')
.where((e) => e.attributes.containsKey('href'))
.map((e) => e.attributes['href'])
.toList();
image = dom
.querySelectorAll(
' body > div.container.weekrank.ranking > div > div > ul > li > a > img')
.querySelectorAll('.manga-list-1-list li > a > img')
.where((e) => e.attributes.containsKey('src'))
.where((e) => e.attributes['src']!.contains("cover"))
.map((e) => e.attributes['src'])
.toList();
name = dom
.querySelectorAll(
'body > div.container.weekrank.ranking > div > div > ul > li > a ')
.querySelectorAll('.manga-list-1-list li > a ')
.where((e) => e.attributes.containsKey('title'))
.map((e) => e.attributes['title'])
.toList();
@ -219,7 +213,8 @@ class Mangahere extends MangaYomiServices {
return secretKeyResultScript;
}
var link = "http://www.mangahere.cc${chapter.url!}";
var link =
"${getMangaBaseUrl(chapter.manga.value!.source!)}${chapter.url!}";
final response = await ref.watch(
httpGetProvider(url: link, source: "mangahere", resDom: false)
.future) as String?;
@ -307,6 +302,39 @@ class Mangahere extends MangaYomiServices {
}
return pageUrls;
}
@override
Future<List<GetManga?>> getLatestUpdatesManga(
{required String source,
required int page,
required AutoDisposeFutureProviderRef ref}) async {
final dom = await ref.watch(httpGetProvider(
url: '${getMangaBaseUrl(source)}/directory/$page.htm?latest',
source: source,
resDom: true)
.future) as Document?;
if (dom!.querySelectorAll('.manga-list-1-list li').isNotEmpty) {
url = dom
.querySelectorAll('.manga-list-1-list li > a ')
.where((e) => e.attributes.containsKey('href'))
.map((e) => e.attributes['href'])
.toList();
image = dom
.querySelectorAll('.manga-list-1-list li > a > img')
.where((e) => e.attributes.containsKey('src'))
.where((e) => e.attributes['src']!.contains("cover"))
.map((e) => e.attributes['src'])
.toList();
name = dom
.querySelectorAll('.manga-list-1-list li > a ')
.where((e) => e.attributes.containsKey('title'))
.map((e) => e.attributes['title'])
.toList();
}
return mangaRes();
}
}
int parseMangaHereChapterDate(String date, String source) {

View file

@ -19,16 +19,18 @@ class Japscan extends MangaYomiServices {
required String lang,
required String source,
required AutoDisposeFutureProviderRef ref}) async {
final dom = await ref.watch(
httpGetProvider(url: manga.url!, source: source, resDom: true)
.future) as Document?;
final dom = await ref.watch(httpGetProvider(
url: manga.url!,
source: source,
resDom: true,
).future) as Document?;
if (dom!.querySelectorAll('.col-7 > p').isNotEmpty) {
final images =
dom.querySelectorAll('.col-5 ').map((e) => e.outerHtml).toList();
RegExp exp = RegExp(r'src="([^"]+)"');
String? srcValue = exp.firstMatch(images[0])?.group(1);
manga.imageUrl = 'https://www.japscan.lol$srcValue';
manga.imageUrl = '${getMangaBaseUrl(source)}l$srcValue';
if (dom.querySelectorAll('.col-7 > p').isNotEmpty) {
final stat = dom
@ -36,13 +38,16 @@ class Japscan extends MangaYomiServices {
.where((element) => element.innerHtml.contains('Statut:'))
.map((e) => e.text)
.toList();
String sta = stat[0].replaceAll('Statut:', '').trim();
if (stat.isNotEmpty) {
String sta = stat[0].replaceAll('Statut:', '').trim();
status = (switch (sta) {
"En Cours" => Status.ongoing,
"Terminé" => Status.completed,
_ => Status.unknown,
});
} else {
status = Status.unknown;
}
final auth = dom
@ -85,7 +90,7 @@ class Japscan extends MangaYomiServices {
RegExp exp = RegExp(r'href="([^"]+)"');
String? srcValue = exp.firstMatch(ok)?.group(1);
chapterUrl.add('https://www.japscan.lol$srcValue');
chapterUrl.add('${getMangaBaseUrl(source)}l$srcValue');
}
final chapterTitlee =
@ -113,7 +118,7 @@ class Japscan extends MangaYomiServices {
required int page,
required AutoDisposeFutureProviderRef ref}) async {
final dom = await ref.watch(httpGetProvider(
url: "https://www.japscan.lol/", source: source, resDom: true)
url: "${getMangaBaseUrl(source)}l/", source: source, resDom: true)
.future) as Document?;
if (dom!.querySelectorAll('#top_mangas_week > ul > li ').isNotEmpty) {
final urls = dom
@ -122,7 +127,7 @@ class Japscan extends MangaYomiServices {
.map((e) => e.attributes['href'])
.toList();
for (var ok in urls) {
url.add("https://www.japscan.lol$ok");
url.add("${getMangaBaseUrl(source)}l$ok");
}
name = dom
.querySelectorAll(
@ -194,7 +199,7 @@ class Japscan extends MangaYomiServices {
Match? match = regex.firstMatch(response!);
String zjsurl = match!.group(1)!;
baseUrl = response;
zjsUrl = "https://www.japscan.lol/zjs/$zjsurl";
zjsUrl = "${getMangaBaseUrl(chapter.manga.value!.source!)}l/zjs/$zjsurl";
zjs(ref);
await Future.doWhile(() async {
await Future.delayed(const Duration(seconds: 1));
@ -252,4 +257,38 @@ class Japscan extends MangaYomiServices {
}
isOk = true;
}
@override
Future<List<GetManga?>> getLatestUpdatesManga(
{required String source,
required int page,
required AutoDisposeFutureProviderRef ref}) async {
final dom = await ref.watch(httpGetProvider(
url: "${getMangaBaseUrl(source)}l/", source: source, resDom: true)
.future) as Document?;
if (dom!
.querySelectorAll(
'#chapters h3.text-truncate, #chapters_list h3.text-truncate')
.isNotEmpty) {
final urls = dom
.querySelectorAll(
'#chapters h3.text-truncate, #chapters_list h3.text-truncate > a')
.where((e) => e.attributes['href'].toString().contains('manga'))
.map((e) => e.attributes['href'])
.toList();
for (var ok in urls) {
url.add("${getMangaBaseUrl(source)}l$ok");
}
name = dom
.querySelectorAll(
'#chapters h3.text-truncate, #chapters_list h3.text-truncate > a.text-dark.font-weight-bold')
.map((e) => e.innerHtml)
.toList();
for (var i = 0; i < name.length; i++) {
image.add("");
}
}
return mangaRes();
}
}

View file

@ -212,4 +212,10 @@ class MangaKawaii extends MangaYomiServices {
}
return pageUrls;
}
@override
Future<List<GetManga?>> getLatestUpdatesManga({required String source, required int page, required AutoDisposeFutureProviderRef ref}) {
// TODO: implement getLatestUpdatesManga
throw UnimplementedError();
}
}