{-# LANGUAGE OverloadedStrings #-}

{-|
Module:      SignalDBus
Description: Bindings for the DBus interface of signal-cli
Copyright:   (c) Lia Lenckowski, 2022
License:     AGPL
Maintainer:  lialenck@protonmail.com
Stability:   stable
Portability: GNU/Linux, MacOS

This module is the main entry point for this library.

To get started, install and set up [signal-cli](https://github.com/asamk/signal-cli),
and make sure it's running in daemon mode, with the dbus interface enabled. Then, as
an example, you could use the following code to react with "💀" to every message
received from a specific user either via PM or in groups you're a member of:

> import Control.Monad (forever, when)
> import SignalDBus
>
> reactWithSkull :: Timestamp -> String -> Maybe Group -> SignalConn -> IO Timestamp
> reactWithSkull ts n mayG sc =
>     case mayG of
>         Nothing -> sendMessageReaction "💀" False n ts n sc
>         Just g -> sendGroupMessageReaction "💀" False n ts g sc
>
> -- react with 💀 to every message received by a specific user
> main :: IO ()
> main = do
>     let num = "[insert phone number with country code]"
>     withConn $ \sc -> do
>         n <- getSelfNumber sc
>         putStrLn $ "Running on: " ++ show n
>         withReceiveMessages sc $ \getMsg -> forever $ do
>             getMsg >>= \case
>                 Receipt _ _ -> return ()
>                 SyncMessage _ _ _ _ _ -> return ()
>                 Message ts n g _ _ -> when (n == num) $ do
>                     reactWithSkull ts num g sc
>                     return ()
>
>     return ()

All of the functions exported may fail with a 'DBus.Client.ClientError' if something
goes wrong. None of the functions should throw any other exception.

Quite a few of these functions have a scary-looking \"UNTESTED\" in their documentation.
If you end up using any of those, and they work, please tell me so I can remove that
disclaimer.

This package aims to provide somewhat direct bindings for all methods described by
<https://github.com/AsamK/signal-cli/blob/master/man/signal-cli-dbus.5.adoc>. In cases
where methods are overloaded, this library almost always chooses to implement the more
general ones. Some functionality of the dbus interface of signal-cli isn't implemented,
as it's either not documented or not often useful; if you require any of that, I'd
recommend looking at SignalDBus.Interface.
-}

module SignalDBus (
    -- * Opening connections
    SignalDBus.Interface.withConn,
    SignalDBus.Interface.withConnNum,

    -- * Receiving Messages
    SignalDBus.Interface.withReceiveMessages,

    -- * Control interface
    -- $control
    link,
    listAccounts,
    register,
    registerWithCaptcha,
    verify,
    verifyWithPin,

    -- * Account interface
    -- $signal
    getContactName,
    getContactNumber,
    getSelfNumber,
    isContactBlocked,
    isRegistered,
    listNumbers,
    removePin,
    sendEndSessionMessage,
    sendMessage,
    sendMessageReaction,
    sendNoteToSelfMessage,
    sendReadReceipt,
    sendViewedReceipt,
    sendRemoteDeleteMessage,
    sendTyping,
    setContactBlocked,
    setContactName,
    deleteContact,
    deleteRecipient,
    setExpirationTimer,
    setPin,
    submitRateLimitChallenge,
    updateProfile,
    uploadStickerPack,
    version,
    createGroup,
    getGroup,
    joinGroup,
    listGroups,
    sendGroupMessage,
    sendGroupTyping,
    sendGroupMessageReaction,
    sendGroupRemoteDeleteMessage,
    addDevice,
    getDevice,
    listDevices,

    -- * Group interface
    getGroupId,
    getGroupName,
    getGroupDescription,
    getGroupIsBlocked,
    getGroupIsAdmin,
    getGroupMessageExpirationTimer,
    getGroupMembers,
    getGroupPendingMembers,
    getGroupRequestingMembers,
    getGroupAdmins,
    getGroupPermissionAddMember,
    getGroupPermissionEditDetails,
    getGroupPermissionSendMessage,
    -- could've been 'getGroupGroupInviteLink' for consistency, but eww.
    getGroupInviteLink,

    setGroupName,
    setGroupDescription,
    setGroupAvatar,
    setGroupIsBlocked,
    setGroupMessageExpirationTimer,
    setGroupPermissionAddMember,
    setGroupPermissionEditDetails,
    setGroupPermissionSendMessage,

    groupAddAdmins,
    groupAddMembers,
    groupDisableLink,
    groupEnableLink,
    groupQuit,
    groupRemoveAdmins,
    groupRemoveMembers,
    groupResetLink,

    -- TODO: * Device interface

    -- * Types
    SignalDBus.Types.SignalConn,
    SignalDBus.Types.Timestamp,
    SignalDBus.Types.Device,
    SignalDBus.Types.Group,
    SignalDBus.Types.ReceivedMessage(..),
) where

import Data.ByteString (ByteString)
import Data.Int (Int32, Int64)
import DBus.Internal.Types (toVariant, ObjectPath(..))
import SignalDBus.Interface
import SignalDBus.Types
import UnliftIO (MonadIO)

-- $control
--
-- These methods are only available if the signal-cli daemon was started in
-- multi-account mode.

-- |UNTESTED. Link this as a new device, identified by the given string.
link :: MonadIO m => String -> SignalConn -> m String
link :: String -> SignalConn -> m String
link String
name = MemberName -> [Variant] -> SignalConn -> m String
forall (m :: * -> *) a.
(MonadIO m, IsVariant a) =>
MemberName -> [Variant] -> SignalConn -> m a
callControl MemberName
"link" [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
name]

-- |List accounts attached to this signal-cli instance
listAccounts :: MonadIO m => SignalConn -> m [String]
listAccounts :: SignalConn -> m [String]
listAccounts SignalConn
sc = do
    [ObjectPath]
obs <- MemberName -> [Variant] -> SignalConn -> m [ObjectPath]
forall (m :: * -> *) a.
(MonadIO m, IsVariant a) =>
MemberName -> [Variant] -> SignalConn -> m a
callControl MemberName
"listAccounts" [] SignalConn
sc
    [String] -> m [String]
forall (m :: * -> *) a. Monad m => a -> m a
return ([String] -> m [String]) -> [String] -> m [String]
forall a b. (a -> b) -> a -> b
$! ((ObjectPath -> String) -> [ObjectPath] -> [String])
-> [ObjectPath] -> (ObjectPath -> String) -> [String]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (ObjectPath -> String) -> [ObjectPath] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map [ObjectPath]
obs ((ObjectPath -> String) -> [String])
-> (ObjectPath -> String) -> [String]
forall a b. (a -> b) -> a -> b
$ \(ObjectPath String
s) 
        -> Char
'+' Char -> String -> String
forall a. a -> [a] -> [a]
: Int -> String -> String
forall a. Int -> [a] -> [a]
drop (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (String
"/org/asamk/Signal/_" :: String)) String
s

-- |UNTESTED. Register this as the primary device for the given number. Set the
-- second argument to 'True' to request voice verification instead of SMS verification.
register :: MonadIO m => String -> Bool -> SignalConn -> m ()
register :: String -> Bool -> SignalConn -> m ()
register String
name Bool
b = MemberName -> [Variant] -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> SignalConn -> m ()
callControl_ MemberName
"register" [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
name, Bool -> Variant
forall a. IsVariant a => a -> Variant
toVariant Bool
b]

-- |UNTESTED. Same as 'register', but include a Captcha string.
registerWithCaptcha :: MonadIO m => String -> Bool -> String -> SignalConn -> m ()
registerWithCaptcha :: String -> Bool -> String -> SignalConn -> m ()
registerWithCaptcha String
name Bool
b String
c = MemberName -> [Variant] -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> SignalConn -> m ()
callControl_ MemberName
"registerWithCaptcha"
    ([Variant] -> SignalConn -> m ())
-> [Variant] -> SignalConn -> m ()
forall a b. (a -> b) -> a -> b
$ [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
name, Bool -> Variant
forall a. IsVariant a => a -> Variant
toVariant Bool
b, String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
c]

-- | UNTESTED. Verify your phone number after requesting registration via 'register'
-- or 'registerWithCaptcha'
verify :: MonadIO m
    => String     -- ^ Phone number
    -> String     -- ^ Verification code
    -> SignalConn -- ^ Connection object
    -> m ()
verify :: String -> String -> SignalConn -> m ()
verify String
n String
c = MemberName -> [Variant] -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> SignalConn -> m ()
callControl_ MemberName
"verify" [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
n, String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
c]

-- | UNTESTED. Same as 'verify', but include a registration pin for protected accounts
verifyWithPin :: MonadIO m
    => String     -- ^ Phone number
    -> String     -- ^ Verification code
    -> String     -- ^ Pin
    -> SignalConn -- ^ Connection object
    -> m ()
verifyWithPin :: String -> String -> String -> SignalConn -> m ()
verifyWithPin String
n String
c String
p = MemberName -> [Variant] -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> SignalConn -> m ()
callControl_ MemberName
"verifyWithPin"
    ([Variant] -> SignalConn -> m ())
-> [Variant] -> SignalConn -> m ()
forall a b. (a -> b) -> a -> b
$ [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
n, String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
c, String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
p]

-- $signal
--
-- These methods may only be called on a connection object that knows which account to
-- use; that is, either the signal daemon has a default account, and you've used
-- 'withConn', or it doesn't, and you've used 'withConnNum'.

-- |Takes a number, and returns the name of the contact, empty if unknown
getContactName :: MonadIO m => String -> SignalConn -> m String
getContactName :: String -> SignalConn -> m String
getContactName String
n = MemberName -> [Variant] -> SignalConn -> m String
forall (m :: * -> *) a.
(MonadIO m, IsVariant a) =>
MemberName -> [Variant] -> SignalConn -> m a
callSC MemberName
"getContactName" [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
n]

-- |Takes a contact name, and returns known numbers, both as strings
getContactNumber :: MonadIO m => String -> SignalConn -> m [String]
getContactNumber :: String -> SignalConn -> m [String]
getContactNumber String
name = MemberName -> [Variant] -> SignalConn -> m [String]
forall (m :: * -> *) a.
(MonadIO m, IsVariant a) =>
MemberName -> [Variant] -> SignalConn -> m a
callSC MemberName
"getContactNumber" [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
name]

-- |Returns your own number
getSelfNumber :: MonadIO m => SignalConn -> m String
getSelfNumber :: SignalConn -> m String
getSelfNumber = MemberName -> [Variant] -> SignalConn -> m String
forall (m :: * -> *) a.
(MonadIO m, IsVariant a) =>
MemberName -> [Variant] -> SignalConn -> m a
callSC MemberName
"getSelfNumber" []

-- |Returns true if you blocked this number
isContactBlocked :: MonadIO m => String -> SignalConn -> m Bool
isContactBlocked :: String -> SignalConn -> m Bool
isContactBlocked String
number = MemberName -> [Variant] -> SignalConn -> m Bool
forall (m :: * -> *) a.
(MonadIO m, IsVariant a) =>
MemberName -> [Variant] -> SignalConn -> m a
callSC MemberName
"isContactBlocked" [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
number]

-- |For each given number, returns whether that user is registered on Signal
isRegistered :: MonadIO m => [String] -> SignalConn -> m [Bool]
isRegistered :: [String] -> SignalConn -> m [Bool]
isRegistered [String]
nums = MemberName -> [Variant] -> SignalConn -> m [Bool]
forall (m :: * -> *) a.
(MonadIO m, IsVariant a) =>
MemberName -> [Variant] -> SignalConn -> m a
callSC MemberName
"isRegistered" [[String] -> Variant
forall a. IsVariant a => a -> Variant
toVariant [String]
nums]

-- |List all known numbers (e.g. group members and senders of received messages)
listNumbers :: MonadIO m => SignalConn -> m [String]
listNumbers :: SignalConn -> m [String]
listNumbers = MemberName -> [Variant] -> SignalConn -> m [String]
forall (m :: * -> *) a.
(MonadIO m, IsVariant a) =>
MemberName -> [Variant] -> SignalConn -> m a
callSC MemberName
"listNumbers" []

-- |UNTESTED. Removes registration pin protection.
removePin :: MonadIO m => SignalConn -> m ()
removePin :: SignalConn -> m ()
removePin = MemberName -> [Variant] -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> SignalConn -> m ()
callSC_ MemberName
"removePin" []

-- |UNTESTED. No idea what this accomplishes, so hmu if you know. It's implemented though
sendEndSessionMessage :: MonadIO m => SignalConn -> m ()
sendEndSessionMessage :: SignalConn -> m ()
sendEndSessionMessage = MemberName -> [Variant] -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> SignalConn -> m ()
callSC_ MemberName
"sendEndSessionMessage" []

-- |Sends a message, possibly with attachments, to a number of recipients
sendMessage :: MonadIO m
    => String      -- ^ Message content
    -> [String]    -- ^ Paths to attachments. Resolves using the working dir of the signal-cli daemon, not this process
    -> [String]    -- ^ Recipients
    -> SignalConn  -- ^ Connection object
    -> m Timestamp -- ^ Timestamp of sent message
sendMessage :: String -> [String] -> [String] -> SignalConn -> m Timestamp
sendMessage String
m [String]
as [String]
rs = MemberName -> [Variant] -> SignalConn -> m Timestamp
forall (m :: * -> *) a.
(MonadIO m, IsVariant a) =>
MemberName -> [Variant] -> SignalConn -> m a
callSC MemberName
"sendMessage"
    [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
m, [String] -> Variant
forall a. IsVariant a => a -> Variant
toVariant [String]
as, [String] -> Variant
forall a. IsVariant a => a -> Variant
toVariant [String]
rs]

-- |Reacts to a message
sendMessageReaction :: MonadIO m
    => String      -- ^ Unicode grapheme cluster. Only tested with "😂"
    -> Bool        -- ^ Whether to remove a previously sent reaction instead of adding one
    -> String      -- ^ Author of the message you want to react to
    -> Timestamp   -- ^ Timestamp of message to react to
    -> String      -- ^ Phone numbers of recipient
    -> SignalConn  -- ^ Connection object
    -> m Timestamp -- ^ Timestamp of reaction
sendMessageReaction :: String
-> Bool
-> String
-> Timestamp
-> String
-> SignalConn
-> m Timestamp
sendMessageReaction String
emoji Bool
rm String
n Timestamp
ts String
r = MemberName -> [Variant] -> SignalConn -> m Timestamp
forall (m :: * -> *) a.
(MonadIO m, IsVariant a) =>
MemberName -> [Variant] -> SignalConn -> m a
callSC MemberName
"sendMessageReaction"
    ([Variant] -> SignalConn -> m Timestamp)
-> [Variant] -> SignalConn -> m Timestamp
forall a b. (a -> b) -> a -> b
$ [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
emoji, Bool -> Variant
forall a. IsVariant a => a -> Variant
toVariant Bool
rm, String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
n, Timestamp -> Variant
forall a. IsVariant a => a -> Variant
toVariant Timestamp
ts, String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
r]

-- |Sends a message to yourself
sendNoteToSelfMessage :: MonadIO m
    => String      -- ^ Message
    -> [String]    -- ^ Paths to attachments. Resolves using the working dir of the signal-cli daemon, not this process
    -> SignalConn  -- ^ Connection object
    -> m Timestamp -- ^ Timestamp of sent message
sendNoteToSelfMessage :: String -> [String] -> SignalConn -> m Timestamp
sendNoteToSelfMessage String
m [String]
as = MemberName -> [Variant] -> SignalConn -> m Timestamp
forall (m :: * -> *) a.
(MonadIO m, IsVariant a) =>
MemberName -> [Variant] -> SignalConn -> m a
callSC MemberName
"sendNoteToSelfMessage"
    ([Variant] -> SignalConn -> m Timestamp)
-> [Variant] -> SignalConn -> m Timestamp
forall a b. (a -> b) -> a -> b
$ [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
m, [String] -> Variant
forall a. IsVariant a => a -> Variant
toVariant [String]
as]

-- |Sends read receipts for the messages with the specified timestamps to the given phone
-- number. These timestamps must belong to messages you received from that number.
sendReadReceipt :: MonadIO m => String -> [Timestamp] -> SignalConn -> m ()
sendReadReceipt :: String -> [Timestamp] -> SignalConn -> m ()
sendReadReceipt String
r [Timestamp]
ts = MemberName -> [Variant] -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> SignalConn -> m ()
callSC_ MemberName
"sendReadReceipt" [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
r, [Timestamp] -> Variant
forall a. IsVariant a => a -> Variant
toVariant [Timestamp]
ts]

-- |Sends viewed receipts for the messages with the specified timestamps to the given phone
-- number. This is probably not what you want; 'sendReadReceipt' seems to be the way to go.
sendViewedReceipt :: MonadIO m => String -> [Timestamp] -> SignalConn -> m ()
sendViewedReceipt :: String -> [Timestamp] -> SignalConn -> m ()
sendViewedReceipt String
r [Timestamp]
ts = MemberName -> [Variant] -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> SignalConn -> m ()
callSC_ MemberName
"sendViewedReceipt" [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
r, [Timestamp] -> Variant
forall a. IsVariant a => a -> Variant
toVariant [Timestamp]
ts]

-- |Delete one of you own private messages; also deletes them remotely on supported
-- clients (Signal-desktop, Android/IOS apps, ...)
sendRemoteDeleteMessage :: MonadIO m
    => Timestamp   -- ^ Timestamp of message to delete
    -> [String]    -- ^ Recipients
    -> SignalConn  -- ^ Connection object
    -> m Timestamp -- ^ Timestamp, can be used to identify corresponding replies
sendRemoteDeleteMessage :: Timestamp -> [String] -> SignalConn -> m Timestamp
sendRemoteDeleteMessage Timestamp
ts [String]
rs = MemberName -> [Variant] -> SignalConn -> m Timestamp
forall (m :: * -> *) a.
(MonadIO m, IsVariant a) =>
MemberName -> [Variant] -> SignalConn -> m a
callSC MemberName
"sendRemoteDeleteMessage"
    ([Variant] -> SignalConn -> m Timestamp)
-> [Variant] -> SignalConn -> m Timestamp
forall a b. (a -> b) -> a -> b
$ [Timestamp -> Variant
forall a. IsVariant a => a -> Variant
toVariant Timestamp
ts, [String] -> Variant
forall a. IsVariant a => a -> Variant
toVariant [String]
rs]

-- |Send updates about whether you're typing to the given number.
-- NOTE: the boolean argument should be False to indicate you're typing, and True to
-- clear the typing state
sendTyping :: MonadIO m => String -> Bool -> SignalConn -> m ()
sendTyping :: String -> Bool -> SignalConn -> m ()
sendTyping String
n Bool
b = MemberName -> [Variant] -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> SignalConn -> m ()
callSC_ MemberName
"sendTyping" [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
n, Bool -> Variant
forall a. IsVariant a => a -> Variant
toVariant Bool
b]

-- |UNTESTED. Sets whether a contact is blocked. This is only done locally, so this just
-- disabled messages from that number from being forwarded via DBus.
setContactBlocked :: MonadIO m => String -> Bool -> SignalConn -> m ()
setContactBlocked :: String -> Bool -> SignalConn -> m ()
setContactBlocked String
n Bool
b = MemberName -> [Variant] -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> SignalConn -> m ()
callSC_ MemberName
"setContactBlocked" [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
n, Bool -> Variant
forall a. IsVariant a => a -> Variant
toVariant Bool
b]

-- |Not implemented, as the documentation doesn't state the type of the name
-- (probably a String, but I dont feel like testing stuff rn)
setContactName :: a
setContactName :: a
setContactName = String -> a
forall a. HasCallStack => String -> a
error String
"Not implemented due to documentation succ"

-- |UNTESTED. Probably deletes a contact, given by a phone number, or something.
deleteContact :: MonadIO m => String -> SignalConn -> m ()
deleteContact :: String -> SignalConn -> m ()
deleteContact String
n = MemberName -> [Variant] -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> SignalConn -> m ()
callSC_ MemberName
"deleteContact" [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
n]

-- |UNTESTED. Idk what this does, but tell me if you know/have used this.
deleteRecipient :: MonadIO m => String -> SignalConn -> m ()
deleteRecipient :: String -> SignalConn -> m ()
deleteRecipient String
n = MemberName -> [Variant] -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> SignalConn -> m ()
callSC_ MemberName
"deleteRecipient" [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
n]

-- |Set seconds until messages to this recipient dissapear (on supported clients). Set to
-- 0 to disable.
setExpirationTimer :: (MonadIO m, Integral i) => String -> i -> SignalConn -> m ()
setExpirationTimer :: String -> i -> SignalConn -> m ()
setExpirationTimer String
n i
i = MemberName -> [Variant] -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> SignalConn -> m ()
callSC_ MemberName
"setExpirationTimer"
    ([Variant] -> SignalConn -> m ())
-> [Variant] -> SignalConn -> m ()
forall a b. (a -> b) -> a -> b
$ [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
n, Int32 -> Variant
forall a. IsVariant a => a -> Variant
toVariant (i -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral i
i :: Int32)]

-- |UNTESTED. Set registration pin to prevent others from registering your number.
setPin :: MonadIO m => String -> SignalConn -> m ()
setPin :: String -> SignalConn -> m ()
setPin String
p = MemberName -> [Variant] -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> SignalConn -> m ()
callSC_ MemberName
"setPin" [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
p]

-- |UNTESTED. Idk but seems to be useful for lifting rate limits
submitRateLimitChallenge :: MonadIO m => String -> String -> SignalConn -> m ()
submitRateLimitChallenge :: String -> String -> SignalConn -> m ()
submitRateLimitChallenge String
ch String
cap = MemberName -> [Variant] -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> SignalConn -> m ()
callSC_ MemberName
"submitRateLimitChallenge"
    ([Variant] -> SignalConn -> m ())
-> [Variant] -> SignalConn -> m ()
forall a b. (a -> b) -> a -> b
$ [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
ch, String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
cap]

-- |Update parts of your profile. You can leave any string field empty to keep the old
-- value.
updateProfile :: MonadIO m
    => String     -- ^ Given name
    -> String     -- ^ Family name
    -> String     -- ^ About message
    -> String     -- ^ Emoji for profile
    -> String     -- ^ Avatar file name. Resolves using the working dir of the signal-cli daemon, not this process
    -> Bool       -- ^ True if the avatar should be removed
    -> SignalConn -- ^ Connection object
    -> m ()
updateProfile :: String
-> String
-> String
-> String
-> String
-> Bool
-> SignalConn
-> m ()
updateProfile String
gn String
fn String
ab String
em String
fp Bool
rm = MemberName -> [Variant] -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> SignalConn -> m ()
callSC_ MemberName
"updateProfile"
    ([Variant] -> SignalConn -> m ())
-> [Variant] -> SignalConn -> m ()
forall a b. (a -> b) -> a -> b
$ [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
gn, String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
fn, String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
ab, String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
em, String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
fp, Bool -> Variant
forall a. IsVariant a => a -> Variant
toVariant Bool
rm]

-- |UNTESTED. Uploads a sticker pack, given by the path to a manifest.json or zip file,
-- and return the URL of the pack.
uploadStickerPack :: MonadIO m => String -> SignalConn -> m String
uploadStickerPack :: String -> SignalConn -> m String
uploadStickerPack String
fp = MemberName -> [Variant] -> SignalConn -> m String
forall (m :: * -> *) a.
(MonadIO m, IsVariant a) =>
MemberName -> [Variant] -> SignalConn -> m a
callSC MemberName
"uploadStickerPack" [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
fp]

-- |Return version string of signal-cli. This also works for multi-account connections.
version :: MonadIO m => SignalConn -> m String
version :: SignalConn -> m String
version = MemberName -> [Variant] -> SignalConn -> m String
forall (m :: * -> *) a.
(MonadIO m, IsVariant a) =>
MemberName -> [Variant] -> SignalConn -> m a
callSC MemberName
"version" []

-- |Create a group
createGroup :: MonadIO m
    => String       -- ^ Group name
    -> [String]     -- ^ Initial members
    -> String       -- ^ Avatar file name. Resolves using the working dir of the signal-cli daemon, not this process
    -> SignalConn   -- ^ Connection object
    -> m Group      -- ^ Group object
createGroup :: String -> [String] -> String -> SignalConn -> m Group
createGroup String
n [String]
ms String
f SignalConn
sc = do
    ByteString
gId <- MemberName -> [Variant] -> SignalConn -> m ByteString
forall (m :: * -> *) a.
(MonadIO m, IsVariant a) =>
MemberName -> [Variant] -> SignalConn -> m a
callSC MemberName
"createGroup" [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
n, [String] -> Variant
forall a. IsVariant a => a -> Variant
toVariant [String]
ms, String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
f] SignalConn
sc
    ByteString -> SignalConn -> m Group
forall (m :: * -> *).
MonadIO m =>
ByteString -> SignalConn -> m Group
getGroup ByteString
gId SignalConn
sc

-- |Get DBus object path for a group, given by its signal-internal binary identifier.
getGroup :: MonadIO m => ByteString -> SignalConn -> m Group
getGroup :: ByteString -> SignalConn -> m Group
getGroup ByteString
g = MemberName -> [Variant] -> SignalConn -> m Group
forall (m :: * -> *) a.
(MonadIO m, IsVariant a) =>
MemberName -> [Variant] -> SignalConn -> m a
callSC MemberName
"getGroup" [ByteString -> Variant
forall a. IsVariant a => a -> Variant
toVariant ByteString
g]

-- |UNTESTED. Join a group given by an invite link. Behaviour of this depends on
-- properties of the group; see "joinGroup" on
-- https://github.com/AsamK/signal-cli/blob/master/man/signal-cli-dbus.5.adoc
-- (latest commit while writing this: 34cc64f8ce97a63c859bd95faf6783422f14df61)
joinGroup :: MonadIO m => String -> SignalConn -> m ()
joinGroup :: String -> SignalConn -> m ()
joinGroup String
l = MemberName -> [Variant] -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> SignalConn -> m ()
callSC_ MemberName
"joinGroup" [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
l]

-- |List known groups, represented as (group object, internal identifier, group name)
listGroups :: MonadIO m => SignalConn -> m [(Group, ByteString, String)]
listGroups :: SignalConn -> m [(Group, ByteString, String)]
listGroups = MemberName
-> [Variant] -> SignalConn -> m [(Group, ByteString, String)]
forall (m :: * -> *) a.
(MonadIO m, IsVariant a) =>
MemberName -> [Variant] -> SignalConn -> m a
callSC MemberName
"listGroups" []

-- |Sends a message, possibly with attachments, to a group
sendGroupMessage :: MonadIO m
    => String      -- ^ Message content
    -> [String]    -- ^ Paths to attachments. Resolves using the working dir of the signal-cli daemon, not this process
    -> Group       -- ^ Group in which to send a message
    -> SignalConn  -- ^ Connection object
    -> m Timestamp -- ^ Timestamp of sent message
sendGroupMessage :: String -> [String] -> Group -> SignalConn -> m Timestamp
sendGroupMessage String
m [String]
as Group
g SignalConn
sc = do
    ByteString
gId <- MemberName -> Group -> SignalConn -> m ByteString
forall (m :: * -> *) a.
(MonadIO m, IsValue a) =>
MemberName -> Group -> SignalConn -> m a
getGroupProp MemberName
"Id" Group
g SignalConn
sc
    MemberName -> [Variant] -> SignalConn -> m Timestamp
forall (m :: * -> *) a.
(MonadIO m, IsVariant a) =>
MemberName -> [Variant] -> SignalConn -> m a
callSC MemberName
"sendGroupMessage"
        [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
m, [String] -> Variant
forall a. IsVariant a => a -> Variant
toVariant [String]
as, ByteString -> Variant
forall a. IsVariant a => a -> Variant
toVariant (ByteString
gId :: ByteString)] SignalConn
sc

-- |Send updates about whether you're typing to the given group.
-- NOTE: the boolean argument should be False to indicate you're typing, and True to
-- clear the typing state
sendGroupTyping :: MonadIO m => Group -> Bool -> SignalConn -> m ()
sendGroupTyping :: Group -> Bool -> SignalConn -> m ()
sendGroupTyping Group
g Bool
b SignalConn
sc = do
    ByteString
gId <- Group -> SignalConn -> m ByteString
forall (m :: * -> *).
MonadIO m =>
Group -> SignalConn -> m ByteString
getGroupId Group
g SignalConn
sc
    MemberName -> [Variant] -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> SignalConn -> m ()
callSC_ MemberName
"sendGroupTyping" [ByteString -> Variant
forall a. IsVariant a => a -> Variant
toVariant ByteString
gId, Bool -> Variant
forall a. IsVariant a => a -> Variant
toVariant Bool
b] SignalConn
sc

-- |Reacts to a message
sendGroupMessageReaction :: MonadIO m
    => String      -- ^ Unicode grapheme cluster. Only tested with "😂"
    -> Bool        -- ^ Whether to remove a previously sent reaction instead of adding one
    -> String      -- ^ Author of the message you want to react to
    -> Timestamp   -- ^ Timestamp of message to react to
    -> Group       -- ^ Group in which to react
    -> SignalConn  -- ^ Connection object
    -> m Timestamp -- ^ Timestamp of reaction
sendGroupMessageReaction :: String
-> Bool
-> String
-> Timestamp
-> Group
-> SignalConn
-> m Timestamp
sendGroupMessageReaction String
emoji Bool
rm String
n Timestamp
ts Group
g SignalConn
sc = do
    ByteString
gId <- Group -> SignalConn -> m ByteString
forall (m :: * -> *).
MonadIO m =>
Group -> SignalConn -> m ByteString
getGroupId Group
g SignalConn
sc
    MemberName -> [Variant] -> SignalConn -> m Timestamp
forall (m :: * -> *) a.
(MonadIO m, IsVariant a) =>
MemberName -> [Variant] -> SignalConn -> m a
callSC MemberName
"sendGroupMessageReaction" [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
emoji, Bool -> Variant
forall a. IsVariant a => a -> Variant
toVariant Bool
rm, String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
n,
        Timestamp -> Variant
forall a. IsVariant a => a -> Variant
toVariant Timestamp
ts, ByteString -> Variant
forall a. IsVariant a => a -> Variant
toVariant ByteString
gId] SignalConn
sc

-- |Delete one of you own group messages; also deletes them remotely on supported
-- clients (Signal-desktop, Android/IOS apps, ...)
sendGroupRemoteDeleteMessage :: MonadIO m
    => Timestamp   -- ^ Timestamp of message to delete
    -> Group       -- ^ Group in which to delete your message
    -> SignalConn  -- ^ Connection object
    -> m Timestamp -- ^ Timestamp, can be used to identify corresponding replies
sendGroupRemoteDeleteMessage :: Timestamp -> Group -> SignalConn -> m Timestamp
sendGroupRemoteDeleteMessage Timestamp
ts Group
g SignalConn
sc = do
    ByteString
gId <- Group -> SignalConn -> m ByteString
forall (m :: * -> *).
MonadIO m =>
Group -> SignalConn -> m ByteString
getGroupId Group
g SignalConn
sc
    MemberName -> [Variant] -> SignalConn -> m Timestamp
forall (m :: * -> *) a.
(MonadIO m, IsVariant a) =>
MemberName -> [Variant] -> SignalConn -> m a
callSC MemberName
"sendGroupRemoteDeleteMessage" [Timestamp -> Variant
forall a. IsVariant a => a -> Variant
toVariant Timestamp
ts, ByteString -> Variant
forall a. IsVariant a => a -> Variant
toVariant ByteString
gId] SignalConn
sc

-- |UNTESTED. Add a device that wants to link to this account using a link
addDevice :: MonadIO m => String -> SignalConn -> m ()
addDevice :: String -> SignalConn -> m ()
addDevice String
l = MemberName -> [Variant] -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> SignalConn -> m ()
callSC_ MemberName
"addDevice" [String -> Variant
forall a. IsVariant a => a -> Variant
toVariant String
l]

-- |Get DBus object path for a device given by a device ID
getDevice :: MonadIO m => Int64 -> SignalConn -> m ObjectPath
getDevice :: Int64 -> SignalConn -> m ObjectPath
getDevice Int64
d = MemberName -> [Variant] -> SignalConn -> m ObjectPath
forall (m :: * -> *) a.
(MonadIO m, IsVariant a) =>
MemberName -> [Variant] -> SignalConn -> m a
callSC MemberName
"getDevice" [Int64 -> Variant
forall a. IsVariant a => a -> Variant
toVariant Int64
d]

-- |List devices linked with this account, represented as
-- (object path, device id, device name)
listDevices :: MonadIO m => SignalConn -> m [(ObjectPath, Int64, String)]
listDevices :: SignalConn -> m [(ObjectPath, Int64, String)]
listDevices = MemberName
-> [Variant] -> SignalConn -> m [(ObjectPath, Int64, String)]
forall (m :: * -> *) a.
(MonadIO m, IsVariant a) =>
MemberName -> [Variant] -> SignalConn -> m a
callSC MemberName
"listDevices" []

-- |Byte array representing the internal group identifier
getGroupId :: MonadIO m => Group -> SignalConn -> m ByteString
getGroupId :: Group -> SignalConn -> m ByteString
getGroupId = MemberName -> Group -> SignalConn -> m ByteString
forall (m :: * -> *) a.
(MonadIO m, IsValue a) =>
MemberName -> Group -> SignalConn -> m a
getGroupProp MemberName
"Id"

-- |Display name
getGroupName :: MonadIO m => Group -> SignalConn -> m String
getGroupName :: Group -> SignalConn -> m String
getGroupName = MemberName -> Group -> SignalConn -> m String
forall (m :: * -> *) a.
(MonadIO m, IsValue a) =>
MemberName -> Group -> SignalConn -> m a
getGroupProp MemberName
"Name"

-- |Description
getGroupDescription :: MonadIO m => Group -> SignalConn -> m String
getGroupDescription :: Group -> SignalConn -> m String
getGroupDescription = MemberName -> Group -> SignalConn -> m String
forall (m :: * -> *) a.
(MonadIO m, IsValue a) =>
MemberName -> Group -> SignalConn -> m a
getGroupProp MemberName
"Description"

-- |UNTESTED. If true, messages won't be forwarded via DBus
getGroupIsBlocked :: MonadIO m => Group -> SignalConn -> m Bool
getGroupIsBlocked :: Group -> SignalConn -> m Bool
getGroupIsBlocked = MemberName -> Group -> SignalConn -> m Bool
forall (m :: * -> *) a.
(MonadIO m, IsValue a) =>
MemberName -> Group -> SignalConn -> m a
getGroupProp MemberName
"IsBlocked"

-- |Whether this account is a group admin
getGroupIsAdmin :: MonadIO m => Group -> SignalConn -> m Bool
getGroupIsAdmin :: Group -> SignalConn -> m Bool
getGroupIsAdmin = MemberName -> Group -> SignalConn -> m Bool
forall (m :: * -> *) a.
(MonadIO m, IsValue a) =>
MemberName -> Group -> SignalConn -> m a
getGroupProp MemberName
"IsAdmin"

-- |Message expiration timer. 0 if disabled
getGroupMessageExpirationTimer :: MonadIO m => Group -> SignalConn -> m Int
getGroupMessageExpirationTimer :: Group -> SignalConn -> m Int
getGroupMessageExpirationTimer Group
g SignalConn
sc = do
    Int32
i <- MemberName -> Group -> SignalConn -> m Int32
forall (m :: * -> *) a.
(MonadIO m, IsValue a) =>
MemberName -> Group -> SignalConn -> m a
getGroupProp MemberName
"MessageExpirationTimer" Group
g SignalConn
sc
    Int -> m Int
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> m Int) -> Int -> m Int
forall a b. (a -> b) -> a -> b
$! Int32 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int32
i :: Int32)

