kevin-0.4: Kevin/IRC/Protocol/Send.hs
module Kevin.IRC.Protocol.Send (
sendJoin,
sendPart,
sendSetUserMode,
sendChangeUserMode,
sendNotice,
sendRoomNotice,
sendChanMsg,
sendChanAction,
sendKick,
sendTopic,
sendChanMode,
sendUserList,
sendPong,
sendNoticeClone,
sendNoticeUnclone,
sendWhoisReply
) where
import Kevin.Base
import qualified Data.Text as T
hostname :: T.Text
hostname = ":chat.deviantart.com"
getHost :: T.Text -> T.Text
getHost u = T.concat [":", u, "!", u, "@chat.deviantart.com"]
sendPacket :: T.Text -> KevinIO ()
sendPacket p = get_ >>= \k -> io . writeClient k $ T.append p "\r\n"
maybeBody :: Maybe T.Text -> T.Text
maybeBody = maybe "" (T.append " :")
type Str = T.Text
type Room = Str
type Username = Str
sendJoin :: Username -> Room -> KevinIO ()
sendPart :: Username -> Room -> Maybe Str -> KevinIO ()
sendSetUserMode :: Username -> Room -> Int -> KevinIO ()
sendChangeUserMode :: Username -> Room -> Int -> Int -> KevinIO ()
sendNotice :: Str -> KevinIO ()
sendRoomNotice :: Room -> Str -> KevinIO ()
sendChanMsg, sendChanAction :: Username -> Room -> Str -> KevinIO ()
sendKick :: Username -> Username -> Room -> Maybe Str -> KevinIO ()
sendTopic :: Username -> Room -> Username -> Str -> Str -> KevinIO ()
sendChanMode :: Username -> Room -> KevinIO ()
sendUserList :: Username -> [User] -> Room -> KevinIO ()
sendPong :: T.Text -> KevinIO ()
sendNoticeClone :: Username -> Int -> Room -> KevinIO ()
sendNoticeUnclone :: Username -> Int -> Room -> KevinIO ()
sendWhoisReply :: Username -> Username -> Username -> [Room] -> Int -> Int -> KevinIO ()
sendJoin us rm =
sendPacket $ printf "%s JOIN :%s" [getHost us, rm]
sendPart us rm msg =
sendPacket $ printf "%s PART %s%s" [getHost us, rm, maybeBody msg]
sendSetUserMode us rm m = unless (T.null mode) $
sendPacket $ printf "%s MODE %s +%s %s" [hostname, rm, mode, us]
where mode = levelToMode m
sendChangeUserMode us rm old new = unless (oldMode == newMode) $
sendPacket $ printf "%s MODE %s %s" [hostname, rm, modesAndUser]
where
oldMode = levelToMode old
newMode = levelToMode new
modesAndUser = case (oldMode, newMode) of
("", "") -> T.concat ["-v ", us]
("", _) -> T.concat ["+", newMode, " ", us]
(_, "") -> T.concat ["-", oldMode, " ", us]
(a, b) -> T.concat ["-", a, "+", b, " ", us, " ", us]
sendNotice =
sendPacket . printf "NOTICE AUTH :%s" . return
sendRoomNotice room n =
sendPacket $ printf "%s NOTICE %s :%s" [hostname, room, n]
sendChanMsg sender room msg = mapM_ (\x ->
sendPacket $ printf "%s PRIVMSG %s :%s" [getHost sender, room, x]
) . T.splitOn "\n" $ msg
sendChanAction sender room msg = mapM_ (\x ->
sendPacket $ printf "%s PRIVMSG %s :\1ACTION %s\1" [getHost sender, room, x]
) . T.splitOn "\n" $ msg
sendKick kickee kicker room msg =
sendPacket $ printf "%s KICK %s %s%s" [getHost kicker, room, kickee, maybeBody msg]
sendTopic us rm maker top startdate = do
sendPacket $ printf "%s 332 %s %s :%s" [hostname, us, rm, top]
sendPacket $ printf "%s 333 %s %s %s %s" [hostname, us, rm, maker, startdate]
sendChanMode us rm = do
sendPacket $ printf "%s 324 %s %s +t" [hostname, us, rm]
sendPacket $ printf "%s 329 %s %s 767529000" [hostname, us, rm]
sendUserList us uss rm = do
mapM_ (\nms ->
sendPacket $ printf "%s 353 %s = %s :%s" [hostname, us, rm, T.unwords nms]) chunkedNames
sendPacket $ printf "%s 366 %s %s :End of /NAMES list." [hostname, us, rm]
where
names = map (\u -> T.concat [levelToSym $ privclassLevel u, username u]) uss
chunkedNames = reverse . map reverse . subchunk' 432 names $ [[]]
subchunk' n = fix (\f x y -> let hy = head y; hx = head x; ty = tail y; tx = tail x in if null x
then y
else if sum (map T.length hy) + T.length hx <= n
then f tx ((hx:hy):ty)
else f tx ([hx]:y))
sendPong p =
sendPacket $ printf "%s PONG chat.deviantart.com :%s" [hostname, p]
sendNoticeClone uname i rm =
sendPacket $ printf "%s NOTICE %s :%s has joined again (now joined %s times)" [hostname, rm, uname, T.pack $ show i]
sendNoticeUnclone uname i rm =
sendPacket $ printf "%s NOTICE %s :%s has parted (now joined %s)" [hostname, rm, uname, times]
where
times | i == 1 = "once"
| otherwise = T.pack (show i) `T.append` " times"
sendWhoisReply me us rn rooms idle signon = do
sendPacket $ printf "%s 311 %s %s %s chat.deviantart.com * :%s" [hostname, me, us, us, rn]
sendPacket $ printf "%s 307 %s %s :is a registered nick" [hostname, me, us]
sendPacket $ printf "%s 319 %s %s :%s" [hostname, me, us, T.intercalate " " . map (T.cons '#') $ rooms]
sendPacket $ printf "%s 312 %s %s chat.deviantart.com :dAmn" [hostname, me, us]
sendPacket $ printf "%s 317 %s %s %s %s :seconds idle, signon time" [hostname, me, us, T.pack $ show idle, T.pack $ show signon]
sendPacket $ printf "%s 318 %s %s :End of /WHOIS list." [hostname, me, us]
levelToSym :: Int -> T.Text
levelToSym x | x > 0 && x <= 35 = ""
| x > 35 && x <= 70 = "+"
| x > 70 && x < 99 = "@"
| x == 99 = "~"
| otherwise = ""
levelToMode :: Int -> T.Text
levelToMode x = case levelToSym x of
"" -> ""
"+" -> "v"
"@" -> "o"
"~" -> "q"
_ -> error "levelToSym, what are you doing"