-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A framework for modular, portable chat bots. -- -- A framework for writing portable chat bots. Inspired by hubot. -- -- The best way to get started with this library is with the -- documentation on readthedocs: https://marvin.readthedocs.io @package marvin @version 0.2.2 module Marvin.Util.Regex -- | Abstract Wrapper for a reglar expression implementation. Has an -- IsString implementation, so literal strings can be used to -- create a Regex. Alternatively use r to create one with -- custom options. data Regex -- | A match to a Regex. Index 0 is the full match, all other -- indices are match groups. type Match = [Text] -- | Compile a regex with options -- -- Normally it is sufficient to just write the regex as a plain string -- and have it be converted automatically, but if you want certain match -- options you can use this function. r :: [MatchOption] -> Text -> Regex -- | Match a regex against a string and return the first match found (if -- any). match :: Regex -> Text -> Maybe Match -- | Options for controlling matching behaviour. data MatchOption :: * -- | Enable case insensitive matching. CaseInsensitive :: MatchOption -- | Allow comments and white space within patterns. Comments :: MatchOption -- | If set, '.' matches line terminators. Otherwise '.' -- matching stops at line end. DotAll :: MatchOption -- | If set, treat the entire pattern as a literal string. Metacharacters -- or escape sequences in the input sequence will be given no special -- meaning. -- -- The option CaseInsensitive retains its meanings on matching -- when used in conjunction with this option. Other options become -- superfluous. Literal :: MatchOption -- | Control behaviour of '$' and '^'. If set, recognize -- line terminators within string, Otherwise, match only at start and end -- of input string. Multiline :: MatchOption -- | Haskell-only line endings. When this mode is enabled, only -- '\n' is recognized as a line ending in the behavior of -- '.', '^', and '$'. HaskellLines :: MatchOption -- | Unicode word boundaries. If set, '\\b' uses the Unicode TR 29 -- definition of word boundaries. -- -- Warning: Unicode word boundaries are quite different from -- traditional regular expression word boundaries. See -- http://unicode.org/reports/tr29/#Word_Boundaries. UnicodeWord :: MatchOption -- | Throw an error on unrecognized backslash escapes. If set, fail with an -- error on patterns that contain backslash-escaped ASCII letters without -- a known special meaning. If this flag is not set, these escaped -- letters represent themselves. ErrorOnUnknownEscapes :: MatchOption -- | Set a processing limit for match operations. -- -- Some patterns, when matching certain strings, can run in exponential -- time. For practical purposes, the match operation may appear to be in -- an infinite loop. When a limit is set a match operation will fail with -- an error if the limit is exceeded. -- -- The units of the limit are steps of the match engine. Correspondence -- with actual processor time will depend on the speed of the processor -- and the details of the specific pattern, but will typically be on the -- order of milliseconds. -- -- By default, the matching time is not limited. WorkLimit :: Int -> MatchOption -- | Set the amount of heap storage avaliable for use by the match -- backtracking stack. -- -- ICU uses a backtracking regular expression engine, with the backtrack -- stack maintained on the heap. This function sets the limit to the -- amount of memory that can be used for this purpose. A backtracking -- stack overflow will result in an error from the match operation that -- caused it. -- -- A limit is desirable because a malicious or poorly designed pattern -- can use excessive memory, potentially crashing the process. A limit is -- enabled by default. StackLimit :: Int -> MatchOption instance Control.DeepSeq.NFData Marvin.Util.Regex.Regex instance GHC.Show.Show Marvin.Util.Regex.Regex instance Data.String.IsString Marvin.Util.Regex.Regex module Marvin.Util.Random -- | Generate a random value. For more information see random randomVal :: (MonadIO m, Random a) => m a -- | Generate a random value frbounded by a range. See randomR for -- how the range works. randomValFromRange :: (MonadIO m, Random a) => (a, a) -> m a -- | Get a random value out of an integer indexed sequence, like -- (Vector, '[a]', Seq or Set) This uses the -- sequences length and therefore does not terminate for infinite -- sequences. -- -- Uses the global random number generator. -- -- Usable in all IO capable monads, such as BotReacting and -- ScriptDefinition. randomFrom :: MonadIO m => [e] -> m e module Marvin.Util.Mutable -- | A mutable reference to a value of type v -- -- This is like a pointer in c, the value behind which can be mutated by -- several functions. So long as they retain this reference they are able -- to retrieve the updated value. type Mutable v = IORef v -- | Create a new mutable reference of type v from an initial -- value. newMutable :: MonadIO m => a -> m (Mutable a) -- | Retrieve the value behind by a mutable reference. readMutable :: MonadIO m => Mutable a -> m a -- | Set the value inside a mutable reference. writeMutable :: MonadIO m => Mutable a -> a -> m () -- | Change the value behind a mutable reference. modifyMutable :: MonadIO m => Mutable a -> (a -> a) -> m () -- | A value that can be shared on multiple concurrent Threads. -- -- This value works like a channel. It can either be empty or full. If it -- is empty writeSynchronized fills it, otherwise the write -- blocks. If it is full takeSynchronized empties, otherwise it -- blocks until it is filled. readSynchronized does not empty it -- and also blocks if the Synchronized is empty. -- -- Should you just use it as a thread safe mutable variable, mutations -- typically follow the pattern: -- --
--   val <- takeSynchronized -- obtain the value and leave it empty to block concurrent reads
--   mod <- modifyWithIO val -- modify the value, typically involves IO
--   writeSynchronized mod -- write back the result
--   
-- -- Another use for this type is as a message channel, where we have a -- producer and a consumer, the producer tries to write values into the -- Synchronized (writeSynchronized) and the consumer waits -- for the Synchronized to be filled and takes the value -- (takeSynchronized) for procesing. -- -- It works generally best if any Synchronized is only used for -- one of these two applications at the same time. -- -- This type is the same as MVar, only renamed for readability. If -- you want a more in depth documentation, see the documentation for -- MVar. type Synchronized = MVar -- | Read the vaue, but don't empty the Synchronized. Blocks if it -- is empty. readSynchronized :: MonadIO m => Synchronized a -> m a -- | Non blocking version of readSynchronized. Returns -- Nothing if it was empty. tryReadSynchronized :: MonadIO m => Synchronized a -> m (Maybe a) -- | Read the value and empty the Synchronized, blocks if already -- empty. takeSynchronized :: MonadIO m => Synchronized a -> m a -- | Non blocking version of takeSynchronized, returns -- Nothing if it was empty. tryTakeSynchronized :: MonadIO m => Synchronized a -> m (Maybe a) -- | Fills the empty Synchronized with a value, blocks if it is -- full. writeSynchronized :: MonadIO m => Synchronized a -> a -> m () -- | Non blocking version of writeSynchronized. Returns False -- if it was full. tryWriteSynchronized :: MonadIO m => Synchronized a -> a -> m Bool -- | Query if the Synchronized is empty or full. isEmptySynchronized :: MonadIO m => Synchronized a -> m Bool -- | This is provisionary, this might get properly wrapped at some point. module Marvin.Util.JSON -- | Read a file containing JSON encoded data readJSON :: (MonadIO m, FromJSON a) => FilePath -> m (Either String a) -- | Write some data to a file using JSON serialization writeJSON :: (MonadIO m, ToJSON a) => FilePath -> a -> m () module Marvin.Util.HTTP module Marvin.Types -- | The contents of a recieved message type Message = Text -- | An abstract type describing a marvin script. -- -- This is basically a collection of event handlers. -- -- Internal structure is exposed for people wanting to extend this. data Script a_aufx -- | A type, basically a String, which identifies a script to the config -- and the logging facilities. -- -- For conversion please use mkScriptId and unwrapScriptId. -- They will perform necessary checks. data ScriptId -- | Attempt to create a script id from Text mkScriptId :: Text -> Either String ScriptId unwrapScriptId :: ScriptId -> Text -- | Script id sed for the bot itself applicationScriptId :: ScriptId -- | Similar to AccessAdapter, this class says there is a -- ScriptId reachable from the type (usually a monad) m. class IsScript m -- | Retrieve the script id out of m, ususally a monad. getScriptId :: IsScript m => m ScriptId -- | Retrieve the script id out of m, ususally a monad. getScriptId :: IsScript m => m ScriptId -- | Denotes a place from which we may access the configuration. -- -- During script definition or when handling a request we can obtain the -- config with getConfigVal or requireConfigVal. class (IsScript m, MonadIO m) => HasConfigAccess m -- | A timestamp type. Supplied with most Event types newtype TimeStamp TimeStamp :: UTCTime -> TimeStamp [unwrapTimeStamp] :: TimeStamp -> UTCTime -- | Similar to IsScript, this class says that there is an adapter -- AdapterT available from this type (usually a monad) m. -- -- The type of adapter depends on the monad itself. This class can be -- thought of as MonadReader specified to AdapterT. class AccessAdapter m where type AdapterT m where { type family AdapterT m; } -- | Wrapping type for users. Only used to enable Get typeclass -- instances. newtype User' a User' :: User a -> User' a [unwrapUser'] :: User' a -> User a -- | Wrapping type for channels. Only used to enable Get typeclass -- instances. newtype Channel' a Channel' :: Channel a -> Channel' a [unwrapChannel'] :: Channel' a -> Channel a -- | Class which says that there is a way to get to b from this -- type a. -- -- This typeclass is used to allow handlers with different types of -- payload to share common accessor functions such as getUser and -- getMessage. -- -- The instances specify for each type of payload which pieces of data -- can be extracted and how. class Get a b getLens :: Get a b => Lens' a b -- | Representation for the types of events which can occur data Event a MessageEvent :: (User a) -> (Channel a) -> Message -> TimeStamp -> Event a CommandEvent :: (User a) -> (Channel a) -> Message -> TimeStamp -> Event a ChannelJoinEvent :: (User a) -> (Channel a) -> TimeStamp -> Event a ChannelLeaveEvent :: (User a) -> (Channel a) -> TimeStamp -> Event a TopicChangeEvent :: (User a) -> (Channel a) -> Topic -> TimeStamp -> Event a -- | Basic monad which most internal actions run in type RunnerM = LoggingT IO -- | Read only data available to a handler when the bot reacts to an event. data BotActionState a_atqZ d_atr0 class HasScriptId s a | s -> a scriptId :: HasScriptId s a => Lens' s a class HasAdapter s a | s -> a adapter :: HasAdapter s a => Lens' s a class HasPayload s a | s -> a payload :: HasPayload s a => Lens' s a class HasActions s a | s -> a actions :: HasActions s a => Lens' s a module Marvin.Adapter type RunWithAdapter a = EventHandler a -> AdapterM a () type EventHandler a = Event a -> IO () -- | Basic functionality required of any adapter class IsAdapter a where type User a type Channel a where { type family User a; type family Channel a; } -- | Used for scoping config and logging adapterId :: IsAdapter a => AdapterId a -- | Post a message to a channel given the internal channel identifier messageChannel :: IsAdapter a => Channel a -> Text -> AdapterM a () -- | Initialize the adapter state initAdapter :: IsAdapter a => RunnerM a -- | Run the bot runWithAdapter :: IsAdapter a => RunWithAdapter a -- | Resolve a username given the internal user identifier getUsername :: IsAdapter a => User a -> AdapterM a Text -- | Resolve the human readable name for a channel given the internal -- channel identifier getChannelName :: IsAdapter a => Channel a -> AdapterM a Text -- | Resolve to the internal channel structure given a human readable name resolveChannel :: IsAdapter a => Text -> AdapterM a (Maybe (Channel a)) -- | Resolve to the internal user structure given a human readable name resolveUser :: IsAdapter a => Text -> AdapterM a (Maybe (User a)) -- | A type, basically a String, which identifies an adapter to the config -- and the logging facilities. -- -- For conversion please use mkAdapterId and -- unwrapAdapterId. They will perform necessary checks. data AdapterId a -- | Attempt to create an adapter id from Text mkAdapterId :: Text -> Either String (AdapterId a) unwrapAdapterId :: AdapterId a -> Text -- | Monad in which adapter actions run in data AdapterM a r -- | Representation for the types of events which can occur data Event a MessageEvent :: (User a) -> (Channel a) -> Message -> TimeStamp -> Event a CommandEvent :: (User a) -> (Channel a) -> Message -> TimeStamp -> Event a ChannelJoinEvent :: (User a) -> (Channel a) -> TimeStamp -> Event a ChannelLeaveEvent :: (User a) -> (Channel a) -> TimeStamp -> Event a TopicChangeEvent :: (User a) -> (Channel a) -> Topic -> TimeStamp -> Event a lookupFromAdapterConfig :: (IsAdapter a, Configured v) => Name -> AdapterM a (Maybe v) requireFromAdapterConfig :: (IsAdapter a, Configured v) => Name -> AdapterM a v lookupFromAppConfig :: Configured v => Name -> AdapterM a (Maybe v) requireFromAppConfig :: Configured v => Name -> AdapterM a v getBotname :: AdapterM a Text getAdapterConfig :: forall a. IsAdapter a => AdapterM a Config getAppConfig :: AdapterM a Config getAdapter :: AccessAdapter m => m (AdapterT m) liftAdapterAction :: (MonadIO m, HasConfigAccess m, AccessAdapter m, IsAdapter a, a ~ AdapterT m) => AdapterM a r -> m r -- | See caveats and potential issues with this adapter here -- https://marvin.readthedocs.io/en/latest/adapters.html#irc. module Marvin.Adapter.IRC data IRCAdapter data IRCChannel instance Marvin.Internal.Types.IsAdapter Marvin.Adapter.IRC.IRCAdapter module Marvin.Adapter.Shell -- | Adapter for a shell prompt data ShellAdapter instance Marvin.Internal.Types.IsAdapter Marvin.Adapter.Shell.ShellAdapter module Marvin.Adapter.Slack.EventsAPI -- | Adapter for interacting with Slack API's. Polymorphic over the method -- for retrieving events. data SlackAdapter a -- | Recieve events as a server via HTTP webhook (not implemented yet) data EventsAPI -- | Identifier for a user (internal and not equal to the username) data SlackUserId -- | Identifier for a channel (internal and not equal to the channel name) data SlackChannelId -- | Class to enable polymorphism for SlackAdapter over the method -- used for retrieving updates. (RTM or EventsAPI) class MkSlack a instance Marvin.Adapter.Slack.Common.MkSlack Marvin.Adapter.Slack.EventsAPI.EventsAPI module Marvin.Adapter.Slack.RTM -- | Adapter for interacting with Slack API's. Polymorphic over the method -- for retrieving events. data SlackAdapter a -- | Recieve events by opening a websocket to the Real Time Messaging API data RTM -- | Identifier for a user (internal and not equal to the username) data SlackUserId -- | Identifier for a channel (internal and not equal to the channel name) data SlackChannelId -- | Class to enable polymorphism for SlackAdapter over the method -- used for retrieving updates. (RTM or EventsAPI) class MkSlack a instance Marvin.Adapter.Slack.Common.MkSlack Marvin.Adapter.Slack.RTM.RTM -- |

