-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Lambdabot core functionality
--   
--   Lambdabot is an IRC bot written over several years by those on the
--   #haskell IRC channel.
--   
--   Manage plugins, network connections, configurations and much more.
@package lambdabot-core
@version 5.3.0.1


-- | Time compatibility layer (stuff to support old lambdabot state
--   serialization formats)
--   
--   TODO: trim this down to just the explicitly serialization-related
--   stuff
module Lambdabot.Compat.AltTime

-- | Wrapping ClockTime (which doesn't provide a Read instance!) seems
--   easier than talking care of the serialization of UserStatus ourselves.
data ClockTime

-- | Retrieve the current clocktime
getClockTime :: IO ClockTime

-- | Difference of two clock times
diffClockTimes :: ClockTime -> ClockTime -> TimeDiff

-- | <tt><a>addToClockTime</a> d t</tt> adds a time difference <tt>d</tt>
--   and a -- clock time <tt>t</tt> to yield a new clock time.
addToClockTime :: TimeDiff -> ClockTime -> ClockTime

-- | Pretty-print a TimeDiff. Both positive and negative Timediffs produce
--   the same output.
--   
--   14d 17h 8m 53s
timeDiffPretty :: TimeDiff -> String
newtype TimeDiff
TimeDiff :: NominalDiffTime -> TimeDiff
noTimeDiff :: TimeDiff
instance GHC.Classes.Ord Lambdabot.Compat.AltTime.TimeDiff
instance GHC.Classes.Eq Lambdabot.Compat.AltTime.TimeDiff
instance GHC.Classes.Eq Lambdabot.Compat.AltTime.ClockTime
instance GHC.Show.Show Lambdabot.Compat.AltTime.TimeDiff
instance GHC.Read.Read Lambdabot.Compat.AltTime.TimeDiff
instance Data.Binary.Class.Binary Lambdabot.Compat.AltTime.TimeDiff
instance GHC.Show.Show Lambdabot.Compat.AltTime.ClockTime
instance GHC.Read.Read Lambdabot.Compat.AltTime.ClockTime
instance Data.Binary.Class.Binary Lambdabot.Compat.AltTime.ClockTime


-- | Extensible configuration system for lambdabot
--   
--   TODO: there's notthing lambdabot-specific about this, it could be a
--   useful standalone library.
module Lambdabot.Config
data Config t
getConfigDefault :: Config t -> t
mergeConfig :: Config t -> t -> t -> t
class Monad m => MonadConfig m
getConfig :: MonadConfig m => Config a -> m a

-- | Define a new configuration key with the specified name, type and
--   default value
--   
--   You should probably also provide an explicit export list for any
--   module that defines config keys, because the definition introduces a
--   few extra types that will clutter up the export list otherwise.
config :: String -> TypeQ -> ExpQ -> Q [Dec]

-- | Like <a>config</a>, but also allowing you to specify a "merge rule"
--   that will be used to combine multiple bindings of the same key.
--   
--   For example, in <a>Lambdabot.Config.Core</a>, <tt>onStartupCmds</tt>
--   is defined as a list of commands to execute on startup. Its default
--   value is ["offlinerc"], so if a user invokes the default lambdabot
--   executable without arguments, they will get a REPL. Each instance of
--   "-e" on the command-line adds a binding of the form:
--   
--   <pre>
--   onStartupCmds :=&gt; [command]
--   </pre>
--   
--   So if they give one "-e", it replaces the default (note that it is
--   _not_ merged with the default - the default is discarded), and if they
--   give more than one they are merged using the specified operation (in
--   this case, <a>(++)</a>).
configWithMerge :: ExpQ -> String -> TypeQ -> ExpQ -> Q [Dec]
instance Lambdabot.Config.MonadConfig m => Lambdabot.Config.MonadConfig (Control.Monad.Trans.Reader.ReaderT r m)
instance (Lambdabot.Config.MonadConfig m, GHC.Base.Monoid w) => Lambdabot.Config.MonadConfig (Control.Monad.Trans.Writer.Lazy.WriterT w m)
instance Lambdabot.Config.MonadConfig m => Lambdabot.Config.MonadConfig (Control.Monad.Trans.State.Lazy.StateT s m)
instance Data.GADT.Internal.GEq Lambdabot.Config.Config
instance Data.GADT.Internal.GCompare Lambdabot.Config.Config

module Lambdabot.Logging

-- | Priorities are used to define how important a log message is. Users
--   can filter log messages based on priorities.
--   
--   These have their roots on the traditional syslog system. The standard
--   definitions are given below, but you are free to interpret them
--   however you like. They are listed here in ascending importance order.
data Priority

-- | Debug messages
DEBUG :: Priority

-- | Information
INFO :: Priority

-- | Normal runtime conditions
NOTICE :: Priority

-- | General Warnings
WARNING :: Priority

-- | General Errors
ERROR :: Priority

-- | Severe situations
CRITICAL :: Priority

-- | Take immediate action
ALERT :: Priority

-- | System is unusable
EMERGENCY :: Priority
class Monad m => MonadLogging m
getCurrentLogger :: MonadLogging m => m [String]
logM :: MonadLogging m => String -> Priority -> String -> m ()
debugM :: MonadLogging m => String -> m ()
infoM :: MonadLogging m => String -> m ()
noticeM :: MonadLogging m => String -> m ()
warningM :: MonadLogging m => String -> m ()
errorM :: MonadLogging m => String -> m ()
criticalM :: MonadLogging m => String -> m ()
alertM :: MonadLogging m => String -> m ()
emergencyM :: MonadLogging m => String -> m ()
instance Lambdabot.Logging.MonadLogging GHC.Types.IO


-- | String and other utilities
module Lambdabot.Util

-- | <a>strip</a> takes as input a predicate and a list and strips elements
--   matching the predicate from the prefix as well as the suffix of the
--   list. Example:
--   
--   <pre>
--   strip isSpace "   abc  " ===&gt; "abc"
--   </pre>
strip :: (a -> Bool) -> [a] -> [a]

-- | Drop elements matching a predicate from the end of a list
dropFromEnd :: (a -> Bool) -> [a] -> [a]

-- | Break a String into it's first word, and the rest of the string.
--   Example:
--   
--   <pre>
--   split_first_word "A fine day" ===&gt; ("A", "fine day)
--   </pre>
splitFirstWord :: String -> (String, String)

-- | Truncate a string to the specified length, putting ellipses at the end
--   if necessary.
limitStr :: Int -> String -> String

-- | Form a list of terms using a single conjunction. Example:
--   
--   <pre>
--   listToStr "and" ["a", "b", "c"] ===&gt; "a, b and c"
--   </pre>
listToStr :: String -> [String] -> String

-- | show a list without heavyweight formatting NB: assumes show instance
--   outputs a quoted <a>String</a>. under that assumption, strips the
--   outer quotes.
showClean :: Show a => [a] -> String

-- | untab an string
expandTab :: Int -> String -> String
arePrefixesWithSpaceOf :: [String] -> String -> Bool
arePrefixesOf :: [String] -> String -> Bool
io :: MonadIO m => IO a -> m a
forkUnmasked :: MonadBaseControl IO m => m () -> m ThreadId

-- | Pick a random element of the list.
random :: MonadIO m => [a] -> m a
randomFailureMsg :: (MonadIO m, MonadConfig m) => m String
randomSuccessMsg :: MonadIO m => m String

module Lambdabot.Nick

-- | The type of nicknames isolated from a message.
data Nick
Nick :: !String -> !String -> Nick

-- | The tag of the server this nick is on
[nTag] :: Nick -> !String

-- | The server-specific nickname of this nick
[nName] :: Nick -> !String

-- | Format a nickname for display. This will automatically omit the server
--   field if it is the same as the server of the provided message.
fmtNick :: String -> Nick -> String

-- | Parse a nickname received in a message. If the server field is not
--   provided, it defaults to the same as that of the message.
parseNick :: String -> String -> Nick
instance GHC.Classes.Eq Lambdabot.Nick.Nick
instance GHC.Classes.Ord Lambdabot.Nick.Nick

module Lambdabot.Message
class Show a => Message a

-- | extracts the tag of the server involved in a given message
server :: Message a => a -> String

-- | extracts the nickname involved in a given message.
nick :: Message a => a -> Nick

-- | <a>fullName</a> extracts the full user name involved in a given
--   message.
fullName :: Message a => a -> String

-- | <a>channels</a> extracts the channels a Message operate on.
channels :: Message a => a -> [Nick]
lambdabotName :: Message a => a -> Nick


-- | The IRC module processes the IRC protocol and provides a nice API for
--   sending and receiving IRC messages with an IRC server.
module Lambdabot.IRC

-- | An IRC message is a server, a prefix, a command and a list of
--   parameters.
--   
--   Note that the strings here are treated as lists of bytes!
data IrcMessage
IrcMessage :: !String -> !String -> !String -> !String -> ![String] -> IrcMessage
[ircMsgServer] :: IrcMessage -> !String
[ircMsgLBName] :: IrcMessage -> !String
[ircMsgPrefix] :: IrcMessage -> !String
[ircMsgCommand] :: IrcMessage -> !String
[ircMsgParams] :: IrcMessage -> ![String]
joinChannel :: Nick -> IrcMessage
partChannel :: Nick -> IrcMessage
getTopic :: Nick -> IrcMessage
setTopic :: Nick -> String -> IrcMessage

-- | <a>codepage</a> creates a server CODEPAGE message. The input string
--   given is the codepage name for current session.
codepage :: String -> String -> IrcMessage

-- | <a>privmsg</a> creates a private message to the person designated.
privmsg :: Nick -> String -> IrcMessage

-- | <a>quit</a> creates a server QUIT message. The input string given is
--   the quit message, given to other parties when leaving the network.
quit :: String -> String -> IrcMessage

-- | Construct a privmsg from the CTCP TIME notice, to feed up to the
--   @localtime-reply plugin, which then passes the output to the
--   appropriate client.
timeReply :: IrcMessage -> IrcMessage
pass :: String -> String -> IrcMessage
user :: String -> String -> String -> String -> IrcMessage
setNick :: Nick -> IrcMessage
instance GHC.Show.Show Lambdabot.IRC.IrcMessage
instance Lambdabot.Message.Message Lambdabot.IRC.IrcMessage

module Lambdabot.Compat.PackedNick

-- | The type of nicknames
type PackedNick = ByteString

-- | Pack a nickname into a ByteString. Note that the resulting strings are
--   not optimally formatted for human consumtion.
packNick :: Nick -> ByteString

-- | Unpack a nickname packed by <a>packNick</a>.
unpackNick :: ByteString -> Nick

module Lambdabot.Command
data Command m
Command :: String -> [String] -> Bool -> Cmd m () -> (String -> Cmd m ()) -> Command m
[cmdName] :: Command m -> String
[aliases] :: Command m -> [String]
[privileged] :: Command m -> Bool
[help] :: Command m -> Cmd m ()
[process] :: Command m -> String -> Cmd m ()
cmdNames :: Command m -> [String]
command :: String -> Command Identity
runCommand :: (Monad m, Message a) => Command m -> a -> Nick -> String -> String -> m [String]
data Cmd m a
execCmd :: (Monad m, Message a) => Cmd m t -> a -> Nick -> String -> m [String]
getCmdName :: Monad m => Cmd m String
withMsg :: Monad m => (forall a. Message a => a -> Cmd m t) -> Cmd m t
readNick :: Monad m => String -> Cmd m Nick
showNick :: Monad m => Nick -> Cmd m String
getServer :: Monad m => Cmd m String
getSender :: Monad m => Cmd m Nick
getTarget :: Monad m => Cmd m Nick
getLambdabotName :: Monad m => Cmd m Nick
say :: Monad m => String -> Cmd m ()
instance GHC.Base.Functor f => GHC.Base.Functor (Lambdabot.Command.Cmd f)
instance GHC.Base.Applicative f => GHC.Base.Applicative (Lambdabot.Command.Cmd f)
instance GHC.Base.Monad m => GHC.Base.Monad (Lambdabot.Command.Cmd m)
instance Control.Monad.Fail.MonadFail m => Control.Monad.Fail.MonadFail (Lambdabot.Command.Cmd m)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Lambdabot.Command.Cmd m)
instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (Lambdabot.Command.Cmd m)
instance Control.Monad.Trans.Class.MonadTrans Lambdabot.Command.Cmd
instance Control.Monad.Trans.Control.MonadTransControl Lambdabot.Command.Cmd
instance Control.Monad.Trans.Control.MonadBaseControl b m => Control.Monad.Trans.Control.MonadBaseControl b (Lambdabot.Command.Cmd m)
instance Lambdabot.Config.MonadConfig m => Lambdabot.Config.MonadConfig (Lambdabot.Command.Cmd m)
instance Lambdabot.Logging.MonadLogging m => Lambdabot.Logging.MonadLogging (Lambdabot.Command.Cmd m)

module Lambdabot.ChanName
data ChanName
mkCN :: Nick -> ChanName
getCN :: ChanName -> Nick
instance GHC.Classes.Ord Lambdabot.ChanName.ChanName
instance GHC.Classes.Eq Lambdabot.ChanName.ChanName

module Lambdabot.Util.Network

-- | This is essentially a reimplementation of the former Network.connectTo
--   function, except that we don't do the service name lookup.
connectTo' :: HostName -> PortNumber -> IO Handle

module Lambdabot.Module

-- | The Module type class.
data Module st
Module :: !Maybe (Serial st) -> !LB st -> !Bool -> !ModuleT st LB [Command (ModuleT st LB)] -> !ModuleT st LB () -> !ModuleT st LB () -> !String -> Cmd (ModuleT st LB) () -> Module st

-- | If the module wants its state to be saved, this function should return
--   a Serial.
--   
--   The default implementation returns Nothing.
[moduleSerialize] :: Module st -> !Maybe (Serial st)

-- | If the module maintains state, this method specifies the default state
--   (for example in case the state can't be read from a state).
--   
--   The default implementation returns an error and assumes the state is
--   never accessed.
[moduleDefState] :: Module st -> !LB st

-- | Is the module sticky? Sticky modules (as well as static ones) can't be
--   unloaded. By default, modules are not sticky.
[moduleSticky] :: Module st -> !Bool

-- | The commands the module listens to.
[moduleCmds] :: Module st -> !ModuleT st LB [Command (ModuleT st LB)]

-- | Initialize the module. The default implementation does nothing.
[moduleInit] :: Module st -> !ModuleT st LB ()

-- | Finalize the module. The default implementation does nothing.
[moduleExit] :: Module st -> !ModuleT st LB ()

-- | Process contextual input. A plugin that implements <a>contextual</a>
--   is able to respond to text not part of a normal command.
[contextual] :: Module st -> !String -> Cmd (ModuleT st LB) ()
newModule :: Module st
data ModuleID st
newModuleID :: IO (ModuleID st)

-- | Info about a running module.
data ModuleInfo st
ModuleInfo :: !String -> !ModuleID st -> !Module st -> !MVar st -> ModuleInfo st
[moduleName] :: ModuleInfo st -> !String
[moduleID] :: ModuleInfo st -> !ModuleID st
[theModule] :: ModuleInfo st -> !Module st
[moduleState] :: ModuleInfo st -> !MVar st

-- | This transformer encodes the additional information a module might
--   need to access its name or its state.
data ModuleT st m a
runModuleT :: ModuleT st m a -> ModuleInfo st -> m a
instance Control.Monad.Catch.MonadMask m => Control.Monad.Catch.MonadMask (Lambdabot.Module.ModuleT st m)
instance Control.Monad.Catch.MonadCatch m => Control.Monad.Catch.MonadCatch (Lambdabot.Module.ModuleT st m)
instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Lambdabot.Module.ModuleT st m)
instance System.Console.Haskeline.MonadException.MonadException m => System.Console.Haskeline.MonadException.MonadException (Lambdabot.Module.ModuleT st m)
instance Control.Monad.Fail.MonadFail m => Control.Monad.Fail.MonadFail (Lambdabot.Module.ModuleT st m)
instance Lambdabot.Config.MonadConfig m => Lambdabot.Config.MonadConfig (Lambdabot.Module.ModuleT st m)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Lambdabot.Module.ModuleT st m)
instance Control.Monad.Trans.Class.MonadTrans (Lambdabot.Module.ModuleT st)
instance GHC.Base.Monad m => Control.Monad.Reader.Class.MonadReader (Lambdabot.Module.ModuleInfo st) (Lambdabot.Module.ModuleT st m)
instance GHC.Base.Monad m => GHC.Base.Monad (Lambdabot.Module.ModuleT st m)
instance GHC.Base.Functor m => GHC.Base.Functor (Lambdabot.Module.ModuleT st m)
instance GHC.Base.Applicative m => GHC.Base.Applicative (Lambdabot.Module.ModuleT st m)
instance Data.GADT.Internal.GCompare Lambdabot.Module.ModuleID
instance Data.GADT.Internal.GEq Lambdabot.Module.ModuleID
instance Lambdabot.Logging.MonadLogging m => Lambdabot.Logging.MonadLogging (Lambdabot.Module.ModuleT st m)
instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (Lambdabot.Module.ModuleT st m)
instance Control.Monad.Trans.Control.MonadTransControl (Lambdabot.Module.ModuleT st)
instance Control.Monad.Trans.Control.MonadBaseControl b m => Control.Monad.Trans.Control.MonadBaseControl b (Lambdabot.Module.ModuleT st m)

