diff --git a/src/db.rs b/src/db.rs index b7d225b..dbf7fd2 100644 --- a/src/db.rs +++ b/src/db.rs @@ -1,6 +1,8 @@ use std::path::Path; +use iter_tools::Itertools; use rusqlite::{Connection, Result}; +use tracing::error; use crate::auth; @@ -133,6 +135,22 @@ impl Database { |row| Ok(auth::Permissions(row.get(0)?)), ) } + + pub(crate) fn get_user_channel_intros( + &self, + username: &str, + guild_id: u64, + channel_name: &str, + ) -> Result> { + let all_user_intros = self.get_all_user_intros(guild_id)?.into_iter(); + + let intros = all_user_intros + .filter(|intro| &intro.username == &username && &intro.channel_name == channel_name) + .map(|intro| intro.intro) + .collect(); + + Ok(intros) + } } pub struct Guild { diff --git a/src/page.rs b/src/page.rs index c919083..4943bc2 100644 --- a/src/page.rs +++ b/src/page.rs @@ -120,10 +120,10 @@ pub(crate) async fn guild_dashboard( .get_user_permissions(&user.name, guild_id) .unwrap_or_default(); - let grouped_intros = all_user_intros.iter().group_by(|intro| &intro.username); - let user_intros = grouped_intros - .into_iter() - .filter(|(username, _)| username == &&user.name); + let user_intros = all_user_intros + .iter() + .filter(|intro| &intro.username == &user.name) + .group_by(|intro| &intro.channel_name); let can_upload = user_permissions.can(auth::Permission::UploadSounds); let is_moderator = user_permissions.can(auth::Permission::DeleteSounds); @@ -175,26 +175,22 @@ pub(crate) async fn guild_dashboard( .builder(Tag::Article, |b| { let mut b = b.builder_text(Tag::Header, "Guild Intros"); - for (_, intros) in user_intros { - for (channel_name, intros) in - intros.group_by(|intro| &intro.channel_name).into_iter() - { - b = b.builder(Tag::Article, |b| { - b.builder_text(Tag::Header, &channel_name).builder( - Tag::Div, - |b| { - b.attribute("id", "channel-intro-selector") - .push_builder(channel_intro_selector( - &state.origin, - guild_id, - channel_name, - intros.map(|intro| &intro.intro), - guild_intros.iter(), - )) - }, - ) - }); - } + for (channel_name, intros) in user_intros.into_iter() { + b = b.builder(Tag::Article, |b| { + b.builder_text(Tag::Header, &channel_name).builder( + Tag::Div, + |b| { + b.attribute("id", "channel-intro-selector") + .push_builder(channel_intro_selector( + &state.origin, + guild_id, + channel_name, + intros.map(|intro| &intro.intro), + guild_intros.iter(), + )) + }, + ) + }); } b diff --git a/src/routes.rs b/src/routes.rs index 59ec973..f843648 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -364,42 +364,21 @@ pub(crate) async fn v2_add_intro_to_user( // TODO: change to actual error Redirect::to("/login") })?; - let all_user_intros = db.get_all_user_intros(guild_id).map_err(|err| { - error!(?err, %guild_id, "couldn't get user intros"); - // TODO: change to actual error - Redirect::to("/login") - })?; - let grouped_intros = all_user_intros.iter().group_by(|intro| &intro.username); - let user_intros = grouped_intros - .into_iter() - .filter_map(|(username, intro)| { - if username == &user.name { - Some(intro) - } else { - None - } - }) - .flatten(); - - let grouped_user_intros = user_intros.group_by(|intro| &intro.channel_name); - let intros = grouped_user_intros - .into_iter() - .filter_map(|(channel_name, intros)| { - if channel_name == &channel { - Some(intros.map(|intro| &intro.intro)) - } else { - None - } - }) - .flatten(); + let intros = db + .get_user_channel_intros(&user.name, guild_id, &channel) + .map_err(|err| { + error!(?err, user = %user.name, %guild_id, "couldn't get user intros"); + // TODO: change to actual error + Redirect::to("/login") + })?; Ok(Html( page::channel_intro_selector( &state.origin, guild_id, &channel, - intros, + intros.iter(), guild_intros.iter(), ) .build(), @@ -411,42 +390,41 @@ pub(crate) async fn v2_remove_intro_from_user( Path((guild_id, channel)): Path<(u64, String)>, user: User, mut form_data: Multipart, -) -> HeaderMap { - let mut headers = HeaderMap::new(); - headers.insert("HX-Refresh", HeaderValue::from_static("true")); - - let mut settings = state.settings.lock().await; - - let Some(guild) = settings.guilds.get_mut(&guild_id) else { - return headers; - }; - let Some(channel) = guild.channels.get_mut(&channel) else { - return headers; - }; - let Some(channel_user) = channel.users.get_mut(&user.name) else { - return headers; - }; +) -> Result, Redirect> { + let db = state.db.lock().await; while let Ok(Some(field)) = form_data.next_field().await { let Some(field_name) = field.name() else { continue; }; - if let Some(index) = channel_user - .intros - .iter() - .position(|intro| intro.index == field_name) - { - channel_user.intros.remove(index); - } + // TODO: remove from database } - // TODO: don't save on every change - if let Err(err) = settings.save() { - error!("Failed to save config: {err:?}"); - } + let guild_intros = db.get_guild_intros(guild_id).map_err(|err| { + error!(?err, %guild_id, "couldn't get guild intros"); + // TODO: change to actual error + Redirect::to("/login") + })?; - headers + let intros = db + .get_user_channel_intros(&user.name, guild_id, &channel) + .map_err(|err| { + error!(?err, user = %user.name, %guild_id, "couldn't get user intros"); + // TODO: change to actual error + Redirect::to("/login") + })?; + + Ok(Html( + page::channel_intro_selector( + &state.origin, + guild_id, + &channel, + intros.iter(), + guild_intros.iter(), + ) + .build(), + )) } pub(crate) async fn add_intro_to_user(