{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}

-- Copyright (c) 2005 Don Stewart - http://www.cse.unsw.edu.au/~dons
-- GPL version 2 or later (see http://www.gnu.org/copyleft/gpl.html)

-- | Simple wrapper over privmsg to get time information via the CTCP
module Lambdabot.Plugin.IRC.Localtime (localtimePlugin) where

import Lambdabot.Plugin
import Lambdabot.Bot (ircPrivmsg')
import qualified Data.Map as M

type TimeMap = M.Map Nick  -- the person who's time we requested
                    [Nick] -- a list of targets waiting on this time

localtimePlugin :: Module TimeMap
localtimePlugin :: Module (Map Nick [Nick])
localtimePlugin = Module (Map Nick [Nick])
forall st. Module st
newModule
    { moduleDefState = return M.empty

    , moduleCmds = return
        [ (command "time")
            { aliases = ["localtime"]
            , help = say "time <user>. Print a user's local time. User's client must support ctcp pings."
            , process = doLocalTime
            }
        , (command "localtime-reply")
            { help = say "time <user>. Print a user's local time. User's client must support ctcp pings."
            , process = doReply
            }
        ]
    } :: Module TimeMap

-- record this person as a callback, for when we (asynchronously) get a result
doLocalTime :: (MonadLBState m, LBState m ~ M.Map Nick [Nick]) =>
               [Char] -> Cmd m ()
doLocalTime :: forall (m :: * -> *).
(MonadLBState m, LBState m ~ Map Nick [Nick]) =>
String -> Cmd m ()
doLocalTime [] = do
    n <- Cmd m Nick
forall (m :: * -> *). Monad m => Cmd m Nick
getSender
    doLocalTime (nName n)

doLocalTime String
rawWho = do
    whoAsked <- Cmd m Nick
forall (m :: * -> *). Monad m => Cmd m Nick
getTarget
    whoToPing <- readNick $ fst $ break (== ' ') rawWho
    me <- getLambdabotName
    if whoToPing /= me
        then do
            modifyMS $ \LBState (Cmd m)
st -> ([Nick] -> [Nick] -> [Nick])
-> Nick -> [Nick] -> Map Nick [Nick] -> Map Nick [Nick]
forall k a. Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
M.insertWith [Nick] -> [Nick] -> [Nick]
forall a. [a] -> [a] -> [a]
(++) Nick
whoToPing [Nick
whoAsked] Map Nick [Nick]
LBState (Cmd m)
st
            -- this is a CTCP time call, which returns a NOTICE
            lb $ ircPrivmsg' whoToPing ("\^ATIME\^A")     -- has to be raw
        else say "I live on the internet, do you expect me to have a local time?"

-- the Base module caught the NOTICE TIME, mapped it to a PRIVMGS, and here it is :)
doReply :: (MonadLBState m, LBState m ~ M.Map Nick [Nick]) =>
           [Char] -> Cmd m ()
doReply :: forall (m :: * -> *).
(MonadLBState m, LBState m ~ Map Nick [Nick]) =>
String -> Cmd m ()
doReply String
text = do
    let (String
whoGotPinged', String
time') = (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
break (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
':') String
text
        time :: String
time = Int -> String -> String
forall a. Int -> [a] -> [a]
drop Int
1 String
time'
    whoGotPinged <- String -> Cmd m Nick
forall (m :: * -> *). Monad m => String -> Cmd m Nick
readNick String
whoGotPinged'

    targets <- withMS $ \LBState (Cmd m)
st LBState (Cmd m) -> Cmd m ()
set -> do
        case Nick -> Map Nick [Nick] -> Maybe [Nick]
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup Nick
whoGotPinged Map Nick [Nick]
LBState (Cmd m)
st of
            Maybe [Nick]
Nothing -> [Nick] -> Cmd m [Nick]
forall a. a -> Cmd m a
forall (m :: * -> *) a. Monad m => a -> m a
return []
            Just [Nick]
xs -> do LBState (Cmd m) -> Cmd m ()
set (Nick -> [Nick] -> Map Nick [Nick] -> Map Nick [Nick]
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert Nick
whoGotPinged [] Map Nick [Nick]
LBState (Cmd m)
st) -- clear the callback state
                          [Nick] -> Cmd m [Nick]
forall a. a -> Cmd m a
forall (m :: * -> *) a. Monad m => a -> m a
return [Nick]
xs
    whoGotPinged'' <- showNick whoGotPinged
    let txt = String
"Local time for " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
whoGotPinged'' String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
time
    lb $ flip mapM_ targets $ flip ircPrivmsg' txt