module Lambdabot.Monad

-- | Global read-only state.
data IRCRState

-- | Default ro state
initRoState :: [DSum Config Identity] -> IO IRCRState
reportInitDone :: LB ()
waitForInit :: MonadLB m => m ()
waitForQuit :: MonadLB m => m ()
type Callback st = IrcMessage -> ModuleT st LB ()
type OutputFilter st = Nick -> [String] -> ModuleT st LB [String]
type Server st = IrcMessage -> ModuleT st LB ()

-- | Global read/write state.
data IRCRWState
IRCRWState :: Map String (DSum ModuleID ServerRef) -> Set Nick -> Set Nick -> Map ChanName String -> Map String Bool -> Map String (Some ModuleInfo) -> DMap ModuleID ModuleInfo -> Map String (DMap ModuleID CallbackRef) -> [DSum ModuleID OutputFilterRef] -> Map String (DSum ModuleID CommandRef) -> IRCRWState
[ircServerMap] :: IRCRWState -> Map String (DSum ModuleID ServerRef)
[ircPrivilegedUsers] :: IRCRWState -> Set Nick
[ircIgnoredUsers] :: IRCRWState -> Set Nick

-- | maps channel names to topics
[ircChannels] :: IRCRWState -> Map ChanName String

-- | lists servers to which to reconnect on failure (one-time or always)
[ircPersists] :: IRCRWState -> Map String Bool
[ircModulesByName] :: IRCRWState -> Map String (Some ModuleInfo)
[ircModulesByID] :: IRCRWState -> DMap ModuleID ModuleInfo
[ircCallbacks] :: IRCRWState -> Map String (DMap ModuleID CallbackRef)

