packages feed

irc-fun-client 0.1.0.0 → 0.1.1.0

raw patch · 6 files changed

+347/−11 lines, 6 filesdep +auto-updatedep +fast-loggerdep +timePVP ok

version bump matches the API change (PVP)

Dependencies added: auto-update, fast-logger, time, time-units, unordered-containers

API changes (from Hackage documentation)

+ Network.IRC.Fun.Client.ChannelLogger: Enter :: NickName -> ChannelName -> LogEvent
+ Network.IRC.Fun.Client.ChannelLogger: EnterChan :: NickName -> ChanLogEvent
+ Network.IRC.Fun.Client.ChannelLogger: Leave :: NickName -> ChannelName -> LogEvent
+ Network.IRC.Fun.Client.ChannelLogger: LeaveAll :: NickName -> LogEvent
+ Network.IRC.Fun.Client.ChannelLogger: LeaveChan :: NickName -> ChanLogEvent
+ Network.IRC.Fun.Client.ChannelLogger: Message :: NickName -> ChannelName -> String -> LogEvent
+ Network.IRC.Fun.Client.ChannelLogger: MessageChan :: NickName -> String -> ChanLogEvent
+ Network.IRC.Fun.Client.ChannelLogger: Rename :: NickName -> NickName -> LogEvent
+ Network.IRC.Fun.Client.ChannelLogger: RenameInChan :: NickName -> NickName -> ChanLogEvent
+ Network.IRC.Fun.Client.ChannelLogger: data ChanLogEvent
+ Network.IRC.Fun.Client.ChannelLogger: data LogEvent
+ Network.IRC.Fun.Client.ChannelLogger: data Logger
+ Network.IRC.Fun.Client.ChannelLogger: fromClientEvent :: Event -> Maybe LogEvent
+ Network.IRC.Fun.Client.ChannelLogger: instance Show ChanLogEvent
+ Network.IRC.Fun.Client.ChannelLogger: instance Show LogEvent
+ Network.IRC.Fun.Client.ChannelLogger: logEvent :: Logger -> ChanLogEvent -> IO ()
+ Network.IRC.Fun.Client.ChannelLogger: logFilePath :: FilePath -> String -> ChannelName -> FilePath
+ Network.IRC.Fun.Client.ChannelLogger: newLogger :: IO String -> FilePath -> IO Logger
+ Network.IRC.Fun.Client.ChannelLogger: removeLogger :: Logger -> IO ()
+ Network.IRC.Fun.Client.NickTracker: ChannelTracker :: (HashSet NickName) -> ChannelTracker
+ Network.IRC.Fun.Client.NickTracker: NetworkTracker :: (HashMap ChannelName ChannelTracker) -> NetworkTracker
+ Network.IRC.Fun.Client.NickTracker: addChannel :: ChannelName -> [NickName] -> NetworkTracker -> NetworkTracker
+ Network.IRC.Fun.Client.NickTracker: addMember :: NickName -> ChannelTracker -> ChannelTracker
+ Network.IRC.Fun.Client.NickTracker: addToChannel :: ChannelName -> NickName -> NetworkTracker -> NetworkTracker
+ Network.IRC.Fun.Client.NickTracker: isInChannel :: NickName -> ChannelName -> NetworkTracker -> Bool
+ Network.IRC.Fun.Client.NickTracker: isMemberOf :: NickName -> ChannelTracker -> Bool
+ Network.IRC.Fun.Client.NickTracker: newChannel :: [NickName] -> ChannelTracker
+ Network.IRC.Fun.Client.NickTracker: newNetwork :: NetworkTracker
+ Network.IRC.Fun.Client.NickTracker: newtype ChannelTracker
+ Network.IRC.Fun.Client.NickTracker: newtype NetworkTracker
+ Network.IRC.Fun.Client.NickTracker: presence :: NickName -> NetworkTracker -> [ChannelName]
+ Network.IRC.Fun.Client.NickTracker: removeChannel :: ChannelName -> NetworkTracker -> NetworkTracker
+ Network.IRC.Fun.Client.NickTracker: removeChannels :: [ChannelName] -> NetworkTracker -> NetworkTracker
+ Network.IRC.Fun.Client.NickTracker: removeFromChannel :: ChannelName -> NickName -> NetworkTracker -> NetworkTracker
+ Network.IRC.Fun.Client.NickTracker: removeFromNetwork :: NickName -> NetworkTracker -> NetworkTracker
+ Network.IRC.Fun.Client.NickTracker: removeMember :: NickName -> ChannelTracker -> ChannelTracker
+ Network.IRC.Fun.Client.Time: currentTimeGetter :: IO (IO (UTCTime, String))

