{-# Language OverloadedStrings #-}
{-|
Module      : Client.Commands.Channel
Description : Channel management command implementations
Copyright   : (c) Eric Mertens, 2016-2020
License     : ISC
Maintainer  : emertens@gmail.com
-}

module Client.Commands.Channel (channelCommands) where

import           Client.Commands.Arguments.Spec
import           Client.Commands.TabCompletion
import           Client.Commands.Types
import           Client.Commands.WordCompletion
import           Client.State
import           Client.State.Channel
import           Client.State.Focus
import           Client.State.Network
import           Client.UserHost
import           Control.Applicative
import           Control.Lens
import           Control.Monad
import           Data.Foldable (traverse_)
import           Data.List.Split (chunksOf)
import           Data.Maybe (fromMaybe)
import           Data.Text (Text)
import qualified Client.State.EditBox as Edit
import qualified Data.HashMap.Strict as HashMap
import qualified Data.Text as Text
import           Irc.Commands
import           Irc.Modes
import           Irc.UserInfo
import           Irc.Identifier
import           LensUtils (setStrict)

channelCommands :: CommandSection
channelCommands :: CommandSection
channelCommands = Text -> [Command] -> CommandSection
CommandSection Text
"IRC channel management"

  [ NonEmpty Text
-> Args ClientState [String]
-> Text
-> CommandImpl [String]
-> Command
forall a.
NonEmpty Text
-> Args ClientState a -> Text -> CommandImpl a -> Command
Command
      (Text -> NonEmpty Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
"mode")
      ([String] -> Maybe [String] -> [String]
forall a. a -> Maybe a -> a
fromMaybe [] (Maybe [String] -> [String])
-> Ap (Arg ClientState) (Maybe [String])
-> Args ClientState [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Args ClientState [String] -> Ap (Arg ClientState) (Maybe [String])
forall r a. Args r a -> Args r (Maybe a)
optionalArg (String
-> (ClientState -> String -> Maybe (Args ClientState [String]))
-> Args ClientState [String]
forall r a. String -> (r -> String -> Maybe (Args r a)) -> Args r a
extensionArg String
"[modes]" ClientState -> String -> Maybe (Args ClientState [String])
modeParamArgs))
      Text
"Sets IRC modes.\n\
      \\n\
      \Examples:\n\
      \Setting a ban:           /mode +b *!*@hostname\n\
      \Removing a quiet:        /mode -q *!*@hostname\n\
      \Voicing two users:       /mode +vv user1 user2\n\
      \Demoting an op to voice: /mode +v-o user1 user1\n\
      \\n\
      \When executed in a network window, mode changes are applied to your user.\n\
      \When executed in a channel window, mode changes are applied to the channel.\n\
      \\n\
      \This command has parameter sensitive tab-completion.\n\
      \\n\
      \See also: /masks /channelinfo\n"
    (CommandImpl [String] -> Command)
-> CommandImpl [String] -> Command
forall a b. (a -> b) -> a -> b
$ NetworkCommand [String]
-> (Bool -> NetworkCommand String) -> CommandImpl [String]
forall a.
NetworkCommand a
-> (Bool -> NetworkCommand String) -> CommandImpl a
NetworkCommand NetworkCommand [String]
cmdMode Bool -> NetworkCommand String
tabMode

  , NonEmpty Text
-> Args ClientState String -> Text -> CommandImpl String -> Command
forall a.
NonEmpty Text
-> Args ClientState a -> Text -> CommandImpl a -> Command
Command
      (Text -> NonEmpty Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
"masks")
      (String -> Args ClientState String
forall r. String -> Args r String
simpleToken String
"mode")
      Text
"Show mask lists for current channel.\n\
      \\n\
      \Common \^Bmode\^B values:\n\
      \\^Bb\^B: bans\n\
      \\^Bq\^B: quiets\n\
      \\^BI\^B: invite exemptions (op view only)\n\
      \\^Be\^B: ban exemption (op view only)s\n\
      \\n\
      \To populate the mask lists for the first time use: /mode \^Bmode\^B\n\
      \\n\
      \See also: /mode\n"
    (CommandImpl String -> Command) -> CommandImpl String -> Command
forall a b. (a -> b) -> a -> b
$ ChannelCommand String
-> (Bool -> ChannelCommand String) -> CommandImpl String
forall a.
ChannelCommand a
-> (Bool -> ChannelCommand String) -> CommandImpl a
ChannelCommand ChannelCommand String
cmdMasks Bool -> ChannelCommand String
noChannelTab

  , NonEmpty Text
-> Args ClientState String -> Text -> CommandImpl String -> Command
forall a.
NonEmpty Text
-> Args ClientState a -> Text -> CommandImpl a -> Command
Command
      (Text -> NonEmpty Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
"invite")
      (String -> Args ClientState String
forall r. String -> Args r String
simpleToken String
"nick")
      Text
"Invite a user to the current channel.\n"
    (CommandImpl String -> Command) -> CommandImpl String -> Command
forall a b. (a -> b) -> a -> b
$ ChannelCommand String
-> (Bool -> ChannelCommand String) -> CommandImpl String
forall a.
ChannelCommand a
-> (Bool -> ChannelCommand String) -> CommandImpl a
ChannelCommand ChannelCommand String
cmdInvite Bool -> ChannelCommand String
simpleChannelTab

  , NonEmpty Text
-> Args ClientState String -> Text -> CommandImpl String -> Command
forall a.
NonEmpty Text
-> Args ClientState a -> Text -> CommandImpl a -> Command
Command
      (Text -> NonEmpty Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
"topic")
      (String -> Args ClientState String
forall r. String -> Args r String
remainingArg String
"message")
      Text
"Set the topic on the current channel.\n\
      \\n\
      \Tab-completion with no \^Bmessage\^B specified will load the current topic for editing.\n"
    (CommandImpl String -> Command) -> CommandImpl String -> Command
forall a b. (a -> b) -> a -> b
$ ChannelCommand String
-> (Bool -> ChannelCommand String) -> CommandImpl String
forall a.
ChannelCommand a
-> (Bool -> ChannelCommand String) -> CommandImpl a
ChannelCommand ChannelCommand String
cmdTopic Bool -> ChannelCommand String
tabTopic

  , NonEmpty Text
-> Args ClientState (String, String)
-> Text
-> CommandImpl (String, String)
-> Command
forall a.
NonEmpty Text
-> Args ClientState a -> Text -> CommandImpl a -> Command
Command
      (Text -> NonEmpty Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
"kick")
      ((String -> String -> (String, String))
-> Args ClientState String
-> Args ClientState String
-> Args ClientState (String, String)
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 (,) (String -> Args ClientState String
forall r. String -> Args r String
simpleToken String
"nick") (String -> Args ClientState String
forall r. String -> Args r String
remainingArg String
"reason"))
      Text
"Kick a user from the current channel.\n\
      \\n\
      \See also: /kickban /remove\n"
    (CommandImpl (String, String) -> Command)
-> CommandImpl (String, String) -> Command
forall a b. (a -> b) -> a -> b
$ ChannelCommand (String, String)
-> (Bool -> ChannelCommand String) -> CommandImpl (String, String)
forall a.
ChannelCommand a
-> (Bool -> ChannelCommand String) -> CommandImpl a
ChannelCommand ChannelCommand (String, String)
cmdKick Bool -> ChannelCommand String
simpleChannelTab

  , NonEmpty Text
-> Args ClientState (String, String)
-> Text
-> CommandImpl (String, String)
-> Command
forall a.
NonEmpty Text
-> Args ClientState a -> Text -> CommandImpl a -> Command
Command
      (Text -> NonEmpty Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
"kickban")
      ((String -> String -> (String, String))
-> Args ClientState String
-> Args ClientState String
-> Args ClientState (String, String)
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 (,) (String -> Args ClientState String
forall r. String -> Args r String
simpleToken String
"nick") (String -> Args ClientState String
forall r. String -> Args r String
remainingArg String
"reason"))
      Text
"Ban and kick a user from the current channel.\n\
      \\n\
      \Users are banned by hostname match.\n\
      \See also: /kick /remove\n"
    (CommandImpl (String, String) -> Command)
-> CommandImpl (String, String) -> Command
forall a b. (a -> b) -> a -> b
$ ChannelCommand (String, String)
-> (Bool -> ChannelCommand String) -> CommandImpl (String, String)
forall a.
ChannelCommand a
-> (Bool -> ChannelCommand String) -> CommandImpl a
ChannelCommand ChannelCommand (String, String)
cmdKickBan Bool -> ChannelCommand String
simpleChannelTab

  , NonEmpty Text
-> Args ClientState (String, String)
-> Text
-> CommandImpl (String, String)
-> Command
forall a.
NonEmpty Text
-> Args ClientState a -> Text -> CommandImpl a -> Command
Command
      (Text -> NonEmpty Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
"remove")
      ((String -> String -> (String, String))
-> Args ClientState String
-> Args ClientState String
-> Args ClientState (String, String)
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 (,) (String -> Args ClientState String
forall r. String -> Args r String
simpleToken String
"nick") (String -> Args ClientState String
forall r. String -> Args r String
remainingArg String
"reason"))
      Text
"Remove a user from the current channel.\n\
      \\n\
      \Remove works like /kick except it results in a PART.\n\
      \See also: /kick /kickban\n"
    (CommandImpl (String, String) -> Command)
-> CommandImpl (String, String) -> Command
forall a b. (a -> b) -> a -> b
$ ChannelCommand (String, String)
-> (Bool -> ChannelCommand String) -> CommandImpl (String, String)
forall a.
ChannelCommand a
-> (Bool -> ChannelCommand String) -> CommandImpl a
ChannelCommand ChannelCommand (String, String)
cmdRemove Bool -> ChannelCommand String
simpleChannelTab

  ]

cmdRemove :: ChannelCommand (String, String)
cmdRemove :: ChannelCommand (String, String)
cmdRemove Identifier
channelId NetworkState
cs ClientState
st (String
who,String
reason) =
  do let msg :: Text
msg = String -> Text
Text.pack String
reason
         cmd :: RawIrcMsg
cmd = Identifier -> Text -> Text -> RawIrcMsg
ircRemove Identifier
channelId (String -> Text
Text.pack String
who) Text
msg
     NetworkState
cs' <- Identifier -> [RawIrcMsg] -> NetworkState -> IO NetworkState
sendModeration Identifier
channelId [RawIrcMsg
cmd] NetworkState
cs
     NetworkState -> ClientState -> IO CommandResult
commandSuccessUpdateCS NetworkState
cs' ClientState
st

cmdKick :: ChannelCommand (String, String)
cmdKick :: ChannelCommand (String, String)
cmdKick Identifier
channelId NetworkState
cs ClientState
st (String
who,String
reason) =
  do let msg :: Text
msg = String -> Text
Text.pack String
reason
         cmd :: RawIrcMsg
cmd = Identifier -> Text -> Text -> RawIrcMsg
ircKick Identifier
channelId (String -> Text
Text.pack String
who) Text
msg
     NetworkState
cs' <- Identifier -> [RawIrcMsg] -> NetworkState -> IO NetworkState
sendModeration Identifier
channelId [RawIrcMsg
cmd] NetworkState
cs
     NetworkState -> ClientState -> IO CommandResult
commandSuccessUpdateCS NetworkState
cs' ClientState
st


cmdKickBan :: ChannelCommand (String, String)
cmdKickBan :: ChannelCommand (String, String)
cmdKickBan Identifier
channelId NetworkState
cs ClientState
st (String
who,String
reason) =
  do let msg :: Text
msg = String -> Text
Text.pack String
reason

         whoTxt :: Text
whoTxt     = String -> Text
Text.pack String
who

         mask :: Text
mask = UserInfo -> Text
renderUserInfo (Identifier -> NetworkState -> UserInfo
computeBanUserInfo (Text -> Identifier
mkId Text
whoTxt) NetworkState
cs)
         cmds :: [RawIrcMsg]
cmds = [ Identifier -> [Text] -> RawIrcMsg
ircMode Identifier
channelId [Text
"b", Text
mask]
                , Identifier -> Text -> Text -> RawIrcMsg
ircKick Identifier
channelId Text
whoTxt Text
msg
                ]
     NetworkState
cs' <- Identifier -> [RawIrcMsg] -> NetworkState -> IO NetworkState
sendModeration Identifier
channelId [RawIrcMsg]
cmds NetworkState
cs
     NetworkState -> ClientState -> IO CommandResult
commandSuccessUpdateCS NetworkState
cs' ClientState
st

cmdInvite :: ChannelCommand String
cmdInvite :: ChannelCommand String
cmdInvite Identifier
channelId NetworkState
cs ClientState
st String
nick =
  do let freeTarget :: Bool
freeTarget = Getting Any NetworkState Text -> NetworkState -> Bool
forall s a. Getting Any s a -> s -> Bool
has ((HashMap Identifier ChannelState
 -> Const Any (HashMap Identifier ChannelState))
-> NetworkState -> Const Any NetworkState
Lens' NetworkState (HashMap Identifier ChannelState)
csChannels ((HashMap Identifier ChannelState
  -> Const Any (HashMap Identifier ChannelState))
 -> NetworkState -> Const Any NetworkState)
-> ((Text -> Const Any Text)
    -> HashMap Identifier ChannelState
    -> Const Any (HashMap Identifier ChannelState))
-> Getting Any NetworkState Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (HashMap Identifier ChannelState)
-> Traversal'
     (HashMap Identifier ChannelState)
     (IxValue (HashMap Identifier ChannelState))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Identifier
Index (HashMap Identifier ChannelState)
channelId ((ChannelState -> Const Any ChannelState)
 -> HashMap Identifier ChannelState
 -> Const Any (HashMap Identifier ChannelState))
-> ((Text -> Const Any Text)
    -> ChannelState -> Const Any ChannelState)
-> (Text -> Const Any Text)
-> HashMap Identifier ChannelState
-> Const Any (HashMap Identifier ChannelState)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Map Char Text -> Const Any (Map Char Text))
-> ChannelState -> Const Any ChannelState
Lens' ChannelState (Map Char Text)
chanModes ((Map Char Text -> Const Any (Map Char Text))
 -> ChannelState -> Const Any ChannelState)
-> ((Text -> Const Any Text)
    -> Map Char Text -> Const Any (Map Char Text))
-> (Text -> Const Any Text)
-> ChannelState
-> Const Any ChannelState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (Map Char Text)
-> Traversal' (Map Char Text) (IxValue (Map Char Text))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Char
Index (Map Char Text)
'g') NetworkState
cs
         cmd :: RawIrcMsg
cmd = Text -> Identifier -> RawIrcMsg
ircInvite (String -> Text
Text.pack String
nick) Identifier
channelId
     NetworkState
cs' <- if Bool
freeTarget
              then NetworkState
cs NetworkState -> IO () -> IO NetworkState
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ NetworkState -> RawIrcMsg -> IO ()
sendMsg NetworkState
cs RawIrcMsg
cmd
              else Identifier -> [RawIrcMsg] -> NetworkState -> IO NetworkState
sendModeration Identifier
channelId [RawIrcMsg
cmd] NetworkState
cs
     NetworkState -> ClientState -> IO CommandResult
commandSuccessUpdateCS NetworkState
cs' ClientState
st

commandSuccessUpdateCS :: NetworkState -> ClientState -> IO CommandResult
commandSuccessUpdateCS :: NetworkState -> ClientState -> IO CommandResult
commandSuccessUpdateCS NetworkState
cs ClientState
st =
  do let network :: Text
network = Getting Text NetworkState Text -> NetworkState -> Text
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Text NetworkState Text
Lens' NetworkState Text
csNetwork NetworkState
cs
     ClientState -> IO CommandResult
forall (m :: * -> *). Monad m => ClientState -> m CommandResult
commandSuccess
       (ClientState -> IO CommandResult)
-> ClientState -> IO CommandResult
forall a b. (a -> b) -> a -> b
$ ASetter ClientState ClientState NetworkState NetworkState
-> NetworkState -> ClientState -> ClientState
forall s t a b. ASetter s t a b -> b -> s -> t
setStrict (Text -> ASetter ClientState ClientState NetworkState NetworkState
forall (f :: * -> *).
Applicative f =>
Text -> LensLike' f ClientState NetworkState
clientConnection Text
network) NetworkState
cs ClientState
st

cmdMasks :: ChannelCommand String
cmdMasks :: ChannelCommand String
cmdMasks Identifier
channel NetworkState
cs ClientState
st String
rest =
  case String
rest of
    [Char
mode] | Char
mode Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` Getting String NetworkState String -> NetworkState -> String
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view ((ModeTypes -> Const String ModeTypes)
-> NetworkState -> Const String NetworkState
Lens' NetworkState ModeTypes
csModeTypes ((ModeTypes -> Const String ModeTypes)
 -> NetworkState -> Const String NetworkState)
-> ((String -> Const String String)
    -> ModeTypes -> Const String ModeTypes)
-> Getting String NetworkState String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Const String String)
-> ModeTypes -> Const String ModeTypes
forall (f :: * -> *).
Functor f =>
(String -> f String) -> ModeTypes -> f ModeTypes
modesLists) NetworkState
cs ->

        do let connecting :: Bool
connecting = Getting Any NetworkState (Int, Maybe UTCTime, ConnectRestriction)
-> NetworkState -> Bool
forall s a. Getting Any s a -> s -> Bool
has ((PingStatus -> Const Any PingStatus)
-> NetworkState -> Const Any NetworkState
Lens' NetworkState PingStatus
csPingStatus ((PingStatus -> Const Any PingStatus)
 -> NetworkState -> Const Any NetworkState)
-> (((Int, Maybe UTCTime, ConnectRestriction)
     -> Const Any (Int, Maybe UTCTime, ConnectRestriction))
    -> PingStatus -> Const Any PingStatus)
-> Getting
     Any NetworkState (Int, Maybe UTCTime, ConnectRestriction)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Int, Maybe UTCTime, ConnectRestriction)
 -> Const Any (Int, Maybe UTCTime, ConnectRestriction))
-> PingStatus -> Const Any PingStatus
Prism' PingStatus (Int, Maybe UTCTime, ConnectRestriction)
_PingConnecting) NetworkState
cs
               listLoaded :: Bool
listLoaded = Getting Any NetworkState (HashMap Text MaskListEntry)
-> NetworkState -> Bool
forall s a. Getting Any s a -> s -> Bool
has ((HashMap Identifier ChannelState
 -> Const Any (HashMap Identifier ChannelState))
-> NetworkState -> Const Any NetworkState
Lens' NetworkState (HashMap Identifier ChannelState)
csChannels ((HashMap Identifier ChannelState
  -> Const Any (HashMap Identifier ChannelState))
 -> NetworkState -> Const Any NetworkState)
-> ((HashMap Text MaskListEntry
     -> Const Any (HashMap Text MaskListEntry))
    -> HashMap Identifier ChannelState
    -> Const Any (HashMap Identifier ChannelState))
-> Getting Any NetworkState (HashMap Text MaskListEntry)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (HashMap Identifier ChannelState)
-> Traversal'
     (HashMap Identifier ChannelState)
     (IxValue (HashMap Identifier ChannelState))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Identifier
Index (HashMap Identifier ChannelState)
channel ((ChannelState -> Const Any ChannelState)
 -> HashMap Identifier ChannelState
 -> Const Any (HashMap Identifier ChannelState))
-> ((HashMap Text MaskListEntry
     -> Const Any (HashMap Text MaskListEntry))
    -> ChannelState -> Const Any ChannelState)
-> (HashMap Text MaskListEntry
    -> Const Any (HashMap Text MaskListEntry))
-> HashMap Identifier ChannelState
-> Const Any (HashMap Identifier ChannelState)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Map Char (HashMap Text MaskListEntry)
 -> Const Any (Map Char (HashMap Text MaskListEntry)))
-> ChannelState -> Const Any ChannelState
Lens' ChannelState (Map Char (HashMap Text MaskListEntry))
chanLists ((Map Char (HashMap Text MaskListEntry)
  -> Const Any (Map Char (HashMap Text MaskListEntry)))
 -> ChannelState -> Const Any ChannelState)
-> ((HashMap Text MaskListEntry
     -> Const Any (HashMap Text MaskListEntry))
    -> Map Char (HashMap Text MaskListEntry)
    -> Const Any (Map Char (HashMap Text MaskListEntry)))
-> (HashMap Text MaskListEntry
    -> Const Any (HashMap Text MaskListEntry))
-> ChannelState
-> Const Any ChannelState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (Map Char (HashMap Text MaskListEntry))
-> Traversal'
     (Map Char (HashMap Text MaskListEntry))
     (IxValue (Map Char (HashMap Text MaskListEntry)))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Char
Index (Map Char (HashMap Text MaskListEntry))
mode) NetworkState
cs
           Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Bool
connecting Bool -> Bool -> Bool
|| Bool
listLoaded)
             (NetworkState -> RawIrcMsg -> IO ()
sendMsg NetworkState
cs (Identifier -> [Text] -> RawIrcMsg
ircMode Identifier
channel [Char -> Text
Text.singleton Char
mode]))

           ClientState -> IO CommandResult
forall (m :: * -> *). Monad m => ClientState -> m CommandResult
commandSuccess (Subfocus -> ClientState -> ClientState
changeSubfocus (Char -> Subfocus
FocusMasks Char
mode) ClientState
st)

    String
_ -> Text -> ClientState -> IO CommandResult
commandFailureMsg Text
"unknown mask mode" ClientState
st

computeBanUserInfo :: Identifier -> NetworkState    -> UserInfo
computeBanUserInfo :: Identifier -> NetworkState -> UserInfo
computeBanUserInfo Identifier
who NetworkState
cs =
  case Getting (Maybe UserAndHost) NetworkState (Maybe UserAndHost)
-> NetworkState -> Maybe UserAndHost
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (Identifier
-> Getting (Maybe UserAndHost) NetworkState (Maybe UserAndHost)
forall (f :: * -> *).
Functor f =>
Identifier -> LensLike' f NetworkState (Maybe UserAndHost)
csUser Identifier
who) NetworkState
cs of
    Maybe UserAndHost
Nothing                     -> Identifier -> Text -> Text -> UserInfo
UserInfo Identifier
who Text
"*" Text
"*"
    Just (UserAndHost Text
_ Text
host Text
_) -> Identifier -> Text -> Text -> UserInfo
UserInfo Identifier
"*" Text
"*" Text
host

cmdTopic :: ChannelCommand String
cmdTopic :: ChannelCommand String
cmdTopic Identifier
channelId NetworkState
cs ClientState
st String
rest =
  do Identifier -> Text -> NetworkState -> IO ()
sendTopic Identifier
channelId (String -> Text
Text.pack String
rest) NetworkState
cs
     ClientState -> IO CommandResult
forall (m :: * -> *). Monad m => ClientState -> m CommandResult
commandSuccess ClientState
st

tabTopic ::
  Bool {- ^ reversed -} ->
  ChannelCommand String
tabTopic :: Bool -> ChannelCommand String
tabTopic Bool
_ Identifier
channelId NetworkState
cs ClientState
st String
rest

  | (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
==Char
' ') String
rest
  , Just Text
topic <- Getting (First Text) NetworkState Text
-> NetworkState -> Maybe Text
forall s (m :: * -> *) a.
MonadReader s m =>
Getting (First a) s a -> m (Maybe a)
preview ((HashMap Identifier ChannelState
 -> Const (First Text) (HashMap Identifier ChannelState))
-> NetworkState -> Const (First Text) NetworkState
Lens' NetworkState (HashMap Identifier ChannelState)
csChannels ((HashMap Identifier ChannelState
  -> Const (First Text) (HashMap Identifier ChannelState))
 -> NetworkState -> Const (First Text) NetworkState)
-> ((Text -> Const (First Text) Text)
    -> HashMap Identifier ChannelState
    -> Const (First Text) (HashMap Identifier ChannelState))
-> Getting (First Text) NetworkState Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (HashMap Identifier ChannelState)
-> Traversal'
     (HashMap Identifier ChannelState)
     (IxValue (HashMap Identifier ChannelState))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Identifier
Index (HashMap Identifier ChannelState)
channelId ((ChannelState -> Const (First Text) ChannelState)
 -> HashMap Identifier ChannelState
 -> Const (First Text) (HashMap Identifier ChannelState))
-> ((Text -> Const (First Text) Text)
    -> ChannelState -> Const (First Text) ChannelState)
-> (Text -> Const (First Text) Text)
-> HashMap Identifier ChannelState
-> Const (First Text) (HashMap Identifier ChannelState)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Const (First Text) Text)
-> ChannelState -> Const (First Text) ChannelState
Lens' ChannelState Text
chanTopic) NetworkState
cs =
     do let textBox :: EditBox -> EditBox
textBox = ASetter EditBox EditBox Line Line -> Line -> EditBox -> EditBox
forall s t a b. ASetter s t a b -> b -> s -> t
set ASetter EditBox EditBox Line Line
forall c. HasLine c => Lens' c Line
Edit.line (String -> Line
Edit.endLine (String -> Line) -> String -> Line
forall a b. (a -> b) -> a -> b
$ String
"/topic " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Text -> String
Text.unpack Text
topic)
        ClientState -> IO CommandResult
forall (m :: * -> *). Monad m => ClientState -> m CommandResult
commandSuccess (ASetter ClientState ClientState EditBox EditBox
-> (EditBox -> EditBox) -> ClientState -> ClientState
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over ASetter ClientState ClientState EditBox EditBox
Lens' ClientState EditBox
clientTextBox EditBox -> EditBox
textBox ClientState
st)

  | Bool
otherwise = ClientState -> IO CommandResult
forall (m :: * -> *). Monad m => ClientState -> m CommandResult
commandFailure ClientState
st

cmdMode :: NetworkCommand [String]
cmdMode :: NetworkCommand [String]
cmdMode NetworkState
cs ClientState
st [String]
xs = [Text] -> NetworkState -> ClientState -> IO CommandResult
modeCommand (String -> Text
Text.pack (String -> Text) -> [String] -> [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [String]
xs) NetworkState
cs ClientState
st

modeCommand ::
  [Text] {- mode parameters -} ->
  NetworkState                 ->
  ClientState                  ->
  IO CommandResult
modeCommand :: [Text] -> NetworkState -> ClientState -> IO CommandResult
modeCommand [Text]
modes NetworkState
cs ClientState
st =
  case Getting Focus ClientState Focus -> ClientState -> Focus
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Focus ClientState Focus
Lens' ClientState Focus
clientFocus ClientState
st of

    NetworkFocus Text
_ ->
      do NetworkState -> RawIrcMsg -> IO ()
sendMsg NetworkState
cs (Identifier -> [Text] -> RawIrcMsg
ircMode (Getting Identifier NetworkState Identifier
-> NetworkState -> Identifier
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Identifier NetworkState Identifier
Lens' NetworkState Identifier
csNick NetworkState
cs) [Text]
modes)
         ClientState -> IO CommandResult
forall (m :: * -> *). Monad m => ClientState -> m CommandResult
commandSuccess ClientState
st

    ChannelFocus Text
_ Identifier
chan ->
      case [Text]
modes of
        [] -> Bool -> [[Text]] -> IO CommandResult
success Bool
False [[]]
        Text
flags:[Text]
params ->
          case ModeTypes -> Text -> [Text] -> Maybe [(Bool, Char, Text)]
splitModes (Getting ModeTypes NetworkState ModeTypes
-> NetworkState -> ModeTypes
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting ModeTypes NetworkState ModeTypes
Lens' NetworkState ModeTypes
csModeTypes NetworkState
cs) Text
flags [Text]
params of
            Maybe [(Bool, Char, Text)]
Nothing -> Text -> ClientState -> IO CommandResult
commandFailureMsg Text
"failed to parse modes" ClientState
st
            Just [(Bool, Char, Text)]
parsedModes ->
              Bool -> [[Text]] -> IO CommandResult
success Bool
needOp ([(Bool, Char, Text)] -> [Text]
unsplitModes ([(Bool, Char, Text)] -> [Text])
-> [[(Bool, Char, Text)]] -> [[Text]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> [(Bool, Char, Text)] -> [[(Bool, Char, Text)]]
forall e. Int -> [e] -> [[e]]
chunksOf (Getting Int NetworkState Int -> NetworkState -> Int
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Int NetworkState Int
Lens' NetworkState Int
csModeCount NetworkState
cs) [(Bool, Char, Text)]
parsedModes')
              where
                parsedModes' :: [(Bool, Char, Text)]
parsedModes'
                  | Identifier -> NetworkState -> Bool
useChanServ Identifier
chan NetworkState
cs = ((Bool, Char, Text) -> Bool)
-> [(Bool, Char, Text)] -> [(Bool, Char, Text)]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool)
-> ((Bool, Char, Text) -> Bool) -> (Bool, Char, Text) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool, Char, Text) -> Bool
isOpMe) [(Bool, Char, Text)]
parsedModes
                  | Bool
otherwise           = [(Bool, Char, Text)]
parsedModes

                needOp :: Bool
needOp = Bool -> Bool
not (((Bool, Char, Text) -> Bool) -> [(Bool, Char, Text)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Bool, Char, Text) -> Bool
isPublicChannelMode [(Bool, Char, Text)]
parsedModes)
      where
        isOpMe :: (Bool, Char, Text) -> Bool
isOpMe (Bool
True, Char
'o', Text
param) = Text -> Identifier
mkId Text
param Identifier -> Identifier -> Bool
forall a. Eq a => a -> a -> Bool
== Getting Identifier NetworkState Identifier
-> NetworkState -> Identifier
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Identifier NetworkState Identifier
Lens' NetworkState Identifier
csNick NetworkState
cs
        isOpMe (Bool, Char, Text)
_                  = Bool
False

        success :: Bool -> [[Text]] -> IO CommandResult
success Bool
needOp [[Text]]
argss =
          do let cmds :: [RawIrcMsg]
cmds = Identifier -> [Text] -> RawIrcMsg
ircMode Identifier
chan ([Text] -> RawIrcMsg) -> [[Text]] -> [RawIrcMsg]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [[Text]]
argss
             NetworkState
cs' <- if Bool
needOp
                      then Identifier -> [RawIrcMsg] -> NetworkState -> IO NetworkState
sendModeration Identifier
chan [RawIrcMsg]
cmds NetworkState
cs
                      else NetworkState
cs NetworkState -> IO () -> IO NetworkState
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ (RawIrcMsg -> IO ()) -> [RawIrcMsg] -> IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ (NetworkState -> RawIrcMsg -> IO ()
sendMsg NetworkState
cs) [RawIrcMsg]
cmds
             NetworkState -> ClientState -> IO CommandResult
commandSuccessUpdateCS NetworkState
cs' ClientState
st

    Focus
_ -> ClientState -> IO CommandResult
forall (m :: * -> *). Monad m => ClientState -> m CommandResult
commandFailure ClientState
st

tabMode :: Bool -> NetworkCommand String
tabMode :: Bool -> NetworkCommand String
tabMode Bool
isReversed NetworkState
cs ClientState
st String
rest =
  case Getting Focus ClientState Focus -> ClientState -> Focus
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Focus ClientState Focus
Lens' ClientState Focus
clientFocus ClientState
st of

    ChannelFocus Text
_ Identifier
channel
      | Text
flags:[Text]
params     <- Text -> [Text]
Text.words (String -> Text
Text.pack String
rest)
      , Just [(Bool, Char, Text)]
parsedModes <- ModeTypes -> Text -> [Text] -> Maybe [(Bool, Char, Text)]
splitModes (Getting ModeTypes NetworkState ModeTypes
-> NetworkState -> ModeTypes
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting ModeTypes NetworkState ModeTypes
Lens' NetworkState ModeTypes
csModeTypes NetworkState
cs) Text
flags [Text]
params
      , let parsedModesWithParams :: [(Bool, Char)]
parsedModesWithParams =
              [ (Bool
pol,Char
mode) | (Bool
pol,Char
mode,Text
arg) <- [(Bool, Char, Text)]
parsedModes, Bool -> Bool
not (Text -> Bool
Text.null Text
arg) ]
      , (Bool
pol,Char
mode):[(Bool, Char)]
_      <- Int -> [(Bool, Char)] -> [(Bool, Char)]
forall a. Int -> [a] -> [a]
drop (Int
paramIndexInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
3) [(Bool, Char)]
parsedModesWithParams
      , let ([Identifier]
hint, [Identifier]
completions) = Bool
-> Char
-> Identifier
-> NetworkState
-> ClientState
-> ([Identifier], [Identifier])
computeModeCompletion Bool
pol Char
mode Identifier
channel NetworkState
cs ClientState
st
      -> WordCompletionMode
-> [Identifier]
-> [Identifier]
-> Bool
-> ClientState
-> IO CommandResult
forall a.
Prefix a =>
WordCompletionMode
-> [a] -> [a] -> Bool -> ClientState -> IO CommandResult
simpleTabCompletion WordCompletionMode
plainWordCompleteMode [Identifier]
hint [Identifier]
completions Bool
isReversed ClientState
st

    Focus
_ -> ClientState -> IO CommandResult
forall (m :: * -> *). Monad m => ClientState -> m CommandResult
commandFailure ClientState
st

  where
    paramIndex :: Int
paramIndex = [String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([String] -> Int) -> [String] -> Int
forall a b. (a -> b) -> a -> b
$ String -> [String]
words (String -> [String]) -> String -> [String]
forall a b. (a -> b) -> a -> b
$ (Int -> String -> String) -> (Int, String) -> String
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Int -> String -> String
forall a. Int -> [a] -> [a]
take ((Int, String) -> String) -> (Int, String) -> String
forall a b. (a -> b) -> a -> b
$ ClientState -> (Int, String)
clientLine ClientState
st

modeParamArgs :: ClientState -> String -> Maybe (Args ClientState [String])
modeParamArgs :: ClientState -> String -> Maybe (Args ClientState [String])
modeParamArgs ClientState
st String
str =
  case Getting Focus ClientState Focus -> ClientState -> Focus
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Focus ClientState Focus
Lens' ClientState Focus
clientFocus ClientState
st of
    Focus
Unfocused      -> Maybe (Args ClientState [String])
forall a. Maybe a
Nothing
    NetworkFocus Text
_ -> Args ClientState [String] -> Maybe (Args ClientState [String])
forall a. a -> Maybe a
Just ([String] -> Args ClientState [String]
forall (f :: * -> *) a. Applicative f => a -> f a
pure [String
str])
    ChannelFocus Text
net Identifier
_ ->

         -- determine current mode types
      do NetworkState
cs <- Getting (First NetworkState) ClientState NetworkState
-> ClientState -> Maybe NetworkState
forall s (m :: * -> *) a.
MonadReader s m =>
Getting (First a) s a -> m (Maybe a)
preview (Text -> Getting (First NetworkState) ClientState NetworkState
forall (f :: * -> *).
Applicative f =>
Text -> LensLike' f ClientState NetworkState
clientConnection Text
net) ClientState
st
         let types :: ModeTypes
types = Getting ModeTypes NetworkState ModeTypes
-> NetworkState -> ModeTypes
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting ModeTypes NetworkState ModeTypes
Lens' NetworkState ModeTypes
csModeTypes NetworkState
cs

         -- parse the list of modes being set
         [(Bool, Char, Text)]
flags <- ModeTypes -> Text -> [Text] -> Maybe [(Bool, Char, Text)]
splitModes ModeTypes
types (String -> Text
Text.pack String
str) []

         -- generate the argument specification
         let ([String]
req,[String]
opt) = ((Bool, Char, Text)
 -> ([String], [String]) -> ([String], [String]))
-> ([String], [String])
-> [(Bool, Char, Text)]
-> ([String], [String])
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (ModeTypes
-> (Bool, Char, Text)
-> ([String], [String])
-> ([String], [String])
countFlags ModeTypes
types) ([],[]) [(Bool, Char, Text)]
flags
         Args ClientState [String] -> Maybe (Args ClientState [String])
forall (m :: * -> *) a. Monad m => a -> m a
return ((String
strString -> [String] -> [String]
forall a. a -> [a] -> [a]
:) ([String] -> [String])
-> Args ClientState [String] -> Args ClientState [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [String] -> [String] -> Args ClientState [String]
forall r. [String] -> [String] -> Args r [String]
tokenList [String]
req ((String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String -> String -> String
forall a. [a] -> [a] -> [a]
++String
"?") [String]
opt))

-- | This function computes the list of required and optional parameters
-- corresponding to the flags that have been entered.
countFlags ::
  ModeTypes           {- ^ network's mode behaviors              -} ->
  (Bool, Char, Text)  {- ^ polarity mode-letter unused-parameter -} ->
  ([String],[String]) {- ^ required-names optional-names         -} ->
  ([String],[String]) {- ^ required-names optional-names         -}
countFlags :: ModeTypes
-> (Bool, Char, Text)
-> ([String], [String])
-> ([String], [String])
countFlags ModeTypes
types (Bool
pol, Char
flag, Text
_)
  |        Char
flag Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` ((String -> Const String String)
 -> ModeTypes -> Const String ModeTypes)
-> ModeTypes -> String
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (String -> Const String String)
-> ModeTypes -> Const String ModeTypes
forall (f :: * -> *).
Functor f =>
(String -> f String) -> ModeTypes -> f ModeTypes
modesLists       ModeTypes
types = ([String], [String]) -> ([String], [String])
addOpt
  | Bool
pol Bool -> Bool -> Bool
&& Char
flag Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` ((String -> Const String String)
 -> ModeTypes -> Const String ModeTypes)
-> ModeTypes -> String
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (String -> Const String String)
-> ModeTypes -> Const String ModeTypes
forall (f :: * -> *).
Functor f =>
(String -> f String) -> ModeTypes -> f ModeTypes
modesSetArg      ModeTypes
types = ([String], [String]) -> ([String], [String])
forall b. ([String], b) -> ([String], b)
addReq
  |        Char
flag Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` ((String -> Const String String)
 -> ModeTypes -> Const String ModeTypes)
-> ModeTypes -> String
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (String -> Const String String)
-> ModeTypes -> Const String ModeTypes
forall (f :: * -> *).
Functor f =>
(String -> f String) -> ModeTypes -> f ModeTypes
modesAlwaysArg   ModeTypes
types = ([String], [String]) -> ([String], [String])
forall b. ([String], b) -> ([String], b)
addReq
  | Getting Any ModeTypes Char -> Char -> ModeTypes -> Bool
forall a s. Eq a => Getting Any s a -> a -> s -> Bool
elemOf (([(Char, Char)] -> Const Any [(Char, Char)])
-> ModeTypes -> Const Any ModeTypes
forall (f :: * -> *).
Functor f =>
([(Char, Char)] -> f [(Char, Char)]) -> ModeTypes -> f ModeTypes
modesPrefixModes (([(Char, Char)] -> Const Any [(Char, Char)])
 -> ModeTypes -> Const Any ModeTypes)
-> ((Char -> Const Any Char)
    -> [(Char, Char)] -> Const Any [(Char, Char)])
-> Getting Any ModeTypes Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Char, Char) -> Const Any (Char, Char))
-> [(Char, Char)] -> Const Any [(Char, Char)]
forall (f :: * -> *) a. Foldable f => IndexedFold Int (f a) a
folded (((Char, Char) -> Const Any (Char, Char))
 -> [(Char, Char)] -> Const Any [(Char, Char)])
