Compare commits
3 Commits
jude/restr
...
current
Author | SHA1 | Date | |
---|---|---|---|
a9edcec43c | |||
cc5f6d9d55 | |||
761d545496 |
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -1,6 +1,6 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 4
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "addr2line"
|
name = "addr2line"
|
||||||
@ -2614,7 +2614,7 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reminder-rs"
|
name = "reminder-rs"
|
||||||
version = "1.7.37"
|
version = "1.7.38"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "reminder-rs"
|
name = "reminder-rs"
|
||||||
version = "1.7.37"
|
version = "1.7.38"
|
||||||
authors = ["Jude Southworth <judesouthworth@pm.me>"]
|
authors = ["Jude Southworth <judesouthworth@pm.me>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "AGPL-3.0 only"
|
license = "AGPL-3.0 only"
|
||||||
|
@ -75,8 +75,8 @@ Please select a unique name for your macro.",
|
|||||||
CreateEmbed::new()
|
CreateEmbed::new()
|
||||||
.title("Macro Recording Started")
|
.title("Macro Recording Started")
|
||||||
.description(
|
.description(
|
||||||
"Run up to 5 commands, or type `/macro finish` to stop at any point.
|
"Run up to 5 commands to record in this macro. Use `/macro finish` to stop recording at any point.
|
||||||
Any commands ran as part of recording will be inconsequential",
|
Any commands performed during recording won't take any actual action- they are only captured for the macro.",
|
||||||
)
|
)
|
||||||
.color(*THEME_COLOR),
|
.color(*THEME_COLOR),
|
||||||
),
|
),
|
||||||
|
57
src/hooks.rs
57
src/hooks.rs
@ -1,4 +1,6 @@
|
|||||||
use poise::{CommandInteractionType, CreateReply};
|
use crate::consts::THEME_COLOR;
|
||||||
|
use poise::{serenity_prelude::CreateEmbed, CommandInteractionType, CreateReply};
|
||||||
|
use serenity::builder::CreateEmbedFooter;
|
||||||
|
|
||||||
use crate::{consts::MACRO_MAX_COMMANDS, models::command_macro::RecordedCommand, Context, Error};
|
use crate::{consts::MACRO_MAX_COMMANDS, models::command_macro::RecordedCommand, Context, Error};
|
||||||
|
|
||||||
@ -18,7 +20,18 @@ async fn macro_check(ctx: Context<'_>) -> bool {
|
|||||||
.send(
|
.send(
|
||||||
CreateReply::default()
|
CreateReply::default()
|
||||||
.ephemeral(true)
|
.ephemeral(true)
|
||||||
.content(format!("{} commands already recorded. Please use `/macro finish` to end recording.", MACRO_MAX_COMMANDS))
|
.embed(CreateEmbed::new()
|
||||||
|
.title("💾 Currently recording macro")
|
||||||
|
.description(
|
||||||
|
format!("{} commands already recorded. Please use `/macro finish` to end recording.", MACRO_MAX_COMMANDS),
|
||||||
|
)
|
||||||
|
.footer(
|
||||||
|
CreateEmbedFooter::new(
|
||||||
|
"Any commands performed during recording won't take any actual action- they are only captured for the macro"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.color(*THEME_COLOR),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
} else {
|
} else {
|
||||||
@ -28,9 +41,19 @@ async fn macro_check(ctx: Context<'_>) -> bool {
|
|||||||
|
|
||||||
let _ = ctx
|
let _ = ctx
|
||||||
.send(
|
.send(
|
||||||
CreateReply::default()
|
CreateReply::default().ephemeral(true).embed(
|
||||||
.ephemeral(true)
|
CreateEmbed::new()
|
||||||
.content("Command recorded to macro"),
|
.title("💾 Currently recording macro")
|
||||||
|
.description(
|
||||||
|
"Command recorded. Use `/macro finish` to end recording.",
|
||||||
|
)
|
||||||
|
.footer(
|
||||||
|
CreateEmbedFooter::new(
|
||||||
|
"Any commands performed during recording won't take any actual action- they are only captured for the macro"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.color(*THEME_COLOR),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@ -38,8 +61,18 @@ async fn macro_check(ctx: Context<'_>) -> bool {
|
|||||||
None => {
|
None => {
|
||||||
let _ = ctx
|
let _ = ctx
|
||||||
.send(
|
.send(
|
||||||
CreateReply::default().ephemeral(true).content(
|
CreateReply::default().ephemeral(true).embed(
|
||||||
"This command is not supported in macros yet.",
|
CreateEmbed::new()
|
||||||
|
.title("💾 Currently recording macro")
|
||||||
|
.description(
|
||||||
|
"This command is not supported in macros, so it hasn't been recorded. Use `/macro finish` to end recording.",
|
||||||
|
)
|
||||||
|
.footer(
|
||||||
|
CreateEmbedFooter::new(
|
||||||
|
"Any commands performed during recording won't take any actual action- they are only captured for the macro"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.color(*THEME_COLOR),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
@ -74,6 +107,7 @@ async fn check_self_permissions(ctx: Context<'_>) -> bool {
|
|||||||
return if permissions.send_messages()
|
return if permissions.send_messages()
|
||||||
&& permissions.embed_links()
|
&& permissions.embed_links()
|
||||||
&& manage_webhooks
|
&& manage_webhooks
|
||||||
|
&& permissions.view_channel()
|
||||||
{
|
{
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
@ -81,12 +115,13 @@ async fn check_self_permissions(ctx: Context<'_>) -> bool {
|
|||||||
.send(CreateReply::default().content(format!(
|
.send(CreateReply::default().content(format!(
|
||||||
"The bot appears to be missing some permissions:
|
"The bot appears to be missing some permissions:
|
||||||
|
|
||||||
|
{} **View Channels**
|
||||||
{} **Send Message**
|
{} **Send Message**
|
||||||
{} **Embed Links**
|
{} **Embed Links**
|
||||||
{} **Manage Webhooks**
|
{} **Manage Webhooks**
|
||||||
|
|
||||||
Please check the bot's roles, and any channel overrides. Alternatively, giving the bot
|
Please check the bot's roles, and any channel overrides. Alternatively, giving the bot \"Administrator\" will bypass permission checks",
|
||||||
\"Administrator\" will bypass permission checks",
|
if permissions.view_channel() { "✅" } else { "❌" },
|
||||||
if permissions.send_messages() { "✅" } else { "❌" },
|
if permissions.send_messages() { "✅" } else { "❌" },
|
||||||
if permissions.embed_links() { "✅" } else { "❌" },
|
if permissions.embed_links() { "✅" } else { "❌" },
|
||||||
if manage_webhooks { "✅" } else { "❌" },
|
if manage_webhooks { "✅" } else { "❌" },
|
||||||
@ -100,9 +135,7 @@ Please check the bot's roles, and any channel overrides. Alternatively, giving t
|
|||||||
manage_webhooks
|
manage_webhooks
|
||||||
}
|
}
|
||||||
|
|
||||||
None => {
|
None => true,
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,6 +92,8 @@ enum Error {
|
|||||||
SQLx(sqlx::Error),
|
SQLx(sqlx::Error),
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
Serenity(serenity::Error),
|
Serenity(serenity::Error),
|
||||||
|
#[allow(unused)]
|
||||||
|
MissingDiscordPermission(&'static str),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn initialize(
|
pub async fn initialize(
|
||||||
|
@ -305,7 +305,15 @@ pub async fn edit_reminder(
|
|||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("`create_database_channel` returned an error code: {:?}", e);
|
warn!("`create_database_channel` returned an error code: {:?}", e);
|
||||||
|
|
||||||
error.push("Failed to configure channel for reminders. Please check the bot permissions".to_string());
|
// Provide more specific error messages based on the error type
|
||||||
|
match e {
|
||||||
|
crate::web::Error::MissingDiscordPermission(permission) => {
|
||||||
|
error.push(format!("Please ensure the bot has the \"{}\" permission in the channel", permission));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
error.push("Failed to configure channel for reminders. Please check the bot permissions".to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,16 @@ pub async fn create_reminder(
|
|||||||
if let Err(e) = channel {
|
if let Err(e) = channel {
|
||||||
warn!("`create_database_channel` returned an error code: {:?}", e);
|
warn!("`create_database_channel` returned an error code: {:?}", e);
|
||||||
|
|
||||||
return Err(json!({"error": "Failed to configure channel for reminders."}));
|
// Provide more specific error messages based on the error type
|
||||||
|
let error_msg = match e {
|
||||||
|
Error::MissingDiscordPermission(permission) => format!(
|
||||||
|
"Please ensure the bot has the \"{}\" permission in the channel",
|
||||||
|
permission
|
||||||
|
),
|
||||||
|
_ => "Failed to configure channel for reminders.".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
return Err(json!({"error": error_msg}));
|
||||||
}
|
}
|
||||||
|
|
||||||
let channel = channel.unwrap();
|
let channel = channel.unwrap();
|
||||||
|
@ -10,6 +10,7 @@ use rocket::{
|
|||||||
use rocket_dyn_templates::Template;
|
use rocket_dyn_templates::Template;
|
||||||
use secrecy::ExposeSecret;
|
use secrecy::ExposeSecret;
|
||||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
use serenity::http::HttpError;
|
||||||
use serenity::{
|
use serenity::{
|
||||||
all::CacheHttp,
|
all::CacheHttp,
|
||||||
builder::CreateWebhook,
|
builder::CreateWebhook,
|
||||||
@ -404,9 +405,19 @@ pub(crate) async fn create_reminder(
|
|||||||
if let Err(e) = channel {
|
if let Err(e) = channel {
|
||||||
warn!("`create_database_channel` returned an error code: {:?}", e);
|
warn!("`create_database_channel` returned an error code: {:?}", e);
|
||||||
|
|
||||||
return Err(
|
// Provide more specific error messages based on the error type
|
||||||
json!({"error": "Failed to configure channel for reminders. Please check the bot permissions"}),
|
let error_msg = match e {
|
||||||
);
|
Error::MissingDiscordPermission(permission) => {
|
||||||
|
format!(
|
||||||
|
"Please ensure the bot has the \"{}\" permission in the channel",
|
||||||
|
permission
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_ => "Failed to configure channel for reminders. Please check the bot permissions"
|
||||||
|
.to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
return Err(json!({"error": error_msg}));
|
||||||
}
|
}
|
||||||
|
|
||||||
let channel = channel.unwrap();
|
let channel = channel.unwrap();
|
||||||
@ -716,13 +727,36 @@ async fn create_database_channel(
|
|||||||
|
|
||||||
match row {
|
match row {
|
||||||
Ok(row) => {
|
Ok(row) => {
|
||||||
let is_dm =
|
let is_dm = channel
|
||||||
channel.to_channel(&ctx).await.map_err(|e| Error::Serenity(e))?.private().is_some();
|
.to_channel(&ctx)
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
if let serenity::Error::Http(http_error) = &e {
|
||||||
|
if let HttpError::UnsuccessfulRequest(response) = http_error {
|
||||||
|
if response.error.code == 50001 {
|
||||||
|
return Error::MissingDiscordPermission("View Channel");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Error::Serenity(e)
|
||||||
|
})?
|
||||||
|
.private()
|
||||||
|
.is_some();
|
||||||
if !is_dm && (row.webhook_token.is_none() || row.webhook_id.is_none()) {
|
if !is_dm && (row.webhook_token.is_none() || row.webhook_id.is_none()) {
|
||||||
let webhook = channel
|
let webhook = channel
|
||||||
.create_webhook(&ctx, CreateWebhook::new("Reminder").avatar(&*DEFAULT_AVATAR))
|
.create_webhook(&ctx, CreateWebhook::new("Reminder").avatar(&*DEFAULT_AVATAR))
|
||||||
.await
|
.await
|
||||||
.map_err(|e| Error::Serenity(e))?;
|
.map_err(|e| match &e {
|
||||||
|
serenity::Error::Http(HttpError::UnsuccessfulRequest(response)) => {
|
||||||
|
match response.error.code {
|
||||||
|
50001 => Error::MissingDiscordPermission("View Channel"),
|
||||||
|
50013 => Error::MissingDiscordPermission("Manage Webhooks"),
|
||||||
|
_ => Error::Serenity(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Error::Serenity(e),
|
||||||
|
})?;
|
||||||
|
|
||||||
let token = webhook.token.unwrap();
|
let token = webhook.token.unwrap();
|
||||||
|
|
||||||
@ -747,7 +781,16 @@ async fn create_database_channel(
|
|||||||
let webhook = channel
|
let webhook = channel
|
||||||
.create_webhook(&ctx, CreateWebhook::new("Reminder").avatar(&*DEFAULT_AVATAR))
|
.create_webhook(&ctx, CreateWebhook::new("Reminder").avatar(&*DEFAULT_AVATAR))
|
||||||
.await
|
.await
|
||||||
.map_err(|e| Error::Serenity(e))?;
|
.map_err(|e| match &e {
|
||||||
|
serenity::Error::Http(HttpError::UnsuccessfulRequest(response)) => {
|
||||||
|
match response.error.code {
|
||||||
|
50001 => Error::MissingDiscordPermission("View Channel"),
|
||||||
|
50013 => Error::MissingDiscordPermission("Manage Webhooks"),
|
||||||
|
_ => Error::Serenity(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Error::Serenity(e),
|
||||||
|
})?;
|
||||||
|
|
||||||
let token = webhook.token.unwrap();
|
let token = webhook.token.unwrap();
|
||||||
|
|
||||||
@ -806,22 +849,15 @@ pub async fn todos_redirect(id: &str) -> Redirect {
|
|||||||
|
|
||||||
#[get("/")]
|
#[get("/")]
|
||||||
pub async fn dashboard_home(cookies: &CookieJar<'_>) -> DashboardPage {
|
pub async fn dashboard_home(cookies: &CookieJar<'_>) -> DashboardPage {
|
||||||
if cookies.get_private("userid").is_some() {
|
render_dashboard(cookies).await
|
||||||
match NamedFile::open(Path::new(path!("static/index.html"))).await {
|
|
||||||
Ok(f) => DashboardPage::Ok(f),
|
|
||||||
Err(e) => {
|
|
||||||
warn!("Couldn't render dashboard: {:?}", e);
|
|
||||||
|
|
||||||
DashboardPage::NotConfigured(internal_server_error().await)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DashboardPage::Unauthorised(Redirect::to("/login/discord"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/<_..>")]
|
#[get("/<_..>")]
|
||||||
pub async fn dashboard(cookies: &CookieJar<'_>) -> DashboardPage {
|
pub async fn dashboard(cookies: &CookieJar<'_>) -> DashboardPage {
|
||||||
|
render_dashboard(cookies).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn render_dashboard(cookies: &CookieJar<'_>) -> DashboardPage {
|
||||||
if cookies.get_private("userid").is_some() {
|
if cookies.get_private("userid").is_some() {
|
||||||
match NamedFile::open(Path::new(path!("static/index.html"))).await {
|
match NamedFile::open(Path::new(path!("static/index.html"))).await {
|
||||||
Ok(f) => DashboardPage::Ok(f),
|
Ok(f) => DashboardPage::Ok(f),
|
||||||
|
Reference in New Issue
Block a user