package adapter import ( "fmt" . "forge.lightcrystal.systems/lightcrystal/underbbs/models" madon "github.com/McKael/madon" "log" "os" ) type MastoAdapter struct { data *chan SocketData nickname string server string apiKey string masto *madon.Client events chan madon.StreamEvent stop chan bool done chan bool } var scopes = []string{"read", "write", "follow"} func (self *MastoAdapter) send(data SocketData) { if self.data != nil { *self.data <- data } else { fmt.Println(os.Stdout, string(data.ToDatagram())) } } func (self *MastoAdapter) Name() string { return self.nickname } func (self *MastoAdapter) Init(settings Settings, data *chan SocketData) error { self.nickname = settings.Nickname self.server = *settings.Server self.apiKey = *settings.ApiKey self.data = data masto, err := madon.NewApp("underbbs", "https://lightcrystal.systems", scopes, madon.NoRedirect, self.server) if err != nil { return err } self.masto = masto err = self.masto.SetUserToken(self.apiKey, "", "", []string{}) return err } func (self *MastoAdapter) Subscribe(filter string) []error { // TODO: decode separate timelines and hashtags // for now, the filter is just the timeline if self.events != nil { close(self.events) } self.events = make(chan madon.StreamEvent) if self.stop != nil { close(self.stop) } self.stop = make(chan bool) self.done = make(chan bool) err := self.masto.StreamListener(filter, "", self.events, self.stop, self.done) if err != nil { return []error{err} } go func() { for e := range self.events { log.Printf("event: %s !!!", e.Event) switch e.Event { case "error": case "update": var msg *Message switch v := e.Data.(type) { case int64: s, _ := self.masto.GetStatus(v) if s != nil { msg = self.mastoUpdateToMessage(*s) } case madon.Status: msg = self.mastoUpdateToMessage(v) } if msg != nil { self.send(msg) } case "notification": case "delete": } } }() // in the background, read and translate events from the stream // and check for doneCh closing // the stopCh will be closed by a subsequent call to subscribe return nil } func (self *MastoAdapter) Fetch(etype string, ids []string) error { return nil } func (self *MastoAdapter) Do(action string, data map[string]string) error { return nil } func (self *MastoAdapter) DefaultSubscriptionFilter() string { return "user" } func (self *MastoAdapter) mastoUpdateToMessage(status madon.Status) *Message { msg := Message{ Datagram: Datagram{ Protocol: "mastodon", Adapter: self.nickname, Id: fmt.Sprintf("%d", status.ID), Uri: status.URI, Type: "message", Created: status.CreatedAt.UnixMilli(), }, Content: status.Content, Author: status.Account.Acct, Visibility: status.Visibility, } if status.InReplyToID != nil { idStr := fmt.Sprintf("%d", *status.InReplyToID) msg.ReplyTo = &idStr } // TODO: mentions and replies return &msg }