Skip to content

Commit

Permalink
Merge pull request #84 from jontze/release/v0.3.1
Browse files Browse the repository at this point in the history
Prepare relese v0.3.1
  • Loading branch information
jontze authored Feb 6, 2023
2 parents 7972ebc + e1ed8c0 commit fe9c05b
Show file tree
Hide file tree
Showing 30 changed files with 891 additions and 951 deletions.
6 changes: 3 additions & 3 deletions cadency/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cadency"
version = "0.3.0"
version = "0.3.1"
edition = "2021"
description = "An extensible discord bot with support with music commands"
license = "MIT"
Expand All @@ -14,11 +14,11 @@ log = "0.4.17"

[dependencies.cadency_core]
path = "../cadency_core"
version = "0.3.0"
version = "0.3.1"

[dependencies.cadency_commands]
path = "../cadency_commands"
version = "0.3.0"
version = "0.3.1"

[dependencies.tokio]
version = "1.25.0"
Expand Down
3 changes: 2 additions & 1 deletion cadency_codegen/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cadency_codegen"
version = "0.3.0"
version = "0.3.1"
edition = "2021"
description = "Library with codegen macros for the cadency discord bot"
license = "MIT"
Expand All @@ -12,5 +12,6 @@ proc_macro = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
proc-macro2 = "1.0.51"
quote = "1.0.23"
syn = "1.0.107"
26 changes: 0 additions & 26 deletions cadency_codegen/src/attribute.rs

This file was deleted.

149 changes: 142 additions & 7 deletions cadency_codegen/src/derive.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,156 @@
use proc_macro::TokenStream;
use syn::DeriveInput;
use syn::{DeriveInput, Lit, Meta, NestedMeta};

