aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristine Dodrill <me@christine.website>2018-09-30 13:32:15 -0700
committerChristine Dodrill <me@christine.website>2018-09-30 13:33:02 -0700
commite816e3be6d80c30b804de8614cee41c0ce644eea (patch)
tree2f9c535ab05de3d97e4f1a5004b261358ba6a5e9
parentb1af575815bdcc05329f3aa92bcaa46b6fb0ada6 (diff)
downloadx-e816e3be6d80c30b804de8614cee41c0ce644eea.tar.xz
x-e816e3be6d80c30b804de8614cee41c0ce644eea.zip
ilo-kesi: prepare for discord
-rw-r--r--discord/ilo-kesi/bot.go32
-rw-r--r--discord/ilo-kesi/context.go5
-rw-r--r--discord/ilo-kesi/main.go141
-rw-r--r--discord/ilo-kesi/parse.go85
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
+}