diff --git a/discord_bot/Cargo.lock b/discord_bot/Cargo.lock index 955208e74e..7220ce4f61 100644 --- a/discord_bot/Cargo.lock +++ b/discord_bot/Cargo.lock @@ -776,6 +776,7 @@ dependencies = [ "hmac", "indoc", "itertools", + "log", "once_cell", "poise", "rand", diff --git a/discord_bot/Cargo.toml b/discord_bot/Cargo.toml index 2ef06ca845..c939e4e881 100644 --- a/discord_bot/Cargo.toml +++ b/discord_bot/Cargo.toml @@ -18,6 +18,7 @@ hex-literal = "0.4.1" hmac = "0.12.1" indoc = "2.0.4" itertools = "0.12.0" +log = "0.4.22" once_cell = "1.19.0" poise = "0.6.1" rand = "0.8.5" diff --git a/discord_bot/Dockerfile b/discord_bot/Dockerfile index 29438a462d..2172bdb522 100644 --- a/discord_bot/Dockerfile +++ b/discord_bot/Dockerfile @@ -18,4 +18,5 @@ RUN apt-get update && \ rm -rf /var/lib/apt/lists/* RUN /usr/sbin/update-ca-certificates COPY --from=builder /usr/local/cargo/bin/discord_bot /usr/local/bin/discord_bot +ENV RUST_LOG="discord_bot=debug" CMD ["discord_bot"] diff --git a/discord_bot/src/clickup/get_task.rs b/discord_bot/src/clickup/get_task.rs index 073e27652a..a4a91d7f4a 100644 --- a/discord_bot/src/clickup/get_task.rs +++ b/discord_bot/src/clickup/get_task.rs @@ -1,4 +1,5 @@ use crate::{webhook::TaskTag, WinstonError, CLIENT}; +use log::warn; use serde::{Deserialize, Serialize}; use serde_json::Value; use strum::IntoEnumIterator; @@ -23,8 +24,8 @@ pub async fn get_task_from_clickup(task_id: &str) -> Result match serde_json::from_str::(&text) { Ok(task) => Ok(task), Err(e) => { - eprintln!("failed to deserialize task: {}", e); - eprintln!("response: {}", text); + warn!("failed to deserialize task: {}", e); + warn!("response: {}", text); Err(WinstonError::ParseJson(e)) } } diff --git a/discord_bot/src/clickup/get_tasks.rs b/discord_bot/src/clickup/get_tasks.rs index 8d23c8986f..60332ec61f 100644 --- a/discord_bot/src/clickup/get_tasks.rs +++ b/discord_bot/src/clickup/get_tasks.rs @@ -1,3 +1,4 @@ +use log::warn; use url::Url; use crate::{WinstonError, CLICKUP_LIST_ID, CLIENT}; @@ -47,8 +48,8 @@ pub async fn get_tasks(query: TasksQuery) -> Result match serde_json::from_str::(&text) { Ok(tasks) => Ok(tasks), Err(e) => { - eprintln!("failed to deserialize task: {}", e); - eprintln!("response: {}", text); + warn!("failed to deserialize task: {}", e); + warn!("response: {}", text); Err(WinstonError::ParseJson(e)) } } diff --git a/discord_bot/src/clickup/move_done.rs b/discord_bot/src/clickup/move_done.rs index 66275c5650..1c90f4b4f2 100644 --- a/discord_bot/src/clickup/move_done.rs +++ b/discord_bot/src/clickup/move_done.rs @@ -1,3 +1,5 @@ +use log::info; + use crate::WinstonError; use super::{get_tasks, update_task, TaskStatus, TasksQuery, UpdateTask}; @@ -8,7 +10,7 @@ pub async fn move_done_to_beta() -> Result<(), WinstonError> { }) .await?; - println!( + info!( "Moving tasks to beta: {}", tasks .tasks diff --git a/discord_bot/src/discord/close_ticket.rs b/discord_bot/src/discord/close_ticket.rs index 63d4e5feec..6e51ed1c32 100644 --- a/discord_bot/src/discord/close_ticket.rs +++ b/discord_bot/src/discord/close_ticket.rs @@ -1,6 +1,7 @@ use std::fmt::{self, Display, Formatter}; use indoc::formatdoc; +use log::{debug, warn}; use poise::{ serenity_prelude::{ ButtonStyle, CacheHttp, ChannelId, CreateButton, CreateEmbed, CreateEmbedFooter, @@ -141,7 +142,7 @@ pub async fn close_ticket( channel.send_message(&ctx, message).await?; if let Err(e) = remove_support_members_from_thread(&ctx, channel.id).await { - eprintln!("Could not remove members from thread: {e}"); + warn!("Could not remove members from thread: {e}"); } channel @@ -181,8 +182,10 @@ where continue; } + debug!("Removing member from thread: {user_id}"); + if let Err(e) = channel_id.remove_thread_member(&ctx, user_id).await { - eprintln!("Could not remove member from thread: {e}"); + warn!("Could not remove member from thread: {e}"); } } @@ -194,13 +197,14 @@ async fn is_support(ctx: &impl CacheHttp, thread_member: ThreadMember) -> bool { Some(member) => member, None => { let Some(guild_id) = thread_member.guild_id else { + warn!("Could not get guild from thread member"); return false; }; let guild = match guild_id.to_partial_guild(&ctx).await { Ok(guild) => guild, Err(e) => { - eprintln!("Could not get guild from thread member: {e}"); + warn!("Could not get guild from thread member: {e}"); return false; } }; @@ -208,7 +212,7 @@ async fn is_support(ctx: &impl CacheHttp, thread_member: ThreadMember) -> bool { match guild.member(ctx, thread_member.user_id).await { Ok(member) => member, Err(e) => { - eprintln!("Could not get member from thread member: {e}"); + warn!("Could not get member from thread member: {e}"); return false; } } diff --git a/discord_bot/src/discord/create_task.rs b/discord_bot/src/discord/create_task.rs index c4ea4c79d6..6b350abc9e 100644 --- a/discord_bot/src/discord/create_task.rs +++ b/discord_bot/src/discord/create_task.rs @@ -3,6 +3,7 @@ use crate::{ clickup::{create_task_in_clickup, TaskPriority, TaskSize, TaskType}, remove_support_members_from_thread, Context, WinstonError, }; +use log::warn; use poise::{ serenity_prelude::{CreateEmbed, CreateMessage}, CreateReply, @@ -80,7 +81,7 @@ pub async fn create_task( .await?; if let Err(e) = remove_support_members_from_thread(&ctx, channel).await { - eprintln!("Could not remove members from thread: {e}"); + warn!("Could not remove members from thread: {e}"); } Ok(()) diff --git a/discord_bot/src/discord/task_fixed.rs b/discord_bot/src/discord/task_fixed.rs index 61e525c40d..184c279ec9 100644 --- a/discord_bot/src/discord/task_fixed.rs +++ b/discord_bot/src/discord/task_fixed.rs @@ -1,6 +1,7 @@ use async_trait::async_trait; use indoc::formatdoc; use itertools::Itertools; +use log::warn; use poise::serenity_prelude::{ ComponentInteraction, Context, EditInteractionResponse, EditMessage, EventHandler, GuildChannel, Interaction, UserId, @@ -29,7 +30,7 @@ impl EventHandler for TaskFixedHandler { } if let Err(err) = component.defer_ephemeral(&ctx).await { - eprintln!("Failed to defer ephemeral: {}", err); + warn!("Failed to defer ephemeral: {}", err); return; } @@ -41,7 +42,7 @@ impl EventHandler for TaskFixedHandler { "Something whent wrong with the button. It seems to be outdated.", ) .await; - eprintln!("Invalid custom_id: {}", custom_id); + warn!("Invalid custom_id: {}", custom_id); return; } let task_status = split[1].to_string(); @@ -71,7 +72,7 @@ impl EventHandler for TaskFixedHandler { "Something whent wrong with the button. It seems to be outdated.", ) .await; - eprintln!("Invalid task status: {}", task_status); + warn!("Invalid task status: {}", task_status); return; } }; @@ -83,7 +84,7 @@ impl EventHandler for TaskFixedHandler { format!("Failed to mark task as {}: {}", task_status, e), ) .await; - eprintln!("Failed to mark task as {}: {}", task_status, e); + warn!("Failed to mark task as {}: {}", task_status, e); return; } } @@ -197,7 +198,7 @@ pub async fn update_response( .await; if let Err(e) = result { - eprintln!("Failed to update response: {}", e); + warn!("Failed to update response: {}", e); } } @@ -212,7 +213,7 @@ pub async fn check_permissions( "Something whent wrong with the button. It seems to be outdated.", ) .await; - eprintln!("No channel found"); + warn!("No channel found"); return None; }; @@ -223,7 +224,7 @@ pub async fn check_permissions( "Something whent wrong with the button. It seems to be outdated.", ) .await; - eprintln!("No guild channel found"); + warn!("No guild channel found"); return None; }; @@ -234,7 +235,7 @@ pub async fn check_permissions( "Something whent wrong with the button. It seems to be outdated.", ) .await; - eprintln!("No owner found for channel: {}", guild_channel.name()); + warn!("No owner found for channel: {}", guild_channel.name()); return None; }; diff --git a/discord_bot/src/discord/thread_archiving.rs b/discord_bot/src/discord/thread_archiving.rs index ec17ecf16f..355899e28e 100644 --- a/discord_bot/src/discord/thread_archiving.rs +++ b/discord_bot/src/discord/thread_archiving.rs @@ -1,4 +1,5 @@ use async_trait::async_trait; +use log::warn; use poise::serenity_prelude::{Context, EditThread, EventHandler, GuildChannel}; use crate::{CloseReason, QUESTIONS_FORUM_ID}; @@ -30,7 +31,7 @@ impl EventHandler for ThreadArchivingHandler { let parent = match parent.to_channel(&ctx).await { Ok(parent) => parent, Err(e) => { - eprintln!("Error getting parent channel: {}", e); + warn!("Error getting parent channel: {}", e); return; } }; @@ -64,7 +65,7 @@ impl EventHandler for ThreadArchivingHandler { .edit_thread(&ctx, EditThread::default().archived(has_close_tag)) .await { - eprintln!("Error editing thread: {}", e); + warn!("Error editing thread: {}", e); return; } } diff --git a/discord_bot/src/discord/thread_cleanup.rs b/discord_bot/src/discord/thread_cleanup.rs index fb07799b7a..ed1025ff29 100644 --- a/discord_bot/src/discord/thread_cleanup.rs +++ b/discord_bot/src/discord/thread_cleanup.rs @@ -1,5 +1,6 @@ use chrono::Duration; use indoc::formatdoc; +use log::{info, warn}; use poise::serenity_prelude::{ model::channel, ButtonStyle, Context, CreateButton, CreateEmbed, CreateMessage, EditThread, ForumTag, ForumTagId, Mentionable, ReactionType, Timestamp, @@ -82,7 +83,7 @@ async fn archive_thread( return Ok(()); } - println!("Archiving thread {} ({})", thread.id, thread.name()); + info!("Archiving thread {} ({})", thread.id, thread.name()); thread .edit_thread(&discord, EditThread::default().archived(true)) @@ -107,7 +108,7 @@ async fn resolve_answered_thread( return Ok(()); } - println!("Auto Resolving thread {} ({})", thread.id, thread.name()); + info!("Auto Resolving thread {} ({})", thread.id, thread.name()); // Close the thread let Some(resolved_tag) = available_tags.get_tag_id("resolved") else { @@ -145,7 +146,7 @@ async fn resolve_answered_thread( .await?; if let Err(e) = remove_support_members_from_thread(&discord, thread.id).await { - eprintln!("Could not remove members from thread: {e}"); + warn!("Could not remove members from thread: {e}"); } Ok(()) @@ -166,7 +167,7 @@ async fn reask_verification( return Ok(()); } - println!( + info!( "Reasking verification for thread {} ({})", thread.id, thread.name() diff --git a/discord_bot/src/discord/thread_closed_blocker.rs b/discord_bot/src/discord/thread_closed_blocker.rs index 9d4d0411a2..1a5687dc78 100644 --- a/discord_bot/src/discord/thread_closed_blocker.rs +++ b/discord_bot/src/discord/thread_closed_blocker.rs @@ -1,5 +1,6 @@ use async_trait::async_trait; use indoc::formatdoc; +use log::warn; use poise::serenity_prelude::{ Context, CreateMessage, EditMessage, EventHandler, Mentionable, Message, }; @@ -31,7 +32,7 @@ impl EventHandler for ThreadClosedBlockerHandler { let parent = match parent.to_channel(&ctx).await { Ok(parent) => parent, Err(e) => { - eprintln!("Error getting parent channel: {}", e); + warn!("Error getting parent channel: {}", e); return; } }; @@ -80,14 +81,14 @@ impl EventHandler for ThreadClosedBlockerHandler { .await; if let Err(e) = new_message.delete(&ctx).await { - eprintln!("Error deleting message: {}", e); + warn!("Error deleting message: {}", e); return; } let mut error_message = match error_message { Ok(error_message) => error_message, Err(e) => { - eprintln!("Error sending error message: {}", e); + warn!("Error sending error message: {}", e); return; } }; @@ -114,7 +115,7 @@ impl EventHandler for ThreadClosedBlockerHandler { ) .await { - eprintln!("Error editing error message: {}", e); + warn!("Error editing error message: {}", e); return; } @@ -122,7 +123,7 @@ impl EventHandler for ThreadClosedBlockerHandler { } if let Err(e) = error_message.delete(&ctx).await { - eprintln!("Error deleting error message: {}", e); + warn!("Error deleting error message: {}", e); return; } } diff --git a/discord_bot/src/discord/thread_support_answering.rs b/discord_bot/src/discord/thread_support_answering.rs index aabb7a8725..3c6725d3ef 100644 --- a/discord_bot/src/discord/thread_support_answering.rs +++ b/discord_bot/src/discord/thread_support_answering.rs @@ -1,5 +1,6 @@ use async_trait::async_trait; use chrono::Utc; +use log::{info, warn}; use poise::{ serenity_prelude::{ Colour, Context, CreateAllowedMentions, CreateEmbed, CreateMessage, EditThread, @@ -30,7 +31,7 @@ impl EventHandler for SupportAnsweringHandler { let parent = match parent.to_channel(&ctx).await { Ok(parent) => parent, Err(e) => { - eprintln!("Error getting parent channel: {}", e); + warn!("Error getting parent channel: {}", e); return; } }; @@ -45,12 +46,12 @@ impl EventHandler for SupportAnsweringHandler { let available_tags = parent.available_tags; let Some(support_tag) = available_tags.get_tag_id("support") else { - eprintln!("Support tag not found in available tags"); + warn!("Support tag not found in available tags"); return; }; let Some(pending_tag) = available_tags.get_tag_id("pending") else { - eprintln!("Pending tag not found in available tags"); + warn!("Pending tag not found in available tags"); return; }; thread @@ -133,7 +134,7 @@ impl EventHandler for SupportAnsweringHandler { let parent = match parent.to_channel(&ctx).await { Ok(parent) => parent, Err(e) => { - eprintln!("Error getting parent channel: {}", e); + warn!("Error getting parent channel: {}", e); return; } }; @@ -148,7 +149,7 @@ impl EventHandler for SupportAnsweringHandler { let available_tags = parent.available_tags; let Some(support_tag) = available_tags.get_tag_id("support") else { - eprintln!("Support tag not found in available tags"); + warn!("Support tag not found in available tags"); return; }; @@ -157,12 +158,12 @@ impl EventHandler for SupportAnsweringHandler { } let Some(answered_tag) = available_tags.get_tag_id("answered") else { - eprintln!("Answered tag not found in available tags"); + warn!("Answered tag not found in available tags"); return; }; let Some(pending_tag) = available_tags.get_tag_id("pending") else { - eprintln!("Pending tag not found in available tags"); + warn!("Pending tag not found in available tags"); return; }; @@ -174,12 +175,12 @@ impl EventHandler for SupportAnsweringHandler { Ok(true) => true, Ok(false) => false, Err(e) => { - eprintln!("Error while handling error: {}", e); + warn!("Error while handling error: {}", e); return; } }; - println!( + info!( "Marking thread {} ({}) as {}", thread.id, thread.name(), @@ -232,7 +233,7 @@ pub async fn support_answering( // Check if the ticket has the support tag let Some(support_tag) = available_tags.get_tag_id("support") else { - eprintln!("Support tag not found in available tags"); + warn!("Support tag not found in available tags"); return Err(WinstonError::TagNotFound("support".to_string())); }; @@ -251,7 +252,7 @@ pub async fn support_answering( let target_tag_name = if answered { "answered" } else { "pending" }; let Some(target_tag) = available_tags.get_tag_id(target_tag_name) else { - eprintln!("Target tag not found in available tags"); + warn!("Target tag not found in available tags"); return Err(WinstonError::TagNotFound(target_tag_name.to_string())); }; diff --git a/discord_bot/src/discord/ticket_reopen.rs b/discord_bot/src/discord/ticket_reopen.rs index ea396c3304..b5d9baa435 100644 --- a/discord_bot/src/discord/ticket_reopen.rs +++ b/discord_bot/src/discord/ticket_reopen.rs @@ -1,11 +1,12 @@ use async_trait::async_trait; use indoc::formatdoc; +use log::warn; use poise::serenity_prelude::{ ComponentInteraction, Context, CreateEmbed, CreateInteractionResponseFollowup, CreateMessage, CreateQuickModal, EditThread, EventHandler, Interaction, Timestamp, }; -use crate::{check_permissions, webhooks::GetTagId, SUPPORT_ROLE_ID, QUESTIONS_FORUM_ID}; +use crate::{check_permissions, webhooks::GetTagId, QUESTIONS_FORUM_ID, SUPPORT_ROLE_ID}; pub struct TicketReopenHandler; @@ -36,7 +37,7 @@ impl EventHandler for TicketReopenHandler { Ok(Some(responds)) if responds.inputs.len() > 0 => responds, Err(err) => { send_followup(&ctx, &component, "Failed to open modal").await; - eprintln!("Failed to open modal: {}", err); + warn!("Failed to open modal: {}", err); return; } _ => { @@ -58,7 +59,7 @@ impl EventHandler for TicketReopenHandler { ) .await { - eprintln!("Failed to acknowledge interaction: {}", e); + warn!("Failed to acknowledge interaction: {}", e); return; } @@ -70,7 +71,7 @@ impl EventHandler for TicketReopenHandler { let parent = match parent.to_channel(&ctx).await { Ok(parent) => parent, Err(e) => { - eprintln!("Error getting parent channel: {}", e); + warn!("Error getting parent channel: {}", e); return; } }; @@ -86,12 +87,12 @@ impl EventHandler for TicketReopenHandler { let available_tags = parent.available_tags; let Some(support_tag) = available_tags.get_tag_id("support") else { - eprintln!("Support tag not found in available tags"); + warn!("Support tag not found in available tags"); return; }; let Some(pending_tag) = available_tags.get_tag_id("pending") else { - eprintln!("Pending tag not found in available tags"); + warn!("Pending tag not found in available tags"); return; }; @@ -106,7 +107,7 @@ impl EventHandler for TicketReopenHandler { .await { send_followup(&ctx, &component, "Failed to reopen ticket").await; - eprintln!("Failed to edit thread: {}", e); + warn!("Failed to edit thread: {}", e); return; } @@ -133,13 +134,13 @@ impl EventHandler for TicketReopenHandler { .await { send_followup(&ctx, &component, "Failed to reopen ticket").await; - eprintln!("Failed to send new message: {}", e); + warn!("Failed to send new message: {}", e); return; } if let Err(e) = component.message.delete(&ctx).await { send_followup(&ctx, &component, "Failed to reopen ticket").await; - eprintln!("Failed to delete old message: {}", e); + warn!("Failed to delete old message: {}", e); return; } } @@ -155,6 +156,6 @@ async fn send_followup(ctx: &Context, interaction: &ComponentInteraction, conten ) .await { - eprintln!("Failed to send followup: {}", e); + warn!("Failed to send followup: {}", e); } } diff --git a/discord_bot/src/main.rs b/discord_bot/src/main.rs index 179884fd82..4f18f03a18 100644 --- a/discord_bot/src/main.rs +++ b/discord_bot/src/main.rs @@ -1,6 +1,7 @@ use std::sync::Arc; use actix_web::{middleware::Logger, App, HttpServer}; +use log::{error, info, warn}; use once_cell::sync::Lazy; use poise::serenity_prelude::{self as serenity, GatewayIntents, Mentionable}; use tokio::signal; @@ -62,6 +63,7 @@ static DISCORD_CLIENT: Lazy>> = #[tokio::main] async fn main() { dotenv::dotenv().ok(); + env_logger::init(); let token = CancellationToken::new(); let webhook_token = token.clone(); @@ -91,11 +93,11 @@ async fn main() { match signal::ctrl_c().await { Ok(()) => { - println!("\nShutting down..."); + info!("\nShutting down..."); token.cancel(); } Err(err) => { - eprintln!("Unable to listen for shutdown signal: {}", err); + error!("Unable to listen for shutdown signal: {}", err); token.cancel(); } } @@ -107,7 +109,7 @@ async fn main() { async fn startup_webhook() { // env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); - println!("Starting webhook server..."); + info!("Starting webhook server..."); HttpServer::new(|| { App::new() .wrap(Logger::default()) @@ -161,7 +163,7 @@ async fn startup_discord_bot() { .event_handler(ThreadClosedBlockerHandler) .await; - println!("Starting bot..."); + info!("Starting bot..."); client .unwrap() @@ -173,17 +175,17 @@ async fn startup_discord_bot() { async fn schedule_task() { let mut fail_count = 0; loop { - println!("Running schedule task..."); + info!("Running schedule task..."); let wait_time = if let Err(e) = cleanup_threads().await { - eprintln!("Failed to run cleanup task: {}", e); + warn!("Failed to run cleanup task: {}", e); fail_count += 1; 30 * 2u64.pow(fail_count) } else { - println!("Cleanup task completed"); + info!("Cleanup task completed"); fail_count = 0; 60 * 60 }; - println!("Waiting for {} seconds before running again", wait_time); + info!("Waiting for {} seconds before running again", wait_time); tokio::time::sleep(std::time::Duration::from_secs(wait_time)).await; } } @@ -192,11 +194,11 @@ async fn on_error(error: poise::FrameworkError<'_, Data, WinstonError>) { match error { poise::FrameworkError::Setup { error, .. } => panic!("Failed to start bot: {:?}", error), poise::FrameworkError::Command { error, ctx, .. } => { - eprintln!("Error in command `{}`: {:?}", ctx.command().name, error,); + warn!("Error in command `{}`: {:?}", ctx.command().name, error,); } error => { if let Err(e) = poise::builtins::on_error(error).await { - eprintln!("Error while handling error: {}", e) + warn!("Error while handling error: {}", e) } } } @@ -217,7 +219,7 @@ pub async fn check_has_role( let has_role = ctx.author().has_role(ctx, GUILD_ID, role_id).await?; if !has_role { - eprintln!( + warn!( "User {} is not a {} and tried to run command", ctx.author().name, role_id.mention(), diff --git a/discord_bot/src/webhook.rs b/discord_bot/src/webhook.rs index 7f79b30401..91522501d3 100644 --- a/discord_bot/src/webhook.rs +++ b/discord_bot/src/webhook.rs @@ -1,5 +1,6 @@ use actix_web::{web::Bytes, HttpRequest, HttpResponse, Responder}; use hmac::{Hmac, Mac}; +use log::{debug, warn}; use serde::{Deserialize, Serialize}; use sha2::Sha256; @@ -32,7 +33,7 @@ pub async fn publish_beta_version(req: HttpRequest) -> impl Responder { match move_done_to_beta().await { Ok(_) => HttpResponse::Ok().body("ok"), Err(e) => { - eprintln!("failed to move tasks to beta: {}", e); + warn!("failed to move tasks to beta: {}", e); HttpResponse::InternalServerError().body(format!("failed to move tasks to beta: {}", e)) } } @@ -61,13 +62,13 @@ pub async fn clickup_webhook(req: HttpRequest, bytes: Bytes) -> impl Responder { }; let Ok(signature) = hex::decode(new_signature.trim()) else { - eprintln!("failed to decode signature"); + warn!("failed to decode signature"); return HttpResponse::BadRequest() .body("failed to decode signature") .into(); }; if let Err(_) = mac.verify_slice(&signature) { - eprintln!("invalid signature: {:?}", signature); + warn!("invalid signature: {:?}", signature); return HttpResponse::Unauthorized() .body("invalid signature") .into(); @@ -75,7 +76,7 @@ pub async fn clickup_webhook(req: HttpRequest, bytes: Bytes) -> impl Responder { let event: Event = serde_json::from_slice(&bytes).expect("failed to deserialize event"); - println!("Received Event: {:?}", event); + debug!("Received Event: {:?}", event); let result = match event { Event::TaskCreated(e) => crate::webhooks::handle_task_created(e).await, @@ -85,7 +86,7 @@ pub async fn clickup_webhook(req: HttpRequest, bytes: Bytes) -> impl Responder { }; if let Err(e) = result { - eprintln!("failed to handle event: {}", e); + warn!("failed to handle event: {}", e); return HttpResponse::InternalServerError() .body(format!("failed to handle event: {}", e)) .into();