-- 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.0.3


-- | 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.ClockTime
instance GHC.Read.Read 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.ClockTime
instance Data.Binary.Class.Binary Lambdabot.Compat.AltTime.TimeDiff


-- | 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, `(++)`).
configWithMerge :: ExpQ -> String -> TypeQ -> ExpQ -> Q [Dec]
instance Data.GADT.Compare.GEq Lambdabot.Config.Config
instance Data.GADT.Compare.GCompare Lambdabot.Config.Config
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)

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

-- | 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


-- | Backward-compatibility shim for (de-)serializing <a>Nick</a>s using
--   the old 'Read'/'Show' 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.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.OutputFilter
type OutputFilter m = Nick -> [String] -> m [String]
textwidth :: Int

-- | For now, this just checks for duplicate empty lines.
cleanOutput :: Monad m => OutputFilter m

-- | wrap long lines.
lineify :: Monad m => OutputFilter m


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

-- | An IRC message is a server, a prefix, a command and a list of
--   parameters.
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.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.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.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 listenes 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

-- | This transformer encodes the additional information a module might
--   need to access its name or its state.
newtype ModuleT st m a
ModuleT :: ReaderT (MVar st, String) m a -> ModuleT st m a
[runModuleT] :: ModuleT st m a -> ReaderT (MVar st, String) m a
getRef :: Monad m => ModuleT st m (MVar st)
getModuleName :: Monad m => ModuleT mod m String

-- | bind an action to the current module so it can be run from the plain
--   <a>LB</a> monad.
bindModule0 :: ModuleT mod LB a -> ModuleT mod LB (LB a)

-- | variant of <a>bindModule0</a> for monad actions with one argument
bindModule1 :: (a -> ModuleT mod LB b) -> ModuleT mod LB (a -> LB b)

