packages feed

GrowlNotify 0.2 → 0.3

raw patch · 3 files changed

+84/−19 lines, 3 files

Files

GrowlNotify.cabal view
@@ -1,5 +1,5 @@ Name:           GrowlNotify-Version:        0.2+Version:        0.3 Author:         Nick Burlett Maintainer:     nickburlett@mac.com Description:    Notification utility for Growl.
Network/GrowlNotify.hs view
@@ -1,3 +1,8 @@+-- | A network notification utility to work with Growl <http://growl.info/>. +-- +--   An application must register itself by sending a registrationPacket. Then, to send+--   a notification, send a notificationPacket. Any packet must have an md5sum tacked on+--   to the end before being sent.  module Network.GrowlNotify      ( registrationPacket     , notificationPacket@@ -12,6 +17,7 @@ import qualified Char import Data.Digest.MD5 import Network.Socket+import Network.BSD   growl_udp_port=9887@@ -24,9 +30,11 @@ putString :: String -> Put putString = do putLazyByteString . makeBS --- register this application and its notification with growl--- any notifications will be on by default-registrationPacket :: String -> [String]  -> B.ByteString+-- | register this application and its notification with growl+-- |  any notifications will be on by default+registrationPacket :: String        -- ^ The name of this application+                   -> [String]      -- ^ A list of notifications+                   -> B.ByteString  -- ^ The packet registrationPacket appName notiNames = runPut $ do     putWord8 growl_protocol_version     putWord8 growl_type_registration@@ -43,12 +51,17 @@             putLazyByteString $ makeBS s         lengthnames = length notiNames --- make a notification-notificationPacket :: String -> String -> String -> String -> B.ByteString-notificationPacket appName notification title description = runPut $ do+-- | Create a notification packet+notificationPacket :: Bool          -- ^ True iff the notification should be sticky+                   -> String        -- ^ The name of this application+                   -> String        -- ^ The notification name+                   -> String        -- ^ The title of this notification+                   -> String        -- ^ The notification text+                   -> B.ByteString  -- ^ The packet+notificationPacket sticky appName notification title description = runPut $ do     putWord8 growl_protocol_version     putWord8 growl_type_notification-    putWord16be 0+    putWord16be $ if sticky then 1 else 0     putLength notification     putLength title     putLength description@@ -60,21 +73,27 @@     where         putLength = putWord16be . fromIntegral . length -addMD5Sum :: String -> B.ByteString -> B.ByteString+-- | Tack on the md5sum to the end of the message, with a (possibly empty) password+addMD5Sum :: String         -- ^ The password+          -> B.ByteString   -- ^ The packet (from notificationPacket or registrationPacket)+          -> B.ByteString   -- ^ The message with appended md5sum, ready for sendMessage addMD5Sum password message = B.append message s     where         s = B.pack $ hash $ map fromIntegral $ B.unpack $ B.append message bspassword         bspassword = makeBS password -sendMessage :: String -> B.ByteString -> IO ()+-- | Send the packet +sendMessage :: String       -- ^ The server (an IP address or hostname)+            -> B.ByteString -- ^ The message (with md5sum) to send+            -> IO () sendMessage server m = do+    server' <- getHostByName server     let d = map (Char.chr . fromIntegral) $ B.unpack m     s <- socket AF_INET Datagram  0-    write server s d+    write (hostAddress server') s d     sClose s     -write :: String -> Socket -> String -> IO ()-write server sock s = do-    addr <- inet_addr server+write :: HostAddress -> Socket -> String -> IO ()+write addr sock s = do     sendTo sock s (SockAddrInet (fromIntegral growl_udp_port) addr)      return ()
growlnotify.hs view
@@ -1,14 +1,60 @@ import Network.GrowlNotify import System (getArgs)+import System.Console.GetOpt+import Data.Maybe ( fromMaybe )  main = do     args <- getArgs-    (server, password, title, message) <- case args of-        server:password:title:message -> return $ (server, password, title, message)-        _ -> error "Usage: server password title message"-    let b =  registrationPacket "growlnotify" ["Command-Line Growl Notification"]+    (opts, message) <- growlOpts args+    let Options { optSticky = sticky+                , optName = name+                , optNotification = notification+                , optTitle = title +                , optServer = server+                , optPassword = password } = opts+    let b =  registrationPacket name [notification]     let m = addMD5Sum password b-    let b2 = notificationPacket "growlnotify" "Command-Line Growl Notification" title (unwords message)+    let b2 = notificationPacket sticky name notification title (unwords message)     let m2 = addMD5Sum password b2     sendMessage server m      sendMessage server m2+++data Options = Options  { optSticky   :: Bool+                        , optNotification :: String+                        , optName      :: String+                        , optTitle     :: String+                        , optServer    :: String+                        , optPassword  :: String+                        }+                        +startOptions :: Options+startOptions = Options { optSticky   = False+                       , optNotification = "Cmdline Growl Notification"+                       , optName     = "growlnotify"+                       , optTitle    = "Network Notification"+                       , optServer   = "127.0.0.1"+                       , optPassword = ""+                       }+                        +options :: [OptDescr (Options -> IO Options)]+options =+ [ Option ['k']  ["sticky"]       (NoArg (\opt -> return opt {optSticky=True}) ) "sticky message"+ , Option ['n']  ["programname"]  (ReqArg (\arg opt -> return opt {optName=arg}) "NAME")   "program registration NAME"+ , Option ['s']  ["server"]       (ReqArg (\arg opt -> return opt {optServer=arg}) "SERVER") "growl SERVER"+ , Option ['p']  ["password"]     (ReqArg (\arg opt -> return opt {optPassword=arg}) "PASSWORD")   "growl PASSWORD"+ , Option ['N']  ["notification"] (ReqArg (\arg opt -> return opt {optNotification=arg}) "NOTIFICATION") "NOTIFICATION"+ , Option ['t']  ["title"]        (ReqArg (\arg opt -> return opt {optTitle=arg}) "TITLE") "message TITLE"+ ]++++growlOpts :: [String] -> IO (Options, [String])+growlOpts argv = do+    -- Parse options, getting a list of option actions+    let (actions, nonOptions, errors) = getOpt RequireOrder options argv++    -- Here we thread startOptions through all supplied option actions+    opts <- foldl (>>=) (return startOptions) actions+    +    return (opts, nonOptions)