module Lambdabot.Plugin.Social.Karma (karmaPlugin) where
import Lambdabot.Compat.FreenodeNick
import Lambdabot.Plugin
import qualified Lambdabot.Util.NickEq as E
import Data.Char
import Data.List
import qualified Data.Map as M
import Data.Maybe
import Text.Printf
type KarmaState = M.Map Nick Integer
type Karma = ModuleT KarmaState LB
karmaPlugin :: Module KarmaState
karmaPlugin = newModule
{ moduleCmds = return
[ (command "karma")
{ help = say "karma <polynick>. Return a person's karma value"
, process = \rest -> withMsg $ \msg -> do
sender <- getSender
tellKarma sender $ case words rest of
[] -> E.mononickToPolynick sender
(nick:_) -> E.readPolynick msg nick
}
, (command "karma+")
{ help = say "karma+ <nick>. Increment someone's karma"
, process = doCmd 1
}
, (command "karma-")
{ help = say "karma- <nick>. Decrement someone's karma"
, process = doCmd (-1)
}
, (command "karma-all")
{ help = say "karma-all. List all karma"
, process = const listKarma
}
]
, moduleDefState = return $ M.empty
, moduleSerialize = Just freenodeNickMapSerial
, contextual = \text -> withMsg $ \_ -> do
sender <- getSender
let ws = words text
decs = match "--"
incs = match "++"
match m = mapM readNick . filter okay . map (reverse . drop 2)
. filter (isPrefixOf m) . map reverse $ ws
okay x = not (elem x badNicks || any (`isPrefixOf` x) badPrefixes)
badNicks = ["", "C", "c", "notepad"]
badPrefixes = ["$", "@", "%"]
mapM_ (changeKarma (-1) sender) =<< decs
mapM_ (changeKarma 1 sender) =<< incs
}
doCmd :: Integer -> String -> Cmd Karma ()
doCmd dk rest = do
sender <- getSender
case words rest of
[] -> say "usage @karma(+|-) nick"
(nick:_) -> do
nick' <- readNick nick
changeKarma dk sender nick' >>= say
tellKarma :: Nick -> E.Polynick -> Cmd Karma ()
tellKarma sender nick = do
lookup' <- lb E.lookupMononickMap
karma <- (sum . map snd . lookup' nick) `fmap` readMS
nickStr <- withMsg (return . flip E.showPolynick nick)
say $ concat [if E.mononickToPolynick sender == nick then "You have" else nickStr ++ " has"
," a karma of "
,show karma]
listKarma :: Cmd Karma ()
listKarma = do
ks <- M.toList `fmap` readMS
let ks' = sortBy (\(_,e) (_,e') -> e' `compare` e) ks
flip mapM_ ks' $ \(k,e) -> do
k' <- showNick k
say (printf " %-20s %4d" k' e)
changeKarma :: Integer -> Nick -> Nick -> Cmd Karma String
changeKarma km sender nick
| map toLower (nName nick) == "java" && km > 0 = do
me <- getLambdabotName
changeKarma (-km) me sender
| sender == nick = return "You can't change your own karma, silly."
| otherwise = do
nickStr <- showNick nick
withMS $ \fm write -> do
let fm' = M.insertWith (+) nick km fm
let karma = fromMaybe 0 $ M.lookup nick fm'
write fm'
return (fmt nickStr km (show karma))
where
fmt n v k | v < 0 = n ++ "'s karma lowered to " ++ k ++ "."
| v == 0 = n ++ "'s karma unchanged at " ++ k ++ "."
| otherwise = n ++ "'s karma raised to " ++ k ++ "."