aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulio Capote <jcapote@gmail.com>2023-01-02 02:57:23 +0000
committerJulio Capote <jcapote@gmail.com>2023-01-02 02:57:23 +0000
commit2148666991eb98fa6935f4f36fc29cf1e704f834 (patch)
treedf9ef2db74685543d7458650b69ce89db14ae51a
parent5efad50005484e4bcd56fd68a46040e3d89b0efe (diff)
downloadcommunique-2148666991eb98fa6935f4f36fc29cf1e704f834.tar.gz
followers and following endpoints
-rw-r--r--http/router.go26
-rw-r--r--registry/registry.go50
-rw-r--r--urls/urls.go12
-rw-r--r--views/outbox.go8
-rw-r--r--views/profile.go61
5 files changed, 140 insertions, 17 deletions
diff --git a/http/router.go b/http/router.go
index 04fa583..9730dbf 100644
--- a/http/router.go
+++ b/http/router.go
@@ -47,6 +47,28 @@ func (s *Router) Start(zapWriter io.Writer) {
})
+ router.GET("/actors/:actor/followers", func(c *gin.Context) {
+ actorParam := c.Param("actor")
+ resource, _ := s.registry.Followers(actorParam)
+ if resource != nil {
+ c.Writer.Header().Set("Content-Type", "application/activity+json")
+ c.JSON(http.StatusOK, resource)
+ } else {
+ c.JSON(http.StatusNotFound, nil)
+ }
+ })
+
+ router.GET("/actors/:actor/following", func(c *gin.Context) {
+ actorParam := c.Param("actor")
+ resource, _ := s.registry.Following(actorParam)
+ if resource != nil {
+ c.Writer.Header().Set("Content-Type", "application/activity+json")
+ c.JSON(http.StatusOK, resource)
+ } else {
+ c.JSON(http.StatusNotFound, nil)
+ }
+ })
+
// // Inbox
// router.POST("/actors/:actor/inbox", func(c *gin.Context) {
// actorParam := c.Param("actor")
@@ -81,7 +103,7 @@ func (s *Router) Start(zapWriter io.Writer) {
actorParam := c.Param("actor")
idParam := c.Param("id")
var resource map[string]interface{}
- resource, _ = s.registry.Activity(actorParam, idParam)
+ resource, _ = s.registry.ActivityOrNote("activity", actorParam, idParam)
if resource != nil {
c.Writer.Header().Set("Content-Type", "application/activity+json")
@@ -96,7 +118,7 @@ func (s *Router) Start(zapWriter io.Writer) {
actorParam := c.Param("actor")
idParam := c.Param("id")
var resource map[string]interface{}
- resource, _ = s.registry.Note(actorParam, idParam)
+ resource, _ = s.registry.ActivityOrNote("note", actorParam, idParam)
if resource != nil {
c.Writer.Header().Set("Content-Type", "application/activity+json")
diff --git a/registry/registry.go b/registry/registry.go
index 13f2889..0a5df77 100644
--- a/registry/registry.go
+++ b/registry/registry.go
@@ -7,6 +7,7 @@ import (
"git.capotej.com/capotej/communique/config"
"git.capotej.com/capotej/communique/models"
+ "git.capotej.com/capotej/communique/urls"
"git.capotej.com/capotej/communique/views"
)
@@ -62,7 +63,7 @@ func (r *Registry) OutboxCollection(name string) (map[string]interface{}, error)
return nil, err
}
var outboxItems []models.OutboxItem
- for _, v := range page {
+ for _, v := range page[0:20] { //TODO pagination
buf := bytes.NewBuffer(v)
dec := gob.NewDecoder(buf)
var outboxItem models.OutboxItem
@@ -74,29 +75,53 @@ func (r *Registry) OutboxCollection(name string) (map[string]interface{}, error)
}
return views.RenderOutboxCollection(handler.handlerCfg.Name, r.cfg.Domain, outboxItems)
}
+func (r *Registry) Following(name string) (map[string]interface{}, error) {
+ handler := r.findByName(name)
+ if handler == nil {
+ return nil, nil
+ }
+ profile, err := urls.UrlProfile(name, r.cfg.Domain)
+ if err != nil {
+ return nil, err
+ }
+ following, err := urls.UrlFollowing(name, r.cfg.Domain)
+ if err != nil {
+ return nil, err
+ }
+ result := make(map[string]interface{})
+ result["@context"] = "https://www.w3.org/ns/activitystreams"
+ result["attributedTo"] = profile.String()
+ result["id"] = following.String()
+ result["totalItems"] = 0
+ result["orderedItems"] = []bool{}
+ result["type"] = "OrderedCollection"
+ return result, nil
+}
-func (r *Registry) Activity(name, id string) (map[string]interface{}, error) {
+func (r *Registry) Followers(name string) (map[string]interface{}, error) {
handler := r.findByName(name)
if handler == nil {
return nil, nil
}
- lookup := models.NewOutboxItem(handler.handlerCfg)
- lookup.Id = []byte(id)
- result, err := r.persister.Find(lookup)
+ profile, err := urls.UrlProfile(name, r.cfg.Domain)
if err != nil {
return nil, err
}
- buf := bytes.NewBuffer(result)
- dec := gob.NewDecoder(buf)
- var outboxItem models.OutboxItem
- err = dec.Decode(&outboxItem)
+ followers, err := urls.UrlFollowers(name, r.cfg.Domain)
if err != nil {
return nil, err
}
- return views.RenderActivity(handler.handlerCfg.Name, r.cfg.Domain, outboxItem)
+ result := make(map[string]interface{})
+ result["@context"] = "https://www.w3.org/ns/activitystreams"
+ result["attributedTo"] = profile.String()
+ result["id"] = followers.String()
+ result["totalItems"] = 0
+ result["orderedItems"] = []bool{}
+ result["type"] = "OrderedCollection"
+ return result, nil
}
-func (r *Registry) Note(name, id string) (map[string]interface{}, error) {
+func (r *Registry) ActivityOrNote(activityOrNote, name, id string) (map[string]interface{}, error) {
handler := r.findByName(name)
if handler == nil {
return nil, nil
@@ -114,6 +139,9 @@ func (r *Registry) Note(name, id string) (map[string]interface{}, error) {
if err != nil {
return nil, err
}
+ if activityOrNote == "activity" {
+ return views.RenderActivity(handler.handlerCfg.Name, r.cfg.Domain, outboxItem)
+ }
return views.RenderNote(handler.handlerCfg.Name, r.cfg.Domain, outboxItem)
}
diff --git a/urls/urls.go b/urls/urls.go
index 6a2025b..65aa042 100644
--- a/urls/urls.go
+++ b/urls/urls.go
@@ -25,6 +25,18 @@ func UrlOutbox(name, domain string) (*url.URL, error) {
return linkTo("outbox", domain, "actors", name, "outbox")
}
+func UrlProfile(name, domain string) (*url.URL, error) {
+ return linkTo("outbox", domain, "actors", name)
+}
+
+func UrlFollowers(name, domain string) (*url.URL, error) {
+ return linkTo("outbox", domain, "actors", name, "followers")
+}
+
+func UrlFollowing(name, domain string) (*url.URL, error) {
+ return linkTo("outbox", domain, "actors", name, "following")
+}
+
func UrlActivity(name, domain, id string) (*url.URL, error) {
return linkTo("activity", domain, "actors", name, "activity", id)
}
diff --git a/views/outbox.go b/views/outbox.go
index ee28842..8aef906 100644
--- a/views/outbox.go
+++ b/views/outbox.go
@@ -57,6 +57,14 @@ func RenderOutboxCollection(name, domain string, page []models.OutboxItem) (map[
crea.SetActivityStreamsTo(toProp)
crea.SetActivityStreamsPublished(publishedProp)
+ actorUrl, err := urls.UrlProfile(name, domain)
+ if err != nil {
+ return nil, err
+ }
+ actorProp := streams.NewActivityStreamsActorProperty()
+ actorProp.AppendIRI(actorUrl)
+ crea.SetActivityStreamsActor(actorProp)
+
noteUrl, err := urls.UrlNote(name, domain, string(v.Id))
if err != nil {
return nil, err
diff --git a/views/profile.go b/views/profile.go
index 12aae54..5b82b46 100644
--- a/views/profile.go
+++ b/views/profile.go
@@ -1,21 +1,74 @@
package views
import (
+ "fmt"
+
"git.capotej.com/capotej/communique/urls"
"github.com/go-fed/activity/streams"
)
func RenderProfile(name, domain string) (map[string]interface{}, error) {
- u, err := urls.UrlInbox(name, domain)
+ inbox, err := urls.UrlInbox(name, domain)
+ if err != nil {
+ return nil, err
+ }
+
+ inboxProp := streams.NewActivityStreamsInboxProperty()
+ inboxProp.SetIRI(inbox)
+
+ outbox, err := urls.UrlOutbox(name, domain)
+ if err != nil {
+ return nil, err
+ }
+
+ outboxProp := streams.NewActivityStreamsOutboxProperty()
+ outboxProp.SetIRI(outbox)
+
+ actorUrl, err := urls.UrlProfile(name, domain)
+ if err != nil {
+ return nil, err
+ }
+
+ followingUrl, err := urls.UrlFollowing(name, domain)
if err != nil {
return nil, err
}
- inb := streams.NewActivityStreamsInboxProperty()
- inb.SetIRI(u)
+ followersUrl, err := urls.UrlFollowers(name, domain)
+ if err != nil {
+ return nil, err
+ }
p := streams.NewActivityStreamsService()
- p.SetActivityStreamsInbox(inb)
+ idProp := streams.NewJSONLDIdProperty()
+ idProp.Set(actorUrl)
+ p.SetJSONLDId(idProp)
+ p.SetActivityStreamsInbox(inboxProp)
+ p.SetActivityStreamsOutbox(outboxProp)
+
+ nameProp := streams.NewActivityStreamsNameProperty()
+ nameProp.AppendXMLSchemaString(name)
+ p.SetActivityStreamsName(nameProp)
+
+ usernameProp := streams.NewActivityStreamsPreferredUsernameProperty()
+ usernameProp.SetXMLSchemaString(name)
+ p.SetActivityStreamsPreferredUsername(usernameProp)
+
+ urlProp := streams.NewActivityStreamsUrlProperty()
+ urlProp.AppendIRI(actorUrl)
+ p.SetActivityStreamsUrl(urlProp)
+
+ summaryProp := streams.NewActivityStreamsSummaryProperty()
+ summaryProp.AppendXMLSchemaString(fmt.Sprintf("profile for %s", name))
+ p.SetActivityStreamsSummary(summaryProp)
+
+ followersProp := streams.NewActivityStreamsFollowersProperty()
+ followersProp.SetIRI(followersUrl)
+ p.SetActivityStreamsFollowers(followersProp)
+
+ followingProp := streams.NewActivityStreamsFollowingProperty()
+ followingProp.SetIRI(followingUrl)
+ p.SetActivityStreamsFollowing(followingProp)
return streams.Serialize(p)
}