-- |List of group members' phone numbers
getGroupMembers :: MonadIO m => Group -> SignalConn -> m [String]
getGroupMembers :: Group -> SignalConn -> m [String]
getGroupMembers = MemberName -> Group -> SignalConn -> m [String]
forall (m :: * -> *) a.
(MonadIO m, IsValue a) =>
MemberName -> Group -> SignalConn -> m a
getGroupProp MemberName
"Members"

-- |UNTESTED. List of pending group members; I don't know what this does, but I
-- imagine you're probably looking for 'getGroupRequestingMembers'
getGroupPendingMembers :: MonadIO m => Group -> SignalConn -> m [String]
getGroupPendingMembers :: Group -> SignalConn -> m [String]
getGroupPendingMembers = MemberName -> Group -> SignalConn -> m [String]
forall (m :: * -> *) a.
(MonadIO m, IsValue a) =>
MemberName -> Group -> SignalConn -> m a
getGroupProp MemberName
"PendingMembers"

-- |List of phone numbers requesting to join the group, if theres an invite link set
-- to require admin approval
getGroupRequestingMembers :: MonadIO m => Group -> SignalConn -> m [String]
getGroupRequestingMembers :: Group -> SignalConn -> m [String]
getGroupRequestingMembers = MemberName -> Group -> SignalConn -> m [String]
forall (m :: * -> *) a.
(MonadIO m, IsValue a) =>
MemberName -> Group -> SignalConn -> m a
getGroupProp MemberName
"RequestingMembers"

