Skip to content

Commit

Permalink
Refactor codebase and add helper functions (#6)
Browse files Browse the repository at this point in the history
This PR:
- Updates various variable names
- Updates file names
- Adds helper functions
- Adds user mentions to slash command replies
  • Loading branch information
brage-andreas authored Mar 22, 2024
1 parent 94362b9 commit 9d25987
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 44 deletions.
File renamed without changes.
File renamed without changes.
63 changes: 25 additions & 38 deletions src/roulette.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
use lazy_static::lazy_static;
use rand::Rng;
use rand::seq::SliceRandom;
use serde::{de::DeserializeOwned, Deserialize};

enum JsonFile {
Pizza,
Roulette,
}

pub enum SpinMode {
pub enum RouletteFilter {
All,
Vegan,
Vegetarian,
Any,
}

trait Deserializable: DeserializeOwned {}

#[derive(Debug, Clone, Deserialize)]
pub struct PizzaDetail {
pub struct PizzaEntry {
pub name: String,
pub extra: String,
pub description: String,
Expand All @@ -25,44 +18,38 @@ pub struct PizzaDetail {
}

#[derive(Debug, Clone, Deserialize)]
pub struct RouletteMessage {
phrase: String,
pub struct FortunePhraseEntry {
pub phrase: String,
}

impl Deserializable for PizzaDetail {}
impl Deserializable for RouletteMessage {}

lazy_static! {
static ref PIZZA_OPTIONS: Vec<PizzaDetail> = load_from_json(JsonFile::Pizza);
static ref ROULETTE_MESSAGES: Vec<RouletteMessage> = load_from_json(JsonFile::Roulette);
static ref PIZZAS: Vec<PizzaEntry> = load_json(include_str!("../config/pizzas.json"));
static ref FORTUNE_PHRASES: Vec<FortunePhraseEntry> =
load_json(include_str!("../config/fortune_phrases.json"));
}

fn load_from_json<T: Deserializable>(file: JsonFile) -> Vec<T> {
let json = match file {
JsonFile::Pizza => include_str!("../config/pizza.json"),
JsonFile::Roulette => include_str!("../config/roulette.json"),
};
let result: Vec<T> = serde_json::from_str(json).expect("Failed to parse JSON configuration");
result
fn load_json<T: DeserializeOwned>(include_str: &str) -> Vec<T> {
serde_json::from_str(include_str).expect("Failed to parse JSON configuration")
}

pub fn get_random_pizza(mode: SpinMode) -> PizzaDetail {
fn get_random_element<T>(source: &[T]) -> Option<&T> {
let mut rng = rand::thread_rng();
let mut filtered_pizzas: Vec<&PizzaDetail> = PIZZA_OPTIONS
source.choose(&mut rng)
}

pub fn get_random_pizza(filter: RouletteFilter) -> &'static PizzaEntry {
let filtered_pizzas: Vec<&PizzaEntry> = PIZZAS
.iter()
.filter(|p| match mode {
SpinMode::Vegan => p.vegan,
SpinMode::Vegetarian => p.vegetarian,
SpinMode::Any => true,
.filter(|pizza_entry| match filter {
RouletteFilter::All => true,
RouletteFilter::Vegan => pizza_entry.vegan,
RouletteFilter::Vegetarian => pizza_entry.vegetarian,
})
.collect();
let random_index = rng.gen_range(0..filtered_pizzas.len());
filtered_pizzas.remove(random_index).clone()

get_random_element(&filtered_pizzas).expect("PizzaEntry vector is empty")
}

pub fn get_random_roulette_message() -> String {
let mut rng = rand::thread_rng();
let phrases = ROULETTE_MESSAGES.to_vec();
let random_index = rng.gen_range(0..phrases.len());
phrases.get(random_index).unwrap().phrase.clone()
pub fn get_random_fortune_phrase() -> &'static FortunePhraseEntry {
get_random_element(&FORTUNE_PHRASES).expect("FortunePhrases vector is empty")
}
12 changes: 6 additions & 6 deletions src/slack.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::roulette::{get_random_pizza, get_random_roulette_message, SpinMode};
use crate::roulette::{get_random_fortune_phrase, get_random_pizza, RouletteFilter};
use crate::slack_message::incoming;
use crate::slack_message::outgoing;
use reqwest::header::{HeaderMap, HeaderValue};
Expand Down Expand Up @@ -152,9 +152,9 @@ async fn handle_slash_command(
message: incoming::Incoming<incoming::SlashCommandIncomingMessage>,
) -> outgoing::SlackOutgoingMessage {
let spin_mode = match message.payload.command.as_str() {
"/spin" => SpinMode::Any,
"/spin-vegan" => SpinMode::Vegan,
"/spin-vegetarian" => SpinMode::Vegetarian,
"/spin" => RouletteFilter::All,
"/spin-vegan" => RouletteFilter::Vegan,
"/spin-vegetarian" => RouletteFilter::Vegetarian,
_ => {
tracing::warn!("Received unknown command: {}", message.payload.command);
return outgoing::SlackOutgoingMessage::Empty(outgoing::Outgoing::new(
Expand All @@ -166,7 +166,7 @@ async fn handle_slash_command(

let pizza = get_random_pizza(spin_mode);
let mention = mention_user(message.payload.user_id);
let roulette_message = get_random_roulette_message();
let fortune_phrase = get_random_fortune_phrase();

let outgoing_message = outgoing::SlashCommandOutgoingMessage {
response_type: "in_channel".to_string(),
Expand All @@ -175,7 +175,7 @@ async fn handle_slash_command(
r#type: "section".to_string(),
text: outgoing::SlackCommandBlockText {
r#type: "mrkdwn".to_string(),
text: format!("{} {} *{}* 🎉", mention, roulette_message, pizza.name),
text: format!("{} {} *{}* 🎉", mention, fortune_phrase.phrase, pizza.name),
},
},
outgoing::SlackCommandBlock {
Expand Down

0 comments on commit 9d25987

Please sign in to comment.