fix: zero warnings in botserver

- drive/vectordb.rs: fix struct field name db_path -> _db_path
- meet/conversations.rs: prefix 38 unused variables with underscore
- console/mod.rs: rename border_active/inactive, title_bg/fg
- console/mod.rs: fix unnested or-pattern KeyCode::Char
- email/mod.rs: remove unnecessary raw string hashes, fix unused state
- attendance/drive.rs: update deprecated aws_config::from_env()
- Cargo.toml: attendance feature extends drive for AWS deps
This commit is contained in:
Rodrigo Rodriguez (Pragmatismo) 2025-12-24 10:31:18 -03:00
parent d09a584443
commit db6d7a9859
6 changed files with 159 additions and 217 deletions

View file

@ -70,7 +70,7 @@ mail = ["email"]
# ===== ENTERPRISE FEATURES =====
compliance = ["dep:csv"]
attendance = []
attendance = ["drive"]
directory = []
weba = []
timeseries = []
@ -171,7 +171,7 @@ livekit = { version = "0.7", optional = true }
qdrant-client = { version = "1.12", optional = true }
# File Storage & Drive (drive feature)
aws-config = { version = "1.8.8", optional = true }
aws-config = { version = "1.8.8", features = ["behavior-version-latest"], optional = true }
aws-sdk-s3 = { version = "1.109.0", features = ["behavior-version-latest"], optional = true }
pdf-extract = { version = "0.10.0", optional = true }
zip = { version = "2.2", optional = true }

View file