-> ((Char -> Const Any Char)
    -> (Char, Char) -> Const Any (Char, Char))
-> (Char -> Const Any Char)
-> [(Char, Char)]
-> Const Any [(Char, Char)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Const Any Char) -> (Char, Char) -> Const Any (Char, Char)
forall s t a b. Field1 s t a b => Lens s t a b
_1) Char
flag ModeTypes
types = ([String], [String]) -> ([String], [String])
forall b. ([String], b) -> ([String], b)
addReq
  | Bool
otherwise                                      = ([String], [String]) -> ([String], [String])
forall a. a -> a
id
  where
    addReq :: ([String], b) -> ([String], b)
addReq ([String]
req,b
opt) = ((Char
flagChar -> String -> String
forall a. a -> [a] -> [a]
:String
" param")String -> [String] -> [String]
forall a. a -> [a] -> [a]
:[String]
req,b
opt)
    addOpt :: ([String], [String]) -> ([String], [String])
addOpt ([] ,[String]
opt) = ([], (Char
flagChar -> String -> String
forall a. a -> [a] -> [a]
:String
" param")String -> [String] -> [String]
forall a. a -> [a] -> [a]
:[String]
opt)
    addOpt ([String]
req,[String]
opt) = ((Char
flagChar -> String -> String
forall a. a -> [a] -> [a]
:String
" param")String -> [String] -> [String]
forall a. a -> [a] -> [a]
:[String]
req,[String]
opt)


