packages feed

kevin-0.11.0: src/Kevin/Damn/Protocol/Send.hs

{-# LANGUAGE OverloadedStrings #-}

module Kevin.Damn.Protocol.Send (
    sendPacket,
    formatRoom,
    deformatRoom,

    sendHandshake,
    sendLogin,
    sendJoin,
    sendPart,
    sendMsg,
    sendAction,
    sendNpMsg,
    sendPromote,
    sendDemote,
    sendBan,
    sendUnban,
    sendKick,
    sendGet,
    sendWhois,
    sendSet,
    sendAdmin,
    sendKill
) where

import           Data.Char      (toLower)
import           Data.List      (sort)
import           Data.Monoid
import qualified Data.Text as T
import           Kevin.Base
import           Kevin.Version

maybeBody :: Maybe T.Text -> T.Text
maybeBody = maybe "" ("\n\n" <>)

sendPacket :: T.Text -> KevinIO ()
sendPacket p = get_ >>= \k -> io . writeServer k . T.snoc p $ '\0'

formatRoom :: T.Text -> KevinIO T.Text
formatRoom b = case T.splitAt 1 b of
                   ("#",s) -> return $ "chat:" <> s
                   ("&",s) -> do
                       uname <- use_ name
                       return . ("pchat:" <>) . T.intercalate ":" . sort . map (T.map toLower) $ [uname, s]
                   r -> return $ "chat" <> uncurry (<>) r

deformatRoom :: T.Text -> KevinIO T.Text
deformatRoom room = if "chat:" `T.isPrefixOf` room
                       then return $ '#' `T.cons` T.drop 5 room
                       else do
                           uname <- use_ name
                           return $ T.cons '&' (head (filter (/= uname) . T.splitOn ":" . T.drop 6 $ room))

type Str      = T.Text -- just make it shorter
type Room     = Str
type Username = Str
type Pc       = Str

-- * Communication to the server
sendHandshake                  ::                                  KevinIO ()
sendLogin                      :: Username -> Str               -> KevinIO ()
sendJoin, sendPart             :: Room                          -> KevinIO ()
sendMsg, sendAction, sendNpMsg :: Room -> Str                   -> KevinIO ()
sendPromote, sendDemote        :: Room -> Username -> Maybe Pc  -> KevinIO ()
sendBan, sendUnban             :: Room -> Username              -> KevinIO ()
sendKick                       :: Room -> Username -> Maybe Str -> KevinIO ()
sendGet                        :: Room -> Str                   -> KevinIO ()
sendWhois                      :: Username                      -> KevinIO ()
sendSet                        :: Room -> Str -> Str            -> KevinIO ()
sendAdmin                      :: Room -> Str                   -> KevinIO ()
sendKill                       :: Username -> Str               -> KevinIO ()

sendHandshake = sendPacket $ printf "dAmnClient 0.3\nagent=kevin%s\n" [versionStr]

sendLogin u token = sendPacket $ printf "login %s\npk=%s\n" [u, token]

sendJoin room = do
    roomname <- formatRoom room
    sendPacket $ printf "join %s\n" [roomname]

sendPart room = do
    roomname <- formatRoom room
    sendPacket $ printf "part %s\n" [roomname]

sendMsg = sendNpMsg

sendAction room msg = do
    roomname <- formatRoom room
    sendPacket $ printf "send %s\n\naction main\n\n%s" [roomname, msg]

sendNpMsg room msg = do
    roomname <- formatRoom room
    sendPacket $ printf "send %s\n\nnpmsg main\n\n%s" [roomname, msg]

sendPromote room us pc = do
    roomname <- formatRoom room
    sendPacket $ printf "send %s\n\npromote %s%s" [roomname, us, maybeBody pc]

sendDemote room us pc = do
    roomname <- formatRoom room
    sendPacket $ printf "send %s\n\ndemote %s%s" [roomname, us, maybeBody pc]

sendBan room us = do
    roomname <- formatRoom room
    sendPacket $ printf "send %s\n\nban %s\n\n" [roomname, us]

sendUnban room us = do
    roomname <- formatRoom room
    sendPacket $ printf "send %s\n\nunban %s\n\n" [roomname, us]

sendKick room us reason = do
    roomname <- formatRoom room
    sendPacket $ printf "kick %s\nu=%s%s\n" [roomname, us, maybeBody reason]

sendGet room prop = do
    guard $ prop `elem` ["title", "topic", "privclasses", "members"]
    roomname <- formatRoom room
    sendPacket $ printf "get %s\np=%s\n" [roomname, prop]

sendWhois us = sendPacket $ printf "get login:%s\np=info\n" [us]

sendSet room prop val = do
    guard (prop == "topic" || prop == "title")
    roomname <- formatRoom room
    sendPacket $ printf "set %s\np=%s\n\n%s\n" [roomname, prop, val]

sendAdmin room cmd = do
    roomname <- formatRoom room
    sendPacket $ printf "send %s\n\nadmin\n\n%s" [roomname, cmd]

sendKill = undefined