mirror of
https://github.com/versia-pub/versia-go.git
synced 2026-03-13 04:29:15 +01:00
chore: init
This commit is contained in:
commit
320715f3e7
174 changed files with 42083 additions and 0 deletions
147
internal/service/svc_impls/Inbox_service_impl.go
Normal file
147
internal/service/svc_impls/Inbox_service_impl.go
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
package svc_impls
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/google/uuid"
|
||||
"github.com/lysand-org/versia-go/internal/repository"
|
||||
"github.com/lysand-org/versia-go/internal/service"
|
||||
|
||||
"git.devminer.xyz/devminer/unitel"
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/lysand-org/versia-go/ent"
|
||||
"github.com/lysand-org/versia-go/ent/user"
|
||||
"github.com/lysand-org/versia-go/internal/api_schema"
|
||||
"github.com/lysand-org/versia-go/internal/entity"
|
||||
"github.com/lysand-org/versia-go/pkg/lysand"
|
||||
)
|
||||
|
||||
var _ service.InboxService = (*InboxServiceImpl)(nil)
|
||||
|
||||
type InboxServiceImpl struct {
|
||||
repositories repository.Manager
|
||||
|
||||
federationService service.FederationService
|
||||
|
||||
telemetry *unitel.Telemetry
|
||||
log logr.Logger
|
||||
}
|
||||
|
||||
func NewInboxService(repositories repository.Manager, federationService service.FederationService, telemetry *unitel.Telemetry, log logr.Logger) *InboxServiceImpl {
|
||||
return &InboxServiceImpl{
|
||||
repositories: repositories,
|
||||
federationService: federationService,
|
||||
telemetry: telemetry,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (i InboxServiceImpl) WithRepositories(repositories repository.Manager) service.InboxService {
|
||||
return NewInboxService(repositories, i.federationService, i.telemetry, i.log)
|
||||
}
|
||||
|
||||
func (i InboxServiceImpl) Handle(ctx context.Context, obj any, userId uuid.UUID) error {
|
||||
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.InboxServiceImpl.Handle")
|
||||
defer s.End()
|
||||
ctx = s.Context()
|
||||
|
||||
return i.repositories.Atomic(ctx, func(ctx context.Context, tx repository.Manager) error {
|
||||
i := i.WithRepositories(tx).(*InboxServiceImpl)
|
||||
|
||||
u, err := i.repositories.Users().GetLocalByID(ctx, userId)
|
||||
if err != nil {
|
||||
i.log.Error(err, "Failed to get user", "id", userId)
|
||||
|
||||
return api_schema.ErrInternalServerError(nil)
|
||||
}
|
||||
if u == nil {
|
||||
return api_schema.ErrNotFound(map[string]any{
|
||||
"id": userId,
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: Implement more types
|
||||
switch o := obj.(type) {
|
||||
case lysand.Note:
|
||||
i.log.Info("Received note", "note", o)
|
||||
if err := i.handleNote(ctx, o, u); err != nil {
|
||||
i.log.Error(err, "Failed to handle note", "note", o)
|
||||
return err
|
||||
}
|
||||
|
||||
case lysand.Patch:
|
||||
i.log.Info("Received patch", "patch", o)
|
||||
case lysand.Follow:
|
||||
if err := i.handleFollow(ctx, o, u); err != nil {
|
||||
i.log.Error(err, "Failed to handle follow", "follow", o)
|
||||
return err
|
||||
}
|
||||
case lysand.Undo:
|
||||
i.log.Info("Received undo", "undo", o)
|
||||
default:
|
||||
i.log.Info("Unimplemented object type", "object", obj)
|
||||
return api_schema.ErrNotImplemented(nil)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (i InboxServiceImpl) handleFollow(ctx context.Context, o lysand.Follow, u *entity.User) error {
|
||||
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.InboxServiceImpl.handleFollow")
|
||||
defer s.End()
|
||||
ctx = s.Context()
|
||||
|
||||
author, err := i.repositories.Users().Resolve(ctx, o.Author)
|
||||
if err != nil {
|
||||
i.log.Error(err, "Failed to resolve author", "author", o.Author)
|
||||
return err
|
||||
}
|
||||
|
||||
f, err := i.repositories.Follows().Follow(ctx, author, u)
|
||||
if err != nil {
|
||||
// TODO: Handle constraint errors
|
||||
if ent.IsConstraintError(err) {
|
||||
i.log.Error(err, "Follow already exists", "user", user.ID, "author", author.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
i.log.Error(err, "Failed to create follow", "user", user.ID, "author", author.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
switch u.PrivacyLevel {
|
||||
case user.PrivacyLevelPublic:
|
||||
if err := i.repositories.Follows().AcceptFollow(ctx, author, u); err != nil {
|
||||
i.log.Error(err, "Failed to accept follow", "user", user.ID, "author", author.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := i.federationService.SendToInbox(ctx, u, author, f.ToLysandAccept()); err != nil {
|
||||
i.log.Error(err, "Failed to send follow accept to inbox", "user", user.ID, "author", author.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
case user.PrivacyLevelRestricted:
|
||||
case user.PrivacyLevelPrivate:
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i InboxServiceImpl) handleNote(ctx context.Context, o lysand.Note, u *entity.User) error {
|
||||
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.InboxServiceImpl.handleNote")
|
||||
defer s.End()
|
||||
ctx = s.Context()
|
||||
|
||||
author, err := i.repositories.Users().Resolve(ctx, o.Author)
|
||||
if err != nil {
|
||||
i.log.Error(err, "Failed to resolve author", "author", o.Author)
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: Implement
|
||||
|
||||
_ = author
|
||||
|
||||
return nil
|
||||
}
|
||||
56
internal/service/svc_impls/federation_service_impl.go
Normal file
56
internal/service/svc_impls/federation_service_impl.go
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
package svc_impls
|
||||
|
||||
import (
|
||||
"context"
|
||||
"git.devminer.xyz/devminer/unitel"
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/lysand-org/versia-go/internal/entity"
|
||||
"github.com/lysand-org/versia-go/internal/service"
|
||||
"github.com/lysand-org/versia-go/pkg/lysand"
|
||||
)
|
||||
|
||||
var _ service.FederationService = (*FederationServiceImpl)(nil)
|
||||
|
||||
type FederationServiceImpl struct {
|
||||
federationClient *lysand.FederationClient
|
||||
|
||||
telemetry *unitel.Telemetry
|
||||
|
||||
log logr.Logger
|
||||
}
|
||||
|
||||
func NewFederationServiceImpl(federationClient *lysand.FederationClient, telemetry *unitel.Telemetry, log logr.Logger) *FederationServiceImpl {
|
||||
return &FederationServiceImpl{
|
||||
federationClient: federationClient,
|
||||
telemetry: telemetry,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (i FederationServiceImpl) SendToInbox(ctx context.Context, author *entity.User, target *entity.User, object any) ([]byte, error) {
|
||||
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.FederationServiceImpl.SendToInbox")
|
||||
defer s.End()
|
||||
ctx = s.Context()
|
||||
|
||||
response, err := i.federationClient.SendToInbox(ctx, author.Signer, target.ToLysand(), object)
|
||||
if err != nil {
|
||||
i.log.Error(err, "Failed to send to inbox", "author", author.ID, "target", target.ID)
|
||||
return response, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (i FederationServiceImpl) GetUser(ctx context.Context, uri *lysand.URL) (*lysand.User, error) {
|
||||
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.FederationServiceImpl.GetUser")
|
||||
defer s.End()
|
||||
ctx = s.Context()
|
||||
|
||||
u, err := i.federationClient.GetUser(ctx, uri.ToStd())
|
||||
if err != nil {
|
||||
i.log.Error(err, "Failed to fetch remote user", "uri", uri)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return u, nil
|
||||
}
|
||||
102
internal/service/svc_impls/follow_service_impl.go
Normal file
102
internal/service/svc_impls/follow_service_impl.go
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
package svc_impls
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/lysand-org/versia-go/internal/repository"
|
||||
"github.com/lysand-org/versia-go/internal/service"
|
||||
|
||||
"git.devminer.xyz/devminer/unitel"
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/google/uuid"
|
||||
"github.com/lysand-org/versia-go/internal/entity"
|
||||
"github.com/lysand-org/versia-go/pkg/lysand"
|
||||
)
|
||||
|
||||
var _ service.FollowService = (*FollowServiceImpl)(nil)
|
||||
|
||||
type FollowServiceImpl struct {
|
||||
federationService service.FederationService
|
||||
|
||||
repositories repository.Manager
|
||||
|
||||
telemetry *unitel.Telemetry
|
||||
log logr.Logger
|
||||
}
|
||||
|
||||
func NewFollowServiceImpl(federationService service.FederationService, repositories repository.Manager, telemetry *unitel.Telemetry, log logr.Logger) *FollowServiceImpl {
|
||||
return &FollowServiceImpl{
|
||||
federationService: federationService,
|
||||
repositories: repositories,
|
||||
telemetry: telemetry,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (i FollowServiceImpl) NewFollow(ctx context.Context, follower, followee *entity.User) (*entity.Follow, error) {
|
||||
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.FollowServiceImpl.NewFollow").
|
||||
AddAttribute("follower", follower.URI).
|
||||
AddAttribute("followee", followee.URI)
|
||||
defer s.End()
|
||||
ctx = s.Context()
|
||||
|
||||
f, err := i.repositories.Follows().Follow(ctx, follower, followee)
|
||||
if err != nil {
|
||||
i.log.Error(err, "Failed to create follow", "follower", follower.ID, "followee", followee.ID)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.AddAttribute("followID", f.URI).
|
||||
AddAttribute("followURI", f.URI)
|
||||
|
||||
i.log.V(2).Info("Created follow", "follower", follower.ID, "followee", followee.ID)
|
||||
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (i FollowServiceImpl) GetFollow(ctx context.Context, id uuid.UUID) (*entity.Follow, error) {
|
||||
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.FollowServiceImpl.GetFollow").
|
||||
AddAttribute("followID", id)
|
||||
defer s.End()
|
||||
ctx = s.Context()
|
||||
|
||||
f, err := i.repositories.Follows().GetByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if f != nil {
|
||||
s.AddAttribute("followURI", f.URI)
|
||||
}
|
||||
|
||||
return f, nil
|
||||
}
|
||||
|
||||
func (i FollowServiceImpl) ImportLysandFollow(ctx context.Context, lFollow *lysand.Follow) (*entity.Follow, error) {
|
||||
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.FollowServiceImpl.ImportLysandFollow").
|
||||
AddAttribute("uri", lFollow.URI.String())
|
||||
defer s.End()
|
||||
ctx = s.Context()
|
||||
|
||||
var f *entity.Follow
|
||||
if err := i.repositories.Atomic(ctx, func(ctx context.Context, tx repository.Manager) error {
|
||||
follower, err := i.repositories.Users().Resolve(ctx, lFollow.Author)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.AddAttribute("follower", follower.URI)
|
||||
|
||||
followee, err := i.repositories.Users().Resolve(ctx, lFollow.Followee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.AddAttribute("followee", followee.URI)
|
||||
|
||||
f, err = i.repositories.Follows().Follow(ctx, follower, followee)
|
||||
return err
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.AddAttribute("followID", f.ID).
|
||||
AddAttribute("followURI", f.URI)
|
||||
|
||||
return f, nil
|
||||
}
|
||||
98
internal/service/svc_impls/note_service_impl.go
Normal file
98
internal/service/svc_impls/note_service_impl.go
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
package svc_impls
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/lysand-org/versia-go/internal/repository"
|
||||
"github.com/lysand-org/versia-go/internal/service"
|
||||
"slices"
|
||||
|
||||
"git.devminer.xyz/devminer/unitel"
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/google/uuid"
|
||||
"github.com/lysand-org/versia-go/internal/api_schema"
|
||||
"github.com/lysand-org/versia-go/internal/entity"
|
||||
"github.com/lysand-org/versia-go/internal/tasks"
|
||||
"github.com/lysand-org/versia-go/pkg/lysand"
|
||||
)
|
||||
|
||||
var _ service.NoteService = (*NoteServiceImpl)(nil)
|
||||
|
||||
type NoteServiceImpl struct {
|
||||
federationService service.FederationService
|
||||
taskService service.TaskService
|
||||
|
||||
repositories repository.Manager
|
||||
|
||||
telemetry *unitel.Telemetry
|
||||
|
||||
log logr.Logger
|
||||
}
|
||||
|
||||
func NewNoteServiceImpl(federationService service.FederationService, taskService service.TaskService, repositories repository.Manager, telemetry *unitel.Telemetry, log logr.Logger) *NoteServiceImpl {
|
||||
return &NoteServiceImpl{
|
||||
federationService: federationService,
|
||||
taskService: taskService,
|
||||
repositories: repositories,
|
||||
telemetry: telemetry,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (i NoteServiceImpl) CreateNote(ctx context.Context, req api_schema.CreateNoteRequest) (*entity.Note, error) {
|
||||
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.NoteServiceImpl.CreateNote")
|
||||
defer s.End()
|
||||
ctx = s.Context()
|
||||
|
||||
var n *entity.Note
|
||||
|
||||
if err := i.repositories.Atomic(ctx, func(ctx context.Context, tx repository.Manager) error {
|
||||
// FIXME: Use the user that created the note
|
||||
author, err := tx.Users().GetLocalByID(ctx, uuid.MustParse("b6f4bcb5-ac5a-4a87-880a-c7f88f58a172"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if author == nil {
|
||||
return api_schema.ErrBadRequest(map[string]any{"reason": "author not found"})
|
||||
}
|
||||
|
||||
mentionedUsers, err := i.repositories.Users().ResolveMultiple(ctx, req.Mentions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if slices.ContainsFunc(mentionedUsers, func(u *entity.User) bool { return u.ID == author.ID }) {
|
||||
return api_schema.ErrBadRequest(map[string]any{"reason": "cannot mention self"})
|
||||
}
|
||||
|
||||
n, err = tx.Notes().NewNote(ctx, author, req.Content, mentionedUsers)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := i.taskService.ScheduleTask(ctx, tasks.FederateNote, tasks.FederateNoteData{NoteID: n.ID}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (i NoteServiceImpl) GetNote(ctx context.Context, id uuid.UUID) (*entity.Note, error) {
|
||||
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.NoteServiceImpl.GetUserByID")
|
||||
defer s.End()
|
||||
ctx = s.Context()
|
||||
|
||||
return i.repositories.Notes().GetByID(ctx, id)
|
||||
}
|
||||
|
||||
func (i NoteServiceImpl) ImportLysandNote(ctx context.Context, lNote *lysand.Note) (*entity.Note, error) {
|
||||
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.NoteServiceImpl.ImportLysandNote")
|
||||
defer s.End()
|
||||
ctx = s.Context()
|
||||
|
||||
return i.repositories.Notes().ImportLysandNote(ctx, lNote)
|
||||
}
|
||||
49
internal/service/svc_impls/task_service_impl.go
Normal file
49
internal/service/svc_impls/task_service_impl.go
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
package svc_impls
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/lysand-org/versia-go/internal/service"
|
||||
|
||||
"git.devminer.xyz/devminer/unitel"
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/lysand-org/versia-go/pkg/taskqueue"
|
||||
)
|
||||
|
||||
var _ service.TaskService = (*TaskServiceImpl)(nil)
|
||||
|
||||
type TaskServiceImpl struct {
|
||||
client *taskqueue.Client
|
||||
|
||||
telemetry *unitel.Telemetry
|
||||
log logr.Logger
|
||||
}
|
||||
|
||||
func NewTaskServiceImpl(client *taskqueue.Client, telemetry *unitel.Telemetry, log logr.Logger) *TaskServiceImpl {
|
||||
return &TaskServiceImpl{
|
||||
client: client,
|
||||
|
||||
telemetry: telemetry,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (i TaskServiceImpl) ScheduleTask(ctx context.Context, type_ string, data any) error {
|
||||
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.TaskServiceImpl.ScheduleTask")
|
||||
defer s.End()
|
||||
ctx = s.Context()
|
||||
|
||||
t, err := taskqueue.NewTask(type_, data)
|
||||
if err != nil {
|
||||
i.log.Error(err, "Failed to create task", "type", type_)
|
||||
return err
|
||||
}
|
||||
|
||||
if err := i.client.Submit(ctx, t); err != nil {
|
||||
i.log.Error(err, "Failed to schedule task", "type", type_, "taskID", t.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
i.log.V(2).Info("Scheduled task", "type", type_, "taskID", t.ID)
|
||||
|
||||
return nil
|
||||
}
|
||||
122
internal/service/svc_impls/user_service_impl.go
Normal file
122
internal/service/svc_impls/user_service_impl.go
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
package svc_impls
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ed25519"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"github.com/lysand-org/versia-go/internal/repository"
|
||||
"github.com/lysand-org/versia-go/internal/service"
|
||||
"net/url"
|
||||
|
||||
"git.devminer.xyz/devminer/unitel"
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/google/uuid"
|
||||
"github.com/lysand-org/versia-go/config"
|
||||
"github.com/lysand-org/versia-go/ent/schema"
|
||||
"github.com/lysand-org/versia-go/internal/entity"
|
||||
"github.com/lysand-org/versia-go/internal/utils"
|
||||
"github.com/lysand-org/versia-go/pkg/webfinger"
|
||||
)
|
||||
|
||||
var _ service.UserService = (*UserServiceImpl)(nil)
|
||||
|
||||
type UserServiceImpl struct {
|
||||
repositories repository.Manager
|
||||
|
||||
federationService service.FederationService
|
||||
|
||||
telemetry *unitel.Telemetry
|
||||
|
||||
log logr.Logger
|
||||
}
|
||||
|
||||
func NewUserServiceImpl(repositories repository.Manager, federationService service.FederationService, telemetry *unitel.Telemetry, log logr.Logger) *UserServiceImpl {
|
||||
return &UserServiceImpl{
|
||||
repositories: repositories,
|
||||
federationService: federationService,
|
||||
telemetry: telemetry,
|
||||
log: log,
|
||||
}
|
||||
}
|
||||
|
||||
func (i UserServiceImpl) WithRepositories(repositories repository.Manager) service.UserService {
|
||||
return NewUserServiceImpl(repositories, i.federationService, i.telemetry, i.log)
|
||||
}
|
||||
|
||||
func (i UserServiceImpl) NewUser(ctx context.Context, username, password string) (*entity.User, error) {
|
||||
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.UserServiceImpl.NewUser")
|
||||
defer s.End()
|
||||
ctx = s.Context()
|
||||
|
||||
if err := schema.ValidateUsername(username); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pub, priv, err := ed25519.GenerateKey(rand.Reader)
|
||||
if err != nil {
|
||||
i.log.Error(err, "Failed to generate ed25519 key pair")
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
user, err := i.repositories.Users().NewUser(ctx, username, password, priv, pub)
|
||||
if err != nil {
|
||||
i.log.Error(err, "Failed to create user", "username", username)
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
i.log.V(2).Info("Create user", "id", user.ID, "uri", user.URI)
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (i UserServiceImpl) GetUserByID(ctx context.Context, id uuid.UUID) (*entity.User, error) {
|
||||
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.UserServiceImpl.GetUserByID")
|
||||
defer s.End()
|
||||
ctx = s.Context()
|
||||
|
||||
return i.repositories.Users().LookupByIDOrUsername(ctx, id.String())
|
||||
}
|
||||
|
||||
func (i UserServiceImpl) GetWebfingerForUser(ctx context.Context, userID string) (*webfinger.User, error) {
|
||||
s := i.telemetry.StartSpan(ctx, "function", "service/svc_impls.UserServiceImpl.GetWebfingerForUser")
|
||||
defer s.End()
|
||||
ctx = s.Context()
|
||||
|
||||
u, err := i.repositories.Users().LookupByIDOrUsername(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if u == nil {
|
||||
return nil, fmt.Errorf("user not found")
|
||||
}
|
||||
|
||||
wf := &webfinger.User{
|
||||
UserID: webfinger.UserID{
|
||||
ID: u.ID.String(),
|
||||
// FIXME: Move this away into a service or sth
|
||||
Domain: config.C.PublicAddress.Host,
|
||||
},
|
||||
URI: utils.UserAPIURL(u.ID).ToStd(),
|
||||
}
|
||||
|
||||
if u.Edges.AvatarImage != nil {
|
||||
avatarURL, err := url.Parse(u.Edges.AvatarImage.URL)
|
||||
if err != nil {
|
||||
i.log.Error(err, "Failed to parse avatar URL")
|
||||
|
||||
wf.Avatar = utils.DefaultAvatarURL(u.ID).ToStd()
|
||||
wf.AvatarMIMEType = "image/svg+xml"
|
||||
} else {
|
||||
wf.Avatar = avatarURL
|
||||
wf.AvatarMIMEType = u.Edges.AvatarImage.MimeType
|
||||
}
|
||||
} else {
|
||||
wf.Avatar = utils.DefaultAvatarURL(u.ID).ToStd()
|
||||
wf.AvatarMIMEType = "image/svg+xml"
|
||||
}
|
||||
|
||||
return wf, nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue