123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- package wikidata
- import (
- "notabug.org/apiote/amuse/datastructure"
- "notabug.org/apiote/amuse/network"
- "database/sql"
- "encoding/json"
- "errors"
- "net/http"
- "strconv"
- "strings"
- "notabug.org/apiote/gott"
- )
- type Editions struct {
- Entities map[string]struct {
- OriginalLang string
- Image struct {
- Url string
- }
- }
- }
- func queryBookByTmdb(args ...interface{}) (interface{}, error) {
- id := args[0].(*network.Request).Id
- tag := args[0].(*network.Request).Language[:2]
- result := args[1].(*Result)
- repo := result.Repo
- res, err := repo.Query(`SELECT ?book ?bookLabel ?bookseries ?bookseriesLabel WHERE {
- OPTIONAL {
- ?serie wdt:P4983 "` + id + `";
- wdt:P144 ?book.
- ?book wdt:P31 wd:Q47461344.
- }
- OPTIONAL {
- ?film wdt:P4947 "` + id + `";
- wdt:P144 ?book.
- ?book wdt:P31 wd:Q47461344.
- }
- OPTIONAL {
- ?film wdt:P4947 "` + id + `";
- wdt:P144 ?bookseries.
- ?bookseries (wdt:P31/(wdt:P279*)) wd:Q277759.
- }
- OPTIONAL {
- ?serie wdt:P4983 "` + id + `";
- wdt:P144 ?bookseries.
- ?bookseries (wdt:P31/(wdt:P279*)) wd:Q277759.
- }
- SERVICE wikibase:label { bd:serviceParam wikibase:language "` + tag + `", "en". }
- }`)
- result.Result = res
- return gott.Tuple(args), err
- }
- func queryBook(args ...interface{}) (interface{}, error) {
- id := args[0].(*network.Request).Id
- tag := args[0].(*network.Request).Language[:2]
- result := args[1].(*Result)
- repo := result.Repo
- res, err := repo.Query(`SELECT ?title ?bookLabel ?authorLabel ?series ?seriesLabel ?ordinal ?genreLabel (YEAR(?publication) AS ?year) ?article_title WHERE {
- ` + id + ` wdt:P50 ?author.
- ` + id + ` wdt:P1476 ?title.
- optional {
- ` + id + ` wdt:P577 ?publication.
- }
- optional {
- ` + id + ` wdt:P136 ?genre.
- }
- OPTIONAL {
- ?article schema:about ` + id + `;
- schema:inLanguage "` + tag + `";
- schema:name ?article_title;
- schema:isPartOf _:b18.
- _:b18 wikibase:wikiGroup "wikipedia".
- FILTER(!(CONTAINS(?article_title, ":")))
- }
- OPTIONAL {
- ` + id + ` wdt:P179 ?series.
- OPTIONAL { ` + id + ` wdt:P1545 ?ordinal. }
- }
- SERVICE wikibase:label { bd:serviceParam wikibase:language "` + tag + `", "en". }
- SERVICE wikibase:label {
- bd:serviceParam wikibase:language "` + tag + `", "en".
- ` + id + ` rdfs:label ?bookLabel.
- }
- }`)
- result.Result = res
- return gott.Tuple(args), err
- }
- func parseBook(args ...interface{}) (interface{}, error) {
- id := args[0].(*network.Request).Id
- results := args[1].(*Result)
- res := results.Result
- if res.Results.Bindings == nil || len(res.Results.Bindings) == 0 {
- results.Work = &datastructure.Book{}
- } else {
- authors := map[string]bool{}
- genres := map[string]bool{}
- result := res.Results.Bindings[0]
- var year int64
- var err error
- if result["year"].Value != "" {
- year, err = strconv.ParseInt(result["year"].Value, 10, 64)
- if err != nil {
- return gott.Tuple(args), err
- }
- }
- bookId := id
- if result["book"].Value != "" {
- bookId = strings.Replace(result["book"].Value, "http://www.wikidata.org/entity/", "wd:", 1)
- }
- title := result["bookLabel"].Value
- if title == strings.Replace(bookId, "wd:", "", 1) || title == "" {
- title = result["title"].Value
- }
- book := datastructure.Book{
- Id: bookId,
- Uri: "/books/" + bookId,
- Source: []datastructure.Source{},
- Title: title,
- Year: year,
- SerieUri: strings.Replace(result["series"].Value, "http://www.wikidata.org/entity/", "/bookseries/wd:", 1),
- SerieName: result["seriesLabel"].Value,
- PartInSerie: result["ordinal"].Value,
- Authors: []string{},
- Genres: []string{},
- Article: result["article_title"].Value,
- }
- book.Source = append(book.Source, datastructure.Source{
- Url: "https://www.wikidata.org/wiki/" + strings.Replace(id, "wd:", "", 1),
- Name: "Wikidata",
- })
- book.Source = append(book.Source, datastructure.Source{
- Url: "https://inventaire.io/entity/" + id,
- Name: "Inventaire",
- })
- if result["bookseries"].Value != "" {
- book.Uri = strings.Replace(result["bookseries"].Value, "http://www.wikidata.org/entity/", "/bookseries/wd:", 1)
- book.Title = result["bookseriesLabel"].Value
- }
- for _, r := range res.Results.Bindings {
- authors[r["authorLabel"].Value] = true
- if r["genreLabel"].Value != "" {
- genres[r["genreLabel"].Value] = true
- }
- }
- for k := range authors {
- book.Authors = append(book.Authors, k)
- }
- for k := range genres {
- book.Genres = append(book.Genres, k)
- }
- results.Work = &book
- }
- return gott.Tuple(args), nil
- }
- func createIsbnRequest(args ...interface{}) (interface{}, error) {
- descriptionRequest := args[0].(*network.Request)
- result := args[1].(*network.Result)
- result.Client = &http.Client{}
- id := descriptionRequest.Id
- request, err := http.NewRequest("GET", "https://inventaire.io/api/entities?action=reverse-claims&property=wdt:P629&value="+id, nil)
- result.Request = request
- return gott.Tuple(args), err
- }
- func unmarshalIsbn(args ...interface{}) (interface{}, error) {
- var isbns struct{ Uris []string }
- result := args[1].(*network.Result)
- err := json.Unmarshal(result.Body, &isbns)
- uris := ""
- for _, isbn := range isbns.Uris {
- uris += "|" + isbn
- }
- if len(uris) > 0 {
- uris = uris[1:]
- }
- result.Result = uris
- return gott.Tuple(args), err
- }
- func getIsbn(args ...interface{}) (interface{}, error) {
- request := args[0].(*network.Request)
- res, err := gott.
- NewResult(gott.Tuple{request, &network.Result{}}).
- Bind(createIsbnRequest).
- Bind(network.DoRequest).
- Bind(network.HandleRequestError).
- Bind(network.ReadResponse).
- Bind(unmarshalIsbn).
- Finish()
- request.Id = res.(gott.Tuple)[1].(*network.Result).Result.(string)
- return gott.Tuple(args), err
- }
- func checkEmpty(args ...interface{}) (interface{}, error) {
- request := args[0].(*network.Request)
- if request.Id == "" {
- return gott.Tuple(args), errors.New("warning: empty ISBN")
- }
- return gott.Tuple(args), nil
- }
- func createEditionsRequest(args ...interface{}) (interface{}, error) {
- editionsRequest := args[0].(*network.Request)
- result := args[1].(*network.Result)
- result.Client = &http.Client{}
- id := editionsRequest.Id
- request, err := http.NewRequest("GET", "https://inventaire.io/api/entities?action=by-uris&uris="+id+"&refresh=false", nil)
- result.Request = request
- return gott.Tuple(args), err
- }
- func unmarshalEditions(args ...interface{}) (interface{}, error) {
- var editions Editions
- result := args[1].(*network.Result)
- err := json.Unmarshal(result.Body, &editions)
- result.Result = editions
- return gott.Tuple(args), err
- }
- func filterEditionLanguage(args ...interface{}) interface{} {
- result := args[1].(*network.Result)
- editions := result.Result.(Editions)
- language := args[0].(*network.Request).Language[:2]
- covers := []string{}
- englishCover := ""
- for _, edition := range editions.Entities {
- if edition.OriginalLang == language && edition.Image.Url != "" {
- covers = append(covers, "https://inventaire.io"+edition.Image.Url)
- }
- if edition.OriginalLang == "en" && englishCover == "" && edition.Image.Url != "" {
- englishCover = "https://inventaire.io" + edition.Image.Url
- }
- }
- if len(covers) == 0 {
- result.Result = englishCover
- } else {
- result.Result = covers[0]
- }
- return gott.Tuple(args)
- }
- func getCover(args ...interface{}) (interface{}, error) {
- request := args[0].(*network.Request)
- res, err := gott.
- NewResult(gott.Tuple{request, &network.Result{}}).
- Bind(createEditionsRequest).
- Bind(network.DoRequest).
- Bind(network.HandleRequestError).
- Bind(network.ReadResponse).
- Bind(unmarshalEditions).
- Map(filterEditionLanguage).
- Finish()
- args[1] = res.(gott.Tuple)[1].(*network.Result).Result.(string)
- return gott.Tuple(args), err
- }
- func GetBookByTmdb(id, language string) (datastructure.Book, error) {
- res, err := gott.
- NewResult(gott.Tuple{&network.Request{Id: id, Language: language}, &Result{}}).
- Bind(createRepo).
- Bind(queryBookByTmdb).
- Bind(parseBook).
- Finish()
- if err != nil {
- return datastructure.Book{}, err
- }
- book := res.(gott.Tuple)[1].(*Result).Work.(*datastructure.Book)
- return *book, nil
- }
- func GetBook(id, language string, connection *sql.DB) (*datastructure.Book, error) {
- res, err := gott.
- NewResult(gott.Tuple{&network.Request{Id: id, Language: language}, &Result{}}).
- Bind(createRepo).
- Bind(queryBook).
- Bind(parseBook).
- Finish()
- if err != nil {
- return &datastructure.Book{}, err
- }
- return res.(gott.Tuple)[1].(*Result).Work.(*datastructure.Book), nil
- }
- func GetCover(id, language string, connection *sql.DB) (string, error) {
- res, err := gott.
- NewResult(gott.Tuple{&network.Request{Id: id, Language: language, Connection: connection}, ""}).
- Bind(getIsbn).
- Bind(checkEmpty).
- Bind(getCover).
- Finish()
- if err != nil && strings.HasPrefix(err.Error(), "warning") {
- return "", nil
- } else if err != nil {
- return "", err
- } else {
- return res.(gott.Tuple)[1].(string), nil
- }
- }
|