-- |List of group admins' phone numbers
getGroupAdmins :: MonadIO m => Group -> SignalConn -> m [String]
getGroupAdmins :: Group -> SignalConn -> m [String]
getGroupAdmins = MemberName -> Group -> SignalConn -> m [String]
forall (m :: * -> *) a.
(MonadIO m, IsValue a) =>
MemberName -> Group -> SignalConn -> m a
getGroupProp MemberName
"Admins"

-- |String representing who has permission to add members
-- (one of "ONLY_ADMINS", "EVERY_MEMBER")
getGroupPermissionAddMember :: MonadIO m => Group -> SignalConn -> m String
getGroupPermissionAddMember :: Group -> SignalConn -> m String
getGroupPermissionAddMember = MemberName -> Group -> SignalConn -> m String
forall (m :: * -> *) a.
(MonadIO m, IsValue a) =>
MemberName -> Group -> SignalConn -> m a
getGroupProp MemberName
"PermissionAddMember"

-- |String representing who has permission to edit group description
-- (one of "ONLY_ADMINS", "EVERY_MEMBER")
getGroupPermissionEditDetails :: MonadIO m => Group -> SignalConn -> m String
getGroupPermissionEditDetails :: Group -> SignalConn -> m String
getGroupPermissionEditDetails = MemberName -> Group -> SignalConn -> m String
forall (m :: * -> *) a.
(MonadIO m, IsValue a) =>
MemberName -> Group -> SignalConn -> m a
getGroupProp MemberName
"PermissionEditDetails"

