fix: chat accepts posts

This commit is contained in:
Krispire Admin
2026-08-29 16:26:38 +05:30
parent 18bac9a22d
commit 7a730cd42e
8 changed files with 545 additions and 22 deletions
+20 -8
View File
@@ -547,6 +547,12 @@ type AddAttachmentParams struct {
Description *string
SiteName *string
ImageURL *string
// Shared entity: the durable reference plus a snapshot used only as a
// fallback. Live data is re-resolved per viewer at read time.
EntityType *string
EntityID *string
Snapshot []byte
}
// AddAttachment persists one attachment. conversation_id is denormalized here
@@ -557,17 +563,20 @@ func (r *ChatRepo) AddAttachment(ctx context.Context, p AddAttachmentParams) (*m
INSERT INTO message_attachments
(message_id, conversation_id, ord, kind, r2_key, mime, size_bytes,
width, height, duration_ms, blurhash, file_name,
url, title, description, site_name, image_url)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17)
url, title, description, site_name, image_url,
entity_type, entity_id, snapshot)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20)
RETURNING id, message_id, ord, kind, mime, size_bytes, width, height,
duration_ms, blurhash, file_name, url, title, description,
site_name, image_url, created_at`,
site_name, image_url, entity_type, entity_id, snapshot, created_at`,
p.MessageID, p.ConversationID, p.Ord, p.Kind, p.R2Key, p.Mime, p.SizeBytes,
p.Width, p.Height, p.DurationMs, p.Blurhash, p.FileName,
p.URL, p.Title, p.Description, p.SiteName, p.ImageURL,
p.EntityType, p.EntityID, p.Snapshot,
).Scan(&a.ID, &a.MessageID, &a.Ord, &a.Kind, &a.Mime, &a.SizeBytes, &a.Width,
&a.Height, &a.DurationMs, &a.Blurhash, &a.FileName, &a.URL, &a.Title,
&a.Description, &a.SiteName, &a.ImageURL, &a.CreatedAt)
&a.Description, &a.SiteName, &a.ImageURL,
&a.EntityType, &a.EntityID, &a.Entity, &a.CreatedAt)
if err != nil {
return nil, fmt.Errorf("add attachment: %w", err)
}
@@ -583,7 +592,7 @@ func (r *ChatRepo) AttachmentsFor(ctx context.Context, messageIDs []string) (map
rows, err := r.pg.Pool.Query(ctx, `
SELECT id, message_id, ord, kind, mime, size_bytes, width, height,
duration_ms, blurhash, file_name, url, title, description,
site_name, image_url, created_at
site_name, image_url, entity_type, entity_id, snapshot, created_at
FROM message_attachments
WHERE message_id = ANY($1)
ORDER BY message_id, ord`, messageIDs)
@@ -595,7 +604,8 @@ func (r *ChatRepo) AttachmentsFor(ctx context.Context, messageIDs []string) (map
var a model.Attachment
if err := rows.Scan(&a.ID, &a.MessageID, &a.Ord, &a.Kind, &a.Mime, &a.SizeBytes,
&a.Width, &a.Height, &a.DurationMs, &a.Blurhash, &a.FileName, &a.URL,
&a.Title, &a.Description, &a.SiteName, &a.ImageURL, &a.CreatedAt); err != nil {
&a.Title, &a.Description, &a.SiteName, &a.ImageURL,
&a.EntityType, &a.EntityID, &a.Entity, &a.CreatedAt); err != nil {
return nil, fmt.Errorf("scan attachment: %w", err)
}
out[a.MessageID] = append(out[a.MessageID], a)
@@ -640,7 +650,8 @@ func (r *ChatRepo) Gallery(ctx context.Context, conversationID, userID string, k
rows, err := r.pg.Pool.Query(ctx, `
SELECT a.id, a.message_id, a.ord, a.kind, a.mime, a.size_bytes, a.width,
a.height, a.duration_ms, a.blurhash, a.file_name, a.url, a.title,
a.description, a.site_name, a.image_url, a.created_at
a.description, a.site_name, a.image_url,
a.entity_type, a.entity_id, a.snapshot, a.created_at
FROM message_attachments a
JOIN messages m ON m.id = a.message_id
WHERE a.conversation_id = $1
@@ -661,7 +672,8 @@ func (r *ChatRepo) Gallery(ctx context.Context, conversationID, userID string, k
var a model.Attachment
if err := rows.Scan(&a.ID, &a.MessageID, &a.Ord, &a.Kind, &a.Mime, &a.SizeBytes,
&a.Width, &a.Height, &a.DurationMs, &a.Blurhash, &a.FileName, &a.URL,
&a.Title, &a.Description, &a.SiteName, &a.ImageURL, &a.CreatedAt); err != nil {
&a.Title, &a.Description, &a.SiteName, &a.ImageURL,
&a.EntityType, &a.EntityID, &a.Entity, &a.CreatedAt); err != nil {
return nil, fmt.Errorf("scan gallery row: %w", err)
}
out = append(out, a)
+40
View File
@@ -160,6 +160,46 @@ func (r *PostRepo) FindByID(ctx context.Context, id string) (*model.Post, error)
return p, nil
}
// FindByIDs loads many posts at once, keyed by id. Missing and soft-deleted
// ids are simply absent from the map.
//
// Exists so a page of chat messages sharing N posts costs one query instead of
// N — the same reason ImagesFor is batched.
func (r *PostRepo) FindByIDs(ctx context.Context, ids []string) (map[string]*model.Post, error) {
out := make(map[string]*model.Post, len(ids))
if len(ids) == 0 {
return out, nil
}
q := `SELECT ` + postSelectColumns + postSelectFrom + `WHERE p.id = ANY($1) AND p.deleted_at IS NULL`
rows, err := r.pg.Pool.Query(ctx, q, ids)
if err != nil {
return nil, fmt.Errorf("find posts: %w", err)
}
defer rows.Close()
found := make([]string, 0, len(ids))
for rows.Next() {
p := &model.Post{}
if err := scanPost(rows, p); err != nil {
return nil, fmt.Errorf("scan post: %w", err)
}
out[p.ID] = p
found = append(found, p.ID)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("find posts: %w", err)
}
imgs, err := r.ImagesFor(ctx, found)
if err != nil {
return nil, err
}
for id, p := range out {
p.Images = imgs[id]
}
return out, nil
}
// ListByHandle returns the profile feed for a user. Unknown handle →
// empty page (matches pre-existing behaviour).
func (r *PostRepo) ListByHandle(ctx context.Context, handle string, limit, offset int) ([]model.Post, int, error) {
+29
View File
@@ -242,6 +242,35 @@ func (r *BlockRepo) Unblock(ctx context.Context, blockerID, blockedID string) er
// BlockState reports, in one round-trip, whether a blocked b and whether
// b blocked a.
// BlockedWith returns the subset of others that viewerID is blocked with in
// EITHER direction — the set whose content must be hidden from them.
//
// The batched counterpart to BlockState, for resolving many authors at once.
func (r *BlockRepo) BlockedWith(ctx context.Context, viewerID string, others []string) (map[string]bool, error) {
out := make(map[string]bool, len(others))
if viewerID == "" || len(others) == 0 {
return out, nil
}
rows, err := r.pg.Pool.Query(ctx, `
SELECT CASE WHEN blocker_id = $1 THEN blocked_id ELSE blocker_id END
FROM user_blocks
WHERE (blocker_id = $1 AND blocked_id = ANY($2))
OR (blocked_id = $1 AND blocker_id = ANY($2))`,
viewerID, others)
if err != nil {
return nil, fmt.Errorf("blocked with: %w", err)
}
defer rows.Close()
for rows.Next() {
var id string
if err := rows.Scan(&id); err != nil {
return nil, fmt.Errorf("scan blocked with: %w", err)
}
out[id] = true
}
return out, rows.Err()
}
func (r *BlockRepo) BlockState(ctx context.Context, a, b string) (aBlockedB, bBlockedA bool, err error) {
err = r.pg.Pool.QueryRow(ctx, `
SELECT