Skip to main content

teams_cli/
backend.rs

1//! Shared operations for CLI, TUI and other frontends. Desktop data access is limited to chats.
2use crate::{
3    auth,
4    config::{self, BackendKind},
5    desktop::{self, DesktopClient},
6    error::AppError,
7    graph::{GraphClient, Page},
8};
9use serde_json::Value;
10
11pub enum TeamsBackend {
12    Graph(GraphClient),
13    Desktop(Box<DesktopClient>),
14}
15
16impl TeamsBackend {
17    pub async fn connect(profile: Option<&str>) -> Result<Self, AppError> {
18        let (name, selected) = config::load(profile)?;
19        match selected.backend {
20            BackendKind::Graph => Ok(Self::Graph(GraphClient::new(
21                auth::access_token(&name, &selected).await?,
22            ))),
23            BackendKind::Desktop => Ok(Self::Desktop(Box::new(DesktopClient::from_profile(
24                &selected,
25            )?))),
26        }
27    }
28
29    fn graph(&self) -> Result<&GraphClient, AppError> {
30        match self {
31            Self::Graph(client) => Ok(client),
32            Self::Desktop(_) => Err(desktop::messaging_unsupported()),
33        }
34    }
35
36    pub async fn me(&self) -> Result<Value, AppError> {
37        self.graph()?.me().await
38    }
39    pub async fn teams(&self, limit: u16, offset: usize) -> Result<Page, AppError> {
40        self.graph()?.teams(limit, offset).await
41    }
42    pub async fn teams_available(&self) -> Result<(), AppError> {
43        self.graph()?.teams_available().await
44    }
45    pub async fn channels(&self, team: &str, limit: u16, offset: usize) -> Result<Page, AppError> {
46        self.graph()?.channels(team, limit, offset).await
47    }
48    pub async fn chats(&self, limit: u16, cursor: Option<&str>) -> Result<Page, AppError> {
49        match self {
50            Self::Graph(client) => client.chats(limit, cursor).await,
51            Self::Desktop(client) => client.chats(limit, cursor).await,
52        }
53    }
54    pub async fn search_people(&self, query: &str, limit: u16) -> Result<Page, AppError> {
55        crate::graph::validate_people_query(query, usize::from(limit))?;
56        match self {
57            Self::Graph(client) => client.search_people(query, usize::from(limit)).await,
58            Self::Desktop(client) => client.search_people(query, limit).await,
59        }
60    }
61    pub async fn create_chat(&self, recipient: &str) -> Result<Value, AppError> {
62        match self {
63            Self::Graph(client) => client.create_chat(recipient).await,
64            Self::Desktop(client) => client.create_chat(recipient).await,
65        }
66    }
67    pub async fn messages(
68        &self,
69        chat: Option<&str>,
70        team: Option<&str>,
71        channel: Option<&str>,
72        limit: u16,
73        cursor: Option<&str>,
74    ) -> Result<Page, AppError> {
75        match (self, chat, team, channel) {
76            (Self::Graph(client), ..) => client.messages(chat, team, channel, limit, cursor).await,
77            (Self::Desktop(client), Some(chat), None, None) => {
78                client.messages(chat, limit, cursor).await
79            }
80            (Self::Desktop(_), ..) => Err(desktop::messaging_unsupported()),
81        }
82    }
83    pub async fn send(
84        &self,
85        chat: Option<&str>,
86        team: Option<&str>,
87        channel: Option<&str>,
88        body: &str,
89    ) -> Result<Value, AppError> {
90        match (self, chat, team, channel) {
91            (Self::Graph(client), ..) => client.send(chat, team, channel, body).await,
92            (Self::Desktop(client), Some(chat), None, None) => client.send(chat, body).await,
93            (Self::Desktop(_), ..) => Err(desktop::messaging_unsupported()),
94        }
95    }
96}
97
98impl TeamsBackend {
99    pub async fn send_with_id(&self, chat: &str, body: &str, id: &str) -> Result<Value, AppError> {
100        match self {
101            Self::Desktop(client) => client.send_with_id(chat, body, id).await,
102            Self::Graph(client) => client.send(Some(chat), None, None, body).await,
103        }
104    }
105    pub async fn delivery(&self, chat: &str, id: &str) -> Result<Value, AppError> {
106        match self {
107            Self::Desktop(client) => client.delivery(chat, id).await,
108            Self::Graph(_) => Err(AppError::Unsupported("delivery reconciliation by client message ID is available on desktop profiles only; check the conversation before resending".into())),
109        }
110    }
111}