Started to create Mongo models

This commit is contained in:
Victor Mignot 2022-11-08 09:05:49 -05:00
parent 5c0faf05f6
commit 8df494c949
No known key found for this signature in database
GPG key ID: FFE4EF056FB5E0D0
8 changed files with 125 additions and 46 deletions

View file

@ -1,8 +1,7 @@
//! Module containing the Yorokobot client and used structs //! Module containing the Yorokobot client and used structs
use crate::errors::ClientsError; use crate::{database::Client as DatabaseClient, errors::ClientError, DatabaseCredentials};
use mongodb::{options::ClientOptions as MongoClientOptions, Client as MongoClient};
use serenity::{prelude::GatewayIntents, Client as DiscordClient}; use serenity::{prelude::GatewayIntents, Client as DiscordClient};
/// Yorokobot's client. /// Yorokobot's client.
@ -27,15 +26,12 @@ use serenity::{prelude::GatewayIntents, Client as DiscordClient};
/// ///
/// # } /// # }
/// ``` /// ```
pub struct Client { pub struct Client<'a> {
/// The Serenity Discord Client /// The Serenity Discord Client
discord_client: DiscordClient, discord_client: DiscordClient,
/// The MongoDB Client /// The database client
mongodb_client: Option<MongoClient>, database_client: DatabaseClient<'a>,
/// MongoDB Client Options
mongodb_options: MongoClientOptions,
} }
/// Yorokobot connection credentials /// Yorokobot connection credentials
@ -44,12 +40,12 @@ pub struct ClientCredentials<'a> {
pub discord_token: &'a String, pub discord_token: &'a String,
/// MongoDB connection string. /// MongoDB connection string.
pub mongo_uri: &'a String, pub db_credentials: &'a DatabaseCredentials,
} }
impl<'a> Client { impl<'a> Client<'a> {
/// Create a Yorokobot client /// Create a Yorokobot client
pub async fn new(credentials: ClientCredentials<'a>) -> Result<Self, ClientsError> { pub async fn new(credentials: ClientCredentials<'a>) -> Result<Client, ClientError> {
let discord_client = match DiscordClient::builder( let discord_client = match DiscordClient::builder(
credentials.discord_token, credentials.discord_token,
GatewayIntents::empty(), GatewayIntents::empty(),
@ -57,43 +53,29 @@ impl<'a> Client {
.await .await
{ {
Ok(c) => c, Ok(c) => c,
Err(e) => return Err(ClientsError::Discord(e)), Err(e) => return Err(ClientError::Discord(e)),
}; };
let mongodb_options = match MongoClientOptions::parse(credentials.mongo_uri).await { let database_client = DatabaseClient::new(credentials.db_credentials);
Ok(o) => o,
Err(e) => return Err(ClientsError::Database(e)),
};
Ok(Client { Ok(Client {
discord_client, discord_client,
mongodb_options, database_client,
mongodb_client: None,
}) })
} }
/// Start connection to Discord API. /// Start connection to Discord API.
/// Wrap [`serenity::client::Client`] start method. /// Wrap [`serenity::client::Client`] start method.
pub async fn connect_discord(&mut self) -> Result<(), ClientsError> { pub async fn connect_discord(&mut self) -> Result<(), ClientError> {
match self.discord_client.start().await { match self.discord_client.start().await {
Ok(_) => Ok(()), Ok(_) => Ok(()),
Err(e) => Err(ClientsError::Discord(e)), Err(e) => Err(ClientError::Discord(e)),
} }
} }
/// Connect to the Mongo Database
pub fn connect_mongodb(&mut self) -> Result<(), ClientsError> {
self.mongodb_client = match MongoClient::with_options(self.mongodb_options.clone()) {
Ok(c) => Some(c),
Err(e) => return Err(ClientsError::Database(e)),
};
Ok(())
}
/// Connect client to the Mongo database then to the Discord API. /// Connect client to the Mongo database then to the Discord API.
pub async fn connect(&mut self) -> Result<(), ClientsError> { pub async fn connect(&mut self) -> Result<(), ClientError> {
self.connect_mongodb()?; self.database_client.connect().await?;
self.connect_discord().await?; self.connect_discord().await?;
Ok(()) Ok(())

6
src/database.rs Normal file
View file

@ -0,0 +1,6 @@
//! Module for database interaction and wrapping
pub mod client;
mod models;
pub use {client::Client, mongodb::options::ClientOptions as DatabaseCredentials};

44
src/database/client.rs Normal file
View file

@ -0,0 +1,44 @@
use mongodb::Client as MongoClient;
use crate::errors::ClientError;
use crate::DatabaseCredentials;
/// Database client
pub struct Client<'a> {
mongo_client: Option<MongoClient>,
// database: Option<Database>,
credentials: &'a DatabaseCredentials,
}
impl<'a> Client<'a> {
/// Create a new database client
pub fn new(credentials: &'a DatabaseCredentials) -> Client {
return Client {
credentials,
mongo_client: None,
// database: None,
};
}
/// Connect the client
pub async fn connect(&mut self) -> Result<(), ClientError> {
self.mongo_client = match MongoClient::with_options(self.credentials.clone()) {
Ok(c) => Some(c),
Err(e) => return Err(ClientError::Database(e)),
};
if let None = self.mongo_client.as_ref().unwrap().default_database() {
// TODO:
// Implement an Environment Variable catcher to wrap std::env::var()
// As we often call it and always have to use a match control flow
// TODO:
// Complete error kind to be more specific.
// Ex: DatabaseConnection
todo!();
}
Ok(())
}
}

37
src/database/models.rs Normal file
View file

@ -0,0 +1,37 @@
//! Bot data models
#![allow(dead_code)]
use serde::{Deserialize, Serialize};
/// All the models within Mongo COllections
pub enum CollectionModels {
/// Discord Guild
Guild(Guild),
/// Yorokobot tags
Tag(Tag),
}
/// Settings for a server
#[derive(Debug, Serialize, Deserialize)]
pub struct GuildSettings {
admin_only_can_tag: bool,
server_ban_list: Vec<String>,
}
/// Server infos
#[derive(Debug, Serialize, Deserialize)]
pub struct Guild {
discord_guild_id: String,
bot_settings: GuildSettings,
}
/// Tags
#[derive(Debug, Serialize, Deserialize)]
pub struct Tag {
name: String,
guild: String,
is_nsfw: bool,
subscribers: Vec<String>,
}

0
src/env_catcher.rs Normal file
View file

View file

@ -1,14 +1,14 @@
//! Common Yorokobot errors //! Common Yorokobot errors
use mongodb::error::Error as MongoError; pub use mongodb::error::Error as DatabaseError;
use serenity::prelude::SerenityError; pub use serenity::prelude::SerenityError as DiscordError;
/// The kind of errors that can be returned by Client::new /// The kind of errors that can be returned by Client::new
#[derive(Debug)] #[derive(Debug)]
pub enum ClientsError { pub enum ClientError {
/// Serenity error while building client /// Serenity error while building client
Discord(SerenityError), Discord(DiscordError),
///Mongo error while parsing options ///Mongo error while parsing options
Database(MongoError), Database(DatabaseError),
} }

View file

@ -6,6 +6,11 @@
#![deny(missing_docs)] #![deny(missing_docs)]
#![deny(warnings)] #![deny(warnings)]
pub mod client; mod client;
mod database;
pub mod errors; pub mod errors;
pub use crate::{
client::{Client, ClientCredentials},
database::DatabaseCredentials,
};

View file

@ -1,10 +1,7 @@
use log::error; use log::error;
use std::env; use std::env;
use yorokobot::{ use yorokobot::{errors::ClientError, Client, ClientCredentials, DatabaseCredentials};
client::{Client, ClientCredentials},
errors::ClientsError,
};
#[tokio::main] #[tokio::main]
async fn main() -> std::process::ExitCode { async fn main() -> std::process::ExitCode {
@ -27,9 +24,17 @@ async fn main() -> std::process::ExitCode {
} }
}; };
let db_credentials = match DatabaseCredentials::parse(mongodb_uri).await {
Ok(c) => c,
Err(_) => {
error!(target: "bot_warn_errors", "Could not parse database credentials.");
return std::process::ExitCode::FAILURE;
}
};
let credentials = ClientCredentials { let credentials = ClientCredentials {
discord_token: &discord_token, discord_token: &discord_token,
mongo_uri: &mongodb_uri, db_credentials: &db_credentials,
}; };
let mut client = match Client::new(credentials).await { let mut client = match Client::new(credentials).await {
@ -42,10 +47,10 @@ async fn main() -> std::process::ExitCode {
if let Err(error) = client.connect().await { if let Err(error) = client.connect().await {
match error { match error {
ClientsError::Database(e) => { ClientError::Database(e) => {
error!(target: "bot_warn_errors", "Could not connect to database: {:?}", e) error!(target: "bot_warn_errors", "Could not connect to database: {:?}", e)
} }
ClientsError::Discord(e) => { ClientError::Discord(e) => {
error!(target: "bot_warn_errors", "Could not connect to Discord: {:?}", e) error!(target: "bot_warn_errors", "Could not connect to Discord: {:?}", e)
} }
}; };