diff --git a/adapter/mastodon.go b/adapter/mastodon.go index 1d0d16f..5923c73 100644 --- a/adapter/mastodon.go +++ b/adapter/mastodon.go @@ -22,10 +22,9 @@ type MastoAdapter struct { var scopes = []string{"read", "write", "follow"} func (self *MastoAdapter) Name() string { - return self.nickname + return self.nickname } - func (self *MastoAdapter) Init(settings Settings, data chan SocketData) error { self.nickname = settings.Nickname self.server = *settings.Server diff --git a/adapter/misskey.go b/adapter/misskey.go index a8c5be7..3e2e96f 100644 --- a/adapter/misskey.go +++ b/adapter/misskey.go @@ -7,9 +7,10 @@ import ( mkcore "github.com/yitsushi/go-misskey/core" mkm "github.com/yitsushi/go-misskey/models" n "github.com/yitsushi/go-misskey/services/notes" - users "github.com/yitsushi/go-misskey/services/users" tl "github.com/yitsushi/go-misskey/services/notes/timeline" + users "github.com/yitsushi/go-misskey/services/users" "strings" + "sync" "time" ) @@ -25,12 +26,13 @@ type MisskeyAdapter struct { // from different API calls instead of streaming them in a single channel cache map[string]time.Time + mtx sync.RWMutex stop chan bool } func (self *MisskeyAdapter) Name() string { - return self.nickname + return self.nickname } func (self *MisskeyAdapter) Init(settings Settings, data chan SocketData) error { @@ -99,8 +101,8 @@ func (self *MisskeyAdapter) poll() { default: // TODO: we have to actually decode and pass our filter criteria - // probe for new notes + // probe for new notes probenote, err := timelineService.Get(tl.GetRequest{ Limit: 1, }) @@ -166,32 +168,36 @@ func (self *MisskeyAdapter) poll() { time.Sleep(5 * time.Second) } - } - } func (self *MisskeyAdapter) isNew(n mkm.Note) bool { + self.mtx.RLock() timestamp, exists := self.cache[n.ID] + self.mtx.RUnlock() return !exists || timestamp.Before(n.CreatedAt) } func (self *MisskeyAdapter) toMessageIfNew(n mkm.Note) *Message { - return self.toMessage(n, false); + return self.toMessage(n, false) } func (self *MisskeyAdapter) toMessage(n mkm.Note, bustCache bool) *Message { + self.mtx.RLock() timestamp, exists := self.cache[n.ID] + self.mtx.RUnlock() if bustCache || !exists || timestamp.Before(n.CreatedAt) { - host := mkcore.StringValue(n.User.Host) - authorId := "" - if host != "" { - authorId = fmt.Sprintf("@%s@%s", n.User.Username, host) - } else { - authorId = fmt.Sprintf("@%s", n.User.Username) - } - + host := mkcore.StringValue(n.User.Host) + authorId := "" + if host != "" { + authorId = fmt.Sprintf("@%s@%s", n.User.Username, host) + } else { + authorId = fmt.Sprintf("@%s", n.User.Username) + } + + self.mtx.Lock() self.cache[n.ID] = n.CreatedAt + self.mtx.Unlock() msg := Message{ Datagram: Datagram{ Id: n.ID, @@ -227,102 +233,109 @@ func (self *MisskeyAdapter) toMessage(n mkm.Note, bustCache bool) *Message { } func (self *MisskeyAdapter) toAuthor(usr mkm.User) *Author { - fmt.Println("converting author: " + usr.ID) - host := mkcore.StringValue(usr.Host) + fmt.Println("converting author: " + usr.ID) + host := mkcore.StringValue(usr.Host) authorId := "" if host != "" { - authorId = fmt.Sprintf("@%s@%s", usr.Username, host) + authorId = fmt.Sprintf("@%s@%s", usr.Username, host) } else { - authorId = fmt.Sprintf("@%s", usr.Username) + authorId = fmt.Sprintf("@%s", usr.Username) } - - author := Author{ - Datagram: Datagram { - Id: authorId, - Uri: mkcore.StringValue(usr.URL), - Protocol: "misskey", - Adapter: self.nickname, - Type: "author", - }, - Name: usr.Name, - ProfilePic: usr.AvatarURL, - ProfileData: usr.Description, - } - - return &author + + author := Author{ + Datagram: Datagram{ + Id: authorId, + Uri: mkcore.StringValue(usr.URL), + Protocol: "misskey", + Adapter: self.nickname, + Type: "author", + }, + Name: usr.Name, + ProfilePic: usr.AvatarURL, + ProfileData: usr.Description, + } + + return &author } func (self *MisskeyAdapter) Fetch(etype, id string) error { - switch (etype) { - case "message": - data, err := self.mk.Notes().Show(id) - if err != nil { - return err - } else { - msg := self.toMessage(data, true) - if msg != nil { - self.data <- msg - } - } - case "children": - data, err := self.mk.Notes().Children(n.ChildrenRequest{ - NoteID: id, - Limit: 100, - }) - if err != nil { - return err - } else { - for _, n := range data { - msg := self.toMessage(n, true) - if msg != nil { - self.data <- msg - } - } - } - case "convoy": - data, err := self.mk.Notes().Conversation(n.ConversationRequest{ - NoteID: id, - Limit: 100, - }) - if err != nil { - return err - } else { - for _, n := range data { - msg := self.toMessage(n, true) - if msg != nil{ - self.data <- msg - } - } - } - case "author": - user := "" - host := "" - idParts := strings.Split(id, "@") - user = idParts[0] - if len(idParts) == 2 { - host = idParts[1] - } + switch etype { + case "message": + data, err := self.mk.Notes().Show(id) + if err != nil { + return err + } else { + msg := self.toMessage(data, true) + if msg != nil { + self.data <- msg + } + } + case "children": + data, err := self.mk.Notes().Children(n.ChildrenRequest{ + NoteID: id, + Limit: 100, + }) + if err != nil { + return err + } else { + for _, n := range data { + msg := self.toMessage(n, true) + if msg != nil { + self.data <- msg + } + } + } + case "convoy": + data, err := self.mk.Notes().Conversation(n.ConversationRequest{ + NoteID: id, + Limit: 100, + }) + if err != nil { + return err + } else { + for _, n := range data { + msg := self.toMessage(n, true) + if msg != nil { + self.data <- msg + } + } + } + case "author": + user := "" + host := "" + fmt.Printf("fetch author: %s\n", id) + idParts := strings.Split(id, "@") + user = idParts[1] + if len(idParts) == 3 { + host = idParts[2] + } - var hostPtr *string = nil - if len(host) > 0 { - hostPtr = &host - } - - // fmt.Printf("attempting user resolution: @%s@%s\n", user, host) - data, err := self.mk.Users().Show(users.ShowRequest{ - Username: &user, - Host: hostPtr, - }) - if err != nil { - return err - } else { - a := self.toAuthor(data) - if a != nil { - self.data <- a - } - } + var hostPtr *string = nil + if len(host) > 0 { + hostPtr = &host + } - } + if hostPtr == nil { + fmt.Printf("looking up user: @%s\n", user) + } else { + fmt.Printf("looking up remote user: @%s@%s\n", user, host) + } + + // fmt.Printf("attempting user resolution: @%s@%s\n", user, host) + data, err := self.mk.Users().Show(users.ShowRequest{ + Username: &user, + Host: hostPtr, + }) + if err != nil { + return err + } else { + a := self.toAuthor(data) + if a != nil { + self.data <- a + } + } + + } return nil } diff --git a/adapter/nostr.go b/adapter/nostr.go index 9d0e6e8..0906d58 100644 --- a/adapter/nostr.go +++ b/adapter/nostr.go @@ -18,7 +18,7 @@ type NostrAdapter struct { } func (self *NostrAdapter) Name() string { - return self.nickname + return self.nickname } func (self *NostrAdapter) Init(settings Settings, data chan SocketData) error { diff --git a/build.sh b/build.sh index 76c3fe1..ca76d27 100755 --- a/build.sh +++ b/build.sh @@ -1,7 +1,7 @@ #!/bin/sh case "$1" in - client) + front) if [ ! -e ./frontend/.js ]; then mkdir ./frontend/.js fi @@ -13,10 +13,10 @@ case "$1" in fi if [ -s ${buildlog} ]; then cat ${buildlog} | head - rm ${buildlog} else npx webpack --config webpack.config.js fi + rm ${buildlog} ;; server) go mod tidy diff --git a/models/msg.go b/models/msg.go index 74a94e6..ec0ad9d 100644 --- a/models/msg.go +++ b/models/msg.go @@ -6,42 +6,42 @@ import ( ) type Datagram struct { - Id string `json:"id"` - Uri string `json:"uri"` - Protocol string `json:"protocol"` - Adapter string `json:"adapter"` - Type string `json:"type"` + Id string `json:"id"` + Uri string `json:"uri"` + Protocol string `json:"protocol"` + Adapter string `json:"adapter"` + Type string `json:"type"` Target *string `json:"target,omitempty"` } type Message struct { Datagram - Author string `json:"author"` - Content string `json:"content"` - Attachments []Attachment `json:"attachments"` - ReplyTo *string `json:"replyTo"` - Replies []string `json:"replies"` - ReplyCount int `json:"replyCount"` - Mentions []string `json:"mentions"` - Created time.Time `json:"created"` - Edited *time.Time `json:"edited,omitempty"` - Visibility string `json:"visibility"` + Author string `json:"author"` + Content string `json:"content"` + Attachments []Attachment `json:"attachments"` + ReplyTo *string `json:"replyTo"` + Replies []string `json:"replies"` + ReplyCount int `json:"replyCount"` + Mentions []string `json:"mentions"` + Created time.Time `json:"created"` + Edited *time.Time `json:"edited,omitempty"` + Visibility string `json:"visibility"` } type Author struct { Datagram - Name string `json:"name"` + Name string `json:"name"` ProfileData interface{} `json:"profileData"` - ProfilePic string `json:"profilePic"` - Messages []string `json:"messages,omitempty"` + ProfilePic string `json:"profilePic"` + Messages []string `json:"messages,omitempty"` } type Attachment struct { - Src string `json:"src"` - ThumbSrc string `json:"thumbSrc"` - Desc string `json:"desc"` + Src string `json:"src"` + ThumbSrc string `json:"thumbSrc"` + Desc string `json:"desc"` CreatedAt time.Time `json:"createdAt"` - Size uint64 `json:"size"` + Size uint64 `json:"size"` } type SocketData interface { diff --git a/server/api.go b/server/api.go index a3952c9..b0d5771 100644 --- a/server/api.go +++ b/server/api.go @@ -148,8 +148,8 @@ func ProtectWithSubscriberKey(next http.Handler, subscribers map[*Subscriber][]a if strings.HasPrefix(authHeader, "Bearer ") { subscriberKey := strings.Split(authHeader, "Bearer ")[1] if getSubscriberByKey(subscriberKey, subscribers) != nil { - next.ServeHTTP(w, req); - return + next.ServeHTTP(w, req) + return } } w.WriteHeader(http.StatusUnauthorized) @@ -157,34 +157,33 @@ func ProtectWithSubscriberKey(next http.Handler, subscribers map[*Subscriber][]a } func apiAdapterFetch(next http.Handler, subscribers map[*Subscriber][]adapter.Adapter) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - authHeader := req.Header.Get("Authorization") + return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + authHeader := req.Header.Get("Authorization") if strings.HasPrefix(authHeader, "Bearer ") { subscriberKey := strings.Split(authHeader, "Bearer ")[1] s := getSubscriberByKey(subscriberKey, subscribers) if s != nil { - apiParams := req.Context().Value("params").(map[string]string) - queryParams := req.URL.Query() - for _, a := range subscribers[s] { - if a.Name() == apiParams["adapter_id"] { - err := a.Fetch(queryParams["entity_type"][0], queryParams["entity_id"][0]) - if err != nil { - fmt.Println(err.Error()) - w.WriteHeader(http.StatusInternalServerError) - } else { - w.WriteHeader(http.StatusAccepted) - } - next.ServeHTTP(w, req) - return - } - } + apiParams := req.Context().Value("params").(map[string]string) + queryParams := req.URL.Query() + for _, a := range subscribers[s] { + if a.Name() == apiParams["adapter_id"] { + err := a.Fetch(queryParams["entity_type"][0], queryParams["entity_id"][0]) + if err != nil { + fmt.Println(err.Error()) + w.WriteHeader(http.StatusInternalServerError) + } else { + w.WriteHeader(http.StatusAccepted) + } + next.ServeHTTP(w, req) + return + } + } } } w.WriteHeader(http.StatusUnauthorized) }) } - func (self *BBSServer) apiMux() http.Handler { errTemplate, err := template.New("err").Parse("{{ $params := (.Context).Value \"params\" }}

ERROR {{ $params.ErrorCode }}

{{ $params.ErrorMessage }}

") if err != nil { @@ -209,10 +208,10 @@ func (self *BBSServer) apiMux() http.Handler { apiAdapterSubscribe(renderer.JSON("data")), self.subscribers, )) - + rtr.Get(`/adapters/(?P\S+)/fetch`, ProtectWithSubscriberKey( - apiAdapterFetch(renderer.JSON("data"), self.subscribers), - self.subscribers, + apiAdapterFetch(renderer.JSON("data"), self.subscribers), + self.subscribers, )) return http.HandlerFunc(rtr.ServeHTTP)