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