packages feed

push-notify-apn-0.2.0.1: app/Main.hs

{-# LANGUAGE OverloadedStrings #-}
module Main where

import Control.Concurrent
import Control.Monad
import Data.Maybe
import Data.Semigroup ((<>))
import Options.Applicative

import qualified Data.ByteString.Char8 as B8
import qualified Data.Text as T
import qualified Data.Text.IO as TI

import Network.PushNotify.APN


data ApnOptions = ApnOptions
  { certpath    :: !String
  , keypath     :: !String
  , capath      :: !String
  , topic       :: !String
  , tokens      :: !([String])
  , sandbox     :: !Bool
  , interactive :: !Bool
  , text        :: !(Maybe String) }

p :: Parser ApnOptions
p = ApnOptions
      <$> strOption
          ( short 'c'
         <> metavar "CERTIFICATE"
         <> help "Path to the certificate" )
      <*> strOption
          ( short 'k'
         <> metavar "PRIVATEKEY"
         <> help "Path to the certificate's private key" )
      <*> strOption
          ( short 'a'
         <> metavar "CATRUSTSTORE"
         <> help "Path to the CA truststore" )
      <*> strOption
          ( short 'b'
         <> metavar "BUNDLEID"
         <> help "Bundle ID of the app to send the notification to. Must correspond to the certificate." )
      <*> many ( strOption
          ( short 't'
         <> metavar "TOKEN"
         <> help "Tokens of the devices to send the notification to" ) )
      <*> switch
          ( long "sandbox"
         <> short 's'
         <> help "Whether to use the sandbox (non-production deployments)" )
      <*> switch
          ( long "interactive"
         <> short 'i'
         <> help "Run an interactive mode; each line must have this format: token:message " )
      <*> optional (strOption
          ( short 'm'
         <> metavar "MESSAGE"
         <> help "Message to send to the device" ))
      

main :: IO ()
main = send =<< execParser opts
  where
    opts = info (p <**> helper)
      ( fullDesc
     <> progDesc "Sends a push notification to an apple device"
     <> header "apn- a test for the apn library" )

send :: ApnOptions -> IO ()
send o = do
    let mkSession =
            newSession (keypath o) (certpath o) (capath o) (sandbox o) 10 1 (B8.pack $ topic o)
    session <- mkSession
    if interactive o
    then
        let loop sess = do
                TI.putStrLn "Message in the form token:sound:title:message please"
                line <- TI.getLine
                let parts = T.splitOn ":" line
                if length parts >= 4
                then
                    let token   = hexEncodedToken $ head parts
                        text    = T.intercalate ":" (drop 3 parts)
                        title   = parts !! 2
                        sound   = parts !! 1
                        payload = setSound sound . alertMessage title $ text
                        message = newMessage payload
                    in (sendMessage sess token message >>= TI.putStrLn . T.pack . show) >> loop sess
                else case line of
                    "close" -> closeSession sess >> loop sess
                    "reset" -> mkSession >>= loop
                    "quit"  -> return ()
                    _ -> TI.putStrLn "Erroneous format" >> loop sess
        in loop session
    else do
        when (isNothing $ text o) $ error "You need to specify a message with -m"
        let payload  = alertMessage "push-notify-apn" (T.pack $ fromJust $ text o)
            message  = newMessage payload
        forM_ (tokens o) $ \token ->
            let apntoken = hexEncodedToken . T.pack $ token
            in sendMessage session apntoken message >>= print