-- | Output filters, invoked from right to left
[ircOutputFilters] :: IRCRWState -> [DSum ModuleID OutputFilterRef]
[ircCommands] :: IRCRWState -> Map String (DSum ModuleID CommandRef)

-- | Default rw state
initRwState :: IRCRWState

-- | The IRC Monad. The reader transformer holds information about the
--   connection to the IRC server.
--   
--   instances Monad, Functor, MonadIO, MonadState, MonadError
data LB a
runLB :: LB a -> (IRCRState, IORef IRCRWState) -> IO a
class (MonadIO m, MonadBaseControl IO m, MonadConfig m, MonadLogging m, Applicative m, MonadFail m) => MonadLB m
lb :: MonadLB m => LB a -> m a
registerModule :: String -> Module st -> st -> LB (ModuleInfo st)
registerCommands :: [Command (ModuleT st LB)] -> ModuleT st LB ()
registerCallback :: String -> Callback st -> ModuleT st LB ()
registerOutputFilter :: OutputFilter st -> ModuleT st LB ()
unregisterModule :: String -> LB ()
registerServer :: String -> Server st -> ModuleT st LB ()
unregisterServer :: String -> ModuleT mod LB ()
send :: IrcMessage -> LB ()
received :: IrcMessage -> LB ()
applyOutputFilters :: Nick -> String -> LB [String]

