mods: Add api.ai module (replaces wit.ai WIP module)
This commit is contained in:
parent
1ae8af29ce
commit
318a3f8d16
2 changed files with 143 additions and 46 deletions
|
@ -43,11 +43,10 @@ var mods = map[string]Mod{
|
|||
OnInit: initproverbio,
|
||||
OnMessage: proverbio,
|
||||
},
|
||||
/*
|
||||
"talk": {
|
||||
OnInit: inittalk,
|
||||
OnMessage: talk,
|
||||
},*/
|
||||
},
|
||||
"stt": {
|
||||
OnInit: initstt,
|
||||
OnMessage: stt,
|
||||
|
@ -96,7 +95,7 @@ var impact *string
|
|||
var gillmt *string
|
||||
var sourcesans *string
|
||||
var proverbi *string
|
||||
var wittoken *string
|
||||
var talktoken *string
|
||||
var gapifile *string
|
||||
|
||||
func main() {
|
||||
|
@ -108,7 +107,7 @@ func main() {
|
|||
macropath = flag.String("macropath", "macros.json", "Path to macros db (JSON)")
|
||||
remindpath = flag.String("remindpath", "reminders.json", "Path to reminder db (JSON)")
|
||||
proverbi = flag.String("proverbi", "proverbi.txt", "Path to proverbi pairs (separated by /)")
|
||||
wittoken = flag.String("wit", "", "Wit.ai token")
|
||||
talktoken = flag.String("apiai", "", "api.ai token")
|
||||
gapifile = flag.String("gapi", "gapi.json", "Google API Service Credentials file")
|
||||
disable := flag.String("disable", "", "Blacklist mods (separated by comma)")
|
||||
enable := flag.String("enable", "", "Whitelist mods (separated by comma)")
|
||||
|
|
162
mods/talk.go
162
mods/talk.go
|
@ -1,58 +1,156 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hamcha/clessy/tg"
|
||||
"github.com/kurrik/witgo/v1/witgo"
|
||||
)
|
||||
|
||||
type ClessyHandler struct {
|
||||
type QRequest struct {
|
||||
SessionID string `json:"sessionId"`
|
||||
Query string `json:"query"`
|
||||
Language string `json:"lang"`
|
||||
}
|
||||
|
||||
var wit *witgo.Witgo
|
||||
var witHandler ClessyHandler
|
||||
type QResponse struct {
|
||||
ID string `json:"id"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Result struct {
|
||||
Source string `json:"source"`
|
||||
ResolvedQuery string `json:"resolvedQuery"`
|
||||
Action string `json:"action"`
|
||||
ActionIncomplete bool `json:"actionIncomplete"`
|
||||
Parameters struct {
|
||||
Name string `json:"name"`
|
||||
} `json:"parameters"`
|
||||
Contexts []struct {
|
||||
Name string `json:"name"`
|
||||
Parameters struct {
|
||||
Name string `json:"name"`
|
||||
} `json:"parameters"`
|
||||
Lifespan int `json:"lifespan"`
|
||||
} `json:"contexts"`
|
||||
Metadata struct {
|
||||
IntentID string `json:"intentId"`
|
||||
IntentName string `json:"intentName"`
|
||||
} `json:"metadata"`
|
||||
Fulfillment struct {
|
||||
Speech string `json:"speech"`
|
||||
} `json:"fulfillment"`
|
||||
} `json:"result"`
|
||||
Status struct {
|
||||
Code int `json:"code"`
|
||||
ErrorType string `json:"errorType"`
|
||||
} `json:"status"`
|
||||
}
|
||||
|
||||
const talkBaseURL = "https://api.api.ai/v1"
|
||||
|
||||
func inittalk() {
|
||||
// Disable if token is not provided
|
||||
if *wittoken == "" {
|
||||
panic(errors.New("No or empty wit token provided (-wit)"))
|
||||
if *talktoken == "" {
|
||||
panic(fmt.Errorf("API token for api.ai must be provided! (provide it or --disable talk)"))
|
||||
}
|
||||
|
||||
witgo.NewWitgo(witgo.NewClient(*wittoken), &witHandler)
|
||||
}
|
||||
|
||||
func talk(broker *tg.Broker, update tg.APIMessage) {
|
||||
}
|
||||
|
||||
func (h *ClessyHandler) Action(session *witgo.Session, action string) (response *witgo.Session, err error) {
|
||||
response = session
|
||||
response.Context.Set("forecast", "sunny")
|
||||
// Must be a text message
|
||||
if update.Text == nil {
|
||||
return
|
||||
}
|
||||
text := *(update.Text)
|
||||
|
||||
func (h *ClessyHandler) Say(session *witgo.Session, msg string) (response *witgo.Session, err error) {
|
||||
response = session
|
||||
fmt.Printf("< %v\n", msg)
|
||||
return
|
||||
}
|
||||
|
||||
func (h *ClessyHandler) Merge(session *witgo.Session, entities witgo.EntityMap) (response *witgo.Session, err error) {
|
||||
var (
|
||||
value string
|
||||
)
|
||||
response = session
|
||||
if value, err = entities.FirstEntityValue("location"); err != nil {
|
||||
response.Context = witgo.Context{}
|
||||
err = nil
|
||||
// Make sure it's aimed at Clessy
|
||||
if strings.Index(text, "@"+*botname) >= 0 {
|
||||
// @maudbot <something>
|
||||
text = strings.Replace(text, "@"+*botname, "", 1)
|
||||
} else if idx := strings.Index(strings.ToLower(text), "clessy"); idx == 0 && len(text) > 7 {
|
||||
// Clessy, <something>
|
||||
text = strings.TrimLeft(text[len("clessy"):], ":,")
|
||||
} else if text[0] != '/' && update.ReplyTo != nil && update.ReplyTo.User.Username == *botname {
|
||||
// Reply to Clessy (previous prompt?) which is not a command (such as unsplash), pass
|
||||
} else if update.Chat.Username != nil {
|
||||
// Private chat, pass
|
||||
} else {
|
||||
response.Context.Merge(witgo.Context{
|
||||
"loc": value,
|
||||
return
|
||||
}
|
||||
text = strings.TrimSpace(text)
|
||||
|
||||
// Generate unique id for user
|
||||
id := strconv.FormatInt(update.User.UserID, 36)
|
||||
if len(id) > 36 {
|
||||
id = id[:36]
|
||||
}
|
||||
|
||||
// Create POST body
|
||||
data, err := json.Marshal(QRequest{
|
||||
SessionID: id,
|
||||
Query: text,
|
||||
Language: "it",
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("[talk] Could not create JSON body: %s\n", err.Error())
|
||||
broker.SendTextMessage(update.Chat, "<b>ERRORE!</b> @hamcha controlla la console!", &update.MessageID)
|
||||
return
|
||||
}
|
||||
|
||||
// Build the request
|
||||
req, err := http.NewRequest("POST", talkBaseURL+"/query?v=20150910", bytes.NewReader(data))
|
||||
if err != nil {
|
||||
log.Printf("[talk] Could not create POST request: %s\n", err.Error())
|
||||
broker.SendTextMessage(update.Chat, "<b>ERRORE!</b> @hamcha controlla la console!", &update.MessageID)
|
||||
return
|
||||
}
|
||||
|
||||
req.Header.Add("Authorization", "Bearer "+*talktoken)
|
||||
req.Header.Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
log.Printf("[talk] Request error: %s\n", err.Error())
|
||||
broker.SendTextMessage(update.Chat, "<b>ERRORE!</b> @hamcha controlla la console!", &update.MessageID)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var record QResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&record); err != nil {
|
||||
log.Printf("[talk] Could not decode JSON response: %s\n", err.Error())
|
||||
broker.SendTextMessage(update.Chat, "<b>ERRORE!</b> @hamcha controlla la console!", &update.MessageID)
|
||||
return
|
||||
}
|
||||
|
||||
if record.Status.ErrorType != "success" {
|
||||
body, _ := json.MarshalIndent(record, "", " ")
|
||||
log.Printf("[talk] Non-success status, full response body follows:\n%s\n", body)
|
||||
broker.SendTextMessage(update.Chat, "<b>ERRORE!</b> @hamcha controlla la console!", &update.MessageID)
|
||||
return
|
||||
}
|
||||
|
||||
reply := record.Result.Fulfillment.Speech
|
||||
|
||||
// Replace tokens if found
|
||||
if strings.Index(reply, "$") >= 0 {
|
||||
reply = strings.Replace(reply, "$name", update.User.FirstName, -1)
|
||||
}
|
||||
|
||||
// Call command if needed
|
||||
if reply[0] == '#' {
|
||||
//TODO Find a better way?
|
||||
if strings.HasPrefix(reply, "#metafora") {
|
||||
message := "/metafora"
|
||||
update.Text = &message
|
||||
metafora(broker, update)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (h *ClessyHandler) Error(session *witgo.Session, msg string) {
|
||||
broker.SendTextMessage(update.Chat, reply, &update.MessageID)
|
||||
}
|
||||
|
|
Reference in a new issue