doJoinChannel ::
  UserInfo         {- ^ who joined   -} ->
  Fuzzy ByteString {- ^ account name -} ->
  Identifier       {- ^ channel      -} ->
  IrcConnection -> Logic IrcConnection
doJoinChannel who acct chan conn =
  do stamp <- getStamp

     -- add channel if necessary
     let conn1
           | isMyNick (userNick who) conn =
               set (connChannels . at chan) (Just defaultChannel) conn
           | otherwise = conn

     -- add user to channel
         conn2 = set (connChannels . ix chan . chanUsers . at (userNick who))
                     (Just "") -- empty modes
                     conn1

         conn3 = recordAccount (learnUserInfo who (ensureRecord conn2))

     -- update user record
         ensureRecord = over (connUsers . at (userNick who)) (Just . fromMaybe defaultIrcUser)

         recordAccount = case acct of
                   None -> over (connUsers . ix (userNick who))
                                (set usrAccount Nothing)
                   Known a -> over (connUsers . ix (userNick who))
                                (set usrAccount (Just a))
                   Unknown -> id

     -- record join event
         m = defaultIrcMessage
               { _mesgType = JoinMsgType
               , _mesgSender = who
               , _mesgStamp = stamp
               }
     recordMessage m chan conn3
doJoinChannel ::
  UserInfo         {- ^ who joined   -} ->
  Fuzzy ByteString {- ^ account name -} ->
  Identifier       {- ^ channel      -} ->
  IrcConnection -> Logic IrcConnection
doJoinChannel who acct chan conn =
  do stamp <- getStamp

     -- add channel if necessary
     let conn1
           | isMyNick (userNick who) conn =
               set (connChannels . at chan) (Just defaultChannel) conn
           | otherwise = conn

     -- add user to channel
         conn2 = set (connChannels . ix chan . chanUsers . at (userNick who))
                     (Just "") -- empty modes
                     conn1

         conn3 = recordAccount (learnUserInfo who (ensureRecord conn2))

     -- update user record
         ensureRecord = over (connUsers . at (userNick who)) (Just . fromMaybe defaultIrcUser)

         recordAccount = case acct of
                   None -> over (connUsers . ix (userNick who))
                                (set usrAccount Nothing)
                   Known a -> over (connUsers . ix (userNick who))
                                (set usrAccount (Just a))
                   Unknown -> id

     -- record join event
         m = defaultIrcMessage
               { _mesgType = JoinMsgType
               , _mesgSender = who
               , _mesgStamp = stamp
               }
     recordMessage m chan conn3
doJoinChannel who acct chan conn =
  do stamp <- getStamp

     -- add channel if necessary
     let conn1
           | isMyNick (userNick who) conn =
               set (connChannels . at chan) (Just defaultChannel) conn
           | otherwise = conn

     -- add user to channel
         conn2 = set (connChannels . ix chan . chanUsers . at (userNick who))
                     (Just "") -- empty modes
                     conn1

         conn3 = recordAccount (learnUserInfo who (ensureRecord conn2))

     -- update user record
         ensureRecord = over (connUsers . at (userNick who)) (Just . fromMaybe defaultIrcUser)

         recordAccount = case acct of
                   None -> over (connUsers . ix (userNick who))
                                (set usrAccount Nothing)
                   Known a -> over (connUsers . ix (userNick who))
                                (set usrAccount (Just a))
                   Unknown -> id

     -- record join event
         m = defaultIrcMessage
               { _mesgType = JoinMsgType
               , _mesgSender = who
               , _mesgStamp = stamp
               }
     recordMessage m chan conn3