-- | Interpret an expression in the context of a module.
inModuleNamed :: String -> LB a -> (forall st. ModuleT st LB a) -> LB a
inModuleWithID :: ModuleID st -> LB a -> ModuleT st LB a -> LB a
withCommand :: String -> LB a -> (forall st. Command (ModuleT st LB) -> ModuleT st LB a) -> LB a
listModules :: LB [String]

-- | Interpret a function in the context of all modules
withAllModules :: (forall st. ModuleT st LB a) -> LB ()
instance Control.Monad.Catch.MonadMask Lambdabot.Monad.LB
instance Control.Monad.Catch.MonadCatch Lambdabot.Monad.LB
instance Control.Monad.Catch.MonadThrow Lambdabot.Monad.LB
instance System.Console.Haskeline.MonadException.MonadException Lambdabot.Monad.LB
instance Control.Monad.Fail.MonadFail Lambdabot.Monad.LB
instance Control.Monad.IO.Class.MonadIO Lambdabot.Monad.LB
instance GHC.Base.Monad Lambdabot.Monad.LB
instance GHC.Base.Applicative Lambdabot.Monad.LB
instance GHC.Base.Functor Lambdabot.Monad.LB
instance Lambdabot.Monad.MonadLB Lambdabot.Monad.LB
instance Lambdabot.Monad.MonadLB m => Lambdabot.Monad.MonadLB (Lambdabot.Module.ModuleT st m)
instance Lambdabot.Monad.MonadLB m => Lambdabot.Monad.MonadLB (Lambdabot.Command.Cmd m)
instance Lambdabot.Config.MonadConfig Lambdabot.Monad.LB
instance Control.Monad.Base.MonadBase GHC.Types.IO Lambdabot.Monad.LB
instance Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO Lambdabot.Monad.LB
instance Control.Monad.State.Class.MonadState Lambdabot.Monad.IRCRWState Lambdabot.Monad.LB
instance Lambdabot.Logging.MonadLogging Lambdabot.Monad.LB


