mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-10-10 17:58:39 +00:00
cli: add name, image and relay server address flags (#6944)
* cli: add --relay-address-server option for chat relay New CLI flag --relay-address-server SERVER selects the SMP server used for the chat relay address link created at startup. Only valid together with --relay; errors out otherwise. Threads Maybe SMPServerWithAuth through APICreateMyAddress to the new agent createConnection parameter. * cli: add --user-display-name option Selects or creates the active user non-interactively: - no active user: create one with the given display name - active user with matching localDisplayName: continue - active user with different name: exit with error Mutually exclusive with --create-bot-display-name. * cli: add --user-image-file option Sets the active user's profile image from a .png/.jpg/.jpeg file at startup. Reads file, base64-encodes as data URL, and updates the user profile directly in the DB - no notification is sent to existing contacts. Skips the update if the stored image already matches. Requires --user-display-name. * cli: address PR review comments - rename APICreateMyAddress field srv_ to server_ - extract repeated `loop` and putStrLn from createActiveUser via prompt where-clause - fuse u_ inspection: validate active user display name in the same case that creates the user when missing * cli: enforce profile image size limit in --user-image-file Reject the file if the encoded data URL exceeds 12500 bytes - matches the cap mobile and desktop UIs pass to resizeImageToStrSize for profile images. Without this, oversized images would be silently set on the user profile. * core: validate profile image size in chat commands Enforced in CreateActiveUser, updateProfile_, newGroup, runUpdateGroupProfile via checkProfileImageSize; max 12500 bytes (matches mobile UIs). * fix: thread new ChatOpts/CoreChatOpts fields through bot/test constructors * bots/docs: filter hidden params before type introspection Hide APICreateMyAddress server_ field so the bot doc generator does not try to introspect SMPServerWithAuth (an unregistered type). * core: validate full encoded profile size Add checkProfileSize / checkGroupProfileSize that encode the full ChatMessage and check against maxEncodedInfoLength, so a long displayName/bio combined with a near-max image is also caught at command time instead of failing later at send time with CEException. Run alongside the existing checkProfileImageSize (image-only cap of 12500 bytes, matching mobile UIs) in CreateActiveUser, updateProfile_, newGroup, runUpdateGroupProfile. Update genProfileImg to fit the cap. * cli: add --headless option for chat relay Skips interactive prompts (relay address creation, display name) so the chat relay can run non-interactively as a service. Requires --relay; creating a new profile also requires --user-display-name. * test: cover profile image size limit and address server Adds tests for two new capabilities: - profile image size validation rejects oversized images - /_address with a server pins the address to the requested SMP server * core: update simplexmq (pass optional SMP server to prepareConnectionLink) * cli: add /set profile image file, fix image flag Add "/set profile image file <path>" command to set the profile image from a .png/.jpg/.jpeg file in a running session. Make --user-image-file create-only: for an existing user it now no-ops with a note instead of failing with "chat not started" (the update ran before the chat controller was started). * core: unify image loading and profile size checks - loadImageFile (CLI) and readProfileImageFile (command) now share one loadImageData; removes the duplicated mime/base64 encoding and its decodeUtf8/safeDecodeUtf8 divergence. A missing --user-image-file no longer crashes with an uncaught IOException, and empty files are rejected. - checkProfileSize/checkGroupProfileSize share checkInfoSize. - --relay-address-server/--headless requires-relay checks use errorWithoutStackTrace, matching the adjacent validation (no callstack dump). * bots/docs: document UpdateProfileImageFromFile as a CLI command
This commit is contained in:
@@ -22,7 +22,7 @@ where
|
||||
import Control.Logger.Simple (LogLevel (..))
|
||||
import qualified Data.Attoparsec.ByteString.Char8 as A
|
||||
import qualified Data.ByteString.Char8 as B
|
||||
import Data.Maybe (fromMaybe)
|
||||
import Data.Maybe (fromMaybe, isJust, isNothing)
|
||||
import Data.Text (Text)
|
||||
import qualified Data.Text as T
|
||||
import Data.Text.Encoding (encodeUtf8)
|
||||
@@ -50,7 +50,9 @@ data ChatOpts = ChatOpts
|
||||
autoAcceptFileSize :: Integer,
|
||||
muteNotifications :: Bool,
|
||||
markRead :: Bool,
|
||||
createBot :: Maybe CreateBotOpts
|
||||
createBot :: Maybe CreateBotOpts,
|
||||
userDisplayName :: Maybe Text,
|
||||
userImageFile :: Maybe FilePath
|
||||
}
|
||||
|
||||
data CoreChatOpts = CoreChatOpts
|
||||
@@ -67,6 +69,8 @@ data CoreChatOpts = CoreChatOpts
|
||||
deviceName :: Maybe Text,
|
||||
chatRelay :: Bool,
|
||||
webPreviewConfig :: Maybe WebPreviewConfig,
|
||||
chatRelayServer :: Maybe SMPServerWithAuth,
|
||||
headless :: Bool,
|
||||
highlyAvailable :: Bool,
|
||||
yesToUpMigrations :: Bool,
|
||||
migrationBackupPath :: Maybe FilePath,
|
||||
@@ -281,6 +285,19 @@ coreChatOptsP appDir defaultDbName = do
|
||||
(Just webDomain, Just webJsonDir) -> Just WebPreviewConfig {webDomain, webJsonDir, webCorsFile, webUpdateInterval, webPreviewItemCount}
|
||||
(Nothing, Nothing) -> Nothing
|
||||
_ -> errorWithoutStackTrace "--relay-web-domain and --relay-web-dir must both be provided"
|
||||
chatRelayServer <-
|
||||
optional $
|
||||
option
|
||||
strParse
|
||||
( long "relay-address-server"
|
||||
<> metavar "SERVER"
|
||||
<> help "SMP server to use for chat relay address link (requires --relay)"
|
||||
)
|
||||
headless <-
|
||||
switch
|
||||
( long "headless"
|
||||
<> help "Run chat relay without interactive prompts, e.g. as a service (requires --relay; on first run also --user-display-name to create the profile)"
|
||||
)
|
||||
highlyAvailable <-
|
||||
switch
|
||||
( long "ha"
|
||||
@@ -325,6 +342,12 @@ coreChatOptsP appDir defaultDbName = do
|
||||
deviceName,
|
||||
chatRelay,
|
||||
webPreviewConfig,
|
||||
chatRelayServer = case chatRelayServer of
|
||||
Just _ | not chatRelay -> errorWithoutStackTrace "--relay-address-server option requires --relay option"
|
||||
_ -> chatRelayServer,
|
||||
headless = case headless of
|
||||
True | not chatRelay -> errorWithoutStackTrace "--headless option requires --relay option"
|
||||
_ -> headless,
|
||||
highlyAvailable,
|
||||
yesToUpMigrations,
|
||||
migrationBackupPath,
|
||||
@@ -438,6 +461,20 @@ chatOptsP appDir defaultDbName = do
|
||||
( long "create-bot-client-service"
|
||||
<> help "Flag for created bot to use client service certificate"
|
||||
)
|
||||
userDisplayName <-
|
||||
optional $
|
||||
strOption
|
||||
( long "user-display-name"
|
||||
<> metavar "NAME"
|
||||
<> help "Use existing active user with this display name, or create one on the first start (incompatible with --create-bot-display-name)"
|
||||
)
|
||||
userImageFile <-
|
||||
optional $
|
||||
strOption
|
||||
( long "user-image-file"
|
||||
<> metavar "FILE"
|
||||
<> help "Set user profile image from .png/.jpg/.jpeg file when the profile is created (requires --user-display-name); ignored if the user already exists (use \"/set profile image file <path>\" to change it)"
|
||||
)
|
||||
pure
|
||||
ChatOpts
|
||||
{ coreOptions,
|
||||
@@ -453,11 +490,17 @@ chatOptsP appDir defaultDbName = do
|
||||
muteNotifications,
|
||||
markRead,
|
||||
createBot = case createBotDisplayName of
|
||||
Just botDisplayName -> Just CreateBotOpts {botDisplayName, allowFiles = createBotAllowFiles, clientService = createBotClientService}
|
||||
Just botDisplayName
|
||||
| isJust userDisplayName -> error "--user-display-name and --create-bot-display-name are mutually exclusive"
|
||||
| otherwise -> Just CreateBotOpts {botDisplayName, allowFiles = createBotAllowFiles, clientService = createBotClientService}
|
||||
Nothing
|
||||
| createBotAllowFiles -> error "--create-bot-allow-files option requires --create-bot-name option"
|
||||
| createBotClientService -> error "--create-bot-client-service option requires --create-bot-name option"
|
||||
| otherwise -> Nothing
|
||||
| otherwise -> Nothing,
|
||||
userDisplayName,
|
||||
userImageFile = case userImageFile of
|
||||
Just _ | isNothing userDisplayName -> error "--user-image-file option requires --user-display-name option"
|
||||
_ -> userImageFile
|
||||
}
|
||||
|
||||
parseProtocolServers :: ProtocolTypeI p => ReadM [ProtoServerWithAuth p]
|
||||
|
||||
Reference in New Issue
Block a user