-- |String representing who has permission to send messages
-- (one of "ONLY_ADMINS", "EVERY_MEMBER")
getGroupPermissionSendMessage :: MonadIO m => Group -> SignalConn -> m String
getGroupPermissionSendMessage :: Group -> SignalConn -> m String
getGroupPermissionSendMessage = MemberName -> Group -> SignalConn -> m String
forall (m :: * -> *) a.
(MonadIO m, IsValue a) =>
MemberName -> Group -> SignalConn -> m a
getGroupProp MemberName
"PermissionSendMessage"

-- |Group invitation link. Empty if disabled
getGroupInviteLink :: MonadIO m => Group -> SignalConn -> m String
getGroupInviteLink :: Group -> SignalConn -> m String
getGroupInviteLink = MemberName -> Group -> SignalConn -> m String
forall (m :: * -> *) a.
(MonadIO m, IsValue a) =>
MemberName -> Group -> SignalConn -> m a
getGroupProp MemberName
"GroupInviteLink"

-- |Display name
setGroupName :: MonadIO m => String -> Group -> SignalConn -> m ()
setGroupName :: String -> Group -> SignalConn -> m ()
setGroupName String
s = MemberName -> String -> Group -> SignalConn -> m ()
forall (m :: * -> *) a.
(MonadIO m, IsValue a) =>
MemberName -> a -> Group -> SignalConn -> m ()
setGroupProp MemberName
"Name" String
s

