All checks were successful
/ docker (push) Successful in 3m59s
Will be used later to add to internal db
171 lines
5.4 KiB
Go
171 lines
5.4 KiB
Go
package activitypub
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"time"
|
|
|
|
webutils "git.mstar.dev/mstar/goutils/http"
|
|
"git.mstar.dev/mstar/goutils/other"
|
|
"git.mstar.dev/mstar/goutils/sliceutils"
|
|
"github.com/rs/zerolog/hlog"
|
|
|
|
"git.mstar.dev/mstar/linstrom/activitypub/shared/types"
|
|
"git.mstar.dev/mstar/linstrom/config"
|
|
"git.mstar.dev/mstar/linstrom/storage-new"
|
|
"git.mstar.dev/mstar/linstrom/storage-new/dbgen"
|
|
"git.mstar.dev/mstar/linstrom/storage-new/models"
|
|
webshared "git.mstar.dev/mstar/linstrom/web/shared"
|
|
)
|
|
|
|
func users(w http.ResponseWriter, r *http.Request) {
|
|
type OutboundKey struct {
|
|
Id string `json:"id"`
|
|
Owner string `json:"owner"`
|
|
Pem string `json:"publicKeyPem"`
|
|
}
|
|
type OutboundMedia struct {
|
|
Type string `json:"type"`
|
|
Url string `json:"url"`
|
|
MediaType string `json:"mediaType"`
|
|
}
|
|
type Outbound struct {
|
|
Context []any `json:"@context"`
|
|
Id string `json:"id"`
|
|
Type string `json:"type"`
|
|
PreferredUsername string `json:"preferredUsername"`
|
|
Inbox string `json:"inbox"`
|
|
PublicKey OutboundKey `json:"publicKey"`
|
|
Published time.Time `json:"published"`
|
|
DisplayName string `json:"name"`
|
|
Description *string `json:"summary,omitempty"`
|
|
PublicUrl string `json:"url"`
|
|
Icon *OutboundMedia `json:"icon,omitempty"`
|
|
Banner *OutboundMedia `json:"image,omitempty"`
|
|
Discoverable bool `json:"discoverable"`
|
|
Location *string `json:"vcard:Address,omitempty"`
|
|
Birthday *string `json:"vcard:bday,omitempty"`
|
|
SpeakAsCat bool `json:"speakAsCat"`
|
|
IsCat bool `json:"isCat"`
|
|
RestrictedFollow bool `json:"manuallyApprovesFollowers"`
|
|
}
|
|
log := hlog.FromRequest(r)
|
|
userId := r.PathValue("id")
|
|
user, err := dbgen.User.Where(dbgen.User.ID.Eq(userId)).
|
|
Preload(dbgen.User.Icon).Preload(dbgen.User.Banner).
|
|
Preload(dbgen.User.BeingTypes).
|
|
First()
|
|
if err != nil {
|
|
webutils.ProblemDetails(w, 500, "/errors/db-failure", "internal database failure", nil, nil)
|
|
if storage.HandleReconnectError(err) {
|
|
log.Warn().Msg("Connection to db lost. Reconnect attempt started")
|
|
} else {
|
|
log.Error().Err(err).Msg("Failed to get total user count from db")
|
|
}
|
|
return
|
|
}
|
|
|
|
apUrl := userIdToApUrl(user.ID)
|
|
var keyBytes string
|
|
if config.GlobalConfig.Experimental.UseEd25519Keys {
|
|
keyBytes = keyBytesToPem(user.PublicKeyEd)
|
|
} else {
|
|
keyBytes = keyBytesToPem(user.PublicKeyRsa)
|
|
}
|
|
data := Outbound{
|
|
Context: types.BaseLdContext,
|
|
Id: apUrl,
|
|
Type: "Person",
|
|
PreferredUsername: user.Username,
|
|
Inbox: apUrl + "/inbox",
|
|
PublicKey: OutboundKey{
|
|
Id: apUrl + "#main-key",
|
|
Owner: apUrl,
|
|
Pem: keyBytes,
|
|
},
|
|
Published: user.CreatedAt,
|
|
DisplayName: user.DisplayName,
|
|
PublicUrl: config.GlobalConfig.General.GetFullPublicUrl() + "/user/" + user.Username,
|
|
Discoverable: user.Indexable,
|
|
RestrictedFollow: user.RestrictedFollow,
|
|
}
|
|
if user.Description != "" {
|
|
data.Description = &user.Description
|
|
}
|
|
if user.Icon != nil {
|
|
log.Debug().Msg("icon found")
|
|
data.Icon = &OutboundMedia{
|
|
Type: "Image",
|
|
Url: config.GlobalConfig.General.GetFullPublicUrl() + webshared.EnsurePublicUrl(
|
|
user.Icon.Location,
|
|
),
|
|
MediaType: user.Icon.Type,
|
|
}
|
|
}
|
|
if user.Banner != nil {
|
|
log.Debug().Msg("icon banner")
|
|
data.Banner = &OutboundMedia{
|
|
Type: "Image",
|
|
Url: config.GlobalConfig.General.GetFullPublicUrl() + webshared.EnsurePublicUrl(
|
|
user.Banner.Location,
|
|
),
|
|
MediaType: user.Banner.Type,
|
|
}
|
|
}
|
|
if sliceutils.ContainsFunc(user.BeingTypes, func(t models.UserToBeing) bool {
|
|
return t.Being == models.BEING_CAT
|
|
}) {
|
|
data.IsCat = true
|
|
// data.SpeakAsCat = true // TODO: Move to check of separate field in db model
|
|
}
|
|
if user.Location.Valid {
|
|
data.Location = &user.Location.String
|
|
}
|
|
if user.Birthday.Valid {
|
|
data.Birthday = other.IntoPointer(user.Birthday.Time.Format("2006-Jan-02")) //YYYY-Month-DD
|
|
}
|
|
|
|
encoded, err := json.Marshal(data)
|
|
w.Header().Add("Content-Type", "application/activity+json")
|
|
fmt.Fprint(w, string(encoded))
|
|
}
|
|
|
|
func userInbox(w http.ResponseWriter, r *http.Request) {
|
|
log := hlog.FromRequest(r)
|
|
userId := r.PathValue("id")
|
|
data, err := io.ReadAll(r.Body)
|
|
log.Info().Err(err).Str("userId", userId).Bytes("body", data).Msg("Inbox message")
|
|
}
|
|
|
|
/*
|
|
Fine. You win JsonLD. I can't get you to work properly. I'll just treat you like normal json then
|
|
Fuck you.
|
|
|
|
If anyone wants to get this shit working *the propper way* with JsonLD, here's the
|
|
original code
|
|
var chain goap.BaseApChain = &goap.EmptyBaseObject{}
|
|
chain = goap.AppendUDIdData(chain, apUrl)
|
|
chain = goap.AppendUDTypeData(chain, "Person")
|
|
chain = goap.AppendASPreferredNameData(chain, goap.ValueValue[string]{Value: user.DisplayName})
|
|
chain = goap.AppendW3SecurityPublicKeyData(
|
|
chain,
|
|
apUrl+"#main-key",
|
|
apUrl,
|
|
keyBytesToPem(user.PublicKey),
|
|
)
|
|
|
|
chainMap := chain.MarshalToMap()
|
|
proc := ld.NewJsonLdProcessor()
|
|
options := ld.NewJsonLdOptions("")
|
|
tmp, tmperr := json.Marshal(chainMap)
|
|
fmt.Println(string(tmp), tmperr)
|
|
data, err := proc.Compact(chainMap, baseLdContext, options)
|
|
// data, err := goap.Compact(chain, baseLdContext)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("Failed to marshal ap chain")
|
|
webutils.ProblemDetailsStatusOnly(w, 500)
|
|
return
|
|
}
|
|
*/
|