1use super::config;
2use super::irc_msgs::OwningMsgPrefix;
3use super::BotCommand;
4use super::ErrorKind;
5use super::MsgPrefix;
6use super::Result;
7use super::Server;
8use super::ServerId;
9use super::State;
10use rand::StdRng;
11use std::borrow::Cow;
12use std::path::Path;
13use std::sync::MutexGuard;
14use std::sync::RwLockReadGuard;
15
16impl State {
17 pub fn nick(&self, server_id: ServerId) -> Result<String> {
18 self.read_msg_prefix(server_id)?
19 .parse()
20 .nick
21 .ok_or(ErrorKind::NicknameUnknown.into())
22 .map(ToOwned::to_owned)
23 }
24
25 pub fn module_data_path(&self) -> Result<&Path> {
26 Ok(self.module_data_path.as_ref())
27 }
28
29 pub fn command(&self, name: &str) -> Result<Option<&BotCommand>> {
30 Ok(self.commands.get(name))
31 }
32
33 pub fn command_names(&self) -> Result<Vec<Cow<'static, str>>> {
34 Ok(self.commands.keys().cloned().collect())
35 }
36
37 pub fn have_admin(
38 &self,
39 MsgPrefix {
40 nick: nick_1,
41 user: user_1,
42 host: host_1,
43 }: MsgPrefix,
44 ) -> Result<bool> {
45 Ok(self.config.admins.iter().any(
46 |&config::Admin {
47 nick: ref nick_2,
48 user: ref user_2,
49 host: ref host_2,
50 }| {
51 check_admin_cred(nick_1, nick_2) && check_admin_cred(user_1, user_2)
52 && check_admin_cred(host_1, host_2)
53 },
54 ))
55 }
56
57 pub(super) fn read_msg_prefix(
59 &self,
60 _server_id: ServerId,
61 ) -> Result<RwLockReadGuard<OwningMsgPrefix>> {
62 self.msg_prefix
63 .read()
64 .map_err(|_| ErrorKind::LockPoisoned("stored message prefix".into()).into())
65 }
66
67 pub(super) fn read_server(
68 &self,
69 server_id: ServerId,
70 ) -> Result<Option<RwLockReadGuard<Server>>> {
71 match self.servers.get(&server_id) {
72 Some(lock) => match lock.read() {
73 Ok(guard) => Ok(Some(guard)),
74 Err(_) => Err(ErrorKind::LockPoisoned(
75 format!("server {}", server_id.uuid.hyphenated()).into(),
76 ).into()),
77 },
78 None => Ok(None),
79 }
80 }
81
82 pub fn rng(&self) -> Result<MutexGuard<StdRng>> {
85 self.rng.lock().map_err(|_| {
86 ErrorKind::LockPoisoned("the central random number generator".into()).into()
87 })
88 }
89
90 pub(super) fn server_socket_addr_dbg_string(&self, server_id: ServerId) -> String {
94 let uuid = server_id.uuid.hyphenated();
95
96 match self.read_server(server_id) {
97 Ok(Some(s)) => s.socket_addr_string.clone(),
98 Ok(None) => format!("<unknown server {} (not found)>", uuid),
99 Err(e) => format!("<unknown server {} ({})>", uuid, e),
100 }
101 }
102}
103
104fn check_admin_cred(candidate: Option<&str>, control: &Option<String>) -> bool {
108 match (candidate, control) {
109 (Some(cdt), &Some(ref ctl)) => {
110 cdt == ctl
112 }
113 (_, &None) => {
114 true
116 }
117 (None, &Some(_)) => {
118 false
120 }
121 }
122}