-- |Description
setGroupDescription :: MonadIO m => String -> Group -> SignalConn -> m ()
setGroupDescription :: String -> Group -> SignalConn -> m ()
setGroupDescription String
s = MemberName -> String -> Group -> SignalConn -> m ()
forall (m :: * -> *) a.
(MonadIO m, IsValue a) =>
MemberName -> a -> Group -> SignalConn -> m ()
setGroupProp MemberName
"Description" String
s

-- |Filename of group avatar. Resolves using the working dir of the signal-cli daemon, not this process
setGroupAvatar :: MonadIO m => String -> Group -> SignalConn -> m ()
setGroupAvatar :: String -> Group -> SignalConn -> m ()
setGroupAvatar String
s = MemberName -> String -> Group -> SignalConn -> m ()
forall (m :: * -> *) a.
(MonadIO m, IsValue a) =>
MemberName -> a -> Group -> SignalConn -> m ()
setGroupProp MemberName
"Avatar" String
s

-- |UNTESTED. If true, messages won't be forwarded via DBus
setGroupIsBlocked :: MonadIO m => Bool -> Group -> SignalConn -> m ()
setGroupIsBlocked :: Bool -> Group -> SignalConn -> m ()
setGroupIsBlocked Bool
b = MemberName -> Bool -> Group -> SignalConn -> m ()
forall (m :: * -> *) a.
(MonadIO m, IsValue a) =>
MemberName -> a -> Group -> SignalConn -> m ()
setGroupProp MemberName
"IsBlocked" Bool
b

