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
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};
/// 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
discord_client: DiscordClient,
/// The MongoDB Client
mongodb_client: Option<MongoClient>,
/// MongoDB Client Options
mongodb_options: MongoClientOptions,
/// The database client
database_client: DatabaseClient<'a>,
}
/// Yorokobot connection credentials
@ -44,12 +40,12 @@ pub struct ClientCredentials<'a> {
pub discord_token: &'a 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
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(
credentials.discord_token,
GatewayIntents::empty(),
@ -57,43 +53,29 @@ impl<'a> Client {
.await
{
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 {
Ok(o) => o,
Err(e) => return Err(ClientsError::Database(e)),
};
let database_client = DatabaseClient::new(credentials.db_credentials);
Ok(Client {
discord_client,
mongodb_options,
mongodb_client: None,
database_client,
})
}
/// Start connection to Discord API.
/// 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 {
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.
pub async fn connect(&mut self) -> Result<(), ClientsError> {
self.connect_mongodb()?;
pub async fn connect(&mut self) -> Result<(), ClientError> {
self.database_client.connect().await?;
self.connect_discord().await?;
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
use mongodb::error::Error as MongoError;
use serenity::prelude::SerenityError;
pub use mongodb::error::Error as DatabaseError;
pub use serenity::prelude::SerenityError as DiscordError;
/// The kind of errors that can be returned by Client::new
#[derive(Debug)]
pub enum ClientsError {
pub enum ClientError {
/// Serenity error while building client
Discord(SerenityError),
Discord(DiscordError),
///Mongo error while parsing options
Database(MongoError),
Database(DatabaseError),
}

View file

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

View file

@ -1,10 +1,7 @@
use log::error;
use std::env;
use yorokobot::{
client::{Client, ClientCredentials},
errors::ClientsError,
};
use yorokobot::{errors::ClientError, Client, ClientCredentials, DatabaseCredentials};
#[tokio::main]
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 {
discord_token: &discord_token,
mongo_uri: &mongodb_uri,
db_credentials: &db_credentials,
};
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 {
match error {
ClientsError::Database(e) => {
ClientError::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)
}
};