Finish initial ForgeFed implementation
parent
d12fd434ba
commit
a7f32d3382
|
@ -0,0 +1,55 @@
|
||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package forgefed
|
||||||
|
|
||||||
|
import (
|
||||||
|
ap "github.com/go-ap/activitypub"
|
||||||
|
"github.com/valyala/fastjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
BranchType ap.ActivityVocabularyType = "Branch"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Branch struct {
|
||||||
|
ap.Object
|
||||||
|
// Ref the unique identifier of the branch within the repo
|
||||||
|
Ref ap.Item `jsonld:"ref,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// BranchNew initializes a Branch type Object
|
||||||
|
func BranchNew() *Branch {
|
||||||
|
a := ap.ObjectNew(BranchType)
|
||||||
|
o := Branch{Object: *a}
|
||||||
|
return &o
|
||||||
|
}
|
||||||
|
|
||||||
|
func (br Branch) MarshalJSON() ([]byte, error) {
|
||||||
|
b, err := br.Object.MarshalJSON()
|
||||||
|
if len(b) == 0 || err != nil {
|
||||||
|
return make([]byte, 0), err
|
||||||
|
}
|
||||||
|
|
||||||
|
b = b[:len(b)-1]
|
||||||
|
if br.Ref != nil {
|
||||||
|
ap.WriteItemJSONProp(&b, "ref", br.Ref)
|
||||||
|
}
|
||||||
|
ap.Write(&b, '}')
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (br *Branch) UnmarshalJSON(data []byte) error {
|
||||||
|
p := fastjson.Parser{}
|
||||||
|
val, err := p.ParseBytes(data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
br.Ref = ap.JSONGetItem(val, "ref")
|
||||||
|
|
||||||
|
return ap.OnObject(&br.Object, func(a *ap.Object) error {
|
||||||
|
return ap.LoadObject(val, a)
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package forgefed
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
ap "github.com/go-ap/activitypub"
|
||||||
|
"github.com/valyala/fastjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
CommitType ap.ActivityVocabularyType = "Commit"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Commit struct {
|
||||||
|
ap.Object
|
||||||
|
// Created time at which the commit was written by its author
|
||||||
|
Created time.Time `jsonld:"created,omitempty"`
|
||||||
|
// Committed time at which the commit was committed by its committer
|
||||||
|
Committed time.Time `jsonld:"committed,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommitNew initializes a Commit type Object
|
||||||
|
func CommitNew() *Commit {
|
||||||
|
a := ap.ObjectNew(CommitType)
|
||||||
|
o := Commit{Object: *a}
|
||||||
|
return &o
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Commit) MarshalJSON() ([]byte, error) {
|
||||||
|
b, err := c.Object.MarshalJSON()
|
||||||
|
if len(b) == 0 || err != nil {
|
||||||
|
return make([]byte, 0), err
|
||||||
|
}
|
||||||
|
|
||||||
|
b = b[:len(b)-1]
|
||||||
|
if !c.Created.IsZero() {
|
||||||
|
ap.WriteTimeJSONProp(&b, "created", c.Created)
|
||||||
|
}
|
||||||
|
if !c.Committed.IsZero() {
|
||||||
|
ap.WriteTimeJSONProp(&b, "committed", c.Committed)
|
||||||
|
}
|
||||||
|
ap.Write(&b, '}')
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Commit) UnmarshalJSON(data []byte) error {
|
||||||
|
p := fastjson.Parser{}
|
||||||
|
val, err := p.ParseBytes(data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Created = ap.JSONGetTime(val, "created")
|
||||||
|
c.Committed = ap.JSONGetTime(val, "committed")
|
||||||
|
|
||||||
|
return ap.OnObject(&c.Object, func(a *ap.Object) error {
|
||||||
|
return ap.LoadObject(val, a)
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package forgefed
|
||||||
|
|
||||||
|
import (
|
||||||
|
ap "github.com/go-ap/activitypub"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetItemByType instantiates a new ForgeFed object if the type matches
|
||||||
|
// otherwise it defaults to existing activitypub package typer function.
|
||||||
|
func GetItemByType(typ ap.ActivityVocabularyType) (ap.Item, error) {
|
||||||
|
if typ == CommitType {
|
||||||
|
return CommitNew(), nil
|
||||||
|
} else if typ == BranchType {
|
||||||
|
return BranchNew(), nil
|
||||||
|
} else if typ == RepositoryType {
|
||||||
|
return RepositoryNew(""), nil
|
||||||
|
} else if typ == PushType {
|
||||||
|
return PushNew(), nil
|
||||||
|
} else if typ == TicketType {
|
||||||
|
return TicketNew(), nil
|
||||||
|
}
|
||||||
|
return ap.GetItemByType(typ)
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package forgefed
|
||||||
|
|
||||||
|
import (
|
||||||
|
ap "github.com/go-ap/activitypub"
|
||||||
|
"github.com/valyala/fastjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
PushType ap.ActivityVocabularyType = "Push"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Push struct {
|
||||||
|
ap.Object
|
||||||
|
// Target the specific repo history tip onto which the commits were added
|
||||||
|
Target ap.Item `jsonld:"target,omitempty"`
|
||||||
|
// HashBefore hash before adding the new commits
|
||||||
|
HashBefore ap.Item `jsonld:"hashBefore,omitempty"`
|
||||||
|
// HashAfter hash before adding the new commits
|
||||||
|
HashAfter ap.Item `jsonld:"hashAfter,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PushNew initializes a Push type Object
|
||||||
|
func PushNew() *Push {
|
||||||
|
a := ap.ObjectNew(PushType)
|
||||||
|
o := Push{Object: *a}
|
||||||
|
return &o
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Push) MarshalJSON() ([]byte, error) {
|
||||||
|
b, err := p.Object.MarshalJSON()
|
||||||
|
if len(b) == 0 || err != nil {
|
||||||
|
return make([]byte, 0), err
|
||||||
|
}
|
||||||
|
|
||||||
|
b = b[:len(b)-1]
|
||||||
|
if p.Target != nil {
|
||||||
|
ap.WriteItemJSONProp(&b, "target", p.Target)
|
||||||
|
}
|
||||||
|
if p.HashBefore != nil {
|
||||||
|
ap.WriteItemJSONProp(&b, "hashBefore", p.HashBefore)
|
||||||
|
}
|
||||||
|
if p.HashAfter != nil {
|
||||||
|
ap.WriteItemJSONProp(&b, "hashAfter", p.HashAfter)
|
||||||
|
}
|
||||||
|
ap.Write(&b, '}')
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Push) UnmarshalJSON(data []byte) error {
|
||||||
|
p := fastjson.Parser{}
|
||||||
|
val, err := p.ParseBytes(data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Target = ap.JSONGetItem(val, "target")
|
||||||
|
c.HashBefore = ap.JSONGetItem(val, "hashBefore")
|
||||||
|
c.HashAfter = ap.JSONGetItem(val, "hashAfter")
|
||||||
|
|
||||||
|
return ap.OnObject(&c.Object, func(a *ap.Object) error {
|
||||||
|
return ap.LoadObject(val, a)
|
||||||
|
})
|
||||||
|
}
|
|
@ -21,15 +21,6 @@ type Repository struct {
|
||||||
Forks ap.Item `jsonld:"forks,omitempty"`
|
Forks ap.Item `jsonld:"forks,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetItemByType instantiates a new Repository object if the type matches
|
|
||||||
// otherwise it defaults to existing activitypub package typer function.
|
|
||||||
func GetItemByType(typ ap.ActivityVocabularyType) (ap.Item, error) {
|
|
||||||
if typ == RepositoryType {
|
|
||||||
return RepositoryNew(""), nil
|
|
||||||
}
|
|
||||||
return ap.GetItemByType(typ)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RepositoryNew initializes a Repository type actor
|
// RepositoryNew initializes a Repository type actor
|
||||||
func RepositoryNew(id ap.ID) *Repository {
|
func RepositoryNew(id ap.ID) *Repository {
|
||||||
a := ap.ActorNew(id, RepositoryType)
|
a := ap.ActorNew(id, RepositoryType)
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package forgefed
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
ap "github.com/go-ap/activitypub"
|
||||||
|
"github.com/valyala/fastjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
TicketType ap.ActivityVocabularyType = "Ticket"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Ticket struct {
|
||||||
|
ap.Object
|
||||||
|
// Dependants Collection of Tickets which depend on this ticket
|
||||||
|
Dependants ap.ItemCollection `jsonld:"dependants,omitempty"`
|
||||||
|
// Dependencies Collection of Tickets on which this ticket depends
|
||||||
|
Dependencies ap.ItemCollection `jsonld:"dependencies,omitempty"`
|
||||||
|
// IsResolved Whether the work on this ticket is done
|
||||||
|
IsResolved bool `jsonld:"isResolved,omitempty"`
|
||||||
|
// ResolvedBy If the work on this ticket is done, who marked the ticket as resolved, or which activity did so
|
||||||
|
ResolvedBy ap.Item `jsonld:"resolvedBy,omitempty"`
|
||||||
|
// Resolved When the ticket has been marked as resolved
|
||||||
|
Resolved time.Time `jsonld:"resolved,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TicketNew initializes a Ticket type Object
|
||||||
|
func TicketNew() *Ticket {
|
||||||
|
a := ap.ObjectNew(TicketType)
|
||||||
|
o := Ticket{Object: *a}
|
||||||
|
return &o
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Ticket) MarshalJSON() ([]byte, error) {
|
||||||
|
b, err := t.Object.MarshalJSON()
|
||||||
|
if len(b) == 0 || err != nil {
|
||||||
|
return make([]byte, 0), err
|
||||||
|
}
|
||||||
|
|
||||||
|
b = b[:len(b)-1]
|
||||||
|
if t.Dependants != nil {
|
||||||
|
ap.WriteItemCollectionJSONProp(&b, "dependants", t.Dependants)
|
||||||
|
}
|
||||||
|
if t.Dependencies != nil {
|
||||||
|
ap.WriteItemCollectionJSONProp(&b, "dependencies", t.Dependencies)
|
||||||
|
}
|
||||||
|
ap.WriteBoolJSONProp(&b, "isResolved", t.IsResolved)
|
||||||
|
if t.ResolvedBy != nil {
|
||||||
|
ap.WriteItemJSONProp(&b, "resolvedBy", t.ResolvedBy)
|
||||||
|
}
|
||||||
|
if !t.Resolved.IsZero() {
|
||||||
|
ap.WriteTimeJSONProp(&b, "resolved", t.Resolved)
|
||||||
|
}
|
||||||
|
ap.Write(&b, '}')
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Ticket) UnmarshalJSON(data []byte) error {
|
||||||
|
p := fastjson.Parser{}
|
||||||
|
val, err := p.ParseBytes(data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Dependants = ap.JSONGetItems(val, "dependants")
|
||||||
|
t.Dependencies = ap.JSONGetItems(val, "dependencies")
|
||||||
|
t.IsResolved = ap.JSONGetBoolean(val, "isResolved")
|
||||||
|
t.ResolvedBy = ap.JSONGetItem(val, "resolvedBy")
|
||||||
|
t.Resolved = ap.JSONGetTime(val, "resolved")
|
||||||
|
|
||||||
|
return ap.OnObject(&t.Object, func(a *ap.Object) error {
|
||||||
|
return ap.LoadObject(val, a)
|
||||||
|
})
|
||||||
|
}
|
|
@ -137,7 +137,7 @@ func PersonOutbox(ctx *context.APIContext) {
|
||||||
// "200":
|
// "200":
|
||||||
// "$ref": "#/responses/ActivityPub"
|
// "$ref": "#/responses/ActivityPub"
|
||||||
|
|
||||||
link := strings.TrimSuffix(setting.AppURL, "/") + strings.TrimSuffix(ctx.Req.URL.EscapedPath(), "/")
|
link := strings.TrimSuffix(setting.AppURL, "/") + "/api/v1/activitypub/user/" + ctx.ContextUser.Name
|
||||||
|
|
||||||
feed, err := models.GetFeeds(ctx, models.GetFeedsOptions{
|
feed, err := models.GetFeeds(ctx, models.GetFeedsOptions{
|
||||||
RequestedUser: ctx.ContextUser,
|
RequestedUser: ctx.ContextUser,
|
||||||
|
@ -145,19 +145,19 @@ func PersonOutbox(ctx *context.APIContext) {
|
||||||
IncludePrivate: false,
|
IncludePrivate: false,
|
||||||
OnlyPerformedBy: true,
|
OnlyPerformedBy: true,
|
||||||
IncludeDeleted: false,
|
IncludeDeleted: false,
|
||||||
Date: ctx.FormString("date"),
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("Couldn't fetch outbox", err)
|
ctx.ServerError("Couldn't fetch outbox", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
outbox := ap.OrderedCollectionNew(ap.IRI(link))
|
outbox := ap.OrderedCollectionNew(ap.IRI(link + "/outbox"))
|
||||||
for _, action := range feed {
|
for _, action := range feed {
|
||||||
/*if action.OpType == ExampleType {
|
if action.OpType == models.ActionCommentIssue {
|
||||||
activity := ap.ExampleNew()
|
log.Debug("action", action)
|
||||||
|
activity := ap.Note{Type: ap.NoteType, Content: ap.NaturalLanguageValuesNew()}
|
||||||
|
activity.Content.Set("en", ap.Content(action.Content))
|
||||||
outbox.OrderedItems.Append(activity)
|
outbox.OrderedItems.Append(activity)
|
||||||
}*/
|
}
|
||||||
log.Debug(action.Content)
|
|
||||||
}
|
}
|
||||||
outbox.TotalItems = uint(len(outbox.OrderedItems))
|
outbox.TotalItems = uint(len(outbox.OrderedItems))
|
||||||
|
|
||||||
|
@ -181,7 +181,7 @@ func PersonFollowing(ctx *context.APIContext) {
|
||||||
// "200":
|
// "200":
|
||||||
// "$ref": "#/responses/ActivityPub"
|
// "$ref": "#/responses/ActivityPub"
|
||||||
|
|
||||||
link := strings.TrimSuffix(setting.AppURL, "/") + strings.TrimSuffix(ctx.Req.URL.EscapedPath(), "/")
|
link := strings.TrimSuffix(setting.AppURL, "/") + "/api/v1/activitypub/user/" + ctx.ContextUser.Name
|
||||||
|
|
||||||
users, err := user_model.GetUserFollowing(ctx.ContextUser, utils.GetListOptions(ctx))
|
users, err := user_model.GetUserFollowing(ctx.ContextUser, utils.GetListOptions(ctx))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -189,7 +189,7 @@ func PersonFollowing(ctx *context.APIContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
following := ap.OrderedCollectionNew(ap.IRI(link))
|
following := ap.OrderedCollectionNew(ap.IRI(link + "/following"))
|
||||||
following.TotalItems = uint(len(users))
|
following.TotalItems = uint(len(users))
|
||||||
|
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
|
@ -218,7 +218,7 @@ func PersonFollowers(ctx *context.APIContext) {
|
||||||
// "200":
|
// "200":
|
||||||
// "$ref": "#/responses/ActivityPub"
|
// "$ref": "#/responses/ActivityPub"
|
||||||
|
|
||||||
link := strings.TrimSuffix(setting.AppURL, "/") + strings.TrimSuffix(ctx.Req.URL.EscapedPath(), "/")
|
link := strings.TrimSuffix(setting.AppURL, "/") + "/api/v1/activitypub/user/" + ctx.ContextUser.Name
|
||||||
|
|
||||||
users, err := user_model.GetUserFollowers(ctx.ContextUser, utils.GetListOptions(ctx))
|
users, err := user_model.GetUserFollowers(ctx.ContextUser, utils.GetListOptions(ctx))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -226,7 +226,7 @@ func PersonFollowers(ctx *context.APIContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
followers := ap.OrderedCollectionNew(ap.IRI(link))
|
followers := ap.OrderedCollectionNew(ap.IRI(link + "/followers"))
|
||||||
followers.TotalItems = uint(len(users))
|
followers.TotalItems = uint(len(users))
|
||||||
|
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
|
@ -254,7 +254,7 @@ func PersonLiked(ctx *context.APIContext) {
|
||||||
// "200":
|
// "200":
|
||||||
// "$ref": "#/responses/ActivityPub"
|
// "$ref": "#/responses/ActivityPub"
|
||||||
|
|
||||||
link := strings.TrimSuffix(setting.AppURL, "/") + strings.TrimSuffix(ctx.Req.URL.EscapedPath(), "/")
|
link := strings.TrimSuffix(setting.AppURL, "/") + "/api/v1/activitypub/user/" + ctx.ContextUser.Name
|
||||||
|
|
||||||
repos, count, err := repo_model.SearchRepository(&repo_model.SearchRepoOptions{
|
repos, count, err := repo_model.SearchRepository(&repo_model.SearchRepoOptions{
|
||||||
Actor: ctx.Doer,
|
Actor: ctx.Doer,
|
||||||
|
@ -266,7 +266,7 @@ func PersonLiked(ctx *context.APIContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
liked := ap.OrderedCollectionNew(ap.IRI(link))
|
liked := ap.OrderedCollectionNew(ap.IRI(link + "/liked"))
|
||||||
liked.TotalItems = uint(count)
|
liked.TotalItems = uint(count)
|
||||||
|
|
||||||
for _, repo := range repos {
|
for _, repo := range repos {
|
||||||
|
|
|
@ -42,7 +42,7 @@ func Repo(ctx *context.APIContext) {
|
||||||
// "200":
|
// "200":
|
||||||
// "$ref": "#/responses/ActivityPub"
|
// "$ref": "#/responses/ActivityPub"
|
||||||
|
|
||||||
link := strings.TrimSuffix(setting.AppURL, "/") + strings.TrimSuffix(ctx.Req.URL.EscapedPath(), "/")
|
link := strings.TrimSuffix(setting.AppURL, "/") + "/api/v1/activitypub/repo/" + ctx.ContextUser.Name + "/" + ctx.Repo.Repository.Name
|
||||||
repo := forgefed.RepositoryNew(ap.IRI(link))
|
repo := forgefed.RepositoryNew(ap.IRI(link))
|
||||||
|
|
||||||
repo.Name = ap.NaturalLanguageValuesNew()
|
repo.Name = ap.NaturalLanguageValuesNew()
|
||||||
|
@ -52,7 +52,7 @@ func Repo(ctx *context.APIContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
repo.AttributedTo = ap.IRI(strings.TrimSuffix(link, "/"+ctx.Repo.Repository.Name))
|
repo.AttributedTo = ap.IRI(strings.TrimSuffix(setting.AppURL, "/") + "/api/v1/activitypub/user/" + ctx.ContextUser.Name)
|
||||||
|
|
||||||
repo.Summary = ap.NaturalLanguageValuesNew()
|
repo.Summary = ap.NaturalLanguageValuesNew()
|
||||||
err = repo.Summary.Set("en", ap.Content(ctx.Repo.Repository.Description))
|
err = repo.Summary.Set("en", ap.Content(ctx.Repo.Repository.Description))
|
||||||
|
@ -129,7 +129,7 @@ func RepoOutbox(ctx *context.APIContext) {
|
||||||
// "200":
|
// "200":
|
||||||
// "$ref": "#/responses/ActivityPub"
|
// "$ref": "#/responses/ActivityPub"
|
||||||
|
|
||||||
link := strings.TrimSuffix(setting.AppURL, "/") + strings.TrimSuffix(ctx.Req.URL.EscapedPath(), "/")
|
link := strings.TrimSuffix(setting.AppURL, "/") + "/api/v1/activitypub/repo/" + ctx.ContextUser.Name + "/" + ctx.Repo.Repository.Name
|
||||||
|
|
||||||
feed, err := models.GetFeeds(ctx, models.GetFeedsOptions{
|
feed, err := models.GetFeeds(ctx, models.GetFeedsOptions{
|
||||||
RequestedUser: ctx.ContextUser,
|
RequestedUser: ctx.ContextUser,
|
||||||
|
@ -143,7 +143,7 @@ func RepoOutbox(ctx *context.APIContext) {
|
||||||
ctx.ServerError("Couldn't fetch outbox", err)
|
ctx.ServerError("Couldn't fetch outbox", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
outbox := ap.OrderedCollectionNew(ap.IRI(link))
|
outbox := ap.OrderedCollectionNew(ap.IRI(link + "/outbox"))
|
||||||
for _, action := range feed {
|
for _, action := range feed {
|
||||||
/*if action.OpType == ExampleType {
|
/*if action.OpType == ExampleType {
|
||||||
activity := ap.ExampleNew()
|
activity := ap.ExampleNew()
|
||||||
|
@ -178,7 +178,7 @@ func RepoFollowers(ctx *context.APIContext) {
|
||||||
// "200":
|
// "200":
|
||||||
// "$ref": "#/responses/ActivityPub"
|
// "$ref": "#/responses/ActivityPub"
|
||||||
|
|
||||||
link := strings.TrimSuffix(setting.AppURL, "/") + strings.TrimSuffix(ctx.Req.URL.EscapedPath(), "/")
|
link := strings.TrimSuffix(setting.AppURL, "/") + "/api/v1/activitypub/repo/" + ctx.ContextUser.Name + "/" + ctx.Repo.Repository.Name
|
||||||
|
|
||||||
users, err := user_model.GetUserFollowers(ctx.ContextUser, utils.GetListOptions(ctx))
|
users, err := user_model.GetUserFollowers(ctx.ContextUser, utils.GetListOptions(ctx))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -186,7 +186,7 @@ func RepoFollowers(ctx *context.APIContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
followers := ap.OrderedCollectionNew(ap.IRI(link))
|
followers := ap.OrderedCollectionNew(ap.IRI(link + "/followers"))
|
||||||
followers.TotalItems = uint(len(users))
|
followers.TotalItems = uint(len(users))
|
||||||
|
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
|
|
Loading…
Reference in New Issue