Files

NEWS view
@@ -3,6 +3,35 @@   +irc-fun-client 0.1.1.0 -- 2015-09-10+====================================++General, build and documentation changes:++* (None)++New APIs, features and enhancements:++* Basic channel logger API+* Efficient and scalable time getter+* Channel member tracker++Bug fixes:++* (None)++Dependency changes:++* Add dependency: auto-update+* Add dependency: fast-logger+* Add dependency: time+* Add dependency: time-units+* Add dependency: unordered-containers+++++ irc-fun-client 0.1.0.0 -- 2015-08-09 ==================================== 
irc-fun-client.cabal view
@@ -1,5 +1,5 @@ name:                irc-fun-client-version:             0.1.0.0+version:             0.1.1.0 synopsis:            Another library for writing IRC clients. description:   This is an IRC client library that uses @irc-fun-messages@ library package@@ -24,14 +24,22 @@  library   exposed-modules:     Network.IRC.Fun.Client+                     , Network.IRC.Fun.Client.ChannelLogger                      , Network.IRC.Fun.Client.Commands                      , Network.IRC.Fun.Client.Events                      , Network.IRC.Fun.Client.IO+                     , Network.IRC.Fun.Client.NickTracker+                     , Network.IRC.Fun.Client.Time                      , Network.IRC.Fun.Client.Util   -- other-modules:   -- other-extensions:    -  build-depends:       base             >=4.7 && <5+  build-depends:       auto-update+                     , base                 >=4.7 && <5                      , irc-fun-messages-                     , network          >=2.3+                     , fast-logger          >=2.4.1+                     , network              >=2.3+                     , time                 >=1.5+                     , time-units           >=1+                     , unordered-containers >=0.2.5   hs-source-dirs:      src   default-language:    Haskell2010
src/Network/IRC/Fun/Client.hs view
@@ -20,6 +20,11 @@ -- * "Commands": Provides functions for sending IRC commands to the server. -- * "Events": Provides an Event type and functions for receiving IRC events. --   These events are an abstraction on top of IRC messages.+-- * "ChannelLogger": Provides a system for logging IRC channel activity into a+--   file.+-- * "Time": Provides an efficient scalable way to get the current time, and a+--   formatted time string for use in the logger.+-- * "NickTracker": Provides functions for tracking channels and their members -- * "Util": Miscellaneous helper functions which could be useful to clients -- -- If you're writing an IRC client, here is a suggestion for how to begin:@@ -32,14 +37,20 @@ --     need to receive IRC messages directly, use functions from the "IO" --     module. module Network.IRC.Fun.Client-    ( module Network.IRC.Fun.Client.Commands-    , module Network.IRC.Fun.Client.Events-    , module Network.IRC.Fun.Client.IO-    , module Network.IRC.Fun.Client.Util+    ( module ChannelLogger+    , module Commands+    , module Events+    , module IO+    , module NickTracker+    , module Util+    , module Time     ) where -import Network.IRC.Fun.Client.Commands-import Network.IRC.Fun.Client.Events-import Network.IRC.Fun.Client.IO-import Network.IRC.Fun.Client.Util+import qualified Network.IRC.Fun.Client.ChannelLogger as ChannelLogger+import qualified Network.IRC.Fun.Client.Commands      as Commands+import qualified Network.IRC.Fun.Client.Events        as Events+import qualified Network.IRC.Fun.Client.IO            as IO+import qualified Network.IRC.Fun.Client.NickTracker   as NickTracker+import qualified Network.IRC.Fun.Client.Util          as Util+import qualified Network.IRC.Fun.Client.Time          as Time
+ src/Network/IRC/Fun/Client/ChannelLogger.hs view
@@ -0,0 +1,116 @@+{- This file is part of irc-fun-client.+ -+ - Written in 2015 by fr33domlover <fr33domlover@rel4tion.org>.+ -+ - ♡ Copying is an act of love. Please copy, reuse and share.+ -+ - The author(s) have dedicated all copyright and related and neighboring+ - rights to this software to the public domain worldwide. This software is+ - distributed without any warranty.+ -+ - You should have received a copy of the CC0 Public Domain Dedication along+ - with this software. If not, see+ - <http://creativecommons.org/publicdomain/zero/1.0/>.+ -}++{-# LANGUAGE OverloadedStrings #-}++module Network.IRC.Fun.Client.ChannelLogger+    ( Logger ()+    , ChanLogEvent (..)+    , LogEvent (..)+    , logFilePath+    , newLogger+    , removeLogger+    , logEvent+    , fromClientEvent+    )+where++import Control.Monad (liftM)+import Data.Monoid ((<>))+import Network.IRC.Fun.Client.Events (Event (..))+import Network.IRC.Fun.Messages.TypeAliases (NickName, ChannelName)+import System.Log.FastLogger++data Logger = Logger+    { loggerSet     :: LoggerSet+    , loggerGetTime :: IO String+    }++data ChanLogEvent+    = EnterChan NickName+    | LeaveChan NickName+    | MessageChan NickName String+    | RenameInChan NickName NickName+    deriving Show++data LogEvent+    = Enter NickName ChannelName+    | Leave NickName ChannelName+    | LeaveAll NickName+    | Message NickName ChannelName String+    | Rename NickName NickName+    deriving Show++-- | Utility for constructing a log file path.+logFilePath :: FilePath    -- ^ Directory in which to place log files. Relative+                           -- to the program's working directory, or absolute.+            -> String      -- ^ Server label, e.g. @\"freenode\"@+            -> ChannelName -- ^ IRC channel name, e.g. @\"#freepost\"@+            -> FilePath+logFilePath dir server chan = dir ++ "/" ++ server ++ "." ++ chan ++ ".irc"++-- | Create a logger for a given IRC channel.+newLogger :: IO String -- ^ Action which returns a formatted time string. You+                       -- can use "Network.IRC.Fun.Client.Time" to create such+                       -- an action.+          -> FilePath  -- ^ Path of the log file+          -> IO Logger+newLogger getTime path = do+    lset <- newFileLoggerSet defaultBufSize path+    return $ Logger+        { loggerSet     = lset+        , loggerGetTime = getTime+        }++-- | Flush buffers and release resources.+--+-- When the logger is paused for a long period of time (i.e. not momentarily -+-- e.g. by a user disabling channel logging via UI), you can use this to+-- release resources. Later, when logging is needed again, create a fresh new+-- logger.+--+-- If your client joins many channels but log few of them, you can save+-- resources by keeping open loggers only for the few logged channels.+removeLogger :: Logger -> IO ()+removeLogger logger = rmLoggerSet $ loggerSet logger++formatEvent :: ChanLogEvent -> LogStr+formatEvent e = case e of+    EnterChan nick       -> "|-->| " <> toLogStr nick <> " has joined"+    LeaveChan nick       -> "|<--| " <> toLogStr nick <> " has left"+    MessageChan nick msg -> "<" <> toLogStr nick <> "> " <> toLogStr msg+    RenameInChan old new -> "|---| " <> toLogStr old <> " is now known as "+                                     <> toLogStr new++formatLine :: IO String -> ChanLogEvent -> IO LogStr+formatLine getTime event = do+    t <- getTime+    return $ toLogStr t <> " " <> formatEvent event++-- | Write a log message corresponding to a given event.+logEvent :: Logger -> ChanLogEvent -> IO ()+logEvent logger event = do+    line <- formatLine (loggerGetTime logger) event+    pushLogStrLn (loggerSet logger) line++-- | If an IRC client event can be logged, return a matching log event and the+-- channel in which the event has occured.+fromClientEvent :: Event -> Maybe LogEvent+fromClientEvent event = case event of+    Join chan nick                       -> Just $ Enter nick chan+    Part chan nick _reason               -> Just $ Leave nick chan+    Quit nick _reason                    -> Just $ LeaveAll nick+    ChannelMessage chan nick msg _notice -> Just $ Message nick chan msg+    _                                    -> Nothing
+ src/Network/IRC/Fun/Client/NickTracker.hs view
@@ -0,0 +1,126 @@+{- This file is part of irc-fun-client.+ -+ - Written in 2015 by fr33domlover <fr33domlover@rel4tion.org>.+ -+ - ♡ Copying is an act of love. Please copy, reuse and share.+ -+ - The author(s) have dedicated all copyright and related and neighboring+ - rights to this software to the public domain worldwide. This software is+ - distributed without any warranty.+ -+ - You should have received a copy of the CC0 Public Domain Dedication along+ - with this software. If not, see+ - <http://creativecommons.org/publicdomain/zero/1.0/>.+ -}++-- | Using the tools provided here, you can track which users are members of+-- which channels. This functionality has a veriety of uses, e.g. displaying+-- user lists in client UI and logging/displaying quit messages in the correct+-- channel logs/buffers.+module Network.IRC.Fun.Client.NickTracker+    ( ChannelTracker (..)+    , NetworkTracker (..)+    , isMemberOf+    , isInChannel+    , presence+    , newChannel+    , newNetwork+    , addMember+    , addToChannel+    , addChannel+    , removeMember+    , removeFromChannel+    , removeFromNetwork+    , removeChannel+    , removeChannels+    )+where++import qualified Data.HashMap.Lazy as M+import qualified Data.HashSet as S+import Network.IRC.Fun.Messages.TypeAliases++newtype ChannelTracker = ChannelTracker (S.HashSet NickName)++newtype NetworkTracker = NetworkTracker (M.HashMap ChannelName ChannelTracker)++-- | Check whether a nickname is present in a channel.+isMemberOf :: NickName -> ChannelTracker -> Bool+nick `isMemberOf` (ChannelTracker nicks) = nick `S.member` nicks++-- | Check whether a nickname is present in a channel.+isInChannel :: NickName -> ChannelName -> NetworkTracker -> Bool+isInChannel nick chan (NetworkTracker cts) =+    case M.lookup chan cts of+        Nothing -> False+        Just ct -> nick `isMemberOf` ct++applySnd :: (b -> c) -> (a, b) -> (a, c)+applySnd f (x, y) = (x, f y)++-- | Check in which channels a nickname is present.+presence :: NickName -> NetworkTracker -> [ChannelName]+presence nick (NetworkTracker cts) =+    [ chan | (chan, True) <- map (applySnd (nick `isMemberOf`)) $ M.toList cts]++-- | Record a channel with the given present nicknames.+newChannel :: [NickName] -> ChannelTracker+newChannel nicks = ChannelTracker $ S.fromList nicks++-- | Create new tracker.+newNetwork :: NetworkTracker+newNetwork = NetworkTracker $ M.empty++-- | Record a nickname being present in a channel.+addMember :: NickName -> ChannelTracker -> ChannelTracker+addMember nick (ChannelTracker nicks) = ChannelTracker $ S.insert nick nicks++-- | Record a nickname being present in a channel.+addToChannel :: ChannelName -> NickName -> NetworkTracker -> NetworkTracker+addToChannel chan nick (NetworkTracker cts) = NetworkTracker $ f cts+    where+    f chans =+        case M.lookup chan chans of+            Nothing ->+                let ct = ChannelTracker $ S.singleton nick+                in  M.insert chan ct chans+            Just (ChannelTracker nicks) ->+                let ct = ChannelTracker $ S.insert nick nicks+                in  M.insert chan ct chans++-- | Record a channel with the given present nicknames.+addChannel :: ChannelName -> [NickName] -> NetworkTracker -> NetworkTracker+addChannel chan nicks (NetworkTracker cts) = NetworkTracker $ f cts+    where+    f = M.insert chan $ newChannel nicks++-- | Record a channel not having a given nickname anymore.+removeMember :: NickName -> ChannelTracker -> ChannelTracker+removeMember nick (ChannelTracker nicks) = ChannelTracker $ S.delete nick nicks++-- | Record a channel not having a given nickname anymore.+removeFromChannel :: ChannelName+                  -> NickName+                  -> NetworkTracker+                  -> NetworkTracker+removeFromChannel chan nick (NetworkTracker cts) = NetworkTracker $ f cts+    where+    f chans = M.adjust (removeMember nick) chan chans++-- | Record a nickname not being present in any channel anymore.+removeFromNetwork :: NickName -> NetworkTracker -> NetworkTracker+removeFromNetwork nick (NetworkTracker cts) = NetworkTracker $ f cts+    where+    f = M.map (removeMember nick)++-- | Remove a channel from the tracker.+removeChannel :: ChannelName -> NetworkTracker -> NetworkTracker+removeChannel chan (NetworkTracker cts) = NetworkTracker $ f cts+    where+    f = M.delete chan++-- | Remove channels from the tracker.+removeChannels :: [ChannelName] -> NetworkTracker -> NetworkTracker+removeChannels chans (NetworkTracker cts) = NetworkTracker $ f cts+    where+    f ts = ts `M.difference` M.fromList (zip chans (repeat ()))
+ src/Network/IRC/Fun/Client/Time.hs view
@@ -0,0 +1,46 @@+{- This file is part of irc-fun-client.+ -+ - Written in 2015 by fr33domlover <fr33domlover@rel4tion.org>.+ -+ - ♡ Copying is an act of love. Please copy, reuse and share.+ -+ - The author(s) have dedicated all copyright and related and neighboring+ - rights to this software to the public domain worldwide. This software is+ - distributed without any warranty.+ -+ - You should have received a copy of the CC0 Public Domain Dedication along+ - with this software. If not, see+ - <http://creativecommons.org/publicdomain/zero/1.0/>.+ -}++-- | Get the current UTC time and formatted time strings, using auto-update to+-- run the actual action periodically and by demand. In other words, these+-- functions can safely be used at high frequency.+--+-- Intended use: Create a single getter in the main thread and pass as needed+-- to other threads for their own use.+module Network.IRC.Fun.Client.Time+    ( currentTimeGetter+    )+where++import Control.AutoUpdate+import Data.Time.Clock (UTCTime, getCurrentTime)+import Data.Time.Format (defaultTimeLocale, formatTime)+import Data.Time.Units (Second, toMicroseconds)++format = formatTime defaultTimeLocale "%F %T"++action = do+    t <- getCurrentTime+    return (t, format t)++settings = defaultUpdateSettings+    { updateFreq   = fromInteger $ toMicroseconds (1 :: Second)+    , updateAction = action+    }++-- | Make a getter which returns the current time, and a formatted time string+-- for use in IRC logs.+currentTimeGetter :: IO (IO (UTCTime, String))+currentTimeGetter = mkAutoUpdate settings