diff --git a/.vscode/settings.json b/.vscode/settings.json index e0f15db2..3d36e652 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,6 @@ { - "java.configuration.updateBuildConfiguration": "automatic" + "java.configuration.updateBuildConfiguration": "automatic", + "githubPullRequests.ignoredPullRequestBranches": [ + "main" + ] } \ No newline at end of file diff --git a/lib/models/source_model.dart b/lib/models/source_model.dart index cf10e126..1748762b 100644 --- a/lib/models/source_model.dart +++ b/lib/models/source_model.dart @@ -7,7 +7,7 @@ class SourceModel extends HiveObject { @HiveField(0) final String sourceName; @HiveField(1) - final String url; + final String baseUrl; @HiveField(2) final String lang; @HiveField(3, defaultValue: true) @@ -28,10 +28,11 @@ class SourceModel extends HiveObject { final String dateFormat; @HiveField(11) final String dateFormatLocale; - + @HiveField(12) + final String apiUrl; SourceModel({ required this.sourceName, - required this.url, + required this.baseUrl, required this.lang, required this.typeSource, required this.logoUrl, @@ -42,6 +43,7 @@ class SourceModel extends HiveObject { this.isNsfw = false, this.isFullData = false, this.isCloudflare = false, + this.apiUrl = "", }); } @@ -54,5 +56,7 @@ enum TypeSource { @HiveField(3) comick, @HiveField(4) - mmrcms + mmrcms, + @HiveField(5) + heancms } diff --git a/lib/models/source_model.g.dart b/lib/models/source_model.g.dart index d8a648a6..115bb2ac 100644 --- a/lib/models/source_model.g.dart +++ b/lib/models/source_model.g.dart @@ -18,7 +18,7 @@ class SourceModelAdapter extends TypeAdapter { }; return SourceModel( sourceName: fields[0] as String, - url: fields[1] as String, + baseUrl: fields[1] as String, lang: fields[2] as String, typeSource: fields[6] as TypeSource, logoUrl: fields[7] as String, @@ -29,17 +29,18 @@ class SourceModelAdapter extends TypeAdapter { isNsfw: fields[5] == null ? false : fields[5] as bool, isFullData: fields[8] == null ? false : fields[8] as bool, isCloudflare: fields[9] == null ? false : fields[9] as bool, + apiUrl: fields[12] as String, ); } @override void write(BinaryWriter writer, SourceModel obj) { writer - ..writeByte(12) + ..writeByte(13) ..writeByte(0) ..write(obj.sourceName) ..writeByte(1) - ..write(obj.url) + ..write(obj.baseUrl) ..writeByte(2) ..write(obj.lang) ..writeByte(3) @@ -59,7 +60,9 @@ class SourceModelAdapter extends TypeAdapter { ..writeByte(10) ..write(obj.dateFormat) ..writeByte(11) - ..write(obj.dateFormatLocale); + ..write(obj.dateFormatLocale) + ..writeByte(12) + ..write(obj.apiUrl); } @override @@ -88,6 +91,8 @@ class TypeSourceAdapter extends TypeAdapter { return TypeSource.comick; case 4: return TypeSource.mmrcms; + case 5: + return TypeSource.heancms; default: return TypeSource.single; } @@ -108,6 +113,9 @@ class TypeSourceAdapter extends TypeAdapter { case TypeSource.mmrcms: writer.writeByte(4); break; + case TypeSource.heancms: + writer.writeByte(5); + break; } } diff --git a/lib/services/get_manga_chapter_url.dart b/lib/services/get_manga_chapter_url.dart index 5fe93e94..e654e989 100644 --- a/lib/services/get_manga_chapter_url.dart +++ b/lib/services/get_manga_chapter_url.dart @@ -5,12 +5,13 @@ import 'package:mangayomi/models/chapter.dart'; import 'package:mangayomi/models/source_model.dart'; import 'package:mangayomi/providers/hive_provider.dart'; import 'package:mangayomi/providers/storage_provider.dart'; +import 'package:mangayomi/sources/multisrc/heancms/heancms.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/src/multi/mangathemesia/src/mangathemesia.dart'; -import 'package:mangayomi/sources/src/multi/mmrcms/src/mmrcms.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:mangayomi/utils/reg_exp_matcher.dart'; import 'package:mangayomi/views/more/settings/providers/incognito_mode_state_provider.dart'; @@ -49,7 +50,7 @@ Future getMangaChapterUrl( /*comick*/ /********/ - else if (getWpMangTypeSource(source) == TypeSource.comick) { + else if (getMangaTypeSource(source) == TypeSource.comick) { pageUrls = await Comick().getMangaChapterUrl(chapter: chapter); } @@ -57,7 +58,7 @@ Future getMangaChapterUrl( /*mangathemesia*/ /**************/ - else if (getWpMangTypeSource(source) == TypeSource.mangathemesia) { + else if (getMangaTypeSource(source) == TypeSource.mangathemesia) { pageUrls = await MangaThemeSia().getMangaChapterUrl(chapter: chapter); } @@ -73,7 +74,7 @@ Future getMangaChapterUrl( /*mmrcms*/ /***********/ - else if (getWpMangTypeSource(source) == TypeSource.mmrcms) { + else if (getMangaTypeSource(source) == TypeSource.mmrcms) { pageUrls = await Mmrcms().getMangaChapterUrl(chapter: chapter); } @@ -93,6 +94,14 @@ Future getMangaChapterUrl( pageUrls = await Japscan().getMangaChapterUrl(chapter: chapter); } + /***********/ + /*heancms*/ + /***********/ + + else if (getMangaTypeSource(source) == TypeSource.heancms) { + pageUrls = await HeanCms().getMangaChapterUrl(chapter: chapter); + } + if (pageUrls.isNotEmpty) { if (!incognitoMode) { ref.watch(hiveBoxMangaProvider).put( diff --git a/lib/services/get_manga_chapter_url.g.dart b/lib/services/get_manga_chapter_url.g.dart index 9aa49202..c185c92e 100644 --- a/lib/services/get_manga_chapter_url.g.dart +++ b/lib/services/get_manga_chapter_url.g.dart @@ -7,7 +7,7 @@ part of 'get_manga_chapter_url.dart'; // ************************************************************************** String _$getMangaChapterUrlHash() => - r'4daf1dc296255c64ca0ee2cf963dd98b3595d93c'; + r'066c4d826fd17ba3d3682d806778fe1010378c05'; /// Copied from Dart SDK class _SystemHash { diff --git a/lib/services/get_manga_detail.dart b/lib/services/get_manga_detail.dart index 370cff7a..fea6cafa 100644 --- a/lib/services/get_manga_detail.dart +++ b/lib/services/get_manga_detail.dart @@ -1,64 +1,63 @@ import 'dart:async'; import 'package:mangayomi/models/source_model.dart'; -import 'package:mangayomi/sources/service/service.dart'; +import 'package:mangayomi/sources/multisrc/heancms/heancms.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/src/multi/mangathemesia/src/mangathemesia.dart'; -import 'package:mangayomi/sources/src/multi/mmrcms/src/mmrcms.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_manga_detail.g.dart'; @riverpod -Future getMangaDetail(GetMangaDetailRef ref, - {required String imageUrl, - required String url, - required String title, +Future getMangaDetail(GetMangaDetailRef ref, + {required GetManga manga, required String lang, required String source}) async { - GetMangaDetailModel? mangadetail; + GetManga? mangadetail; /********/ /*comick*/ /********/ - if (getWpMangTypeSource(source.toLowerCase()) == TypeSource.comick) { - mangadetail = await Comick().getMangaDetail( - imageUrl: imageUrl, url: url, title: title, lang: lang, source: source); + if (getMangaTypeSource(source.toLowerCase()) == TypeSource.comick) { + mangadetail = + await Comick().getMangaDetail(manga: manga, lang: lang, source: source); } /*************/ /*mangathemesia*/ /**************/ - if (getWpMangTypeSource(source.toLowerCase()) == TypeSource.mangathemesia) { - mangadetail = await MangaThemeSia().getMangaDetail( - imageUrl: imageUrl, url: url, title: title, lang: lang, source: source); + if (getMangaTypeSource(source.toLowerCase()) == TypeSource.mangathemesia) { + mangadetail = await MangaThemeSia() + .getMangaDetail(manga: manga, lang: lang, source: source); } /***********/ /*mangakawaii*/ /***********/ else if (source.toLowerCase() == "mangakawaii") { - mangadetail = await MangaKawaii().getMangaDetail( - imageUrl: imageUrl, url: url, title: title, lang: lang, source: source); + mangadetail = await MangaKawaii() + .getMangaDetail(manga: manga, lang: lang, source: source); } /***********/ /*mmrcms*/ /***********/ - else if (getWpMangTypeSource(source.toLowerCase()) == TypeSource.mmrcms) { - mangadetail = await Mmrcms().getMangaDetail( - imageUrl: imageUrl, url: url, title: title, lang: lang, source: source); + else if (getMangaTypeSource(source.toLowerCase()) == TypeSource.mmrcms) { + mangadetail = + await Mmrcms().getMangaDetail(manga: manga, lang: lang, source: source); } /***********/ /*mangahere*/ /***********/ else if (source.toLowerCase() == "mangahere") { - mangadetail = await Mangahere().getMangaDetail( - imageUrl: imageUrl, url: url, title: title, lang: lang, source: source); + mangadetail = await Mangahere() + .getMangaDetail(manga: manga, lang: lang, source: source); } /***********/ @@ -66,8 +65,17 @@ Future getMangaDetail(GetMangaDetailRef ref, /***********/ else if (source.toLowerCase() == "japscan") { - mangadetail = await Japscan().getMangaDetail( - imageUrl: imageUrl, url: url, title: title, lang: lang, source: source); + mangadetail = await Japscan() + .getMangaDetail(manga: manga, lang: lang, source: source); + } + + /***********/ + /*heancms*/ + /***********/ + + else if (getMangaTypeSource(source.toLowerCase()) == TypeSource.heancms) { + mangadetail = await HeanCms() + .getMangaDetail(manga: manga, lang: lang, source: source); } return mangadetail!; } diff --git a/lib/services/get_manga_detail.g.dart b/lib/services/get_manga_detail.g.dart index 5a329282..8c38b1f1 100644 --- a/lib/services/get_manga_detail.g.dart +++ b/lib/services/get_manga_detail.g.dart @@ -6,7 +6,7 @@ part of 'get_manga_detail.dart'; // RiverpodGenerator // ************************************************************************** -String _$getMangaDetailHash() => r'989fdfaf80bf546d1f9910b0715afc9a0e64f33a'; +String _$getMangaDetailHash() => r'ee4c8c5203a9cc0d6de3697f96e5e46e80218fc2'; /// Copied from Dart SDK class _SystemHash { @@ -29,29 +29,25 @@ class _SystemHash { } } -typedef GetMangaDetailRef = AutoDisposeFutureProviderRef; +typedef GetMangaDetailRef = AutoDisposeFutureProviderRef; /// See also [getMangaDetail]. @ProviderFor(getMangaDetail) const getMangaDetailProvider = GetMangaDetailFamily(); /// See also [getMangaDetail]. -class GetMangaDetailFamily extends Family> { +class GetMangaDetailFamily extends Family> { /// See also [getMangaDetail]. const GetMangaDetailFamily(); /// See also [getMangaDetail]. GetMangaDetailProvider call({ - required String imageUrl, - required String url, - required String title, + required GetManga manga, required String lang, required String source, }) { return GetMangaDetailProvider( - imageUrl: imageUrl, - url: url, - title: title, + manga: manga, lang: lang, source: source, ); @@ -62,9 +58,7 @@ class GetMangaDetailFamily extends Family> { covariant GetMangaDetailProvider provider, ) { return call( - imageUrl: provider.imageUrl, - url: provider.url, - title: provider.title, + manga: provider.manga, lang: provider.lang, source: provider.source, ); @@ -86,21 +80,16 @@ class GetMangaDetailFamily extends Family> { } /// See also [getMangaDetail]. -class GetMangaDetailProvider - extends AutoDisposeFutureProvider { +class GetMangaDetailProvider extends AutoDisposeFutureProvider { /// See also [getMangaDetail]. GetMangaDetailProvider({ - required this.imageUrl, - required this.url, - required this.title, + required this.manga, required this.lang, required this.source, }) : super.internal( (ref) => getMangaDetail( ref, - imageUrl: imageUrl, - url: url, - title: title, + manga: manga, lang: lang, source: source, ), @@ -115,18 +104,14 @@ class GetMangaDetailProvider GetMangaDetailFamily._allTransitiveDependencies, ); - final String imageUrl; - final String url; - final String title; + final GetManga manga; final String lang; final String source; @override bool operator ==(Object other) { return other is GetMangaDetailProvider && - other.imageUrl == imageUrl && - other.url == url && - other.title == title && + other.manga == manga && other.lang == lang && other.source == source; } @@ -134,9 +119,7 @@ class GetMangaDetailProvider @override int get hashCode { var hash = _SystemHash.combine(0, runtimeType.hashCode); - hash = _SystemHash.combine(hash, imageUrl.hashCode); - hash = _SystemHash.combine(hash, url.hashCode); - hash = _SystemHash.combine(hash, title.hashCode); + hash = _SystemHash.combine(hash, manga.hashCode); hash = _SystemHash.combine(hash, lang.hashCode); hash = _SystemHash.combine(hash, source.hashCode); diff --git a/lib/services/get_popular_manga.dart b/lib/services/get_popular_manga.dart index 4d8eb48f..44aae982 100644 --- a/lib/services/get_popular_manga.dart +++ b/lib/services/get_popular_manga.dart @@ -1,33 +1,34 @@ import 'dart:async'; import 'package:mangayomi/models/source_model.dart'; -import 'package:mangayomi/sources/service/service.dart'; +import 'package:mangayomi/sources/multisrc/heancms/heancms.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/src/multi/mangathemesia/src/mangathemesia.dart'; -import 'package:mangayomi/sources/src/multi/mmrcms/src/mmrcms.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_popular_manga.g.dart'; @riverpod -Future getPopularManga(GetPopularMangaRef ref, +Future> getPopularManga(GetPopularMangaRef ref, {required String source, required int page}) async { - GetMangaModel? popularManga; + List? popularManga; source = source.toLowerCase(); /*********/ /*comick*/ /*******/ - if (getWpMangTypeSource(source) == TypeSource.comick) { + if (getMangaTypeSource(source) == TypeSource.comick) { popularManga = await Comick().getPopularManga(source: source, page: page); } /***************/ /*mangathemesia*/ /**************/ - if (getWpMangTypeSource(source) == TypeSource.mangathemesia) { + if (getMangaTypeSource(source) == TypeSource.mangathemesia) { popularManga = await MangaThemeSia().getPopularManga(source: source, page: page); } @@ -44,7 +45,7 @@ Future getPopularManga(GetPopularMangaRef ref, /*mmrcms*/ /***********/ - else if (getWpMangTypeSource(source) == TypeSource.mmrcms) { + else if (getMangaTypeSource(source) == TypeSource.mmrcms) { popularManga = await Mmrcms().getPopularManga(source: source, page: page); } @@ -61,5 +62,12 @@ Future getPopularManga(GetPopularMangaRef ref, else if (source == "japscan") { popularManga = await Japscan().getPopularManga(source: source, page: page); } + + /***********/ + /*japscan*/ + /***********/ + else if (getMangaTypeSource(source) == TypeSource.heancms) { + popularManga = await HeanCms().getPopularManga(source: source, page: page); + } return popularManga!; } diff --git a/lib/services/get_popular_manga.g.dart b/lib/services/get_popular_manga.g.dart index 8410de8e..2171ce41 100644 --- a/lib/services/get_popular_manga.g.dart +++ b/lib/services/get_popular_manga.g.dart @@ -6,7 +6,7 @@ part of 'get_popular_manga.dart'; // RiverpodGenerator // ************************************************************************** -String _$getPopularMangaHash() => r'cec4ced8864aca6f08b29a8ef9405fd21b68927f'; +String _$getPopularMangaHash() => r'0571fdcea7fc7aebb97c5748f6781e4075705382'; /// Copied from Dart SDK class _SystemHash { @@ -29,14 +29,14 @@ class _SystemHash { } } -typedef GetPopularMangaRef = AutoDisposeFutureProviderRef; +typedef GetPopularMangaRef = AutoDisposeFutureProviderRef>; /// See also [getPopularManga]. @ProviderFor(getPopularManga) const getPopularMangaProvider = GetPopularMangaFamily(); /// See also [getPopularManga]. -class GetPopularMangaFamily extends Family> { +class GetPopularMangaFamily extends Family>> { /// See also [getPopularManga]. const GetPopularMangaFamily(); @@ -77,7 +77,8 @@ class GetPopularMangaFamily extends Family> { } /// See also [getPopularManga]. -class GetPopularMangaProvider extends AutoDisposeFutureProvider { +class GetPopularMangaProvider + extends AutoDisposeFutureProvider> { /// See also [getPopularManga]. GetPopularMangaProvider({ required this.source, diff --git a/lib/services/http_service/http_res_to_dom_html.dart b/lib/services/http_service/http_res_to_dom_html.dart index 5e3704ba..6b15490c 100644 --- a/lib/services/http_service/http_res_to_dom_html.dart +++ b/lib/services/http_service/http_res_to_dom_html.dart @@ -3,10 +3,6 @@ import 'package:http/http.dart' as http; Future httpResToDom( {required String url, required Map? headers}) async { - try { - final response = await http.get(Uri.parse(url), headers: headers); - return Document.html(response.body); - } catch (e) { - rethrow; - } + final response = await http.get(Uri.parse(url), headers: headers); + return Document.html(response.body); } diff --git a/lib/services/search_manga.dart b/lib/services/search_manga.dart index 9ba2bb2b..723fa0c4 100644 --- a/lib/services/search_manga.dart +++ b/lib/services/search_manga.dart @@ -1,26 +1,27 @@ import 'package:mangayomi/models/source_model.dart'; -import 'package:mangayomi/sources/service/service.dart'; +import 'package:mangayomi/sources/multisrc/heancms/heancms.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/src/multi/mangathemesia/src/mangathemesia.dart'; -import 'package:mangayomi/sources/src/multi/mmrcms/src/mmrcms.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 'search_manga.g.dart'; @riverpod -Future searchManga(SearchMangaRef ref, +Future> searchManga(SearchMangaRef ref, {required String source, required String query}) async { - GetMangaModel? manga; + List? manga; source = source.toLowerCase(); /********/ /*comick*/ /********/ - if (getWpMangTypeSource(source) == TypeSource.comick) { + if (getMangaTypeSource(source) == TypeSource.comick) { manga = await Comick().searchManga(source: source, query: query); } @@ -28,10 +29,10 @@ Future searchManga(SearchMangaRef ref, /*mangathemesia*/ /***************/ - else if (getWpMangTypeSource(source) == TypeSource.mangathemesia) { + else if (getMangaTypeSource(source) == TypeSource.mangathemesia) { manga = await MangaThemeSia().searchManga(source: source, query: query); } - + /***********/ /*mangakawaii*/ /***********/ @@ -44,10 +45,10 @@ Future searchManga(SearchMangaRef ref, /*mmrcms*/ /***********/ - else if (getWpMangTypeSource(source) == TypeSource.mmrcms) { + else if (getMangaTypeSource(source) == TypeSource.mmrcms) { manga = await Mmrcms().searchManga(source: source, query: query); } - + /***********/ /*mangahere*/ /***********/ @@ -64,5 +65,13 @@ Future searchManga(SearchMangaRef ref, manga = await Japscan().searchManga(source: source, query: query); } + /***********/ + /*heancms*/ + /***********/ + + else if (getMangaTypeSource(source) == TypeSource.heancms) { + manga = await HeanCms().searchManga(source: source, query: query); + } + return manga!; } diff --git a/lib/services/search_manga.g.dart b/lib/services/search_manga.g.dart index 5428864b..7e0d10ec 100644 --- a/lib/services/search_manga.g.dart +++ b/lib/services/search_manga.g.dart @@ -6,7 +6,7 @@ part of 'search_manga.dart'; // RiverpodGenerator // ************************************************************************** -String _$searchMangaHash() => r'1694578ec0cc207b533f4709427d3f68b691b1b7'; +String _$searchMangaHash() => r'881d305e97081528fa6259bc4c2ea0a28b63e1fd'; /// Copied from Dart SDK class _SystemHash { @@ -29,14 +29,14 @@ class _SystemHash { } } -typedef SearchMangaRef = AutoDisposeFutureProviderRef; +typedef SearchMangaRef = AutoDisposeFutureProviderRef>; /// See also [searchManga]. @ProviderFor(searchManga) const searchMangaProvider = SearchMangaFamily(); /// See also [searchManga]. -class SearchMangaFamily extends Family> { +class SearchMangaFamily extends Family>> { /// See also [searchManga]. const SearchMangaFamily(); @@ -77,7 +77,7 @@ class SearchMangaFamily extends Family> { } /// See also [searchManga]. -class SearchMangaProvider extends AutoDisposeFutureProvider { +class SearchMangaProvider extends AutoDisposeFutureProvider> { /// See also [searchManga]. SearchMangaProvider({ required this.source, diff --git a/lib/sources/multisrc/heancms/heancms.dart b/lib/sources/multisrc/heancms/heancms.dart new file mode 100644 index 00000000..a1a9b8d2 --- /dev/null +++ b/lib/sources/multisrc/heancms/heancms.dart @@ -0,0 +1,157 @@ +import 'dart:convert'; +import 'package:mangayomi/models/chapter.dart'; +import 'package:mangayomi/services/http_service/http_res_to_dom_html.dart'; +import 'package:mangayomi/sources/multisrc/heancms/model/search.dart'; +import 'package:mangayomi/sources/multisrc/heancms/utils/utils.dart'; +import 'package:mangayomi/sources/service.dart'; +import 'package:http/http.dart' as http; +import 'package:mangayomi/sources/utils/utils.dart'; + +class HeanCms extends MangaYomiServices { + Map _headers(String source) => { + 'Origin': getMangaBaseUrl(source), + 'Referer': getMangaAPIUrl(source), + 'Accept': 'application/json, text/plain, */*', + 'Content-Type': 'application/json' + }; + @override + Future> getMangaChapterUrl({required Chapter chapter}) async { + final chapterId = chapter.url!.split("#").last; + var request = http.Request( + 'GET', + Uri.parse( + '${getMangaAPIUrl("${chapter.manga.value!.source}")}series/chapter/$chapterId')); + request.headers.addAll({ + 'Accept': 'application/json, text/plain, */*', + }); + http.StreamedResponse response = await request.send(); + final res = await response.stream.bytesToString(); + var page = jsonDecode(res) as Map; + for (var url in page["content"]["images"]) { + if (url.startsWith("http")) { + pageUrls.add(url); + } else { + pageUrls.add("${getMangaAPIUrl("${chapter.manga.value!.source}")}$url"); + } + } + return pageUrls; + } + + @override + Future getMangaDetail( + {required GetManga manga, + required String lang, + required String source}) async { + String currentSlug = manga.url!.split('/').last; + + var request = http.Request( + 'GET', + Uri.parse( + '${getMangaAPIUrl(source)}series/$currentSlug#${manga.status}')); + request.headers.addAll({ + 'Accept': 'application/json, text/plain, */*', + }); + http.StreamedResponse response = await request.send(); + final res = await response.stream.bytesToString(); + var mangaDetail = jsonDecode(res) as Map; + final d = Data.fromJson(mangaDetail); + + final dom = await httpResToDom( + url: '${getMangaBaseUrl(source)}/series/$currentSlug', headers: {}); + final des = dom + .querySelectorAll("div.description-container") + .map((e) => e.text.trim()) + .toList(); + final genres = dom + .querySelectorAll("div.tags-container.pt-3 > span") + .map((e) => e.text) + .toList(); + final auth = dom + .querySelectorAll("div > p") + .where((element) => element.outerHtml.toLowerCase().contains('autor')) + .map((e) => e.text) + .toList(); + author = auth.first.split(":").last; + status = manga.status; + genre = genres; + description = des.first; + for (var chapter in d.chapters!) { + chapterUrl + .add("/series/$currentSlug/${chapter.chapterSlug}#${chapter.id}"); + chapterTitle.add(chapter.chapterName!.trim()); + chapterDate.add(parseDate(chapter.createdAt!, source)); + } + return mangadetailRes(manga: manga, source: source); + } + + @override + Future> getPopularManga( + {required String source, required int page}) async { + var request = http.Request( + 'POST', Uri.parse('${getMangaAPIUrl(source)}series/querysearch')); + request.body = json.encode({ + "page": page, + "order": "desc", + "order_by": "total_views", + "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; + if (res.startsWith("{")) { + var popularManga = jsonDecode(res) as Map; + 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) { + statusList.add(a.status ?? "Unknown"); + 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(); + } + + @override + Future> searchManga( + {required String source, required String query}) async { + var request = http.Request( + 'POST', Uri.parse('${getMangaAPIUrl(source)}series/search')); + request.body = json.encode({"term": query.trim()}); + request.headers.addAll({ + 'Accept': 'application/json, text/plain, */*', + 'Content-Type': 'application/json' + }); + http.StreamedResponse response = await request.send(); + final res = await response.stream.bytesToString(); + List? data; + if (res.startsWith("{")) { + var popularManga = jsonDecode(res) as Map; + 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) { + statusList.add(a.status ?? "Unknown"); + 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(); + } +} diff --git a/lib/sources/multisrc/heancms/heancms_source_list.dart b/lib/sources/multisrc/heancms/heancms_source_list.dart new file mode 100644 index 00000000..89eb5600 --- /dev/null +++ b/lib/sources/multisrc/heancms/heancms_source_list.dart @@ -0,0 +1,15 @@ +import 'package:mangayomi/models/source_model.dart'; + +List get heanCmsSourcesList => _heanCmsSourcesList; +List _heanCmsSourcesList = [ + SourceModel( + sourceName: "Yugenmangas", + baseUrl: "https://yugenmangas.com", + apiUrl: "https://api.yugenmangas.com/", + lang: "es", + typeSource: TypeSource.heancms, + isNsfw: true, + logoUrl: '', + dateFormat: "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ", + dateFormatLocale: "en"), +]; diff --git a/lib/sources/multisrc/heancms/model/search.dart b/lib/sources/multisrc/heancms/model/search.dart new file mode 100644 index 00000000..9c1fb8f9 --- /dev/null +++ b/lib/sources/multisrc/heancms/model/search.dart @@ -0,0 +1,136 @@ +class HeanCmsSearchModel { + Meta? meta; + List? data; + + HeanCmsSearchModel({this.meta, this.data}); + + HeanCmsSearchModel.fromJson(Map json) { + meta = json['meta'] != null ? Meta.fromJson(json['meta']) : null; + if (json['data'] != null) { + data = []; + json['data'].forEach((v) { + data!.add(Data.fromJson(v)); + }); + } + } +} + +class Meta { + int? total; + int? perPage; + int? currentPage; + int? lastPage; + int? firstPage; + String? firstPageUrl; + String? lastPageUrl; + String? nextPageUrl; + + Meta({ + this.total, + this.perPage, + this.currentPage, + this.lastPage, + this.firstPage, + this.firstPageUrl, + this.lastPageUrl, + this.nextPageUrl, + }); + + Meta.fromJson(Map json) { + total = json['total']; + perPage = json['per_page']; + currentPage = json['current_page']; + lastPage = json['last_page']; + firstPage = json['first_page']; + firstPageUrl = json['first_page_url']; + lastPageUrl = json['last_page_url']; + nextPageUrl = json['next_page_url']; + } +} + +class Data { + String? title; + int? id; + String? seriesType; + String? visibility; + String? thumbnail; + String? seriesSlug; + String? status; + String? latest; + String? badge; + List? chapters; + Meta? meta; + + Data( + {this.title, + this.id, + this.seriesType, + this.visibility, + this.thumbnail, + this.seriesSlug, + this.status, + this.latest, + this.badge, + this.chapters, + this.meta}); + + Data.fromJson(Map json) { + title = json['title']; + id = json['id']; + seriesType = json['series_type']; + visibility = json['visibility']; + thumbnail = json['thumbnail']; + seriesSlug = json['series_slug']; + status = json['status']; + latest = json['latest']; + badge = json['badge']; + if (json['chapters'] != null) { + chapters = []; + json['chapters'].forEach((v) { + chapters!.add(Chapters.fromJson(v)); + }); + } + meta = json['meta'] != null ? Meta.fromJson(json['meta']) : null; + } +} + +class Chapters { + int? id; + String? index; + String? chapterName; + String? chapterSlug; + String? createdAt; + String? updatedAt; + int? seriesId; + + Chapters( + {this.id, + this.index, + this.chapterName, + this.chapterSlug, + this.createdAt, + this.updatedAt, + this.seriesId}); + + Chapters.fromJson(Map json) { + id = json['id']; + index = json['index']; + chapterName = json['chapter_name']; + chapterSlug = json['chapter_slug']; + createdAt = json['created_at']; + updatedAt = json['updated_at']; + seriesId = json['series_id']; + } + + Map toJson() { + final Map data = {}; + data['id'] = id; + data['index'] = index; + data['chapter_name'] = chapterName; + data['chapter_slug'] = chapterSlug; + data['created_at'] = createdAt; + data['updated_at'] = updatedAt; + data['series_id'] = seriesId; + return data; + } +} diff --git a/lib/sources/multisrc/heancms/utils/utils.dart b/lib/sources/multisrc/heancms/utils/utils.dart new file mode 100644 index 00000000..0b293ead --- /dev/null +++ b/lib/sources/multisrc/heancms/utils/utils.dart @@ -0,0 +1,2 @@ + +RegExp timeStampRegex = RegExp("-\\d+"); \ No newline at end of file diff --git a/lib/sources/src/multi/mangathemesia/mangathemesia_source_list.dart b/lib/sources/multisrc/mangathemesia/mangathemesia_source_list.dart similarity index 84% rename from lib/sources/src/multi/mangathemesia/mangathemesia_source_list.dart rename to lib/sources/multisrc/mangathemesia/mangathemesia_source_list.dart index f554eac9..d791b774 100644 --- a/lib/sources/src/multi/mangathemesia/mangathemesia_source_list.dart +++ b/lib/sources/multisrc/mangathemesia/mangathemesia_source_list.dart @@ -1,9 +1,10 @@ import 'package:mangayomi/models/source_model.dart'; -List mangathemesiaSourcesList = [ +List get mangathemesiaSourcesList => _mangathemesiaSourcesList; +List _mangathemesiaSourcesList = [ SourceModel( sourceName: "KomikLab", - url: "https://komiklab.com", + baseUrl: "https://komiklab.com", lang: "en", typeSource: TypeSource.mangathemesia, logoUrl: '', @@ -11,7 +12,7 @@ List mangathemesiaSourcesList = [ dateFormatLocale: "en"), SourceModel( sourceName: "AnimatedGlitchedScans", - url: "https://anigliscans.com", + baseUrl: "https://anigliscans.com", lang: "en", typeSource: TypeSource.mangathemesia, logoUrl: '', @@ -19,7 +20,7 @@ List mangathemesiaSourcesList = [ dateFormatLocale: "en"), // SourceModel( // sourceName: "ArenaScans", - // url: "https://arenascans.net", + // baseUrl: "https://arenascans.net", // lang: "en", // typeSource: TypeSource.mangathemesia, // logoUrl: @@ -27,14 +28,14 @@ List mangathemesiaSourcesList = [ // isCloudflare: true), // SourceModel( // sourceName: "AzureScans", - // url: "https://azuremanga.com", + // baseUrl: "https://azuremanga.com", // lang: "en", // typeSource: TypeSource.mangathemesia, // logoUrl: ''), SourceModel( sourceName: "Boosei", - url: "https://boosei.net", + baseUrl: "https://boosei.net", lang: "id", typeSource: TypeSource.mangathemesia, logoUrl: @@ -43,7 +44,7 @@ List mangathemesiaSourcesList = [ dateFormatLocale: "id"), SourceModel( sourceName: "Clayrer", - url: "https://clayrer.net", + baseUrl: "https://clayrer.net", lang: "es", typeSource: TypeSource.mangathemesia, logoUrl: @@ -52,7 +53,7 @@ List mangathemesiaSourcesList = [ dateFormatLocale: "es"), SourceModel( sourceName: "CosmicScans", - url: "https://cosmicscans.com", + baseUrl: "https://cosmicscans.com", lang: "en", typeSource: TypeSource.mangathemesia, logoUrl: '', @@ -60,7 +61,7 @@ List mangathemesiaSourcesList = [ dateFormatLocale: "en"), SourceModel( sourceName: "DiskusScan", - url: "https://diskusscan.com", + baseUrl: "https://diskusscan.com", lang: "pt-br", typeSource: TypeSource.mangathemesia, logoUrl: @@ -69,7 +70,7 @@ List mangathemesiaSourcesList = [ dateFormatLocale: "pt"), SourceModel( sourceName: "DuniaKomik", - url: "https://duniakomik.id", + baseUrl: "https://duniakomik.id", lang: "id", typeSource: TypeSource.mangathemesia, logoUrl: '', @@ -77,19 +78,19 @@ List mangathemesiaSourcesList = [ dateFormatLocale: "id"), // SourceModel( // sourceName: "FlameScans", - // url: "https://flamescans.fr", + // baseUrl: "https://flamescans.fr", // lang: "fr", // typeSource: TypeSource.mangathemesia, // logoUrl: ''), // SourceModel( // sourceName: "GremoryMangas", - // url: "https://gremorymangas.com", + // baseUrl: "https://gremorymangas.com", // lang: "es", // typeSource: TypeSource.mangathemesia, // logoUrl: 'https://gremorymangas.com/wp-content/uploads/2022/09/6941.png'), SourceModel( sourceName: "InfernalVoidScans", - url: "https://void-scans.com", + baseUrl: "https://void-scans.com", lang: "en", typeSource: TypeSource.mangathemesia, logoUrl: '', @@ -99,7 +100,7 @@ List mangathemesiaSourcesList = [ // SourceModel( // sourceName: "Kiryuu", - // url: "https://kiryuu.id", + // baseUrl: "https://kiryuu.id", // lang: "id", // typeSource: TypeSource.mangathemesia, // logoUrl: '', @@ -107,7 +108,7 @@ List mangathemesiaSourcesList = [ // dateFormatLocale: "id"), // SourceModel( // sourceName: "KomikIndo", - // url: "https://komikindo.co", + // baseUrl: "https://komikindo.co", // lang: "id", // typeSource: TypeSource.mangathemesia, // logoUrl: '', @@ -115,7 +116,7 @@ List mangathemesiaSourcesList = [ // dateFormatLocale: "id"), SourceModel( sourceName: "KomikMama", - url: "https://komikmama.co", + baseUrl: "https://komikmama.co", lang: "id", typeSource: TypeSource.mangathemesia, logoUrl: '', @@ -123,7 +124,7 @@ List mangathemesiaSourcesList = [ dateFormatLocale: "id"), SourceModel( sourceName: "Komiku", - url: "https://komiku.com", + baseUrl: "https://komiku.com", lang: "id", typeSource: TypeSource.mangathemesia, logoUrl: 'https://komiku.com/wp-content/uploads/2022/03/logooo.png', @@ -131,7 +132,7 @@ List mangathemesiaSourcesList = [ dateFormatLocale: "id"), SourceModel( sourceName: "KumaScans (Kuma Translation)", - url: "https://kumascans.com", + baseUrl: "https://kumascans.com", lang: "en", typeSource: TypeSource.mangathemesia, logoUrl: @@ -140,7 +141,7 @@ List mangathemesiaSourcesList = [ dateFormatLocale: "en"), // SourceModel( // sourceName: "MangaKita", - // url: "https://mangakita.net", + // baseUrl: "https://mangakita.net", // lang: "id", // typeSource: TypeSource.mangathemesia, // logoUrl: '', @@ -148,7 +149,7 @@ List mangathemesiaSourcesList = [ // dateFormatLocale: "en"), // SourceModel( // sourceName: "MangaTale", - // url: "https://mangatale.co", + // baseUrl: "https://mangatale.co", // lang: "id", // typeSource: TypeSource.mangathemesia, // logoUrl: @@ -157,7 +158,7 @@ List mangathemesiaSourcesList = [ // dateFormatLocale: "en"), SourceModel( sourceName: "MangaYaro", - url: "https://mangayaro.net", + baseUrl: "https://mangayaro.net", lang: "id", typeSource: TypeSource.mangathemesia, logoUrl: @@ -166,7 +167,7 @@ List mangathemesiaSourcesList = [ dateFormatLocale: "en"), SourceModel( sourceName: "MangKomik", - url: "https://mangkomik.net", + baseUrl: "https://mangkomik.net", lang: "id", typeSource: TypeSource.mangathemesia, logoUrl: @@ -175,7 +176,7 @@ List mangathemesiaSourcesList = [ dateFormatLocale: "id"), SourceModel( sourceName: "MangásChan", - url: "https://mangaschan.com", + baseUrl: "https://mangaschan.com", lang: "pt-br", typeSource: TypeSource.mangathemesia, logoUrl: 'https://mangaschan.com/wp-content/uploads/Logo-web.webp', @@ -183,7 +184,7 @@ List mangathemesiaSourcesList = [ dateFormatLocale: "pt-br"), // SourceModel( // sourceName: "ManhwaFreak", - // url: "https://manhwafreak.com", + // baseUrl: "https://manhwafreak.com", // lang: "en", // typeSource: TypeSource.mangathemesia, // logoUrl: @@ -192,7 +193,7 @@ List mangathemesiaSourcesList = [ // dateFormatLocale: "en"), SourceModel( sourceName: "ManhwaList", - url: "https://manhwalist.in", + baseUrl: "https://manhwalist.in", lang: "id", typeSource: TypeSource.mangathemesia, logoUrl: 'https://manhwalist.in/wp-content/uploads/2022/12/4666667.png', @@ -200,7 +201,7 @@ List mangathemesiaSourcesList = [ dateFormatLocale: "en"), // SourceModel( // sourceName: "MasterKomik", - // url: "https://masterkomik.com", + // baseUrl: "https://masterkomik.com", // lang: "id", // typeSource: TypeSource.mangathemesia, // logoUrl: 'https://masterkomik.com/wp-content/uploads/2020/12/New-MK.png', @@ -208,7 +209,7 @@ List mangathemesiaSourcesList = [ // dateFormatLocale: "id"), // SourceModel( // sourceName: "Nekomik", - // url: "https://nekomik.com", + // baseUrl: "https://nekomik.com", // lang: "id", // typeSource: TypeSource.mangathemesia, // logoUrl: '', @@ -216,7 +217,7 @@ List mangathemesiaSourcesList = [ // dateFormatLocale: "en"), // SourceModel( // sourceName: "PhantomScans", - // url: "https://phantomscans.com", + // baseUrl: "https://phantomscans.com", // lang: "en", // typeSource: TypeSource.mangathemesia, // logoUrl: '', @@ -224,7 +225,7 @@ List mangathemesiaSourcesList = [ // dateFormatLocale: "en"), // SourceModel( // sourceName: "PhoenixFansub", - // url: "https://phoenixfansub.com", + // baseUrl: "https://phoenixfansub.com", // lang: "es", // typeSource: TypeSource.mangathemesia, // logoUrl: '', @@ -232,7 +233,7 @@ List mangathemesiaSourcesList = [ // dateFormatLocale: "es"), SourceModel( sourceName: "PiScans", - url: "https://piscans.in", + baseUrl: "https://piscans.in", lang: "id", typeSource: TypeSource.mangathemesia, logoUrl: @@ -241,7 +242,7 @@ List mangathemesiaSourcesList = [ dateFormatLocale: "en"), // SourceModel( // sourceName: "Rawkuma", - // url: "https://rawkuma.com/", + // baseUrl: "https://rawkuma.com/", // lang: "ja", // typeSource: TypeSource.mangathemesia, // logoUrl: 'http://rawkuma.com/wp-content/uploads/2021/12/Rawkuma-Logo.png', @@ -249,7 +250,7 @@ List mangathemesiaSourcesList = [ // dateFormatLocale: "en"), SourceModel( sourceName: "Readkomik", - url: "https://readkomik.com", + baseUrl: "https://readkomik.com", lang: "en", typeSource: TypeSource.mangathemesia, logoUrl: @@ -258,7 +259,7 @@ List mangathemesiaSourcesList = [ dateFormatLocale: "en"), SourceModel( sourceName: "SuryaScans", - url: "https://suryascans.com", + baseUrl: "https://suryascans.com", lang: "en", typeSource: TypeSource.mangathemesia, logoUrl: @@ -267,7 +268,7 @@ List mangathemesiaSourcesList = [ dateFormatLocale: "en"), SourceModel( sourceName: "SushiScan", - url: "https://sushiscan.net", + baseUrl: "https://sushiscan.net", lang: "fr", typeSource: TypeSource.mangathemesia, logoUrl: 'https://sushiscan.net/wp-content/uploads/SushiScanNewLogo.png', @@ -276,7 +277,7 @@ List mangathemesiaSourcesList = [ dateFormatLocale: "fr"), SourceModel( sourceName: "TsundokuTraduções", - url: "https://tsundoku.com.br", + baseUrl: "https://tsundoku.com.br", lang: "pt-br", typeSource: TypeSource.mangathemesia, logoUrl: @@ -285,7 +286,7 @@ List mangathemesiaSourcesList = [ dateFormatLocale: "pt-br"), SourceModel( sourceName: "TukangKomik", - url: "https://tukangkomik.id", + baseUrl: "https://tukangkomik.id", lang: "id", typeSource: TypeSource.mangathemesia, logoUrl: @@ -294,7 +295,7 @@ List mangathemesiaSourcesList = [ dateFormatLocale: "en"), // SourceModel( // sourceName: "WestManga", - // url: "https://westmanga.info", + // baseUrl: "https://westmanga.info", // lang: "id", // typeSource: TypeSource.mangathemesia, // logoUrl: 'https://westmanga.info/wp-content/uploads/2021/01/LOGOxx-1.png', @@ -302,7 +303,7 @@ List mangathemesiaSourcesList = [ // dateFormatLocale: "en"), SourceModel( sourceName: "xCaliBRScans", - url: "https://xcalibrscans.com", + baseUrl: "https://xcalibrscans.com", lang: "en", typeSource: TypeSource.mangathemesia, logoUrl: diff --git a/lib/sources/src/multi/mangathemesia/src/mangathemesia.dart b/lib/sources/multisrc/mangathemesia/src/mangathemesia.dart similarity index 94% rename from lib/sources/src/multi/mangathemesia/src/mangathemesia.dart rename to lib/sources/multisrc/mangathemesia/src/mangathemesia.dart index 35d7443a..64c8271d 100644 --- a/lib/sources/src/multi/mangathemesia/src/mangathemesia.dart +++ b/lib/sources/multisrc/mangathemesia/src/mangathemesia.dart @@ -1,19 +1,17 @@ import 'package:html/dom.dart'; import 'package:mangayomi/models/chapter.dart'; import 'package:mangayomi/services/http_service/http_service.dart'; -import 'package:mangayomi/sources/service/service.dart'; +import 'package:mangayomi/sources/service.dart'; import 'package:mangayomi/sources/utils/utils.dart'; class MangaThemeSia extends MangaYomiServices { @override - Future getMangaDetail( - {required String imageUrl, - required String url, - required String title, + Future getMangaDetail( + {required GetManga manga, required String lang, required String source}) async { final dom = await httpGet( - url: url, + url: manga.url!, source: source, resDom: true, useUserAgent: true) as Document?; @@ -138,17 +136,17 @@ class MangaThemeSia extends MangaYomiServices { } } } - return mangadetailRes( - imageUrl: imageUrl, url: url, title: title, source: source); + return mangadetailRes(manga: manga, source: source); } @override - Future getPopularManga( + Future> getPopularManga( {required String source, required int page}) async { source = source.toLowerCase(); final dom = await httpGet( useUserAgent: true, - url: '${getWpMangaUrl(source)}/manga/?title=&page=$page&order=popular', + url: + '${getMangaBaseUrl(source)}/manga/?title=&page=$page&order=popular', source: source, resDom: true) as Document?; if (dom! @@ -189,10 +187,10 @@ class MangaThemeSia extends MangaYomiServices { } @override - Future searchManga( + Future> searchManga( {required String source, required String query}) async { final dom = await httpGet( - url: '${getWpMangaUrl(source)}/?s=${query.trim()}', + url: '${getMangaBaseUrl(source)}/?s=${query.trim()}', source: source, resDom: true) as Document?; if (dom! diff --git a/lib/sources/src/multi/mmrcms/mmrcms_source_list.dart b/lib/sources/multisrc/mmrcms/mmrcms_source_list.dart similarity index 77% rename from lib/sources/src/multi/mmrcms/mmrcms_source_list.dart rename to lib/sources/multisrc/mmrcms/mmrcms_source_list.dart index 7430d7b5..2a9d364a 100644 --- a/lib/sources/src/multi/mmrcms/mmrcms_source_list.dart +++ b/lib/sources/multisrc/mmrcms/mmrcms_source_list.dart @@ -1,11 +1,10 @@ import 'package:mangayomi/models/source_model.dart'; -List mmrcmsSourcesList = [ - - +List get mmrcmsSourcesList => _mmrcmsSourcesList; +List _mmrcmsSourcesList = [ // SourceModel( // sourceName: "Fallen Angels", - // url: "https://manga.fascans.com", + // baseUrl: "https://manga.fascans.com", // lang: "en", // typeSource: TypeSource.mmrcms, // logoUrl: '', @@ -13,7 +12,7 @@ List mmrcmsSourcesList = [ // dateFormatLocale: "en_US"), SourceModel( sourceName: "Scan FR", - url: "https://www.scan-fr.org", + baseUrl: "https://www.scan-fr.org", lang: "fr", typeSource: TypeSource.mmrcms, logoUrl: '', @@ -21,7 +20,7 @@ List mmrcmsSourcesList = [ dateFormatLocale: "en_US"), SourceModel( sourceName: "Scan VF", - url: "https://www.scan-vf.net", + baseUrl: "https://www.scan-vf.net", lang: "fr", typeSource: TypeSource.mmrcms, logoUrl: '', @@ -29,7 +28,7 @@ List mmrcmsSourcesList = [ dateFormatLocale: "en_US"), // SourceModel( sourceName: "Komikid", - url: "https://www.komikid.com", + baseUrl: "https://www.komikid.com", lang: "id", typeSource: TypeSource.mmrcms, logoUrl: '', @@ -37,7 +36,7 @@ List mmrcmsSourcesList = [ dateFormatLocale: "en_US"), // SourceModel( // sourceName: "MangaHanta", - // url: "http://mangahanta.com", + // baseUrl: "http://mangahanta.com", // lang: "tr", // typeSource: TypeSource.mmrcms, // logoUrl: '', @@ -45,7 +44,7 @@ List mmrcmsSourcesList = [ // dateFormatLocale: "en_US"), SourceModel( sourceName: "MangaID", - url: "https://mangaid.click", + baseUrl: "https://mangaid.click", lang: "id", typeSource: TypeSource.mmrcms, logoUrl: '', @@ -53,7 +52,7 @@ List mmrcmsSourcesList = [ dateFormatLocale: "en_US"), SourceModel( sourceName: "Jpmangas", - url: "https://jpmangas.cc", + baseUrl: "https://jpmangas.cc", lang: "fr", typeSource: TypeSource.mmrcms, logoUrl: '', diff --git a/lib/sources/src/multi/mmrcms/src/mmrcms.dart b/lib/sources/multisrc/mmrcms/src/mmrcms.dart similarity index 86% rename from lib/sources/src/multi/mmrcms/src/mmrcms.dart rename to lib/sources/multisrc/mmrcms/src/mmrcms.dart index d928edc2..4bb11fbc 100644 --- a/lib/sources/src/multi/mmrcms/src/mmrcms.dart +++ b/lib/sources/multisrc/mmrcms/src/mmrcms.dart @@ -3,20 +3,18 @@ import 'dart:convert'; import 'package:html/dom.dart'; import 'package:mangayomi/models/chapter.dart'; import 'package:mangayomi/services/http_service/http_service.dart'; -import 'package:mangayomi/sources/service/service.dart'; +import 'package:mangayomi/sources/service.dart'; import 'package:mangayomi/sources/utils/utils.dart'; import 'package:mangayomi/utils/reg_exp_matcher.dart'; class Mmrcms extends MangaYomiServices { @override - Future getMangaDetail( - {required String imageUrl, - required String url, - required String title, + Future getMangaDetail( + {required GetManga manga, required String lang, required String source}) async { - final dom = - await httpGet(url: url, source: source, resDom: true) as Document?; + final dom = await httpGet(url: manga.url!, source: source, resDom: true) + as Document?; description = dom! .querySelectorAll('.row .well p') .map((e) => e.text.trim()) @@ -73,9 +71,9 @@ class Mmrcms extends MangaYomiServices { final data = rrr.map((e) => e.outerHtml).toList(); if (source.toLowerCase() == 'jpmangas' || source.toLowerCase() == 'fr scan') { - imageUrl = regSrcMatcher(data.first).replaceAll('//', 'https://'); + manga.imageUrl = regSrcMatcher(data.first).replaceAll('//', 'https://'); } else { - imageUrl = regSrcMatcher(data.first); + manga.imageUrl = regSrcMatcher(data.first); } final ttt = dom @@ -101,16 +99,15 @@ class Mmrcms extends MangaYomiServices { chapterDate.add(parseDate(da, source)); } } - return mangadetailRes( - imageUrl: imageUrl, url: url, title: title, source: source); + return mangadetailRes(manga: manga, source: source); } @override - Future getPopularManga( + Future> getPopularManga( {required String source, required int page}) async { final dom = await httpGet( url: - '${getWpMangaUrl(source)}/filterList?page=$page&sortBy=views&asc=false', + '${getMangaBaseUrl(source)}/filterList?page=$page&sortBy=views&asc=false', source: source, resDom: true) as Document?; final urlElement = dom!.getElementsByClassName('chart-title'); @@ -132,20 +129,20 @@ class Mmrcms extends MangaYomiServices { } @override - Future searchManga( + Future> searchManga( {required String source, required String query}) async { final response = await httpGet( - url: '${getWpMangaUrl(source)}/search?query=${query.trim()}', + url: '${getMangaBaseUrl(source)}/search?query=${query.trim()}', source: source, resDom: false) as String?; final rep = jsonDecode(response!); for (var ok in rep['suggestions']) { if (source == 'Read Comics Online') { - url.add('${getWpMangaUrl(source)}/comic/${ok['data']}'); + url.add('${getMangaBaseUrl(source)}/comic/${ok['data']}'); } else if (source == 'Scan VF') { - url.add('${getWpMangaUrl(source)}/${ok['data']}'); + url.add('${getMangaBaseUrl(source)}/${ok['data']}'); } else { - url.add('${getWpMangaUrl(source)}/manga/${ok['data']}'); + url.add('${getMangaBaseUrl(source)}/manga/${ok['data']}'); } name.add(ok["value"]); image.add(''); @@ -163,7 +160,8 @@ class Mmrcms extends MangaYomiServices { if (dom!.querySelectorAll('#all > .img-responsive').isNotEmpty) { pageUrls = dom.querySelectorAll('#all > .img-responsive').map((e) { final RegExp regexx = RegExp(r'data-src="([^"]+)"'); - if (chapter.manga.value!.source!.toLowerCase() == 'fr scan') { + if (chapter.manga.value!.source!.toLowerCase() == 'fr scan' || + chapter.manga.value!.source!.toLowerCase() == 'jpmangas') { return regexx .allMatches(e.outerHtml) .first diff --git a/lib/sources/service/service.dart b/lib/sources/service.dart similarity index 63% rename from lib/sources/service/service.dart rename to lib/sources/service.dart index 67080878..762f2d09 100644 --- a/lib/sources/service/service.dart +++ b/lib/sources/service.dart @@ -5,29 +5,34 @@ abstract class MangaYomiServices { List name = []; List image = []; List genre = []; - String? author; - String? status; + String? author = ""; + String? status = ""; + List statusList = []; List chapterTitle = []; List chapterUrl = []; List chapterDate = []; - String? description; + String? description = ""; List chapters = []; List scanlators = []; List pageUrls = []; - - GetMangaModel mangaRes() { - return GetMangaModel( - name: name, - url: url, - image: image, - ); + List mangaList = []; + List mangaRes() { + for (var i = 0; i < name.length; i++) { + mangaList.add(GetManga( + genre: genre, + author: author, + status: statusList.isEmpty ? "" : statusList[i], + chapters: chapters, + imageUrl: image[i], + description: description, + url: url[i], + name: name[i], + source: "")); + } + return mangaList; } - GetMangaDetailModel mangadetailRes( - {required String imageUrl, - required String url, - required String title, - required String source}) { + GetManga mangadetailRes({required GetManga manga, required String source}) { if (chapterDate.isNotEmpty && chapterTitle.isNotEmpty && chapterUrl.isNotEmpty) { @@ -43,48 +48,31 @@ abstract class MangaYomiServices { mangaId: null)); } } - return GetMangaDetailModel( + return GetManga( status: status, genre: genre, author: author, description: description, - name: title, - url: url, + name: manga.name, + url: manga.url, source: source, - imageUrl: imageUrl, + imageUrl: manga.imageUrl, chapters: chapters, ); } - Future getPopularManga( + Future> getPopularManga( {required String source, required int page}); - Future getMangaDetail( - {required String imageUrl, - required String url, - required String title, - required String lang, - required String source}); + Future getMangaDetail( + {required GetManga manga, required String lang, required String source}); Future?> getMangaChapterUrl({ required Chapter chapter, }); - Future searchManga( + Future> searchManga( {required String source, required String query}); } - - -class GetMangaModel { - late List url; - late List name; - late List image; - GetMangaModel({ - required this.name, - required this.url, - required this.image, - }); -} - -class GetMangaDetailModel { +class GetManga { List genre = []; List chapters = []; String? author; @@ -94,7 +82,7 @@ class GetMangaDetailModel { String? name; String? imageUrl; String? description; - GetMangaDetailModel({ + GetManga({ required this.genre, required this.author, required this.status, diff --git a/lib/sources/source_list.dart b/lib/sources/source_list.dart index bbe2e4a0..b62d2106 100644 --- a/lib/sources/source_list.dart +++ b/lib/sources/source_list.dart @@ -1,10 +1,11 @@ import 'package:mangayomi/models/source_model.dart'; +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/src/multi/mangathemesia/mangathemesia_source_list.dart'; -import 'package:mangayomi/sources/src/multi/mmrcms/mmrcms_source_list.dart'; +import 'package:mangayomi/sources/multisrc/mangathemesia/mangathemesia_source_list.dart'; +import 'package:mangayomi/sources/multisrc/mmrcms/mmrcms_source_list.dart'; List get sourcesList => _sourcesList; List _sourcesList = [ @@ -13,5 +14,6 @@ List _sourcesList = [ ...mangathemesiaSourcesList, ...comickSourcesList, ...mmrcmsSourcesList, - japscanSource + japscanSource, + ...heanCmsSourcesList ]; diff --git a/lib/sources/src/all/comick/comick_source_list.dart b/lib/sources/src/all/comick/comick_source_list.dart index 1bbc58ff..212ea50e 100644 --- a/lib/sources/src/all/comick/comick_source_list.dart +++ b/lib/sources/src/all/comick/comick_source_list.dart @@ -1,12 +1,16 @@ import 'package:mangayomi/models/source_model.dart'; -String logoUrl = +const logoUrl = 'https://comick.app/_next/image?url=%2Fstatic%2Ficons%2Funicorn-64.png&w=144&q=75'; -String apiUrl = 'https://api.comick.fun/'; -List comickSourcesList = [ +const apiUrl = 'https://api.comick.fun/'; +const baseUrl = 'https://comick.app/'; + +List get comickSourcesList => _comickSourcesList; +List _comickSourcesList = [ SourceModel( sourceName: 'Comick', - url: apiUrl, + apiUrl: apiUrl, + baseUrl: baseUrl, lang: 'en', typeSource: TypeSource.comick, logoUrl: logoUrl, @@ -14,7 +18,8 @@ List comickSourcesList = [ dateFormatLocale: "en"), SourceModel( sourceName: 'Comick', - url: apiUrl, + apiUrl: apiUrl, + baseUrl: baseUrl, lang: 'ar', typeSource: TypeSource.comick, logoUrl: logoUrl, @@ -22,7 +27,8 @@ List comickSourcesList = [ dateFormatLocale: "en"), SourceModel( sourceName: 'Comick', - url: apiUrl, + apiUrl: apiUrl, + baseUrl: baseUrl, lang: 'pt', typeSource: TypeSource.comick, logoUrl: logoUrl, @@ -30,7 +36,8 @@ List comickSourcesList = [ dateFormatLocale: "en"), SourceModel( sourceName: 'Comick', - url: apiUrl, + apiUrl: apiUrl, + baseUrl: baseUrl, lang: 'pt-br', typeSource: TypeSource.comick, logoUrl: logoUrl, @@ -38,7 +45,8 @@ List comickSourcesList = [ dateFormatLocale: "en"), SourceModel( sourceName: 'Comick', - url: apiUrl, + apiUrl: apiUrl, + baseUrl: baseUrl, lang: 'it', typeSource: TypeSource.comick, logoUrl: logoUrl, @@ -46,7 +54,8 @@ List comickSourcesList = [ dateFormatLocale: "en"), SourceModel( sourceName: 'Comick', - url: apiUrl, + apiUrl: apiUrl, + baseUrl: baseUrl, lang: 'ru', typeSource: TypeSource.comick, logoUrl: logoUrl, @@ -54,7 +63,8 @@ List comickSourcesList = [ dateFormatLocale: "en"), SourceModel( sourceName: 'Comick', - url: apiUrl, + apiUrl: apiUrl, + baseUrl: baseUrl, lang: 'es', typeSource: TypeSource.comick, logoUrl: logoUrl, @@ -62,7 +72,8 @@ List comickSourcesList = [ dateFormatLocale: "en"), SourceModel( sourceName: 'Comick', - url: apiUrl, + apiUrl: apiUrl, + baseUrl: baseUrl, lang: 'es-419', typeSource: TypeSource.comick, logoUrl: logoUrl, @@ -70,7 +81,8 @@ List comickSourcesList = [ dateFormatLocale: "en"), SourceModel( sourceName: 'Comick', - url: apiUrl, + apiUrl: apiUrl, + baseUrl: baseUrl, lang: 'id', typeSource: TypeSource.comick, logoUrl: logoUrl, @@ -78,7 +90,8 @@ List comickSourcesList = [ dateFormatLocale: "en"), SourceModel( sourceName: 'Comick', - url: apiUrl, + apiUrl: apiUrl, + baseUrl: baseUrl, lang: 'hi', typeSource: TypeSource.comick, logoUrl: logoUrl, @@ -86,7 +99,8 @@ List comickSourcesList = [ dateFormatLocale: "en"), SourceModel( sourceName: 'Comick', - url: apiUrl, + apiUrl: apiUrl, + baseUrl: baseUrl, lang: 'de', typeSource: TypeSource.comick, logoUrl: logoUrl, @@ -94,7 +108,8 @@ List comickSourcesList = [ dateFormatLocale: "en"), SourceModel( sourceName: 'Comick', - url: apiUrl, + apiUrl: apiUrl, + baseUrl: baseUrl, lang: 'ja', typeSource: TypeSource.comick, logoUrl: logoUrl, @@ -102,7 +117,8 @@ List comickSourcesList = [ dateFormatLocale: "en"), SourceModel( sourceName: 'Comick', - url: apiUrl, + apiUrl: apiUrl, + baseUrl: baseUrl, lang: 'tr', typeSource: TypeSource.comick, logoUrl: logoUrl, @@ -110,7 +126,8 @@ List comickSourcesList = [ dateFormatLocale: "en"), SourceModel( sourceName: 'Comick', - url: apiUrl, + apiUrl: apiUrl, + baseUrl: baseUrl, lang: 'pl', typeSource: TypeSource.comick, logoUrl: logoUrl, @@ -118,7 +135,8 @@ List comickSourcesList = [ dateFormatLocale: "en"), SourceModel( sourceName: 'Comick', - url: apiUrl, + apiUrl: apiUrl, + baseUrl: baseUrl, lang: 'zh', typeSource: TypeSource.comick, logoUrl: logoUrl, @@ -126,7 +144,8 @@ List comickSourcesList = [ dateFormatLocale: "en"), SourceModel( sourceName: 'Comick', - url: apiUrl, + apiUrl: apiUrl, + baseUrl: baseUrl, lang: 'zh-hk', typeSource: TypeSource.comick, logoUrl: logoUrl, @@ -134,26 +153,11 @@ List comickSourcesList = [ dateFormatLocale: "en"), SourceModel( sourceName: 'Comick', - url: apiUrl, + apiUrl: apiUrl, + baseUrl: baseUrl, lang: 'fr', typeSource: TypeSource.comick, logoUrl: logoUrl, dateFormat: "yyyy-MM-dd'T'HH:mm:ss'Z'", dateFormatLocale: "en"), - SourceModel( - sourceName: "KomikLab", - url: "https://komiklab.com", - lang: "en", - typeSource: TypeSource.mangathemesia, - logoUrl: '', - dateFormat: "MMMM dd, yyyy", - dateFormatLocale: "en"), - SourceModel( - sourceName: "AnimatedGlitchedScans", - url: "https://anigliscans.com", - lang: "en", - typeSource: TypeSource.mangathemesia, - logoUrl: '', - dateFormat: "MMMM dd, yyyy", - dateFormatLocale: "en"), ]; diff --git a/lib/sources/src/all/comick/src/comick.dart b/lib/sources/src/all/comick/src/comick.dart index 9bb374ce..4c4147e8 100644 --- a/lib/sources/src/all/comick/src/comick.dart +++ b/lib/sources/src/all/comick/src/comick.dart @@ -1,19 +1,19 @@ import 'dart:convert'; import 'package:mangayomi/models/chapter.dart'; -import 'package:mangayomi/models/comick/chapter_page_comick.dart'; -import 'package:mangayomi/models/comick/manga_chapter_detail.dart'; -import 'package:mangayomi/models/comick/manga_detail_comick.dart'; -import 'package:mangayomi/models/comick/popular_manga_comick.dart'; -import 'package:mangayomi/models/comick/search_manga_cimick.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'; +import 'package:mangayomi/sources/src/all/comick/src/model/popular_manga_comick.dart'; +import 'package:mangayomi/sources/src/all/comick/src/model/search_manga_cimick.dart'; import 'package:mangayomi/services/http_service/http_service.dart'; -import 'package:mangayomi/sources/service/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'; class Comick extends MangaYomiServices { @override - Future getPopularManga( + Future> getPopularManga( {required String source, required int page}) async { source = source.toLowerCase(); final response = await httpGet( @@ -34,14 +34,12 @@ class Comick extends MangaYomiServices { } @override - Future getMangaDetail( - {required String imageUrl, - required String url, - required String title, + Future getMangaDetail( + {required GetManga manga, required String lang, required String source}) async { final response = await httpGet( - url: 'https://api.comick.fun$url?tachiyomi=true', + url: 'https://api.comick.fun${manga.url}?tachiyomi=true', source: source, resDom: false) as String?; var mangaDetail = jsonDecode(response!) as Map; @@ -86,12 +84,11 @@ class Comick extends MangaYomiServices { chapter.vol ?? "", chapter.chap ?? "", chapter.title ?? "", lang)); } - return mangadetailRes( - imageUrl: imageUrl, url: url, title: title, source: source); + return mangadetailRes(manga: manga, source: source); } @override - Future searchManga( + Future> searchManga( {required String source, required String query}) async { final response = await httpGet( url: diff --git a/lib/models/comick/chapter_page_comick.dart b/lib/sources/src/all/comick/src/model/chapter_page_comick.dart similarity index 100% rename from lib/models/comick/chapter_page_comick.dart rename to lib/sources/src/all/comick/src/model/chapter_page_comick.dart diff --git a/lib/models/comick/manga_chapter_detail.dart b/lib/sources/src/all/comick/src/model/manga_chapter_detail.dart similarity index 100% rename from lib/models/comick/manga_chapter_detail.dart rename to lib/sources/src/all/comick/src/model/manga_chapter_detail.dart diff --git a/lib/models/comick/manga_detail_comick.dart b/lib/sources/src/all/comick/src/model/manga_detail_comick.dart similarity index 100% rename from lib/models/comick/manga_detail_comick.dart rename to lib/sources/src/all/comick/src/model/manga_detail_comick.dart diff --git a/lib/models/comick/popular_manga_comick.dart b/lib/sources/src/all/comick/src/model/popular_manga_comick.dart similarity index 100% rename from lib/models/comick/popular_manga_comick.dart rename to lib/sources/src/all/comick/src/model/popular_manga_comick.dart diff --git a/lib/models/comick/search_manga_cimick.dart b/lib/sources/src/all/comick/src/model/search_manga_cimick.dart similarity index 100% rename from lib/models/comick/search_manga_cimick.dart rename to lib/sources/src/all/comick/src/model/search_manga_cimick.dart diff --git a/lib/sources/src/en/mangahere/mangahere_source.dart b/lib/sources/src/en/mangahere/mangahere_source.dart index fd0894b5..aca635f5 100644 --- a/lib/sources/src/en/mangahere/mangahere_source.dart +++ b/lib/sources/src/en/mangahere/mangahere_source.dart @@ -1,8 +1,10 @@ import 'package:mangayomi/models/source_model.dart'; -SourceModel mangahereSource = SourceModel( +SourceModel get mangahereSource => _mangahereSource; + +SourceModel _mangahereSource = SourceModel( sourceName: "MangaHere", - url: "http://www.mangahere.cc", + baseUrl: "http://www.mangahere.cc", lang: "en", typeSource: TypeSource.single, logoUrl: 'http://static.mangahere.cc/v20210106/mangahere/images/logo.png', diff --git a/lib/sources/src/en/mangahere/src/mangahere.dart b/lib/sources/src/en/mangahere/src/mangahere.dart index fcae3a05..a1972bdd 100644 --- a/lib/sources/src/en/mangahere/src/mangahere.dart +++ b/lib/sources/src/en/mangahere/src/mangahere.dart @@ -2,21 +2,19 @@ import 'package:flutter_js/flutter_js.dart'; import 'package:html/dom.dart'; import 'package:mangayomi/models/chapter.dart'; import 'package:mangayomi/services/http_service/http_service.dart'; -import 'package:mangayomi/sources/service/service.dart'; +import 'package:mangayomi/sources/service.dart'; import 'package:http/http.dart' as http; import 'package:html/dom.dart' as dom; import 'package:mangayomi/sources/utils/utils.dart'; class Mangahere extends MangaYomiServices { @override - Future getMangaDetail( - {required String imageUrl, - required String url, - required String title, + Future getMangaDetail( + {required GetManga manga, required String lang, required String source}) async { final dom = await httpGet( - url: "http://www.mangahere.cc$url", + url: "http://www.mangahere.cc${manga.url}", source: source, resDom: true) as Document?; if (dom! @@ -104,12 +102,11 @@ class Mangahere extends MangaYomiServices { genre.add(ok); } } - return mangadetailRes( - imageUrl: imageUrl, url: url, title: title, source: source); + return mangadetailRes(manga: manga, source: source); } @override - Future getPopularManga( + Future> getPopularManga( {required String source, required int page}) async { final dom = await httpGet( url: 'https://www.mangahere.cc/ranking/', @@ -145,11 +142,11 @@ class Mangahere extends MangaYomiServices { } @override - Future searchManga( + Future> searchManga( {required String source, required String query}) async { final dom = await httpGet( url: - '${getWpMangaUrl(source)}/search?title=${query.trim()}&genres=&nogenres=&sort=&stype=1&name=&type=0&author_method=cw&author=&artist_method=cw&artist=&rating_method=eq&rating=&released_method=eq&released=&st=0', + '${getMangaBaseUrl(source)}/search?title=${query.trim()}&genres=&nogenres=&sort=&stype=1&name=&type=0&author_method=cw&author=&artist_method=cw&artist=&rating_method=eq&rating=&released_method=eq&released=&st=0', source: source, resDom: true) as Document?; diff --git a/lib/sources/src/fr/japscan/japscan_source.dart b/lib/sources/src/fr/japscan/japscan_source.dart index c4eecba2..c7a04981 100644 --- a/lib/sources/src/fr/japscan/japscan_source.dart +++ b/lib/sources/src/fr/japscan/japscan_source.dart @@ -1,8 +1,10 @@ import 'package:mangayomi/models/source_model.dart'; -SourceModel japscanSource = SourceModel( +SourceModel get japscanSource => _japscanSource; + +SourceModel _japscanSource = SourceModel( sourceName: "Japscan", - url: "https://japscan.lol", + baseUrl: "https://japscan.lol", lang: "fr", typeSource: TypeSource.single, logoUrl: '', diff --git a/lib/sources/src/fr/japscan/src/japscan.dart b/lib/sources/src/fr/japscan/src/japscan.dart index 30e9dda2..1c1161e1 100644 --- a/lib/sources/src/fr/japscan/src/japscan.dart +++ b/lib/sources/src/fr/japscan/src/japscan.dart @@ -7,27 +7,25 @@ import 'package:html/dom.dart'; import 'package:mangayomi/models/chapter.dart'; import 'package:mangayomi/services/http_service/cloudflare/cloudflare_bypass.dart'; import 'package:mangayomi/services/http_service/http_service.dart'; -import 'package:mangayomi/sources/service/service.dart'; +import 'package:mangayomi/sources/service.dart'; import 'package:mangayomi/sources/utils/utils.dart'; import 'package:collection/collection.dart'; class Japscan extends MangaYomiServices { @override - Future getMangaDetail( - {required String imageUrl, - required String url, - required String title, + Future getMangaDetail( + {required GetManga manga, required String lang, required String source}) async { - final dom = - await httpGet(url: url, source: source, resDom: true) as Document?; + final dom = await httpGet(url: manga.url!, source: source, resDom: true) + 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); - imageUrl = 'https://www.japscan.lol$srcValue'; + manga.imageUrl = 'https://www.japscan.lol$srcValue'; if (dom.querySelectorAll('.col-7 > p').isNotEmpty) { final stat = dom @@ -98,12 +96,11 @@ class Japscan extends MangaYomiServices { chapterDate.add(parseDate(ok, source)); } } - return mangadetailRes( - imageUrl: imageUrl, url: url, title: title, source: source); + return mangadetailRes(manga: manga, source: source); } @override - Future getPopularManga( + Future> getPopularManga( {required String source, required int page}) async { final dom = await httpGet( url: "https://www.japscan.lol/", @@ -131,7 +128,7 @@ class Japscan extends MangaYomiServices { } @override - Future searchManga( + Future> searchManga( {required String source, required String query}) async { final dom = await httpGet( url: "https://www.google.com/search?q=${query.toLowerCase()}+japscan", diff --git a/lib/sources/src/fr/mangakawaii/mangakawaii_source.dart b/lib/sources/src/fr/mangakawaii/mangakawaii_source.dart index 710a6cce..9f6acbdf 100644 --- a/lib/sources/src/fr/mangakawaii/mangakawaii_source.dart +++ b/lib/sources/src/fr/mangakawaii/mangakawaii_source.dart @@ -1,8 +1,9 @@ import 'package:mangayomi/models/source_model.dart'; -SourceModel mangakawaiiSource = SourceModel( +SourceModel get mangakawaiiSource => _mangakawaiiSource; +SourceModel _mangakawaiiSource = SourceModel( sourceName: "MangaKawaii", - url: "https://www.mangakawaii.io", + baseUrl: "https://www.mangakawaii.io", lang: "fr", typeSource: TypeSource.single, logoUrl: 'https://www.mangakawaii.io/assets/img/logo.png', diff --git a/lib/sources/src/fr/mangakawaii/src/mangakawaii.dart b/lib/sources/src/fr/mangakawaii/src/mangakawaii.dart index c40577ea..6bacb101 100644 --- a/lib/sources/src/fr/mangakawaii/src/mangakawaii.dart +++ b/lib/sources/src/fr/mangakawaii/src/mangakawaii.dart @@ -2,16 +2,14 @@ import 'package:html/dom.dart'; import 'package:mangayomi/models/chapter.dart'; import 'package:mangayomi/services/http_service/http_res_to_dom_html.dart'; import 'package:mangayomi/services/http_service/http_service.dart'; -import 'package:mangayomi/sources/service/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'; class MangaKawaii extends MangaYomiServices { @override - Future getMangaDetail( - {required String imageUrl, - required String url, - required String title, + Future getMangaDetail( + {required GetManga manga, required String lang, required String source}) async { final dom = await httpGet( @@ -19,7 +17,7 @@ class MangaKawaii extends MangaYomiServices { source: source, resDom: true) as Document?; List detail = []; - imageUrl = + manga.imageUrl = "https://cdn.mangakawaii.pics/uploads$url/cover/cover_250x350.jpg"; if (dom!.querySelectorAll('dd.text-justify.text-break').isNotEmpty) { final tt = dom @@ -117,12 +115,11 @@ class MangaKawaii extends MangaYomiServices { } } } - return mangadetailRes( - imageUrl: imageUrl, url: url, title: title, source: source); + return mangadetailRes(manga: manga, source: source); } @override - Future getPopularManga( + Future> getPopularManga( {required String source, required int page}) async { final dom = await httpGet( url: 'https://www.mangakawaii.io/', @@ -146,7 +143,7 @@ class MangaKawaii extends MangaYomiServices { } @override - Future searchManga( + Future> searchManga( {required String source, required String query}) async { final dom = await httpGet( url: diff --git a/lib/sources/utils/utils.dart b/lib/sources/utils/utils.dart index d540fe42..e46433dc 100644 --- a/lib/sources/utils/utils.dart +++ b/lib/sources/utils/utils.dart @@ -2,17 +2,27 @@ import 'package:intl/intl.dart'; import 'package:mangayomi/models/source_model.dart'; import 'package:mangayomi/sources/source_list.dart'; -String getWpMangaUrl(String source) { +String getMangaBaseUrl(String source) { String url = ""; for (var i = 0; i < sourcesList.length; i++) { if (sourcesList[i].sourceName.toLowerCase() == source.toLowerCase()) { - url = sourcesList[i].url; + url = sourcesList[i].baseUrl; } } return url; } -TypeSource getWpMangTypeSource(String source) { +String getMangaAPIUrl(String source) { + String url = ""; + for (var i = 0; i < sourcesList.length; i++) { + if (sourcesList[i].sourceName.toLowerCase() == source.toLowerCase()) { + url = sourcesList[i].apiUrl; + } + } + return url; +} + +TypeSource getMangaTypeSource(String source) { TypeSource? typeSource; for (var i = 0; i < sourcesList.length; i++) { if (sourcesList[i].sourceName.toLowerCase() == source.toLowerCase()) { @@ -59,7 +69,15 @@ String utilDate(String data) { parseDate(String data, String source) { source = source.toLowerCase(); - DateTime date = DateFormat(getFormatDate(source), getFormatDateLocale(source)) - .parse(data); + final now = DateTime.now(); + DateTime? date; + if (data.toLowerCase() == "yesterday") { + date = DateTime(now.year, now.month, now.day - 1); + } else if (data.toLowerCase().contains("hour ago")) { + date = now; + } else { + date = DateFormat(getFormatDate(source), getFormatDateLocale(source)) + .parse(data); + } return date.millisecondsSinceEpoch.toString(); } diff --git a/lib/views/browse/extension/extension_screen.dart b/lib/views/browse/extension/extension_screen.dart index 0edf07f0..2aa9fc67 100644 --- a/lib/views/browse/extension/extension_screen.dart +++ b/lib/views/browse/extension/extension_screen.dart @@ -55,7 +55,8 @@ class ExtensionScreen extends ConsumerWidget { "${element.sourceName}${element.lang}", SourceModel( sourceName: element.sourceName, - url: element.url, + baseUrl: element.baseUrl, + apiUrl: element.apiUrl, lang: element.lang, typeSource: element.typeSource, isAdded: val, diff --git a/lib/views/browse/extension/refresh_filter_data.dart b/lib/views/browse/extension/refresh_filter_data.dart index ae85124a..4c98ec28 100644 --- a/lib/views/browse/extension/refresh_filter_data.dart +++ b/lib/views/browse/extension/refresh_filter_data.dart @@ -6,9 +6,8 @@ part 'refresh_filter_data.g.dart'; @riverpod refreshFilterData(RefreshFilterDataRef ref) async { - final lf = ref - .watch(hiveBoxMangaProvider) - .get("language_filter", defaultValue: []); + final lf = + ref.watch(hiveBoxMangaProvider).get("language_filter", defaultValue: []); if (lf.isEmpty) { for (var element in sourcesList) { final sP = ref.watch(hiveBoxMangaSourceProvider); @@ -20,7 +19,8 @@ refreshFilterData(RefreshFilterDataRef ref) async { "${element.sourceName}${element.lang}", SourceModel( sourceName: element.sourceName, - url: element.url, + baseUrl: element.baseUrl, + apiUrl: element.apiUrl, lang: element.lang, typeSource: element.typeSource, logoUrl: element.logoUrl, @@ -47,7 +47,8 @@ refreshFilterData(RefreshFilterDataRef ref) async { "${element.sourceName}${element.lang}", SourceModel( sourceName: element.sourceName, - url: element.url, + baseUrl: element.baseUrl, + apiUrl: element.apiUrl, lang: element.lang, typeSource: element.typeSource, logoUrl: element.logoUrl, diff --git a/lib/views/browse/extension/refresh_filter_data.g.dart b/lib/views/browse/extension/refresh_filter_data.g.dart index 5c494d2a..d2ae785f 100644 --- a/lib/views/browse/extension/refresh_filter_data.g.dart +++ b/lib/views/browse/extension/refresh_filter_data.g.dart @@ -6,7 +6,7 @@ part of 'refresh_filter_data.dart'; // RiverpodGenerator // ************************************************************************** -String _$refreshFilterDataHash() => r'60c9569f6062e6f951b735873f92a89885cc5964'; +String _$refreshFilterDataHash() => r'03aed46bb9e7b0ee3d7e99b99784d3080751895b'; /// See also [refreshFilterData]. @ProviderFor(refreshFilterData) diff --git a/lib/views/browse/global_search_screen.dart b/lib/views/browse/global_search_screen.dart index e0ad631d..8e8fafe3 100644 --- a/lib/views/browse/global_search_screen.dart +++ b/lib/views/browse/global_search_screen.dart @@ -9,6 +9,7 @@ import 'package:mangayomi/providers/hive_provider.dart'; import 'package:mangayomi/services/get_manga_detail.dart'; import 'package:mangayomi/services/search_manga.dart'; import 'package:mangayomi/models/source_model.dart'; +import 'package:mangayomi/sources/service.dart'; import 'package:mangayomi/utils/cached_network.dart'; import 'package:mangayomi/utils/headers.dart'; import 'package:mangayomi/utils/lang.dart'; @@ -121,15 +122,13 @@ class SourceSearchScreen extends ConsumerWidget { error: (error, stackTrace) => Center(child: Text(error.toString())), data: (data) { - if (data.name.isNotEmpty) { + if (data.isNotEmpty) { return ListView.builder( scrollDirection: Axis.horizontal, - itemCount: data.name.length, + itemCount: data.length, itemBuilder: (context, index) { return MangaGlobalImageCard( - url: data.url[index]!, - name: data.name[index]!, - image: data.image[index]!, + manga: data[index]!, source: source.sourceName, lang: source.lang, ); @@ -148,16 +147,12 @@ class SourceSearchScreen extends ConsumerWidget { } class MangaGlobalImageCard extends ConsumerStatefulWidget { - final String image; - final String url; - final String name; + final GetManga manga; final String source; final String lang; const MangaGlobalImageCard({ super.key, - required this.url, - required this.name, - required this.image, + required this.manga, required this.source, required this.lang, }); @@ -173,11 +168,7 @@ class _MangaGlobalImageCardState extends ConsumerState Widget build(BuildContext context) { super.build(context); final getMangaDetail = ref.watch(getMangaDetailProvider( - source: widget.source, - imageUrl: widget.image, - title: widget.name, - url: widget.url, - lang: widget.lang)); + source: widget.source, manga: widget.manga, lang: widget.lang)); return getMangaDetail.when( data: (data) { @@ -237,7 +228,7 @@ class _MangaGlobalImageCardState extends ConsumerState fit: BoxFit.fill), BottomTextWidget( fontSize: 12.0, - text: widget.name, + text: widget.manga.name!, isLoading: true, isComfortableGrid: true, ) @@ -258,7 +249,7 @@ class _MangaGlobalImageCardState extends ConsumerState ), BottomTextWidget( fontSize: 12.0, - text: widget.name, + text: widget.manga.name!, isLoading: true, isComfortableGrid: true, ) diff --git a/lib/views/manga/detail/manga_detail_main.dart b/lib/views/manga/detail/manga_detail_main.dart index b5cca3cb..23435786 100644 --- a/lib/views/manga/detail/manga_detail_main.dart +++ b/lib/views/manga/detail/manga_detail_main.dart @@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:mangayomi/main.dart'; import 'package:mangayomi/models/chapter.dart'; import 'package:mangayomi/services/get_manga_detail.dart'; +import 'package:mangayomi/sources/service.dart'; import 'package:mangayomi/views/manga/detail/manga_details_view.dart'; import 'package:mangayomi/views/manga/detail/providers/isar_providers.dart'; import 'package:mangayomi/views/widgets/error_text.dart'; @@ -40,25 +41,33 @@ class _MangaReaderDetailState extends ConsumerState { ref.watch(getMangaDetailStreamProvider(mangaId: widget.mangaId)); return Scaffold( body: manga.when( - data: (modelManga) { + data: (manga) { return RefreshIndicator( onRefresh: () async { + final mangaS = GetManga( + genre: manga.genre!, + author: manga.author, + status: manga.status, + chapters: manga.chapters.toList(), + imageUrl: manga.imageUrl, + description: manga.description, + url: manga.link, + name: manga.name, + source: manga.source); bool isOk = false; ref .watch(getMangaDetailProvider( - imageUrl: modelManga.imageUrl!, - lang: modelManga.lang!, - title: modelManga.name!, - source: modelManga.source!, - url: modelManga.link!) - .future) + manga: mangaS, + lang: manga.lang!, + source: manga.source!, + ).future) .then((value) async { if (value.chapters.isNotEmpty && - value.chapters.length > modelManga.chapters.length) { + value.chapters.length > manga.chapters.length) { await isar.writeTxn(() async { int newChapsIndex = - value.chapters.length - modelManga.chapters.length; - modelManga.lastUpdate = DateTime.now().millisecondsSinceEpoch; + value.chapters.length - manga.chapters.length; + manga.lastUpdate = DateTime.now().millisecondsSinceEpoch; for (var i = 0; i < newChapsIndex; i++) { final chapters = Chapter( name: value.chapters[i].name, @@ -68,8 +77,8 @@ class _MangaReaderDetailState extends ConsumerState { scanlator: value.chapters[i].scanlator, isRead: false, lastPageRead: '', - mangaId: modelManga.id) - ..manga.value = modelManga; + mangaId: manga.id) + ..manga.value = manga; await isar.chapters.put(chapters); await chapters.manga.save(); } @@ -90,7 +99,7 @@ class _MangaReaderDetailState extends ConsumerState { }); }, child: MangaDetailsView( - manga: modelManga!, + manga: manga!, ), ); }, diff --git a/lib/views/manga/home/manga_home_screen.dart b/lib/views/manga/home/manga_home_screen.dart index dd2715b6..3b719aa4 100644 --- a/lib/views/manga/home/manga_home_screen.dart +++ b/lib/views/manga/home/manga_home_screen.dart @@ -5,6 +5,7 @@ import 'package:go_router/go_router.dart'; import 'package:mangayomi/models/manga_type.dart'; import 'package:mangayomi/services/get_manga_detail.dart'; import 'package:mangayomi/services/get_popular_manga.dart'; +import 'package:mangayomi/sources/service.dart'; import 'package:mangayomi/sources/utils/utils.dart'; import 'package:mangayomi/utils/colors.dart'; import 'package:mangayomi/views/manga/home/manga_search_screen.dart'; @@ -39,7 +40,7 @@ class _MangaHomeScreenState extends ConsumerState { IconButton( onPressed: () { Map data = { - 'url': getWpMangaUrl(widget.mangaType.source!), + 'url': getMangaBaseUrl(widget.mangaType.source!), 'source': widget.mangaType.source!, }; context.push("/mangawebview", extra: data); @@ -54,7 +55,7 @@ class _MangaHomeScreenState extends ConsumerState { ), body: getManga.when( data: (data) { - if (data.url.isEmpty) { + if (data.isEmpty) { return const Center(child: Text("No result")); } _scrollController.addListener(() { @@ -91,9 +92,7 @@ class _MangaHomeScreenState extends ConsumerState { (value) { if (mounted) { setState(() { - data.url.addAll(value.url); - data.name.addAll(value.name); - data.image.addAll(value.image); + data.addAll(value); _isLoading = false; }); } @@ -103,9 +102,8 @@ class _MangaHomeScreenState extends ConsumerState { } } }); - final length = widget.mangaType.isFullData! - ? _fullDataLength - : data.url.length; + final length = + widget.mangaType.isFullData! ? _fullDataLength : data.length; return Column( children: [ Flexible( @@ -117,9 +115,7 @@ class _MangaHomeScreenState extends ConsumerState { return _buildProgressIndicator(); } return MangaHomeImageCard( - url: data.url[index]!, - name: data.name[index]!, - image: data.image[index]!, + manga: data[index]!, source: widget.mangaType.source!, lang: widget.mangaType.lang!, ); @@ -151,16 +147,12 @@ class _MangaHomeScreenState extends ConsumerState { } class MangaHomeImageCard extends ConsumerStatefulWidget { - final String image; - final String url; - final String name; + final GetManga manga; final String source; final String lang; const MangaHomeImageCard({ super.key, - required this.url, - required this.name, - required this.image, + required this.manga, required this.source, required this.lang, }); @@ -175,11 +167,7 @@ class _MangaHomeImageCardState extends ConsumerState Widget build(BuildContext context) { super.build(context); final getMangaDetail = ref.watch(getMangaDetailProvider( - source: widget.source, - imageUrl: widget.image, - title: widget.name, - url: widget.url, - lang: widget.lang)); + source: widget.source, manga: widget.manga, lang: widget.lang)); return getMangaDetail.when( data: (data) { @@ -198,7 +186,7 @@ class _MangaHomeImageCardState extends ConsumerState ), ), BottomTextWidget( - text: widget.name, + text: widget.manga.name!, isLoading: true, ) ]), diff --git a/lib/views/manga/home/manga_search_screen.dart b/lib/views/manga/home/manga_search_screen.dart index 34724bca..adef571c 100644 --- a/lib/views/manga/home/manga_search_screen.dart +++ b/lib/views/manga/home/manga_search_screen.dart @@ -114,14 +114,12 @@ class SearchResultScreen extends ConsumerWidget { ), error: (error, stackTrace) => Center(child: Text(error.toString())), data: (data) { - if (data.name.isNotEmpty) { + if (data.isNotEmpty) { return GridViewWidget( - itemCount: data.name.length, + itemCount: data.length, itemBuilder: (context, index) { return MangaHomeImageCard( - url: data.url[index]!, - name: data.name[index]!, - image: data.image[index]!, + manga: data[index]!, source: source, lang: lang, ); diff --git a/lib/views/widgets/manga_image_card_widget.dart b/lib/views/widgets/manga_image_card_widget.dart index 12cf187c..47ef7215 100644 --- a/lib/views/widgets/manga_image_card_widget.dart +++ b/lib/views/widgets/manga_image_card_widget.dart @@ -5,7 +5,7 @@ import 'package:mangayomi/main.dart'; import 'package:mangayomi/models/chapter.dart'; import 'package:mangayomi/models/manga.dart'; import 'package:mangayomi/services/get_manga_detail.dart'; -import 'package:mangayomi/sources/service/service.dart'; +import 'package:mangayomi/sources/service.dart'; import 'package:mangayomi/utils/cached_network.dart'; import 'package:mangayomi/utils/headers.dart'; import 'package:mangayomi/views/widgets/bottom_text_widget.dart'; @@ -15,7 +15,7 @@ class MangaImageCardWidget extends StatelessWidget { final String lang; final bool isLoading; - final GetMangaDetailModel? getMangaDetailModel; + final GetManga? getMangaDetailModel; const MangaImageCardWidget({ required this.lang,