-- | Manage lambdabot's state files. There are three relevant directories:
--   
--   <ul>
--   <li>local: <tt>.<i>State</i></tt> (configurable, see
--   <a>outputDir</a>)</li>
--   <li>home: <tt>~<i>.lambdabot</i>State/</tt></li>
--   <li>data: relative to the data directory of the <tt>lambdabot</tt>
--   package.</li>
--   </ul>
--   
--   Files are stored locally if the directory exists; otherwise, in the
--   home directory. When reading a state file, and the file exists in the
--   data directory but nowhere else, then it is picked up from the data
--   directory.
module Lambdabot.File

-- | Locate state directory. Returns the local directory if it exists, and
--   the home directory otherwise.
stateDir :: LB FilePath

-- | Look for the file in the local, home, and data directories.
findLBFileForReading :: FilePath -> LB (Maybe FilePath)

-- | Return file name for writing state. The file will reside in the state
--   directory (<a>stateDir</a>), and <a>findLBFileForWriting</a> ensures
--   that the state directory exists.
findLBFileForWriting :: FilePath -> LB FilePath

-- | This returns the same file name as <a>findLBFileForWriting</a>. If the
--   file does not exist, it is either copied from the data (or home)
--   directory, if a copy is found there; otherwise, an empty file is
--   created instead.
findOrCreateLBFile :: FilePath -> LB String

-- | Try to find a pre-existing file, searching first in the local or home
--   directory (but not in the data directory)

-- | <i>Deprecated: Use <a>findLBFileForReading</a> or
--   <a>findLBFileForWriting</a> instead</i>
findLBFile :: FilePath -> LB (Maybe String)
outputDir :: Config FilePath


-- | Support for the LB (LambdaBot) monad
module Lambdabot.State
class MonadLB m => MonadLBState m where {
    type family LBState m;
}

-- | Update the module's private state. This is the preferred way of
--   changing the state. The state will be locked until the body returns.
--   The function is exception-safe, i.e. even if an error occurs or the
--   thread is killed (e.g. because it deadlocked and therefore exceeded
--   its time limit), the state from the last write operation will be
--   restored. If the writer escapes, calling it will have no observable
--   effect. <tt>withMS</tt> is not composable, in the sense that a readMS
--   from within the body will cause a dead-lock. However, all other
--   possibilies to access the state that came to my mind had even more
--   serious deficiencies such as being prone to race conditions or
--   semantic obscurities.
withMS :: MonadLBState m => (LBState m -> (LBState m -> m ()) -> m a) -> m a