-- | variant of <a>bindModule0</a> for monad actions with two arguments
bindModule2 :: (a -> b -> ModuleT mod LB c) -> ModuleT mod LB (a -> b -> LB c)
instance Lambdabot.Config.MonadConfig m => Lambdabot.Config.MonadConfig (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.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 => 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 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.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.Monad

-- | Global read-only state.
data IRCRState

-- | Default ro state
initRoState :: [DSum Config] -> IO IRCRState
reportInitDone :: MonadIO m => IRCRState -> m ()
waitForInit :: MonadLB m => m ()
waitForQuit :: MonadLB m => m ()
type Callback = IrcMessage -> LB ()
data ModuleRef
ModuleRef :: (Module st) -> (MVar st) -> String -> ModuleRef
data CommandRef
CommandRef :: (Module st) -> (MVar st) -> String -> (Command (ModuleT st LB)) -> CommandRef

-- | Global read/write state.
data IRCRWState
IRCRWState :: Map String (String, IrcMessage -> LB ()) -> Set Nick -> Set Nick -> Map ChanName String -> Map String ModuleRef -> Map String [(String, Callback)] -> [(String, OutputFilter LB)] -> Map String CommandRef -> !Bool -> IRCRWState
[ircServerMap] :: IRCRWState -> Map String (String, IrcMessage -> LB ())
[ircPrivilegedUsers] :: IRCRWState -> Set Nick
[ircIgnoredUsers] :: IRCRWState -> Set Nick

-- | maps channel names to topics
[ircChannels] :: IRCRWState -> Map ChanName String
[ircModules] :: IRCRWState -> Map String ModuleRef
[ircCallbacks] :: IRCRWState -> Map String [(String, Callback)]

-- | Output filters, invoked from right to left
[ircOutputFilters] :: IRCRWState -> [(String, OutputFilter LB)]
[ircCommands] :: IRCRWState -> Map String CommandRef
[ircStayConnected] :: IRCRWState -> !Bool

-- | 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
newtype LB a
LB :: ReaderT (IRCRState, IORef IRCRWState) IO a -> LB a
[runLB] :: LB a -> ReaderT (IRCRState, IORef IRCRWState) IO a
class (MonadIO m, MonadBaseControl IO m, MonadConfig m, MonadLogging m, Applicative m) => MonadLB m
lb :: MonadLB m => LB a -> m a

-- | run a computation in the LB monad
evalLB :: LB a -> IRCRState -> IRCRWState -> IO a
addServer :: String -> (IrcMessage -> LB ()) -> ModuleT mod LB ()
remServer :: String -> LB ()
send :: IrcMessage -> LB ()
received :: IrcMessage -> LB ()
getConfig :: MonadConfig m => Config a -> m a

-- | Interpret an expression in the context of a module. Arguments are
--   which map to use (<tt>ircModules</tt> and <tt>ircCommands</tt> are the
--   only sensible arguments here), the name of the module/command, action
--   for the case that the lookup fails, action if the lookup succeeds.
withModule :: String -> LB a -> (forall st. Module st -> ModuleT st LB a) -> LB a
withCommand :: String -> LB a -> (forall st. Module st -> Command (ModuleT st LB) -> ModuleT st LB a) -> LB a

-- | Interpret a function in the context of all modules
withAllModules :: (forall st. Module st -> ModuleT st LB a) -> LB ()
instance System.Console.Haskeline.MonadException.MonadException 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 Control.Monad.Base.MonadBase GHC.Types.IO Lambdabot.Monad.LB
instance Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO 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 Control.Monad.State.Class.MonadState Lambdabot.Monad.IRCRWState Lambdabot.Monad.LB
instance Lambdabot.Config.MonadConfig 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 ()

-- | flush state of modules
flushModuleState :: LB ()

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

-- | Peristence: write the global state out
writeGlobalState :: Module st -> String -> 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 :: Module st -> String -> LB ()

-- | Unregister a module's entry in the irc state
ircUnloadModule :: String -> LB ()
ircSignalConnect :: String -> Callback -> ModuleT mod LB ()
ircInstallOutputFilter :: OutputFilter LB -> ModuleT mod LB ()

-- | Checks if the given user has admin permissions and excecute the action
--   only in this case.
checkPrivs :: IrcMessage -> LB Bool

-- | Checks if 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. If the message is too long, the rest
--   of it is saved in the (global) more-state.
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 listenes 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
getModuleName :: Monad m => ModuleT mod m String

-- | bind an action to the current module so it can be run from the plain
--   <a>LB</a> monad.
bindModule0 :: ModuleT mod LB a -> ModuleT mod LB (LB a)

-- | variant of <a>bindModule0</a> for monad actions with one argument
bindModule1 :: (a -> ModuleT mod LB b) -> ModuleT mod LB (a -> LB b)

-- | variant of <a>bindModule0</a> for monad actions with two arguments
bindModule2 :: (a -> b -> ModuleT mod LB c) -> ModuleT mod LB (a -> b -> LB c)

-- | 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) => 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. If the message is too long, the rest
--   of it is saved in the (global) more-state.
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
uncaughtExceptionHandler :: Config (SomeException -> IO ())
replaceRootLogger :: Config Bool
lbRootLoggerPath :: Config [String]
consoleLogHandle :: Config Handle
consoleLogLevel :: Config Priority
consoleLogFormat :: Config String
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 revison 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 :: (Monad m, Read a) => String -> m a
class Packable t
readPacked :: Packable t => ByteString -> t
showPacked :: Packable t => t -> ByteString
readOnly :: (ByteString -> b) -> Serial b

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
uncaughtExceptionHandler :: Config (SomeException -> IO ())
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; 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
--   </pre>
--   
--   Then, we have the following valid expressions of type <tt>DSum
--   Tag</tt>:
--   
--   <pre>
--   AString :=&gt; "hello!"
--   AnInt   :=&gt; 42
--   </pre>
--   
--   And we can write functions that consume <tt>DSum Tag</tt> values by
--   matching, such as:
--   
--   <pre>
--   toString :: DSum Tag -&gt; String
--   toString (AString :=&gt; str) = str
--   toString (AnInt   :=&gt; int) = show int
--   </pre>
--   
--   By analogy to the (key =&gt; value) construction for dictionary
--   entries in many dynamic languages, we use (key :=&gt; value) as the
--   constructor for dependent sums. The :=&gt; operator has very low
--   precedence and binds to the right, so if the <tt>Tag</tt> GADT is
--   extended with an additional constructor <tt>Rec :: Tag (DSum
--   Tag)</tt>, then <tt>Rec :=&gt; AnInt :=&gt; 3 + 4</tt> is parsed as
--   would be expected (<tt>Rec :=&gt; (AnInt :=&gt; (3 + 4))</tt>) and has
--   type <tt>DSum Tag</tt>. Its precedence 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>.
data DSum (tag :: * -> *) :: (* -> *) -> *
(:=>) :: SrictNotUnpacked(tag a) -> a -> DSum tag

-- | 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 :: LB () -> [DSum Config] -> IO ExitCode
type Modules = LB ()
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
