Skip to content
This repository has been archived by the owner on Sep 1, 2023. It is now read-only.

Commit

Permalink
Initial API version
Browse files Browse the repository at this point in the history
  • Loading branch information
cozyGalvinism committed Sep 8, 2021
0 parents commit a682b16
Show file tree
Hide file tree
Showing 7 changed files with 527 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/target
Cargo.lock
19 changes: 19 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "bpp-command-api"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tokio = { version = "1.10.1", features = ["macros", "rt-multi-thread", "sync"] }
async-trait = "0.1.51"
chrono = "0.4.19"
lazy_static = "1.4.0"
custom_error = "1.9.2"
fern = { version = "0.6.0", features = ["colored"] }
log = "0.4.14"
dyn-clone = "1.0.4"

[build-dependencies]
rustc_version = "0.4.0"
4 changes: 4 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
fn main() {
let version = rustc_version::version().unwrap();
println!("cargo:rustc-env=RUSTC_VERSION={}", version);
}
150 changes: 150 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
#[macro_use]
extern crate lazy_static;

use async_trait::async_trait;
use chrono::NaiveDateTime;
use dyn_clone::DynClone;
use ::log::error;
use message::StringView;

pub mod log;
pub mod macros;
pub mod message;

pub static CORE_VERSION: &str = env!("CARGO_PKG_VERSION");
pub static RUSTC_VERSION: &str = env!("RUSTC_VERSION");

pub struct CommandUser {
pub channel_id: String,
pub display_name: String,
pub active_time: i64,
pub money: f64,
pub first_seen_at: NaiveDateTime,
pub last_seen_at: NaiveDateTime,
}

pub struct Message {
pub user: CommandUser,
pub message: String,
pub has_command_info: bool,
pub command_name: String,
pub command_args: Vec<String>,
}

impl CommandUser {
pub fn new(channel_id: String, display_name: String, active_time: i64, money: f64, first_seen_at: NaiveDateTime, last_seen_at: NaiveDateTime) -> CommandUser {
CommandUser {
channel_id,
display_name,
active_time,
money,
first_seen_at,
last_seen_at,
}
}

pub fn mock() -> CommandUser {
CommandUser {
channel_id: "mock".to_string(),
display_name: "mock".to_string(),
active_time: 0,
money: 0.0,
first_seen_at: NaiveDateTime::from_timestamp(0, 0),
last_seen_at: NaiveDateTime::from_timestamp(0, 0),
}
}
}

impl Message {
pub fn new(user: CommandUser, message: String) -> Message {
let message_copy = message.clone();
let mut message_view = StringView::new(message);
let args = message_view.get_parameters();
if args.is_err() {
error!("Unable to get parameters from message: {}", args.unwrap_err());
return Message {
user,
message: message_copy,
has_command_info: false,
command_name: String::new(),
command_args: Vec::new(),
};
} else {
let args = args.unwrap();
let command_name = args.first().unwrap().clone();
if args.len() > 1 {
let command_args: Vec<String> = args.iter().skip(1).map(|x| x.clone()).collect();
return Message {
user,
message: message_copy,
command_name,
command_args,
has_command_info: true,
};
} else {
return Message {
user,
message: message_copy,
command_name,
command_args: Vec::new(),
has_command_info: true,
};
}
};
}
}

// define a trait for loadable commands
#[async_trait]
pub trait Command: Send + Sync + DynClone {
async fn execute(&self, message: Message);
}

dyn_clone::clone_trait_object!(Command);

pub struct CommandDeclaration {
pub rustc_version: &'static str,
pub core_version: &'static str,
pub register: unsafe extern "C" fn(&mut dyn CommandRegistrar),
}

pub trait CommandRegistrar {
fn register_command(&mut self, name: &str, aliases: &[&str], command: Box<dyn Command>);
}

/// Exports your command for it to be loaded.
///
/// # Example
///
/// ```
/// use async_trait::async_trait;
/// use bpp_command_api::{Command, CommandRegistrar};
///
/// #[derive(Clone)]
/// pub struct AddCanCommand;
///
/// #[async_trait]
/// impl Command for AddCanCommand {
/// async fn execute(&self, message: bpp_command_api::Message) {
/// println!("Added a can!");
/// }
/// }
///
/// bpp_command_api::export_command!(register);
///
/// extern "C" fn register(registrar: &mut dyn CommandRegistrar) {
/// registrar.register_command("addcan", &["addbear", "addjohn"], Box::new(AddCanCommand));
/// }
/// ```
#[macro_export]
macro_rules! export_command {
($register:expr) => {
#[doc(hidden)]
#[no_mangle]
pub static command_declaration: $crate::CommandDeclaration = $crate::CommandDeclaration {
rustc_version: $crate::RUSTC_VERSION,
core_version: $crate::CORE_VERSION,
register: $register,
};
};
}
40 changes: 40 additions & 0 deletions src/log.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use fern::{
colors::{Color, ColoredLevelConfig},
};

/// Sets up regular logging
pub fn setup_log(verbose: bool) {
let colors_line = ColoredLevelConfig::new()
.error(Color::Red)
.warn(Color::Yellow)
.info(Color::Green)
.debug(Color::White)
.trace(Color::BrightBlack);
let colors_level = colors_line.clone().info(Color::Green);

fern::Dispatch::new()
.chain(
fern::Dispatch::new()
.level(if verbose {
log::LevelFilter::Debug
} else {
log::LevelFilter::Info
})
.format(move |out, message, record| {
out.finish(format_args!(
"{color_line}[{date}][{target}][{level}{color_line}] {message}\x1B[0m",
color_line = format_args!(
"\x1B[{}m",
colors_line.get_color(&record.level()).to_fg_str()
),
date = chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
target = record.target(),
level = colors_level.color(record.level()),
message = message,
));
})
.chain(std::io::stdout()),
)
.apply()
.unwrap();
}
14 changes: 14 additions & 0 deletions src/macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#[macro_export]
macro_rules! collection {
($($k:expr => $v:expr), * $(,)?) => {
{
use std::iter::{Iterator, IntoIterator};
Iterator::collect(IntoIterator::into_iter([$(($k, $v),)*]))
}
};
// set-like
($($v:expr),* $(,)?) => {{
use std::iter::{Iterator, IntoIterator};
Iterator::collect(IntoIterator::into_iter([$($v,)*]))
}};
}
Loading

0 comments on commit a682b16

Please sign in to comment.