-
Notifications
You must be signed in to change notification settings - Fork 0
/
wikigopher.go
144 lines (123 loc) · 3.39 KB
/
wikigopher.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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package wikigopher
import (
"encoding/json"
"io/ioutil"
"net/http"
"net/url"
"github.com/tidwall/gjson"
)
const (
apiURL = "http://en.wikipedia.org/w/api.php"
searchResultsCap = 10
)
// WikipediaPage represents a Wikipedia Page
type WikipediaPage struct {
PageID uint64
Title string
Content string
Categories []string
Links []string
}
// Page returns the WikipediaPage object for a given search query
func Page(query string) (*WikipediaPage, error) {
// first run Search() to get most relevant result for query
var searchResults = Search(query)
v := url.Values{
"titles": []string{searchResults[0]},
"action": []string{"query"},
"prop": []string{"categories|extracts|revisions|links"},
"rvprop": []string{"ids"},
"format": []string{"json"},
"explaintext": []string{""},
}
var page WikipediaPage
respJSON, err := wikiRequest(v)
if err != nil {
return &page, err
}
pageJSON := gjson.GetBytes(respJSON, "query.pages.*")
page.PageID = pageJSON.Get("pageid").Uint()
page.Title = pageJSON.Get("title").String()
page.Content = pageJSON.Get("extract").String()
pageLinks := pageJSON.Get("links.#.title").Array()
for _, link := range pageLinks {
page.Links = append(page.Links, link.String())
}
pageCategories := pageJSON.Get("categories.#.title").Array()
for _, category := range pageCategories {
page.Categories = append(page.Categories, category.String())
}
return &page, nil
}
// Summary returns the Wikipedia summary for a given search query
func Summary(query string) string {
// first run Search() to get most relevant result for query
var searchResults = Search(query)
v := url.Values{
"titles": []string{searchResults[0]},
"action": []string{"query"},
"prop": []string{"extracts"},
"exintro": []string{""},
"format": []string{"json"},
"explaintext": []string{""},
}
resp, err := wikiRequest(v)
if err != nil {
return ""
}
var summaryResult map[string]interface{}
json.Unmarshal(resp, &summaryResult)
pages := summaryResult["query"].(map[string]interface{})["pages"]
page := firstValueInDictionary(pages)
return page["extract"].(string)
}
// get first value in weird wikipedia pages entry
func firstValueInDictionary(page interface{}) map[string]interface{} {
for _, v := range page.(map[string]interface{}) {
return v.(map[string]interface{})
}
return nil
}
// Search does a Wikipedia search of query and returns a slice of the result
// titles
func Search(query string) []string {
v := url.Values{
"list": []string{"search"},
"action": []string{"query"},
"srsearch": []string{query},
"format": []string{"json"},
}
type Page struct {
PageID uint64 `json:"pageid"`
Title string `json:"title"`
}
type SearchResult struct {
Query struct {
Pages []Page `json:"search"`
} `json:"query"`
}
var results SearchResult
resp, err := wikiRequest(v)
if err != nil {
return []string{}
}
json.Unmarshal(resp, &results)
var titles []string
for _, page := range results.Query.Pages {
titles = append(titles, page.Title)
}
return titles
}
// wikiRequest hits the wikipedia api with the given request parameters
func wikiRequest(v url.Values) ([]byte, error) {
res, err := http.Get(apiURL + "?" + v.Encode())
if err != nil {
return nil, err
}
body, err := ioutil.ReadAll(res.Body)
res.Body.Close()
if err != nil {
return nil, err
}
return body, nil
}