Skip to content

Commit c49a391

Browse files
Added support for OpenSERP API
1 parent a0578d1 commit c49a391

File tree

3 files changed

+95
-11
lines changed

3 files changed

+95
-11
lines changed

README.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ CGO_ENABLED=0 go install -ldflags "-s -w" -trimpath github.com/shadowy-pycoder/g
2626
This will install the `goso` binary to your `$GOPATH/bin` directory.
2727

2828

29+
## Search Engine Setup
2930

30-
This tool uses [Custom Search JSON API](https://developers.google.com/custom-search/v1/overview) from Google to obtain most relevant results from Stack Overflow. So, to make it work, you need to obtain an API key from Google and also a [Search Engine ID](https://developers.google.com/custom-search/v1/overview#search_engine_id).
31+
### Google Search JSON API
32+
This approach employs [Custom Search JSON API](https://developers.google.com/custom-search/v1/overview) from Google to obtain most relevant results from Stack Overflow. So, to make it work, you need to get an API key from Google and also a [Search Engine ID](https://developers.google.com/custom-search/v1/overview#search_engine_id). That gives you `100 requests per day`, which I believe is enough for most use cases.
3133

3234
Setup your `Search Engine ID` like this:
3335

@@ -39,6 +41,33 @@ echo "export GOSO_API_KEY=<YOUR_API_KEY>" >> $HOME/.profile
3941
echo "export GOSO_SE=<YOUR_SEARCH_ENGINE_ID>" >> $HOME/.profile
4042
source $HOME/.profile
4143
```
44+
45+
### OpenSerp API
46+
`goso` also supports [OpenSERP (Search Engine Results Page)](https://github.com/karust/openserp) from [Karust](https://github.com/karust). This is a completely *FREE* alternative to the Google Search JSON API, though it works a little bit slower, but gives basically the same results.
47+
48+
So, to make it work, you need tu run OperSERP server locally. You can do it like this:
49+
50+
With Docker:
51+
```shell
52+
docker run -p 127.0.0.1:7000:7000 -it karust/openserp serve -a 0.0.0.0 -p 7000
53+
```
54+
55+
Or as a CLI command:
56+
57+
```shell
58+
openserp serve
59+
```
60+
You can learn more on how to install OpenSERP [here](https://github.com/karust/openserp).
61+
62+
Once you have it running, add variables to your environment:
63+
```shell
64+
echo "export GOSO_OS_HOST=127.0.0.1" >> $HOME/.profile
65+
echo "export GOSO_OS_PORT=7000" >> $HOME/.profile
66+
source $HOME/.profile
67+
```
68+
These variables will have priority over the `GOSO_API_KEY` and `GOSO_SE`.
69+
70+
4271
## Usage
4372

4473
```shell

cmd/goso/cli.go

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -104,21 +104,34 @@ func root(args []string) error {
104104
return fmt.Errorf("-a should be within [min=1, max=10]")
105105
}
106106
conf.AnswerNum = *aNum
107-
apiKey, set := os.LookupEnv("GOSO_API_KEY")
108-
if !set {
109-
return fmt.Errorf("api key is not set")
110-
}
111-
conf.ApiKey = apiKey
112-
se, set := os.LookupEnv("GOSO_SE")
113-
if !set {
114-
return fmt.Errorf("search engine is not set")
107+
var fetchFunc func(*goso.Config, map[int]*goso.Result) error
108+
osHost, hostSet := os.LookupEnv("GOSO_OS_HOST")
109+
osPort, portSet := os.LookupEnv("GOSO_OS_PORT")
110+
if hostSet && portSet {
111+
conf.OpenSerpHost = osHost
112+
conf.OpenSerpPort, err = strconv.Atoi(osPort)
113+
if err != nil {
114+
return fmt.Errorf("failed parsing `GOSO_OS_PORT`")
115+
}
116+
fetchFunc = goso.FetchOpenSerp
117+
} else {
118+
apiKey, set := os.LookupEnv("GOSO_API_KEY")
119+
if !set {
120+
return fmt.Errorf("`GOSO_API_KEY` is not set")
121+
}
122+
conf.ApiKey = apiKey
123+
se, set := os.LookupEnv("GOSO_SE")
124+
if !set {
125+
return fmt.Errorf("`GOSO_SE` is not set")
126+
}
127+
conf.SearchEngine = se
128+
fetchFunc = goso.FetchGoogle
115129
}
116-
conf.SearchEngine = se
117130
conf.Query = strings.Join(flags.Args(), " ")
118131
if conf.Query == "" {
119132
return fmt.Errorf("query is empty")
120133
}
121-
answers, err := goso.GetAnswers(conf, goso.FetchGoogle, goso.FetchStackOverflow)
134+
answers, err := goso.GetAnswers(conf, fetchFunc, goso.FetchStackOverflow)
122135
if err != nil {
123136
return err
124137
}

goso.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,14 @@ type StackOverflowResult struct {
236236
QuotaRemaining int `json:"quota_remaining"`
237237
}
238238

239+
type OpenSerpResult struct {
240+
Rank int `json:"rank"`
241+
URL string `json:"url"`
242+
Title string `json:"title"`
243+
Description string `json:"description"`
244+
Ad bool `json:"ad"`
245+
}
246+
239247
type Config struct {
240248
ApiKey string
241249
SearchEngine string
@@ -244,6 +252,8 @@ type Config struct {
244252
Lexer string
245253
QuestionNum int
246254
AnswerNum int
255+
OpenSerpHost string
256+
OpenSerpPort int
247257
Client *http.Client
248258
}
249259
type Answer struct {
@@ -365,6 +375,38 @@ func FetchGoogle(conf *Config, results map[int]*Result) error {
365375
return nil
366376
}
367377

378+
func FetchOpenSerp(conf *Config, results map[int]*Result) error {
379+
url := fmt.Sprintf("http://%s:%d/google/search?lang=EN&limit=%d&text=%s&site=stackoverflow.com",
380+
conf.OpenSerpHost, conf.OpenSerpPort, conf.QuestionNum, netUrl.QueryEscape(conf.Query))
381+
req, err := http.NewRequest(http.MethodGet, url, nil)
382+
if err != nil {
383+
return err
384+
}
385+
res, err := conf.Client.Do(req)
386+
if err != nil {
387+
return fmt.Errorf("failed connecting to OpenSerp API: check your internet connection")
388+
}
389+
defer res.Body.Close()
390+
if res.StatusCode > 299 {
391+
return fmt.Errorf("failed connecting to OpenSerp API: %s", res.Status)
392+
}
393+
var osResp []OpenSerpResult
394+
err = json.NewDecoder(res.Body).Decode(&osResp)
395+
if err != nil {
396+
return err
397+
}
398+
for _, item := range osResp {
399+
u, _ := netUrl.Parse(item.URL)
400+
questionId, _ := strconv.Atoi(strings.Split(u.Path, "/")[2])
401+
results[questionId] = &Result{
402+
Title: item.Title,
403+
Link: item.URL,
404+
QuestionId: questionId,
405+
}
406+
}
407+
return nil
408+
}
409+
368410
func FetchStackOverflow(conf *Config, results map[int]*Result) error {
369411
questions := make([]string, len(results))
370412
var idx int

0 commit comments

Comments
 (0)