2017-05-09 13:47:49 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"log"
|
|
|
|
"net/http"
|
|
|
|
"net/url"
|
|
|
|
"strings"
|
|
|
|
|
2018-11-08 18:55:34 +00:00
|
|
|
"git.fromouter.space/hamcha/tg"
|
2017-05-09 13:47:49 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type SearchResult struct {
|
|
|
|
Name string
|
|
|
|
Description *string
|
|
|
|
Alternatives []string
|
|
|
|
None bool
|
|
|
|
}
|
|
|
|
|
|
|
|
type SearchResultData struct {
|
|
|
|
ItemListElement []struct {
|
|
|
|
Result struct {
|
|
|
|
Name []struct {
|
|
|
|
Value string `json:"@value"`
|
|
|
|
Lang string `json:"@language"`
|
|
|
|
} `json:"name,omitempty"`
|
|
|
|
Description []struct {
|
|
|
|
Value string `json:"@value"`
|
|
|
|
Lang string `json:"@language"`
|
|
|
|
} `json:"description,omitempty"`
|
|
|
|
DetailedDescription []struct {
|
|
|
|
Value string `json:"articleBody"`
|
|
|
|
Lang string `json:"inLanguage"`
|
|
|
|
} `json:"detailedDescription,omitempty"`
|
|
|
|
} `json:"result"`
|
|
|
|
} `json:"itemListElement"`
|
|
|
|
Error struct {
|
|
|
|
Code int `json:"code"`
|
|
|
|
Message string `json:"message"`
|
|
|
|
} `json:"error,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
const MAX_SEARCH_ALTS = 2
|
|
|
|
|
2018-05-24 15:48:35 +00:00
|
|
|
func search_init() {
|
2017-05-09 13:47:49 +00:00
|
|
|
if strings.HasPrefix(*gapikey, "@") {
|
|
|
|
data, err := ioutil.ReadFile((*gapikey)[1:])
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
*gapikey = strings.TrimSpace(string(data))
|
|
|
|
}
|
|
|
|
if *gapikey == "" {
|
|
|
|
panic(fmt.Errorf("Missing GAPI key for search module (provide it or --disable search)"))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-24 15:48:35 +00:00
|
|
|
func search_message(broker *tg.Broker, update tg.APIMessage) {
|
2017-05-09 13:47:49 +00:00
|
|
|
if isCommand(update, "search") {
|
|
|
|
parts := strings.SplitN(*(update.Text), " ", 2)
|
|
|
|
if len(parts) < 2 {
|
2018-12-13 10:29:45 +00:00
|
|
|
broker.SendTextMessage(update.Chat, "Non mi hai dato niente da cercare!", &tg.MessageOptions{
|
|
|
|
ReplyID: &update.MessageID,
|
|
|
|
})
|
2017-05-09 13:47:49 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
broker.SendChatAction(update.Chat, tg.ActionTyping)
|
|
|
|
|
|
|
|
result, err := searchAPI(parts[1])
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("[search] %s\n", err.Error())
|
2018-12-13 10:29:45 +00:00
|
|
|
broker.SendTextMessage(update.Chat, "<b>ERRORE!</b> @hamcha controlla la console!", &tg.MessageOptions{
|
|
|
|
ReplyID: &update.MessageID,
|
|
|
|
})
|
2017-05-09 13:47:49 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if result.None {
|
2018-12-13 10:29:45 +00:00
|
|
|
broker.SendTextMessage(update.Chat, "Non ho trovato nulla, mi spiace :(", &tg.MessageOptions{
|
|
|
|
ReplyID: &update.MessageID,
|
|
|
|
})
|
2017-05-09 13:47:49 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
resulttxt := fmt.Sprintf("Ecco la prima cosa che ho trovato:\n<b>%s</b>", result.Name)
|
|
|
|
if result.Description != nil {
|
|
|
|
resulttxt += "\n" + *(result.Description)
|
|
|
|
}
|
|
|
|
if len(result.Alternatives) > 0 {
|
|
|
|
resulttxt += "\nAlternativamente:\n - " + strings.Join(result.Alternatives, "\n - ")
|
|
|
|
}
|
|
|
|
|
2018-12-13 10:29:45 +00:00
|
|
|
broker.SendTextMessage(update.Chat, resulttxt, &tg.MessageOptions{
|
|
|
|
ReplyID: &update.MessageID,
|
|
|
|
})
|
2017-05-09 13:47:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func searchAPI(term string) (SearchResult, error) {
|
|
|
|
resp, err := http.Get("https://kgsearch.googleapis.com/v1/entities:search?indent=true&languages=it&languages=en&query=" + url.QueryEscape(term) + "&key=" + *gapikey)
|
|
|
|
if err != nil {
|
|
|
|
return SearchResult{}, err
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
|
|
var res SearchResultData
|
|
|
|
err = json.NewDecoder(resp.Body).Decode(&res)
|
|
|
|
if err != nil {
|
|
|
|
return SearchResult{}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if res.Error.Message != "" {
|
|
|
|
return SearchResult{}, fmt.Errorf("Request error: %d %s", res.Error.Code, res.Error.Message)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(res.ItemListElement) < 1 {
|
|
|
|
return SearchResult{None: true}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
out := SearchResult{None: false}
|
|
|
|
for _, item := range res.ItemListElement {
|
|
|
|
// Skip elements without a name
|
|
|
|
if item.Result.Name == nil || len(item.Result.Name) == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
namestr := item.Result.Name[0].Value
|
|
|
|
|
|
|
|
// Check if it has a small description
|
|
|
|
if item.Result.Description != nil && len(item.Result.Description) > 0 {
|
|
|
|
namestr += " (" + item.Result.Description[0].Value + ")"
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we already had an item, add it to alternatives and find others
|
|
|
|
if out.Name != "" {
|
|
|
|
out.Alternatives = append(out.Alternatives, namestr)
|
|
|
|
if len(out.Alternatives) > MAX_SEARCH_ALTS {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
out.Name = namestr
|
|
|
|
|
|
|
|
// Check for a description
|
|
|
|
if item.Result.DetailedDescription != nil || len(item.Result.DetailedDescription) > 0 {
|
|
|
|
out.Description = &(item.Result.DetailedDescription[0].Value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return out, nil
|
|
|
|
}
|