-- |Message expiration timer. 0 to disable
setGroupMessageExpirationTimer :: MonadIO m => Int -> Group -> SignalConn -> m ()
setGroupMessageExpirationTimer :: Int -> Group -> SignalConn -> m ()
setGroupMessageExpirationTimer Int
i = MemberName -> Int32 -> Group -> SignalConn -> m ()
forall (m :: * -> *) a.
(MonadIO m, IsValue a) =>
MemberName -> a -> Group -> SignalConn -> m ()
setGroupProp MemberName
"MessageExpirationTimer"
    (Int32 -> Group -> SignalConn -> m ())
-> Int32 -> Group -> SignalConn -> m ()
forall a b. (a -> b) -> a -> b
$ (Int -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
i :: Int32)

-- |String representing who has permission to add members
-- (one of "ONLY_ADMINS", "EVERY_MEMBER")
setGroupPermissionAddMember :: MonadIO m => String -> Group -> SignalConn -> m ()
setGroupPermissionAddMember :: String -> Group -> SignalConn -> m ()
setGroupPermissionAddMember String
s = MemberName -> String -> Group -> SignalConn -> m ()
forall (m :: * -> *) a.
(MonadIO m, IsValue a) =>
MemberName -> a -> Group -> SignalConn -> m ()
setGroupProp MemberName
"PermissionAddMember" String
s

