2020-08-18 19:09:21 +00:00
|
|
|
use regex_command_attr::command;
|
|
|
|
|
|
|
|
use serenity::{
|
|
|
|
client::Context,
|
|
|
|
model::{
|
2020-09-02 16:13:17 +00:00
|
|
|
id::RoleId,
|
2020-08-18 19:09:21 +00:00
|
|
|
channel::{
|
|
|
|
Message,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
framework::standard::CommandResult,
|
|
|
|
};
|
|
|
|
|
2020-08-26 17:26:28 +00:00
|
|
|
use regex::Regex;
|
|
|
|
|
2020-08-27 20:37:44 +00:00
|
|
|
use chrono_tz::Tz;
|
|
|
|
|
2020-08-22 00:24:12 +00:00
|
|
|
use crate::{
|
2020-08-27 11:15:20 +00:00
|
|
|
models::{
|
|
|
|
ChannelData,
|
|
|
|
UserData,
|
2020-08-29 19:57:11 +00:00
|
|
|
GuildData,
|
2020-08-27 11:15:20 +00:00
|
|
|
},
|
2020-08-22 00:24:12 +00:00
|
|
|
SQLPool,
|
2020-09-04 20:21:47 +00:00
|
|
|
FrameworkCtx,
|
2020-08-22 00:24:12 +00:00
|
|
|
};
|
2020-09-04 20:21:47 +00:00
|
|
|
use serenity::framework::Framework;
|
2020-08-18 19:09:21 +00:00
|
|
|
|
2020-08-26 17:26:28 +00:00
|
|
|
lazy_static! {
|
|
|
|
static ref REGEX_CHANNEL: Regex = Regex::new(r#"^\s*<#(\d+)>\s*$"#).unwrap();
|
2020-09-03 23:29:19 +00:00
|
|
|
|
2020-09-01 18:00:56 +00:00
|
|
|
static ref REGEX_ROLE: Regex = Regex::new(r#"<@&([0-9]+)>"#).unwrap();
|
2020-09-03 23:29:19 +00:00
|
|
|
|
2020-09-01 18:00:56 +00:00
|
|
|
static ref REGEX_COMMANDS: Regex = Regex::new(r#"([a-z]+)"#).unwrap();
|
2020-09-03 23:29:19 +00:00
|
|
|
|
|
|
|
static ref REGEX_ALIAS: Regex = Regex::new(r#"(?P<name>[\S]{1,12})(?:(?: (?P<cmd>.*)$)|$)"#).unwrap();
|
2020-08-26 17:26:28 +00:00
|
|
|
}
|
|
|
|
|
2020-08-18 19:09:21 +00:00
|
|
|
#[command]
|
|
|
|
#[supports_dm(false)]
|
|
|
|
#[permission_level(Restricted)]
|
2020-08-25 16:19:08 +00:00
|
|
|
#[can_blacklist(false)]
|
2020-08-18 19:09:21 +00:00
|
|
|
async fn blacklist(ctx: &Context, msg: &Message, args: String) -> CommandResult {
|
|
|
|
let pool = ctx.data.read().await
|
|
|
|
.get::<SQLPool>().cloned().expect("Could not get SQLPool from data");
|
|
|
|
|
2020-08-26 17:26:28 +00:00
|
|
|
let capture_opt = REGEX_CHANNEL.captures(&args).map(|cap| cap.get(1)).flatten();
|
|
|
|
|
|
|
|
let mut channel = match capture_opt {
|
|
|
|
Some(capture) =>
|
2020-09-01 16:07:51 +00:00
|
|
|
ChannelData::from_id(capture.as_str().parse::<u64>().unwrap(), &pool).await.unwrap(),
|
2020-08-26 17:26:28 +00:00
|
|
|
|
|
|
|
None =>
|
2020-09-01 16:07:51 +00:00
|
|
|
ChannelData::from_channel(msg.channel(&ctx).await.unwrap(), &pool).await.unwrap(),
|
2020-08-26 17:26:28 +00:00
|
|
|
};
|
2020-08-22 00:24:12 +00:00
|
|
|
|
|
|
|
channel.blacklisted = !channel.blacklisted;
|
2020-09-01 16:07:51 +00:00
|
|
|
channel.commit_changes(&pool).await;
|
2020-08-22 00:24:12 +00:00
|
|
|
|
|
|
|
if channel.blacklisted {
|
2020-08-25 16:19:08 +00:00
|
|
|
let _ = msg.channel_id.say(&ctx, "Blacklisted").await;
|
2020-08-22 00:24:12 +00:00
|
|
|
}
|
|
|
|
else {
|
2020-08-25 16:19:08 +00:00
|
|
|
let _ = msg.channel_id.say(&ctx, "Unblacklisted").await;
|
2020-08-22 00:24:12 +00:00
|
|
|
}
|
2020-08-18 19:09:21 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2020-08-27 11:15:20 +00:00
|
|
|
|
|
|
|
#[command]
|
|
|
|
async fn timezone(ctx: &Context, msg: &Message, args: String) -> CommandResult {
|
|
|
|
let pool = ctx.data.read().await
|
|
|
|
.get::<SQLPool>().cloned().expect("Could not get SQLPool from data");
|
|
|
|
|
2020-09-11 16:41:15 +00:00
|
|
|
let mut user_data = UserData::from_user(&msg.author, &ctx, &pool).await.unwrap();
|
2020-08-27 20:37:44 +00:00
|
|
|
|
2020-09-25 11:48:44 +00:00
|
|
|
if !args.is_empty() {
|
2020-08-29 17:07:15 +00:00
|
|
|
match args.parse::<Tz>() {
|
|
|
|
Ok(_) => {
|
|
|
|
user_data.timezone = args;
|
2020-08-27 20:37:44 +00:00
|
|
|
|
2020-09-01 16:07:51 +00:00
|
|
|
user_data.commit_changes(&pool).await;
|
2020-08-27 20:37:44 +00:00
|
|
|
|
2020-09-01 16:07:51 +00:00
|
|
|
let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "timezone/set_p").await).await;
|
2020-08-29 17:07:15 +00:00
|
|
|
}
|
2020-08-27 20:37:44 +00:00
|
|
|
|
2020-08-29 17:07:15 +00:00
|
|
|
Err(_) => {
|
2020-09-01 16:07:51 +00:00
|
|
|
let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "timezone/no_timezone").await).await;
|
2020-08-29 17:07:15 +00:00
|
|
|
}
|
2020-08-27 20:37:44 +00:00
|
|
|
}
|
|
|
|
}
|
2020-08-29 17:07:15 +00:00
|
|
|
else {
|
2020-09-01 16:07:51 +00:00
|
|
|
let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "timezone/no_argument").await).await;
|
2020-08-29 17:07:15 +00:00
|
|
|
}
|
2020-08-27 20:37:44 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[command]
|
|
|
|
async fn language(ctx: &Context, msg: &Message, args: String) -> CommandResult {
|
|
|
|
let pool = ctx.data.read().await
|
|
|
|
.get::<SQLPool>().cloned().expect("Could not get SQLPool from data");
|
|
|
|
|
2020-09-11 16:41:15 +00:00
|
|
|
let mut user_data = UserData::from_user(&msg.author, &ctx, &pool).await.unwrap();
|
2020-08-27 20:37:44 +00:00
|
|
|
|
2020-08-29 17:07:15 +00:00
|
|
|
match sqlx::query!(
|
|
|
|
"
|
|
|
|
SELECT code FROM languages WHERE code = ? OR name = ?
|
|
|
|
", args, args)
|
|
|
|
.fetch_one(&pool)
|
|
|
|
.await {
|
|
|
|
|
|
|
|
Ok(row) => {
|
|
|
|
user_data.language = row.code;
|
|
|
|
|
2020-09-01 16:07:51 +00:00
|
|
|
user_data.commit_changes(&pool).await;
|
2020-08-29 17:07:15 +00:00
|
|
|
|
2020-09-01 16:07:51 +00:00
|
|
|
let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "lang/set_p").await).await;
|
2020-08-29 17:07:15 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
Err(_) => {
|
2020-09-01 16:07:51 +00:00
|
|
|
let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "lang/invalid").await).await;
|
2020-08-29 17:07:15 +00:00
|
|
|
},
|
|
|
|
}
|
2020-08-27 11:15:20 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2020-08-29 19:57:11 +00:00
|
|
|
|
|
|
|
#[command]
|
2020-09-01 17:48:40 +00:00
|
|
|
#[supports_dm(false)]
|
|
|
|
#[permission_level(Restricted)]
|
2020-08-29 19:57:11 +00:00
|
|
|
async fn prefix(ctx: &Context, msg: &Message, args: String) -> CommandResult {
|
|
|
|
let pool = ctx.data.read().await
|
|
|
|
.get::<SQLPool>().cloned().expect("Could not get SQLPool from data");
|
|
|
|
|
2020-09-01 16:07:51 +00:00
|
|
|
let mut guild_data = GuildData::from_guild(msg.guild(&ctx).await.unwrap(), &pool).await.unwrap();
|
2020-09-11 16:41:15 +00:00
|
|
|
let user_data = UserData::from_user(&msg.author, &ctx, &pool).await.unwrap();
|
2020-08-29 19:57:11 +00:00
|
|
|
|
|
|
|
if args.len() > 5 {
|
2020-09-01 16:07:51 +00:00
|
|
|
let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "prefix/too_long").await).await;
|
2020-08-29 19:57:11 +00:00
|
|
|
}
|
2020-09-25 11:48:44 +00:00
|
|
|
else if args.is_empty() {
|
2020-09-01 16:07:51 +00:00
|
|
|
let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "prefix/no_argument").await).await;
|
2020-08-29 19:57:11 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
guild_data.prefix = args;
|
2020-09-01 16:07:51 +00:00
|
|
|
guild_data.commit_changes(&pool).await;
|
2020-08-29 19:57:11 +00:00
|
|
|
|
2020-09-01 16:07:51 +00:00
|
|
|
let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "prefix/success").await).await;
|
2020-08-29 19:57:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2020-09-01 18:00:56 +00:00
|
|
|
|
|
|
|
#[command]
|
|
|
|
#[supports_dm(false)]
|
|
|
|
#[permission_level(Restricted)]
|
|
|
|
async fn restrict(ctx: &Context, msg: &Message, args: String) -> CommandResult {
|
2020-09-02 16:13:17 +00:00
|
|
|
let pool = ctx.data.read().await
|
|
|
|
.get::<SQLPool>().cloned().expect("Could not get SQLPool from data");
|
|
|
|
|
2020-09-11 16:41:15 +00:00
|
|
|
let user_data = UserData::from_user(&msg.author, &ctx, &pool).await.unwrap();
|
2020-09-02 16:13:17 +00:00
|
|
|
let guild_data = GuildData::from_guild(msg.guild(&ctx).await.unwrap(), &pool).await.unwrap();
|
|
|
|
|
|
|
|
let role_tag_match = REGEX_ROLE.find(&args);
|
|
|
|
|
|
|
|
if let Some(role_tag) = role_tag_match {
|
|
|
|
let commands = REGEX_COMMANDS.find_iter(&args.to_lowercase()).map(|c| c.as_str().to_string()).collect::<Vec<String>>();
|
|
|
|
let role_id = RoleId(role_tag.as_str()[3..role_tag.as_str().len()-1].parse::<u64>().unwrap());
|
|
|
|
|
|
|
|
let role_opt = role_id.to_role_cached(&ctx).await;
|
|
|
|
|
|
|
|
if let Some(role) = role_opt {
|
2020-09-25 11:48:44 +00:00
|
|
|
if commands.is_empty() {
|
2020-09-02 16:13:17 +00:00
|
|
|
let _ = sqlx::query!(
|
|
|
|
"
|
|
|
|
DELETE FROM command_restrictions WHERE role_id = (SELECT id FROM roles WHERE role = ?)
|
|
|
|
", role.id.as_u64())
|
|
|
|
.execute(&pool)
|
|
|
|
.await;
|
|
|
|
|
|
|
|
let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "restrict/disabled").await).await;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
let _ = sqlx::query!(
|
|
|
|
"
|
|
|
|
INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, ?, ?)
|
|
|
|
", role.id.as_u64(), role.name, guild_data.id)
|
|
|
|
.execute(&pool)
|
|
|
|
.await;
|
|
|
|
|
|
|
|
for command in commands {
|
|
|
|
let res = sqlx::query!(
|
|
|
|
"
|
|
|
|
INSERT INTO command_restrictions (role_id, command) VALUES ((SELECT id FROM roles WHERE role = ?), ?)
|
|
|
|
", role.id.as_u64(), command)
|
|
|
|
.execute(&pool)
|
|
|
|
.await;
|
|
|
|
|
|
|
|
if res.is_err() {
|
|
|
|
let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "restrict/failure").await).await;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "restrict/enabled").await).await;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-09-25 11:48:44 +00:00
|
|
|
else if args.is_empty() {
|
|
|
|
let guild_id = msg.guild_id.unwrap().as_u64().to_owned();
|
2020-09-02 16:13:17 +00:00
|
|
|
|
|
|
|
let rows = sqlx::query!(
|
|
|
|
"
|
|
|
|
SELECT
|
|
|
|
roles.role, command_restrictions.command
|
|
|
|
FROM
|
|
|
|
command_restrictions
|
|
|
|
INNER JOIN
|
|
|
|
roles
|
|
|
|
ON
|
|
|
|
roles.id = command_restrictions.role_id
|
|
|
|
WHERE
|
|
|
|
roles.guild_id = (SELECT id FROM guilds WHERE guild = ?)
|
|
|
|
", guild_id)
|
|
|
|
.fetch_all(&pool)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let display_inner = rows.iter().map(|row| format!("<@&{}> can use {}", row.role, row.command)).collect::<Vec<String>>().join("\n");
|
|
|
|
let display = user_data.response(&pool, "restrict/allowed").await.replacen("{}", &display_inner, 1);
|
|
|
|
|
|
|
|
let _ = msg.channel_id.say(&ctx, display).await;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "restrict/help").await).await;
|
|
|
|
}
|
2020-09-01 18:00:56 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2020-09-03 23:29:19 +00:00
|
|
|
|
|
|
|
#[command]
|
|
|
|
#[supports_dm(false)]
|
|
|
|
#[permission_level(Managed)]
|
|
|
|
async fn alias(ctx: &Context, msg: &Message, args: String) -> CommandResult {
|
|
|
|
let pool = ctx.data.read().await
|
|
|
|
.get::<SQLPool>().cloned().expect("Could not get SQLPool from data");
|
|
|
|
|
2020-09-11 16:41:15 +00:00
|
|
|
let user_data = UserData::from_user(&msg.author, &ctx, &pool).await.unwrap();
|
2020-09-03 23:29:19 +00:00
|
|
|
|
|
|
|
let guild_id = msg.guild_id.unwrap().as_u64().to_owned();
|
|
|
|
|
|
|
|
let matches_opt = REGEX_ALIAS.captures(&args);
|
|
|
|
|
|
|
|
if let Some(matches) = matches_opt {
|
|
|
|
let name = matches.name("name").unwrap().as_str();
|
|
|
|
let command_opt = matches.name("cmd").map(|m| m.as_str());
|
|
|
|
|
|
|
|
match name {
|
|
|
|
"list" => {
|
|
|
|
let aliases = sqlx::query!(
|
|
|
|
"
|
|
|
|
SELECT name, command FROM command_aliases WHERE guild_id = (SELECT id FROM guilds WHERE guild = ?)
|
|
|
|
", guild_id)
|
|
|
|
.fetch_all(&pool)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let content = aliases.iter().map(|row| format!("**{}**: {}", row.name, row.command)).collect::<Vec<String>>().join("\n");
|
|
|
|
|
|
|
|
let _ = msg.channel_id.say(&ctx, format!("Aliases: \n{}", content)).await;
|
|
|
|
},
|
|
|
|
|
|
|
|
"remove" => {
|
|
|
|
if let Some(command) = command_opt {
|
|
|
|
sqlx::query!(
|
|
|
|
"
|
|
|
|
DELETE FROM command_aliases WHERE name = ? AND guild_id = (SELECT id FROM guilds WHERE guild = ?)
|
|
|
|
", command, guild_id)
|
|
|
|
.execute(&pool)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "alias/removed").await).await;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "alias/help").await).await;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
name => {
|
|
|
|
if let Some(command) = command_opt {
|
|
|
|
let res = sqlx::query!(
|
|
|
|
"
|
|
|
|
INSERT INTO command_aliases (guild_id, name, command) VALUES ((SELECT id FROM guilds WHERE guild = ?), ?, ?)
|
|
|
|
", guild_id, name, command)
|
|
|
|
.execute(&pool)
|
|
|
|
.await;
|
|
|
|
|
|
|
|
if res.is_err() {
|
|
|
|
sqlx::query!(
|
|
|
|
"
|
|
|
|
UPDATE command_aliases SET command = ? WHERE guild_id = (SELECT id FROM guilds WHERE guild = ?) AND name = ?
|
|
|
|
", command, guild_id, name)
|
|
|
|
.execute(&pool)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
}
|
|
|
|
|
|
|
|
let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "alias/created").await).await;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
match sqlx::query!(
|
|
|
|
"
|
2020-09-04 20:21:47 +00:00
|
|
|
SELECT command FROM command_aliases WHERE guild_id = (SELECT id FROM guilds WHERE guild = ?) AND name = ?
|
2020-09-03 23:29:19 +00:00
|
|
|
", guild_id, name)
|
|
|
|
.fetch_one(&pool)
|
|
|
|
.await {
|
|
|
|
|
|
|
|
Ok(row) => {
|
2020-09-04 20:21:47 +00:00
|
|
|
let framework = ctx.data.read().await
|
|
|
|
.get::<FrameworkCtx>().cloned().expect("Could not get FrameworkCtx from data");
|
|
|
|
|
|
|
|
let mut new_msg = msg.clone();
|
|
|
|
new_msg.content = format!("<@{}> {}", &ctx.cache.current_user_id().await, row.command);
|
|
|
|
|
|
|
|
framework.dispatch(ctx.clone(), new_msg).await;
|
2020-09-03 23:29:19 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
Err(_) => {
|
|
|
|
let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "alias/not_found").await).await;
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
let _ = msg.channel_id.say(&ctx, user_data.response(&pool, "alias/help").await).await;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|