Skip to content

Commit e3b0bf4

Browse files
committed
Introduce admin mode
1 parent f38e445 commit e3b0bf4

7 files changed

Lines changed: 68 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
## 0.10.0 (unreleased)
55

6+
- Introduced admin mode. Can be entered in multi-user mode using tags which can
7+
be configured in the new `admin` section.
8+
69
- Renamed configuration section `user` to `single_user` for clarity.
710

811
- Renamed configuration property `id` in section `single_user` to `user_id` for

config_example.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ button4 = "mystery-zone"
4343
"willkommen-in-der-mystery-zone",
4444
]
4545

46+
#[admin]
47+
#tags = [
48+
# "0123456789",
49+
#]
50+
4651
# Uncomment and provide user ID to enable single-user mode.
4752
#[single_user]
4853
#user_id = "00000000-0000-0000-0000-000000000000"

src/audio.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ fn load_source(path: &Path) -> Result<Decoder<BufReader<File>>> {
7070
}
7171

7272
pub(crate) enum Sound {
73+
AdminModeEntered,
74+
AdminModeLeft,
7375
SignOnSuccessful,
7476
SignOnFailed,
7577
SignOffSuccessful,
@@ -84,6 +86,8 @@ pub(crate) enum Sound {
8486
impl Sound {
8587
pub fn get_name(&self) -> String {
8688
match self {
89+
Sound::AdminModeEntered => "admin_mode_entered".to_owned(),
90+
Sound::AdminModeLeft => "admin_mode_left".to_owned(),
8791
Sound::SignOnSuccessful => "sign_on_successful".to_owned(),
8892
Sound::SignOnFailed => "sign_on_failed".to_owned(),
8993
Sound::SignOffSuccessful => "sign_off_successful".to_owned(),

src/client.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* License: MIT
44
*/
55

6+
use std::collections::HashSet;
67
use std::path::PathBuf;
78

89
use anyhow::Result;
@@ -26,6 +27,7 @@ pub(crate) struct Client {
2627
audio_player: AudioPlayer,
2728
random: Random,
2829
user_mode: UserMode,
30+
admin_tags: HashSet<Tag>,
2931
api_client: ApiClient,
3032
party_config: PartyConfig,
3133
event_receiver: EventReceiver,
@@ -35,6 +37,7 @@ impl Client {
3537
pub(crate) fn new(
3638
sounds_path: PathBuf,
3739
user_mode: UserMode,
40+
admin_tags: HashSet<Tag>,
3841
api_config: &ApiConfig,
3942
party_config: PartyConfig,
4043
event_receiver: EventReceiver,
@@ -43,6 +46,7 @@ impl Client {
4346
audio_player: AudioPlayer::new(sounds_path)?,
4447
random: Random::new(),
4548
user_mode,
49+
admin_tags,
4650
api_client: ApiClient::new(api_config, party_config.party_id.clone()),
4751
party_config,
4852
event_receiver,
@@ -119,9 +123,8 @@ impl Client {
119123
Event::ButtonPressed { button } => {
120124
log::debug!("Button pressed: {:?}", button);
121125

122-
// Submit if user has identified; ignore if no user has
123-
// been specified.
124126
match current_user {
127+
CurrentUser::Admin => self.handle_button_press_by_admin(button)?,
125128
CurrentUser::User(user_id) => {
126129
self.handle_button_press_with_identified_user(user_id, button)?
127130
}
@@ -166,6 +169,12 @@ impl Client {
166169
}
167170

168171
fn handle_tag_read(&self, tag: &Tag) -> Result<EventHandlingResult> {
172+
if self.admin_tags.contains(tag) {
173+
self.play_sound(Sound::AdminModeEntered);
174+
log::info!("Entering admin mode.");
175+
return Ok(EventHandlingResult::SetCurrentUser(CurrentUser::Admin));
176+
}
177+
169178
log::debug!("Requesting details for tag {} ...", tag.value);
170179
match self.api_client.get_tag_details(tag) {
171180
Ok(details) => match details {
@@ -204,6 +213,21 @@ impl Client {
204213
}
205214
}
206215

216+
fn handle_button_press_by_admin(&self, button: Button) -> Result<EventHandlingResult> {
217+
Ok(match button {
218+
Button::Button1 => {
219+
// Leave admin mode.
220+
log::info!("Leaving admin mode.");
221+
self.play_sound(Sound::AdminModeLeft);
222+
EventHandlingResult::ResetCurrentUser
223+
}
224+
_ => {
225+
// Stay in admin mode.
226+
EventHandlingResult::KeepCurrentUser
227+
}
228+
})
229+
}
230+
207231
fn handle_button_press_with_identified_user(
208232
&self,
209233
user_id: &UserId,

src/config.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* License: MIT
44
*/
55

6-
use std::collections::HashMap;
6+
use std::collections::{HashMap, HashSet};
77
use std::fs::read_to_string;
88
use std::path::{Path, PathBuf};
99

@@ -13,7 +13,7 @@ use serde::Deserialize;
1313
use crate::buttons::Button;
1414
use crate::devices::DeviceName;
1515
use crate::keycodenames::KeyName;
16-
use crate::model::{PartyId, UserId, UserMode};
16+
use crate::model::{PartyId, Tag, UserId, UserMode};
1717

1818
#[derive(Deserialize)]
1919
pub(crate) struct Config {
@@ -26,10 +26,21 @@ pub(crate) struct Config {
2626
pub sounds_path: PathBuf,
2727
pub api: ApiConfig,
2828
pub party: PartyConfig,
29+
pub admin: Option<AdminConfig>,
2930
pub single_user: Option<SingleUserConfig>,
3031
}
3132

3233
impl Config {
34+
pub fn get_admin_tags(&self) -> HashSet<Tag> {
35+
self.admin
36+
.as_ref()
37+
.and_then(|admin_config| admin_config.tags.clone())
38+
.unwrap_or_default()
39+
.into_iter()
40+
.map(|s| Tag { value: s })
41+
.collect()
42+
}
43+
3344
pub fn get_user_mode(&self) -> UserMode {
3445
self.single_user
3546
.as_ref()
@@ -54,6 +65,11 @@ pub(crate) struct PartyConfig {
5465
pub whereabouts_sounds: HashMap<String, Vec<String>>,
5566
}
5667

68+
#[derive(Deserialize)]
69+
pub(crate) struct AdminConfig {
70+
pub tags: Option<HashSet<String>>,
71+
}
72+
5773
#[derive(Deserialize)]
5874
pub(crate) struct SingleUserConfig {
5975
pub user_id: Option<UserId>,

src/main.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ fn main() -> Result<()> {
5757
fn run(config_filename: PathBuf) -> Result<()> {
5858
let config = config::load_config(&config_filename)?;
5959

60+
let admin_tags = config.get_admin_tags();
61+
6062
let user_mode = config.get_user_mode();
6163
match user_mode {
6264
UserMode::SingleUser(ref id) => {
@@ -86,7 +88,14 @@ fn run(config_filename: PathBuf) -> Result<()> {
8688
tx3,
8789
)?;
8890

89-
let client = Client::new(sounds_path, user_mode, &config.api, config.party, rx)?;
91+
let client = Client::new(
92+
sounds_path,
93+
user_mode,
94+
admin_tags,
95+
&config.api,
96+
config.party,
97+
rx,
98+
)?;
9099
client.run()
91100
}
92101

src/model.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* License: MIT
44
*/
55

6+
#[derive(Eq, Hash, PartialEq)]
67
pub(crate) struct Tag {
78
pub value: String,
89
}
@@ -19,5 +20,6 @@ pub(crate) enum UserMode {
1920
#[derive(Clone)]
2021
pub(crate) enum CurrentUser {
2122
None,
23+
Admin,
2224
User(UserId),
2325
}

0 commit comments

Comments
 (0)