TeslaBot is a simple Keybase bot to control a Tesla, storing access tokens in KVStore
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

124 lines
2.9 KiB

package main
import (
"context"
"encoding/json"
"strings"
"github.com/bogosj/tesla"
"github.com/google/uuid"
"github.com/rudi9719/loggy"
"golang.org/x/oauth2"
"samhofi.us/x/keybase/v2"
"samhofi.us/x/keybase/v2/types/chat1"
)
var (
k = keybase.NewKeybase()
log = loggy.NewLogger(loggy.LogOpts{
OutFile: "teslabot.log",
KBTeam: "nightmarehaus.logs",
KBChann: "teslabot",
Level: 5,
ProgName: "TeslaBot",
UseStdout: true,
})
commands []BotCommand
)
func main() {
chat := handleChat
handlers := keybase.Handlers{
ChatHandler: &chat,
}
setupCommands()
var adCmds []chat1.UserBotCommandInput
for _, v := range commands {
adCmds = append(adCmds, v.Advert.Commands...)
}
ads := chat1.AdvertiseCommandAPIParam{
Typ: "public",
Commands: adCmds,
}
cmds := keybase.AdvertiseCommandsOptions{
Alias: "Tesla Bot",
Advertisements: []chat1.AdvertiseCommandAPIParam{ads},
}
k.AdvertiseCommands(cmds)
k.Run(handlers, &keybase.RunOptions{})
}
func handleChat(m chat1.MsgSummary) {
defer log.PanicSafe()
if m.Content.TypeName != "text" {
return
}
parts := strings.Split(m.Content.Text.Body, " ")
command := strings.Replace(parts[0], "!", "", -1)
for _, v := range commands {
for _, test := range v.Triggers {
if command == test {
go v.Exec(m)
return
}
}
}
}
func isAuthenticated(m chat1.MsgSummary) bool {
test, _ := k.KVGet(&m.Channel.Name, "teslabot", "authtok")
return test.EntryValue != ""
}
func getTeslaClient(m chat1.MsgSummary) *tesla.Client {
var t *oauth2.Token
if !isAuthenticated(m) {
k.SendMessageByConvID(m.ConvID, "You are not authenticated.")
return nil
}
test, _ := k.KVGet(&m.Channel.Name, "teslabot", "authtok")
err := json.Unmarshal([]byte(test.EntryValue), &t)
if err != nil {
tracker := uuid.NewString()
k.SendMessageByConvID(m.ConvID, "There was an retrieving token from KVStore. Contact @rudi9719 for more information with code %+v", tracker)
log.LogError("%+v: %+v", tracker, err)
return nil
}
c, err := tesla.NewClient(context.Background(), tesla.WithToken(t))
if err != nil {
tracker := uuid.NewString()
k.SendMessageByConvID(m.ConvID, "There was an error logging in. Contact @rudi9719 for more information with code %+v", tracker)
log.LogError("%+v: %+v", tracker, err)
return nil
}
return c
}
func getVehicle(m chat1.MsgSummary) *tesla.Vehicle {
c := getTeslaClient(m)
if c == nil {
return nil
}
parts := strings.Split(m.Content.Text.Body, " ")
vehicles, err := c.Vehicles()
if err != nil {
tracker := uuid.NewString()
k.SendMessageByConvID(m.ConvID, "There was an error listing vehicles. Contact @rudi9719 for more information with code %+v", tracker)
log.LogError("%+v: %+v", tracker, err)
return nil
}
v := vehicles[0]
if len(parts) == 2 {
for _, test := range vehicles {
if parts[1] == test.Vin {
v = test
}
if parts[1] == test.DisplayName {
v = test
}
}
}
return v
}