Caveats:

-- -- resolveUser and resolveChannel resolving are not yet -- supported in this adapter and always returns Nothing. See -- #10. module Marvin.Adapter.Telegram.Poll -- | The telegram adapter type for a particular update type. Either -- Push or Poll data TelegramAdapter updateType -- | Use the telegram API by fetching updates via HTTP data Poll -- | A telegram chat object as contained in telegram updates data TelegramChat TelegramChat :: Integer -> ChatType -> (Maybe Text) -> (Maybe Text) -> (Maybe Text) -> TelegramChat -- | Chat type as defined by the telegram api data ChatType PrivateChat :: ChatType GroupChat :: ChatType SupergroupChat :: ChatType ChannelChat :: ChatType -- | A user object as contained in the telegram update objects data TelegramUser TelegramUser :: Integer -> Text -> (Maybe Text) -> (Maybe Text) -> TelegramUser -- | Class to enable polymorphism over update mechanics for -- TelegramAdapter class MkTelegram a class HasUsername s a | s -> a username :: HasUsername s a => Lens' s a class HasLastName s a | s -> a lastName :: HasLastName s a => Lens' s a class HasId_ s a | s -> a id_ :: HasId_ s a => Lens' s a class HasFirstName s a | s -> a firstName :: HasFirstName s a => Lens' s a class HasType_ s a | s -> a type_ :: HasType_ s a => Lens' s a instance Data.Aeson.Types.FromJSON.FromJSON Marvin.Adapter.Telegram.Poll.UpdateWithId instance Marvin.Adapter.Telegram.Common.MkTelegram Marvin.Adapter.Telegram.Poll.Poll -- |

