123 lines
3.5 KiB
Go
123 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/go-telegram/bot"
|
|
)
|
|
|
|
var docApiURL = "https://docs.godotengine.org/_/api/v3/search/?q=project:godot %s"
|
|
var docURL = "https://docs.godotengine.org/en/stable/search.html?q=%s"
|
|
var docApiURL_ru = "https://docs.godotengine.org/_/api/v3/search/?q=project:godot-ru %s"
|
|
var docURL_ru = "https://docs.godotengine.org/ru/4.x/search.html?q=%s"
|
|
var lastDocSearch = time.Now().Add(-1 * time.Hour)
|
|
|
|
type DocResponse struct {
|
|
Count uint `json:"count"`
|
|
Next string `json:"next"`
|
|
Previous string `json:"previous"`
|
|
Results []DocResult `json:"results"`
|
|
}
|
|
|
|
type DocResult struct {
|
|
Title string `json:"title"`
|
|
Domain string `json:"domain"`
|
|
Path string `json:"path"`
|
|
Highlights DocHighlights `json:"highlights"`
|
|
}
|
|
|
|
type DocHighlights struct {
|
|
Title []string `json:"title"`
|
|
}
|
|
|
|
func getAndDecode[T any](u string) (*T, error) {
|
|
req, err := url.ParseRequestURI(u)
|
|
if err != nil {
|
|
log.Println("Can't parse url: ", err)
|
|
return nil, err
|
|
}
|
|
result, err := http.Get(req.String())
|
|
if err != nil {
|
|
log.Println("Can't get http: ", err)
|
|
return nil, err
|
|
}
|
|
defer result.Body.Close()
|
|
var response T
|
|
err = json.NewDecoder(result.Body).Decode(&response)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &response, nil
|
|
}
|
|
|
|
func getDocs(topic string, russian bool) (string, error) {
|
|
apiURL := docApiURL
|
|
pageURL := docURL
|
|
if russian {
|
|
apiURL = docApiURL_ru
|
|
pageURL = docURL_ru
|
|
}
|
|
since := time.Since(lastDocSearch)
|
|
GO_SEARCH_YOURSELF := fmt.Sprintf("\n\n[Попробуйте поискать самостоятельно\\!](%s)", fmt.Sprintf(pageURL, url.QueryEscape(topic)))
|
|
if since < 5*time.Second {
|
|
return "Извините, запросы происходят слишком часто" + GO_SEARCH_YOURSELF, nil
|
|
}
|
|
lastDocSearch = time.Now()
|
|
|
|
topic_escaped := bot.EscapeMarkdown(topic)
|
|
not_found := fmt.Sprintf("Извините, по запросу *%s* ничего не найдено\\."+GO_SEARCH_YOURSELF, topic_escaped)
|
|
exactUrl := fmt.Sprintf(apiURL, url.QueryEscape(topic))
|
|
looselyUrl := fmt.Sprintf(apiURL, url.QueryEscape(topic+"*"))
|
|
response, err := getAndDecode[DocResponse](exactUrl)
|
|
if err != nil || len(response.Results) == 0 {
|
|
response, err = getAndDecode[DocResponse](looselyUrl)
|
|
if err != nil || len(response.Results) == 0 {
|
|
return not_found, nil
|
|
}
|
|
}
|
|
textResults := ""
|
|
for i, r := range response.Results {
|
|
if i > 9 {
|
|
break
|
|
}
|
|
text := bot.EscapeMarkdown(r.Title)
|
|
link, _ := url.JoinPath(r.Domain, r.Path)
|
|
textResults += fmt.Sprintf("%d\\. [%s](%s)\n", i+1, text, link)
|
|
}
|
|
textResults += fmt.Sprintf("\n\n Или вы можете попробовать [поискать самостоятельно](%s)\\!", fmt.Sprintf(pageURL, topic))
|
|
text := fmt.Sprintf("Вот что я нашла по запросу *%s*: \n\n%s", topic_escaped, textResults)
|
|
return text, nil
|
|
}
|
|
|
|
func HandleDocRequest(g Godette) {
|
|
topic := strings.TrimPrefix(g.update.Message.Text, "/docs ")
|
|
text, docerr := getDocs(topic, false)
|
|
if docerr != nil {
|
|
log.Println("Can't get docs: ", docerr)
|
|
}
|
|
|
|
_, err := g.ReplyWithMarkdown(text)
|
|
if err != nil {
|
|
log.Println(err)
|
|
}
|
|
}
|
|
|
|
func HandleDocRequestRu(g Godette) {
|
|
topic := strings.TrimPrefix(g.update.Message.Text, "/docs_ru ")
|
|
text, docerr := getDocs(topic, true)
|
|
if docerr != nil {
|
|
log.Println("Can't get docs: ", docerr)
|
|
}
|
|
|
|
_, err := g.ReplyWithMarkdown(text)
|
|
if err != nil {
|
|
log.Println(err)
|
|
}
|
|
}
|