-- | Use the *!*@host masks of users for channel lists when setting list modes
--
-- Use the channel's mask list for removing modes
--
-- Use the nick list otherwise
computeModeCompletion ::
  Bool {- ^ mode polarity -} ->
  Char {- ^ mode          -} ->
  Identifier {- ^ channel -} ->
  NetworkState    ->
  ClientState ->
  ([Identifier],[Identifier]) {- ^ (hint, complete) -}
computeModeCompletion :: Bool
-> Char
-> Identifier
-> NetworkState
-> ClientState
-> ([Identifier], [Identifier])
computeModeCompletion Bool
pol Char
mode Identifier
channel NetworkState
cs ClientState
st
  | Char
mode Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` ((String -> Const String String)
 -> ModeTypes -> Const String ModeTypes)
-> ModeTypes -> String
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (String -> Const String String)
-> ModeTypes -> Const String ModeTypes
forall (f :: * -> *).
Functor f =>
(String -> f String) -> ModeTypes -> f ModeTypes
modesLists ModeTypes
modeSettings =
        if Bool
pol then ([],[Identifier]
usermasks [Identifier] -> [Identifier] -> [Identifier]
forall a. Semigroup a => a -> a -> a
<> [Identifier]
accounts) else ([],[Identifier]
masks)
  | Bool
otherwise = (ClientState -> [Identifier]
activeNicks ClientState
st, [Identifier]
nicks)
  where
    modeSettings :: ModeTypes
modeSettings = Getting ModeTypes NetworkState ModeTypes
-> NetworkState -> ModeTypes
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting ModeTypes NetworkState ModeTypes
Lens' NetworkState ModeTypes
csModeTypes NetworkState
cs
    nicks :: [Identifier]
nicks = HashMap Identifier String -> [Identifier]
forall k v. HashMap k v -> [k]
HashMap.keys (Getting
  (HashMap Identifier String)
  NetworkState
  (HashMap Identifier String)
-> NetworkState -> HashMap Identifier String
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view ((HashMap Identifier ChannelState
 -> Const
      (HashMap Identifier String) (HashMap Identifier ChannelState))
-> NetworkState -> Const (HashMap Identifier String) NetworkState
Lens' NetworkState (HashMap Identifier ChannelState)
csChannels ((HashMap Identifier ChannelState
  -> Const
       (HashMap Identifier String) (HashMap Identifier ChannelState))
 -> NetworkState -> Const (HashMap Identifier String) NetworkState)
-> ((HashMap Identifier String
     -> Const (HashMap Identifier String) (HashMap Identifier String))
    -> HashMap Identifier ChannelState
    -> Const
         (HashMap Identifier String) (HashMap Identifier ChannelState))
-> Getting
     (HashMap Identifier String)
     NetworkState
     (HashMap Identifier String)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (HashMap Identifier ChannelState)
-> Traversal'
     (HashMap Identifier ChannelState)
     (IxValue (HashMap Identifier ChannelState))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Identifier
Index (HashMap Identifier ChannelState)
channel ((ChannelState -> Const (HashMap Identifier String) ChannelState)
 -> HashMap Identifier ChannelState
 -> Const
      (HashMap Identifier String) (HashMap Identifier ChannelState))
-> ((HashMap Identifier String
     -> Const (HashMap Identifier String) (HashMap Identifier String))
    -> ChannelState -> Const (HashMap Identifier String) ChannelState)
-> (HashMap Identifier String
    -> Const (HashMap Identifier String) (HashMap Identifier String))
-> HashMap Identifier ChannelState
-> Const
     (HashMap Identifier String) (HashMap Identifier ChannelState)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (HashMap Identifier String
 -> Const (HashMap Identifier String) (HashMap Identifier String))
-> ChannelState -> Const (HashMap Identifier String) ChannelState
Lens' ChannelState (HashMap Identifier String)
chanUsers) NetworkState
cs)

    masks :: [Identifier]
masks = Text -> Identifier
mkId (Text -> Identifier) -> [Text] -> [Identifier]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> HashMap Text MaskListEntry -> [Text]
forall k v. HashMap k v -> [k]
HashMap.keys (Getting
  (HashMap Text MaskListEntry)
  NetworkState
  (HashMap Text MaskListEntry)
-> NetworkState -> HashMap Text MaskListEntry
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view ((HashMap Identifier ChannelState
 -> Const
      (HashMap Text MaskListEntry) (HashMap Identifier ChannelState))
-> NetworkState -> Const (HashMap Text MaskListEntry) NetworkState
Lens' NetworkState (HashMap Identifier ChannelState)
csChannels ((HashMap Identifier ChannelState
  -> Const
       (HashMap Text MaskListEntry) (HashMap Identifier ChannelState))
 -> NetworkState -> Const (HashMap Text MaskListEntry) NetworkState)
-> ((HashMap Text MaskListEntry
     -> Const (HashMap Text MaskListEntry) (HashMap Text MaskListEntry))
    -> HashMap Identifier ChannelState
    -> Const
         (HashMap Text MaskListEntry) (HashMap Identifier ChannelState))
-> Getting
     (HashMap Text MaskListEntry)
     NetworkState
     (HashMap Text MaskListEntry)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (HashMap Identifier ChannelState)
-> Traversal'
     (HashMap Identifier ChannelState)
     (IxValue (HashMap Identifier ChannelState))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Identifier
Index (HashMap Identifier ChannelState)
channel ((ChannelState -> Const (HashMap Text MaskListEntry) ChannelState)
 -> HashMap Identifier ChannelState
 -> Const
      (HashMap Text MaskListEntry) (HashMap Identifier ChannelState))
-> ((HashMap Text MaskListEntry
     -> Const (HashMap Text MaskListEntry) (HashMap Text MaskListEntry))
    -> ChannelState -> Const (HashMap Text MaskListEntry) ChannelState)
-> (HashMap Text MaskListEntry
    -> Const (HashMap Text MaskListEntry) (HashMap Text MaskListEntry))
-> HashMap Identifier ChannelState
-> Const
     (HashMap Text MaskListEntry) (HashMap Identifier ChannelState)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Map Char (HashMap Text MaskListEntry)
 -> Const
      (HashMap Text MaskListEntry)
      (Map Char (HashMap Text MaskListEntry)))
-> ChannelState -> Const (HashMap Text MaskListEntry) ChannelState
Lens' ChannelState (Map Char (HashMap Text MaskListEntry))
chanLists ((Map Char (HashMap Text MaskListEntry)
  -> Const
       (HashMap Text MaskListEntry)
       (Map Char (HashMap Text MaskListEntry)))
 -> ChannelState -> Const (HashMap Text MaskListEntry) ChannelState)
-> ((HashMap Text MaskListEntry
     -> Const (HashMap Text MaskListEntry) (HashMap Text MaskListEntry))
    -> Map Char (HashMap Text MaskListEntry)
    -> Const
         (HashMap Text MaskListEntry)
         (Map Char (HashMap Text MaskListEntry)))
-> (HashMap Text MaskListEntry
    -> Const (HashMap Text MaskListEntry) (HashMap Text MaskListEntry))
-> ChannelState
-> Const (HashMap Text MaskListEntry) ChannelState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (Map Char (HashMap Text MaskListEntry))
-> Traversal'
     (Map Char (HashMap Text MaskListEntry))
     (IxValue (Map Char (HashMap Text MaskListEntry)))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Char
Index (Map Char (HashMap Text MaskListEntry))
mode) NetworkState
cs)

    usermasks :: [Identifier]
usermasks =
      [ Text -> Identifier
mkId (Text
"*!*@" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
host)
        | Identifier
nick <- HashMap Identifier String -> [Identifier]
forall k v. HashMap k v -> [k]
HashMap.keys (Getting
  (HashMap Identifier String)
  NetworkState
  (HashMap Identifier String)
-> NetworkState -> HashMap Identifier String
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view ((HashMap Identifier ChannelState
 -> Const
      (HashMap Identifier String) (HashMap Identifier ChannelState))
-> NetworkState -> Const (HashMap Identifier String) NetworkState
Lens' NetworkState (HashMap Identifier ChannelState)
csChannels ((HashMap Identifier ChannelState
  -> Const
       (HashMap Identifier String) (HashMap Identifier ChannelState))
 -> NetworkState -> Const (HashMap Identifier String) NetworkState)
-> ((HashMap Identifier String
     -> Const (HashMap Identifier String) (HashMap Identifier String))
    -> HashMap Identifier ChannelState
    -> Const
         (HashMap Identifier String) (HashMap Identifier ChannelState))
-> Getting
     (HashMap Identifier String)
     NetworkState
     (HashMap Identifier String)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (HashMap Identifier ChannelState)
-> Traversal'
     (HashMap Identifier ChannelState)
     (IxValue (HashMap Identifier ChannelState))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Identifier
Index (HashMap Identifier ChannelState)
channel ((ChannelState -> Const (HashMap Identifier String) ChannelState)
 -> HashMap Identifier ChannelState
 -> Const
      (HashMap Identifier String) (HashMap Identifier ChannelState))
-> ((HashMap Identifier String
     -> Const (HashMap Identifier String) (HashMap Identifier String))
    -> ChannelState -> Const (HashMap Identifier String) ChannelState)
-> (HashMap Identifier String
    -> Const (HashMap Identifier String) (HashMap Identifier String))
-> HashMap Identifier ChannelState
-> Const
     (HashMap Identifier String) (HashMap Identifier ChannelState)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (HashMap Identifier String
 -> Const (HashMap Identifier String) (HashMap Identifier String))
-> ChannelState -> Const (HashMap Identifier String) ChannelState
Lens' ChannelState (HashMap Identifier String)
chanUsers) NetworkState
cs)
        , UserAndHost Text
_ Text
host Text
_ <- Getting (Endo [UserAndHost]) NetworkState UserAndHost
-> NetworkState -> [UserAndHost]
forall a s. Getting (Endo [a]) s a -> s -> [a]
toListOf ((HashMap Identifier UserAndHost
 -> Const (Endo [UserAndHost]) (HashMap Identifier UserAndHost))
-> NetworkState -> Const (Endo [UserAndHost]) NetworkState
Lens' NetworkState (HashMap Identifier UserAndHost)
csUsers ((HashMap Identifier UserAndHost
  -> Const (Endo [UserAndHost]) (HashMap Identifier UserAndHost))
 -> NetworkState -> Const (Endo [UserAndHost]) NetworkState)
-> ((UserAndHost -> Const (Endo [UserAndHost]) UserAndHost)
    -> HashMap Identifier UserAndHost
    -> Const (Endo [UserAndHost]) (HashMap Identifier UserAndHost))
-> Getting (Endo [UserAndHost]) NetworkState UserAndHost
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (HashMap Identifier UserAndHost)
-> Traversal'
     (HashMap Identifier UserAndHost)
     (IxValue (HashMap Identifier UserAndHost))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Identifier
Index (HashMap Identifier UserAndHost)
nick) NetworkState
cs
        ]
    accounts :: [Identifier]
accounts =
      [ Text -> Identifier
mkId (Text
"$a:" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
account)
        | Identifier
nick <- HashMap Identifier String -> [Identifier]
forall k v. HashMap k v -> [k]
HashMap.keys (Getting
  (HashMap Identifier String)
  NetworkState
  (HashMap Identifier String)
-> NetworkState -> HashMap Identifier String
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view ((HashMap Identifier ChannelState
 -> Const
      (HashMap Identifier String) (HashMap Identifier ChannelState))
-> NetworkState -> Const (HashMap Identifier String) NetworkState
Lens' NetworkState (HashMap Identifier ChannelState)
csChannels ((HashMap Identifier ChannelState
  -> Const
       (HashMap Identifier String) (HashMap Identifier ChannelState))
 -> NetworkState -> Const (HashMap Identifier String) NetworkState)
-> ((HashMap Identifier String
     -> Const (HashMap Identifier String) (HashMap Identifier String))
    -> HashMap Identifier ChannelState
    -> Const
         (HashMap Identifier String) (HashMap Identifier ChannelState))
-> Getting
     (HashMap Identifier String)
     NetworkState
     (HashMap Identifier String)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (HashMap Identifier ChannelState)
-> Traversal'
     (HashMap Identifier ChannelState)
     (IxValue (HashMap Identifier ChannelState))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Identifier
Index (HashMap Identifier ChannelState)
channel ((ChannelState -> Const (HashMap Identifier String) ChannelState)
 -> HashMap Identifier ChannelState
 -> Const
      (HashMap Identifier String) (HashMap Identifier ChannelState))
-> ((HashMap Identifier String
     -> Const (HashMap Identifier String) (HashMap Identifier String))
    -> ChannelState -> Const (HashMap Identifier String) ChannelState)
-> (HashMap Identifier String
    -> Const (HashMap Identifier String) (HashMap Identifier String))
-> HashMap Identifier ChannelState
-> Const
     (HashMap Identifier String) (HashMap Identifier ChannelState)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (HashMap Identifier String
 -> Const (HashMap Identifier String) (HashMap Identifier String))
-> ChannelState -> Const (HashMap Identifier String) ChannelState
Lens' ChannelState (HashMap Identifier String)
chanUsers) NetworkState
cs)
        , UserAndHost Text
_ Text
_ Text
account <- Getting (Endo [UserAndHost]) NetworkState UserAndHost
-> NetworkState -> [UserAndHost]
forall a s. Getting (Endo [a]) s a -> s -> [a]
toListOf ((HashMap Identifier UserAndHost
 -> Const (Endo [UserAndHost]) (HashMap Identifier UserAndHost))
-> NetworkState -> Const (Endo [UserAndHost]) NetworkState
Lens' NetworkState (HashMap Identifier UserAndHost)
csUsers ((HashMap Identifier UserAndHost
  -> Const (Endo [UserAndHost]) (HashMap Identifier UserAndHost))
 -> NetworkState -> Const (Endo [UserAndHost]) NetworkState)
-> ((UserAndHost -> Const (Endo [UserAndHost]) UserAndHost)
    -> HashMap Identifier UserAndHost
    -> Const (Endo [UserAndHost]) (HashMap Identifier UserAndHost))
-> Getting (Endo [UserAndHost]) NetworkState UserAndHost
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (HashMap Identifier UserAndHost)
-> Traversal'
     (HashMap Identifier UserAndHost)
     (IxValue (HashMap Identifier UserAndHost))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Identifier
Index (HashMap Identifier UserAndHost)
nick) NetworkState
cs
        , Bool -> Bool
not (Text -> Bool
Text.null Text
account)
        ]

-- | Predicate for mode commands that can be performed without ops
isPublicChannelMode :: (Bool, Char, Text) -> Bool
isPublicChannelMode :: (Bool, Char, Text) -> Bool
isPublicChannelMode (Bool
True, Char
'b', Text
param) = Text -> Bool
Text.null Text
param -- query ban list
isPublicChannelMode (Bool
True, Char
'q', Text
param) = Text -> Bool
Text.null Text
param -- query quiet list
isPublicChannelMode (Bool, Char, Text)
_                  = Bool
False