rewrite to use sane ids in model

This commit is contained in:
nora 2022-06-16 19:10:36 +02:00
parent dda41f0006
commit 1f6021b555
3 changed files with 118 additions and 38 deletions

View file

@ -197,11 +197,11 @@ async fn lawsuit_command_handler(
UserOption::get_optional(options.get(5)).wrap_err("accused_layer")?; UserOption::get_optional(options.get(5)).wrap_err("accused_layer")?;
let mut lawsuit = Lawsuit { let mut lawsuit = Lawsuit {
plaintiff: plaintiff.0.id.to_string(), plaintiff: plaintiff.id.into(),
accused: accused.0.id.to_string(), accused: accused.id.into(),
judge: judge.0.id.to_string(), judge: judge.id.into(),
plaintiff_layer: plaintiff_layer.map(|l| l.0.id.to_string()), plaintiff_layer: plaintiff_layer.map(|user| user.id.into()),
accused_layer: accused_layer.map(|l| l.0.id.to_string()), accused_layer: accused_layer.map(|user| user.id.into()),
reason: reason.to_owned(), reason: reason.to_owned(),
state: LawsuitState::Initial, state: LawsuitState::Initial,
court_room: None, court_room: None,
@ -228,7 +228,7 @@ async fn lawsuit_command_handler(
Some(category) => { Some(category) => {
let id = category.id; let id = category.id;
mongo_client mongo_client
.set_court_category(&guild_id.to_string(), &id.to_string()) .set_court_category(guild_id.into(), id.into())
.await?; .await?;
} }
None => return Ok(Response::Simple("Das ist keine Kategorie!".to_owned())), None => return Ok(Response::Simple("Das ist keine Kategorie!".to_owned())),
@ -277,13 +277,13 @@ struct UserOption;
#[nougat::gat] #[nougat::gat]
impl GetOption for UserOption { impl GetOption for UserOption {
type Get<'a> = (&'a User, &'a Option<PartialMember>); type Get<'a> = &'a User;
fn extract( fn extract(
command: &ApplicationCommandInteractionDataOptionValue, command: &ApplicationCommandInteractionDataOptionValue,
) -> crate::Result<Self::Get<'_>> { ) -> crate::Result<Self::Get<'_>> {
if let ApplicationCommandInteractionDataOptionValue::User(user, member) = command { if let ApplicationCommandInteractionDataOptionValue::User(user, _) = command {
Ok((user, member)) Ok(user)
} else { } else {
Err(eyre!("Expected user!")) Err(eyre!("Expected user!"))
} }

View file

@ -1,14 +1,16 @@
use std::str::FromStr;
use color_eyre::Result; use color_eyre::Result;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serenity::{ use serenity::{
http::Http, http::Http,
model::{channel::PermissionOverwriteType, id::ChannelId, prelude::*, Permissions}, model::{channel::PermissionOverwriteType, prelude::*, Permissions},
}; };
use tracing::info; use tracing::info;
use crate::{handler::Response, model::CourtRoom, Mongo, WrapErr}; use crate::{
handler::Response,
model::{CourtRoom, SnowflakeId},
Mongo, WrapErr,
};
#[derive(Debug, Clone, Copy, Serialize, Deserialize)] #[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum LawsuitState { pub enum LawsuitState {
@ -19,14 +21,14 @@ pub enum LawsuitState {
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Lawsuit { pub struct Lawsuit {
pub plaintiff: String, pub plaintiff: SnowflakeId,
pub accused: String, pub accused: SnowflakeId,
pub plaintiff_layer: Option<String>, pub plaintiff_layer: Option<SnowflakeId>,
pub accused_layer: Option<String>, pub accused_layer: Option<SnowflakeId>,
pub judge: String, pub judge: SnowflakeId,
pub reason: String, pub reason: String,
pub state: LawsuitState, pub state: LawsuitState,
pub court_room: Option<String>, pub court_room: Option<SnowflakeId>,
} }
impl Lawsuit { impl Lawsuit {
@ -37,7 +39,7 @@ impl Lawsuit {
mongo_client: &Mongo, mongo_client: &Mongo,
) -> Result<Response> { ) -> Result<Response> {
let state = mongo_client let state = mongo_client
.find_or_insert_state(&guild_id.to_string()) .find_or_insert_state(guild_id.into())
.await?; .await?;
let free_room = state let free_room = state
@ -55,7 +57,7 @@ impl Lawsuit {
http, http,
guild_id, guild_id,
state.court_rooms.len(), state.court_rooms.len(),
ChannelId::from_str(category).wrap_err("invalid channel_id stored")?, *category,
mongo_client, mongo_client,
) )
.await .await
@ -83,8 +85,6 @@ impl Lawsuit {
return Ok(response); return Ok(response);
} }
// TODO: now give the people their roles
Ok(Response::Simple(format!( Ok(Response::Simple(format!(
"ha eine ufgmacht im channel <#{}>", "ha eine ufgmacht im channel <#{}>",
room.channel_id room.channel_id
@ -104,7 +104,7 @@ impl Lawsuit {
.channels(http) .channels(http)
.await .await
.wrap_err("fetch channels")?; .wrap_err("fetch channels")?;
let channel = channels.get(&ChannelId::from_str(&room.channel_id).expect("oh god")); let channel = channels.get(&room.channel_id.into());
match channel { match channel {
Some(channel) => { Some(channel) => {
@ -155,7 +155,7 @@ async fn create_room(
http: &Http, http: &Http,
guild_id: GuildId, guild_id: GuildId,
room_len: usize, room_len: usize,
category_id: ChannelId, category_id: SnowflakeId,
mongo_client: &Mongo, mongo_client: &Mongo,
) -> Result<Result<CourtRoom, Response>> { ) -> Result<Result<CourtRoom, Response>> {
let room_number = room_len + 1; let room_number = room_len + 1;
@ -184,7 +184,7 @@ async fn create_room(
let channel_id = match channels.values().find(|c| c.name() == room_name) { let channel_id = match channels.values().find(|c| c.name() == room_name) {
Some(channel) => { Some(channel) => {
if channel.parent_id != Some(category_id) { if channel.parent_id != Some(category_id.into()) {
return Ok(Err(Response::Simple(format!( return Ok(Err(Response::Simple(format!(
"de channel {room_name} isch i de falsche kategorie, man eh" "de channel {room_name} isch i de falsche kategorie, man eh"
)))); ))));
@ -210,13 +210,13 @@ async fn create_room(
}; };
let room = CourtRoom { let room = CourtRoom {
channel_id: channel_id.to_string(), channel_id: channel_id.into(),
ongoing_lawsuit: false, ongoing_lawsuit: false,
role_id: role_id.to_string(), role_id: role_id.into(),
}; };
mongo_client mongo_client
.add_court_room(&guild_id.to_string(), &room) .add_court_room(guild_id.into(), &room)
.await .await
.wrap_err("add court room to database")?; .wrap_err("add court room to database")?;

View file

@ -1,28 +1,104 @@
use std::{
fmt::{Display, Formatter},
num::ParseIntError,
str::FromStr,
};
use color_eyre::Result; use color_eyre::Result;
use mongodb::{ use mongodb::{
bson, bson,
bson::doc, bson::{doc, Bson},
options::{ClientOptions, Credential}, options::{ClientOptions, Credential},
Client, Collection, Database, Client, Collection, Database,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serenity::model::id::{ChannelId, GuildId, RoleId, UserId};
use tracing::info; use tracing::info;
use crate::{lawsuit::Lawsuit, WrapErr}; use crate::{lawsuit::Lawsuit, WrapErr};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct SnowflakeId(#[serde(with = "serde_string")] pub u64);
impl FromStr for SnowflakeId {
type Err = ParseIntError;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
s.parse().map(Self)
}
}
impl Display for SnowflakeId {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Display::fmt(&self.0, f)
}
}
mod serde_string {
use std::{fmt::Display, str::FromStr};
use serde::{de, Deserialize, Deserializer, Serializer};
pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
where
T: Display,
S: Serializer,
{
serializer.collect_str(value)
}
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
T: FromStr,
T::Err: Display,
D: Deserializer<'de>,
{
String::deserialize(deserializer)?
.parse()
.map_err(de::Error::custom)
}
}
impl From<SnowflakeId> for Bson {
fn from(id: SnowflakeId) -> Self {
Bson::String(id.to_string())
}
}
macro_rules! from_snowflake {
($($ty:ty),*) => {
$(
impl From<SnowflakeId> for $ty {
fn from(id: SnowflakeId) -> Self {
Self(id.0)
}
}
impl From<$ty> for SnowflakeId {
fn from(id: $ty) -> Self {
Self(id.0)
}
}
)*
};
}
from_snowflake!(GuildId, RoleId, ChannelId, UserId);
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct State { pub struct State {
pub guild_id: String, pub guild_id: SnowflakeId,
pub lawsuits: Vec<Lawsuit>, pub lawsuits: Vec<Lawsuit>,
pub court_category: Option<String>, pub court_category: Option<SnowflakeId>,
pub court_rooms: Vec<CourtRoom>, pub court_rooms: Vec<CourtRoom>,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CourtRoom { pub struct CourtRoom {
pub channel_id: String, pub channel_id: SnowflakeId,
pub ongoing_lawsuit: bool, pub ongoing_lawsuit: bool,
pub role_id: String, pub role_id: SnowflakeId,
} }
pub struct Mongo { pub struct Mongo {
@ -53,7 +129,7 @@ impl Mongo {
Ok(Self { db }) Ok(Self { db })
} }
pub async fn find_or_insert_state(&self, guild_id: &str) -> Result<State> { pub async fn find_or_insert_state(&self, guild_id: SnowflakeId) -> Result<State> {
let coll = self.state_coll(); let coll = self.state_coll();
let state = coll let state = coll
.find_one(doc! {"guild_id": &guild_id }, None) .find_one(doc! {"guild_id": &guild_id }, None)
@ -71,7 +147,7 @@ impl Mongo {
Ok(state) Ok(state)
} }
pub async fn new_state(&self, guild_id: String) -> Result<State> { pub async fn new_state(&self, guild_id: SnowflakeId) -> Result<State> {
let state = State { let state = State {
guild_id, guild_id,
lawsuits: vec![], lawsuits: vec![],
@ -86,7 +162,11 @@ impl Mongo {
Ok(state) Ok(state)
} }
pub async fn set_court_category(&self, guild_id: &str, category: &str) -> Result<()> { pub async fn set_court_category(
&self,
guild_id: SnowflakeId,
category: SnowflakeId,
) -> Result<()> {
let _ = self.find_or_insert_state(guild_id).await?; let _ = self.find_or_insert_state(guild_id).await?;
let coll = self.state_coll(); let coll = self.state_coll();
coll.update_one( coll.update_one(
@ -99,7 +179,7 @@ impl Mongo {
Ok(()) Ok(())
} }
pub async fn add_court_room(&self, guild_id: &str, room: &CourtRoom) -> Result<()> { pub async fn add_court_room(&self, guild_id: SnowflakeId, room: &CourtRoom) -> Result<()> {
let _ = self.find_or_insert_state(guild_id).await?; let _ = self.find_or_insert_state(guild_id).await?;
let coll = self.state_coll(); let coll = self.state_coll();
coll.update_one( coll.update_one(