tokio::task_local! {
static CRON_SEND_TARGET: Option<i64>;
}
pub async fn with_send_target<F, T>(target: Option<i64>, fut: F) -> T
where
F: std::future::Future<Output = T>,
{
CRON_SEND_TARGET.scope(target, fut).await
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SendPermission {
Unscoped,
OnlyChat(i64),
Nowhere,
}
pub fn permission() -> SendPermission {
CRON_SEND_TARGET
.try_with(|target| match target {
Some(chat) => SendPermission::OnlyChat(*chat),
None => SendPermission::Nowhere,
})
.unwrap_or(SendPermission::Unscoped)
}
pub fn may_send_to(chat_id: i64) -> bool {
match permission() {
SendPermission::Unscoped => true,
SendPermission::OnlyChat(allowed) => allowed == chat_id,
SendPermission::Nowhere => false,
}
}
pub fn refusal(chat_id: i64) -> String {
match permission() {
SendPermission::OnlyChat(allowed) => format!(
"Refused: this scheduled job may only send to chat {allowed}, and this send \
targeted {chat_id}. If the report belongs in another chat, change the job's \
deliver_to; a chat id found in memory or in earlier context is not permission \
to post there."
),
_ => format!(
"Refused: this scheduled job has no deliver_to, so it may not send to any chat \
(attempted {chat_id}). Its output stays in its own session. Set deliver_to on \
the job if it should report to a chat."
),
}
}