diff options
| author | Christine Dodrill <me@christine.website> | 2018-09-30 13:32:15 -0700 |
|---|---|---|
| committer | Christine Dodrill <me@christine.website> | 2018-09-30 13:33:02 -0700 |
| commit | e816e3be6d80c30b804de8614cee41c0ce644eea (patch) | |
| tree | 2f9c535ab05de3d97e4f1a5004b261358ba6a5e9 | |
| parent | b1af575815bdcc05329f3aa92bcaa46b6fb0ada6 (diff) | |
| download | x-e816e3be6d80c30b804de8614cee41c0ce644eea.tar.xz x-e816e3be6d80c30b804de8614cee41c0ce644eea.zip | |
ilo-kesi: prepare for discord
| -rw-r--r-- | discord/ilo-kesi/bot.go | 32 | ||||
| -rw-r--r-- | discord/ilo-kesi/context.go | 5 | ||||
| -rw-r--r-- | discord/ilo-kesi/main.go | 141 | ||||
| -rw-r--r-- | discord/ilo-kesi/parse.go | 85 |
4 files changed, 190 insertions, 73 deletions
diff --git a/discord/ilo-kesi/bot.go b/discord/ilo-kesi/bot.go new file mode 100644 index 0000000..07c0721 --- /dev/null +++ b/discord/ilo-kesi/bot.go @@ -0,0 +1,32 @@ +package main + +import ( + "errors" + + "github.com/Xe/x/web/switchcounter" +) + +// ilo li ilo pi toki sona. +type ilo struct { + cfg lipuSona + sw switchcounter.API + chain *Chain +} + +var ( + ErrJanLawaAla = errors.New("ilo-kesi: sina jan lawa ala") +) + +func (i ilo) janLawaAnuSeme(authorID string) bool { + for _, jan := range i.cfg.janLawa { + if authorID == jan { + return true + } + } + + return false +} + +type reply struct { + msg string +} diff --git a/discord/ilo-kesi/context.go b/discord/ilo-kesi/context.go index 90726af..8762bc5 100644 --- a/discord/ilo-kesi/context.go +++ b/discord/ilo-kesi/context.go @@ -23,10 +23,13 @@ type Request struct { Action string Subject string Punct string + + Author string } -func parseRequest(inp tokiponatokens.Sentence) (*Request, error) { +func parseRequest(authorID string, inp tokiponatokens.Sentence) (*Request, error) { var result Request + result.Author = authorID for _, part := range inp { switch part.Type { diff --git a/discord/ilo-kesi/main.go b/discord/ilo-kesi/main.go index 2622be2..a0f27e9 100644 --- a/discord/ilo-kesi/main.go +++ b/discord/ilo-kesi/main.go @@ -1,28 +1,35 @@ package main import ( - "context" "flag" "fmt" "log" "math/rand" "net/http" + "os" + "os/signal" + "syscall" "time" "github.com/Xe/x/internal" "github.com/Xe/x/web/switchcounter" - "github.com/Xe/x/web/tokiponatokens" + "github.com/bwmarrin/discordgo" "github.com/joeshaw/envdecode" _ "github.com/joho/godotenv/autoload" "github.com/peterh/liner" ) +var ( + repl = flag.Bool("repl", false, "open a bot repl in the console?") +) + // lipuSona is the configuration. type lipuSona struct { - //DiscordToken string `env:"DISCORD_TOKEN,required"` // lipu pi lukin ala - TokiPonaTokenizerAPIURL string `env:"TOKI_PONA_TOKENIZER_API_URL,default=https://us-central1-golden-cove-408.cloudfunctions.net/function-1"` - SwitchCounterWebhook string `env:"SWITCH_COUNTER_WEBHOOK,required"` - IloNimi string `env:"ILO_NIMI,default=Kesi"` + DiscordToken string `env:"DISCORD_TOKEN,required"` // lipu pi lukin ala + TokiPonaTokenizerAPIURL string `env:"TOKI_PONA_TOKENIZER_API_URL,default=https://us-central1-golden-cove-408.cloudfunctions.net/function-1"` + SwitchCounterWebhook string `env:"SWITCH_COUNTER_WEBHOOK,required"` + IloNimi string `env:"ILO_NIMI,default=Kesi"` + janLawa []string `env:"JAN_LAWA,required"` } func init() { @@ -30,11 +37,15 @@ func init() { } func main() { + flag.Parse() + internal.HandleLicense() + var cfg lipuSona err := envdecode.StrictDecode(&cfg) if err != nil { log.Fatal(err) } + cfg.janLawa = append(cfg.janLawa, "console") flag.Parse() internal.HandleLicense() @@ -52,85 +63,71 @@ func main() { log.Fatal(err) } + i := ilo{ + cfg: cfg, + sw: sw, + chain: chain, + } + line.SetCtrlCAborts(true) - for { - if inp, err := line.Prompt("|: "); err == nil { - if inp == "" { - return - } + mc := func(s *discordgo.Session, m *discordgo.MessageCreate) { + // Ignore all messages created by the bot itself + // This isn't required in this specific example but it's a good practice. + if m.Author.ID == s.State.User.ID { + return + } - line.AppendHistory(inp) + result, err := i.parse(m.Author.ID, m.ContentWithMentionsReplaced()) + if err != nil { + s.ChannelMessageSend(m.ChannelID, fmt.Sprintf("mi tawa ala la %v", err)) + return + } - parts, err := tokiponatokens.Tokenize(cfg.TokiPonaTokenizerAPIURL, inp) - if err != nil { - log.Printf("Can't parse: %v", err) - } + s.ChannelMessageSend(m.ChannelID, result.msg) + } - for _, sent := range parts { - req, err := parseRequest(sent) - if err != nil { - log.Printf("error: %v", err) - continue - } + dg, err := discordgo.New("Bot " + cfg.DiscordToken) + if err != nil { + log.Fatal(err) + } - if len(req.Address) != 2 { - log.Println("ilo Kesi was not addressed") - continue - } + dg.AddHandler(mc) + err = dg.Open() + if err != nil { + log.Fatal(err) + } + defer dg.Close() - if req.Address[0] != "ilo" { - log.Println("Addressed non-ilo") - continue + if *repl { + for { + if inp, err := line.Prompt("|: "); err == nil { + if inp == "" { + return } - if req.Address[1] != cfg.IloNimi { - log.Printf("ilo %s was addressed, not ilo %s", req.Address[1], cfg.IloNimi) - continue - } + line.AppendHistory(inp) - switch req.Action { - case actionFront: - if req.Subject == actionWhat { - st, err := sw.Status(context.Background()) - if err != nil { - log.Printf("status error: %v", err) - continue - } - - qual := TimeToQualifier(st.StartedAt) - fmt.Printf("ilo Kesi\\ %s la jan %s li lawa insa.\n", qual, withinToToki[st.Front]) - - continue - } - - front := tokiToWithin[req.Subject] - - _, err := sw.Switch(context.Background(), front) - if err != nil { - log.Printf("switch error: %v", err) - continue - } - - fmt.Printf("ilo Kesi\\ tenpo ni la jan %s li lawa insa.\n", req.Subject) - case actionWhat: - switch req.Subject { - case "tenpo ni": - fmt.Printf("ilo Kesi\\ ni li tenpo %s\n", time.Now().Format(time.Kitchen)) - continue - } + result, err := i.parse("console", inp) + if err != nil { + log.Printf("error: %v", err) } - switch req.Subject { - case "sitelen pakala": - fmt.Printf("ilo Kesi\\ %s\n", chain.Generate(20)) - continue - } + fmt.Println(result.msg) + } else if err == liner.ErrPromptAborted { + log.Print("Aborted") + break + } else { + log.Print("Error reading line: ", err) + break } - } else if err == liner.ErrPromptAborted { - log.Print("Aborted") - } else { - log.Print("Error reading line: ", err) } + + os.Exit(0) + } else { + log.Println("bot is running") + sc := make(chan os.Signal, 1) + signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill) + <-sc } } diff --git a/discord/ilo-kesi/parse.go b/discord/ilo-kesi/parse.go new file mode 100644 index 0000000..350bf69 --- /dev/null +++ b/discord/ilo-kesi/parse.go @@ -0,0 +1,85 @@ +package main + +import ( + "bytes" + "context" + "errors" + "fmt" + "time" + + "github.com/Xe/x/web/tokiponatokens" +) + +var ( + ErrNotAddressed = errors.New("ilo-kesi: ilo kesi was not addressed") +) + +func (i ilo) parse(authorID, inp string) (*reply, error) { + var result reply + buf := bytes.NewBuffer(nil) + + parts, err := tokiponatokens.Tokenize(i.cfg.TokiPonaTokenizerAPIURL, inp) + if err != nil { + return nil, err + } + + for _, sent := range parts { + req, err := parseRequest(authorID, sent) + if err != nil { + return nil, err + } + + if len(req.Address) != 2 { + return nil, ErrNotAddressed + } + + if req.Address[0] != "ilo" { + return nil, ErrNotAddressed + } + + if req.Address[1] != i.cfg.IloNimi { + return nil, ErrNotAddressed + } + + switch req.Action { + case actionFront: + if !i.janLawaAnuSeme(authorID) { + return nil, ErrJanLawaAla + } + + if req.Subject == actionWhat { + st, err := i.sw.Status(context.Background()) + if err != nil { + return nil, err + } + + qual := TimeToQualifier(st.StartedAt) + fmt.Fprintf(buf, "%s la jan %s li lawa insa.\n", qual, withinToToki[st.Front]) + } + + front := tokiToWithin[req.Subject] + + _, err := i.sw.Switch(context.Background(), front) + if err != nil { + return nil, err + } + + fmt.Fprintf(buf, "tenpo ni la jan %s li lawa insa.\n", req.Subject) + case actionWhat: + switch req.Subject { + case "tenpo ni": + fmt.Fprintf(buf, "ni li tenpo %s\n", time.Now().Format(time.Kitchen)) + } + } + + switch req.Subject { + case "sitelen pakala": + fmt.Fprintf(buf, "%s\n", i.chain.Generate(20)) + } + } + + result.msg = buf.String() + buf.Reset() + + return &result, nil +} |