pub(crate) fn impl_command_baseline(derive_input: DeriveInput) -> TokenStream {
let struct_name = derive_input.ident;
let mut command_name = struct_name.to_string().to_lowercase();
let mut description = "".to_string();
let mut deferred = false;
let mut arguments: Vec<(String, String, String, bool)> = vec![];
for attr in derive_input.attrs.iter() {
let attr_meta = attr.parse_meta().unwrap();
match attr_meta {
Meta::NameValue(derive_attr) => {
match derive_attr.path.get_ident().unwrap().to_string().as_str() {
"name" => {
if let Lit::Str(name_attr_value) = derive_attr.lit {
command_name = name_attr_value.value();
} else {
return syn::Error::new(
derive_attr.lit.span(),
"'name' attribute must be a string",
)
.to_compile_error()
.into();
}
}
"description" => {
if let Lit::Str(description_attr_value) = derive_attr.lit {
description = description_attr_value.value();
} else {
return syn::Error::new(
derive_attr.lit.span(),
"'description' attribute must be a string",
)
.to_compile_error()
.into();
}
}
"deferred" => {
if let Lit::Bool(deferred_attr_value) = derive_attr.lit {
deferred = deferred_attr_value.value();
} else {
return syn::Error::new(
derive_attr.lit.span(),
"'deferred' attribute must be a bool",
)
.to_compile_error()
.into();
}
}
_ => (),
}
}
Meta::List(derive_attr_list) => {
if derive_attr_list
.path
.get_ident()
.unwrap()
.to_string()
.as_str()
== "argument"
{
let mut name: Option<String> = None;
let mut description: Option<String> = None;
let mut kind: Option<String> = None;
let mut required = true;

for arguments_attr_meta in derive_attr_list.nested.iter() {
if let NestedMeta::Meta(Meta::NameValue(argument_item)) =
arguments_attr_meta
{
match argument_item.path.get_ident().unwrap().to_string().as_str() {
"name" => {
if let Lit::Str(argument_name) = argument_item.lit.to_owned() {
name = Some(argument_name.value());
} else {
return syn::Error::new(argument_item.lit.span(), "Name must be a string").to_compile_error().into()
}
}
"description" => {
if let Lit::Str(argument_description) = argument_item.lit.to_owned() {
description = Some(argument_description.value());
} else {
return syn::Error::new(argument_item.lit.span(), "Description must be a string").to_compile_error().into()
}
}
"kind" => {
if let Lit::Str(argument_kind) = argument_item.lit.to_owned() {
kind = Some(argument_kind.value());
} else {
return syn::Error::new(argument_item.lit.span(), "Kind must be a string").to_compile_error().into()
}
}
"required" => {
if let Lit::Bool(argument_required) = argument_item.lit.to_owned() {
required = argument_required.value();
}
}
_ => {
return syn::Error::new(argument_item.path.get_ident().unwrap().span(), "Only 'name', 'description', 'kind' and 'required' are supported")
.to_compile_error()
.into()
}
}
}
}
match (name, description, kind) {
(Some(name), Some(description), Some(kind)) => {
arguments.push((name, description, kind, required));
}
_ => {
return syn::Error::new(
derive_attr_list.path.get_ident().unwrap().span(),
"You need to specify at least 'name', 'description' and 'kind'",
)
.to_compile_error()
.into();
}
}
}
}
_ => (),
}
}
let argument_tokens = arguments.iter().map(|(name, description, kind, required)| {
let kind_token: proc_macro2::TokenStream = kind.parse().unwrap();
quote! {
__CadencyCommandOption {
name: #name,
description: #description,
kind: __CommandOptionType::#kind_token,
required: #required
}
}
});
quote! {
use cadency_core::{self, CadencyCommandBaseline};
impl cadency_core::CadencyCommandBaseline for #struct_name {
use cadency_core::{CadencyCommandBaseline as __CadencyCommandBaseline, CadencyCommandOption as __CadencyCommandOption};
use serenity::model::application::command::CommandOptionType as __CommandOptionType;
impl __CadencyCommandBaseline for #struct_name {
fn name(&self) -> String {
String::from(stringify!(#struct_name)).to_lowercase()
String::from(#command_name)
}

fn description(&self) -> String {
self.description.to_string()
String::from(#description)
}

fn deferred(&self) -> bool {
#deferred
}

fn options(&self) -> &Vec<CadencyCommandOption> {
self.options.as_ref()
fn options(&self) -> Vec<__CadencyCommandOption> {
vec![#(#argument_tokens),*]
}
}
}
Expand Down
15 changes: 3 additions & 12 deletions cadency_codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,14 @@
extern crate quote;

use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput, ItemFn};
use syn::{parse_macro_input, DeriveInput};

mod attribute;
mod derive;

#[proc_macro_derive(CommandBaseline)]
#[proc_macro_derive(CommandBaseline, attributes(name, description, deferred, argument))]
pub fn derive_command_baseline(input_item: TokenStream) -> TokenStream {
// Parse token stream into derive syntax tree
let tree: DeriveInput = parse_macro_input!(input_item as DeriveInput);
let tree: DeriveInput = parse_macro_input!(input_item);
// Implement command trait
derive::impl_command_baseline(tree)
}

#[proc_macro_attribute]
pub fn command(_: TokenStream, input_item: TokenStream) -> TokenStream {
// Parse function
let input_function = parse_macro_input!(input_item as ItemFn);
// Return modified function
attribute::command::complete_command(input_function)
}
8 changes: 4 additions & 4 deletions cadency_commands/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "cadency_commands"
version = "0.3.0"
version = "0.3.1"
edition = "2021"
description = "Library with a collection of some commands for the cadency discord bot"
license = "MIT"
Expand All @@ -27,15 +27,15 @@ features = ["builtin-queue", "yt-dlp"]

[dependencies.cadency_core]
path = "../cadency_core"
version = "0.3.0"
version = "0.3.1"

[dependencies.cadency_codegen]
path = "../cadency_codegen"
version = "0.3.0"
version = "0.3.1"

[dependencies.cadency_yt_playlist]
path = "../cadency_yt_playlist"
version = "0.3.0"
version = "0.3.1"

[dev-dependencies.tokio]
version = "1.25.0"
Expand Down
58 changes: 24 additions & 34 deletions cadency_commands/src/fib.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,23 @@
use cadency_core::{utils, CadencyCommand, CadencyCommandOption, CadencyError};
use cadency_core::{
response::{Response, ResponseBuilder},
utils, CadencyCommand, CadencyError,
};
use serenity::{
async_trait,
client::Context,
model::application::{
command::CommandOptionType,
interaction::application_command::{ApplicationCommandInteraction, CommandDataOptionValue},
model::application::interaction::application_command::{
ApplicationCommandInteraction, CommandDataOptionValue,
},
};

#[derive(CommandBaseline)]
pub struct Fib {
description: &'static str,
options: Vec<CadencyCommandOption>,
}

impl std::default::Default for Fib {
fn default() -> Self {
Self {
description: "Calculate the nth number in the fibonacci sequence",
options: vec![CadencyCommandOption {
name: "number",
description: "The number in the fibonacci sequence",
kind: CommandOptionType::Integer,
required: true,
}],
}
}
}
#[derive(CommandBaseline, Default)]
#[description = "Calculate the nth number in the fibonacci sequence"]
#[argument(
name = "number",
description = "The number in the fibonacci sequence",
kind = "Integer"
)]
pub struct Fib {}

impl Fib {
fn calc(n: &i64) -> f64 {
Expand All @@ -40,13 +31,13 @@ impl Fib {

#[async_trait]
impl CadencyCommand for Fib {
#[command]
async fn execute<'a>(
&self,
ctx: &Context,
_ctx: &Context,
command: &'a mut ApplicationCommandInteraction,
) -> Result<(), CadencyError> {
let number_option = utils::get_option_value_at_position(command.data.options.as_ref(), 0)
response_builder: &'a mut ResponseBuilder,
) -> Result<Response, CadencyError> {
let number = utils::get_option_value_at_position(command.data.options.as_ref(), 0)
.and_then(|option_value| {
if let CommandDataOptionValue::Integer(fib_value) = option_value {
Some(fib_value)
Expand All @@ -58,12 +49,11 @@ impl CadencyCommand for Fib {
);
None
}
});
let fib_msg = match number_option {
Some(number) => Self::calc(number).to_string(),
None => "Invalid number input!".to_string(),
};
utils::create_response(ctx, command, &fib_msg).await?;
Ok(())
})
.ok_or(CadencyError::Command {
message: "Invalid number input".to_string(),
})?;
let fib_msg = Self::calc(number).to_string();
Ok(response_builder.message(Some(fib_msg)).build()?)
}
}
Loading

0 comments on commit fe9c05b

Please sign in to comment.