summaryrefslogtreecommitdiff
path: root/internal/server/api/helpers.go
blob: 03f45f10fb5fc18732c5a69a95b4390e07303161 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package api

import (
	"context"
	"log"
	"strings"
	"time"

	"github.com/kyren223/eko/internal/data"
	"github.com/kyren223/eko/internal/packet"
	"github.com/kyren223/eko/internal/server/session"
	"github.com/kyren223/eko/pkg/snowflake"
)

const hex = "0123456789abcdefABCDEF"

func isValidHexColor(color string) (bool, string) {
	if len(color) != 7 {
		return false, "color must be hex with length of 7"
	}

	if color[0] != '#' {
		return false, "color must start with '#'"
	}

	for _, c := range color[1:] {
		if !strings.ContainsRune(hex, c) {
			return false, "color must start with '#' and contain exactly 6 digits 0-9, a-f, A-F"
		}
	}

	return true, ""
}

func IsNetworkAdmin(ctx context.Context, queries *data.Queries, userId, networkId snowflake.ID) (bool, error) {
	userNetwork, err := queries.GetMemberById(ctx, data.GetMemberByIdParams{
		NetworkID: networkId,
		UserID:    userId,
	})
	if err != nil {
		return false, err
	}

	isAdmin := userNetwork.IsAdmin && userNetwork.IsMember && !userNetwork.IsBanned
	return isAdmin, nil
}

func NetworkPropagateWithFilter(
	ctx context.Context, sess *session.Session,
	network snowflake.ID, payload packet.Payload,
	filter func(userId snowflake.ID) (pass bool),
) packet.Payload {
	var sessions []snowflake.ID
	sess.Manager().UseSessions(func(s map[snowflake.ID]*session.Session) {
		sessions = make([]snowflake.ID, 0, len(s)-1)
		for key := range s {
			if key != sess.ID() && filter(key) {
				sessions = append(sessions, key)
			}
		}
	})

	queries := data.New(db)
	sessions, err := queries.FilterUsersInNetwork(ctx, data.FilterUsersInNetworkParams{
		NetworkID: network,
		Users:     sessions,
	})
	if err != nil {
		log.Println("database error in propagate:", err)
		return &ErrInternalError
	}

	for _, sessionId := range sessions {
		session := sess.Manager().Session(sessionId)
		if session == nil {
			continue
		}
		timeout := 1 * time.Second
		context, cancel := context.WithTimeout(context.Background(), timeout)
		go func() {
			defer cancel()
			pkt := packet.NewPacket(packet.NewMsgPackEncoder(payload))
			if ok := session.Write(context, pkt); !ok {
				log.Println(sess.Addr(), "propagation to", session.Addr(), "failed")
			}
		}()
	}

	return payload
}

func NetworkPropagate(
	ctx context.Context, sess *session.Session,
	network snowflake.ID, payload packet.Payload,
) packet.Payload {
	return NetworkPropagateWithFilter(ctx, sess, network, payload, func(userId snowflake.ID) bool {
		return true
	})
}

func SplitMembersAndUsers(membersAndUsers []data.GetNetworkMembersRow) ([]data.Member, []data.User) {
	members := make([]data.Member, 0, len(membersAndUsers))
	users := make([]data.User, 0, len(membersAndUsers))
	for _, memberAndUser := range membersAndUsers {
		members = append(members, memberAndUser.Member)
		users = append(users, memberAndUser.User)
	}

	return members, users
}