-- |String representing who has permission to edit group description
-- (one of "ONLY_ADMINS", "EVERY_MEMBER")
setGroupPermissionEditDetails :: MonadIO m => String -> Group -> SignalConn -> m ()
setGroupPermissionEditDetails :: String -> Group -> SignalConn -> m ()
setGroupPermissionEditDetails String
s = MemberName -> String -> Group -> SignalConn -> m ()
forall (m :: * -> *) a.
(MonadIO m, IsValue a) =>
MemberName -> a -> Group -> SignalConn -> m ()
setGroupProp MemberName
"PermissionEditDetails" String
s

-- |String representing who has permission to send messages
-- (one of "ONLY_ADMINS", "EVERY_MEMBER")
setGroupPermissionSendMessage :: MonadIO m => String -> Group -> SignalConn -> m ()
setGroupPermissionSendMessage :: String -> Group -> SignalConn -> m ()
setGroupPermissionSendMessage String
s = MemberName -> String -> Group -> SignalConn -> m ()
forall (m :: * -> *) a.
(MonadIO m, IsValue a) =>
MemberName -> a -> Group -> SignalConn -> m ()
setGroupProp MemberName
"PermissionSendMessage" String
s

-- |Add admins
groupAddAdmins :: MonadIO m => [String] -> Group -> SignalConn -> m ()
groupAddAdmins :: [String] -> Group -> SignalConn -> m ()
groupAddAdmins [String]
ns = MemberName -> [Variant] -> Group -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> Group -> SignalConn -> m ()
callGroup_ MemberName
"addAdmins" [[String] -> Variant
forall a. IsVariant a => a -> Variant
toVariant [String]
ns]

