2020-08-26 17:26:28 +00:00
|
|
|
#[macro_use]
|
|
|
|
extern crate lazy_static;
|
|
|
|
|
2020-08-18 19:09:21 +00:00
|
|
|
mod models;
|
2020-08-06 14:22:13 +00:00
|
|
|
mod framework;
|
2020-08-09 22:59:31 +00:00
|
|
|
mod commands;
|
2020-08-29 23:16:33 +00:00
|
|
|
mod time_parser;
|
2020-09-28 12:42:20 +00:00
|
|
|
mod consts;
|
2020-08-06 14:22:13 +00:00
|
|
|
|
|
|
|
use serenity::{
|
2020-10-03 16:31:23 +00:00
|
|
|
cache::Cache,
|
2020-10-11 16:41:26 +00:00
|
|
|
http::{
|
|
|
|
CacheHttp,
|
|
|
|
client::Http,
|
|
|
|
},
|
2020-08-06 14:22:13 +00:00
|
|
|
client::{
|
|
|
|
bridge::gateway::GatewayIntents,
|
2020-08-10 21:12:26 +00:00
|
|
|
Client,
|
2020-08-06 14:22:13 +00:00
|
|
|
},
|
2020-10-03 16:31:23 +00:00
|
|
|
model::{
|
|
|
|
id::{
|
|
|
|
GuildId, UserId,
|
|
|
|
},
|
|
|
|
channel::Message,
|
2020-09-15 13:43:49 +00:00
|
|
|
},
|
2020-09-03 23:29:19 +00:00
|
|
|
framework::Framework,
|
2020-08-06 14:22:13 +00:00
|
|
|
prelude::TypeMapKey,
|
|
|
|
};
|
|
|
|
|
|
|
|
use sqlx::{
|
|
|
|
Pool,
|
|
|
|
mysql::{
|
2020-08-07 15:45:19 +00:00
|
|
|
MySqlPool,
|
2020-08-06 14:22:13 +00:00
|
|
|
MySqlConnection,
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
use dotenv::dotenv;
|
|
|
|
|
|
|
|
use std::{
|
|
|
|
sync::Arc,
|
|
|
|
env,
|
|
|
|
};
|
|
|
|
|
2020-09-28 12:42:20 +00:00
|
|
|
use crate::{
|
|
|
|
framework::RegexFramework,
|
2020-10-06 11:02:09 +00:00
|
|
|
consts::{
|
|
|
|
PREFIX, DAY, HOUR, MINUTE,
|
2020-10-11 16:41:26 +00:00
|
|
|
SUBSCRIPTION_ROLES, CNC_GUILD,
|
2020-10-06 11:02:09 +00:00
|
|
|
},
|
2020-09-28 12:42:20 +00:00
|
|
|
commands::{
|
|
|
|
info_cmds,
|
|
|
|
reminder_cmds,
|
|
|
|
todo_cmds,
|
|
|
|
moderation_cmds,
|
|
|
|
},
|
2020-08-09 22:59:31 +00:00
|
|
|
};
|
2020-10-11 16:41:26 +00:00
|
|
|
|
2020-10-06 11:02:09 +00:00
|
|
|
use num_integer::Integer;
|
2020-10-11 16:41:26 +00:00
|
|
|
use serenity::futures::TryFutureExt;
|
2020-08-06 14:22:13 +00:00
|
|
|
|
|
|
|
struct SQLPool;
|
|
|
|
|
|
|
|
impl TypeMapKey for SQLPool {
|
|
|
|
type Value = Pool<MySqlConnection>;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct ReqwestClient;
|
|
|
|
|
|
|
|
impl TypeMapKey for ReqwestClient {
|
|
|
|
type Value = Arc<reqwest::Client>;
|
|
|
|
}
|
|
|
|
|
2020-09-03 23:29:19 +00:00
|
|
|
struct FrameworkCtx;
|
|
|
|
|
|
|
|
impl TypeMapKey for FrameworkCtx {
|
|
|
|
type Value = Arc<Box<dyn Framework + Send + Sync>>;
|
|
|
|
}
|
|
|
|
|
2020-08-07 15:45:19 +00:00
|
|
|
static THEME_COLOR: u32 = 0x8fb677;
|
2020-08-06 14:22:13 +00:00
|
|
|
|
|
|
|
#[tokio::main]
|
|
|
|
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|
|
|
dotenv()?;
|
|
|
|
|
2020-10-11 16:41:26 +00:00
|
|
|
let token = env::var("DISCORD_TOKEN").expect("Missing DISCORD_TOKEN from environment");
|
|
|
|
|
|
|
|
let http = Http::new_with_token(&token);
|
|
|
|
|
|
|
|
let framework = RegexFramework::new(http.get_current_user().map_ok(|user| user.id.as_u64().to_owned()).await?)
|
2020-08-06 14:22:13 +00:00
|
|
|
.ignore_bots(true)
|
2020-09-28 12:42:20 +00:00
|
|
|
.default_prefix(&env::var("DEFAULT_PREFIX").unwrap_or_else(|_| PREFIX.to_string()))
|
2020-09-01 17:48:40 +00:00
|
|
|
|
|
|
|
.add_command("ping", &info_cmds::PING_COMMAND)
|
|
|
|
|
2020-08-09 22:59:31 +00:00
|
|
|
.add_command("help", &info_cmds::HELP_COMMAND)
|
|
|
|
.add_command("info", &info_cmds::INFO_COMMAND)
|
2020-10-11 00:42:19 +00:00
|
|
|
.add_command("invite", &info_cmds::INFO_COMMAND)
|
2020-08-09 22:59:31 +00:00
|
|
|
.add_command("donate", &info_cmds::DONATE_COMMAND)
|
2020-09-01 16:07:51 +00:00
|
|
|
.add_command("dashboard", &info_cmds::DASHBOARD_COMMAND)
|
2020-08-27 20:37:44 +00:00
|
|
|
.add_command("clock", &info_cmds::CLOCK_COMMAND)
|
2020-09-01 17:18:45 +00:00
|
|
|
|
2020-09-08 22:08:02 +00:00
|
|
|
.add_command("timer", &reminder_cmds::TIMER_COMMAND)
|
|
|
|
|
2020-09-11 16:41:15 +00:00
|
|
|
.add_command("remind", &reminder_cmds::REMIND_COMMAND)
|
|
|
|
.add_command("r", &reminder_cmds::REMIND_COMMAND)
|
|
|
|
.add_command("interval", &reminder_cmds::INTERVAL_COMMAND)
|
|
|
|
.add_command("i", &reminder_cmds::INTERVAL_COMMAND)
|
2020-09-19 14:20:43 +00:00
|
|
|
.add_command("natural", &reminder_cmds::NATURAL_COMMAND)
|
|
|
|
.add_command("n", &reminder_cmds::NATURAL_COMMAND)
|
|
|
|
.add_command("", &reminder_cmds::NATURAL_COMMAND)
|
2020-09-11 16:41:15 +00:00
|
|
|
|
2020-09-05 20:17:45 +00:00
|
|
|
.add_command("look", &reminder_cmds::LOOK_COMMAND)
|
2020-09-08 22:08:02 +00:00
|
|
|
.add_command("del", &reminder_cmds::DELETE_COMMAND)
|
2020-09-05 20:17:45 +00:00
|
|
|
|
2020-08-17 23:18:33 +00:00
|
|
|
.add_command("todo", &todo_cmds::TODO_PARSE_COMMAND)
|
2020-09-01 17:18:45 +00:00
|
|
|
|
2020-08-18 19:09:21 +00:00
|
|
|
.add_command("blacklist", &moderation_cmds::BLACKLIST_COMMAND)
|
2020-09-02 16:13:17 +00:00
|
|
|
.add_command("restrict", &moderation_cmds::RESTRICT_COMMAND)
|
2020-08-27 20:37:44 +00:00
|
|
|
.add_command("timezone", &moderation_cmds::TIMEZONE_COMMAND)
|
2020-09-01 16:07:51 +00:00
|
|
|
.add_command("prefix", &moderation_cmds::PREFIX_COMMAND)
|
2020-09-01 14:34:50 +00:00
|
|
|
.add_command("lang", &moderation_cmds::LANGUAGE_COMMAND)
|
2020-09-01 17:18:45 +00:00
|
|
|
|
2020-09-01 14:34:50 +00:00
|
|
|
.add_command("pause", &reminder_cmds::PAUSE_COMMAND)
|
2020-09-01 17:18:45 +00:00
|
|
|
.add_command("offset", &reminder_cmds::OFFSET_COMMAND)
|
2020-09-01 17:37:43 +00:00
|
|
|
.add_command("nudge", &reminder_cmds::NUDGE_COMMAND)
|
|
|
|
|
2020-09-04 20:21:47 +00:00
|
|
|
.add_command("alias", &moderation_cmds::ALIAS_COMMAND)
|
2020-09-05 20:17:45 +00:00
|
|
|
.add_command("a", &moderation_cmds::ALIAS_COMMAND)
|
2020-09-04 20:21:47 +00:00
|
|
|
|
2020-08-06 14:22:13 +00:00
|
|
|
.build();
|
|
|
|
|
2020-09-03 23:29:19 +00:00
|
|
|
let framework_arc = Arc::new(Box::new(framework) as Box<dyn Framework + Send + Sync>);
|
|
|
|
|
2020-10-11 16:41:26 +00:00
|
|
|
let mut client = Client::new(&token)
|
2020-08-06 14:22:13 +00:00
|
|
|
.intents(GatewayIntents::GUILD_MESSAGES | GatewayIntents::GUILDS | GatewayIntents::DIRECT_MESSAGES)
|
2020-09-03 23:29:19 +00:00
|
|
|
.framework_arc(framework_arc.clone())
|
2020-08-06 18:18:30 +00:00
|
|
|
.await.expect("Error occurred creating client");
|
2020-08-06 14:22:13 +00:00
|
|
|
|
2020-08-07 15:45:19 +00:00
|
|
|
{
|
|
|
|
let pool = MySqlPool::new(&env::var("DATABASE_URL").expect("Missing DATABASE_URL from environment")).await.unwrap();
|
|
|
|
|
|
|
|
let mut data = client.data.write().await;
|
|
|
|
|
|
|
|
data.insert::<SQLPool>(pool);
|
|
|
|
data.insert::<ReqwestClient>(Arc::new(reqwest::Client::new()));
|
2020-09-03 23:29:19 +00:00
|
|
|
data.insert::<FrameworkCtx>(framework_arc);
|
2020-08-07 15:45:19 +00:00
|
|
|
}
|
|
|
|
|
2020-08-06 14:22:13 +00:00
|
|
|
client.start_autosharded().await?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2020-09-15 13:43:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
pub async fn check_subscription(cache_http: impl CacheHttp, user_id: impl Into<UserId>) -> bool {
|
2020-10-11 16:41:26 +00:00
|
|
|
|
|
|
|
if let Some(subscription_guild) = *CNC_GUILD {
|
|
|
|
let guild_member = GuildId(subscription_guild).member(cache_http, user_id).await;
|
|
|
|
|
|
|
|
if let Ok(member) = guild_member {
|
|
|
|
for role in member.roles {
|
|
|
|
if SUBSCRIPTION_ROLES.contains(role.as_u64()) {
|
2020-09-15 13:43:49 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
false
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
true
|
|
|
|
}
|
|
|
|
}
|
2020-10-03 16:31:23 +00:00
|
|
|
|
|
|
|
pub async fn check_subscription_on_message(cache_http: impl CacheHttp + AsRef<Cache>, msg: &Message) -> bool {
|
|
|
|
check_subscription(&cache_http, &msg.author).await ||
|
|
|
|
if let Some(guild) = msg.guild(&cache_http).await { check_subscription(&cache_http, guild.owner_id).await } else { false }
|
|
|
|
}
|
2020-10-06 11:02:09 +00:00
|
|
|
|
|
|
|
pub fn shorthand_displacement(seconds: u64) -> String {
|
|
|
|
let (hours, seconds) = seconds.div_rem(&HOUR);
|
|
|
|
let (minutes, seconds) = seconds.div_rem(&MINUTE);
|
|
|
|
|
|
|
|
format!("{:02}:{:02}:{:02}", hours, minutes, seconds)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn longhand_displacement(seconds: u64) -> String {
|
|
|
|
let (days, seconds) = seconds.div_rem(&DAY);
|
|
|
|
let (hours, seconds) = seconds.div_rem(&HOUR);
|
|
|
|
let (minutes, seconds) = seconds.div_rem(&MINUTE);
|
|
|
|
|
|
|
|
let mut sections = vec![];
|
|
|
|
|
|
|
|
for (var, name) in [days, hours, minutes, seconds].iter().zip(["days", "hours", "minutes", "seconds"].iter()) {
|
|
|
|
if *var > 0 {
|
|
|
|
sections.push(format!("{} {}", var, name));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sections.join(", ")
|
|
|
|
}
|