packages feed

lambdabot-4.1: Plugin/Topic.hs

--
-- | The Topic plugin is an interface for messing with the channel topic.
--   It can alter the topic in various ways and keep track of the changes.
--   The advantage of having the bot maintain the topic is that we get an
--   authoritative source for the current topic, when the IRC server decides
--   to delete it due to Network Splits.
--
module Plugin.Topic (theModule) where

import Plugin
import Message (Message, setTopic, Nick, readNick)
import qualified Data.Map as M

import Control.Monad.State (gets)

PLUGIN Topic

instance Module TopicModule () where
  moduleHelp _ s = case s of
      "topic-tell" -> "@topic-tell #chan -- " ++
                       "Tell the requesting person of the topic of the channel"
      "topic-cons" -> "@topic-cons #chan <mess> -- " ++
                       "Add a new topic item to the front of the topic list"
      "topic-snoc" -> "@topic-snoc #chan <mess> -- " ++
                       "Add a new topic item to the back of the topic list"
      "topic-tail" -> "@topic-tail #chan -- " ++
                       "Remove the first topic item from the topic list"
      "topic-null" -> "@topic-null #chan -- " ++
                       "Clear out the topic entirely"
      "topic-init" -> "@topic-init #chan -- " ++
                       "Remove the last topic item from the topic list"
      _ -> "Someone forgot to document his new Topic function! Shame on him/her!"

  moduleCmds   _ = ["topic-tell",
                   "topic-cons", "topic-snoc",
                   "topic-tail", "topic-init", "topic-null"]

  process _ msg _ "topic-cons" text = lift $ alterTopic msg chan (topic_item :)
        where (chan, topic_item) = splitFirstWord text

  process _ msg _ "topic-snoc" text = lift $ alterTopic msg chan (snoc topic_item)
        where (chan, topic_item) = splitFirstWord text

  process _ msg _ "topic-tail" chan = lift $ alterTopic msg chan tail
  process _ msg _ "topic-init" chan = lift $ alterTopic msg chan init
  process _ msg _ "topic-null" chan = lift $ send (Message.setTopic (readNick msg chan) "[]") >> return []
  process _ msg _ "topic-tell" chan = lift $ lookupTopic (readNick msg chan) $ \maybetopic -> return $
        case maybetopic of
            Just x  -> [x]
            Nothing -> ["Do not know that channel"]

------------------------------------------------------------------------

-- | 'lookupTopic' Takes a channel and a modifier function f. It then
--   proceeds to look up the channel topic for the channel given, returning
--   Just t or Nothing to the modifier function which can then decide what
--   to do with the topic
lookupTopic :: Nick                          -- ^ Channel
            -> (Maybe String -> LB [String]) -- ^ Modifier function
            -> LB [String]
lookupTopic chan f = gets (\s -> M.lookup (mkCN chan) (ircChannels s)) >>= f

-- | 'alterTopic' takes a message, a channel and an altering function.
--   Then it alters the topic in the channel by the altering function,
--   returning eventual problems back to the sender.
alterTopic :: Message a
           => a                      -- ^ Original messesg
           -> String                 -- ^ Channel name
           -> ([String] -> [String]) -- ^ Modifying function
           -> LB [String]
alterTopic msg chan f =
  let chan' = readNick msg chan
      p maybetopic =
        case maybetopic of
          Just x -> case reads x of
                [(xs, "")] -> do send $ Message.setTopic chan' (show $ f $ xs)
                                 return []
                [(xs, r)] | length r <= 2
                  -> do send $ Message.setTopic chan' (show $ f $ xs)
                        return ["ignoring bogus characters: " ++ r]

                _ -> return ["Topic does not parse. Should be of the form [\"...\",...,\"...\"]"]
          Nothing -> return ["I do not know the channel " ++ chan]
   in lookupTopic chan' p