packages feed

Hach-0.0.1: client/Client.hs

{-# LANGUAGE UnicodeSyntax #-}
module Main (main) where

import Control.Applicative ((<$>))
import Control.Concurrent (forkIO)
import Control.Exception
import Control.Monad (forever)
import Data.List (isPrefixOf)
import Data.Time.Clock (getCurrentTime)
import Data.Time.Format
import Network
import System.Environment (getArgs)
import System.Console.GetOpt
import System.IO
import System.Locale
import Text.Printf (printf)

import Format
import Hach.Types

client ∷ Nick → Handle → IO ()
client nick h = forkIO
  (handle onDisconnect $ forever $ hGetLine h >>= printMessage . read) >>
  (hPrint h $ CSetNick nick) >>
  (handle onExit $ forever $ getLine >>= hPutStrLn h . processMessage >> hideOwnMessage)
    where processMessage t
            | commandAction  `isPrefixOf` t = show . CAction $ drop (length commandAction) t
            | commandSetNick `isPrefixOf` t = show . CSetNick $ drop (length commandSetNick) t
            | otherwise = show $ CMessage t
          hideOwnMessage = putStrLn "\ESC[2A"
          onExit (SomeException _) = putStrLn $ nick ++" has left"
          onDisconnect (SomeException _) = putStrLn "Server closed connection"

printMessage ∷ S2C → IO ()
printMessage message = do
  timestamp ← formatTime defaultTimeLocale timeFormat <$> getCurrentTime
  printf (format message) timestamp (getText message)
  where getText ∷ S2C → String
        getText (SMessage _ text) = text
        getText (SAction  _ text) = text
        getText (SSetNick _ text) = text
        getText (SSystem    text) = text

main ∷ IO ()
main = do
  (serverIP, nick) ← parseArgs =<< getArgs
  putStrLn $ "Connected to " ++ serverIP
  withSocketsDo $
    do h ← connectTo serverIP $ PortNumber 7123
       hSetBuffering h LineBuffering
       client nick h

data Flag = ServerIP String
          | ClientNick String

options ∷ [OptDescr Flag]
options =
  [ Option "s" ["server"] (ReqArg ServerIP "server_ip") "set server ip adress"
  , Option "n" ["nick"] (ReqArg ClientNick "user nickname") "set user nickname"
  ]

parseArgs ∷ [String] → IO (String, String)
parseArgs argv = case getOpt Permute options argv of
  (os, _, []) → do
    let ips = [ s | ServerIP s ← os ]
    let nicks = [ n | ClientNick n ← os ]
    case (ips, nicks) of
      ([ip], [nick]) → return (ip, nick)
      (_, _) → error $ usageInfo usage options
  (_, _, es) → error $ concat es ++ usageInfo usage options
  where usage = "Usage: hach-client [OPTIONS...]"