mirror of
https://github.com/nostrlabs-io/notepush.git
synced 2025-06-14 11:07:43 +00:00
Add support to "only notifications from following" setting
Testing ------- PASS Devices: Mix of iPhone simulators and real devices notepush: This commit Damus: 4ea6c360e6e33747cb09ecf085049948ec1dadd1 (WIP change from GH issue #2360) Setup: - Account A with push notifications enabled, DM notifications enabled, and "only notifications from following enabled" - Account A follows B but not C Steps: 1. Send DM to A from B. Push notification appears 2. Send DM to A from C. Push notification does not appear Signed-off-by: Daniel D’Aquino <daniel@daquino.me> Closes: https://github.com/damus-io/damus/issues/2360
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
pub mod mute_manager;
|
||||
pub mod nostr_network_helper;
|
||||
mod nostr_event_extensions;
|
||||
pub mod notification_manager;
|
||||
|
||||
pub use mute_manager::MuteManager;
|
||||
pub use nostr_network_helper::NostrNetworkHelper;
|
||||
use nostr_event_extensions::{ExtendedEvent, SqlStringConvertible};
|
||||
pub use notification_manager::NotificationManager;
|
||||
|
@ -2,16 +2,16 @@ use super::ExtendedEvent;
|
||||
use nostr_sdk::prelude::*;
|
||||
use tokio::time::{timeout, Duration};
|
||||
|
||||
pub struct MuteManager {
|
||||
pub struct NostrNetworkHelper {
|
||||
client: Client,
|
||||
}
|
||||
|
||||
impl MuteManager {
|
||||
impl NostrNetworkHelper {
|
||||
pub async fn new(relay_url: String) -> Result<Self, Box<dyn std::error::Error>> {
|
||||
let client = Client::new(&Keys::generate());
|
||||
client.add_relay(relay_url.clone()).await?;
|
||||
client.connect().await;
|
||||
Ok(MuteManager { client })
|
||||
Ok(NostrNetworkHelper { client })
|
||||
}
|
||||
|
||||
pub async fn should_mute_notification_for_pubkey(
|
||||
@ -125,4 +125,63 @@ impl MuteManager {
|
||||
self.client.unsubscribe(this_subscription_id).await;
|
||||
mute_list
|
||||
}
|
||||
|
||||
pub async fn does_pubkey_follow_pubkey(
|
||||
&self,
|
||||
source_pubkey: &PublicKey,
|
||||
target_pubkey: &PublicKey,
|
||||
) -> bool {
|
||||
log::debug!(
|
||||
"Checking if pubkey {:?} follows pubkey {:?}",
|
||||
source_pubkey,
|
||||
target_pubkey
|
||||
);
|
||||
if let Some(contact_list) = self.get_contact_list(source_pubkey).await {
|
||||
let tag_contents = contact_list.get_tags_content(TagKind::SingleLetter(SingleLetterTag {
|
||||
character: Alphabet::P,
|
||||
uppercase: false,
|
||||
}));
|
||||
return tag_contents.iter().any(|t| t == &target_pubkey.to_hex());
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub async fn get_contact_list(&self, pubkey: &PublicKey) -> Option<Event> {
|
||||
let subscription_filter = Filter::new()
|
||||
.kinds(vec![Kind::ContactList])
|
||||
.authors(vec![pubkey.clone()])
|
||||
.limit(1);
|
||||
|
||||
let this_subscription_id = self
|
||||
.client
|
||||
.subscribe(Vec::from([subscription_filter]), None)
|
||||
.await;
|
||||
|
||||
let mut contact_list: Option<Event> = None;
|
||||
let mut notifications = self.client.notifications();
|
||||
|
||||
let timeout_duration = Duration::from_secs(10);
|
||||
while let Ok(result) = timeout(timeout_duration, notifications.recv()).await {
|
||||
if let Ok(notification) = result {
|
||||
if let RelayPoolNotification::Event {
|
||||
subscription_id,
|
||||
event,
|
||||
..
|
||||
} = notification
|
||||
{
|
||||
if this_subscription_id == subscription_id && event.kind == Kind::ContactList {
|
||||
contact_list = Some((*event).clone());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if contact_list.is_none() {
|
||||
log::debug!("Contact list not found for pubkey {:?}", pubkey);
|
||||
}
|
||||
|
||||
self.client.unsubscribe(this_subscription_id).await;
|
||||
contact_list
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@ use tokio::sync::Mutex;
|
||||
use std::collections::HashSet;
|
||||
use tokio;
|
||||
|
||||
use super::mute_manager::MuteManager;
|
||||
use super::nostr_network_helper::NostrNetworkHelper;
|
||||
use super::ExtendedEvent;
|
||||
use super::SqlStringConvertible;
|
||||
use nostr::Event;
|
||||
@ -28,7 +28,7 @@ pub struct NotificationManager {
|
||||
apns_topic: String,
|
||||
apns_client: Mutex<Client>,
|
||||
|
||||
mute_manager: Mutex<MuteManager>,
|
||||
nostr_network_helper: Mutex<NostrNetworkHelper>,
|
||||
}
|
||||
|
||||
impl NotificationManager {
|
||||
@ -43,7 +43,7 @@ impl NotificationManager {
|
||||
apns_environment: a2::client::Endpoint,
|
||||
apns_topic: String,
|
||||
) -> Result<Self, Box<dyn std::error::Error>> {
|
||||
let mute_manager = MuteManager::new(relay_url.clone()).await?;
|
||||
let mute_manager = NostrNetworkHelper::new(relay_url.clone()).await?;
|
||||
|
||||
let connection = db.get()?;
|
||||
Self::setup_database(&connection)?;
|
||||
@ -61,7 +61,7 @@ impl NotificationManager {
|
||||
apns_topic,
|
||||
apns_client: Mutex::new(client),
|
||||
db: Mutex::new(db),
|
||||
mute_manager: Mutex::new(mute_manager),
|
||||
nostr_network_helper: Mutex::new(mute_manager),
|
||||
})
|
||||
}
|
||||
|
||||
@ -221,7 +221,7 @@ impl NotificationManager {
|
||||
let mut pubkeys_to_notify = HashSet::new();
|
||||
for pubkey in relevant_pubkeys_yet_to_receive {
|
||||
let should_mute: bool = {
|
||||
let mute_manager_mutex_guard = self.mute_manager.lock().await;
|
||||
let mute_manager_mutex_guard = self.nostr_network_helper.lock().await;
|
||||
mute_manager_mutex_guard
|
||||
.should_mute_notification_for_pubkey(event, &pubkey)
|
||||
.await
|
||||
@ -285,6 +285,12 @@ impl NotificationManager {
|
||||
event: &Event,
|
||||
) -> Result<bool, Box<dyn std::error::Error>> {
|
||||
let notification_preferences = self.get_user_notification_settings(pubkey, device_token).await?;
|
||||
if notification_preferences.only_notifications_from_following_enabled {
|
||||
let nostr_network_helper_mutex_guard = self.nostr_network_helper.lock().await;
|
||||
if !nostr_network_helper_mutex_guard.does_pubkey_follow_pubkey(pubkey, &event.author()).await {
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
match event.kind {
|
||||
Kind::TextNote => Ok(notification_preferences.mention_notifications_enabled), // TODO: Not 100% accurate
|
||||
Kind::EncryptedDirectMessage => Ok(notification_preferences.dm_notifications_enabled),
|
||||
|
Reference in New Issue
Block a user