diff options
| author | Christine Dodrill <me@christine.website> | 2018-10-04 22:48:42 -0700 |
|---|---|---|
| committer | Christine Dodrill <me@christine.website> | 2018-10-04 22:49:08 -0700 |
| commit | 9c9ae00ab8bd7c2a99590daf42fe9df475131929 (patch) | |
| tree | 44b08805061c0a1b21fa605b3e48544542aa3a85 | |
| parent | 9fd916604c371b41111c14e65d5534d4dbc30ff8 (diff) | |
| download | x-9c9ae00ab8bd7c2a99590daf42fe9df475131929.tar.xz x-9c9ae00ab8bd7c2a99590daf42fe9df475131929.zip | |
add bot to translate toki pona to english
| -rw-r--r-- | mastodon/sona-pi-toki-pona/.gitignore | 1 | ||||
| -rw-r--r-- | mastodon/sona-pi-toki-pona/app/Procfile | 1 | ||||
| -rw-r--r-- | mastodon/sona-pi-toki-pona/main.go | 108 | ||||
| -rw-r--r-- | web/tokipana/tokipana.go | 44 |
4 files changed, 154 insertions, 0 deletions
diff --git a/mastodon/sona-pi-toki-pona/.gitignore b/mastodon/sona-pi-toki-pona/.gitignore new file mode 100644 index 0000000..cca091f --- /dev/null +++ b/mastodon/sona-pi-toki-pona/.gitignore @@ -0,0 +1 @@ +sona-pi-toki-pona
\ No newline at end of file diff --git a/mastodon/sona-pi-toki-pona/app/Procfile b/mastodon/sona-pi-toki-pona/app/Procfile new file mode 100644 index 0000000..03dd662 --- /dev/null +++ b/mastodon/sona-pi-toki-pona/app/Procfile @@ -0,0 +1 @@ +worker: /app/bin/sona-pi-toki-pona diff --git a/mastodon/sona-pi-toki-pona/main.go b/mastodon/sona-pi-toki-pona/main.go new file mode 100644 index 0000000..346fe4c --- /dev/null +++ b/mastodon/sona-pi-toki-pona/main.go @@ -0,0 +1,108 @@ +package main + +import ( + "context" + "fmt" + "io/ioutil" + "net/http" + + madon "github.com/McKael/madon/v2" + "github.com/Xe/ln" + "github.com/Xe/ln/opname" + "github.com/Xe/x/web/tokipana" + "github.com/jaytaylor/html2text" + "github.com/joeshaw/envdecode" + _ "github.com/joho/godotenv/autoload" +) + +type lipuSona struct { + AppID string `env:"APP_ID,required"` + AppSecret string `env:"APP_SECRET,required"` + Token string `env:"TOKEN,required"` + Instance string `env:"INSTANCE,required"` +} + +func main() { + ctx := opname.With(context.Background(), "main") + var lipu lipuSona + err := envdecode.StrictDecode(&lipu) + if err != nil { + ln.FatalErr(ctx, err) + } + + c, err := madon.RestoreApp("sona-pi-toki-pona:", lipu.Instance, lipu.AppID, lipu.AppSecret, &madon.UserToken{AccessToken: lipu.Token}) + if err != nil { + ln.FatalErr(opname.With(ctx, "restore-app"), err) + } + + for { + evChan := make(chan madon.StreamEvent, 10) + stop := make(chan bool) + done := make(chan bool) + ctx = opname.With(ctx, "hashtag-stream") + + err = c.StreamListener("hashtag", "tokipona", evChan, stop, done) + if err != nil { + ln.FatalErr(ctx, err) + } + + for { + select { + case _, _ = <-done: + goto redo + case ev := <-evChan: + switch ev.Event { + case "error": + ln.Error(opname.With(ctx, "event-parse"), err) + case "update": + s := ev.Data.(madon.Status) + ctx = opname.With(ctx, "update") + ctx = ln.WithF(ctx, ln.F{ + "originating_status_id": s.ID, + "originating_status_url": s.URL, + }) + + text, err := html2text.FromString(s.Content, html2text.Options{PrettyTables: true}) + if err != nil { + ln.Error(ctx, err) + continue + } + + req := tokipana.Translate(text) + resp, err := http.DefaultClient.Do(req) + if err != nil { + ln.Error(ctx, err) + continue + } + err = tokipana.Validate(resp) + if err != nil { + ln.Error(ctx, err) + continue + } + data, err := ioutil.ReadAll(resp.Body) + resp.Body.Close() + if err != nil { + ln.Error(ctx, err) + continue + } + + st, err := c.PostStatus(madon.PostStatusParams{ + Text: fmt.Sprintf(translationTemplate, string(data)), + InReplyTo: s.ID, + Visibility: "public", + }) + if err != nil { + ln.Error(ctx, err) + continue + } + + ln.Log(ctx, ln.Info("posted translation of toki pona text"), ln.F{"status_id": st.ID, "status_url": st.URL}) + } + } + } + } + +redo: +} + +const translationTemplate = `Translated into English: %s` diff --git a/web/tokipana/tokipana.go b/web/tokipana/tokipana.go new file mode 100644 index 0000000..2daa54b --- /dev/null +++ b/web/tokipana/tokipana.go @@ -0,0 +1,44 @@ +// Package tokipana wraps http://inamidst.com/services/tokipana. +package tokipana + +import ( + "errors" + "net/http" + "net/url" +) + +// The API URL. +const APIURL = `http://inamidst.com/services/tokipana` + +// Errors +var ( + ErrInvalidRequest = errors.New("tokipana: invalid request") +) + +// Validate checks if a response from the API is valid or not. +func Validate(resp *http.Response) error { + if resp.StatusCode == http.StatusOK { + return nil + } + + if resp.StatusCode%100 != 2 { + return ErrInvalidRequest + } + + return nil +} + +// Translate returns a request to translate the given toki pona text into english. +func Translate(text string) *http.Request { + u, _ := url.Parse(APIURL) + q := u.Query() + q.Set("text", text) + u.RawQuery = q.Encode() + + req, err := http.NewRequest(http.MethodGet, u.String(), nil) + if err != nil { + panic(err) + } + + return req +} |
