packages feed

funbot-0.1.0.0: src/FunBot/Commands.hs

{- This file is part of funbot.
 -
 - Written in 2015 by fr33domlover <fr33domlover@rel4tion.org>.
 -
 - ♡ Copying is an act of love. Please copy, reuse and share.
 -
 - The author(s) have dedicated all copyright and related and neighboring
 - rights to this software to the public domain worldwide. This software is
 - distributed without any warranty.
 -
 - You should have received a copy of the CC0 Public Domain Dedication along
 - with this software. If not, see
 - <http://creativecommons.org/publicdomain/zero/1.0/>.
 -}

module FunBot.Commands
    ( commandSet
    )
where

import Data.List (find, intercalate)
import Data.Settings.Types (showOption)
import FunBot.Memos (submitMemo)
import FunBot.Settings
import FunBot.Types (BotSession)
import Network.IRC.Fun.Bot.Behavior
import Network.IRC.Fun.Bot.Chat
import Network.IRC.Fun.Bot.Types
import Text.Printf (printf)

-- | The main command set, the only one currently
commandSet = CommandSet
    { prefix   = '!'
    , commands =
        [ makeCmdHelp commandSet
        , cmdInfo
        , cmdEcho
        , cmdTell
        , cmdGet
        , cmdSet
        , cmdReset
        , cmdEnable
        , cmdDisable
        ]
    }

-------------------------------------------------------------------------------
-- Echo command
-- Send the input back to the IRC channel
-------------------------------------------------------------------------------

respondEcho :: String -> String -> [String] -> BotSession ()
respondEcho chan _ []      = sendToChannel chan " "
respondEcho chan _ [param] = sendToChannel chan param
respondEcho chan _ params  = sendToChannel chan $ unwords params

cmdEcho = Command
    { names   = ["echo"]
    , respond = respondEcho
    , help    = "‘echo <text>’ - display the given text. Probably not a \
                \useful command. Exists as an example and for testing."
    }

-------------------------------------------------------------------------------
-- Help command
-- Show command help strings
-------------------------------------------------------------------------------

respondHelp :: CommandSet e s -> String -> String -> [String] -> BotSession ()
respondHelp cset chan _ [cname] =
    case find (any (== cname) . names) $ commands cset of
        Just cmd -> sendToChannel chan $
               help cmd
            ++ "\nCommand names: "
            ++ listNames Nothing Nothing True (names cmd)
        Nothing  -> sendToChannel chan "No such command, try just ‘help’ \
                                       \without a parameter."
respondHelp cset chan _ _       =
     sendToChannel chan $
           help (makeCmdHelp cset)
        ++ "\nAvailable commands: "
        ++ listPrimaryNames (Just $ prefix cset) Nothing False (commands cset)

makeCmdHelp cset = Command
    { names   = ["help", "h", "?"]
    , respond = respondHelp cset
    , help    = "‘help [<command>]’ - display help for the given command. \
                \Passing no parameters, or passing 2 or more, displays the \
                \general help (i.e. this text)."
    }

-------------------------------------------------------------------------------
-- Info command
-- Ask the bot to display some information
-------------------------------------------------------------------------------

respondInfo :: String -> String -> [String] -> BotSession ()
respondInfo chan _ ["intro"] = sendToChannel chan $
    "I’m fpbot. An instance of funbot, written in Haskell. I run in #freepost \
    \(and some extra channels). Developed in the Freepost community, I exist \
    \for fun, collaboration and learning. But I also aim to provide useful \
    \tools, in particular to Freepost and related projects and communities.\n\
    \You can start by trying ‘!help’."
respondInfo chan _ ["features"] = sendToChannel chan $
    "This is a high-level list of features and subsystems I provide. It will \
    \hopefully be kept up-to-date by updating it every time new features are \
    \added.\n\
    \• Help and information system (!help, !info)\n\
    \• A settings system (!get, !set, etc.)\n\
    \• Announcing commits in Git repositories\n\
    \• Announcing RSS/Atom feed items\n\
    \• Leaving memos (requires enabling nick tracking for the channel)\n\
    \There is also an overview of the bot API features, useful to \
    \contributors/developers, in the guide at \
    \<http://rel4tion.org/projects/funbot/guide>."
