diff --git a/crates/meilisearch/src/analytics/segment_analytics.rs b/crates/meilisearch/src/analytics/segment_analytics.rs index ee8a9ee20..2c0121ffc 100644 --- a/crates/meilisearch/src/analytics/segment_analytics.rs +++ b/crates/meilisearch/src/analytics/segment_analytics.rs @@ -277,6 +277,7 @@ impl Infos { log_level, indexer_options, config_file_path, + contact_email: _, no_analytics: _, } = options; diff --git a/crates/meilisearch/src/main.rs b/crates/meilisearch/src/main.rs index b16dda097..cca704df5 100644 --- a/crates/meilisearch/src/main.rs +++ b/crates/meilisearch/src/main.rs @@ -21,6 +21,7 @@ use meilisearch::{ }; use meilisearch_auth::{generate_master_key, AuthController, MASTER_KEY_MIN_SIZE}; use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; +use tokio::io::{AsyncBufReadExt, BufReader}; use tracing::level_filters::LevelFilter; use tracing_subscriber::layer::SubscriberExt as _; use tracing_subscriber::Layer; @@ -89,10 +90,16 @@ async fn main() -> anyhow::Result<()> { } async fn try_main() -> anyhow::Result<()> { - let (opt, config_read_from) = Opt::try_build()?; + let (mut opt, config_read_from) = Opt::try_build()?; std::panic::set_hook(Box::new(on_panic)); + opt.contact_email = match opt.contact_email.as_ref().map(|email| email.as_deref()) { + Some(Some("false")) | None => prompt_for_contact_email().await.map(Some)?, + Some(Some(email)) => Some(Some(email.to_string())), + Some(None) => None, + }; + anyhow::ensure!( !(cfg!(windows) && opt.experimental_reduce_indexing_memory_usage), "The `experimental-reduce-indexing-memory-usage` flag is not supported on Windows" @@ -139,6 +146,27 @@ async fn try_main() -> anyhow::Result<()> { Ok(()) } +/// Prompt the user about the contact email for support and news. +/// It only displays the prompt if the input is an interactive terminal. +async fn prompt_for_contact_email() -> anyhow::Result> { + let stdin = tokio::io::stdin(); + + if !stdin.is_terminal() { + return Ok(None); + } + + println!("Would you mind providing your contact email for support and news?"); + println!("We will use it to contact you with news only."); + print!("contact email> "); + std::io::stdout().flush()?; + + let mut email = String::new(); + let mut stdin = BufReader::new(stdin); + let _ = stdin.read_line(&mut email).await?; + + Ok(Some(email.trim().to_string())) +} + async fn run_http( index_scheduler: Arc, auth_controller: Arc, diff --git a/crates/meilisearch/src/option.rs b/crates/meilisearch/src/option.rs index 6e06b161d..8b34ef8dd 100644 --- a/crates/meilisearch/src/option.rs +++ b/crates/meilisearch/src/option.rs @@ -66,6 +66,7 @@ const MEILI_EXPERIMENTAL_LIMIT_BATCHED_TASKS_TOTAL_SIZE: &str = const MEILI_EXPERIMENTAL_EMBEDDING_CACHE_ENTRIES: &str = "MEILI_EXPERIMENTAL_EMBEDDING_CACHE_ENTRIES"; const MEILI_EXPERIMENTAL_NO_SNAPSHOT_COMPACTION: &str = "MEILI_EXPERIMENTAL_NO_SNAPSHOT_COMPACTION"; +const MEILI_CONTACT_EMAIL: &str = "MEILI_CONTACT_EMAIL"; const DEFAULT_CONFIG_FILE_PATH: &str = "./config.toml"; const DEFAULT_DB_PATH: &str = "./data.ms"; const DEFAULT_HTTP_ADDR: &str = "localhost:7700"; @@ -347,6 +348,10 @@ pub struct Opt { #[serde(default)] pub log_level: LogLevel, + /// Sets the email address to contact for support and news. + #[clap(long, env = MEILI_CONTACT_EMAIL)] + pub contact_email: Option>, + /// Experimental contains filter feature. For more information, /// see: /// @@ -556,6 +561,7 @@ impl Opt { ignore_dump_if_db_exists: _, config_file_path: _, no_analytics, + contact_email, experimental_contains_filter, experimental_enable_metrics, experimental_search_queue_size, @@ -588,6 +594,10 @@ impl Opt { } export_to_env_if_not_present(MEILI_NO_ANALYTICS, no_analytics.to_string()); + export_to_env_if_not_present( + MEILI_CONTACT_EMAIL, + contact_email.flatten().unwrap_or_else(|| "false".to_string()), + ); export_to_env_if_not_present( MEILI_HTTP_PAYLOAD_SIZE_LIMIT, http_payload_size_limit.to_string(),