big update: added reactions, groups, media share
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
)
|
||||
|
||||
// CreateGroup creates a group conversation with the creator as owner and
|
||||
// the given members added, returning the created conversation.
|
||||
func (s *Store) CreateGroup(ctx context.Context, creatorID int64, name string, memberIDs []int64) (*Conversation, error) {
|
||||
conn, err := s.pool.Acquire(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer conn.Release()
|
||||
|
||||
tx, err := conn.Begin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer tx.Rollback(ctx)
|
||||
|
||||
var conv Conversation
|
||||
err = tx.QueryRow(ctx, `
|
||||
INSERT INTO conversations(type, name) VALUES('group', $1)
|
||||
RETURNING id, type, name, avatar, created_at
|
||||
`, name).Scan(&conv.ID, &conv.Type, &conv.Name, &conv.Avatar, &conv.CreatedAt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err := tx.Exec(ctx, `
|
||||
INSERT INTO conversation_members(conversation_id, user_id, role)
|
||||
VALUES($1, $2, 'owner')
|
||||
`, conv.ID, creatorID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
seen := map[int64]struct{}{creatorID: {}}
|
||||
for _, uid := range memberIDs {
|
||||
if _, ok := seen[uid]; ok {
|
||||
continue
|
||||
}
|
||||
seen[uid] = struct{}{}
|
||||
if _, err := tx.Exec(ctx, `
|
||||
INSERT INTO conversation_members(conversation_id, user_id, role)
|
||||
VALUES($1, $2, 'member')
|
||||
ON CONFLICT (conversation_id, user_id) DO NOTHING
|
||||
`, conv.ID, uid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err := tx.Commit(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &conv, nil
|
||||
}
|
||||
|
||||
// AddMember adds a user to a conversation; it is a no-op if already a member.
|
||||
func (s *Store) AddMember(ctx context.Context, conversationID, userID int64) error {
|
||||
_, err := s.pool.Exec(ctx, `
|
||||
INSERT INTO conversation_members(conversation_id, user_id, role)
|
||||
VALUES($1, $2, 'member')
|
||||
ON CONFLICT (conversation_id, user_id) DO NOTHING
|
||||
`, conversationID, userID)
|
||||
return err
|
||||
}
|
||||
|
||||
// RemoveMember removes a user from a conversation; it is a no-op if absent.
|
||||
func (s *Store) RemoveMember(ctx context.Context, conversationID, userID int64) error {
|
||||
_, err := s.pool.Exec(ctx, `
|
||||
DELETE FROM conversation_members WHERE conversation_id=$1 AND user_id=$2
|
||||
`, conversationID, userID)
|
||||
return err
|
||||
}
|
||||
|
||||
// MemberRole returns the role of a user in a conversation, or ErrNotFound.
|
||||
func (s *Store) MemberRole(ctx context.Context, conversationID, userID int64) (string, error) {
|
||||
var role string
|
||||
err := s.pool.QueryRow(ctx, `
|
||||
SELECT role FROM conversation_members WHERE conversation_id=$1 AND user_id=$2
|
||||
`, conversationID, userID).Scan(&role)
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return "", ErrNotFound
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
return role, nil
|
||||
}
|
||||
|
||||
// ListMembers returns the members of a conversation with their profiles.
|
||||
func (s *Store) ListMembers(ctx context.Context, conversationID int64) ([]MemberInfo, error) {
|
||||
rows, err := s.pool.Query(ctx, `
|
||||
SELECT u.id, u.username, u.display_name, u.avatar, u.created_at, cm.role, cm.joined_at
|
||||
FROM conversation_members cm
|
||||
JOIN users u ON u.id = cm.user_id
|
||||
WHERE cm.conversation_id = $1
|
||||
ORDER BY cm.joined_at, u.id
|
||||
`, conversationID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var members []MemberInfo
|
||||
for rows.Next() {
|
||||
var m MemberInfo
|
||||
if err := rows.Scan(
|
||||
&m.User.ID, &m.User.Username, &m.User.DisplayName, &m.User.Avatar, &m.User.CreatedAt,
|
||||
&m.Role, &m.JoinedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
members = append(members, m)
|
||||
}
|
||||
return members, nil
|
||||
}
|
||||
Reference in New Issue
Block a user