use tonic::{Request, metadata::MetadataValue};
use uuid::Uuid;
use super::{
ConciergeClient, ConciergeError,
proto::{
EmitRequest, EmitResponse, GetScopeNotificationSettingsRequest, GetScopeUnreadCountRequest, ListNotificationsResponse, ListScopeNotificationsRequest, MarkReadResponse,
MarkScopeNotificationsReadRequest, NotificationSettings, SetScopeTopicSubscriptionRequest,
},
};
pub const DEFAULT_INBOX_LIMIT: u32 = 20;
const USER_TOKEN_HEADER: &str = "x-ev-user-token";
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct InboxQuery {
pub cursor: String,
pub limit: u32,
pub unread_only: bool,
pub topic: String,
}
impl Default for InboxQuery {
fn default() -> Self {
Self {
cursor: String::new(),
limit: DEFAULT_INBOX_LIMIT,
unread_only: false,
topic: String::new(),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum MarkRead {
Ids(Vec<String>),
All,
}
impl ConciergeClient {
pub async fn list_scope_notifications(&self, user_id: Uuid, query: InboxQuery) -> Result<ListNotificationsResponse, ConciergeError> {
let limit = if query.limit == 0 { DEFAULT_INBOX_LIMIT } else { query.limit };
let request = self.with_credential(ListScopeNotificationsRequest {
user_id: user_id.to_string(),
cursor: query.cursor,
limit,
unread_only: query.unread_only,
topic: query.topic,
});
Ok(self.inbox.clone().list_scope_notifications(request).await?.into_inner())
}
pub async fn scope_unread_count(&self, user_id: Uuid) -> Result<u32, ConciergeError> {
let request = self.with_credential(GetScopeUnreadCountRequest { user_id: user_id.to_string() });
Ok(self.inbox.clone().get_scope_unread_count(request).await?.into_inner().unread_count)
}
pub async fn scope_notification_settings(&self, user_id: Uuid) -> Result<NotificationSettings, ConciergeError> {
let request = self.with_credential(GetScopeNotificationSettingsRequest { user_id: user_id.to_string() });
Ok(self.inbox.clone().get_scope_notification_settings(request).await?.into_inner())
}
pub async fn mark_scope_notifications_read(&self, user_access_token: &str, what: MarkRead) -> Result<MarkReadResponse, ConciergeError> {
let (ids, all) = match what {
MarkRead::Ids(ids) => (ids, false),
MarkRead::All => (Vec::new(), true),
};
let request = self.as_user(user_access_token, MarkScopeNotificationsReadRequest { user_id: String::new(), ids, all })?;
Ok(self.inbox.clone().mark_scope_notifications_read(request).await?.into_inner())
}
pub async fn set_scope_topic_subscription(&self, user_access_token: &str, topic: &str, subscribed: bool, email_enabled: bool) -> Result<NotificationSettings, ConciergeError> {
let request = self.as_user(
user_access_token,
SetScopeTopicSubscriptionRequest {
user_id: String::new(),
topic: topic.to_owned(),
subscribed,
email_enabled,
},
)?;
Ok(self.inbox.clone().set_scope_topic_subscription(request).await?.into_inner())
}
pub async fn emit_scope_notification(&self, notification: EmitRequest) -> Result<EmitResponse, ConciergeError> {
let request = self.with_credential(notification);
Ok(self.inbox.clone().emit_scope_notification(request).await?.into_inner())
}
fn as_user<T>(&self, user_access_token: &str, message: T) -> Result<Request<T>, ConciergeError> {
let mut token = MetadataValue::try_from(user_access_token).map_err(|_| ConciergeError::Config("the user access token is not a valid header value".into()))?;
token.set_sensitive(true);
let mut request = self.with_credential(message);
request.metadata_mut().insert(USER_TOKEN_HEADER, token);
Ok(request)
}
}