package inventaire import ( "encoding/json" "math" "sort" "strings" "git.artlef.fr/PersonalLibraryManager/internal/callapiutils" ) type InventaireEditionResult struct { Results []InventaireEditionResultBook `json:"results"` Count int64 `json:"count"` } type InventaireEditionResultBook struct { Id string `json:"uri"` Title string `json:"title"` ISBN string `json:"isbn"` Publisher string `json:"publisher"` ReleaseDate string `json:"date"` Image string `json:"image"` Lang string `json:"lang"` } type inventaireReverseClaimsResult struct { Uris []string `json:"uris"` } type inventaireEditionQueryResult struct { Entities []inventaireEditionQueryEntity } type inventaireEditionQueryEntity struct { WdId string EditionId string Title string ISBN string Uri string Image string Lang string ReleaseDate string } func (i *inventaireEditionQueryResult) UnmarshalJSON(b []byte) error { var parsed struct { Entities map[string]json.RawMessage `json:"entities"` } err := json.Unmarshal(b, &parsed) if err != nil { return err } for _, entity := range parsed.Entities { var parsedEntity struct { WdId string `json:"wdId"` Labels map[string]json.RawMessage `json:"labels"` Type string `json:"type"` Uri string `json:"uri"` Image map[string]json.RawMessage `json:"image"` Lang string `json:"originalLang"` Claims map[string]json.RawMessage `json:"claims"` } err = json.Unmarshal(entity, &parsedEntity) if err != nil { return err } if parsedEntity.Type == "edition" { editionId, err := parseStringArrayFieldInJsonRaw(parsedEntity.Claims, "wdt:P123") if err != nil { return err } releaseDate, err := parseStringArrayFieldInJsonRaw(parsedEntity.Claims, "wdt:P577") if err != nil { return err } isbn, err := parseStringArrayFieldInJsonRaw(parsedEntity.Claims, "wdt:P212") if err != nil { return err } label, err := findLangageField(parsedEntity.Labels, "fromclaims") if err != nil { return err } image := "" imageFieldToParse, ok := parsedEntity.Image["url"] if ok { err := json.Unmarshal(imageFieldToParse, &image) if err != nil { return err } if image != "" { image = GetBaseInventaireUrl() + image } } i.Entities = append(i.Entities, inventaireEditionQueryEntity{ WdId: parsedEntity.WdId, EditionId: editionId, Title: label, ISBN: isbn, Uri: parsedEntity.Uri, Image: image, Lang: parsedEntity.Lang, ReleaseDate: releaseDate, }) } } return err } func parseStringArrayFieldInJsonRaw(jsonRawMap map[string]json.RawMessage, key string) (string, error) { fieldToParse, ok := jsonRawMap[key] if !ok { return "", nil } var fieldArray []string s := "" err := json.Unmarshal(fieldToParse, &fieldArray) if err != nil { return s, err } if len(fieldArray) > 0 { s = fieldArray[0] } return s, err } func CallInventaireEdition(inventaireId string, lang string, limit int, offset int) (InventaireEditionResult, error) { var queryResult InventaireEditionResult uris, err := callInventaireUris(inventaireId) if err != nil { return queryResult, err } queryResult.Count = int64(len(uris.Uris)) sort.Strings(uris.Uris) limitedUris := uris.Uris if limit != 0 { l := len(uris.Uris) startIndex := int(math.Min(float64(offset), float64(l))) endIndex := int(math.Min(float64(limit+offset), float64(l))) limitedUris = uris.Uris[startIndex:endIndex] } editionEntities, err := callInventaireEditionEntities(limitedUris) if err != nil { return queryResult, err } sortedEntities := editionEntities.Entities sort.Slice(sortedEntities, func(i, j int) bool { return sortedEntities[i].Uri < sortedEntities[j].Uri }) for _, entity := range sortedEntities { publisher := "" if entity.EditionId != "" { publisher, err = callInventairePublisherGetName(entity.EditionId, lang) if err != nil { return queryResult, err } } queryResult.Results = append(queryResult.Results, InventaireEditionResultBook{ Id: entity.Uri, ISBN: entity.ISBN, Title: entity.Title, ReleaseDate: entity.ReleaseDate, Image: entity.Image, Publisher: publisher, Lang: entity.Lang, }) } return queryResult, err } func callInventaireUris(inventaireId string) (inventaireReverseClaimsResult, error) { var queryResult inventaireReverseClaimsResult u, err := computeInventaireApiUrl("entities") if err != nil { return queryResult, err } callapiutils.AddQueryParam(u, "action", "reverse-claims") callapiutils.AddQueryParam(u, "property", "wdt:P629") callapiutils.AddQueryParam(u, "value", inventaireId) err = callapiutils.FetchAndParseResult(u, &queryResult) return queryResult, err } func callInventaireEditionEntities(uris []string) (inventaireEditionQueryResult, error) { var queryResult inventaireEditionQueryResult u, err := computeInventaireApiUrl("entities") if err != nil { return queryResult, err } callapiutils.AddQueryParam(u, "action", "by-uris") callapiutils.AddQueryParam(u, "uris", strings.Join(uris, "|")) err = callapiutils.FetchAndParseResult(u, &queryResult) return queryResult, err } type inventaireEditionPublisherResult struct { Lang string Label string } func (i *inventaireEditionPublisherResult) UnmarshalJSON(b []byte) error { var parsed struct { Entities map[string]json.RawMessage } err := json.Unmarshal(b, &parsed) if err != nil { return err } for _, entity := range parsed.Entities { var publisherEntity struct { Type string `json:"type"` Labels map[string]json.RawMessage `json:"labels"` } err := json.Unmarshal(entity, &publisherEntity) if err != nil { return err } label, _ := findLangageField(publisherEntity.Labels, i.Lang) i.Label = label } return err } func callInventairePublisherGetName(editionId string, lang string) (string, error) { var queryResult inventaireEditionPublisherResult u, err := computeInventaireApiUrl("entities") if err != nil { return "", err } queryResult.Lang = lang callapiutils.AddQueryParam(u, "action", "by-uris") callapiutils.AddQueryParam(u, "uris", editionId) callapiutils.AddQueryParam(u, "attributes", "info|labels") err = callapiutils.FetchAndParseResult(u, &queryResult) return queryResult.Label, err }