-- | Read the module's private state.
readMS :: MonadLBState m => m (LBState m)

-- | Write the module's private state. Try to use withMS instead.
writeMS :: MonadLBState m => LBState m -> m ()

-- | Modify the module's private state.
modifyMS :: MonadLBState m => (LBState m -> LBState m) -> m ()

-- | This datatype allows modules to conviently maintain both global (i.e.
--   for all clients they're interacting with) and private state. It is
--   implemented on top of readMS/withMS.
--   
--   This simple implementation is linear in the number of private states
--   used.
data GlobalPrivate g p

-- | Creates a <tt>GlobalPrivate</tt> given the value of the global state.
--   No private state for clients will be created.
mkGlobalPrivate :: Int -> g -> GlobalPrivate g p

-- | Writes private state. For now, it locks everything.
withPS :: (MonadLBState m, LBState m ~ GlobalPrivate g p) => Nick -> (Maybe p -> (Maybe p -> LB ()) -> LB a) -> m a

-- | Reads private state.
readPS :: (MonadLBState m, LBState m ~ GlobalPrivate g p) => Nick -> m (Maybe p)
writePS :: (MonadLBState m, LBState m ~ GlobalPrivate g p) => Nick -> Maybe p -> m ()

-- | Writes global state. Locks everything
withGS :: (MonadLBState m, LBState m ~ GlobalPrivate g p) => (g -> (g -> m ()) -> m ()) -> m ()

-- | Reads global state.
readGS :: (MonadLBState m, LBState m ~ GlobalPrivate g p) => m g
writeGS :: (MonadLBState m, LBState m ~ GlobalPrivate g p) => g -> m ()

-- | Read it in
readGlobalState :: Module st -> String -> LB (Maybe st)

-- | Peristence: write the global state out
writeGlobalState :: ModuleT st LB ()
instance Lambdabot.Monad.MonadLB m => Lambdabot.State.MonadLBState (Lambdabot.Module.ModuleT st m)
instance Lambdabot.State.MonadLBState m => Lambdabot.State.MonadLBState (Lambdabot.Command.Cmd m)


-- | The guts of lambdabot.
--   
--   The LB/Lambdabot monad Generic server connection,disconnection The
--   module typeclass, type and operations on modules
module Lambdabot.Bot

-- | Register a module in the irc state
ircLoadModule :: String -> Module st -> LB ()

-- | Unregister a module's entry in the irc state
ircUnloadModule :: String -> LB ()

-- | Checks whether the given user has admin permissions
checkPrivs :: IrcMessage -> LB Bool

-- | Checks whether the given user is being ignored. Privileged users can't
--   be ignored.
checkIgnore :: IrcMessage -> LB Bool
ircCodepage :: String -> String -> LB ()
ircGetChannels :: LB [Nick]
ircQuit :: String -> String -> LB ()
ircReconnect :: String -> String -> LB ()

-- | Send a message to a channel/user, applying all output filters
ircPrivmsg :: Nick -> String -> LB ()
ircPrivmsg' :: Nick -> String -> LB ()
instance Data.Random.Internal.Source.MonadRandom Lambdabot.Monad.LB

module Lambdabot.Plugin

-- | The Module type class.
data Module st
Module :: !Maybe (Serial st) -> !LB st -> !Bool -> !ModuleT st LB [Command (ModuleT st LB)] -> !ModuleT st LB () -> !ModuleT st LB () -> !String -> Cmd (ModuleT st LB) () -> Module st

-- | If the module wants its state to be saved, this function should return
--   a Serial.
--   
--   The default implementation returns Nothing.
[moduleSerialize] :: Module st -> !Maybe (Serial st)

-- | If the module maintains state, this method specifies the default state
--   (for example in case the state can't be read from a state).
--   
--   The default implementation returns an error and assumes the state is
--   never accessed.
[moduleDefState] :: Module st -> !LB st

-- | Is the module sticky? Sticky modules (as well as static ones) can't be
--   unloaded. By default, modules are not sticky.
[moduleSticky] :: Module st -> !Bool

-- | The commands the module listens to.
[moduleCmds] :: Module st -> !ModuleT st LB [Command (ModuleT st LB)]

-- | Initialize the module. The default implementation does nothing.
[moduleInit] :: Module st -> !ModuleT st LB ()

-- | Finalize the module. The default implementation does nothing.
[moduleExit] :: Module st -> !ModuleT st LB ()

-- | Process contextual input. A plugin that implements <a>contextual</a>
--   is able to respond to text not part of a normal command.
[contextual] :: Module st -> !String -> Cmd (ModuleT st LB) ()

-- | This transformer encodes the additional information a module might
--   need to access its name or its state.
data ModuleT st m a
newModule :: Module st

-- | The IRC Monad. The reader transformer holds information about the
--   connection to the IRC server.
--   
--   instances Monad, Functor, MonadIO, MonadState, MonadError
data LB a
class (MonadIO m, MonadBaseControl IO m, MonadConfig m, MonadLogging m, Applicative m, MonadFail m) => MonadLB m
lb :: MonadLB m => LB a -> m a
lim80 :: Monad m => m String -> Cmd m ()

-- | convenience, similar to ios but also cut output to channel to 80
--   characters usage: <tt>process _ _ to _ s = ios80 to (plugs s)</tt>
ios80 :: MonadIO m => IO String -> Cmd m ()
data ChanName
mkCN :: Nick -> ChanName
getCN :: ChanName -> Nick

-- | The type of nicknames isolated from a message.
data Nick
Nick :: !String -> !String -> Nick

-- | The tag of the server this nick is on
[nTag] :: Nick -> !String

-- | The server-specific nickname of this nick
[nName] :: Nick -> !String

-- | Send a message to a channel/user, applying all output filters
ircPrivmsg :: Nick -> String -> LB ()
commandPrefixes :: Config [String]
disabledCommands :: Config [String]
editDistanceLimit :: Config Int
enableInsults :: Config Bool
onStartupCmds :: Config [String]
outputDir :: Config FilePath
dataDir :: Config FilePath
lbVersion :: Config Version
textWidth :: Config Int
uncaughtExceptionHandler :: Config DIH
replaceRootLogger :: Config Bool
lbRootLoggerPath :: Config [String]
consoleLogHandle :: Config Handle
consoleLogLevel :: Config Priority
consoleLogFormat :: Config String
data Command m
Command :: String -> [String] -> Bool -> Cmd m () -> (String -> Cmd m ()) -> Command m
[cmdName] :: Command m -> String
[aliases] :: Command m -> [String]
[privileged] :: Command m -> Bool
[help] :: Command m -> Cmd m ()
[process] :: Command m -> String -> Cmd m ()
data Cmd m a
cmdNames :: Command m -> [String]
command :: String -> Command Identity
getTarget :: Monad m => Cmd m Nick
getCmdName :: Monad m => Cmd m String
say :: Monad m => String -> Cmd m ()
withMsg :: Monad m => (forall a. Message a => a -> Cmd m t) -> Cmd m t
readNick :: Monad m => String -> Cmd m Nick
showNick :: Monad m => Nick -> Cmd m String
getServer :: Monad m => Cmd m String
getSender :: Monad m => Cmd m Nick
getLambdabotName :: Monad m => Cmd m Nick
data Serial s
Serial :: (s -> Maybe ByteString) -> (ByteString -> Maybe s) -> Serial s
[serialize] :: Serial s -> s -> Maybe ByteString
[deserialize] :: Serial s -> ByteString -> Maybe s

-- | Default `instance' for a Serial
stdSerial :: (Show s, Read s) => Serial s

-- | Serializes a <a>Map</a> type if both the key and the value are
--   instances of Read and Show. The serialization is done by converting
--   the map to and from lists. Results are saved line-wise, for better
--   editing and revision control.
mapSerial :: (Ord k, Show k, Show v, Read k, Read v) => Serial (Map k v)
mapPackedSerial :: Serial (Map ByteString ByteString)
assocListPackedSerial :: Serial [(ByteString, ByteString)]
mapListPackedSerial :: Serial (Map ByteString [ByteString])

-- | <a>readM</a> behaves like read, but catches failure in a monad. this
--   allocates a 20-30 M on startup...
readM :: (MonadFail m, Read a) => String -> m a
class Packable t
readPacked :: Packable t => ByteString -> t
showPacked :: Packable t => t -> ByteString
readOnly :: (ByteString -> b) -> Serial b


-- | Backward-compatibility shim for (de-)serializing <a>Nick</a>s using
--   the old <a>Read</a>/<a>Show</a> instances which gave freenode special
--   treatment.
module Lambdabot.Compat.FreenodeNick
newtype FreenodeNick
FreenodeNick :: Nick -> FreenodeNick
[getFreenodeNick] :: FreenodeNick -> Nick
freenodeNickMapSerial :: (Show v, Read v) => Serial (Map Nick v)
instance GHC.Classes.Ord Lambdabot.Compat.FreenodeNick.FreenodeNick
instance GHC.Classes.Eq Lambdabot.Compat.FreenodeNick.FreenodeNick
instance GHC.Show.Show Lambdabot.Compat.FreenodeNick.FreenodeNick
instance GHC.Read.Read Lambdabot.Compat.FreenodeNick.FreenodeNick

module Lambdabot.Plugin.Core
basePlugin :: Module (GlobalPrivate () ())
systemPlugin :: Module SystemState
offlineRCPlugin :: Module OfflineRCState
composePlugin :: Module ()
helpPlugin :: Module ()
morePlugin :: Module (GlobalPrivate () [String])
versionPlugin :: Module ()
corePlugins :: [String]
commandPrefixes :: Config [String]
disabledCommands :: Config [String]
editDistanceLimit :: Config Int
enableInsults :: Config Bool
onStartupCmds :: Config [String]
outputDir :: Config FilePath
dataDir :: Config FilePath
lbVersion :: Config Version
textWidth :: Config Int
uncaughtExceptionHandler :: Config DIH
replaceRootLogger :: Config Bool
lbRootLoggerPath :: Config [String]
consoleLogHandle :: Config Handle
consoleLogLevel :: Config Priority
consoleLogFormat :: Config String

module Lambdabot.Main
lambdabotVersion :: Version
data Config t

-- | A basic dependent sum type where the first component is a tag that
--   specifies the type of the second. For example, think of a GADT such
--   as:
--   
--   <pre>
--   data Tag a where
--      AString :: Tag String
--      AnInt   :: Tag Int
--      Rec     :: Tag (DSum Tag Identity)
--   </pre>
--   
--   Then we can write expressions where the RHS of
--   <tt>(<a>:=&gt;</a>)</tt> has different types depending on the
--   <tt>Tag</tt> constructor used. Here are some expressions of type
--   <tt>DSum Tag <tt>Identity</tt></tt>:
--   
--   <pre>
--   AString :=&gt; Identity "hello!"
--   AnInt   :=&gt; Identity 42
--   </pre>
--   
--   Often, the <tt>f</tt> we choose has an <a>Applicative</a> instance,
--   and we can use the helper function <tt>(<a>==&gt;</a>)</tt>. The
--   following expressions all have the type <tt>Applicative f =&gt; DSum
--   Tag f</tt>:
--   
--   <pre>
--   AString ==&gt; "hello!"
--   AnInt   ==&gt; 42
--   </pre>
--   
--   We can write functions that consume <tt>DSum Tag f</tt> values by
--   matching, such as:
--   
--   <pre>
--   toString :: DSum Tag Identity -&gt; String
--   toString (AString :=&gt; Identity str) = str
--   toString (AnInt   :=&gt; Identity int) = show int
--   toString (Rec     :=&gt; Identity sum) = toString sum
--   </pre>
--   
--   The <tt>(<a>:=&gt;</a>)</tt> constructor and <tt>(<a>==&gt;</a>)</tt>
--   helper are chosen to resemble the <tt>(key =&gt; value)</tt>
--   construction for dictionary entries in many dynamic languages. The
--   <tt>:=&gt;</tt> and <tt>==&gt;</tt> operators have very low precedence
--   and bind to the right, making repeated use of these operators behave
--   as you'd expect:
--   
--   <pre>
--   -- Parses as: Rec ==&gt; (AnInt ==&gt; (3 + 4))
--   -- Has type: Applicative f =&gt; DSum Tag f
--   Rec ==&gt; AnInt ==&gt; 3 + 4
--   </pre>
--   
--   The precedence of these operators is just above that of <a>$</a>, so
--   <tt>foo bar $ AString ==&gt; "eep"</tt> is equivalent to <tt>foo bar
--   (AString ==&gt; "eep")</tt>.
--   
--   To use the <a>Eq</a>, <a>Ord</a>, <a>Read</a>, and <a>Show</a>
--   instances for <tt><a>DSum</a> tag f</tt>, you will need an
--   <a>ArgDict</a> instance for your tag type. Use <a>deriveArgDict</a>
--   from the <tt>constraints-extras</tt> package to generate this
--   instance.
data DSum (tag :: k -> Type) (f :: k -> Type)
(:=>) :: !tag a -> f a -> DSum (tag :: k -> Type) (f :: k -> Type)
infixr 1 :=>

-- | Convenience helper. Uses <a>pure</a> to lift <tt>a</tt> into <tt>f
--   a</tt>.
(==>) :: forall (f :: Type -> Type) tag a. Applicative f => tag a -> a -> DSum tag f
infixr 1 ==>

-- | The Lambdabot entry point. Initialise plugins, connect, and run the
--   bot in the LB monad
--   
--   Also, handle any fatal exceptions (such as non-recoverable signals),
--   (i.e. print a message and exit). Non-fatal exceptions should be dealt
--   with in the mainLoop or further down.
lambdabotMain :: Modules -> [DSum Config Identity] -> IO ExitCode
type Modules = [(String, Some Module)]
modules :: [String] -> Q Exp

-- | Priorities are used to define how important a log message is. Users
--   can filter log messages based on priorities.
--   
--   These have their roots on the traditional syslog system. The standard
--   definitions are given below, but you are free to interpret them
--   however you like. They are listed here in ascending importance order.
data Priority

-- | Debug messages
DEBUG :: Priority

-- | Information
INFO :: Priority

-- | Normal runtime conditions
NOTICE :: Priority

-- | General Warnings
WARNING :: Priority

-- | General Errors
ERROR :: Priority

-- | Severe situations
CRITICAL :: Priority

-- | Take immediate action
ALERT :: Priority

-- | System is unusable
EMERGENCY :: Priority
