communicatorPart :: IRC.BotMonad m
                 => MVar (IRCMessage -> IO ())
                 -> TVar (S.Set B.ByteString)
                 -> TChan IRCMessage
                 -> m ()
communicatorPart mvar tvar tchan = do
    chan <- IRC.askOutChan
    _ <- liftIO $ tryPutMVar mvar (\case
        PrivateMessage {..} ->
            writeChan chan $ IRC.toMessage $
            IRC.PrivMsg Nothing [T.encodeUtf8 target] (T.encodeUtf8 content)
        Join channel -> do
            atomically $ modifyTVar tvar (S.insert (T.encodeUtf8 channel))
            writeChan chan (joinChan $ T.encodeUtf8 channel)
        Part channel -> do
            atomically $ modifyTVar tvar (S.delete (T.encodeUtf8 channel))
            writeChan chan (part $ T.encodeUtf8 channel))

    mesg <- IRC.askMessage
    maybe_nname <- IRC.askSenderNickName
    guard (isJust maybe_nname)
    let Just nname = maybe_nname

    me <- IRC.whoami

    if | msg_command mesg == "JOIN" &&
         nname == me ->
             liftIO $ atomically $ writeTChan tchan $
                 Join $ T.decodeUtf8 $ head $ msg_params mesg
       | msg_command mesg == "PART" &&
         nname == me ->
             liftIO $ atomically $ writeTChan tchan $
                 Part $ T.decodeUtf8 $ head $ msg_params mesg
       | msg_command mesg == "PRIVMSG" -> do
            privmsg <- IRC.privMsg
            reply_to <- IRC.replyTo
            case reply_to of
                Nothing -> return ()
                Just rep ->
                    liftIO $ atomically $ writeTChan tchan $
                        PrivateMessage (T.decodeUtf8 nname)
                                       (T.decodeUtf8 $ head $
                                        IRC.receivers privmsg)
                                       (T.decodeUtf8 rep)
                                       (T.decodeUtf8 $ IRC.msg privmsg)
        | otherwise -> return ()
communicatorPart :: IRC.BotMonad m
                 => MVar (IRCMessage -> IO ())
                 -> TVar (S.Set B.ByteString)
                 -> TChan IRCMessage
                 -> m ()
communicatorPart mvar tvar tchan = do
    chan <- IRC.askOutChan
    _ <- liftIO $ tryPutMVar mvar (\case
        PrivateMessage {..} ->
            writeChan chan $ IRC.toMessage $
            IRC.PrivMsg Nothing [T.encodeUtf8 target] (T.encodeUtf8 content)
        Join channel -> do
            atomically $ modifyTVar tvar (S.insert (T.encodeUtf8 channel))
            writeChan chan (joinChan $ T.encodeUtf8 channel)
        Part channel -> do
            atomically $ modifyTVar tvar (S.delete (T.encodeUtf8 channel))
            writeChan chan (part $ T.encodeUtf8 channel))

    mesg <- IRC.askMessage
    maybe_nname <- IRC.askSenderNickName
    guard (isJust maybe_nname)
    let Just nname = maybe_nname

    me <- IRC.whoami

    if | msg_command mesg == "JOIN" &&
         nname == me ->
             liftIO $ atomically $ writeTChan tchan $
                 Join $ T.decodeUtf8 $ head $ msg_params mesg
       | msg_command mesg == "PART" &&
         nname == me ->
             liftIO $ atomically $ writeTChan tchan $
                 Part $ T.decodeUtf8 $ head $ msg_params mesg
       | msg_command mesg == "PRIVMSG" -> do
            privmsg <- IRC.privMsg
            reply_to <- IRC.replyTo
            case reply_to of
                Nothing -> return ()
                Just rep ->
                    liftIO $ atomically $ writeTChan tchan $
                        PrivateMessage (T.decodeUtf8 nname)
                                       (T.decodeUtf8 $ head $
                                        IRC.receivers privmsg)
                                       (T.decodeUtf8 rep)
                                       (T.decodeUtf8 $ IRC.msg privmsg)
        | otherwise -> return ()
communicatorPart mvar tvar tchan = do
    chan <- IRC.askOutChan
    _ <- liftIO $ tryPutMVar mvar (\case
        PrivateMessage {..} ->
            writeChan chan $ IRC.toMessage $
            IRC.PrivMsg Nothing [T.encodeUtf8 target] (T.encodeUtf8 content)
        Join channel -> do
            atomically $ modifyTVar tvar (S.insert (T.encodeUtf8 channel))
            writeChan chan (joinChan $ T.encodeUtf8 channel)
        Part channel -> do
            atomically $ modifyTVar tvar (S.delete (T.encodeUtf8 channel))
            writeChan chan (part $ T.encodeUtf8 channel))

    mesg <- IRC.askMessage
    maybe_nname <- IRC.askSenderNickName
    guard (isJust maybe_nname)
    let Just nname = maybe_nname

    me <- IRC.whoami

    if | msg_command mesg == "JOIN" &&
         nname == me ->
             liftIO $ atomically $ writeTChan tchan $
                 Join $ T.decodeUtf8 $ head $ msg_params mesg
       | msg_command mesg == "PART" &&
         nname == me ->
             liftIO $ atomically $ writeTChan tchan $
                 Part $ T.decodeUtf8 $ head $ msg_params mesg
       | msg_command mesg == "PRIVMSG" -> do
            privmsg <- IRC.privMsg
            reply_to <- IRC.replyTo
            case reply_to of
                Nothing -> return ()
                Just rep ->
                    liftIO $ atomically $ writeTChan tchan $
                        PrivateMessage (T.decodeUtf8 nname)
                                       (T.decodeUtf8 $ head $
                                        IRC.receivers privmsg)
                                       (T.decodeUtf8 rep)
                                       (T.decodeUtf8 $ IRC.msg privmsg)
        | otherwise -> return ()