package adapter import ( "fmt" . "forge.lightcrystal.systems/lightcrystal/underbbs/models" madon "github.com/McKael/madon" ) 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) 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) self.masto.StreamListener(filter, "", self.events, self.stop, self.done) go func() { for e := range self.events { 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.data <- 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) SendMessage(msg Message) error { return nil } func (self *MastoAdapter) Follow(author Author) error { return nil } func (self *MastoAdapter) Unfollow(author Author) error { return nil } func (self *MastoAdapter) GetFollowers() error { return nil } func (self *MastoAdapter) UpdateMetadata(data interface{}) error { return nil } func (self *MastoAdapter) DefaultSubscriptionFilter() string { return "home" } func (self *MastoAdapter) mastoUpdateToMessage(status madon.Status) *Message { var parent *madon.Status if status.InReplyToID != nil { parent, _ = self.masto.GetStatus(*status.InReplyToID) } msg := Message{ Protocol: "mastodon", Content: status.Content, Uri: status.URI, Author: Author{ Id: fmt.Sprintf("%d", status.Account.ID), Name: status.Account.Username, // TODO: we can add the fields to the profiledata as well ProfileData: status.Account.Note, ProfileUri: status.Account.URL, ProfilePic: status.Account.Avatar, }, Created: status.CreatedAt, } if parent != nil { msg.ReplyTo = &parent.URI } // TODO: mentions and replies msg.Aux = make(map[string]string) msg.Aux["visibility"] = status.Visibility return &msg }