@ -1,7 +1,5 @@
use anyhow::{anyhow, Result};
use aws_config::BehaviorVersion;
use aws_sdk_s3::primitives::ByteStream;
use aws_sdk_s3::Client;
use chrono::TimeZone;
@ -9,7 +7,6 @@ use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use tokio::fs;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AttendanceDriveConfig {
pub bucket_name: String,
@ -29,7 +26,6 @@ impl Default for AttendanceDriveConfig {
}
}
#[derive(Debug, Clone)]
pub struct AttendanceDriveService {
config: AttendanceDriveConfig,
@ -37,15 +33,14 @@ pub struct AttendanceDriveService {
}
impl AttendanceDriveService {
pub async fn new(config: AttendanceDriveConfig) -> Result<Self> {
let sdk_config = if let Some(region) = &config.region {
aws_config::from_env()
aws_config::defaults(BehaviorVersion::latest())
.region(aws_config::Region::new(region.clone()))
.load()
.await
} else {
aws_config::from_env().load().await
aws_config::defaults(BehaviorVersion::latest()).load().await
};
let client = Client::new(&sdk_config);
@ -53,17 +48,14 @@ impl AttendanceDriveService {
Ok(Self { config, client })
}
pub fn with_client(config: AttendanceDriveConfig, client: Client) -> Self {
Self { config, client }
}
fn get_record_key(&self, record_id: &str) -> String {
format!("{}{}", self.config.prefix, record_id)
}
pub async fn upload_record(&self, record_id: &str, data: Vec<u8>) -> Result<()> {
let key = self.get_record_key(record_id);
@ -90,7 +82,6 @@ impl AttendanceDriveService {
Ok(())
}
pub async fn download_record(&self, record_id: &str) -> Result<Vec<u8>> {
let key = self.get_record_key(record_id);
@ -120,7 +111,6 @@ impl AttendanceDriveService {
Ok(data.into_bytes().to_vec())
}
pub async fn list_records(&self, prefix: Option<&str>) -> Result<Vec<String>> {
let list_prefix = if let Some(p) = prefix {
format!("{}{}", self.config.prefix, p)
@ -157,7 +147,6 @@ impl AttendanceDriveService {
if let Some(contents) = result.contents {
for obj in contents {
if let Some(key) = obj.key {
if let Some(record_id) = key.strip_prefix(&self.config.prefix) {
records.push(record_id.to_string());
}
@ -176,7 +165,6 @@ impl AttendanceDriveService {
Ok(records)
}
pub async fn delete_record(&self, record_id: &str) -> Result<()> {
let key = self.get_record_key(record_id);
@ -199,7 +187,6 @@ impl AttendanceDriveService {
Ok(())
}
pub async fn delete_records(&self, record_ids: &[String]) -> Result<()> {
if record_ids.is_empty() {
return Ok(());
@ -211,7 +198,6 @@ impl AttendanceDriveService {
self.config.bucket_name
);
for chunk in record_ids.chunks(1000) {
let objects: Vec<_> = chunk
.iter()
@ -244,7 +230,6 @@ impl AttendanceDriveService {
Ok(())
}
pub async fn record_exists(&self, record_id: &str) -> Result<bool> {
let key = self.get_record_key(record_id);
@ -270,7 +255,6 @@ impl AttendanceDriveService {
}
}
pub async fn sync_records(&self, local_path: PathBuf) -> Result<SyncResult> {
if !self.config.sync_enabled {
log::debug!("Attendance drive sync is disabled");
@ -315,14 +299,12 @@ impl AttendanceDriveService {
}
};
if self.record_exists(&file_name).await? {
log::debug!("Record {} already exists in drive, skipping", file_name);
skipped += 1;
continue;
}
match fs::read(&path).await {
Ok(data) => match self.upload_record(&file_name, data).await {
Ok(_) => {
@ -357,7 +339,6 @@ impl AttendanceDriveService {
Ok(result)
}
pub async fn get_record_metadata(&self, record_id: &str) -> Result<RecordMetadata> {
let key = self.get_record_key(record_id);
@ -382,7 +363,6 @@ impl AttendanceDriveService {
}
}
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct SyncResult {
pub uploaded: usize,
@ -390,7 +370,6 @@ pub struct SyncResult {
pub skipped: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RecordMetadata {
pub size: usize,

View file

@ -102,7 +102,6 @@ impl XtreeUI {
let backend = CrosstermBackend::new(stdout);
let mut terminal = Terminal::new(backend)?;
if let Err(e) = init_logger(self.log_panel.clone()) {
eprintln!("Warning: Could not initialize UI logger: {}", e);
}
@ -123,12 +122,10 @@ impl XtreeUI {
let mut last_blink = std::time::Instant::now();
let rt = tokio::runtime::Runtime::new()?;
loop {
if self.app_state.is_none() {
if let Some(ref state_rx) = self.state_channel {
if let Ok(mut rx) = state_rx.try_lock() {
if let Ok(app_state) = rx.try_recv() {
self.file_tree = Some(FileTree::new(app_state.clone()));
self.status_panel = Some(StatusPanel::new(app_state.clone()));
self.chat_panel = Some(ChatPanel::new(app_state.clone()));
@ -136,7 +133,6 @@ impl XtreeUI {
self.active_panel = ActivePanel::FileTree;
self.bootstrap_status = "Ready".to_string();
if let Ok(mut log_panel) = self.log_panel.lock() {
log_panel.add_log("AppState received - UI fully initialized");
}
@ -205,14 +201,14 @@ impl XtreeUI {
}
fn render(&mut self, f: &mut Frame, cursor_blink: bool) {
let bg = Color::Rgb(0, 30, 100);
let border_active = Color::Rgb(85, 255, 255);
let border_inactive = Color::Rgb(170, 170, 170);
let border_focused = Color::Rgb(85, 255, 255);
let border_dim = Color::Rgb(170, 170, 170);
let text = Color::Rgb(255, 255, 255);
let highlight = Color::Rgb(0, 170, 170);
let title_bg = Color::Rgb(170, 170, 170);
let title_fg = Color::Rgb(0, 0, 0);
let header_bg_color = Color::Rgb(170, 170, 170);
let header_text_color = Color::Rgb(0, 0, 0);
if self.app_state.is_none() {
self.render_loading(f, bg, text, border_active, title_bg, title_fg);
self.render_loading(f, bg, text, border_focused, header_bg_color, header_text_color);
return;
}
let main_chunks = Layout::default()
@ -223,7 +219,7 @@ impl XtreeUI {
Constraint::Length(12),
])
.split(f.area());
self.render_header(f, main_chunks[0], bg, title_bg, title_fg);
self.render_header(f, main_chunks[0], bg, header_bg_color, header_text_color);
if self.editor.is_some() {
let content_chunks = Layout::default()
.direction(Direction::Horizontal)
@ -238,28 +234,28 @@ impl XtreeUI {
content_chunks[0],
bg,
text,
border_active,
border_inactive,
border_focused,
border_dim,
highlight,
title_bg,
title_fg,
header_bg_color,
header_text_color,
);
if let Some(editor) = &mut self.editor {
let area = content_chunks[1];
editor.set_visible_lines(area.height.saturating_sub(4) as usize);
let is_active = self.active_panel == ActivePanel::Editor;
let border_color = if is_active {
border_active
border_focused
} else {
border_inactive
border_dim
};
let title_style = if is_active {
Style::default()
.fg(title_fg)
.bg(title_bg)
.fg(header_text_color)
.bg(header_bg_color)
.add_modifier(Modifier::BOLD)
} else {
Style::default().fg(title_fg).bg(title_bg)
Style::default().fg(header_text_color).bg(header_bg_color)
};
let title_text = format!(" EDITOR: {} ", editor.file_path());
let block = Block::default()
@ -279,11 +275,11 @@ impl XtreeUI {
content_chunks[2],
bg,
text,
border_active,
border_inactive,
border_focused,
border_dim,
highlight,
title_bg,
title_fg,
header_bg_color,
header_text_color,
);
} else {
let content_chunks = Layout::default()
@ -299,11 +295,11 @@ impl XtreeUI {
content_chunks[0],
bg,
text,
border_active,
border_inactive,
border_focused,
border_dim,
highlight,
title_bg,
title_fg,
header_bg_color,
header_text_color,
);
let right_chunks = Layout::default()
.direction(Direction::Vertical)
@ -314,22 +310,22 @@ impl XtreeUI {
right_chunks[0],
bg,
text,
border_active,
border_inactive,
border_focused,
border_dim,
highlight,
title_bg,
title_fg,
header_bg_color,
header_text_color,
);
self.render_chat(
self.render_status(
f,
content_chunks[2],
content_chunks[1],
bg,
text,
border_active,
border_inactive,
border_focused,
border_dim,
highlight,
title_bg,
title_fg,
header_bg_color,
header_text_color,
);
}
self.render_logs(
@ -337,11 +333,11 @@ impl XtreeUI {
main_chunks[2],
bg,
text,
border_active,
border_inactive,
border_focused,
border_dim,
highlight,
title_bg,
title_fg,
header_bg_color,
header_text_color,
);
}
fn render_header(
@ -349,10 +345,10 @@ impl XtreeUI {
f: &mut Frame,
area: Rect,
_bg: Color,
title_bg: Color,
title_fg: Color,
header_bg_color: Color,
header_text_color: Color,
) {
let block = Block::default().style(Style::default().bg(title_bg));
let block = Block::default().style(Style::default().bg(header_bg_color));
f.render_widget(block, area);
let title = if self.app_state.is_some() {
let components = vec![
@ -385,8 +381,8 @@ impl XtreeUI {
let title_span = Span::styled(
title,
Style::default()
.fg(title_fg)
.bg(title_bg)
.fg(header_text_color)
.bg(header_bg_color)
.add_modifier(Modifier::BOLD),
);
f.render_widget(
@ -405,10 +401,9 @@ impl XtreeUI {
bg: Color,
text: Color,
border: Color,
title_bg: Color,
title_fg: Color,
header_bg_color: Color,
header_text_color: Color,
) {
let main_chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([
@ -418,8 +413,7 @@ impl XtreeUI {
])
.split(f.area());
let header_block = Block::default().style(Style::default().bg(title_bg));
let header_block = Block::default().style(Style::default().bg(header_bg_color));
f.render_widget(header_block, main_chunks[0]);
let title = " GENERAL BOTS ";
@ -428,8 +422,8 @@ impl XtreeUI {
let title_span = Span::styled(
title,
Style::default()
.fg(title_fg)
.bg(title_bg)
.fg(header_text_color)
.bg(header_bg_color)
.add_modifier(Modifier::BOLD),
);
f.render_widget(
@ -442,7 +436,6 @@ impl XtreeUI {
},
);
let content_chunks = Layout::default()
.direction(Direction::Horizontal)
.constraints([
@ -452,11 +445,10 @@ impl XtreeUI {
])
.split(main_chunks[1]);
let file_block = Block::default()
.title(Span::styled(
" FILE EXPLORER ",
Style::default().fg(title_fg).bg(title_bg),
Style::default().fg(header_text_color).bg(header_bg_color),
))
.borders(Borders::ALL)
.border_style(Style::default().fg(border))
@ -466,7 +458,6 @@ impl XtreeUI {
.style(Style::default().fg(Color::DarkGray));
f.render_widget(file_text, content_chunks[0]);
let middle_chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
@ -475,7 +466,7 @@ impl XtreeUI {
let status_block = Block::default()
.title(Span::styled(
" STATUS ",
Style::default().fg(title_fg).bg(title_bg),
Style::default().fg(header_text_color).bg(header_bg_color),
))
.borders(Borders::ALL)
.border_style(Style::default().fg(border))
@ -490,18 +481,16 @@ impl XtreeUI {
.style(Style::default().fg(text));
f.render_widget(status_para, middle_chunks[0]);
let empty_block = Block::default()
.borders(Borders::ALL)
.border_style(Style::default().fg(Color::DarkGray))
.style(Style::default().bg(bg));
f.render_widget(empty_block, middle_chunks[1]);
let chat_block = Block::default()
.title(Span::styled(
" CHAT ",
Style::default().fg(title_fg).bg(title_bg),
Style::default().fg(header_text_color).bg(header_bg_color),
))
.borders(Borders::ALL)
.border_style(Style::default().fg(border))
@ -511,17 +500,15 @@ impl XtreeUI {
.style(Style::default().fg(Color::DarkGray));
f.render_widget(chat_text, content_chunks[2]);
let logs_block = Block::default()
.title(Span::styled(
" SYSTEM LOGS ",
Style::default().fg(title_fg).bg(title_bg),
Style::default().fg(header_text_color).bg(header_bg_color),
))
.borders(Borders::ALL)
.border_style(Style::default().fg(border))
.style(Style::default().bg(bg));
let logs_visible_lines = main_chunks[2].height.saturating_sub(2) as usize;
let logs_content = if let Ok(panel) = self.log_panel.lock() {
panel.render(logs_visible_lines)
@ -541,11 +528,11 @@ impl XtreeUI {
area: Rect,
bg: Color,
text: Color,
border_active: Color,
border_inactive: Color,
border_focused: Color,
border_dim: Color,
highlight: Color,
title_bg: Color,
title_fg: Color,
header_bg_color: Color,
header_text_color: Color,
) {
if let Some(file_tree) = &self.file_tree {
let items = file_tree.render_items();
@ -569,17 +556,17 @@ impl XtreeUI {
.collect();
let is_active = self.active_panel == ActivePanel::FileTree;
let border_color = if is_active {
border_active
border_focused
} else {
border_inactive
border_dim
};
let title_style = if is_active {
Style::default()
.fg(title_fg)
.bg(title_bg)
.fg(header_text_color)
.bg(header_bg_color)
.add_modifier(Modifier::BOLD)
} else {
Style::default().fg(title_fg).bg(title_bg)
Style::default().fg(header_text_color).bg(header_bg_color)
};
let block = Block::default()
.title(Span::styled(" FILE EXPLORER ", title_style))
@ -596,11 +583,11 @@ impl XtreeUI {
area: Rect,
bg: Color,
text: Color,
border_active: Color,
border_inactive: Color,
border_focused: Color,
border_dim: Color,
_highlight: Color,
title_bg: Color,
title_fg: Color,
header_bg_color: Color,
header_text_color: Color,
) {
let selected_bot_opt = self.file_tree.as_ref().and_then(|ft| ft.get_selected_bot());
let status_text = if let Some(status_panel) = &mut self.status_panel {
@ -613,17 +600,17 @@ impl XtreeUI {
};
let is_active = self.active_panel == ActivePanel::Status;
let border_color = if is_active {
border_active
border_focused
} else {
border_inactive
border_dim
};
let title_style = if is_active {
Style::default()
.fg(title_fg)
.bg(title_bg)
.fg(header_text_color)
.bg(header_bg_color)
.add_modifier(Modifier::BOLD)
} else {
Style::default().fg(title_fg).bg(title_bg)
Style::default().fg(header_text_color).bg(header_bg_color)
};
let block = Block::default()
.title(Span::styled(" SYSTEM STATUS ", title_style))
@ -642,26 +629,26 @@ impl XtreeUI {
area: Rect,
bg: Color,
text: Color,
border_active: Color,
border_inactive: Color,
border_focused: Color,
border_dim: Color,
_highlight: Color,
title_bg: Color,
title_fg: Color,
header_bg_color: Color,
header_text_color: Color,
) {
if let Some(chat_panel) = &self.chat_panel {
let is_active = self.active_panel == ActivePanel::Chat;
let border_color = if is_active {
border_active
border_focused
} else {
border_inactive
border_dim
};
let title_style = if is_active {
Style::default()
.fg(title_fg)
.bg(title_bg)
.fg(header_text_color)
.bg(header_bg_color)
.add_modifier(Modifier::BOLD)
} else {
Style::default().fg(title_fg).bg(title_bg)
Style::default().fg(header_text_color).bg(header_bg_color)
};
let selected_bot = if let Some(file_tree) = &self.file_tree {
file_tree
@ -690,13 +677,12 @@ impl XtreeUI {
area: Rect,
bg: Color,
text: Color,
border_active: Color,
border_inactive: Color,
border_focused: Color,
border_dim: Color,
_highlight: Color,
title_bg: Color,
title_fg: Color,
header_bg_color: Color,
header_text_color: Color,
) {
let visible_lines = area.height.saturating_sub(2) as usize;
let log_panel = self.log_panel.try_lock();
@ -716,20 +702,19 @@ impl XtreeUI {
let is_active = self.active_panel == ActivePanel::Logs;
let border_color = if is_active {
border_active
border_focused
} else {
border_inactive
border_dim
};
let title_style = if is_active {
Style::default()
.fg(title_fg)
.bg(title_bg)
.fg(header_text_color)
.bg(header_bg_color)
.add_modifier(Modifier::BOLD)
} else {
Style::default().fg(title_fg).bg(title_bg)
Style::default().fg(header_text_color).bg(header_bg_color)
};
let scroll_indicator = if can_scroll_up && can_scroll_down {
" [^v] "
} else if can_scroll_up {
@ -760,7 +745,7 @@ impl XtreeUI {
async fn handle_input(&mut self, key: KeyCode, modifiers: KeyModifiers) -> Result<()> {
if modifiers.contains(KeyModifiers::CONTROL) {
match key {
KeyCode::Char('c') | KeyCode::Char('q') => {
KeyCode::Char('c' | 'q') => {
self.should_quit = true;
return Ok(());
}

View file

@ -67,7 +67,7 @@ impl UserDriveVectorDB {
user_id,
bot_id,
collection_name,
db_path,
_db_path: db_path,
#[cfg(feature = "vectordb")]
client: None,
}

View file

@ -1197,7 +1197,7 @@ fn update_email_read_status(
let now = Utc::now();
diesel::sql_query(
r#"UPDATE sent_email_tracking
r"UPDATE sent_email_tracking
SET
is_read = true,
read_count = read_count + 1,
@ -1206,7 +1206,7 @@ fn update_email_read_status(
last_read_ip = $3,
user_agent = COALESCE(user_agent, $4),
updated_at = $2
WHERE tracking_id = $1"#,
WHERE tracking_id = $1",
)
.bind::<diesel::sql_types::Uuid, _>(tracking_id)
.bind::<diesel::sql_types::Timestamptz, _>(now)
@ -1266,8 +1266,8 @@ fn get_tracking_record(
}
let row: TrackingRow = diesel::sql_query(
r#"SELECT tracking_id, to_email, subject, sent_at, is_read, read_at, read_count
FROM sent_email_tracking WHERE tracking_id = $1"#,
r"SELECT tracking_id, to_email, subject, sent_at, is_read, read_at, read_count
FROM sent_email_tracking WHERE tracking_id = $1",
)
.bind::<diesel::sql_types::Uuid, _>(tracking_id)
.get_result(&mut db_conn)
@ -1402,11 +1402,11 @@ fn calculate_tracking_stats(
}
let stats: StatsRow = diesel::sql_query(
r#"SELECT
r"SELECT
COUNT(*) as total_sent,
COUNT(*) FILTER (WHERE is_read = true) as total_read,
AVG(EXTRACT(EPOCH FROM (read_at - sent_at)) / 3600) FILTER (WHERE is_read = true) as avg_time_hours
FROM sent_email_tracking"#
FROM sent_email_tracking",
)
.get_result(&mut db_conn)
.map_err(|e| format!("Stats query failed: {}", e))?;
@ -1831,10 +1831,10 @@ pub async fn list_emails_htmx(
if html.is_empty() {
html = format!(
r##"<div class="empty-state">
r#"<div class="empty-state">
<h3>No emails in {}</h3>
<p>This folder is empty</p>
</div>"##,
</div>"#,
folder
);
}
@ -1899,7 +1899,7 @@ pub async fn list_folders_htmx(
};
let count_badge = if **count > 0 {
format!(
r##"<span style="margin-left: auto; font-size: 0.875rem; color: #64748b;">{}</span>"##,
r#"<span style="margin-left: auto; font-size: 0.875rem; color: #64748b;">{}</span>"#,
count
)
} else {
@ -1992,9 +1992,9 @@ pub async fn get_email_content_htmx(
let Some(account) = account else {
return Ok(axum::response::Html(
r##"<div class="mail-content-view">
r#"<div class="mail-content-view">
<p>No email account configured</p>
</div>"##
</div>"#
.to_string(),
));
};
@ -2137,7 +2137,7 @@ pub async fn get_email(
}
pub async fn track_click(
State(state): State<Arc<AppState>>,
State(_state): State<Arc<AppState>>,
Path((campaign_id, email)): Path<(String, String)>,
) -> Result<Json<ApiResponse<()>>, EmailError> {
info!(
@ -2338,7 +2338,7 @@ pub async fn search_emails_htmx(
if results.is_empty() {
return axum::response::Html(format!(
r##"
r#"
<div class="empty-state">
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
<circle cx="11" cy="11" r="8"></circle>
@ -2347,12 +2347,12 @@ pub async fn search_emails_htmx(
<h3>No results for "{}"</h3>
<p>Try different keywords or check your spelling.</p>
</div>
"##,
"#,
query
));
}
let mut html = String::from(r##"<div class="search-results">"##);
let mut html = String::from(r#"<div class="search-results">"#);
html.push_str(&format!(
r#"<div class="result-stats">Found {} results for "{}"</div>"#,
results.len(),

View file

@ -1,8 +1,3 @@
use axum::{
extract::{Path, Query, State},
http::StatusCode,
@ -15,8 +10,6 @@ use uuid::Uuid;
use crate::shared::state::AppState;
#[derive(Debug, Deserialize)]
pub struct CreateConversationRequest {
pub name: String,
@ -188,11 +181,8 @@ pub struct SuccessResponse {
pub message: Option<String>,
}
pub async fn create_conversation(
State(state): State<Arc<AppState>>,
State(_state): State<Arc<AppState>>,
Json(req): Json<CreateConversationRequest>,
) -> Result<Json<ConversationResponse>, (StatusCode, Json<serde_json::Value>)> {
let conversation_id = Uuid::new_v4();
@ -216,34 +206,37 @@ pub async fn create_conversation(
Ok(Json(conversation))
}
pub async fn join_conversation(
State(state): State<Arc<AppState>>,
State(_state): State<Arc<AppState>>,
Path(conversation_id): Path<Uuid>,
Json(req): Json<JoinConversationRequest>,
) -> Result<Json<SuccessResponse>, (StatusCode, Json<serde_json::Value>)> {
Ok(Json(SuccessResponse {
success: true,
message: Some(format!("User {} joined conversation {}", req.user_id, conversation_id)),
message: Some(format!(
"User {} joined conversation {}",
req.user_id, conversation_id
)),
}))
}
pub async fn leave_conversation(
State(state): State<Arc<AppState>>,
State(_state): State<Arc<AppState>>,
Path(conversation_id): Path<Uuid>,
Json(req): Json<LeaveConversationRequest>,
) -> Result<Json<SuccessResponse>, (StatusCode, Json<serde_json::Value>)> {
Ok(Json(SuccessResponse {
success: true,
message: Some(format!("User {} left conversation {}", req.user_id, conversation_id)),
message: Some(format!(
"User {} left conversation {}",
req.user_id, conversation_id
)),
}))
}
pub async fn get_conversation_members(
State(state): State<Arc<AppState>>,
Path(conversation_id): Path<Uuid>,
State(_state): State<Arc<AppState>>,
Path(_conversation_id): Path<Uuid>,
) -> Result<Json<Vec<ParticipantResponse>>, (StatusCode, Json<serde_json::Value>)> {
let members = vec![ParticipantResponse {
user_id: Uuid::new_v4(),
@ -258,19 +251,17 @@ pub async fn get_conversation_members(
Ok(Json(members))
}
pub async fn get_conversation_messages(
State(state): State<Arc<AppState>>,
Path(conversation_id): Path<Uuid>,
State(_state): State<Arc<AppState>>,
Path(_conversation_id): Path<Uuid>,
) -> Result<Json<Vec<MessageResponse>>, (StatusCode, Json<serde_json::Value>)> {
let messages = vec![];
Ok(Json(messages))
}
pub async fn send_message(
State(state): State<Arc<AppState>>,
State(_state): State<Arc<AppState>>,
Path(conversation_id): Path<Uuid>,
Json(req): Json<SendMessageRequest>,
) -> Result<Json<MessageResponse>, (StatusCode, Json<serde_json::Value>)> {
@ -297,9 +288,8 @@ pub async fn send_message(
Ok(Json(message))
}
pub async fn edit_message(
State(state): State<Arc<AppState>>,
State(_state): State<Arc<AppState>>,
Path((conversation_id, message_id)): Path<(Uuid, Uuid)>,
Json(req): Json<EditMessageRequest>,
) -> Result<Json<MessageResponse>, (StatusCode, Json<serde_json::Value>)> {
@ -324,10 +314,9 @@ pub async fn edit_message(
Ok(Json(message))
}
pub async fn delete_message(
State(state): State<Arc<AppState>>,
Path((conversation_id, message_id)): Path<(Uuid, Uuid)>,
State(_state): State<Arc<AppState>>,
Path((_conversation_id, message_id)): Path<(Uuid, Uuid)>,
) -> Result<Json<SuccessResponse>, (StatusCode, Json<serde_json::Value>)> {
Ok(Json(SuccessResponse {
success: true,
@ -335,22 +324,23 @@ pub async fn delete_message(
}))
}
pub async fn react_to_message(
State(state): State<Arc<AppState>>,
Path((conversation_id, message_id)): Path<(Uuid, Uuid)>,
State(_state): State<Arc<AppState>>,
Path((_conversation_id, message_id)): Path<(Uuid, Uuid)>,
Json(req): Json<ReactToMessageRequest>,
) -> Result<Json<SuccessResponse>, (StatusCode, Json<serde_json::Value>)> {
Ok(Json(SuccessResponse {
success: true,
message: Some(format!("Reaction '{}' added to message {}", req.reaction, message_id)),
message: Some(format!(
"Reaction '{}' added to message {}",
req.reaction, message_id
)),
}))
}
pub async fn pin_message(
State(state): State<Arc<AppState>>,
Path((conversation_id, message_id)): Path<(Uuid, Uuid)>,
State(_state): State<Arc<AppState>>,
Path((_conversation_id, message_id)): Path<(Uuid, Uuid)>,
) -> Result<Json<SuccessResponse>, (StatusCode, Json<serde_json::Value>)> {
Ok(Json(SuccessResponse {
success: true,
@ -358,20 +348,18 @@ pub async fn pin_message(
}))
}
pub async fn search_messages(
State(state): State<Arc<AppState>>,
Path(conversation_id): Path<Uuid>,
Query(params): Query<SearchMessagesQuery>,
State(_state): State<Arc<AppState>>,
Path(_conversation_id): Path<Uuid>,
Query(_params): Query<SearchMessagesQuery>,
) -> Result<Json<Vec<MessageResponse>>, (StatusCode, Json<serde_json::Value>)> {
let messages = vec![];
Ok(Json(messages))
}
pub async fn start_call(
State(state): State<Arc<AppState>>,
State(_state): State<Arc<AppState>>,
Path(conversation_id): Path<Uuid>,
Json(req): Json<StartCallRequest>,
) -> Result<Json<CallResponse>, (StatusCode, Json<serde_json::Value>)> {
@ -395,10 +383,9 @@ pub async fn start_call(
Ok(Json(call))
}
pub async fn join_call(
State(state): State<Arc<AppState>>,
Path(conversation_id): Path<Uuid>,
State(_state): State<Arc<AppState>>,
Path(_conversation_id): Path<Uuid>,
) -> Result<Json<SuccessResponse>, (StatusCode, Json<serde_json::Value>)> {
Ok(Json(SuccessResponse {
success: true,
@ -406,10 +393,9 @@ pub async fn join_call(
}))
}
pub async fn leave_call(
State(state): State<Arc<AppState>>,
Path(conversation_id): Path<Uuid>,
State(_state): State<Arc<AppState>>,
Path(_conversation_id): Path<Uuid>,
) -> Result<Json<SuccessResponse>, (StatusCode, Json<serde_json::Value>)> {
Ok(Json(SuccessResponse {
success: true,
@ -417,10 +403,9 @@ pub async fn leave_call(
}))
}
pub async fn mute_call(
State(state): State<Arc<AppState>>,
Path(conversation_id): Path<Uuid>,
State(_state): State<Arc<AppState>>,
Path(_conversation_id): Path<Uuid>,
) -> Result<Json<SuccessResponse>, (StatusCode, Json<serde_json::Value>)> {
Ok(Json(SuccessResponse {
success: true,
@ -428,10 +413,9 @@ pub async fn mute_call(
}))
}
pub async fn unmute_call(
State(state): State<Arc<AppState>>,
Path(conversation_id): Path<Uuid>,
State(_state): State<Arc<AppState>>,
Path(_conversation_id): Path<Uuid>,
) -> Result<Json<SuccessResponse>, (StatusCode, Json<serde_json::Value>)> {
Ok(Json(SuccessResponse {
success: true,
@ -439,9 +423,8 @@ pub async fn unmute_call(
}))
}
pub async fn start_screen_share(
State(state): State<Arc<AppState>>,
State(_state): State<Arc<AppState>>,
Path(conversation_id): Path<Uuid>,
Json(req): Json<ScreenShareRequest>,
) -> Result<Json<ScreenShareResponse>, (StatusCode, Json<serde_json::Value>)> {
@ -462,10 +445,9 @@ pub async fn start_screen_share(
Ok(Json(screen_share))
}
pub async fn stop_screen_share(
State(state): State<Arc<AppState>>,
Path(conversation_id): Path<Uuid>,
State(_state): State<Arc<AppState>>,
Path(_conversation_id): Path<Uuid>,
) -> Result<Json<SuccessResponse>, (StatusCode, Json<serde_json::Value>)> {
Ok(Json(SuccessResponse {
success: true,
@ -473,10 +455,9 @@ pub async fn stop_screen_share(
}))
}
pub async fn start_recording(
State(state): State<Arc<AppState>>,
Path(conversation_id): Path<Uuid>,
State(_state): State<Arc<AppState>>,
Path(_conversation_id): Path<Uuid>,
) -> Result<Json<SuccessResponse>, (StatusCode, Json<serde_json::Value>)> {
Ok(Json(SuccessResponse {
success: true,
@ -484,10 +465,9 @@ pub async fn start_recording(
}))
}
pub async fn stop_recording(
State(state): State<Arc<AppState>>,
Path(conversation_id): Path<Uuid>,
State(_state): State<Arc<AppState>>,
Path(_conversation_id): Path<Uuid>,
) -> Result<Json<SuccessResponse>, (StatusCode, Json<serde_json::Value>)> {
Ok(Json(SuccessResponse {
success: true,
@ -495,9 +475,8 @@ pub async fn stop_recording(
}))
}
pub async fn create_whiteboard(
State(state): State<Arc<AppState>>,
State(_state): State<Arc<AppState>>,
Path(conversation_id): Path<Uuid>,
) -> Result<Json<WhiteboardResponse>, (StatusCode, Json<serde_json::Value>)> {
let whiteboard_id = Uuid::new_v4();
@ -518,11 +497,10 @@ pub async fn create_whiteboard(
Ok(Json(whiteboard))
}
pub async fn collaborate_whiteboard(
State(state): State<Arc<AppState>>,
Path(conversation_id): Path<Uuid>,
Json(data): Json<serde_json::Value>,
State(_state): State<Arc<AppState>>,
Path(_conversation_id): Path<Uuid>,
Json(_data): Json<serde_json::Value>,
) -> Result<Json<SuccessResponse>, (StatusCode, Json<serde_json::Value>)> {
Ok(Json(SuccessResponse {
success: true,