feat: move over to using the "mbwatch" group for watchers
Now mbwatch will look for a group called "mbwatch" to find what channels and mailboxes to watch. This allows the user to be move specific in what they are watching. You don't always need to watch the "INBOX" nor do you have to watch all of the channels you have setup in with mbsync. The config will need to be defined in the `Channels` prop on the group. It needs to be a comma separated of channels and mailboxes. This is an example of the config. ``` Group mbwatch Channels work:INBOX, work:Archive, personal:INBOX ```
This commit is contained in:
parent
7549d36192
commit
30d34ce171
2 changed files with 80 additions and 10 deletions
|
|
@ -40,17 +40,24 @@ impl ImapStoreConfig {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct ChannelConfig {
|
||||
pub name: String,
|
||||
pub near: String,
|
||||
pub far: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct GroupConfig {
|
||||
pub name: String,
|
||||
pub channels: Vec<(String, String)>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Config {
|
||||
pub channels: Vec<ChannelConfig>,
|
||||
pub imap_stores: Vec<ImapStoreConfig>,
|
||||
pub groups: Vec<GroupConfig>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
|
|
@ -60,6 +67,20 @@ impl Config {
|
|||
.find(|store| format!(":{}:", store.name) == name)
|
||||
.map(|store| store.clone())
|
||||
}
|
||||
|
||||
pub fn find_channel(&self, name: &str) -> Option<ChannelConfig> {
|
||||
self.channels
|
||||
.iter()
|
||||
.find(|channel| channel.name == name)
|
||||
.map(|channel| channel.clone())
|
||||
}
|
||||
|
||||
pub fn find_group(&self, name: &str) -> Option<GroupConfig> {
|
||||
self.groups
|
||||
.iter()
|
||||
.find(|group| group.name == name)
|
||||
.map(|group| group.clone())
|
||||
}
|
||||
}
|
||||
|
||||
enum ConfigLine {
|
||||
|
|
@ -75,6 +96,9 @@ enum ConfigLine {
|
|||
Near(String),
|
||||
Far(String),
|
||||
|
||||
Group(String),
|
||||
Channels(String),
|
||||
|
||||
End,
|
||||
}
|
||||
|
||||
|
|
@ -97,6 +121,9 @@ impl TryFrom<&str> for ConfigLine {
|
|||
"Near" => Ok(ConfigLine::Near(value)),
|
||||
"Far" => Ok(ConfigLine::Far(value)),
|
||||
|
||||
"Group" => Ok(ConfigLine::Group(value)),
|
||||
"Channels" => Ok(ConfigLine::Channels(value)),
|
||||
|
||||
_ => {
|
||||
if value == "" {
|
||||
return Ok(ConfigLine::End);
|
||||
|
|
@ -143,7 +170,7 @@ pub fn from_file(config_path: &str) -> Config {
|
|||
ConfigLine::ImapStore(name) => {
|
||||
let mut imap_store_config = ImapStoreConfig::default();
|
||||
imap_store_config.name = name;
|
||||
config.imap_stores.push(imap_store_config)
|
||||
config.imap_stores.push(imap_store_config);
|
||||
}
|
||||
ConfigLine::Host(host) => {
|
||||
let store = config.imap_stores.last_mut().unwrap();
|
||||
|
|
@ -184,6 +211,27 @@ pub fn from_file(config_path: &str) -> Config {
|
|||
channel.near = near;
|
||||
}
|
||||
|
||||
ConfigLine::Group(name) => {
|
||||
let mut group = GroupConfig::default();
|
||||
group.name = name;
|
||||
|
||||
config.groups.push(group);
|
||||
}
|
||||
ConfigLine::Channels(channels) => {
|
||||
let group = config.groups.last_mut().unwrap();
|
||||
group.channels = channels
|
||||
.split(',')
|
||||
.map(|channel| {
|
||||
let mut iter = channel.trim().split(':');
|
||||
|
||||
(
|
||||
iter.next().unwrap_or("").to_string(),
|
||||
iter.next().unwrap_or("").to_string(),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
|
||||
ConfigLine::End => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
38
src/main.rs
38
src/main.rs
|
|
@ -6,7 +6,7 @@ use std::thread;
|
|||
use config::ImapStoreConfig;
|
||||
use imap::{ImapConnection, Session};
|
||||
|
||||
fn connect(config: &ImapStoreConfig) -> Option<Session<Box<dyn ImapConnection>>> {
|
||||
fn connect(config: &ImapStoreConfig, mailbox: &String) -> Option<Session<Box<dyn ImapConnection>>> {
|
||||
let mut client_builder = imap::ClientBuilder::new(config.host.clone(), config.port())
|
||||
.mode(imap::ConnectionMode::AutoTls)
|
||||
.tls_kind(imap::TlsKind::Rust);
|
||||
|
|
@ -38,7 +38,7 @@ fn connect(config: &ImapStoreConfig) -> Option<Session<Box<dyn ImapConnection>>>
|
|||
return None;
|
||||
}
|
||||
|
||||
session.select("INBOX").expect("Unable to select folder");
|
||||
session.select(mailbox).expect("Unable to select folder");
|
||||
|
||||
Some(session)
|
||||
}
|
||||
|
|
@ -56,18 +56,32 @@ fn main() {
|
|||
};
|
||||
|
||||
let config = config::from_file(&format!("{home}/.mbsyncrc"));
|
||||
let mbwatch_group = match config.find_group("mbwatch") {
|
||||
Some(group) => group,
|
||||
None => panic!("Unable to find mbwatch group in your mbsync config"),
|
||||
};
|
||||
|
||||
let mut watchers = Vec::new();
|
||||
|
||||
for channel in &config.channels {
|
||||
for (channel_name, mailbox) in &mbwatch_group.channels {
|
||||
let channel = match config.find_channel(channel_name) {
|
||||
Some(channel) => channel,
|
||||
None => panic!("Unable to find channel {}", channel_name),
|
||||
};
|
||||
|
||||
if mailbox.is_empty() {
|
||||
panic!("No mailbox defined for channel {}", channel_name);
|
||||
}
|
||||
|
||||
let imap_store = match config.find_imap_store(&channel.far) {
|
||||
Some(store) => store,
|
||||
None => panic!("Unable to find store {}", &channel.far),
|
||||
};
|
||||
|
||||
let channel_name = channel.name.clone();
|
||||
let mailbox = mailbox.clone();
|
||||
watchers.push(thread::spawn(move || {
|
||||
let mut session = match connect(&imap_store) {
|
||||
let mut session = match connect(&imap_store, &mailbox) {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
log::error!("Unable to connect to channel {}", channel_name);
|
||||
|
|
@ -75,7 +89,11 @@ fn main() {
|
|||
}
|
||||
};
|
||||
|
||||
log::info!("Watching for messages on channel {}", channel_name);
|
||||
log::info!(
|
||||
"Watching for messages on channel {} in mailbox {}",
|
||||
channel_name,
|
||||
mailbox
|
||||
);
|
||||
|
||||
loop {
|
||||
let result = session
|
||||
|
|
@ -86,15 +104,19 @@ fn main() {
|
|||
log::error!("Error while idling: {:?}", result);
|
||||
|
||||
thread::sleep(std::time::Duration::from_secs(10));
|
||||
session = connect(&imap_store).unwrap();
|
||||
session = connect(&imap_store, &mailbox).unwrap();
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
log::info!("Syncing changes for {}", channel_name);
|
||||
log::info!(
|
||||
"Syncing changes for {} in mailbox {}",
|
||||
channel_name,
|
||||
mailbox
|
||||
);
|
||||
|
||||
Command::new("mbsync")
|
||||
.args(["--all", &format!("{}:INBOX", channel_name)])
|
||||
.args(["--all", &format!("{}:{}", channel_name, mailbox)])
|
||||
.output()
|
||||
.expect("Unable to sync mail");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue