various small cleanups

This commit is contained in:
ranfdev
2023-10-27 11:30:24 +02:00
parent 04c3f86a4b
commit d93356905c
6 changed files with 54 additions and 77 deletions

View File

@ -26,11 +26,9 @@ impl Db {
Ok(this) Ok(this)
} }
fn migrate(&mut self) -> Result<()> { fn migrate(&mut self) -> Result<()> {
{ self.conn
self.conn .borrow()
.borrow() .execute_batch(include_str!("./migrations/00.sql"))?;
.execute_batch(include_str!("./migrations/00.sql"))?
};
Ok(()) Ok(())
} }
fn get_or_insert_server(&mut self, server: &str) -> Result<i64> { fn get_or_insert_server(&mut self, server: &str) -> Result<i64> {
@ -90,9 +88,9 @@ impl Db {
", ",
)?; )?;
let msgs: Result<Vec<String>, _> = stmt let msgs: Result<Vec<String>, _> = stmt
.query_map(params![server, topic, since], |row| Ok(row.get(0)?))? .query_map(params![server, topic, since], |row| row.get(0))?
.collect(); .collect();
Ok(msgs?) msgs
} }
pub fn insert_subscription(&mut self, sub: models::Subscription) -> Result<(), Error> { pub fn insert_subscription(&mut self, sub: models::Subscription) -> Result<(), Error> {
let server_id = self.get_or_insert_server(&sub.server)?; let server_id = self.get_or_insert_server(&sub.server)?;
@ -116,7 +114,7 @@ impl Db {
WHERE server = ?1 AND topic = ?2", WHERE server = ?1 AND topic = ?2",
params![server_id, topic], params![server_id, topic],
)?; )?;
if res <= 0 { if res == 0 {
return Err(Error::SubscriptionNotFound("removing subscription".into())); return Err(Error::SubscriptionNotFound("removing subscription".into()));
} }
Ok(()) Ok(())
@ -162,7 +160,7 @@ impl Db {
sub.topic, sub.topic,
], ],
)?; )?;
if res <= 0 { if res == 0 {
return Err(Error::SubscriptionNotFound("updating subscription".into())); return Err(Error::SubscriptionNotFound("updating subscription".into()));
} }
info!(info = ?sub, "stored subscription info"); info!(info = ?sub, "stored subscription info");
@ -184,7 +182,7 @@ impl Db {
", ",
params![server_id, topic, value], params![server_id, topic, value],
)?; )?;
if res <= 0 { if res == 0 {
return Err(Error::SubscriptionNotFound("updating read_until".into())); return Err(Error::SubscriptionNotFound("updating read_until".into()));
} }
Ok(()) Ok(())
@ -198,7 +196,7 @@ impl Db {
", ",
params![server_id, topic], params![server_id, topic],
)?; )?;
if res <= 0 { if res == 0 {
return Err(Error::SubscriptionNotFound("deleting messages".into())); return Err(Error::SubscriptionNotFound("deleting messages".into()));
} }
Ok(()) Ok(())

View File

@ -148,7 +148,7 @@ impl Subscription {
let mut url = url::Url::parse(server)?; let mut url = url::Url::parse(server)?;
url.path_segments_mut() url.path_segments_mut()
.map_err(|_| url::ParseError::RelativeUrlWithCannotBeABaseBase)? .map_err(|_| url::ParseError::RelativeUrlWithCannotBeABaseBase)?
.push(&topic) .push(topic)
.push("json"); .push("json");
url.query_pairs_mut() url.query_pairs_mut()
.append_pair("since", &since.to_string()); .append_pair("since", &since.to_string());
@ -162,7 +162,7 @@ impl Subscription {
if let Err(e) = Self::build_url(&self.server, &self.topic, 0) { if let Err(e) = Self::build_url(&self.server, &self.topic, 0) {
errs.push(e); errs.push(e);
}; };
if errs.len() > 0 { if !errs.is_empty() {
return Err(errs); return Err(errs);
} }
Ok(self) Ok(self)

View File

@ -63,7 +63,7 @@ impl output_channel::Server for NotifyForwarder {
let already_stored: bool = { let already_stored: bool = {
// If this fails parsing, the message is not valid at all. // If this fails parsing, the message is not valid at all.
// The server is probably misbehaving. // The server is probably misbehaving.
let min_message: MinMessage = pry!(serde_json::from_str(&message) let min_message: MinMessage = pry!(serde_json::from_str(message)
.map_err(|e| Error::InvalidMinMessage(message.to_string(), e))); .map_err(|e| Error::InvalidMinMessage(message.to_string(), e)));
let model = self.model.borrow(); let model = self.model.borrow();
match self.env.db.insert_message(&model.server, message) { match self.env.db.insert_message(&model.server, message) {
@ -83,20 +83,15 @@ impl output_channel::Server for NotifyForwarder {
// Show notification // Show notification
// Our priority is to show notifications. If anything fails, panic. // Our priority is to show notifications. If anything fails, panic.
if !{ self.model.borrow().muted } { if !{ self.model.borrow().muted } {
let msg: Message = pry!(serde_json::from_str(&message) let msg: Message = pry!(serde_json::from_str(message)
.map_err(|e| Error::InvalidMessage(message.to_string(), e))); .map_err(|e| Error::InvalidMessage(message.to_string(), e)));
let np = self.env.proxy.clone(); let np = self.env.proxy.clone();
let title = { msg.notification_title(&*self.model.borrow()) }; let title = { msg.notification_title(&self.model.borrow()) };
let n = models::Notification { let n = models::Notification {
title: title.to_string(), title,
body: msg body: msg.display_message().as_deref().unwrap_or("").to_string(),
.display_message()
.as_ref()
.map(|x| x.as_str())
.unwrap_or("")
.to_string(),
actions: msg.actions, actions: msg.actions,
}; };
@ -380,7 +375,7 @@ impl SystemNotifier {
pub fn watch_subscribed(&mut self) -> Promise<(), capnp::Error> { pub fn watch_subscribed(&mut self) -> Promise<(), capnp::Error> {
let f: Vec<_> = pry!(self.env.db.list_subscriptions()) let f: Vec<_> = pry!(self.env.db.list_subscriptions())
.into_iter() .into_iter()
.map(|m| self.watch(m.clone())) .map(|m| self.watch(m))
.collect(); .collect();
Promise::from_future(async move { Promise::from_future(async move {
join_all(f.into_iter().map(|x| async move { join_all(f.into_iter().map(|x| async move {
@ -434,7 +429,7 @@ impl system_notifier::Server for SystemNotifier {
pry!(self pry!(self
.env .env
.db .db
.remove_subscription(&server, &topic) .remove_subscription(server, topic)
.map_err(|e| capnp::Error::failed(e.to_string()))); .map_err(|e| capnp::Error::failed(e.to_string())));
info!(server, topic, "Unsubscribed"); info!(server, topic, "Unsubscribed");
} }

View File

@ -9,7 +9,7 @@ use glib::Properties;
use gtk::{gio, glib}; use gtk::{gio, glib};
use ntfy_daemon::models; use ntfy_daemon::models;
use ntfy_daemon::ntfy_capnp::{output_channel, subscription, watch_handle, Status}; use ntfy_daemon::ntfy_capnp::{output_channel, subscription, watch_handle, Status};
use tracing::{debug, debug_span, error, instrument}; use tracing::{debug, error, instrument};
struct TopicWatcher { struct TopicWatcher {
sub: glib::WeakRef<Subscription>, sub: glib::WeakRef<Subscription>,
@ -217,8 +217,7 @@ impl Subscription {
val.set_display_name(&*imp.display_name.borrow()); val.set_display_name(&*imp.display_name.borrow());
val.set_read_until(imp.read_until.get()); val.set_read_until(imp.read_until.get());
Promise::from_future(async move { Promise::from_future(async move {
let _span = debug_span!("send_updated_info").entered(); debug!("sending update_info");
debug!("sending");
req.send().promise.await?; req.send().promise.await?;
Ok(()) Ok(())
}) })
@ -233,12 +232,8 @@ impl Subscription {
} }
fn update_unread_count(&self) { fn update_unread_count(&self) {
let imp = self.imp(); let imp = self.imp();
if let Some(last) = Self::last_message(&imp.messages) { if Self::last_message(&imp.messages).map(|last| last.time) > Some(imp.read_until.get()) {
if last.time > imp.read_until.get() { imp.unread_count.set(1);
imp.unread_count.set(1);
} else {
imp.unread_count.set(0);
}
} else { } else {
imp.unread_count.set(0); imp.unread_count.set(0);
} }
@ -256,13 +251,12 @@ impl Subscription {
} }
pub fn flag_all_as_read(&self) -> Promise<(), capnp::Error> { pub fn flag_all_as_read(&self) -> Promise<(), capnp::Error> {
let imp = self.imp(); let imp = self.imp();
let Some(last) = Self::last_message(&imp.messages) else { let Some(value) = Self::last_message(&imp.messages)
.map(|last| last.time)
.filter(|time| *time > self.imp().read_until.get())
else {
return Promise::ok(()); return Promise::ok(());
}; };
let value = last.time;
if self.imp().read_until.get() == value {
return Promise::ok(());
}
let this = self.clone(); let this = self.clone();
Promise::from_future(async move { Promise::from_future(async move {
@ -276,14 +270,15 @@ impl Subscription {
} }
pub fn publish_msg(&self, mut msg: models::Message) -> Promise<(), capnp::Error> { pub fn publish_msg(&self, mut msg: models::Message) -> Promise<(), capnp::Error> {
let imp = self.imp(); let imp = self.imp();
let json = {
msg.topic = self.topic();
serde_json::to_string(&msg).map_err(|e| capnp::Error::failed(e.to_string()))
};
let mut req = imp.client.get().unwrap().publish_request(); let mut req = imp.client.get().unwrap().publish_request();
msg.topic = self.topic();
let json = serde_json::to_string(&msg).map_err(|e| capnp::Error::failed(e.to_string()));
req.get().set_message(&pry!(json)); req.get().set_message(&pry!(json));
Promise::from_future(async move { Promise::from_future(async move {
let _span = debug_span!("publish").entered(); debug!("sending publish");
debug!("sending");
req.send().promise.await?; req.send().promise.await?;
Ok(()) Ok(())
}) })
@ -294,8 +289,7 @@ impl Subscription {
let req = imp.client.get().unwrap().clear_notifications_request(); let req = imp.client.get().unwrap().clear_notifications_request();
let this = self.clone(); let this = self.clone();
Promise::from_future(async move { Promise::from_future(async move {
let _span = debug_span!("clear_notifications").entered(); debug!("sending clear_notifications");
debug!("sending");
req.send().promise.await?; req.send().promise.await?;
this.imp().messages.remove_all(); this.imp().messages.remove_all();
Ok(()) Ok(())

View File

@ -145,39 +145,29 @@ impl MessageRow {
self.attach(&tags, 0, row, 3, 1); self.attach(&tags, 0, row, 3, 1);
} }
} }
fn fetch_image_bytes(url: &str) -> anyhow::Result<Vec<u8>> {
let path = glib::user_cache_dir().join("com.ranfdev.Notify").join(&url);
let bytes = if path.exists() {
std::fs::read(&path)?
} else {
let mut bytes = vec![];
ureq::get(&url)
.call()?
.into_reader()
.take(5 * 1_000_000) // 5 MB
.read_to_end(&mut bytes)?;
bytes
};
Ok(bytes)
}
fn build_image(&self, url: String) -> gtk::Picture { fn build_image(&self, url: String) -> gtk::Picture {
let (tx, rx) = glib::MainContext::channel(Default::default()); let (tx, rx) = glib::MainContext::channel(Default::default());
gio::spawn_blocking(move || { gio::spawn_blocking(move || {
let path = glib::user_cache_dir().join("com.ranfdev.Notify").join(&url); if let Err(e) =
let bytes = if path.exists() { Self::fetch_image_bytes(&url).map(|bytes| tx.send(glib::Bytes::from_owned(bytes)))
match std::fs::read(&path) { {
Ok(v) => v, error!(error = %e)
Err(e) => { }
error!(error = %e, path = %path.display(), "reading image from disk");
return glib::ControlFlow::Break;
}
}
} else {
let res = match ureq::get(&url).call() {
Ok(res) => res,
Err(e) => {
error!(error = %e, "fetching image");
return glib::ControlFlow::Break;
}
};
let mut bytes = vec![];
if let Err(e) = res
.into_reader()
.take(5 * 1_000_000) // 5 MB
.read_to_end(&mut bytes)
{
error!(error = %e, "reading image data");
return glib::ControlFlow::Break;
}
bytes
};
tx.send(glib::Bytes::from_owned(bytes)).unwrap();
glib::ControlFlow::Break glib::ControlFlow::Break
}); });
let picture = gtk::Picture::new(); let picture = gtk::Picture::new();

View File

@ -346,7 +346,7 @@ impl NotifyWindow {
.bind_model(Some(&imp.subscription_list_model), |obj| { .bind_model(Some(&imp.subscription_list_model), |obj| {
let sub = obj.downcast_ref::<Subscription>().unwrap(); let sub = obj.downcast_ref::<Subscription>().unwrap();
Self::build_subscription_ui(&sub).upcast() Self::build_subscription_row(&sub).upcast()
}); });
let this = self.clone(); let this = self.clone();
@ -445,7 +445,7 @@ impl NotifyWindow {
chip chip
} }
fn build_subscription_ui(sub: &Subscription) -> impl glib::IsA<gtk::Widget> { fn build_subscription_row(sub: &Subscription) -> impl glib::IsA<gtk::Widget> {
let b = gtk::Box::builder().spacing(4).build(); let b = gtk::Box::builder().spacing(4).build();
let label = gtk::Label::builder() let label = gtk::Label::builder()