nostr-sdk 0.45.0

A full-featured SDK for building high-performance and reliable nostr applications.
Documentation
use std::borrow::Cow;
use std::future::IntoFuture;

use nostr::types::url::RelayUrl;

use crate::client::url::RelayUrlArg;
use crate::client::{Client, Error};
use crate::future::BoxedFuture;

/// Remove a relay from the pool.
#[must_use = "Does nothing unless you await!"]
pub struct RemoveRelay<'client, 'url> {
    client: &'client Client,
    url: RelayUrlArg<'url>,
    force: bool,
}

impl<'client, 'url> RemoveRelay<'client, 'url> {
    pub(crate) fn new(client: &'client Client, url: RelayUrlArg<'url>) -> Self {
        Self {
            client,
            url,
            force: false,
        }
    }

    /// Force remove
    #[inline]
    pub fn force(mut self) -> Self {
        self.force = true;
        self
    }
}

impl<'client, 'url> IntoFuture for RemoveRelay<'client, 'url>
where
    'url: 'client,
{
    type Output = Result<(), Error>;
    type IntoFuture = BoxedFuture<'client, Self::Output>;

    fn into_future(self) -> Self::IntoFuture {
        Box::pin(async move {
            // Convert into relay URL
            let url: Cow<RelayUrl> = self.url.try_into_relay_url()?;

            // Remove the relay from the pool
            self.client.pool().remove_relay(url, self.force).await
        })
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::error::ErrorKind;
    use crate::relay::RelayCapabilities;

    #[tokio::test]
    async fn test_remove_nonexistent_relay() {
        let client = Client::default();

        client.add_relay("ws://127.0.0.1:6666").await.unwrap();

        let err = client
            .remove_relay("ws://127.0.0.1:7777")
            .await
            .unwrap_err();
        assert_eq!(err.kind(), ErrorKind::NotFound);
        assert_eq!(err.to_string(), "relay not found");
    }

    #[tokio::test]
    async fn test_remove_relay() {
        let client = Client::default();

        client.add_relay("ws://127.0.0.1:6666").await.unwrap();

        client
            .add_relay("ws://127.0.0.1:8888")
            .capabilities(RelayCapabilities::default() | RelayCapabilities::GOSSIP)
            .await
            .unwrap();

        assert_eq!(client.relays().await.len(), 2);
        assert_eq!(client.pool().all_relays().await.len(), 2);

        // Remove the non-gossip relay
        assert!(client.remove_relay("ws://127.0.0.1:6666").await.is_ok());
        assert!(client.relay("ws://127.0.0.1:6666").await.unwrap().is_none());
        assert_eq!(client.relays().await.len(), 1);
        assert_eq!(client.pool().all_relays().await.len(), 1);

        // Try to remove the gossip relay (will not be removed)
        assert!(client.remove_relay("ws://127.0.0.1:8888").await.is_ok());
        assert!(client.relay("ws://127.0.0.1:8888").await.is_ok()); // The relay exists in the client!
        assert!(client.relays().await.is_empty()); // This gets only the READ/WRITE relays, which are now 0
        assert_eq!(client.pool().all_relays().await.len(), 1);
    }

    #[tokio::test]
    async fn test_force_remove_relay() {
        let client = Client::default();

        client.add_relay("ws://127.0.0.1:6666").await.unwrap();

        client
            .add_relay("ws://127.0.0.1:8888")
            .capabilities(RelayCapabilities::default() | RelayCapabilities::GOSSIP)
            .await
            .unwrap();

        assert_eq!(client.relays().await.len(), 2);
        assert_eq!(client.pool().all_relays().await.len(), 2);

        // Force remove the non-gossip relay
        assert!(
            client
                .remove_relay("ws://127.0.0.1:6666")
                .force()
                .await
                .is_ok()
        );
        assert!(client.relay("ws://127.0.0.1:6666").await.unwrap().is_none());
        assert_eq!(client.relays().await.len(), 1);
        assert_eq!(client.pool().all_relays().await.len(), 1);

        // Force remove the gossip relay
        assert!(
            client
                .remove_relay("ws://127.0.0.1:8888")
                .force()
                .await
                .is_ok()
        );
        assert!(client.relay("ws://127.0.0.1:8888").await.unwrap().is_none());
        assert!(client.relays().await.is_empty());
        assert!(client.pool().all_relays().await.is_empty());
    }
}