feature: movie description

main
daniel-michel 2024-01-10 14:46:03 +01:00
parent 9aa0278ab0
commit 0520120ccf
3 changed files with 70 additions and 2 deletions

View File

@ -75,7 +75,7 @@ class WikidataMovieApi implements MovieApi {
final start = i * batchSize;
final end = min((i + 1) * batchSize, movieIds.length);
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> batchEntities = result["entities"];
entities.addAll(batchEntities);
@ -94,6 +94,12 @@ class WikidataMovieApi implements MovieApi {
// they will be retrieved from the cache in fromWikidataEntity
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
.map((id) => WikidataMovieData.fromWikidataEntity(id, entities[id]))
.toList();
@ -142,6 +148,13 @@ class WikidataMovieData extends MovieData {
String title =
selectInJson<String>(entity, "labels.en.value").firstOrNull ??
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"];
List<TitleInLanguage>? titles = selectInJson(
claims, "${WikidataProperties.title}.*.mainsnak.datavalue.value")
@ -167,6 +180,7 @@ class WikidataMovieData extends MovieData {
DateTime.now(), DatePrecision.decade, "unknown location"),
entityId);
movie.setDetails(
description: description,
titles: titles,
releaseDates: releaseDates,
genres: genres,
@ -267,3 +281,44 @@ Future<Map<String, String>> _getLabelsForEntities(
String _getCachedLabelForEntity(String 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];
}

View File

@ -7,6 +7,7 @@ class MovieData extends ChangeNotifier {
bool _bookmarked = false;
bool _hasDetails = false;
String? _description;
List<DateWithPrecisionAndCountry>? _releaseDates;
List<String>? _genres;
List<TitleInLanguage>? _titles;
@ -25,6 +26,10 @@ class MovieData extends ChangeNotifier {
return _bookmarked;
}
get description {
return _description;
}
List<DateWithPrecisionAndCountry>? get releaseDates {
return _releaseDates;
}
@ -47,6 +52,7 @@ class MovieData extends ChangeNotifier {
setDetails(
title: movie.title,
releaseDate: movie.releaseDate,
description: movie.description,
releaseDates: movie.releaseDates,
genres: movie.genres,
titles: movie.titles);
@ -56,6 +62,7 @@ class MovieData extends ChangeNotifier {
{String? title,
DateWithPrecisionAndCountry? releaseDate,
bool? bookmarked,
String? description,
List<DateWithPrecisionAndCountry>? releaseDates,
List<String>? genres,
List<TitleInLanguage>? titles}) {
@ -68,6 +75,9 @@ class MovieData extends ChangeNotifier {
if (bookmarked != null) {
_bookmarked = bookmarked;
}
if (description != null) {
_description = description;
}
if (releaseDates != null) {
_releaseDates = releaseDates;
}
@ -99,6 +109,7 @@ class MovieData extends ChangeNotifier {
"title": title,
"releaseDate": _releaseDate.toJsonEncodable(),
"bookmarked": _bookmarked,
"description": _description,
"releaseDates": releaseDatesByCountry,
"genres": genres,
"titles": titlesByCountry,
@ -111,6 +122,7 @@ class MovieData extends ChangeNotifier {
DateWithPrecisionAndCountry.fromJsonEncodable(json["releaseDate"]) {
setDetails(
bookmarked: json["bookmarked"] as bool,
description: json["description"] as String?,
genres: (json["genres"] as List<dynamic>?)
?.map((genre) => genre as String)
.toList(),

View File

@ -51,7 +51,8 @@ class MoviePage extends StatelessWidget {
.toList() ??
[],
),
const SizedBox(height: 20),
const Heading("Description"),
Text(movie.description ?? "No description"),
const Heading("Titles"),
Table(
border: TableBorder.symmetric(