mirror of
https://github.com/soywod/himalaya.git
synced 2024-11-24 20:10:23 +00:00
init folder watch command
This commit is contained in:
parent
a68d297366
commit
7fccdd822a
9 changed files with 329 additions and 7 deletions
215
Cargo.lock
generated
215
Cargo.lock
generated
|
@ -188,6 +188,32 @@ dependencies = [
|
|||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-executor"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c"
|
||||
dependencies = [
|
||||
"async-lock 3.2.0",
|
||||
"async-task",
|
||||
"concurrent-queue",
|
||||
"fastrand 2.0.1",
|
||||
"futures-lite 2.1.0",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-fs"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06"
|
||||
dependencies = [
|
||||
"async-lock 2.8.0",
|
||||
"autocfg",
|
||||
"blocking",
|
||||
"futures-lite 1.13.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-io"
|
||||
version = "1.13.0"
|
||||
|
@ -390,6 +416,12 @@ version = "2.4.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||
|
||||
[[package]]
|
||||
name = "block"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
|
@ -834,9 +866,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.16"
|
||||
version = "0.8.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
|
||||
checksum = "c06d96137f14f244c37f989d9fff8f95e6c18b918e71f36638f8c49112e4c78f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
@ -1096,6 +1128,16 @@ dependencies = [
|
|||
"dirs-sys 0.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-next"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"dirs-sys-next",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.3.7"
|
||||
|
@ -1119,6 +1161,17 @@ dependencies = [
|
|||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys-next"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dunce"
|
||||
version = "1.0.4"
|
||||
|
@ -1193,8 +1246,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "email-lib"
|
||||
version = "0.17.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "743371f76482a94403ce0ab49da129065fc84cbcf9ed126524882c6ed5389efc"
|
||||
source = "git+https://git.sr.ht/~soywod/pimalaya#8fb9b5ecc417a34a824a6decc3c0cda01af98ffe"
|
||||
dependencies = [
|
||||
"advisory-lock",
|
||||
"anyhow",
|
||||
|
@ -1213,6 +1265,8 @@ dependencies = [
|
|||
"maildirpp",
|
||||
"md5",
|
||||
"mml-lib",
|
||||
"notify",
|
||||
"notify-rust",
|
||||
"notmuch",
|
||||
"oauth-lib",
|
||||
"once_cell",
|
||||
|
@ -1546,7 +1600,10 @@ version = "2.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aeee267a1883f7ebef3700f262d2d54de95dfaf38189015a74fdc4e0c7ad8143"
|
||||
dependencies = [
|
||||
"fastrand 2.0.1",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"parking",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
|
@ -2090,7 +2147,7 @@ dependencies = [
|
|||
"dirs 4.0.0",
|
||||
"gix-path",
|
||||
"libc",
|
||||
"windows",
|
||||
"windows 0.43.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2629,6 +2686,26 @@ dependencies = [
|
|||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inotify"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"inotify-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inotify-sys"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inout"
|
||||
version = "0.1.3"
|
||||
|
@ -2748,6 +2825,26 @@ dependencies = [
|
|||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kqueue"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c"
|
||||
dependencies = [
|
||||
"kqueue-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kqueue-sys"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
|
@ -2855,6 +2952,19 @@ dependencies = [
|
|||
"linked-hash-map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mac-notification-sys"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51fca4d74ff9dbaac16a01b924bc3693fa2bba0862c2c633abc73f9a8ea21f64"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"dirs-next",
|
||||
"objc-foundation",
|
||||
"objc_id",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mail-auth"
|
||||
version = "0.3.6"
|
||||
|
@ -2925,6 +3035,15 @@ dependencies = [
|
|||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "malloc_buf"
|
||||
version = "0.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "match_cfg"
|
||||
version = "0.1.0"
|
||||
|
@ -3008,6 +3127,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
@ -3063,6 +3183,36 @@ dependencies = [
|
|||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "notify"
|
||||
version = "6.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"filetime",
|
||||
"inotify",
|
||||
"kqueue",
|
||||
"libc",
|
||||
"log",
|
||||
"mio",
|
||||
"walkdir",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "notify-rust"
|
||||
version = "4.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "827c5edfa80235ded4ab3fe8e9dc619b4f866ef16fe9b1c6b8a7f8692c0f2226"
|
||||
dependencies = [
|
||||
"log",
|
||||
"mac-notification-sys",
|
||||
"serde",
|
||||
"tauri-winrt-notification",
|
||||
"zbus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "notmuch"
|
||||
version = "0.8.0"
|
||||
|
@ -3238,6 +3388,35 @@ dependencies = [
|
|||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
|
||||
dependencies = [
|
||||
"malloc_buf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc-foundation"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
|
||||
dependencies = [
|
||||
"block",
|
||||
"objc",
|
||||
"objc_id",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc_id"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b"
|
||||
dependencies = [
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.32.1"
|
||||
|
@ -4545,6 +4724,16 @@ version = "0.12.12"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a"
|
||||
|
||||
[[package]]
|
||||
name = "tauri-winrt-notification"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "006851c9ccefa3c38a7646b8cec804bb429def3da10497bfa977179869c3e8e2"
|
||||
dependencies = [
|
||||
"quick-xml",
|
||||
"windows 0.51.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.8.1"
|
||||
|
@ -5152,6 +5341,16 @@ dependencies = [
|
|||
"windows_x86_64_msvc 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.51.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.51.1"
|
||||
|
@ -5422,9 +5621,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "31de390a2d872e4cd04edd71b425e29853f786dc99317ed72d73d6fcf5ebb948"
|
||||
dependencies = [
|
||||
"async-broadcast",
|
||||
"async-executor",
|
||||
"async-fs",
|
||||
"async-io 1.13.0",
|
||||
"async-lock 2.8.0",
|
||||
"async-process",
|
||||
"async-recursion",
|
||||
"async-task",
|
||||
"async-trait",
|
||||
"blocking",
|
||||
"byteorder",
|
||||
"derivative",
|
||||
"enumflags2",
|
||||
|
|
|
@ -50,7 +50,7 @@ clap_mangen = "0.2"
|
|||
console = "0.15.2"
|
||||
dialoguer = "0.10.2"
|
||||
dirs = "4.0"
|
||||
email-lib = { version = "=0.17.1", default-features = false }
|
||||
email-lib = { git = "https://git.sr.ht/~soywod/pimalaya", default-features = false }
|
||||
email_address = "0.2.4"
|
||||
env_logger = "0.8"
|
||||
erased-serde = "0.3"
|
||||
|
|
|
@ -44,6 +44,13 @@ envelope.list.backend = "imap"
|
|||
# Override the backend used for sending messages.
|
||||
message.send.backend = "smtp"
|
||||
|
||||
# Send notification when receiving new messages
|
||||
message.watch.received.notify.summary = "📬 New message from {sender}"
|
||||
message.watch.received.notify.body = "{subject}"
|
||||
|
||||
# Shell commands can also be executed
|
||||
# message.watch.received.cmd = "mbsync -a"
|
||||
|
||||
# IMAP config
|
||||
imap.host = "localhost"
|
||||
imap.port = 3143
|
||||
|
|
|
@ -191,6 +191,14 @@ impl TomlAccountConfig {
|
|||
.or_else(|| self.backend.as_ref())
|
||||
}
|
||||
|
||||
pub fn get_watch_message_kind(&self) -> Option<&BackendKind> {
|
||||
self.message
|
||||
.as_ref()
|
||||
.and_then(|msg| msg.watch.as_ref())
|
||||
.and_then(|watch| watch.backend.as_ref())
|
||||
.or_else(|| self.backend.as_ref())
|
||||
}
|
||||
|
||||
pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
|
||||
let mut used_backends = HashSet::default();
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ use email::imap::{ImapSessionBuilder, ImapSessionSync};
|
|||
use email::smtp::{SmtpClientBuilder, SmtpClientSync};
|
||||
use email::{
|
||||
account::config::AccountConfig,
|
||||
email::watch::{imap::WatchImapEmails, maildir::WatchMaildirEmails},
|
||||
envelope::{
|
||||
get::{imap::GetEnvelopeImap, maildir::GetEnvelopeMaildir},
|
||||
list::{imap::ListEnvelopesImap, maildir::ListEnvelopesMaildir},
|
||||
|
@ -355,6 +356,33 @@ impl BackendBuilder {
|
|||
_ => (),
|
||||
}
|
||||
|
||||
match toml_account_config.backend {
|
||||
Some(BackendKind::Maildir) => {
|
||||
backend_builder = backend_builder.with_watch_emails(|ctx| {
|
||||
ctx.maildir.as_ref().and_then(WatchMaildirEmails::new)
|
||||
});
|
||||
}
|
||||
Some(BackendKind::MaildirForSync) => {
|
||||
backend_builder = backend_builder.with_watch_emails(|ctx| {
|
||||
ctx.maildir_for_sync
|
||||
.as_ref()
|
||||
.and_then(WatchMaildirEmails::new)
|
||||
});
|
||||
}
|
||||
#[cfg(feature = "imap")]
|
||||
Some(BackendKind::Imap) => {
|
||||
backend_builder = backend_builder
|
||||
.with_watch_emails(|ctx| ctx.imap.as_ref().and_then(WatchImapEmails::new));
|
||||
}
|
||||
#[cfg(feature = "notmuch")]
|
||||
Some(BackendKind::Notmuch) => {
|
||||
backend_builder = backend_builder.with_watch_emails(|ctx| {
|
||||
ctx.notmuch.as_ref().and_then(WatchNotmuchEmails::new)
|
||||
});
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
match toml_account_config.get_envelope_kind() {
|
||||
Some(BackendKind::Maildir) => {
|
||||
backend_builder = backend_builder.with_get_envelope(|ctx| {
|
||||
|
|
|
@ -211,6 +211,7 @@ impl TomlConfig {
|
|||
read: c.read.map(|c| c.remote),
|
||||
write: c.write.map(|c| c.remote),
|
||||
send: c.send.map(|c| c.remote),
|
||||
watch: c.watch.map(|c| c.remote),
|
||||
}),
|
||||
sync: config.sync,
|
||||
#[cfg(feature = "pgp")]
|
||||
|
|
|
@ -12,6 +12,8 @@ pub struct MessageConfig {
|
|||
pub copy: Option<MessageCopyConfig>,
|
||||
#[serde(rename = "move")]
|
||||
pub move_: Option<MessageMoveConfig>,
|
||||
|
||||
pub watch: Option<WatchMessageConfig>,
|
||||
}
|
||||
|
||||
impl MessageConfig {
|
||||
|
@ -42,6 +44,10 @@ impl MessageConfig {
|
|||
kinds.extend(move_.get_used_backends());
|
||||
}
|
||||
|
||||
if let Some(watch) = &self.watch {
|
||||
kinds.extend(watch.get_used_backends());
|
||||
}
|
||||
|
||||
kinds
|
||||
}
|
||||
}
|
||||
|
@ -156,3 +162,23 @@ impl MessageMoveConfig {
|
|||
kinds
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
|
||||
pub struct WatchMessageConfig {
|
||||
pub backend: Option<BackendKind>,
|
||||
|
||||
#[serde(flatten)]
|
||||
pub remote: email::message::watch::config::WatchMessageConfig,
|
||||
}
|
||||
|
||||
impl WatchMessageConfig {
|
||||
pub fn get_used_backends(&self) -> HashSet<&BackendKind> {
|
||||
let mut kinds = HashSet::default();
|
||||
|
||||
if let Some(kind) = &self.backend {
|
||||
kinds.insert(kind);
|
||||
}
|
||||
|
||||
kinds
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ mod delete;
|
|||
mod expunge;
|
||||
mod list;
|
||||
mod purge;
|
||||
mod watch;
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::Subcommand;
|
||||
|
@ -11,7 +12,7 @@ use crate::{config::TomlConfig, printer::Printer};
|
|||
|
||||
use self::{
|
||||
create::FolderCreateCommand, delete::FolderDeleteCommand, expunge::FolderExpungeCommand,
|
||||
list::FolderListCommand, purge::FolderPurgeCommand,
|
||||
list::FolderListCommand, purge::FolderPurgeCommand, watch::FolderWatchCommand,
|
||||
};
|
||||
|
||||
/// Manage folders.
|
||||
|
@ -26,6 +27,9 @@ pub enum FolderSubcommand {
|
|||
#[command(alias = "lst")]
|
||||
List(FolderListCommand),
|
||||
|
||||
#[command()]
|
||||
Watch(FolderWatchCommand),
|
||||
|
||||
#[command()]
|
||||
Expunge(FolderExpungeCommand),
|
||||
|
||||
|
@ -41,6 +45,7 @@ impl FolderSubcommand {
|
|||
match self {
|
||||
Self::Create(cmd) => cmd.execute(printer, config).await,
|
||||
Self::List(cmd) => cmd.execute(printer, config).await,
|
||||
Self::Watch(cmd) => cmd.execute(printer, config).await,
|
||||
Self::Expunge(cmd) => cmd.execute(printer, config).await,
|
||||
Self::Purge(cmd) => cmd.execute(printer, config).await,
|
||||
Self::Delete(cmd) => cmd.execute(printer, config).await,
|
||||
|
|
42
src/folder/command/watch.rs
Normal file
42
src/folder/command/watch.rs
Normal file
|
@ -0,0 +1,42 @@
|
|||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
use log::info;
|
||||
|
||||
use crate::{
|
||||
account::arg::name::AccountNameFlag, backend::Backend, cache::arg::disable::CacheDisableFlag,
|
||||
config::TomlConfig, folder::arg::name::FolderNameArg, printer::Printer,
|
||||
};
|
||||
|
||||
/// Watch a folder for changes.
|
||||
///
|
||||
/// This command allows you to watch a new folder using the given
|
||||
/// name.
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct FolderWatchCommand {
|
||||
#[command(flatten)]
|
||||
pub folder: FolderNameArg,
|
||||
|
||||
#[command(flatten)]
|
||||
pub cache: CacheDisableFlag,
|
||||
|
||||
#[command(flatten)]
|
||||
pub account: AccountNameFlag,
|
||||
}
|
||||
|
||||
impl FolderWatchCommand {
|
||||
pub async fn execute(self, printer: &mut impl Printer, config: &TomlConfig) -> Result<()> {
|
||||
info!("executing folder watch command");
|
||||
|
||||
let folder = &self.folder.name;
|
||||
|
||||
let some_account_name = self.account.name.as_ref().map(String::as_str);
|
||||
let (toml_account_config, account_config) = config
|
||||
.clone()
|
||||
.into_account_configs(some_account_name, self.cache.disable)?;
|
||||
let backend = Backend::new(toml_account_config, account_config.clone(), false).await?;
|
||||
|
||||
printer.print_log(format!("Start watching folder {folder} for changes…"))?;
|
||||
|
||||
backend.watch_emails(&folder).await
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue