linstrom/web/debug/posts.go
mStar ff6a730e58
Some checks failed
/ docker (push) Failing after 2m50s
Follow accept works and messags are pushed as expected
2025-05-10 11:18:28 +02:00

169 lines
4.7 KiB
Go

package webdebug
import (
"database/sql"
"encoding/json"
"errors"
"io"
"net/http"
webutils "git.mstar.dev/mstar/goutils/http"
"git.mstar.dev/mstar/goutils/sliceutils"
"github.com/rs/zerolog/hlog"
"gorm.io/gorm"
"git.mstar.dev/mstar/linstrom/activitypub"
"git.mstar.dev/mstar/linstrom/shared"
"git.mstar.dev/mstar/linstrom/storage-new"
"git.mstar.dev/mstar/linstrom/storage-new/dbgen"
"git.mstar.dev/mstar/linstrom/storage-new/models"
webap "git.mstar.dev/mstar/linstrom/web/public/api/activitypub"
webshared "git.mstar.dev/mstar/linstrom/web/shared"
)
func postAs(w http.ResponseWriter, r *http.Request) {
type Inbound struct {
Username string `json:"username"`
Content string `json:"content"`
}
log := hlog.FromRequest(r)
dec := json.NewDecoder(r.Body)
data := Inbound{}
err := dec.Decode(&data)
if err != nil {
webutils.ProblemDetails(
w,
http.StatusBadRequest,
"/errors/bad-request-data",
"bad request data",
nil,
map[string]any{
"sample": Inbound{
Username: "bob",
Content: "Heya there, this is sample data",
},
},
)
return
}
user, err := dbgen.User.GetByUsername(data.Username)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
webutils.ProblemDetailsStatusOnly(w, http.StatusNotFound)
} else {
log.Error().Err(err).Str("name", data.Username).Msg("Failed to find user")
webutils.ProblemDetailsStatusOnly(w, http.StatusInternalServerError)
}
return
}
n := dbgen.Note
note := models.Note{
ID: shared.NewId(),
Creator: *user,
CreatorId: user.ID,
RawContent: data.Content,
Remote: false,
ContentWarning: sql.NullString{Valid: false},
RepliesTo: sql.NullString{Valid: false},
Quotes: sql.NullString{Valid: false},
AccessLevel: models.NOTE_TARGET_PUBLIC,
OriginId: 1,
}
tx := dbgen.Q.Begin()
err = tx.Note.Select(
n.ID,
n.CreatorId,
n.RawContent,
n.Remote,
n.ContentWarning,
n.RepliesTo,
n.Quotes,
n.AccessLevel,
n.OriginId,
).Create(&note)
if err != nil {
_ = tx.Rollback()
log.Error().
Err(err).
Str("username", data.Username).
Str("content", data.Content).
Msg("Failed to create message")
webutils.ProblemDetailsStatusOnly(w, http.StatusInternalServerError)
return
}
activity := models.Activity{
Id: shared.NewId(),
Type: string(models.ActivityCreate),
ObjectId: note.ID,
ObjectType: uint32(models.ActivitystreamsActivityTargetNote),
}
err = tx.Activity.Create(&activity)
if err != nil {
_ = tx.Rollback()
log.Error().Err(err).Msg("Failed to create activity for new note")
}
err = tx.Commit()
if err != nil {
log.Error().Err(err).Msg("Failed to commit note creation")
webutils.ProblemDetailsStatusOnly(w, http.StatusInternalServerError)
return
}
u2u := dbgen.UserToUserRelation
links, err := u2u.GetFollowersForId(user.ID)
if err != nil {
log.Error().Err(err).Msg("Failed to get follower inbox links for user")
webutils.ProblemDetailsStatusOnly(w, http.StatusInternalServerError)
return
}
log.Debug().Strs("links", links).Send()
act, err := webap.CreateFromStorage(r.Context(), activity.Id)
if err != nil {
log.Error().Err(err).Msg("Failed to fetch and format new note")
webutils.ProblemDetailsStatusOnly(w, http.StatusInternalServerError)
return
}
act.Context = activitypub.BaseLdContext
outData, err := json.Marshal(act)
if err != nil {
log.Error().Err(err).Msg("Failed to marshal new note")
webutils.ProblemDetailsStatusOnly(w, http.StatusInternalServerError)
return
}
for _, link := range links {
log.Debug().Str("target-inbox", link).Msg("Sending message to")
go func() {
res, err := webshared.RequestSignedCavage("POST", link, outData, user)
if err != nil {
log.Warn().Err(err).Str("link", link).Msg("Failed to send create to target inbox")
}
if res.StatusCode >= 400 {
body, _ := io.ReadAll(res.Body)
log.Warn().Int("status-code", res.StatusCode).Bytes("body", body).Msg("Bad reply")
}
}()
}
}
func notesFrom(w http.ResponseWriter, r *http.Request) {
log := hlog.FromRequest(r)
username := r.FormValue("username")
user, err := dbgen.User.GetByUsername(username)
if err != nil {
log.Error().Err(err).Str("name", username).Msg("Failed to get user")
storage.HandleReconnectError(err)
webutils.ProblemDetailsStatusOnly(w, http.StatusInternalServerError)
return
}
notes, err := dbgen.Note.GetNotesPaged(user.ID, 0, uint8(models.NOTE_TARGET_PUBLIC))
if err != nil {
log.Error().Err(err).Str("name", username).Msg("Failed to get notes")
webutils.ProblemDetailsStatusOnly(w, http.StatusInternalServerError)
return
}
publicNotes := sliceutils.Map(notes, func(t models.Note) webshared.Note {
n := webshared.Note{}
n.FromModel(&t)
return n
})
webutils.SendJson(w, publicNotes)
}