feature: movie description
parent
9aa0278ab0
commit
0520120ccf
|
@ -75,7 +75,7 @@ class WikidataMovieApi implements MovieApi {
|
||||||
final start = i * batchSize;
|
final start = i * batchSize;
|
||||||
final end = min((i + 1) * batchSize, movieIds.length);
|
final end = min((i + 1) * batchSize, movieIds.length);
|
||||||
var response = await _wikidataApi.get(
|
var response = await _wikidataApi.get(
|
||||||
"&action=wbgetentities&format=json&props=labels|claims&ids=${movieIds.sublist(start, end).join("|")}");
|
"&action=wbgetentities&format=json&props=labels|claims|sitelinks/urls&ids=${movieIds.sublist(start, end).join("|")}");
|
||||||
Map<String, dynamic> result = jsonDecode(response.body);
|
Map<String, dynamic> result = jsonDecode(response.body);
|
||||||
Map<String, dynamic> batchEntities = result["entities"];
|
Map<String, dynamic> batchEntities = result["entities"];
|
||||||
entities.addAll(batchEntities);
|
entities.addAll(batchEntities);
|
||||||
|
@ -94,6 +94,12 @@ class WikidataMovieApi implements MovieApi {
|
||||||
// they will be retrieved from the cache in fromWikidataEntity
|
// they will be retrieved from the cache in fromWikidataEntity
|
||||||
await _getLabelsForEntities(allCountryAndGenreIds);
|
await _getLabelsForEntities(allCountryAndGenreIds);
|
||||||
|
|
||||||
|
// Get wikipedia explaintexts
|
||||||
|
Iterable<String> allWikipediaTitles =
|
||||||
|
selectInJson<String>(entities, "*.sitelinks.enwiki.url")
|
||||||
|
.map((url) => url.split("/").last);
|
||||||
|
await _getWikipediaExplainTextForTitles(allWikipediaTitles.toList());
|
||||||
|
|
||||||
return movieIds
|
return movieIds
|
||||||
.map((id) => WikidataMovieData.fromWikidataEntity(id, entities[id]))
|
.map((id) => WikidataMovieData.fromWikidataEntity(id, entities[id]))
|
||||||
.toList();
|
.toList();
|
||||||
|
@ -142,6 +148,13 @@ class WikidataMovieData extends MovieData {
|
||||||
String title =
|
String title =
|
||||||
selectInJson<String>(entity, "labels.en.value").firstOrNull ??
|
selectInJson<String>(entity, "labels.en.value").firstOrNull ??
|
||||||
selectInJson<String>(entity, "labels.*.value").first;
|
selectInJson<String>(entity, "labels.*.value").first;
|
||||||
|
String? wikipediaTitle = selectInJson(entity, "sitelinks.enwiki.url")
|
||||||
|
.firstOrNull
|
||||||
|
?.split("/")
|
||||||
|
.last;
|
||||||
|
String? description = wikipediaTitle != null
|
||||||
|
? _getCachedWikipediaExplainTextFotTitle(wikipediaTitle)
|
||||||
|
: null;
|
||||||
Map<String, dynamic> claims = entity["claims"];
|
Map<String, dynamic> claims = entity["claims"];
|
||||||
List<TitleInLanguage>? titles = selectInJson(
|
List<TitleInLanguage>? titles = selectInJson(
|
||||||
claims, "${WikidataProperties.title}.*.mainsnak.datavalue.value")
|
claims, "${WikidataProperties.title}.*.mainsnak.datavalue.value")
|
||||||
|
@ -167,6 +180,7 @@ class WikidataMovieData extends MovieData {
|
||||||
DateTime.now(), DatePrecision.decade, "unknown location"),
|
DateTime.now(), DatePrecision.decade, "unknown location"),
|
||||||
entityId);
|
entityId);
|
||||||
movie.setDetails(
|
movie.setDetails(
|
||||||
|
description: description,
|
||||||
titles: titles,
|
titles: titles,
|
||||||
releaseDates: releaseDates,
|
releaseDates: releaseDates,
|
||||||
genres: genres,
|
genres: genres,
|
||||||
|
@ -267,3 +281,44 @@ Future<Map<String, String>> _getLabelsForEntities(
|
||||||
String _getCachedLabelForEntity(String entityId) {
|
String _getCachedLabelForEntity(String entityId) {
|
||||||
return _labelCache[entityId] ?? entityId;
|
return _labelCache[entityId] ?? entityId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ApiManager _wikipediaApi =
|
||||||
|
ApiManager("https://en.wikipedia.org/w/api.php?format=json&origin=*");
|
||||||
|
Map<String, String> _wikipediaExplainTextCache = {};
|
||||||
|
Future<Map<String, String>> _getWikipediaExplainTextForTitles(
|
||||||
|
List<String> pageTitles) async {
|
||||||
|
const batchSize = 50;
|
||||||
|
Map<String, String> explainTexts = {};
|
||||||
|
for (int i = pageTitles.length - 1; i >= 0; i--) {
|
||||||
|
if (_labelCache.containsKey(pageTitles[i])) {
|
||||||
|
explainTexts[pageTitles[i]] = _labelCache[pageTitles[i]]!;
|
||||||
|
pageTitles.removeAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < (pageTitles.length / batchSize).ceil(); i++) {
|
||||||
|
final start = i * batchSize;
|
||||||
|
final end = min((i + 1) * batchSize, pageTitles.length);
|
||||||
|
Response response = await _wikipediaApi.get(
|
||||||
|
"&action=query&prop=extracts&exintro&explaintext&redirects=1&titles=${pageTitles.sublist(start, end).join("|")}");
|
||||||
|
Map<String, dynamic> result = jsonDecode(response.body);
|
||||||
|
List<dynamic> normalize = result["query"]["normalized"];
|
||||||
|
Map<String, dynamic> batchPages = result["query"]["pages"];
|
||||||
|
for (String pageId in batchPages.keys) {
|
||||||
|
String pageTitle = batchPages[pageId]["title"];
|
||||||
|
String originalTitle = normalize
|
||||||
|
.where((element) => element["to"] == pageTitle)
|
||||||
|
.firstOrNull?["from"] ??
|
||||||
|
pageTitle;
|
||||||
|
String? explainText = batchPages[pageId]["extract"];
|
||||||
|
if (explainText != null) {
|
||||||
|
_wikipediaExplainTextCache[originalTitle] =
|
||||||
|
explainTexts[originalTitle] = explainText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return explainTexts;
|
||||||
|
}
|
||||||
|
|
||||||
|
String? _getCachedWikipediaExplainTextFotTitle(String title) {
|
||||||
|
return _wikipediaExplainTextCache[title];
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ class MovieData extends ChangeNotifier {
|
||||||
bool _bookmarked = false;
|
bool _bookmarked = false;
|
||||||
|
|
||||||
bool _hasDetails = false;
|
bool _hasDetails = false;
|
||||||
|
String? _description;
|
||||||
List<DateWithPrecisionAndCountry>? _releaseDates;
|
List<DateWithPrecisionAndCountry>? _releaseDates;
|
||||||
List<String>? _genres;
|
List<String>? _genres;
|
||||||
List<TitleInLanguage>? _titles;
|
List<TitleInLanguage>? _titles;
|
||||||
|
@ -25,6 +26,10 @@ class MovieData extends ChangeNotifier {
|
||||||
return _bookmarked;
|
return _bookmarked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get description {
|
||||||
|
return _description;
|
||||||
|
}
|
||||||
|
|
||||||
List<DateWithPrecisionAndCountry>? get releaseDates {
|
List<DateWithPrecisionAndCountry>? get releaseDates {
|
||||||
return _releaseDates;
|
return _releaseDates;
|
||||||
}
|
}
|
||||||
|
@ -47,6 +52,7 @@ class MovieData extends ChangeNotifier {
|
||||||
setDetails(
|
setDetails(
|
||||||
title: movie.title,
|
title: movie.title,
|
||||||
releaseDate: movie.releaseDate,
|
releaseDate: movie.releaseDate,
|
||||||
|
description: movie.description,
|
||||||
releaseDates: movie.releaseDates,
|
releaseDates: movie.releaseDates,
|
||||||
genres: movie.genres,
|
genres: movie.genres,
|
||||||
titles: movie.titles);
|
titles: movie.titles);
|
||||||
|
@ -56,6 +62,7 @@ class MovieData extends ChangeNotifier {
|
||||||
{String? title,
|
{String? title,
|
||||||
DateWithPrecisionAndCountry? releaseDate,
|
DateWithPrecisionAndCountry? releaseDate,
|
||||||
bool? bookmarked,
|
bool? bookmarked,
|
||||||
|
String? description,
|
||||||
List<DateWithPrecisionAndCountry>? releaseDates,
|
List<DateWithPrecisionAndCountry>? releaseDates,
|
||||||
List<String>? genres,
|
List<String>? genres,
|
||||||
List<TitleInLanguage>? titles}) {
|
List<TitleInLanguage>? titles}) {
|
||||||
|
@ -68,6 +75,9 @@ class MovieData extends ChangeNotifier {
|
||||||
if (bookmarked != null) {
|
if (bookmarked != null) {
|
||||||
_bookmarked = bookmarked;
|
_bookmarked = bookmarked;
|
||||||
}
|
}
|
||||||
|
if (description != null) {
|
||||||
|
_description = description;
|
||||||
|
}
|
||||||
if (releaseDates != null) {
|
if (releaseDates != null) {
|
||||||
_releaseDates = releaseDates;
|
_releaseDates = releaseDates;
|
||||||
}
|
}
|
||||||
|
@ -99,6 +109,7 @@ class MovieData extends ChangeNotifier {
|
||||||
"title": title,
|
"title": title,
|
||||||
"releaseDate": _releaseDate.toJsonEncodable(),
|
"releaseDate": _releaseDate.toJsonEncodable(),
|
||||||
"bookmarked": _bookmarked,
|
"bookmarked": _bookmarked,
|
||||||
|
"description": _description,
|
||||||
"releaseDates": releaseDatesByCountry,
|
"releaseDates": releaseDatesByCountry,
|
||||||
"genres": genres,
|
"genres": genres,
|
||||||
"titles": titlesByCountry,
|
"titles": titlesByCountry,
|
||||||
|
@ -111,6 +122,7 @@ class MovieData extends ChangeNotifier {
|
||||||
DateWithPrecisionAndCountry.fromJsonEncodable(json["releaseDate"]) {
|
DateWithPrecisionAndCountry.fromJsonEncodable(json["releaseDate"]) {
|
||||||
setDetails(
|
setDetails(
|
||||||
bookmarked: json["bookmarked"] as bool,
|
bookmarked: json["bookmarked"] as bool,
|
||||||
|
description: json["description"] as String?,
|
||||||
genres: (json["genres"] as List<dynamic>?)
|
genres: (json["genres"] as List<dynamic>?)
|
||||||
?.map((genre) => genre as String)
|
?.map((genre) => genre as String)
|
||||||
.toList(),
|
.toList(),
|
||||||
|
|
|
@ -51,7 +51,8 @@ class MoviePage extends StatelessWidget {
|
||||||
.toList() ??
|
.toList() ??
|
||||||
[],
|
[],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const Heading("Description"),
|
||||||
|
Text(movie.description ?? "No description"),
|
||||||
const Heading("Titles"),
|
const Heading("Titles"),
|
||||||
Table(
|
Table(
|
||||||
border: TableBorder.symmetric(
|
border: TableBorder.symmetric(
|
||||||
|
|
Loading…
Reference in New Issue