respondInfo chan _ ["contrib"] = sendToChannel chan $
    "Thinking about contributing to my development? Opening a ticket, fixing \
    \a bug, implementing a feature? Check out the project page at \
    \<http://rel4tion.org/projects/funbot>, which links to the contribution \
    \guide, to the tickets page and more."
respondInfo chan _ ["copying"] = sendToChannel chan $
    "♡ Copying is an act of love. Please copy, reuse and share me! \
    \Grab a copy of me from <https://notabug.org/fr33domlover/funbot>."
respondInfo chan _ ["links"] = sendToChannel chan $
    "Website:     http://rel4tion.org/projects/funbot\n\
    \Code:        https://notabug.org/fr33domlover/funbot\n\
    \Tickets:     http://rel4tion.org/projects/funbot/tickets\n\
    \Roadmap:     http://rel4tion.org/projects/funbot/ideas\n\
    \Dev guide:   http://rel4tion.org/projects/funbot/guide\n\
    \User manual: http://rel4tion.org/projects/funbot/manual"
respondInfo chan nick [arg] =
    failToChannel chan nick $ InvalidArg (Just 1) (Just arg)
respondInfo chan nick args =
    failToChannel chan nick $ WrongNumArgsN (Just $ length args) (Just 1)

cmdInfo = Command
    { names   = ["info", "i"]
    , respond = respondInfo
    , help    = "‘info ( intro | features | contrib | copying | links)’ - \
                \display information."
    }

-------------------------------------------------------------------------------
-- Tell command
-- Tell something to some other user
-------------------------------------------------------------------------------

respondTell :: String -> String -> [String] -> BotSession ()
respondTell chan sender (recip:msghead:msgtail) =
    submitMemo sender (Just chan) recip (unwords $ msghead : msgtail)
respondTell chan nick args =
    failToChannel chan nick $ WrongNumArgsN (Just $ length args) Nothing

cmdTell = Command
    { names   = ["tell"]
    , respond = respondTell
    , help    = "‘tell <nick> <text>’ - leave a memo for a user to see later"
    }

-------------------------------------------------------------------------------
-- Get, set, enable and disable commands
-- Manage bot settings
-------------------------------------------------------------------------------

respondGet :: String -> String -> [String] -> BotSession ()
respondGet chan _    []     = respondGet' "" chan
respondGet chan _    [path] = respondGet' path chan
respondGet chan nick args   =
    failToChannel chan nick $ WrongNumArgsN (Just $ length args) (Just 1)

respondSet :: String -> String -> [String] -> BotSession ()
respondSet chan _    [name, val] = respondSet' name val chan
respondSet chan nick args        =
    failToChannel chan nick $ WrongNumArgsN (Just $ length args) (Just 2)

respondReset :: String -> String -> [String] -> BotSession ()
respondReset chan _    [name] = respondReset' name chan
respondReset chan nick args   =
    failToChannel chan nick $ WrongNumArgsN (Just $ length args) (Just 1)

respondBool :: Bool -> String -> String -> [String] -> BotSession ()
respondBool val chan _    [name] = respondSet' name (showOption val) chan
respondBool _   chan nick args   =
    failToChannel chan nick $ WrongNumArgsN (Just $ length args) (Just 1)

respondEnable = respondBool True

respondDisable = respondBool False

cmdGet = Command
    { names   = ["get"]
    , respond = respondGet
    , help    = "‘get <option>’ - get the value of a settings option at the \
                \given path"
    }

cmdSet = Command
    { names   = ["set"]
    , respond = respondSet
    , help    = "‘set <option> <value>’ - set a settings option at the given \
                \path to the given value"
    }

cmdReset = Command
    { names   = ["reset"]
    , respond = respondReset
    , help    = "‘reset <option>’ - set a settings option at the given path to \
                \its default value"
    }

cmdEnable = Command
    { names   = ["enable"]
    , respond = respondEnable
    , help    = "‘enable <option>’ - set a settings option at the given path \
                \to True"
    }

cmdDisable = Command
    { names   = ["disable"]
    , respond = respondDisable
    , help    = "‘disable <option>’ - set a settings option at the given path \
                \to False"
    }