diff options
Diffstat (limited to 'routers/api/v1/activitypub/repo.go')
-rw-r--r-- | routers/api/v1/activitypub/repo.go | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/routers/api/v1/activitypub/repo.go b/routers/api/v1/activitypub/repo.go new file mode 100644 index 000000000..f2abb3977 --- /dev/null +++ b/routers/api/v1/activitypub/repo.go @@ -0,0 +1,198 @@ +// 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 activitypub + +import ( + "io" + "net/http" + "strings" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/models/forgefed" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/routers/api/v1/utils" + + ap "github.com/go-ap/activitypub" +) + +// Repo function +func Repo(ctx *context.APIContext) { + // swagger:operation GET /activitypub/user/{username}/{reponame} activitypub activitypubRepo + // --- + // summary: Returns the repository + // produces: + // - application/activity+json + // parameters: + // - name: username + // in: path + // description: username of the user + // type: string + // required: true + // - name: reponame + // in: path + // description: name of the repository + // type: string + // required: true + // responses: + // "200": + // "$ref": "#/responses/ActivityPub" + + link := strings.TrimSuffix(setting.AppURL, "/") + strings.TrimSuffix(ctx.Req.URL.EscapedPath(), "/") + repo := forgefed.RepositoryNew(ap.IRI(link)) + + repo.Name = ap.NaturalLanguageValuesNew() + err := repo.Name.Set("en", ap.Content(ctx.Repo.Repository.Name)) + if err != nil { + ctx.Error(http.StatusInternalServerError, "Set Name", err) + return + } + + repo.AttributedTo = ap.IRI(strings.TrimSuffix(link, "/"+ctx.Repo.Repository.Name)) + + repo.Summary = ap.NaturalLanguageValuesNew() + err = repo.Summary.Set("en", ap.Content(ctx.Repo.Repository.Description)) + if err != nil { + ctx.Error(http.StatusInternalServerError, "Set Description", err) + return + } + + repo.Inbox = ap.IRI(link + "/inbox") + repo.Outbox = ap.IRI(link + "/outbox") + repo.Followers = ap.IRI(link + "/followers") + repo.Team = ap.IRI(link + "/team") + + response(ctx, repo) +} + +// RepoInbox function +func RepoInbox(ctx *context.APIContext) { + // swagger:operation POST /activitypub/user/{username}/{reponame}/inbox activitypub activitypubRepoInbox + // --- + // summary: Send to the inbox + // produces: + // - application/activity+json + // parameters: + // - name: username + // in: path + // description: username of the user + // type: string + // required: true + // - name: reponame + // in: path + // description: name of the repository + // type: string + // required: true + // responses: + // "204": + // "$ref": "#/responses/empty" + + body, err := io.ReadAll(ctx.Req.Body) + if err != nil { + ctx.Error(http.StatusInternalServerError, "Error reading request body", err) + } + + var activity ap.Activity + activity.UnmarshalJSON(body) + if activity.Type == ap.FollowType { + // activitypub.Follow(ctx, activity) + } else { + log.Warn("ActivityStreams type not supported", activity) + } + + ctx.Status(http.StatusNoContent) +} + +// RepoOutbox function +func RepoOutbox(ctx *context.APIContext) { + // swagger:operation GET /activitypub/user/{username}/outbox activitypub activitypubPersonOutbox + // --- + // summary: Returns the outbox + // produces: + // - application/activity+json + // parameters: + // - name: username + // in: path + // description: username of the user + // type: string + // required: true + // - name: reponame + // in: path + // description: name of the repository + // type: string + // required: true + // responses: + // "200": + // "$ref": "#/responses/ActivityPub" + + link := strings.TrimSuffix(setting.AppURL, "/") + strings.TrimSuffix(ctx.Req.URL.EscapedPath(), "/") + + feed, err := models.GetFeeds(ctx, models.GetFeedsOptions{ + RequestedUser: ctx.ContextUser, + Actor: ctx.ContextUser, + IncludePrivate: false, + OnlyPerformedBy: true, + IncludeDeleted: false, + Date: ctx.FormString("date"), + }) + if err != nil { + ctx.Error(http.StatusInternalServerError, "Couldn't fetch outbox", err) + } + + outbox := ap.OrderedCollectionNew(ap.IRI(link)) + for _, action := range feed { + /*if action.OpType == ExampleType { + activity := ap.ExampleNew() + outbox.OrderedItems.Append(activity) + }*/ + log.Debug(action.Content) + } + outbox.TotalItems = uint(len(outbox.OrderedItems)) + + response(ctx, outbox) +} + +// RepoFollowers function +func RepoFollowers(ctx *context.APIContext) { + // swagger:operation GET /activitypub/user/{username}/{reponame}/followers activitypub activitypubRepoFollowers + // --- + // summary: Returns the followers collection + // produces: + // - application/activity+json + // parameters: + // - name: username + // in: path + // description: username of the user + // type: string + // required: true + // - name: reponame + // in: path + // description: name of the repository + // type: string + // required: true + // responses: + // "200": + // "$ref": "#/responses/ActivityPub" + + link := strings.TrimSuffix(setting.AppURL, "/") + strings.TrimSuffix(ctx.Req.URL.EscapedPath(), "/") + + users, err := user_model.GetUserFollowers(ctx.ContextUser, utils.GetListOptions(ctx)) + if err != nil { + ctx.Error(http.StatusInternalServerError, "GetUserFollowers", err) + return + } + + followers := ap.OrderedCollectionNew(ap.IRI(link)) + followers.TotalItems = uint(len(users)) + + for _, user := range users { + person := ap.PersonNew(ap.IRI(user.Website)) + followers.OrderedItems.Append(person) + } + + response(ctx, followers) +} |