refactor code & add HeanCms source

This commit is contained in:
kodjomoustapha 2023-05-13 11:30:13 +01:00
parent cd20e55e62
commit d23624c39b
44 changed files with 714 additions and 386 deletions

View file

@ -1,3 +1,6 @@
{
"java.configuration.updateBuildConfiguration": "automatic"
"java.configuration.updateBuildConfiguration": "automatic",
"githubPullRequests.ignoredPullRequestBranches": [
"main"
]
}

View file

@ -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
}

View file

@ -18,7 +18,7 @@ class SourceModelAdapter extends TypeAdapter<SourceModel> {
};
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<SourceModel> {
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<SourceModel> {
..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<TypeSource> {
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<TypeSource> {
case TypeSource.mmrcms:
writer.writeByte(4);
break;
case TypeSource.heancms:
writer.writeByte(5);
break;
}
}

View file

@ -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<GetMangaChapterUrlModel> 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<GetMangaChapterUrlModel> 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<GetMangaChapterUrlModel> 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<GetMangaChapterUrlModel> 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(

View file

@ -7,7 +7,7 @@ part of 'get_manga_chapter_url.dart';
// **************************************************************************
String _$getMangaChapterUrlHash() =>
r'4daf1dc296255c64ca0ee2cf963dd98b3595d93c';
r'066c4d826fd17ba3d3682d806778fe1010378c05';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -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<GetMangaDetailModel> getMangaDetail(GetMangaDetailRef ref,
{required String imageUrl,
required String url,
required String title,
Future<GetManga> 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<GetMangaDetailModel> 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!;
}

View file

@ -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<GetMangaDetailModel>;
typedef GetMangaDetailRef = AutoDisposeFutureProviderRef<GetManga>;
/// See also [getMangaDetail].
@ProviderFor(getMangaDetail)
const getMangaDetailProvider = GetMangaDetailFamily();
/// See also [getMangaDetail].
class GetMangaDetailFamily extends Family<AsyncValue<GetMangaDetailModel>> {
class GetMangaDetailFamily extends Family<AsyncValue<GetManga>> {
/// 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<AsyncValue<GetMangaDetailModel>> {
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<AsyncValue<GetMangaDetailModel>> {
}
/// See also [getMangaDetail].
class GetMangaDetailProvider
extends AutoDisposeFutureProvider<GetMangaDetailModel> {
class GetMangaDetailProvider extends AutoDisposeFutureProvider<GetManga> {
/// 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);

View file

@ -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<GetMangaModel> getPopularManga(GetPopularMangaRef ref,
Future<List<GetManga?>> getPopularManga(GetPopularMangaRef ref,
{required String source, required int page}) async {
GetMangaModel? popularManga;
List<GetManga?>? 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<GetMangaModel> 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<GetMangaModel> 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!;
}

View file

@ -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<GetMangaModel>;
typedef GetPopularMangaRef = AutoDisposeFutureProviderRef<List<GetManga?>>;
/// See also [getPopularManga].
@ProviderFor(getPopularManga)
const getPopularMangaProvider = GetPopularMangaFamily();
/// See also [getPopularManga].
class GetPopularMangaFamily extends Family<AsyncValue<GetMangaModel>> {
class GetPopularMangaFamily extends Family<AsyncValue<List<GetManga?>>> {
/// See also [getPopularManga].
const GetPopularMangaFamily();
@ -77,7 +77,8 @@ class GetPopularMangaFamily extends Family<AsyncValue<GetMangaModel>> {
}
/// See also [getPopularManga].
class GetPopularMangaProvider extends AutoDisposeFutureProvider<GetMangaModel> {
class GetPopularMangaProvider
extends AutoDisposeFutureProvider<List<GetManga?>> {
/// See also [getPopularManga].
GetPopularMangaProvider({
required this.source,

View file

@ -3,10 +3,6 @@ import 'package:http/http.dart' as http;
Future<Document> httpResToDom(
{required String url, required Map<String, String>? 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);
}

View file

@ -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<GetMangaModel> searchManga(SearchMangaRef ref,
Future<List<GetManga?>> searchManga(SearchMangaRef ref,
{required String source, required String query}) async {
GetMangaModel? manga;
List<GetManga?>? 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<GetMangaModel> 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<GetMangaModel> 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<GetMangaModel> 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!;
}

View file

@ -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<GetMangaModel>;
typedef SearchMangaRef = AutoDisposeFutureProviderRef<List<GetManga?>>;
/// See also [searchManga].
@ProviderFor(searchManga)
const searchMangaProvider = SearchMangaFamily();
/// See also [searchManga].
class SearchMangaFamily extends Family<AsyncValue<GetMangaModel>> {
class SearchMangaFamily extends Family<AsyncValue<List<GetManga?>>> {
/// See also [searchManga].
const SearchMangaFamily();
@ -77,7 +77,7 @@ class SearchMangaFamily extends Family<AsyncValue<GetMangaModel>> {
}
/// See also [searchManga].
class SearchMangaProvider extends AutoDisposeFutureProvider<GetMangaModel> {
class SearchMangaProvider extends AutoDisposeFutureProvider<List<GetManga?>> {
/// See also [searchManga].
SearchMangaProvider({
required this.source,

View file

@ -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<String, String> _headers(String source) => {
'Origin': getMangaBaseUrl(source),
'Referer': getMangaAPIUrl(source),
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
};
@override
Future<List<dynamic>> 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<String, dynamic>;
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<GetManga?> 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<String, dynamic>;
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<List<GetManga>> 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>? 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) {
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<List<GetManga?>> 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>? 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) {
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();
}
}

View file

@ -0,0 +1,15 @@
import 'package:mangayomi/models/source_model.dart';
List<SourceModel> get heanCmsSourcesList => _heanCmsSourcesList;
List<SourceModel> _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"),
];

View file

@ -0,0 +1,136 @@
class HeanCmsSearchModel {
Meta? meta;
List<Data>? data;
HeanCmsSearchModel({this.meta, this.data});
HeanCmsSearchModel.fromJson(Map<String, dynamic> json) {
meta = json['meta'] != null ? Meta.fromJson(json['meta']) : null;
if (json['data'] != null) {
data = <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<String, dynamic> 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>? 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<String, dynamic> 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 = <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<String, dynamic> 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<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
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;
}
}

View file

@ -0,0 +1,2 @@
RegExp timeStampRegex = RegExp("-\\d+");

View file

@ -1,9 +1,10 @@
import 'package:mangayomi/models/source_model.dart';
List<SourceModel> mangathemesiaSourcesList = [
List<SourceModel> get mangathemesiaSourcesList => _mangathemesiaSourcesList;
List<SourceModel> _mangathemesiaSourcesList = [
SourceModel(
sourceName: "KomikLab",
url: "https://komiklab.com",
baseUrl: "https://komiklab.com",
lang: "en",
typeSource: TypeSource.mangathemesia,
logoUrl: '',
@ -11,7 +12,7 @@ List<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> mangathemesiaSourcesList = [
// SourceModel(
// sourceName: "Kiryuu",
// url: "https://kiryuu.id",
// baseUrl: "https://kiryuu.id",
// lang: "id",
// typeSource: TypeSource.mangathemesia,
// logoUrl: '',
@ -107,7 +108,7 @@ List<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> mangathemesiaSourcesList = [
// dateFormatLocale: "en"),
SourceModel(
sourceName: "xCaliBRScans",
url: "https://xcalibrscans.com",
baseUrl: "https://xcalibrscans.com",
lang: "en",
typeSource: TypeSource.mangathemesia,
logoUrl:

View file

@ -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<GetMangaDetailModel?> getMangaDetail(
{required String imageUrl,
required String url,
required String title,
Future<GetManga?> 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<GetMangaModel?> getPopularManga(
Future<List<GetManga?>> 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<GetMangaModel?> searchManga(
Future<List<GetManga?>> 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!

View file

@ -1,11 +1,10 @@
import 'package:mangayomi/models/source_model.dart';
List<SourceModel> mmrcmsSourcesList = [
List<SourceModel> get mmrcmsSourcesList => _mmrcmsSourcesList;
List<SourceModel> _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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> 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<SourceModel> mmrcmsSourcesList = [
dateFormatLocale: "en_US"),
SourceModel(
sourceName: "Jpmangas",
url: "https://jpmangas.cc",
baseUrl: "https://jpmangas.cc",
lang: "fr",
typeSource: TypeSource.mmrcms,
logoUrl: '',

View file

@ -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<GetMangaDetailModel?> getMangaDetail(
{required String imageUrl,
required String url,
required String title,
Future<GetManga?> 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<GetMangaModel?> getPopularManga(
Future<List<GetManga?>> 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<GetMangaModel?> searchManga(
Future<List<GetManga?>> 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

View file

@ -5,29 +5,34 @@ abstract class MangaYomiServices {
List<String?> name = [];
List<String?> image = [];
List<String> genre = [];
String? author;
String? status;
String? author = "";
String? status = "";
List<String> statusList = [];
List<String> chapterTitle = [];
List<String> chapterUrl = [];
List<String> chapterDate = [];
String? description;
String? description = "";
List<Chapter> chapters = [];
List<String> scanlators = [];
List pageUrls = [];
GetMangaModel mangaRes() {
return GetMangaModel(
name: name,
url: url,
image: image,
);
List<GetManga> mangaList = [];
List<GetManga> 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<GetMangaModel?> getPopularManga(
Future<List<GetManga?>> getPopularManga(
{required String source, required int page});
Future<GetMangaDetailModel?> getMangaDetail(
{required String imageUrl,
required String url,
required String title,
required String lang,
required String source});
Future<GetManga?> getMangaDetail(
{required GetManga manga, required String lang, required String source});
Future<List<dynamic>?> getMangaChapterUrl({
required Chapter chapter,
});
Future<GetMangaModel?> searchManga(
Future<List<GetManga?>> searchManga(
{required String source, required String query});
}
class GetMangaModel {
late List<String?> url;
late List<String?> name;
late List<String?> image;
GetMangaModel({
required this.name,
required this.url,
required this.image,
});
}
class GetMangaDetailModel {
class GetManga {
List<String> genre = [];
List<Chapter> 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,

View file

@ -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<SourceModel> get sourcesList => _sourcesList;
List<SourceModel> _sourcesList = [
@ -13,5 +14,6 @@ List<SourceModel> _sourcesList = [
...mangathemesiaSourcesList,
...comickSourcesList,
...mmrcmsSourcesList,
japscanSource
japscanSource,
...heanCmsSourcesList
];

View file

@ -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<SourceModel> comickSourcesList = [
const apiUrl = 'https://api.comick.fun/';
const baseUrl = 'https://comick.app/';
List<SourceModel> get comickSourcesList => _comickSourcesList;
List<SourceModel> _comickSourcesList = [
SourceModel(
sourceName: 'Comick',
url: apiUrl,
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'en',
typeSource: TypeSource.comick,
logoUrl: logoUrl,
@ -14,7 +18,8 @@ List<SourceModel> comickSourcesList = [
dateFormatLocale: "en"),
SourceModel(
sourceName: 'Comick',
url: apiUrl,
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'ar',
typeSource: TypeSource.comick,
logoUrl: logoUrl,
@ -22,7 +27,8 @@ List<SourceModel> comickSourcesList = [
dateFormatLocale: "en"),
SourceModel(
sourceName: 'Comick',
url: apiUrl,
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'pt',
typeSource: TypeSource.comick,
logoUrl: logoUrl,
@ -30,7 +36,8 @@ List<SourceModel> 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<SourceModel> comickSourcesList = [
dateFormatLocale: "en"),
SourceModel(
sourceName: 'Comick',
url: apiUrl,
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'it',
typeSource: TypeSource.comick,
logoUrl: logoUrl,
@ -46,7 +54,8 @@ List<SourceModel> comickSourcesList = [
dateFormatLocale: "en"),
SourceModel(
sourceName: 'Comick',
url: apiUrl,
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'ru',
typeSource: TypeSource.comick,
logoUrl: logoUrl,
@ -54,7 +63,8 @@ List<SourceModel> comickSourcesList = [
dateFormatLocale: "en"),
SourceModel(
sourceName: 'Comick',
url: apiUrl,
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'es',
typeSource: TypeSource.comick,
logoUrl: logoUrl,
@ -62,7 +72,8 @@ List<SourceModel> 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<SourceModel> comickSourcesList = [
dateFormatLocale: "en"),
SourceModel(
sourceName: 'Comick',
url: apiUrl,
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'id',
typeSource: TypeSource.comick,
logoUrl: logoUrl,
@ -78,7 +90,8 @@ List<SourceModel> comickSourcesList = [
dateFormatLocale: "en"),
SourceModel(
sourceName: 'Comick',
url: apiUrl,
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'hi',
typeSource: TypeSource.comick,
logoUrl: logoUrl,
@ -86,7 +99,8 @@ List<SourceModel> comickSourcesList = [
dateFormatLocale: "en"),
SourceModel(
sourceName: 'Comick',
url: apiUrl,
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'de',
typeSource: TypeSource.comick,
logoUrl: logoUrl,
@ -94,7 +108,8 @@ List<SourceModel> comickSourcesList = [
dateFormatLocale: "en"),
SourceModel(
sourceName: 'Comick',
url: apiUrl,
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'ja',
typeSource: TypeSource.comick,
logoUrl: logoUrl,
@ -102,7 +117,8 @@ List<SourceModel> comickSourcesList = [
dateFormatLocale: "en"),
SourceModel(
sourceName: 'Comick',
url: apiUrl,
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'tr',
typeSource: TypeSource.comick,
logoUrl: logoUrl,
@ -110,7 +126,8 @@ List<SourceModel> comickSourcesList = [
dateFormatLocale: "en"),
SourceModel(
sourceName: 'Comick',
url: apiUrl,
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'pl',
typeSource: TypeSource.comick,
logoUrl: logoUrl,
@ -118,7 +135,8 @@ List<SourceModel> comickSourcesList = [
dateFormatLocale: "en"),
SourceModel(
sourceName: 'Comick',
url: apiUrl,
apiUrl: apiUrl,
baseUrl: baseUrl,
lang: 'zh',
typeSource: TypeSource.comick,
logoUrl: logoUrl,
@ -126,7 +144,8 @@ List<SourceModel> 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<SourceModel> 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"),
];

View file

@ -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<GetMangaModel?> getPopularManga(
Future<List<GetManga?>> 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<GetMangaDetailModel?> getMangaDetail(
{required String imageUrl,
required String url,
required String title,
Future<GetManga?> 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<String, dynamic>;
@ -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<GetMangaModel> searchManga(
Future<List<GetManga?>> searchManga(
{required String source, required String query}) async {
final response = await httpGet(
url:

View file

@ -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',

View file

@ -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<GetMangaDetailModel?> getMangaDetail(
{required String imageUrl,
required String url,
required String title,
Future<GetManga?> 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<GetMangaModel?> getPopularManga(
Future<List<GetManga?>> 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<GetMangaModel?> searchManga(
Future<List<GetManga?>> 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?;

View file

@ -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: '',

View file

@ -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<GetMangaDetailModel?> getMangaDetail(
{required String imageUrl,
required String url,
required String title,
Future<GetManga?> 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<GetMangaModel?> getPopularManga(
Future<List<GetManga?>> 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<GetMangaModel?> searchManga(
Future<List<GetManga?>> searchManga(
{required String source, required String query}) async {
final dom = await httpGet(
url: "https://www.google.com/search?q=${query.toLowerCase()}+japscan",

View file

@ -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',

View file

@ -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<GetMangaDetailModel?> getMangaDetail(
{required String imageUrl,
required String url,
required String title,
Future<GetManga?> 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<GetMangaModel?> getPopularManga(
Future<List<GetManga?>> 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<GetMangaModel?> searchManga(
Future<List<GetManga?>> searchManga(
{required String source, required String query}) async {
final dom = await httpGet(
url:

View file

@ -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();
}

View file

@ -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,

View file

@ -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,

View file

@ -6,7 +6,7 @@ part of 'refresh_filter_data.dart';
// RiverpodGenerator
// **************************************************************************
String _$refreshFilterDataHash() => r'60c9569f6062e6f951b735873f92a89885cc5964';
String _$refreshFilterDataHash() => r'03aed46bb9e7b0ee3d7e99b99784d3080751895b';
/// See also [refreshFilterData].
@ProviderFor(refreshFilterData)

View file

@ -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<MangaGlobalImageCard>
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<MangaGlobalImageCard>
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<MangaGlobalImageCard>
),
BottomTextWidget(
fontSize: 12.0,
text: widget.name,
text: widget.manga.name!,
isLoading: true,
isComfortableGrid: true,
)

View file

@ -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<MangaReaderDetail> {
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<MangaReaderDetail> {
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<MangaReaderDetail> {
});
},
child: MangaDetailsView(
manga: modelManga!,
manga: manga!,
),
);
},

View file

@ -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<MangaHomeScreen> {
IconButton(
onPressed: () {
Map<String, String> 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<MangaHomeScreen> {
),
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<MangaHomeScreen> {
(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<MangaHomeScreen> {
}
}
});
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<MangaHomeScreen> {
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<MangaHomeScreen> {
}
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<MangaHomeImageCard>
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<MangaHomeImageCard>
),
),
BottomTextWidget(
text: widget.name,
text: widget.manga.name!,
isLoading: true,
)
]),

View file

@ -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,
);

View file

@ -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,