-
Notifications
You must be signed in to change notification settings - Fork 43
/
Copy pathmanager.go
136 lines (108 loc) · 3.66 KB
/
manager.go
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package voice
import (
"context"
"log/slog"
"sync"
"github.com/disgoorg/snowflake/v2"
"github.com/disgoorg/disgo/gateway"
)
type (
// StateUpdateFunc is used to update the voice state of the bot from the Manager.
StateUpdateFunc func(ctx context.Context, guildID snowflake.ID, channelID *snowflake.ID, selfMute bool, selfDeaf bool) error
// Manager manages all voice connections.
Manager interface {
// HandleVoiceStateUpdate handles a gateway.EventVoiceStateUpdate
HandleVoiceStateUpdate(update gateway.EventVoiceStateUpdate)
// HandleVoiceServerUpdate handles a gateway.EventVoiceServerUpdate
HandleVoiceServerUpdate(update gateway.EventVoiceServerUpdate)
// CreateConn creates a new voice connection for the given guild.
CreateConn(guildID snowflake.ID) Conn
// GetConn returns the voice connection for the given guild.
GetConn(guildID snowflake.ID) Conn
// ForEachCon runs the given function for each voice connection. This is thread-safe.
ForEachCon(f func(connection Conn))
// RemoveConn removes the voice connection for the given guild.
RemoveConn(guildID snowflake.ID)
// Close closes all voice connections.
Close(ctx context.Context)
}
)
// NewManager creates a new Manager.
func NewManager(voiceStateUpdateFunc StateUpdateFunc, userID snowflake.ID, opts ...ManagerConfigOpt) Manager {
config := DefaultManagerConfig()
config.Apply(opts)
config.Logger = config.Logger.With(slog.String("name", "voice"))
return &managerImpl{
config: *config,
voiceStateUpdateFunc: voiceStateUpdateFunc,
userID: userID,
conns: map[snowflake.ID]Conn{},
}
}
type managerImpl struct {
config ManagerConfig
voiceStateUpdateFunc StateUpdateFunc
userID snowflake.ID
conns map[snowflake.ID]Conn
connsMu sync.Mutex
}
func (m *managerImpl) HandleVoiceStateUpdate(update gateway.EventVoiceStateUpdate) {
m.config.Logger.Debug("new VoiceStateUpdate", slog.Int64("guild_id", int64(update.GuildID)))
conn := m.GetConn(update.GuildID)
if conn == nil {
return
}
conn.HandleVoiceStateUpdate(update)
}
func (m *managerImpl) HandleVoiceServerUpdate(update gateway.EventVoiceServerUpdate) {
m.config.Logger.Debug("new VoiceServerUpdate", slog.Int64("guild_id", int64(update.GuildID)))
conn := m.GetConn(update.GuildID)
if conn == nil {
return
}
conn.HandleVoiceServerUpdate(update)
}
func (m *managerImpl) CreateConn(guildID snowflake.ID) Conn {
m.config.Logger.Debug("Creating new voice conn", slog.Int64("guild_id", int64(guildID)))
if conn := m.GetConn(guildID); conn != nil {
return conn
}
m.connsMu.Lock()
defer m.connsMu.Unlock()
var once sync.Once
removeFunc := func() { once.Do(func() { m.RemoveConn(guildID) }) }
conn := m.config.ConnCreateFunc(guildID, m.userID, m.voiceStateUpdateFunc, removeFunc, append([]ConnConfigOpt{WithConnLogger(m.config.Logger)}, m.config.ConnOpts...)...)
m.conns[guildID] = conn
return conn
}
func (m *managerImpl) GetConn(guildID snowflake.ID) Conn {
m.connsMu.Lock()
defer m.connsMu.Unlock()
return m.conns[guildID]
}
func (m *managerImpl) ForEachCon(f func(connection Conn)) {
m.connsMu.Lock()
defer m.connsMu.Unlock()
for _, connection := range m.conns {
f(connection)
}
}
func (m *managerImpl) RemoveConn(guildID snowflake.ID) {
m.config.Logger.Debug("Removing voice conn", slog.Int64("guild_id", int64(guildID)))
conn := m.GetConn(guildID)
if conn == nil {
return
}
m.connsMu.Lock()
defer m.connsMu.Unlock()
delete(m.conns, guildID)
}
func (m *managerImpl) Close(ctx context.Context) {
m.connsMu.Lock()
conns := m.conns
m.connsMu.Unlock()
for i := range conns {
conns[i].Close(ctx)
}
m.conns = map[snowflake.ID]Conn{}
}