This repository has been archived by the owner on Nov 30, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
unpaywall.go
97 lines (77 loc) · 2.51 KB
/
unpaywall.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"net/url"
"strings"
)
// UnpaywallService looks up DOI info from unpaywall
type UnpaywallService struct {
HTTP Requester // Http client for interacting with unpaywall API
Email string // Email for unpaywall requests
Baseuri string // Unpaywall baseURI
Cache *DoiCache // Can be nil if no caching is desired
}
// DOI lookup response from unpaywall
type unpaywallDOIResponse struct {
OaLocations []unpaywallLocation `json:"oa_locations"`
}
type unpaywallLocation struct {
URLForPdf string `json:"url_for_pdf"`
Version string `json:"version"`
RepositoryInstitution string `json:"repository_institution"`
}
// Lookup looks up DOI info for a given DOI
func (u UnpaywallService) Lookup(doi string) (*DoiInfo, error) {
generator := func() (*DoiInfo, error) {
results, err := u.get(u.apiRequestURI(doi))
if err != nil {
return nil, fmt.Errorf("unpaywall API request failed: %w", err)
}
var doiResponse DoiInfo
for _, location := range results.OaLocations {
if location.URLForPdf != "" {
// Get the file name from the decoded url for pdf
// but log any problems do not cause response to fail
var fileName string
decodedURLForPdf, err := url.QueryUnescape(location.URLForPdf)
if err != nil {
log.Printf("file name decoding failed: %s", err)
} else {
splitURLForPdf := strings.Split(decodedURLForPdf, "/")
fileName = splitURLForPdf[len(splitURLForPdf)-1]
}
doiResponse.Manuscripts = append(doiResponse.Manuscripts, Manuscript{
Location: location.URLForPdf,
RepositoryInstitution: location.RepositoryInstitution,
Type: "application/pdf",
Source: "Unpaywall",
Name: fileName,
})
}
}
return &doiResponse, nil
}
if u.Cache != nil {
return u.Cache.GetOrAdd(doi, generator)
}
return generator()
}
func (u UnpaywallService) apiRequestURI(doi string) string {
return fmt.Sprintf("%s/%s?email=%s", u.Baseuri, doi, u.Email)
}
func (u UnpaywallService) get(uri string) (*unpaywallDOIResponse, error) {
req, err := http.NewRequest(http.MethodGet, uri, nil)
if err != nil {
return nil, fmt.Errorf("could not form unpaywall API request: %w", err)
}
resp, err := mustSucceed(u.HTTP.Do(req))
if err != nil {
return nil, fmt.Errorf("unpaywall request failed: %w", err)
}
defer resp.Body.Close()
var raw unpaywallDOIResponse
return &raw, json.NewDecoder(resp.Body).Decode(&raw)
}