feat: share post to other apps
This commit is contained in:
@@ -228,6 +228,62 @@ func (r *PostRepo) collectPosts(ctx context.Context, total int, query string, ar
|
||||
return posts, total, nil
|
||||
}
|
||||
|
||||
// AddReshare records that `viewerID` reshared `postID`. Idempotent —
|
||||
// repeated calls with the same pair are no-ops (the PRIMARY KEY makes
|
||||
// the second insert a conflict, which we explicitly ignore). Returns
|
||||
// nil on success regardless of whether a row was actually inserted.
|
||||
func (r *PostRepo) AddReshare(ctx context.Context, postID, viewerID string) error {
|
||||
const q = `
|
||||
INSERT INTO post_reshares (post_id, user_id)
|
||||
VALUES ($1, $2)
|
||||
ON CONFLICT (post_id, user_id) DO NOTHING`
|
||||
if _, err := r.pg.Pool.Exec(ctx, q, postID, viewerID); err != nil {
|
||||
return fmt.Errorf("add reshare: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveReshare deletes the reshare relationship. Idempotent — deleting
|
||||
// a row that doesn't exist returns nil rather than ErrPostNotFound,
|
||||
// since "I'm not subscribed" is the desired end state either way.
|
||||
func (r *PostRepo) RemoveReshare(ctx context.Context, postID, viewerID string) error {
|
||||
const q = `DELETE FROM post_reshares WHERE post_id = $1 AND user_id = $2`
|
||||
if _, err := r.pg.Pool.Exec(ctx, q, postID, viewerID); err != nil {
|
||||
return fmt.Errorf("remove reshare: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReshareStatesFor returns a set of post IDs that `viewerID` has
|
||||
// reshared, filtered to the supplied `postIDs`. Same shape as
|
||||
// ImagesFor — one batched query so a feed render doesn't N+1 the
|
||||
// reshare table. Returns an empty map when `viewerID` is "" (anonymous
|
||||
// viewer can't have reshared anything).
|
||||
func (r *PostRepo) ReshareStatesFor(ctx context.Context, viewerID string, postIDs []string) (map[string]bool, error) {
|
||||
out := make(map[string]bool, len(postIDs))
|
||||
if viewerID == "" || len(postIDs) == 0 {
|
||||
return out, nil
|
||||
}
|
||||
rows, err := r.pg.Pool.Query(ctx, `
|
||||
SELECT post_id
|
||||
FROM post_reshares
|
||||
WHERE user_id = $1 AND post_id = ANY($2)`,
|
||||
viewerID, postIDs,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("query reshare states: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var id string
|
||||
if err := rows.Scan(&id); err != nil {
|
||||
return nil, fmt.Errorf("scan reshare state: %w", err)
|
||||
}
|
||||
out[id] = true
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
// ImagesFor returns a map post_id → [images...] for a batch of post IDs in
|
||||
// a single query so we don't N+1 the feed endpoint. Exported because the
|
||||
// CollectionService needs to hydrate images onto posts that come back
|
||||
|
||||
Reference in New Issue
Block a user