-
Notifications
You must be signed in to change notification settings - Fork 563
/
manager.rs
141 lines (122 loc) · 5.08 KB
/
manager.rs
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
137
138
139
140
141
use std::collections::HashMap;
use std::sync::mpsc::Sender as MpscSender;
use super::{Handler, Target};
use ::client::gateway::GatewayStatus;
use ::model::{ChannelId, GuildId, UserId};
/// A manager is a struct responsible for managing [`Handler`]s which belong to
/// a single [WebSocket connection]. This is a fairly complex key-value store,
/// with a bit of extra utility for easily joining a "target".
///
/// The "target" used by the Manager is determined based on the `guild_id` and
/// `channel_id` provided. If a `guild_id` is _not_ provided to methods that
/// optionally require it, then the target is a group or 1-on-1 call with a
/// user. The `channel_id` is then used as the target.
///
/// If a `guild_id` is provided, then the target is the guild, as a user
/// can not be connected to two channels within one guild simultaneously.
///
/// [`Group`]: ../../model/struct.Group.html
/// [`Handler`]: struct.Handler.html
/// [guild's channel]: ../../model/enum.ChannelType.html#variant.Voice
/// [WebSocket connection]: ../../client/struct.Connection.html
pub struct Manager {
handlers: HashMap<Target, Handler>,
user_id: UserId,
ws: MpscSender<GatewayStatus>,
}
impl Manager {
#[doc(hidden)]
pub fn new(ws: MpscSender<GatewayStatus>, user_id: UserId) -> Manager {
Manager {
handlers: HashMap::new(),
user_id: user_id,
ws: ws,
}
}
/// Retrieves a mutable handler for the given target, if one exists.
pub fn get<T: Into<Target>>(&mut self, target_id: T)
-> Option<&mut Handler> {
self.handlers.get_mut(&target_id.into())
}
/// Connects to a target by retrieving its relevant [`Handler`] and
/// connecting, or creating the handler if required.
///
/// This can also switch to the given channel, if a handler already exists
/// for the target and the current connected channel is not equal to the
/// given channel.
///
/// In the case of channel targets, the same channel is used to connect to.
///
/// In the case of guilds, the provided channel is used to connect to. The
/// channel _must_ be in the provided guild. This is _not_ checked by the
/// library, and will result in an error. If there is already a connected
/// handler for the guild, _and_ the provided channel is different from the
/// channel that the connection is already connected to, then the handler
/// will switch the connection to the provided channel.
///
/// If you _only_ need to retrieve the handler for a target, then use
/// [`get`].
///
/// [`Handler`]: struct.Handler.html
/// [`get`]: #method.get
#[allow(map_entry)]
pub fn join(&mut self, guild_id: Option<GuildId>, channel_id: ChannelId)
-> &mut Handler {
if let Some(guild_id) = guild_id {
let target = Target::Guild(guild_id);
{
let mut found = false;
if let Some(handler) = self.handlers.get_mut(&target) {
handler.switch_to(channel_id);
found = true;
}
if found {
// Actually safe, as the key has already been found above.
return self.handlers.get_mut(&target).unwrap();
}
}
let mut handler = Handler::new(target, self.ws.clone(), self.user_id);
handler.join(channel_id);
self.handlers.insert(target, handler);
// Actually safe, as the key would have been inserted above.
self.handlers.get_mut(&target).unwrap()
} else {
let target = Target::Channel(channel_id);
if !self.handlers.contains_key(&target) {
let mut handler = Handler::new(target, self.ws.clone(), self.user_id);
handler.join(channel_id);
self.handlers.insert(target, handler);
}
// Actually safe, as the key would have been inserted above.
self.handlers.get_mut(&target).unwrap()
}
}
/// Retrieves the [handler][`Handler`] for the given target and leaves the
/// associated voice channel, if connected.
///
/// This will _not_ drop the handler, and will preserve it and its settings.
///
/// This is a wrapper around [getting][`get`] a handler and calling
/// [`leave`] on it.
///
/// [`Handler`]: struct.Handler.html
/// [`get`]: #method.get
/// [`leave`]: struct.Handler.html#method.leave
pub fn leave<T: Into<Target>>(&mut self, target_id: T) {
let target = target_id.into();
if let Some(handler) = self.handlers.get_mut(&target) {
handler.leave();
}
}
/// Retrieves the [`Handler`] for the given target and leaves the associated
/// voice channel, if connected.
///
/// The handler is then dropped, removing settings for the target.
///
/// [`Handler`]: struct.Handler.html
pub fn remove<T: Into<Target>>(&mut self, target_id: T) {
let target = target_id.into();
self.leave(target);
self.handlers.remove(&target);
}
}