support adding and removing intros
ci/woodpecker/push/woodpecker Pipeline failed Details

pull/11/head
Patrick Cleavelin 2023-08-06 17:12:26 -05:00
parent 9f426407a9
commit 52d7cc7ded
3 changed files with 128 additions and 19 deletions

View File

@ -2,7 +2,7 @@ use std::path::Path;
use iter_tools::Itertools;
use rusqlite::{Connection, Result};
use tracing::error;
use tracing::{error, warn};
use crate::auth;
@ -136,6 +136,34 @@ impl Database {
)
}
pub(crate) fn get_guild_channels(&self, guild_id: u64) -> Result<Vec<String>> {
let mut query = self.conn.prepare(
"
SELECT
Channel.name
FROM Channel
WHERE
Channel.guild_id = :guild_id
ORDER BY Channel.name DESC
",
)?;
// NOTE(pcleavelin): for some reason this needs to be a let-binding or else
// the compiler complains about it being dropped too early (maybe I should update the compiler version)
let intros = query
.query_map(
&[
// :vomit:
(":guild_id", &guild_id.to_string()),
],
|row| Ok(row.get(0)?),
)?
.into_iter()
.collect::<Result<Vec<String>>>();
intros
}
pub(crate) fn get_user_channel_intros(
&self,
username: &str,
@ -151,6 +179,60 @@ impl Database {
Ok(intros)
}
pub fn insert_user_intro(
&self,
username: &str,
guild_id: u64,
channel_name: &str,
intro_id: i32,
) -> Result<()> {
let affected = self.conn.execute(
"INSERT INTO UserIntro (username, guild_id, channel_name, intro_id) VALUES (?1, ?2, ?3, ?4)",
&[
username,
&guild_id.to_string(),
channel_name,
&intro_id.to_string(),
],
)?;
if affected < 1 {
warn!("no rows affected when attempting to insert user intro");
}
Ok(())
}
pub fn remove_user_intro(
&self,
username: &str,
guild_id: u64,
channel_name: &str,
intro_id: i32,
) -> Result<()> {
let affected = self.conn.execute(
"DELETE FROM
UserIntro
WHERE
username = ?1
AND guild_id = ?2
AND channel_name = ?3
AND intro_id = ?4",
&[
username,
&guild_id.to_string(),
channel_name,
&intro_id.to_string(),
],
)?;
if affected < 1 {
warn!("no rows affected when attempting to delete user intro");
}
Ok(())
}
}
pub struct Guild {

View File

@ -111,6 +111,11 @@ pub(crate) async fn guild_dashboard(
// TODO: change to actual error
Redirect::to("/login")
})?;
let guild_channels = db.get_guild_channels(guild_id).map_err(|err| {
error!(?err, %guild_id, "couldn't get guild channels");
// 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
@ -175,17 +180,27 @@ pub(crate) async fn guild_dashboard(
.builder(Tag::Article, |b| {
let mut b = b.builder_text(Tag::Header, "Guild Intros");
for (channel_name, intros) in user_intros.into_iter() {
let mut user_intros = user_intros.into_iter().peekable();
for guild_channel_name in guild_channels {
// Get user intros for this channel
let intros = user_intros
.peeking_take_while(|(channel_name, _)| {
channel_name == &&guild_channel_name
})
.map(|(_, intros)| intros.map(|intro| &intro.intro))
.flatten();
b = b.builder(Tag::Article, |b| {
b.builder_text(Tag::Header, &channel_name).builder(
b.builder_text(Tag::Header, &guild_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_channel_name,
intros,
guild_intros.iter(),
))
},

View File

@ -342,21 +342,22 @@ pub(crate) async fn v2_add_intro_to_user(
let db = state.db.lock().await;
while let Ok(Some(field)) = form_data.next_field().await {
let Some(field_name) = field.name() else {
let Some(intro_id) = field.name() else {
continue;
};
// TODO: insert into database
//if !channel_user
// .intros
// .iter()
// .any(|intro| intro.index == field_name)
//{
// channel_user.intros.push(IntroIndex {
// index: field_name.to_string(),
// volume: 20,
// });
//}
let intro_id = intro_id.parse::<i32>().map_err(|err| {
error!(?err, "invalid intro id");
// TODO: change to actual error
Redirect::to("/login")
})?;
db.insert_user_intro(&user.name, guild_id, &channel, intro_id)
.map_err(|err| {
error!(?err, "failed to add user intro");
// TODO: change to actual error
Redirect::to("/login")
})?;
}
let guild_intros = db.get_guild_intros(guild_id).map_err(|err| {
@ -394,11 +395,22 @@ pub(crate) async fn v2_remove_intro_from_user(
let db = state.db.lock().await;
while let Ok(Some(field)) = form_data.next_field().await {
let Some(field_name) = field.name() else {
let Some(intro_id) = field.name() else {
continue;
};
// TODO: remove from database
let intro_id = intro_id.parse::<i32>().map_err(|err| {
error!(?err, "invalid intro id");
// TODO: change to actual error
Redirect::to("/login")
})?;
db.remove_user_intro(&user.name, guild_id, &channel, intro_id)
.map_err(|err| {
error!(?err, "failed to remove user intro");
// TODO: change to actual error
Redirect::to("/login")
})?;
}
let guild_intros = db.get_guild_intros(guild_id).map_err(|err| {