tinyrelayfile
tinyrelay/internal/records/rooms.go/

internal/records/rooms.go raw
1package records
2
3import (
4 "context"
5 "database/sql"
6 "errors"
7 "fmt"
8
9 "github.com/FelineStateMachine/tinyrelay/internal/event"
10)
11
12// PublishRoom emits the relay-signed metadata (39000), admins (39001) and
13// members (39002) records for one room. A room that no longer exists has its
14// records retired instead. The slug room is covered by PublishMembership.
15func (s *Service) PublishRoom(ctx context.Context, roomID string, now int64) ([]event.Event, error) {
16 var name, about, picture, access string
17 var deleted int64
18 err := s.store.DB().QueryRowContext(ctx, `SELECT name,about,picture,access,deleted_at FROM rooms WHERE id=?`, roomID).Scan(&name, &about, &picture, &access, &deleted)
19 if errors.Is(err, sql.ErrNoRows) || (err == nil && deleted > 0) {
20 return nil, s.RetireRoom(ctx, roomID)
21 }
22 if err != nil {
23 return nil, fmt.Errorf("room record: %w", err)
24 }
25 rows, err := s.store.DB().QueryContext(ctx, `SELECT pubkey,role FROM room_members WHERE room_id=? ORDER BY CASE role WHEN 'owner' THEN 0 WHEN 'admin' THEN 1 ELSE 2 END,pubkey`, roomID)
26 if err != nil {
27 return nil, fmt.Errorf("room members: %w", err)
28 }
29 defer rows.Close()
30 var admins, members [][]string
31 for rows.Next() {
32 var pk, role string
33 if err := rows.Scan(&pk, &role); err != nil {
34 return nil, err
35 }
36 members = append(members, []string{"p", pk})
37 if role == "owner" || role == "admin" {
38 admins = append(admins, []string{"p", pk, role})
39 }
40 }
41 if err := rows.Err(); err != nil {
42 return nil, err
43 }
44 p := s.policy()
45 if access == "open" && !p.DirectoryPublic {
46 members = nil
47 }
48 meta := [][]string{{"-"}, {"d", roomID}, {"name", name}, {"about", about}}
49 if picture != "" {
50 meta = append(meta, []string{"picture", picture})
51 }
52 if access == "members" {
53 meta = append(meta, []string{"closed"})
54 } else {
55 meta = append(meta, []string{"open"})
56 }
57 if p.Reads == "members" {
58 meta = append(meta, []string{"private"})
59 } else {
60 meta = append(meta, []string{"public"})
61 }
62 vals := []struct {
63 kind int
64 tags [][]string
65 }{
66 {event.KIND_GROUP_METADATA, meta},
67 {event.KIND_GROUP_ADMINS, append([][]string{{"-"}, {"d", roomID}}, admins...)},
68 {event.KIND_GROUP_MEMBERS, append([][]string{{"-"}, {"d", roomID}}, members...)},
69 }
70 out := make([]event.Event, 0, len(vals))
71 for _, v := range vals {
72 e, err := s.signed(ctx, v.kind, v.tags, "", now)
73 if err != nil {
74 return nil, err
75 }
76 out = append(out, e)
77 }
78 return out, nil
79}
80
81// RoomNotice emits the relay-signed member notice a Buzz-compatible client
82// shows when someone is added to (44100) or removed from (44101) a room.
83func (s *Service) RoomNotice(ctx context.Context, roomID, pubkey string, added bool, now int64) (event.Event, error) {
84 kind := event.KIND_ROOM_MEMBER_REMOVED
85 if added {
86 kind = event.KIND_ROOM_MEMBER_ADDED
87 }
88 return s.signed(ctx, kind, [][]string{{"h", roomID}, {"p", pubkey}}, "", now)
89}
90
91// RetireRoom removes the relay's own records for a room that was deleted.
92func (s *Service) RetireRoom(ctx context.Context, roomID string) error {
93 _, err := s.store.DB().ExecContext(ctx, `DELETE FROM events WHERE pubkey=? AND kind IN (?,?,?) AND d=?`, s.PublicKey(), event.KIND_GROUP_METADATA, event.KIND_GROUP_ADMINS, event.KIND_GROUP_MEMBERS, roomID)
94 return err
95}

About

ownerc01503e8035f
visibilitypublic
headd730679639bf

Maintainers

  • c01503e8035f owner
  • ba1b5beed5b5 agent hermes

Clone

  • https://012.run/npub1cq2s86qrtadf36eqq3epm38wmhdynrrcwxf84eldk3f94dkv7ttsrulrz5/tinyrelay.git

Refs