WIP minimal AP
This commit is contained in:
parent
5f49754b71
commit
5e77fdd33b
5
go.mod
5
go.mod
|
@ -15,8 +15,12 @@ require (
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // indirect
|
||||||
github.com/andybalholm/brotli v1.0.5 // indirect
|
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/go-ap/activitypub v0.0.0-20230719093539-2b6a6f3a25ee // indirect
|
||||||
|
github.com/go-ap/errors v0.0.0-20221205040414-01c1adfc98ea // indirect
|
||||||
|
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/klauspost/compress v1.16.3 // indirect
|
github.com/klauspost/compress v1.16.3 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
|
@ -31,6 +35,7 @@ require (
|
||||||
github.com/tinylib/msgp v1.1.8 // indirect
|
github.com/tinylib/msgp v1.1.8 // indirect
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
github.com/valyala/fasthttp v1.47.0 // indirect
|
github.com/valyala/fasthttp v1.47.0 // indirect
|
||||||
|
github.com/valyala/fastjson v1.6.4 // indirect
|
||||||
github.com/valyala/tcplisten v1.0.0 // indirect
|
github.com/valyala/tcplisten v1.0.0 // indirect
|
||||||
golang.org/x/sys v0.10.0 // indirect
|
golang.org/x/sys v0.10.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
|
11
go.sum
11
go.sum
|
@ -1,8 +1,16 @@
|
||||||
|
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:cliQ4HHsCo6xi2oWZYKWW4bly/Ory9FuTpFPRxj/mAg=
|
||||||
|
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs=
|
||||||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||||
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/go-ap/activitypub v0.0.0-20230719093539-2b6a6f3a25ee h1:1OMBlmSzLXftIj5z/D1s1Xr3FanVKtLFZPtdIFslh1A=
|
||||||
|
github.com/go-ap/activitypub v0.0.0-20230719093539-2b6a6f3a25ee/go.mod h1:qw0WNf+PTG69Xu6mVqUluDuKl1VwVYdgntOZQFBZQ48=
|
||||||
|
github.com/go-ap/errors v0.0.0-20221205040414-01c1adfc98ea h1:ywGtLGVjJjMrq4mu35Qmu+NtlhlTk/gTayE6Bb4tQZk=
|
||||||
|
github.com/go-ap/errors v0.0.0-20221205040414-01c1adfc98ea/go.mod h1:SaTNjEEkp0q+w3pUS1ccyEL/lUrHteORlDq/e21mCc8=
|
||||||
|
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73 h1:GMKIYXyXPGIp+hYiWOhfqK4A023HdgisDT4YGgf99mw=
|
||||||
|
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73/go.mod h1:jyveZeGw5LaADntW+UEsMjl3IlIwk+DxlYNsbofQkGA=
|
||||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/gofiber/fiber/v2 v2.47.0 h1:EN5lHVCc+Pyqh5OEsk8fzRiifgwpbrP0rulQ4iNf3fs=
|
github.com/gofiber/fiber/v2 v2.47.0 h1:EN5lHVCc+Pyqh5OEsk8fzRiifgwpbrP0rulQ4iNf3fs=
|
||||||
|
@ -53,6 +61,9 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasthttp v1.47.0 h1:y7moDoxYzMooFpT5aHgNgVOQDrS3qlkfiP9mDtGGK9c=
|
github.com/valyala/fasthttp v1.47.0 h1:y7moDoxYzMooFpT5aHgNgVOQDrS3qlkfiP9mDtGGK9c=
|
||||||
github.com/valyala/fasthttp v1.47.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
|
github.com/valyala/fasthttp v1.47.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
|
||||||
|
github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
|
||||||
|
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
|
||||||
|
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
|
||||||
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
||||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
package web
|
package web
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/url"
|
||||||
|
"owl-blogs/app"
|
||||||
"owl-blogs/app/repository"
|
"owl-blogs/app/repository"
|
||||||
"owl-blogs/config"
|
"owl-blogs/config"
|
||||||
"owl-blogs/domain/model"
|
"owl-blogs/domain/model"
|
||||||
|
|
||||||
|
vocab "github.com/go-ap/activitypub"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -12,6 +16,7 @@ const ACT_PUB_CONF_NAME = "activity_pub"
|
||||||
|
|
||||||
type ActivityPubServer struct {
|
type ActivityPubServer struct {
|
||||||
configRepo repository.ConfigRepository
|
configRepo repository.ConfigRepository
|
||||||
|
entryService *app.EntryService
|
||||||
}
|
}
|
||||||
|
|
||||||
type ActivityPubConfig struct {
|
type ActivityPubConfig struct {
|
||||||
|
@ -22,47 +27,19 @@ type ActivityPubConfig struct {
|
||||||
|
|
||||||
type WebfingerResponse struct {
|
type WebfingerResponse struct {
|
||||||
Subject string `json:"subject"`
|
Subject string `json:"subject"`
|
||||||
Links []ActivityPubLink `json:"links"`
|
Links []WebfingerLink `json:"links"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ActivityPubLink struct {
|
type WebfingerLink struct {
|
||||||
Rel string `json:"rel"`
|
Rel string `json:"rel"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Href string `json:"href"`
|
Href string `json:"href"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ActivityPubActor struct {
|
func NewActivityPubServer(configRepo repository.ConfigRepository, entryService *app.EntryService) *ActivityPubServer {
|
||||||
Context []string `json:"@context"`
|
|
||||||
|
|
||||||
ID string `json:"id"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
PreferredUsername string `json:"preferredUsername"`
|
|
||||||
Inbox string `json:"inbox"`
|
|
||||||
Oubox string `json:"outbox"`
|
|
||||||
Followers string `json:"followers"`
|
|
||||||
|
|
||||||
PublicKey ActivityPubPublicKey `json:"publicKey"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ActivityPubPublicKey struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
Owner string `json:"owner"`
|
|
||||||
PublicKeyPem string `json:"publicKeyPem"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ActivityPubOrderedCollection struct {
|
|
||||||
Context []string `json:"@context"`
|
|
||||||
|
|
||||||
ID string `json:"id"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
TotalItems int `json:"totalItems"`
|
|
||||||
First string `json:"first"`
|
|
||||||
Last string `json:"last"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewActivityPubServer(configRepo repository.ConfigRepository) *ActivityPubServer {
|
|
||||||
return &ActivityPubServer{
|
return &ActivityPubServer{
|
||||||
configRepo: configRepo,
|
configRepo: configRepo,
|
||||||
|
entryService: entryService,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +52,7 @@ func (s *ActivityPubServer) HandleWebfinger(ctx *fiber.Ctx) error {
|
||||||
webfinger := WebfingerResponse{
|
webfinger := WebfingerResponse{
|
||||||
Subject: ctx.Query("resource"),
|
Subject: ctx.Query("resource"),
|
||||||
|
|
||||||
Links: []ActivityPubLink{
|
Links: []WebfingerLink{
|
||||||
{
|
{
|
||||||
Rel: "self",
|
Rel: "self",
|
||||||
Type: "application/activity+json",
|
Type: "application/activity+json",
|
||||||
|
@ -90,6 +67,7 @@ func (s *ActivityPubServer) HandleWebfinger(ctx *fiber.Ctx) error {
|
||||||
|
|
||||||
func (s *ActivityPubServer) Router(router fiber.Router) {
|
func (s *ActivityPubServer) Router(router fiber.Router) {
|
||||||
router.Get("/actor", s.HandleActor)
|
router.Get("/actor", s.HandleActor)
|
||||||
|
router.Get("/outbox", s.HandleOutbox)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ActivityPubServer) HandleActor(ctx *fiber.Ctx) error {
|
func (s *ActivityPubServer) HandleActor(ctx *fiber.Ctx) error {
|
||||||
|
@ -98,25 +76,57 @@ func (s *ActivityPubServer) HandleActor(ctx *fiber.Ctx) error {
|
||||||
s.configRepo.Get(ACT_PUB_CONF_NAME, &apConfig)
|
s.configRepo.Get(ACT_PUB_CONF_NAME, &apConfig)
|
||||||
s.configRepo.Get(config.SITE_CONFIG, &siteConfig)
|
s.configRepo.Get(config.SITE_CONFIG, &siteConfig)
|
||||||
|
|
||||||
actor := ActivityPubActor{
|
actor := vocab.PersonNew(vocab.IRI(siteConfig.FullUrl + "/activitypub/actor"))
|
||||||
Context: []string{
|
actor.PreferredUsername = vocab.NaturalLanguageValues{{Value: vocab.Content(apConfig.PreferredUsername)}}
|
||||||
"https://www.w3.org/ns/activitystreams",
|
actor.Inbox = vocab.IRI(siteConfig.FullUrl + "/activitypub/inbox")
|
||||||
"https://w3id.org/security/v1",
|
actor.Outbox = vocab.IRI(siteConfig.FullUrl + "/activitypub/outbox")
|
||||||
},
|
actor.Followers = vocab.IRI(siteConfig.FullUrl + "/activitypub/followers")
|
||||||
|
actor.PublicKey = vocab.PublicKey{
|
||||||
ID: siteConfig.FullUrl + "/activitypub/actor",
|
ID: vocab.ID(siteConfig.FullUrl + "/activitypub/actor#main-key"),
|
||||||
Type: "Person",
|
Owner: vocab.IRI(siteConfig.FullUrl + "/activitypub/actor"),
|
||||||
PreferredUsername: apConfig.PreferredUsername,
|
|
||||||
Inbox: siteConfig.FullUrl + "/activitypub/inbox",
|
|
||||||
Oubox: siteConfig.FullUrl + "/activitypub/outbox",
|
|
||||||
Followers: siteConfig.FullUrl + "/activitypub/followers",
|
|
||||||
|
|
||||||
PublicKey: ActivityPubPublicKey{
|
|
||||||
ID: siteConfig.FullUrl + "/activitypub/actor#main-key",
|
|
||||||
Owner: siteConfig.FullUrl + "/activitypub/actor",
|
|
||||||
PublicKeyPem: apConfig.PublicKeyPem,
|
PublicKeyPem: apConfig.PublicKeyPem,
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ctx.JSON(actor)
|
data, err := actor.MarshalJSON()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ctx.Set("Content-Type", "application/activity+json")
|
||||||
|
return ctx.Send(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ActivityPubServer) HandleOutbox(ctx *fiber.Ctx) error {
|
||||||
|
siteConfig := model.SiteConfig{}
|
||||||
|
apConfig := ActivityPubConfig{}
|
||||||
|
s.configRepo.Get(ACT_PUB_CONF_NAME, &apConfig)
|
||||||
|
s.configRepo.Get(config.SITE_CONFIG, &siteConfig)
|
||||||
|
|
||||||
|
entries, err := s.entryService.FindAllByType(nil, true, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
items := make([]vocab.Item, len(entries))
|
||||||
|
for i, entry := range entries {
|
||||||
|
url, _ := url.JoinPath(siteConfig.FullUrl, "/posts/"+entry.ID()+"/")
|
||||||
|
items[i] = *vocab.ActivityNew(vocab.IRI(url), vocab.CreateType, vocab.Object{
|
||||||
|
ID: vocab.ID(url),
|
||||||
|
Type: vocab.ArticleType,
|
||||||
|
Content: vocab.NaturalLanguageValues{
|
||||||
|
{Value: vocab.Content(entry.Content())},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
outbox := vocab.OrderedCollectionNew(vocab.IRI(siteConfig.FullUrl + "/activitypub/outbox"))
|
||||||
|
outbox.TotalItems = uint(len(items))
|
||||||
|
outbox.OrderedItems = items
|
||||||
|
|
||||||
|
data, err := outbox.MarshalJSON()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ctx.Set("Content-Type", "application/activity+json")
|
||||||
|
return ctx.Send(data)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,10 +118,10 @@ func NewWebApp(
|
||||||
app.Get("/sitemap.xml", NewSiteMapHandler(entryService, configRepo).Handle)
|
app.Get("/sitemap.xml", NewSiteMapHandler(entryService, configRepo).Handle)
|
||||||
|
|
||||||
// ActivityPub
|
// ActivityPub
|
||||||
// activityPubServer := NewActivityPubServer(configRepo)
|
activityPubServer := NewActivityPubServer(configRepo, entryService)
|
||||||
configRegister.Register(ACT_PUB_CONF_NAME, &ActivityPubConfig{})
|
configRegister.Register(ACT_PUB_CONF_NAME, &ActivityPubConfig{})
|
||||||
// app.Get("/.well-known/webfinger", activityPubServer.HandleWebfinger)
|
app.Get("/.well-known/webfinger", activityPubServer.HandleWebfinger)
|
||||||
// app.Route("/activitypub", activityPubServer.Router)
|
app.Route("/activitypub", activityPubServer.Router)
|
||||||
|
|
||||||
// Webmention
|
// Webmention
|
||||||
// app.Post("/webmention/", userWebmentionHandler(repo))
|
// app.Post("/webmention/", userWebmentionHandler(repo))
|
||||||
|
|
Loading…
Reference in New Issue