-- |Add numbers who are pending members to the group, and other numbers to requesting
-- members list
groupAddMembers :: MonadIO m => [String] -> Group -> SignalConn -> m ()
groupAddMembers :: [String] -> Group -> SignalConn -> m ()
groupAddMembers [String]
ns = MemberName -> [Variant] -> Group -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> Group -> SignalConn -> m ()
callGroup_ MemberName
"addMembers" [[String] -> Variant
forall a. IsVariant a => a -> Variant
toVariant [String]
ns]

-- |Disable group invitation link
groupDisableLink :: MonadIO m => Group -> SignalConn -> m ()
groupDisableLink :: Group -> SignalConn -> m ()
groupDisableLink = MemberName -> [Variant] -> Group -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> Group -> SignalConn -> m ()
callGroup_ MemberName
"disableLink" []

-- |Enable group invitation link. If the argument is true, users cannot join directly,
-- but are added to the requesting members list first.
groupEnableLink :: MonadIO m => Bool -> Group -> SignalConn -> m ()
groupEnableLink :: Bool -> Group -> SignalConn -> m ()
groupEnableLink Bool
b = MemberName -> [Variant] -> Group -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> Group -> SignalConn -> m ()
callGroup_ MemberName
"enableLink" [Bool -> Variant
forall a. IsVariant a => a -> Variant
toVariant Bool
b]

-- |Quit the group
groupQuit :: MonadIO m => Group -> SignalConn -> m ()
groupQuit :: Group -> SignalConn -> m ()
groupQuit = MemberName -> [Variant] -> Group -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> Group -> SignalConn -> m ()
callGroup_ MemberName
"quitGroup" []

-- |Remove admins
groupRemoveAdmins :: MonadIO m => [String] -> Group -> SignalConn -> m ()
groupRemoveAdmins :: [String] -> Group -> SignalConn -> m ()
groupRemoveAdmins [String]
ns = MemberName -> [Variant] -> Group -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> Group -> SignalConn -> m ()
callGroup_ MemberName
"removeAdmins" [[String] -> Variant
forall a. IsVariant a => a -> Variant
toVariant [String]
ns]

-- |Remove numbers from the group
groupRemoveMembers :: MonadIO m => [String] -> Group -> SignalConn -> m ()
groupRemoveMembers :: [String] -> Group -> SignalConn -> m ()
groupRemoveMembers [String]
ns = MemberName -> [Variant] -> Group -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> Group -> SignalConn -> m ()
callGroup_ MemberName
"removeMembers" [[String] -> Variant
forall a. IsVariant a => a -> Variant
toVariant [String]
ns]

-- |Reset the group invitation link
groupResetLink :: MonadIO m => Group -> SignalConn -> m ()
groupResetLink :: Group -> SignalConn -> m ()
groupResetLink = MemberName -> [Variant] -> Group -> SignalConn -> m ()
forall (m :: * -> *).
MonadIO m =>
MemberName -> [Variant] -> Group -> SignalConn -> m ()
callGroup_ MemberName
"resetLink" []