Caveats:

-- -- resolveUser and resolveChannel resolving are not yet -- supported in this adapter and always returns Nothing. See -- #10. module Marvin.Adapter.Telegram.Push -- | The telegram adapter type for a particular update type. Either -- Push or Poll data TelegramAdapter updateType -- | Use the telegram API by recieving updates as a server via webhook -- -- Note: The initialization for this adapter _includes_ registering or -- clearing its own webhook. data Push -- | A telegram chat object as contained in telegram updates data TelegramChat TelegramChat :: Integer -> ChatType -> (Maybe Text) -> (Maybe Text) -> (Maybe Text) -> TelegramChat -- | Chat type as defined by the telegram api data ChatType PrivateChat :: ChatType GroupChat :: ChatType SupergroupChat :: ChatType ChannelChat :: ChatType -- | A user object as contained in the telegram update objects data TelegramUser TelegramUser :: Integer -> Text -> (Maybe Text) -> (Maybe Text) -> TelegramUser -- | Class to enable polymorphism over update mechanics for -- TelegramAdapter class MkTelegram a class HasUsername s a | s -> a username :: HasUsername s a => Lens' s a class HasLastName s a | s -> a lastName :: HasLastName s a => Lens' s a class HasId_ s a | s -> a id_ :: HasId_ s a => Lens' s a class HasFirstName s a | s -> a firstName :: HasFirstName s a => Lens' s a class HasType_ s a | s -> a type_ :: HasType_ s a => Lens' s a instance Marvin.Adapter.Telegram.Common.MkTelegram Marvin.Adapter.Telegram.Push.Push module Marvin.Run -- | Runs the marvin bot using whatever method the adapter uses. runMarvin :: forall a. IsAdapter a => [ScriptInit a] -> IO () -- | Initializer for a script. This gets run by the server during startup -- and creates a Script data ScriptInit a -- | Basic functionality required of any adapter class IsAdapter a -- | Retrieve a value from the application config, given the whole config -- structure. Fails if value not parseable as a or not present. requireFromAppConfig :: Configured a => Config -> Name -> IO a -- | Retrieve a value from the application config, given the whole config -- structure. Returns Nothing if value not parseable as a -- or not present. lookupFromAppConfig :: Configured a => Config -> Name -> IO (Maybe a) -- | Default name for the config file defaultConfigName :: FilePath -- | For the proper, verbose documentation see -- https://marvin.readthedocs.org/en/latest/scripting.html. module Marvin -- | An abstract type describing a marvin script. -- -- This is basically a collection of event handlers. -- -- Internal structure is exposed for people wanting to extend this. data Script a_aufx -- | Define a new script for marvin -- -- You need to provide a ScriptId (which can be written as a non-empty -- string, needs the OverloadedStrings language extension). This -- id is used as the key for the section in the bot config belonging to -- this script and in logging output. -- -- Roughly equivalent to "module.exports" in hubot. defineScript :: ScriptId -> ScriptDefinition a () -> ScriptInit a -- | Initializer for a script. This gets run by the server during startup -- and creates a Script data ScriptInit a -- | A type, basically a String, which identifies a script to the config -- and the logging facilities. -- -- For conversion please use mkScriptId and unwrapScriptId. -- They will perform necessary checks. data ScriptId -- | A monad for gradually defining a Script using respond -- and hear as well as any IO action. data ScriptDefinition a r -- | Basic functionality required of any adapter class IsAdapter a where type User a type Channel a where { type family User a; type family Channel a; } -- | Monad for reacting in the bot. Allows use of functions like -- send, reply and messageChannel as well as any -- arbitrary IO action using liftIO. -- -- The type parameter d is the accessible data provided by the -- trigger for this action and can be obtained with getData or -- other custom functions like getMessage and getMatch -- which typically depend on a particular type of data in d. -- -- For completeness: a is the adapter type and r is the -- return type of the monadic computation. -- -- This is also a MonadReader instance, there you can inspect the -- entire state of this reaction. This is typically only used in internal -- or utility functions and not necessary for the user. To inspect -- particular pieces of this state refer to the *Lenses* section. data BotReacting a d r -- | Whenever any message matches the provided regex this handler gets run. -- -- Equivalent to "robot.hear" in hubot hear :: Regex -> BotReacting a (User' a, Channel' a, Match, Message, TimeStamp) () -> ScriptDefinition a () -- | Runs the handler only if the bot was directly addressed. -- -- Equivalent to "robot.respond" in hubot respond :: Regex -> BotReacting a (User' a, Channel' a, Match, Message, TimeStamp) () -> ScriptDefinition a () -- | This handler runs whenever a user enters any channel (which the -- bot is subscribed to) -- -- The payload contains the entering user and the channel which was -- entered. enter :: BotReacting a (User' a, Channel' a, TimeStamp) () -> ScriptDefinition a () -- | This handler runs whenever a user exits any channel (which the -- bot is subscribed to) -- -- The payload contains the exiting user and the channel which was -- exited. exit :: BotReacting a (User' a, Channel' a, TimeStamp) () -> ScriptDefinition a () -- | This handler runs whenever a user enters the specified channel. -- -- The argument is the human readable name for the channel. -- -- The payload contains the entering user. enterIn :: Text -> BotReacting a (User' a, Channel' a, TimeStamp) () -> ScriptDefinition a () -- | This handler runs whenever a user exits the specified channel, -- provided the bot is subscribed to the channel in question. -- -- The argument is the human readable name for the channel. -- -- The payload contains the exting user. exitFrom :: Text -> BotReacting a (User' a, Channel' a, TimeStamp) () -> ScriptDefinition a () -- | This handler runs when the topic in any channel the bot is -- subscribed to changes. -- -- The payload contains the new topic and the channel in which it was -- set. topic :: BotReacting a (User' a, Channel' a, Topic, TimeStamp) () -> ScriptDefinition a () -- | This handler runs when the topic in the specified channel is -- changed, provided the bot is subscribed to the channel in question. -- -- The argument is the human readable channel name. topicIn :: Text -> BotReacting a (User' a, Channel' a, Topic, TimeStamp) () -> ScriptDefinition a () -- | Extension point for the user -- -- Allows you to handle the raw event yourself. Returning Nothing -- from the trigger function means you dont want to react to the event. -- The value returned inside the Just is available in the handler -- later using getData. customTrigger :: (Event a -> Maybe d) -> BotReacting a d () -> ScriptDefinition a () -- | Obtain the event reaction data. -- -- The type of this data depends on the reaction function used. For -- instance hear and respond will contain -- MessageReactionData. The actual contents comes from the event -- itself and was put together by the trigger. getData :: BotReacting a d d -- | Get the message that triggered this action Includes sender, target -- channel, as well as the full, untruncated text of the original message getMessage :: Get m Message => BotReacting a m Message -- | Get the results from matching the regular expression. -- -- Equivalent to "msg.match" in hubot. getMatch :: Get m Match => BotReacting a m Match -- | Get the the new topic. getTopic :: Get m Topic => BotReacting a m Topic -- | Get the stored channel in which something happened. getChannel :: forall a m. Get m (Channel' a) => BotReacting a m (Channel a) -- | Get the user which was part of the triggered action. getUser :: forall m a. Get m (User' a) => BotReacting a m (User a) -- | Get the username of a registered user. The type signature is so large -- to allow this function to be used both in BotReacting and -- ScriptDefinition. getUsername :: (HasConfigAccess m, AccessAdapter m, IsAdapter a, MonadIO m, AdapterT m ~ a) => User a -> m Text -- | Get the human readable name of a channel. The type signature is so -- large to allow this function to be used both in BotReacting and -- ScriptDefinition. getChannelName :: (HasConfigAccess m, AccessAdapter m, IsAdapter a, MonadIO m, AdapterT m ~ a) => Channel a -> m Text -- | Try to get the user with a particular username. The type signature is -- so large to allow this function to be used both in BotReacting -- and ScriptDefinition. resolveUser :: (HasConfigAccess m, AccessAdapter m, IsAdapter a, MonadIO m, AdapterT m ~ a) => Text -> m (Maybe (User a)) -- | Try to get the channel with a particular human readable name. The type -- signature is so large to allow this function to be used both in -- BotReacting and ScriptDefinition. resolveChannel :: (HasConfigAccess m, AccessAdapter m, IsAdapter a, MonadIO m, AdapterT m ~ a) => Text -> m (Maybe (Channel a)) -- | Send a message to the channel the triggering message came from. -- -- Equivalent to "robot.send" in hubot send :: (IsAdapter a, Get d (Channel' a)) => Text -> BotReacting a d () -- | Send a message to the channel the original message came from and -- address the user that sent the original message. -- -- Equivalent to "robot.reply" in hubot reply :: (IsAdapter a, Get d (User' a), Get d (Channel' a)) => Text -> BotReacting a d () -- | Send a message to a Channel (by name) messageChannel :: (HasConfigAccess m, AccessAdapter m, IsAdapter (AdapterT m), MonadLoggerIO m) => Text -> Text -> m () -- | Send a message to a channel (by adapter dependent channel object) messageChannel' :: (HasConfigAccess m, AccessAdapter m, IsAdapter (AdapterT m), MonadIO m) => Channel (AdapterT m) -> Text -> m () -- | Get a value out of the config, returns Nothing if the value -- didn't exist. -- -- This config is the config for this script. Ergo all config vars -- registered under the config section for the ScriptId of this script. -- -- The HasConfigAccess Constraint means this function can be used -- both during script definition and when a handler is run. getConfigVal :: (Configured a, HasConfigAccess m) => Name -> m (Maybe a) -- | Get a value out of the config and fail with an error if the specified -- key is not found. -- -- This config is the config for this script. Ergo all config vars -- registered under the config section for the ScriptId of this script. -- -- The HasConfigAccess Constraint means this function can be used -- both during script definition and when a handler is run. requireConfigVal :: (Configured a, HasConfigAccess m) => Name -> m a -- | Get the configured name of the bot. getBotName :: HasConfigAccess m => m Text -- | The contents of a recieved message type Message = Text -- | The topic in a channel type Topic = Text -- | Take an action and produce an IO action with the same effect. Useful -- for creating actions which can be scheduled to execute a certain time -- or asynchronous. The idea is that one can conveniently send messages -- from inside a schedulable action. extractAction :: BotReacting a () o -> ScriptDefinition a (IO o) -- | Take a reaction and produce an IO action with the same effect. Useful -- for creating actions which can be scheduled to execute a certain time -- or asynchronous. The idea is that one can conveniently send messages -- from inside a schedulable action. extractReaction :: BotReacting a s o -> BotReacting a s (IO o) module Marvin.Prelude -- | interpolate splice to Lazy Text -- -- Template Haskell splice function, used like $(isL "my str -- #{expr}") -- -- converts all expressions to Text by calling showL on the -- result. isL :: String -> Q Exp -- | interpolate splice to Text -- -- Template Haskell splice function, used like $(isT "my str -- #{expr}") -- -- converts all expressions to Text by calling showT on the -- result. isT :: String -> Q Exp -- | interpolate splice to String -- -- Template Haskell splice function, used like $(isS "my str -- #{expr}") -- -- converts all expressions to String by calling showStr on -- the result. isS :: String -> Q Exp -- | Monads in which IO computations may be embedded. Any monad -- built by applying a sequence of monad transformers to the IO -- monad will be an instance of this class. -- -- Instances should satisfy the following laws, which state that -- liftIO is a transformer of monads: -- -- class Monad m => MonadIO (m :: * -> *) -- | Lift a computation from the IO monad. liftIO :: MonadIO m => IO a -> m a -- | Lift a computation from the IO monad. liftIO :: MonadIO m => forall a. IO a -> m a -- | Conditional execution of Applicative expressions. For example, -- --
--   when debug (putStrLn "Debugging")
--   
-- -- will output the string Debugging if the Boolean value -- debug is True, and otherwise do nothing. when :: Applicative f => Bool -> f () -> f () -- | The reverse of when. unless :: Applicative f => Bool -> f () -> f () -- | for is traverse with its arguments flipped. For a -- version that ignores the results see for_. for :: (Traversable t, Applicative f) => t a -> (a -> f b) -> f (t b) -- | for_ is traverse_ with its arguments flipped. For a -- version that doesn't ignore the results see for. -- --
--   >>> for_ [1..4] print
--   1
--   2
--   3
--   4
--   
for_ :: (Foldable t, Applicative f) => t a -> (a -> f b) -> f () -- | The fromMaybe function takes a default value and and -- Maybe value. If the Maybe is Nothing, it returns -- the default values; otherwise, it returns the value contained in the -- Maybe. -- --

Examples

-- -- Basic usage: -- --
--   >>> fromMaybe "" (Just "Hello, World!")
--   "Hello, World!"
--   
-- --
--   >>> fromMaybe "" Nothing
--   ""
--   
-- -- Read an integer from a string using readMaybe. If we fail to -- parse an integer, we want to return 0 by default: -- --
--   >>> import Text.Read ( readMaybe )
--   
--   >>> fromMaybe 0 (readMaybe "5")
--   5
--   
--   >>> fromMaybe 0 (readMaybe "")
--   0
--   
fromMaybe :: a -> Maybe a -> a