mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-06-04 10:21:50 +00:00
4fd13c637c
* core: access messaging servers via SOCKS5 proxy * update option info * update simplexmq
163 lines
5.0 KiB
Haskell
163 lines
5.0 KiB
Haskell
{-# LANGUAGE ApplicativeDo #-}
|
|
{-# LANGUAGE DuplicateRecordFields #-}
|
|
{-# LANGUAGE NamedFieldPuns #-}
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
{-# LANGUAGE ScopedTypeVariables #-}
|
|
|
|
module Simplex.Chat.Options
|
|
( ChatOpts (..),
|
|
getChatOpts,
|
|
smpServersP,
|
|
)
|
|
where
|
|
|
|
import qualified Data.Attoparsec.ByteString.Char8 as A
|
|
import qualified Data.ByteString.Char8 as B
|
|
import Data.Maybe (fromMaybe)
|
|
import Network.Socket (HostAddress, SockAddr (..), tupleToHostAddress)
|
|
import Network.Socks5 (SocksConf, defaultSocksConf)
|
|
import Options.Applicative
|
|
import Simplex.Chat.Controller (updateStr, versionStr)
|
|
import Simplex.Messaging.Agent.Protocol (SMPServer)
|
|
import Simplex.Messaging.Encoding.String
|
|
import Simplex.Messaging.Parsers (parseAll)
|
|
import System.FilePath (combine)
|
|
|
|
data ChatOpts = ChatOpts
|
|
{ dbFilePrefix :: String,
|
|
smpServers :: [SMPServer],
|
|
socksProxy :: Maybe SocksConf,
|
|
tcpTimeout :: Int,
|
|
logConnections :: Bool,
|
|
logAgent :: Bool,
|
|
chatCmd :: String,
|
|
chatCmdDelay :: Int,
|
|
chatServerPort :: Maybe String,
|
|
maintenance :: Bool
|
|
}
|
|
|
|
chatOpts :: FilePath -> FilePath -> Parser ChatOpts
|
|
chatOpts appDir defaultDbFileName = do
|
|
dbFilePrefix <-
|
|
strOption
|
|
( long "database"
|
|
<> short 'd'
|
|
<> metavar "DB_FILE"
|
|
<> help "Path prefix to chat and agent database files"
|
|
<> value defaultDbFilePath
|
|
<> showDefault
|
|
)
|
|
smpServers <-
|
|
option
|
|
parseSMPServers
|
|
( long "server"
|
|
<> short 's'
|
|
<> metavar "SERVER"
|
|
<> help "Comma separated list of SMP server(s) to use"
|
|
<> value []
|
|
)
|
|
socksProxy <-
|
|
flag' (Just defaultSocksProxy) (short 'x' <> help "use local SOCKS5 proxy at :9050")
|
|
<|> option
|
|
parseSocksConf
|
|
( long "socks-proxy"
|
|
<> metavar "SOCKS5"
|
|
<> help "`ipv4:port` or `:port` of SOCKS5 proxy"
|
|
<> value Nothing
|
|
)
|
|
t <-
|
|
option
|
|
auto
|
|
( long "tcp-timeout"
|
|
<> metavar "TIMEOUT"
|
|
<> help "TCP timeout, seconds (default: 5/10 without/with SOCKS5 proxy)"
|
|
<> value 0
|
|
)
|
|
logConnections <-
|
|
switch
|
|
( long "connections"
|
|
<> short 'c'
|
|
<> help "Log every contact and group connection on start"
|
|
)
|
|
logAgent <-
|
|
switch
|
|
( long "log-agent"
|
|
<> short 'l'
|
|
<> help "Enable logs from SMP agent"
|
|
)
|
|
chatCmd <-
|
|
strOption
|
|
( long "execute"
|
|
<> short 'e'
|
|
<> metavar "COMMAND"
|
|
<> help "Execute chat command (received messages won't be logged) and exit"
|
|
<> value ""
|
|
)
|
|
chatCmdDelay <-
|
|
option
|
|
auto
|
|
( long "time"
|
|
<> short 't'
|
|
<> metavar "TIME"
|
|
<> help "Time to wait after sending chat command before exiting, seconds"
|
|
<> value 3
|
|
<> showDefault
|
|
)
|
|
chatServerPort <-
|
|
option
|
|
parseServerPort
|
|
( long "chat-server-port"
|
|
<> short 'p'
|
|
<> metavar "PORT"
|
|
<> help "Run chat server on specified port"
|
|
<> value Nothing
|
|
)
|
|
maintenance <-
|
|
switch
|
|
( long "maintenance"
|
|
<> short 'm'
|
|
<> help "Run in maintenance mode (/_start to start chat)"
|
|
)
|
|
pure ChatOpts {dbFilePrefix, smpServers, socksProxy, tcpTimeout = useTcpTimeout socksProxy t, logConnections, logAgent, chatCmd, chatCmdDelay, chatServerPort, maintenance}
|
|
where
|
|
useTcpTimeout p t = 1000000 * if t > 0 then t else maybe 5 (const 10) p
|
|
defaultDbFilePath = combine appDir defaultDbFileName
|
|
|
|
parseSMPServers :: ReadM [SMPServer]
|
|
parseSMPServers = eitherReader $ parseAll smpServersP . B.pack
|
|
|
|
defaultSocksHost :: HostAddress
|
|
defaultSocksHost = tupleToHostAddress (127, 0, 0, 1)
|
|
|
|
defaultSocksProxy :: SocksConf
|
|
defaultSocksProxy = defaultSocksConf $ SockAddrInet 9050 defaultSocksHost
|
|
|
|
parseSocksConf :: ReadM (Maybe SocksConf)
|
|
parseSocksConf = eitherReader $ parseAll socksConfP . B.pack
|
|
where
|
|
socksConfP = do
|
|
host <- maybe defaultSocksHost tupleToHostAddress <$> optional ipv4P
|
|
port <- fromMaybe 9050 <$> optional (A.char ':' *> (fromInteger <$> A.decimal))
|
|
pure . Just . defaultSocksConf $ SockAddrInet port host
|
|
ipv4P = (,,,) <$> ipNum <*> ipNum <*> ipNum <*> A.decimal
|
|
ipNum = A.decimal <* A.char '.'
|
|
|
|
parseServerPort :: ReadM (Maybe String)
|
|
parseServerPort = eitherReader $ parseAll serverPortP . B.pack
|
|
|
|
serverPortP :: A.Parser (Maybe String)
|
|
serverPortP = Just . B.unpack <$> A.takeWhile A.isDigit
|
|
|
|
smpServersP :: A.Parser [SMPServer]
|
|
smpServersP = strP `A.sepBy1` A.char ','
|
|
|
|
getChatOpts :: FilePath -> FilePath -> IO ChatOpts
|
|
getChatOpts appDir defaultDbFileName =
|
|
execParser $
|
|
info
|
|
(helper <*> versionOption <*> chatOpts appDir defaultDbFileName)
|
|
(header versionStr <> fullDesc <> progDesc "Start chat with DB_FILE file and use SERVER as SMP server")
|
|
where
|
|
versionOption = infoOption versionAndUpdate (long "version" <> short 'v' <> help "Show version")
|
|
versionAndUpdate = versionStr <> "\n" <> updateStr
|