fix misskey author fetch, fmt

This commit is contained in:
Iris Lightshard 2024-07-07 14:54:33 -06:00
parent 44bdad2e50
commit fead16168a
Signed by: Iris Lightshard
GPG key ID: 688407174966CAF3
6 changed files with 162 additions and 151 deletions

View file

@ -22,10 +22,9 @@ type MastoAdapter struct {
var scopes = []string{"read", "write", "follow"} var scopes = []string{"read", "write", "follow"}
func (self *MastoAdapter) Name() string { func (self *MastoAdapter) Name() string {
return self.nickname return self.nickname
} }
func (self *MastoAdapter) Init(settings Settings, data chan SocketData) error { func (self *MastoAdapter) Init(settings Settings, data chan SocketData) error {
self.nickname = settings.Nickname self.nickname = settings.Nickname
self.server = *settings.Server self.server = *settings.Server

View file

@ -7,9 +7,10 @@ import (
mkcore "github.com/yitsushi/go-misskey/core" mkcore "github.com/yitsushi/go-misskey/core"
mkm "github.com/yitsushi/go-misskey/models" mkm "github.com/yitsushi/go-misskey/models"
n "github.com/yitsushi/go-misskey/services/notes" 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" tl "github.com/yitsushi/go-misskey/services/notes/timeline"
users "github.com/yitsushi/go-misskey/services/users"
"strings" "strings"
"sync"
"time" "time"
) )
@ -25,12 +26,13 @@ type MisskeyAdapter struct {
// from different API calls instead of streaming them in a single channel // from different API calls instead of streaming them in a single channel
cache map[string]time.Time cache map[string]time.Time
mtx sync.RWMutex
stop chan bool stop chan bool
} }
func (self *MisskeyAdapter) Name() string { func (self *MisskeyAdapter) Name() string {
return self.nickname return self.nickname
} }
func (self *MisskeyAdapter) Init(settings Settings, data chan SocketData) error { func (self *MisskeyAdapter) Init(settings Settings, data chan SocketData) error {
@ -99,8 +101,8 @@ func (self *MisskeyAdapter) poll() {
default: default:
// TODO: we have to actually decode and pass our filter criteria // 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{ probenote, err := timelineService.Get(tl.GetRequest{
Limit: 1, Limit: 1,
}) })
@ -166,32 +168,36 @@ func (self *MisskeyAdapter) poll() {
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)
} }
} }
} }
func (self *MisskeyAdapter) isNew(n mkm.Note) bool { func (self *MisskeyAdapter) isNew(n mkm.Note) bool {
self.mtx.RLock()
timestamp, exists := self.cache[n.ID] timestamp, exists := self.cache[n.ID]
self.mtx.RUnlock()
return !exists || timestamp.Before(n.CreatedAt) return !exists || timestamp.Before(n.CreatedAt)
} }
func (self *MisskeyAdapter) toMessageIfNew(n mkm.Note) *Message { 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 { func (self *MisskeyAdapter) toMessage(n mkm.Note, bustCache bool) *Message {
self.mtx.RLock()
timestamp, exists := self.cache[n.ID] timestamp, exists := self.cache[n.ID]
self.mtx.RUnlock()
if bustCache || !exists || timestamp.Before(n.CreatedAt) { if bustCache || !exists || timestamp.Before(n.CreatedAt) {
host := mkcore.StringValue(n.User.Host) host := mkcore.StringValue(n.User.Host)
authorId := "" authorId := ""
if host != "" { if host != "" {
authorId = fmt.Sprintf("@%s@%s", n.User.Username, host) authorId = fmt.Sprintf("@%s@%s", n.User.Username, host)
} else { } else {
authorId = fmt.Sprintf("@%s", n.User.Username) authorId = fmt.Sprintf("@%s", n.User.Username)
} }
self.mtx.Lock()
self.cache[n.ID] = n.CreatedAt self.cache[n.ID] = n.CreatedAt
self.mtx.Unlock()
msg := Message{ msg := Message{
Datagram: Datagram{ Datagram: Datagram{
Id: n.ID, 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 { func (self *MisskeyAdapter) toAuthor(usr mkm.User) *Author {
fmt.Println("converting author: " + usr.ID) fmt.Println("converting author: " + usr.ID)
host := mkcore.StringValue(usr.Host) host := mkcore.StringValue(usr.Host)
authorId := "" authorId := ""
if host != "" { if host != "" {
authorId = fmt.Sprintf("@%s@%s", usr.Username, host) authorId = fmt.Sprintf("@%s@%s", usr.Username, host)
} else { } else {
authorId = fmt.Sprintf("@%s", usr.Username) authorId = fmt.Sprintf("@%s", usr.Username)
} }
author := Author{ author := Author{
Datagram: Datagram { Datagram: Datagram{
Id: authorId, Id: authorId,
Uri: mkcore.StringValue(usr.URL), Uri: mkcore.StringValue(usr.URL),
Protocol: "misskey", Protocol: "misskey",
Adapter: self.nickname, Adapter: self.nickname,
Type: "author", Type: "author",
}, },
Name: usr.Name, Name: usr.Name,
ProfilePic: usr.AvatarURL, ProfilePic: usr.AvatarURL,
ProfileData: usr.Description, ProfileData: usr.Description,
} }
return &author return &author
} }
func (self *MisskeyAdapter) Fetch(etype, id string) error { func (self *MisskeyAdapter) Fetch(etype, id string) error {
switch (etype) { switch etype {
case "message": case "message":
data, err := self.mk.Notes().Show(id) data, err := self.mk.Notes().Show(id)
if err != nil { if err != nil {
return err return err
} else { } else {
msg := self.toMessage(data, true) msg := self.toMessage(data, true)
if msg != nil { if msg != nil {
self.data <- msg self.data <- msg
} }
} }
case "children": case "children":
data, err := self.mk.Notes().Children(n.ChildrenRequest{ data, err := self.mk.Notes().Children(n.ChildrenRequest{
NoteID: id, NoteID: id,
Limit: 100, Limit: 100,
}) })
if err != nil { if err != nil {
return err return err
} else { } else {
for _, n := range data { for _, n := range data {
msg := self.toMessage(n, true) msg := self.toMessage(n, true)
if msg != nil { if msg != nil {
self.data <- msg self.data <- msg
} }
} }
} }
case "convoy": case "convoy":
data, err := self.mk.Notes().Conversation(n.ConversationRequest{ data, err := self.mk.Notes().Conversation(n.ConversationRequest{
NoteID: id, NoteID: id,
Limit: 100, Limit: 100,
}) })
if err != nil { if err != nil {
return err return err
} else { } else {
for _, n := range data { for _, n := range data {
msg := self.toMessage(n, true) msg := self.toMessage(n, true)
if msg != nil{ if msg != nil {
self.data <- msg self.data <- msg
} }
} }
} }
case "author": case "author":
user := "" user := ""
host := "" host := ""
idParts := strings.Split(id, "@") fmt.Printf("fetch author: %s\n", id)
user = idParts[0] idParts := strings.Split(id, "@")
if len(idParts) == 2 { user = idParts[1]
host = idParts[1] if len(idParts) == 3 {
} host = idParts[2]
}
var hostPtr *string = nil var hostPtr *string = nil
if len(host) > 0 { if len(host) > 0 {
hostPtr = &host 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
}
}
} 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 return nil
} }

View file

@ -18,7 +18,7 @@ type NostrAdapter struct {
} }
func (self *NostrAdapter) Name() string { func (self *NostrAdapter) Name() string {
return self.nickname return self.nickname
} }
func (self *NostrAdapter) Init(settings Settings, data chan SocketData) error { func (self *NostrAdapter) Init(settings Settings, data chan SocketData) error {

View file

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
case "$1" in case "$1" in
client) front)
if [ ! -e ./frontend/.js ]; then if [ ! -e ./frontend/.js ]; then
mkdir ./frontend/.js mkdir ./frontend/.js
fi fi
@ -13,10 +13,10 @@ case "$1" in
fi fi
if [ -s ${buildlog} ]; then if [ -s ${buildlog} ]; then
cat ${buildlog} | head cat ${buildlog} | head
rm ${buildlog}
else else
npx webpack --config webpack.config.js npx webpack --config webpack.config.js
fi fi
rm ${buildlog}
;; ;;
server) server)
go mod tidy go mod tidy

View file

@ -6,42 +6,42 @@ import (
) )
type Datagram struct { type Datagram struct {
Id string `json:"id"` Id string `json:"id"`
Uri string `json:"uri"` Uri string `json:"uri"`
Protocol string `json:"protocol"` Protocol string `json:"protocol"`
Adapter string `json:"adapter"` Adapter string `json:"adapter"`
Type string `json:"type"` Type string `json:"type"`
Target *string `json:"target,omitempty"` Target *string `json:"target,omitempty"`
} }
type Message struct { type Message struct {
Datagram Datagram
Author string `json:"author"` Author string `json:"author"`
Content string `json:"content"` Content string `json:"content"`
Attachments []Attachment `json:"attachments"` Attachments []Attachment `json:"attachments"`
ReplyTo *string `json:"replyTo"` ReplyTo *string `json:"replyTo"`
Replies []string `json:"replies"` Replies []string `json:"replies"`
ReplyCount int `json:"replyCount"` ReplyCount int `json:"replyCount"`
Mentions []string `json:"mentions"` Mentions []string `json:"mentions"`
Created time.Time `json:"created"` Created time.Time `json:"created"`
Edited *time.Time `json:"edited,omitempty"` Edited *time.Time `json:"edited,omitempty"`
Visibility string `json:"visibility"` Visibility string `json:"visibility"`
} }
type Author struct { type Author struct {
Datagram Datagram
Name string `json:"name"` Name string `json:"name"`
ProfileData interface{} `json:"profileData"` ProfileData interface{} `json:"profileData"`
ProfilePic string `json:"profilePic"` ProfilePic string `json:"profilePic"`
Messages []string `json:"messages,omitempty"` Messages []string `json:"messages,omitempty"`
} }
type Attachment struct { type Attachment struct {
Src string `json:"src"` Src string `json:"src"`
ThumbSrc string `json:"thumbSrc"` ThumbSrc string `json:"thumbSrc"`
Desc string `json:"desc"` Desc string `json:"desc"`
CreatedAt time.Time `json:"createdAt"` CreatedAt time.Time `json:"createdAt"`
Size uint64 `json:"size"` Size uint64 `json:"size"`
} }
type SocketData interface { type SocketData interface {

View file

@ -148,8 +148,8 @@ func ProtectWithSubscriberKey(next http.Handler, subscribers map[*Subscriber][]a
if strings.HasPrefix(authHeader, "Bearer ") { if strings.HasPrefix(authHeader, "Bearer ") {
subscriberKey := strings.Split(authHeader, "Bearer ")[1] subscriberKey := strings.Split(authHeader, "Bearer ")[1]
if getSubscriberByKey(subscriberKey, subscribers) != nil { if getSubscriberByKey(subscriberKey, subscribers) != nil {
next.ServeHTTP(w, req); next.ServeHTTP(w, req)
return return
} }
} }
w.WriteHeader(http.StatusUnauthorized) 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 { func apiAdapterFetch(next http.Handler, subscribers map[*Subscriber][]adapter.Adapter) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
authHeader := req.Header.Get("Authorization") authHeader := req.Header.Get("Authorization")
if strings.HasPrefix(authHeader, "Bearer ") { if strings.HasPrefix(authHeader, "Bearer ") {
subscriberKey := strings.Split(authHeader, "Bearer ")[1] subscriberKey := strings.Split(authHeader, "Bearer ")[1]
s := getSubscriberByKey(subscriberKey, subscribers) s := getSubscriberByKey(subscriberKey, subscribers)
if s != nil { if s != nil {
apiParams := req.Context().Value("params").(map[string]string) apiParams := req.Context().Value("params").(map[string]string)
queryParams := req.URL.Query() queryParams := req.URL.Query()
for _, a := range subscribers[s] { for _, a := range subscribers[s] {
if a.Name() == apiParams["adapter_id"] { if a.Name() == apiParams["adapter_id"] {
err := a.Fetch(queryParams["entity_type"][0], queryParams["entity_id"][0]) err := a.Fetch(queryParams["entity_type"][0], queryParams["entity_id"][0])
if err != nil { if err != nil {
fmt.Println(err.Error()) fmt.Println(err.Error())
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
} else { } else {
w.WriteHeader(http.StatusAccepted) w.WriteHeader(http.StatusAccepted)
} }
next.ServeHTTP(w, req) next.ServeHTTP(w, req)
return return
} }
} }
} }
} }
w.WriteHeader(http.StatusUnauthorized) w.WriteHeader(http.StatusUnauthorized)
}) })
} }
func (self *BBSServer) apiMux() http.Handler { func (self *BBSServer) apiMux() http.Handler {
errTemplate, err := template.New("err").Parse("{{ $params := (.Context).Value \"params\" }}<html><body><h1>ERROR {{ $params.ErrorCode }}</h1><p class='error'>{{ $params.ErrorMessage }}</p></body></html>") errTemplate, err := template.New("err").Parse("{{ $params := (.Context).Value \"params\" }}<html><body><h1>ERROR {{ $params.ErrorCode }}</h1><p class='error'>{{ $params.ErrorMessage }}</p></body></html>")
if err != nil { if err != nil {
@ -209,10 +208,10 @@ func (self *BBSServer) apiMux() http.Handler {
apiAdapterSubscribe(renderer.JSON("data")), apiAdapterSubscribe(renderer.JSON("data")),
self.subscribers, self.subscribers,
)) ))
rtr.Get(`/adapters/(?P<adapter_id>\S+)/fetch`, ProtectWithSubscriberKey( rtr.Get(`/adapters/(?P<adapter_id>\S+)/fetch`, ProtectWithSubscriberKey(
apiAdapterFetch(renderer.JSON("data"), self.subscribers), apiAdapterFetch(renderer.JSON("data"), self.subscribers),
self.subscribers, self.subscribers,
)) ))
return http.HandlerFunc(rtr.ServeHTTP) return http.HandlerFunc(rtr.ServeHTTP)