search method Null safety
Search for manga
Optional arguments are mangaName
(String), authors
, includedTags
, excludedTags
, status
& demographic
( All List<String>)
status
MUST BE ONE OF ["ongoing","completed","hiatus","cancelled"]
For more info see the official documentation
Returns an empty List<String> if no results
Implementation
Future<List<Manga>> search(
{String mangaTitle = '',
List<String> authors = const [],
List<String> includedTags = const [],
List<String> excludedTags = const [],
List<String> status = const [],
List<String> demographic = const [],
bool useLogin = false}) async {
var res;
if (token != '' && useLogin) {
res = await http.get(
Uri.parse(
'https://api.mangadex.org/manga?title=&includes[]=author&includes[]=artist&includes[]=cover_art$mangaTitle${(authors.isNotEmpty) ? '&authors[]=${authors.join('&authors[]=')}' : ''}${(includedTags.isNotEmpty) ? '&includedTags[]=${includedTags.join('&includedTags[]=')}' : ''}${(excludedTags.isNotEmpty) ? '&excludedTags[]=${excludedTags.join('&excludedTags[]=')}' : ''}${(status.isNotEmpty) ? '&status[]=${status.join('&status[]=')}' : ''}${(demographic.isNotEmpty) ? '&publicationDemographic[]=${demographic.join('&publicationDemographic[]=')}' : ''}'),
headers: {
HttpHeaders.authorizationHeader: 'Bearer $token',
HttpHeaders.userAgentHeader: 'mangadex_dart_api/1.0'
});
} else {
res = await http.get(
Uri.parse(
'https://api.mangadex.org/manga?title=$mangaTitle&includes[]=author&includes[]=artist&includes[]=cover_art${(authors.isNotEmpty) ? '&authors[]=${authors.join('&authors[]=')}' : ''}${(includedTags.isNotEmpty) ? '&includedTags[]=${includedTags.join('&includedTags[]=')}' : ''}${(excludedTags.isNotEmpty) ? '&excludedTags[]=${excludedTags.join('&excludedTags[]=')}' : ''}${(status.isNotEmpty) ? '&status[]=${status.join('&status[]=')}' : ''}${(demographic.isNotEmpty) ? '&publicationDemographic[]=${demographic.join('&publicationDemographic[]=')}' : ''}'),
headers: {HttpHeaders.userAgentHeader: 'mangadex_dart_api/1.0'});
}
var data = jsonDecode(res.body);
if (res.statusCode == 403 && res.headers['X-Captcha-Sitekey'] != null) {
throw CaptchaException(res.headers['X-Captcha-Sitekey'],
message:
'You need to solve a captcha, check `.sitekey` for the sitekey.');
}
if (res.statusCode == 400) {
throw 'Error: ${data["errors"][0]["title"]} - ${data["errors"][0]["detail"]}';
}
List<Manga>? results = [];
for (var manga in data['results']) {
var r = manga['data'];
var relations = manga['relationships'];
var cover, author, artist;
for (var rel in relations) {
switch (rel['type']) {
case 'author':
author = Author(
name: rel['attributes']['name'],
id: rel['id'],
biography: rel['attributes']['biography'],
imageUrl: rel['attributes']['imageUrl']);
break;
case 'artist':
artist = Author(
name: rel['attributes']['name'],
id: rel['id'],
imageUrl: rel['attributes']['imageUrl'],
biography: rel['attributes']['biography']);
break;
case 'cover_art':
cover =
'https://uploads.mangadex.org/covers/${r['id']}/${rel['attributes']['fileName']}';
break;
default:
break;
}
}
results.add(
Manga(
altTitles: r['attributes']['altTitles'],
title: Map.from(r['attributes']['title']),
tags: r['attributes']['tags'],
description: Map.from(r['attributes']['description']),
isLocked: r['attributes']['isLocked'],
links: (r['attributes']['links'] == null)
? null
: Map.from(r['attributes']['links']),
originalLang: r['attributes']['originalLanguage'],
lastChapter: r['attributes']['lastChapter'],
lastVolume: r['attributes']['lastVolume'],
demographic: r['attributes']['publicationDemographic'],
status: r['attributes']['status'],
releaseYear: r['attributes']['year'],
contentRating: r['attributes']['contentRating'],
createdAt: r['attributes']['createdAt'],
updatedAt: r['attributes']['updatedAt'],
id: r['id'],
cover: cover,
author: author,
artist: artist),
);
}
return results;
}