Zoom

Use the Zoom integration to manage your Zoom users and meetings.

Messaging and Conferencing · Zoom

Details

IDZoom
ProviderZoom
CategoryMessaging and Conferencing
From Version5.0.0
Docker Imagedemisto/fastapi:0.125.0.10158186
Supported ModulesAgentix XSIAM EDR Cortex Cloud Cloud Runtime Security

README

Use the Zoom integration manage your Zoom users and meetings
This integration was integrated and tested with version 2.0.0 of Zoom

Configure Zoom in Cortex

Parameter Description Required
Server URL (e.g., ‘https://api.zoom.us/v2/’)   True
Account ID (OAuth)   True
Client ID (OAuth)   True
Client Secret (OAuth)   True
Use system proxy settings   False
Trust any certificate (not secure)   False
Long running instance Enable in order to use zoom-ask and for mirroring. False
Listen Port Listener port number. Required when choosing long running instance with an external engine for using the Zoom Bot. False
Bot JID Zoom Bot app JID. False
Bot Client ID (OAuth) Zoom Bot app client ID. False
Bot Client Secret (OAuth) Zoom Bot app secret ID. False
Secret Token For mirroring, see Configuring Secret Token. False
Verification Token For verify the mirror in. False
Mirroring Enable Incident Mirroring. See how to configure the app. False
Certificate (Required for HTTPS) (For Cortex XSOAR 6.x) For use with HTTPS - the certificate that the service should use. (For Cortex XSOAR 8 and Cortex XSIAM) Custom certificates are supported only using engine. False
Private Key (Required for HTTPS) (For Cortex XSOAR 6.x) For use with HTTPS - the private key that the service should use. (For Cortex XSOAR 8 and Cortex XSIAM) When using an engine, configure a private API key False

Server configuration (XSOAR 6.x)

In the Server Configuration section, verify that the value for the instance.execute.external.INTEGRATION-INSTANCE-NAME key is set to true. If this key does not exist:

  1. Click + Add Server Configuration.
  2. Add instance.execute.external.INTEGRATION-INSTANCE-NAME and set the value to true.

XSOAR endpoint URL-

  • For Cortex XSOAR 6.x: <CORTEX-XSOAR-URL>/instance/execute/<INTEGRATION-INSTANCE-NAME>. For example, https://my.demisto.live/instance/execute/zoom. Note that the string instance does not refer to the name of your XSOAR instance, but rather is part of the URL.
  • For Cortex XSOAR 8.x / XSIAM: you need to run using external engine: https://<Engine URL>:<port>. For example, https://my-engine-url:7001.

Create Zoom ChatBOT app

  1. Log onto the Zoom App Marketplace: https://marketplace.zoom.us/.
  2. Click Develop > Build App.
  3. Choose General App.
  4. Click Create.

enter image description here

Configure App Settings

  1. Update your app’s name. By default, the build flow generates a generic name for your app. To change your app’s name, select the edit icon (pencil) and update the name. To save your changes, click anywhere outside of the app name field.
  2. Under the section “Select how the app is managed”, select “Admin-managed”, and click “Save”.
  3. Enter your Cortex XSOAR endpoint URL in the OAuth Redirect URL.
  4. Click Features > Surface > Team Chat.
    Toggle on the “Team Chat Subscription” section. Under “Bot Endpoint URL”, add:
    • For Cortex XSOAR 6.x: <CORTEX-XSOAR-URL>/instance/execute/<INTEGRATION-INSTANCE-NAME>. For example, https://my.demisto.live/instance/execute/zoom. Note that the string instance does not refer to the name of your Cortex XSOAR instance, but rather is part of the URL.
    • For Cortex XSOAR 8.x / XSIAM you need to run using external engine: https://<Engine Url>:<port>. For example, https://my-engine-url:7001.

enter image description here

  1. Click Scopes > + Add Scopes to add the following scope permissions.

    Scope Type Scope Name
    Team Chat /imchat:bot
    Team Chat /team_chat:read:user_message:admin
    Team Chat /team_chat:read:list_user_sessions:admin
    Team Chat /team_chat:read:list_user_messages:admin
    Team Chat /team_chat:write:user_channel:admin
    Team Chat /team_chat:write:members:admin
    Team Chat /team_chat:update:user_channel:admin
    User /user:read:user:admin

enter image description here

  1. Click Local Test > Add App Now to test your app and authorize your Cortex XSOAR app.

  2. If mirroring is enabled in the integration configuration or using ZoomAsk:

    • Endpoint URL Requirements:
      According to the Zoom requirements in order to receive webhooks, the Event notification endpoint URL that you specify for each event subscription must:
      • Be a publicly accessible https endpoint url that supports TLSv1.2+ with a valid certificate chain issued by a Certificate Authority (CA).
      • Employ the https:// scheme.
      • Be able to accept HTTP POST requests containing JSON payloads.
      • Be a fully qualified domain name (FQDN).
      • be able to respond with an HTTP Status Code.
    • Zoom Configurations:

      1. Copy the Secret Token from the “Features” > “Access” page under the “Token” section and add it to the instance configuration. enter image description here
      2. Configure Event Subscriptions.
      3. In the “Features” section, under “Access”, in the “General Features” section, enable “Event Subscription”.
      4. Click +Add New Event Subscription.
      5. Enter the following information:
        • Subscription name: Enter a name for this Event Subscription (e.g., “Send Message Sent”)
        • Add Events: Click +Add Events. Under Event Types, select Chat Message, and then select Chat Message Sent.
        • Event notification endpoint URL: Enter the Cortex XSOAR URL of your server (CORTEX-XSOAR-URL/instance/execute/INTEGRATION-INSTANCE-NAME) where you want to receive event notifications. This URL should handle incoming event data from Zoom. Make sure it’s publicly accessible.
        • Authentication Header Option -
          1. Default Header Provided by Zoom option - This option allows you to use a verification token provided by Zoom. Copy the Verification Token under the “Token” section and add it to the instance configuration.
            enter image description here

          2. Basic Authentication option - You can use Basic Authentication by providing your Zoom Client ID (OAuth) and Secret ID (OAuth) as configured in the instance configuration.
            enter image description here

        enter image description here

Commands

You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.

zoom-create-user


Create a new user in zoom account

Base Command

zoom-create-user

Input

Argument Name Description Required
first_name First name of the new user. Required
last_name Last name of the new user. Required
email The email of the new user. Required
user_type The type of the newly created user. Note: the old type “pro” in now called “Licensed”, and the type “Corporate” is not sopprted in Zoom v2 and above.. Possible values are: Basic, Licensed, pro, Corporate. Default is Basic. Optional

Context Output

Path Type Description
Zoom.User.id string The ID of the created user
Zoom.User.first_name string First name of the created user
Zoom.User.last_name string Last name for the created user
Zoom.User.email string Email of the created user
Zoom.User.created_at date Created date of the user. Note that this field does not appear in zoom v2 and above.
Zoom.User.type number The type of the user

Command example

!zoom-create-user email=example@example.com first_name=john last_name=smith user_type=Basic

Context Example

{
    "Zoom": {
        "User": {
            "email": "example@example.com",
            "first_name": "john",
            "id": "wSQafNLNSJWq_oBzmT7XOw",
            "last_name": "smith",
            "type": 1
        }
    }
}

Human Readable Output

User created successfully with ID: wSQafNLNSJWq_oBzmT7XOw

zoom-create-meeting


Create a new zoom meeting (scheduled ,instant, or recurring)

Base Command

zoom-create-meeting

Input

Argument Name Description Required
type The type of the meeting. Possible values are: Instant, Scheduled, Recurring meeting with fixed time. Default is Instant. Required
end_date_time For recurring meetings only. Select the final date on which the meeting will recur before it is canceled. For example: 2017-11-25T12:00:00Z. Optional
end_times For recurring meetings only.Select how many times the meeting should recur before it is canceled. max = 365. Default = 1.. Optional
monthly_day For recurring meetings with Monthly recurrence_type only. State the day in a month the meeting should recur. The value range is from 1 to 31. Default = 1.. Optional
monthly_week For recurring meetings with Monthly recurrence_type only.State the week of the month when the meeting should recur. If you use this field, you must also use the monthly_week_day field to state the day of the week when the meeting should recur. Allowed: -1 (for last week of the month) ┃1┃2┃3┃4. Optional
monthly_week_day For recurring meetings with Monthly recurrence_type only. State a specific day in a week when the monthly meeting should recur. Allowed: 1┃2┃3┃4┃5┃6┃7To use this field, you must also use the monthly_week field.. Optional
repeat_interval For recurring meeting with fixed time only. Define the interval at which the meeting should recur. For instance, if you would like to schedule a meeting that recurs every two months, you must set the value of this field as 2 and the value of the type parameter as Monthly. For a daily meeting, the maximum is 90 days. For a weekly meeting the maximum is of 12 weeks. For a monthly meeting, there is a maximum of 3 months. Optional
recurrence_type For recurring meetings only. Set the recurrence meeting types.. Possible values are: Daily, Weekly, Monthly. Optional
weekly_days For recurring meetings with a Weekly recurrence_type only. State a specific day in a week when the weekly meeting should recur. Allowed: 1┃2┃3┃4┃5┃6┃7 Default = 1.. Optional
auto-record-meeting The automatic recording settings. Note that the Cloud option is available for Zoom paid customers only. Possible values are: local, cloud, none. Default is none. Optional
encryption_type The type of end-to-end (E2EE) encryption, enhanced_encryption or e2ee. Possible values are: enhanced_encryption, e2ee. Default is enhanced_encryption. Optional
host_video start meetings with the host video on. Possible values are: true, false. Default is True. Optional
join_before_host_time If the value of the join_before_host field is true, this field sets the time that a participant can join before the meeting’s host. You can choose: 5 or 10 (minutes), or 0 for any time. Possible values are: 0, 5, 10. Optional
join_before_host Whether participants can join the meeting before its host. For scheduled or recurring meetings only. The default value is False. Possible values are: false, true. Optional
meeting_authentication If true, only authenticated users can join the meeting. Possible values are: false, true. Default is false. Optional
user email address or id of user for meeting. Required
topic The topic of the meeting. Required
waiting_room This allows the host to control when a participant joins the meeting. The default is False. Possible values are: false, true. Optional
start-time Meeting start time. When using a format like “yyyy-MM-ddTHH:mm:ssZ”, always use GMT time. When using a format like “yyyy-MM-ddTHH:mm:ss”, you should use local time and you will need to specify the time zone. Only used for scheduled meetings and recurring meetings with fixed time. Optional
timezone Timezone to format start_time. For example, “America/Los_Angeles”. For scheduled meetings only. . Optional

Context Output

Path Type Description
Zoom.Meeting.join_url string Join url for the meeting
Zoom.Meeting.id string Meeting id of the new meeting that is created
Zoom.Meeting.start_url string The URL to start the meeting
Zoom.Meeting.uuid string Unique meeting ID of the new meeting that is created
Zoom.Meeting.status string The status of the meeting
Zoom.Meeting.start_time Date The time that the meeting will start at
Zoom.Meeting.host email string The email of the host of this meeting
Zoom.Meeting.topic string The topic of the meeting
Zoom.Meeting.duration number The duratian of the meeting
Zoom.Meeting.created_at Date The time that this meeting was created
Zoom.Meeting.type number The type of the new meeting, Instant = 1, Scheduled =2,Recurring with fixed time = 8

Command example

!zoom-create-meeting topic=test type=scheduled user=example@example.com start-time=2023-01-29T12:12:12Z

Context Example

{
    "Zoom": {
        "Meeting": {
            "created_at": "2023-01-15T12:44:30Z",
            "duration": 60,
            "host_email": "example@example.com",
            "host_id": "uJiZN-O7Rp6Jp_995FpZGg",
            "id": 88454393857,
            "join_url": "https://us06web.zoom.us/j/8845?pwd=WkI1WUdvbHhnMlJuaXU1WDNPdz09",
            "pre_schedule": false,
            "settings": {
                "allow_multiple_devices": false,
                "alternative_host_update_polls": false,
                "alternative_hosts": "",
                "alternative_hosts_email_notification": true,
                "approval_type": 2,
                "approved_or_denied_countries_or_regions": {
                    "enable": false
                },
                "audio": "both",
                "auto_recording": "none",
                "breakout_room": {
                    "enable": false
                },
                "close_registration": false,
                "cn_meeting": false,
                "device_testing": false,
                "email_notification": true,
                "enable_dedicated_group_chat": false,
                "encryption_type": "enhanced_encryption",
                "enforce_login": false,
                "enforce_login_domains": "",
                "focus_mode": false,
                "global_dial_in_countries": [
                    "US"
                ],
                "global_dial_in_numbers": [
                    {
                        "city": "Houston",
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 3462487799",
                        "type": "toll"
                    },
                    {
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 3602095623",
                        "type": "toll"
                    },
                    {
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 3863475053",
                        "type": "toll"
                    },
                    {
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 5074734847",
                        "type": "toll"
                    },
                    {
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 5642172000",
                        "type": "toll"
                    },
                    {
                        "city": "New York",
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 6465588656",
                        "type": "toll"
                    },
                    {
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 6469313860",
                        "type": "toll"
                    },
                    {
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 6694449171",
                        "type": "toll"
                    },
                    {
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 6892781000",
                        "type": "toll"
                    },
                    {
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 7193594580",
                        "type": "toll"
                    },
                    {
                        "city": "Denver",
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 7207072699",
                        "type": "toll"
                    },
                    {
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 2532050468",
                        "type": "toll"
                    },
                    {
                        "city": "Tacoma",
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 2532158782",
                        "type": "toll"
                    },
                    {
                        "city": "Washington DC",
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 3017158592",
                        "type": "toll"
                    },
                    {
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 3052241968",
                        "type": "toll"
                    },
                    {
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 3092053325",
                        "type": "toll"
                    },
                    {
                        "city": "US",
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 3126266799",
                        "type": "toll"
                    }
                ],
                "host_save_video_order": false,
                "host_video": true,
                "in_meeting": false,
                "jbh_time": 0,
                "join_before_host": false,
                "meeting_authentication": false,
                "mute_upon_entry": false,
                "participant_video": false,
                "private_meeting": false,
                "registrants_confirmation_email": true,
                "registrants_email_notification": true,
                "request_permission_to_unmute_participants": false,
                "show_share_button": false,
                "use_pmi": false,
                "waiting_room": false,
                "watermark": false
            },
            "start_time": "2023-01-29T12:12:12Z",
            "start_url": "https://us06web.zoom.us/s/883857?zIjAwMDAwMSIsInptX3NrbSI6InptX28ybSIsImFsZyI6IkhTMjU2In0.eyJhdWQiOiJjbGllbnRzbSIsInVpZCI6InVKaVpOLU83UnA2SnBfOTk1RnBaR2ciLCJpc3MiOiJ3ZWIiLCJzayI6IjczMjU5NTExMTgxNDYyODc0NjciLCJzdHkiOjEwMCwid2NkIjoidXMwNiIsImNsdCI6MCwibW51bSI6Ijg4NDU0MzkzODU3IiwiZXhwIjoxNjczNzkzODcwLCJpYXQiOjE2NzM3ODY2NzAsImFpZCI6ImFlS0QyQkZKUkFTdDFRVlVSV285Q0EiLCJjaWQiOiIifQ.5vRJBkMbmODUD_7H3bkS7OjR-MuuLUzNMJ_KeCzWc_U",
            "status": "waiting",
            "timezone": "Asia/Jerusalem",
            "topic": "test",
            "type": 2,
            "uuid": "4gbib+fjTFmz1wH1LoE7EQ=="
        }
    }
}

Human Readable Output

Meeting details

uuid id host_id host_email topic type status start_time duration timezone created_at start_url join_url
4gbib+fjTFmz1wH1LoE7EQ== 88454393857 uJiZN-O7Rp6Jp_995FpZGg example@example.com test 2 waiting 2023-01-29T12:12:12Z 60 Asia/Jerusalem 2023-01-15T12:44:30Z https://us06web.zoom.us/s/88454393857?zak=eyJ0eXAiOiJKV1QiLCJzdiI6IjAwMDAwMSIsInptX3NrbSI6InptX28ybSIsImFsZyI6IkhTMjU2In0.eyJhdWQiOiJjbGllbnRzbSIsInVpZCI6InVKaVpOLU83UnA2SnBfOTk1RnBaR2ciLCJpc3MiOiJ3ZWIiLCJzayI6IjczMjU5NTExMTgxNDYyODc0NjciLCJzdHkiOjEwMCwid2NkIjoidXMwNiIsImNsdCI6MCwibW51bSI6Ijg4NDU0MzkzODU3IiwiZXhwIjoxNjczNzkzODcwLCJpYXQiOjE2NzM3ODY2NzAsImFpZCI6ImFlS0QyQkZKUkFTdDFRVlVSV285Q0EiLCJjaWQiOiIifQ.5vRJBkMbmODUD_7H3bkS7OjR-MuuLUzNMJ_KeCzWc_U https://us06web.zoom.us/j/88454393857?pwd=WkI1WnVEWUdvbHhnMlJuaXU1WDNPdz09

zoom-fetch-recording


Get meeting record and save as file in the warroom

Base Command

zoom-fetch-recording

Input

Argument Name Description Required
meeting_id Meeting ID of the recorded meeting. Required
delete_after Whether to delete the recording from the cloud after downloading. Possible values are: false, true. Default is true. Optional

Context Output

Path Type Description
File.SHA256 Unknown Attachment’s SHA256
File.SHA1 Unknown Attachment’s SHA1
File.MD5 Unknown Attachment’s MD5
File.Name Unknown Attachment’s Name
File.Info Unknown Attachment’s Info
File.Size Unknown Attachment’s Size (In Bytes)
File.Extension Unknown Attachment’s Extension
File.Type Unknown Attachment’s Type
File.EntryID Unknown Attachment’s EntryID
File.SSDeep Unknown Attachment’s SSDeep hash

Command example

!zoom-fetch-recording meeting_id=83622325727 delete_after=false

Context Example

{
    "File": [
        {
            "EntryID": "446@37e93103-1bd6-4776-8021-0f7023b1bb79",
            "Extension": "MP4",
            "Info": "video/mp4",
            "MD5": "0de01f8f6d037e9ebecde2f91ad9b7a3",
            "Name": "recording_83622325727_d831fbd5-3938-44d0-b30b-962bf76e2916.MP4",
            "SHA1": "c81f9abb6dcf9be42dae99bc5e1501c43496d66e",
            "SHA256": "8b252b01c8e6af62b88de64abf80d360467da1598dcd6b50ac9a252ffafb2eb5",
            "SHA512": "b273e90a9cd0589eaba1c5e647fedab7b46e198193a54bec70a18def9ada57575833ea89b6eabf7f5852c3dc98b862780793d3e87e32a238ec2a7acffdba2495",
            "SSDeep": "1536:TDWnSNbM8oEWzjSn7anYBcoGdee32hfUunvSHx8:T6t8JWzjSWnYBcoG9325UunvSHq",
            "Size": 320333,
            "Type": "ISO Media, MP4 v2 [ISO 14496-14]"
        },
        {
            "EntryID": "447@37e93103-1bd6-4776-8021-0f7023b1bb79",
            "Extension": "M4A",
            "Info": "video/mp4",
            "MD5": "e826111564499ca8021d0ddfcfde064b",
            "Name": "recording_83622325727_19bf5f8a-e77c-4b75-b09e-13983521703c.M4A",
            "SHA1": "50d3386dc5b74935b8f8d541f319df34a49f90a0",
            "SHA256": "2719528cf61358ccbee861fb8e42d9d5fb37390baa22d0dc7dad1aa7e3935146",
            "SHA512": "74bfb40ade824e6e36329b3e2335b2028fac648d3ecef1a02e9be93d4a455e3acf4c1f9c844d1c2ebcc661d4c84d66c1da4f0ca0462eabc12bf2dff84006d460",
            "SSDeep": "24:fctSXvr4S+08n11/TlllZltk2B0tDilduxEJvCXyxrApd4dEcpXuFxnZQ4r:uYr41Xnf/T/vX/8OvqyrjiCuFhZQK",
            "Size": 243652,
            "Type": "ISO Media, MP4 v2 [ISO 14496-14]"
        }
    ]
}

Human Readable Output

The Audio file recording_83622325727_19bf5f8a-e77c-4b75-b09e-13983521703c.M4A was downloaded successfully

zoom-list-users


List the existing users

Base Command

zoom-list-users

Input

Argument Name Description Required
status Which status of users to list. Possible values are: active, inactive, pending. Default is active. Optional
page-size Number of users to return. Max 300. The default is 30. Optional
next_page_token The next page token is used to get the next page. IMPORTANT: You must pass the same page size that you passed in the first call. Optional
page-number Which page of results to return. The default = 1. Note: This argument is in a deprecate process by the API. As an alternative use “next_page_token” or “limit”.. Optional
limit The total amunt of results to show. Optional
user_id A user ID. this is for a singel user. Optional
role_id Filter the response by a specific role. For example: role_id=0 (Owner), role_id=2 (Member). Optional

Context Output

Path Type Description
Zoom.Metadata.Count number Total page count available
Zoom.Metadata.Number number Current page number
Zoom.Metadata.Size number Number of results in current page
Zoom.Metadata.Total number Total number of records
Zoom.User.id string ID of the user
Zoom.User.first_name string First name of user
Zoom.User.last_name string Last name of user
Zoom.User.email string Email of user
Zoom.User.type number Type of user
Zoom.User.created_at date Date when user was created
Zoom.User.dept string Department for user
Zoom.User.verified number Is the user verified
Zoom.User.last_login_time date Last login time of the user
Zoom.User.timezone string Default timezone for the user
Zoom.User.pmi string PMI of user
Zoom.User.group_ids string Groups user belongs to

Command example

!zoom-list-users status=pending limit=10

Context Example

{
    "Zoom": {
        "Metadata": {
            "Count": 6,
            "Number": 1,
            "Size": 10,
            "Total": 59
        },
        "User": [
            {
                "created_at": "2023-01-15T12:44:34Z",
                "email": "example@example.com",
                "id": "",
                "pmi": 0,
                "role_id": "0",
                "status": "pending",
                "type": 1,
                "user_created_at": "2023-01-02T12:55:33Z",
                "verified": 0
            },
            {
                "created_at": "2023-01-15T12:44:34Z",
                "email": "example@example.com",
                "id": "",
                "pmi": 0,
                "role_id": "0",
                "status": "pending",
                "type": 1,
                "user_created_at": "2023-01-02T13:09:28Z",
                "verified": 0
            },
            {
                "created_at": "2023-01-15T12:44:34Z",
                "email": "example@example.com",
                "id": "",
                "pmi": 0,
                "role_id": "0",
                "status": "pending",
                "type": 1,
                "user_created_at": "2022-12-22T10:19:47Z",
                "verified": 0
            },
            {
                "created_at": "2023-01-15T12:44:34Z",
                "email": "example@example.com",
                "id": "",
                "pmi": 0,
                "role_id": "0",
                "status": "pending",
                "type": 1,
                "user_created_at": "2023-01-02T13:12:46Z",
                "verified": 0
            },
            {
                "created_at": "2023-01-15T12:44:34Z",
                "email": "example@example.com",
                "id": "",
                "pmi": 0,
                "role_id": "0",
                "status": "pending",
                "type": 1,
                "user_created_at": "2023-01-02T12:04:08Z",
                "verified": 0
            },
            {
                "created_at": "2023-01-15T12:44:34Z",
                "email": "example@example.com",
                "id": "",
                "pmi": 0,
                "role_id": "0",
                "status": "pending",
                "type": 1,
                "user_created_at": "2023-01-02T12:56:08Z",
                "verified": 0
            },
            {
                "created_at": "2023-01-15T12:44:34Z",
                "email": "example@example.com",
                "id": "",
                "pmi": 0,
                "role_id": "0",
                "status": "pending",
                "type": 1,
                "user_created_at": "2023-01-02T12:58:16Z",
                "verified": 0
            },
            {
                "created_at": "2023-01-15T12:44:34Z",
                "email": "example@example.com",
                "id": "",
                "pmi": 0,
                "role_id": "0",
                "status": "pending",
                "type": 1,
                "user_created_at": "2023-01-02T13:15:04Z",
                "verified": 0
            },
            {
                "created_at": "2023-01-15T12:44:34Z",
                "email": "example@example.com",
                "id": "",
                "pmi": 0,
                "role_id": "0",
                "status": "pending",
                "type": 1,
                "user_created_at": "2023-01-02T11:58:04Z",
                "verified": 0
            },
            {
                "created_at": "2023-01-15T12:44:34Z",
                "email": "example@example.com",
                "id": "",
                "pmi": 0,
                "role_id": "0",
                "status": "pending",
                "type": 1,
                "user_created_at": "2023-01-02T13:09:52Z",
                "verified": 0
            }
        ]
    }
}

Human Readable Output

Users

id email type pmi verified created_at status role_id
  example@example.com 1 0 0 2023-01-15T12:44:34Z pending 0
  example@example.com 1 0 0 2023-01-15T12:44:34Z pending 0
  example@example.com 1 0 0 2023-01-15T12:44:34Z pending 0
  example@example.com 1 0 0 2023-01-15T12:44:34Z pending 0
  example@example.com 1 0 0 2023-01-15T12:44:34Z pending 0
  example@example.com 1 0 0 2023-01-15T12:44:34Z pending 0
  example@example.com 1 0 0 2023-01-15T12:44:34Z pending 0
  example@example.com 1 0 0 2023-01-15T12:44:34Z pending 0
  example@example.com 1 0 0 2023-01-15T12:44:34Z pending 0
  example@example.com 1 0 0 2023-01-15T12:44:34Z pending 0

Metadata

total_records
59

zoom-delete-user


Delete a user from Zoom

Base Command

zoom-delete-user

Input

Argument Name Description Required
user The user ID or email to delete. Required
action The action to take. Possible values are: disassociate, delete. Default is disassociate. Optional

Context Output

There is no context output for this command.

zoom-meeting-get


Get the information of an existing zoom meeting

Base Command

zoom-meeting-get

Input

Argument Name Description Required
meeting_id The id of the existing meeting. Required
occurrence_id Provide this field to view meeting details of a particular occurrence of the recurring meeting. Optional
show_previous_occurrences Set the value of this field to true if you would like to view meeting details of all previous occurrences of a recurring meeting. Possible values are: false, true. Default is True. Optional

Context Output

Path Type Description
Zoom.Meeting.join_url string Join url for the meeting
Zoom.Meeting.id string Meeting id of the new meeting that is created
Zoom.Meeting.start_url string The URL to start the meeting
Zoom.Meeting.uuid string Unique meeting ID of the new meeting that is created
Zoom.Meeting.status string The status of the meeting
Zoom.Meeting.start_time Date The time that the meeting will start at
Zoom.Meeting.host email string The email of the host of this meeting
Zoom.Meeting.topic string The topic of the meeting
Zoom.Meeting.duration number The duratian of the meeting
Zoom.Meeting.created_at Date The time that this meeting was created
Zoom.Meeting.type number The type of the new meeting, Instant = 1, Scheduled =2,Recurring with fixed time = 8

Command example

!zoom-meeting-get meeting_id=88949894296

Context Example

{
    "Zoom": {
        "Meeting": {
            "agenda": "",
            "assistant_id": "",
            "created_at": "2022-12-29T08:10:13Z",
            "duration": 60,
            "host_email": "example@example.com",
            "host_id": "uJiZN-O7Rp6Jp_995FpZGg",
            "id": 88949894296,
            "join_url": "https://us06web.zoom.us/94296?pwd=b3GdrSDBBNU1FYTVRVmdadz09",
            "pre_schedule": false,
            "settings": {
                "allow_multiple_devices": false,
                "alternative_host_update_polls": false,
                "alternative_hosts": "",
                "alternative_hosts_email_notification": true,
                "approval_type": 2,
                "approved_or_denied_countries_or_regions": {
                    "enable": false
                },
                "audio": "both",
                "auto_recording": "none",
                "breakout_room": {
                    "enable": false
                },
                "close_registration": false,
                "cn_meeting": false,
                "device_testing": false,
                "email_notification": true,
                "enable_dedicated_group_chat": false,
                "encryption_type": "enhanced_encryption",
                "enforce_login": false,
                "enforce_login_domains": "",
                "focus_mode": false,
                "global_dial_in_countries": [
                    "US"
                ],
                "global_dial_in_numbers": [
                    {
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 6469313860",
                        "type": "toll"
                    },
                    {
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 6694449171",
                        "type": "toll"
                    },
                    {
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 6892781000",
                        "type": "toll"
                    },
                    {
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 7193594580",
                        "type": "toll"
                    },
                    {
                        "city": "Denver",
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 7207072699",
                        "type": "toll"
                    },
                    {
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 2532050468",
                        "type": "toll"
                    },
                    {
                        "city": "Tacoma",
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 2532158782",
                        "type": "toll"
                    },
                    {
                        "city": "Washington DC",
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 3017158592",
                        "type": "toll"
                    },
                    {
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 3052241968",
                        "type": "toll"
                    },
                    {
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 3092053325",
                        "type": "toll"
                    },
                    {
                        "city": "US",
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 3126266799",
                        "type": "toll"
                    },
                    {
                        "city": "Houston",
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 3462487799",
                        "type": "toll"
                    },
                    {
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 3602095623",
                        "type": "toll"
                    },
                    {
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 3863475053",
                        "type": "toll"
                    },
                    {
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 5074734847",
                        "type": "toll"
                    },
                    {
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 5642172000",
                        "type": "toll"
                    },
                    {
                        "city": "New York",
                        "country": "US",
                        "country_name": "US",
                        "number": "+1 6465588656",
                        "type": "toll"
                    }
                ],
                "host_save_video_order": false,
                "host_video": true,
                "in_meeting": false,
                "jbh_time": 0,
                "join_before_host": false,
                "meeting_authentication": false,
                "mute_upon_entry": false,
                "participant_video": false,
                "private_meeting": false,
                "registrants_confirmation_email": true,
                "registrants_email_notification": true,
                "request_permission_to_unmute_participants": false,
                "show_share_button": false,
                "use_pmi": false,
                "waiting_room": false,
                "watermark": false
            },
            "start_time": "2022-12-29T12:12:12Z",
            "start_url": "https://us06web.zoom.us/s/88949?zak=eyJ0eXAiOiJKV1QiLCJzdiI6IjAwMDAwMSIsInptX3NrbSI6InVKaVpOLU83UnA2SnBfOTk1RnBaR2ciLCJpc3MiOiJ3ZWIiLCJzayI6IjczMjU5NTExMTgxNDYyODc0NjciLCJzdHkiOjEwMCwid2NkIjoidXMwNiIsImNsdCI6MCwibW51bSI6Ijg4OTQ5ODk0Mjk2IiwiZXhwIjoxNjczNzkzODc2LCJpYXQiOjE2NzM3ODY2NzYsImFpZCI6ImFlS0QyQkZKUkFTdDFRVlVSV285Q0EiLCJjaWQiOiIifQ.BTOeH_-MZRm7A5sACnDJrP_zKbzaDCWZ5orvtH4rVb0",
            "status": "waiting",
            "timezone": "Asia/Jerusalem",
            "topic": "test",
            "type": 2,
            "uuid": "anhEx2x6QWG7TREn71MmoA=="
        }
    }
}

Human Readable Output

Meeting details

uuid id host_id host_email topic type status start_time duration timezone agenda created_at start_url join_url
anhEx2x6QWG7TREn71MmoA== 88949894296 uJiZN-O7Rp6Jp_995FpZGg example@example.com test 2 waiting 2022-12-29T12:12:12Z 60 Asia/Jerusalem   2022-12-29T08:10:13Z https://us06web.zoom.us/s/88949894296?zak=eyJ0eXAiOiJKV1QiLCJzdiI6IjAwMDAwMSIsInptX3NrbSI6InptX28ybSIsImFsZyI6IkhTMjU2In0.eyJhdWQiOiJjbGllbnRzbSIsInVpZCI6InVKaVpOLU83UnA2SnBfOTk1RnBaR2ciLCJpc3MiOiJ3ZWIiLCJzayI6IjczMjU5NTExMTgxNDYyODc0NjciLCJzdHkiOjEwMCwid2NkIjoidXMwNiIsImNsdCI6MCwibW51bSI6Ijg4OTQ5ODk0Mjk2IiwiZXhwIjoxNjczNzkzODc2LCJpYXQiOjE2NzM3ODY2NzYsImFpZCI6ImFlS0QyQkZKUkFTdDFRVlVSV285Q0EiLCJjaWQiOiIifQ.BTOeH_-MZRm7A5sACnDJrP_zKbzaDCWZ5orvtH4rVb0 https://us06web.zoom.us/j/88949894296?pwd=b3dzT1pzWGdrSDBBNU1FYTVRVmdadz09

zoom-meeting-list


Show all the meetings of a given user. Note: only scheduled and unexpired meetings will appear.

Base Command

zoom-meeting-list

Input

Argument Name Description Required
user_id The user ID of the meetings owner. Required
page_size Number of users to return. Default = 30. Max = 300. Optional
page_number Which page of results to return. The default = 1. Note: This argument is in a deprecate process by the API. As an alternative use “next_page_token” or “limit”. Optional
next_page_token The next page token is used to paginate te the next page. IMPORTENT: You must pass the same page size that you pased at the first call.. Optional
limit The total amunt of results to show. Optional
type Filter the results by searching specific types. Possible values are: all, scheduled, live, upcoming, upcoming_meetings, previous_meetings. Default is “scheduled”. Optional

Context Output

Path Type Description
Zoom.Metadata.Total number Total number of records
Zoom.Meeting.page_size number The size of the page returned from the API
Zoom.Meeting.total_records number The total records in the API for this request.
Zoom.Meeting.join_url string Join url for the meeting
Zoom.Meeting.id string Meeting id of the new meeting that is created
Zoom.Meeting.start_url string The URL to start the meeting
Zoom.Meeting.uuid string Unique meeting ID of the new meeting that is created
Zoom.Meeting.status string The status of the meeting
Zoom.Meeting.start_time Date The time that the meeting will start at
Zoom.Meeting.host email string The email of the host of this meeting
Zoom.Meeting.topic string The topic of the meeting
Zoom.Meeting.duration number The duratian of the meeting
Zoom.Meeting.created_at Date The time that this meeting was created
Zoom.Meeting.type unknown The ty pe of this meeting

Command example

!zoom-meeting-list user_id=example@example.com type=scheduled limit=7

Context Example

{
    "Zoom": {
        "Meeting": {
            "meetings": [
                {
                    "created_at": "2022-12-04T10:41:27Z",
                    "duration": 60,
                    "host_id": "uJiZN-O7Rp6Jp_995FpZGg",
                    "id": 83810397585,
                    "join_url": "https://us06web.zoom.us/j/83810397585?pwd=OGFiZjVvMWZzdDBoaXlLdz09",
                    "start_time": "2022-12-10T11:00:00Z",
                    "timezone": "Asia/Jerusalem",
                    "topic": "2",
                    "type": 8,
                    "uuid": "z93Dc6Kj3jx+zaYg=="
                },
                {
                    "created_at": "2022-12-06T07:59:02Z",
                    "duration": 60,
                    "host_id": "uJiZN-O7Rp6Jp_995FpZGg",
                    "id": 84540166459,
                    "join_url": "https://us06web.zoom.us/j/84540166459?pwd=ZzZaaVpFYlBVYnFoUT09",
                    "start_time": "2022-12-12T08:00:00Z",
                    "timezone": "Asia/Jerusalem",
                    "topic": "My recurring Meeting -Dima",
                    "type": 8,
                    "uuid": "4kZQ+HlFOAz0VBPHoCYg=="
                },
                {
                    "created_at": "2022-12-27T21:05:41Z",
                    "duration": 60,
                    "host_id": "uJiZN-O7Rp6Jp_995FpZGg",
                    "id": 89824497327,
                    "join_url": "https://us06web.zoom.us/j/89824497327?pwd=SWp3b3VDRVhmQT09",
                    "start_time": "2022-12-27T21:05:00Z",
                    "timezone": "Asia/Jerusalem",
                    "topic": "efe",
                    "type": 8,
                    "uuid": "RABXy2D4hA1rgpDgQ=="
                },
                {
                    "created_at": "2022-12-27T21:11:01Z",
                    "duration": 60,
                    "host_id": "uJiZN-O7Rp6Jp_995FpZGg",
                    "id": 83245658341,
                    "join_url": "https://us06web.zoom.us/j/83245658341?pwd=SmNGMHI0RDNkZ2Yms3Zz09",
                    "start_time": "2022-12-27T21:11:00Z",
                    "timezone": "Asia/Jerusalem",
                    "topic": "efe",
                    "type": 8,
                    "uuid": "qOXvloSamJjjFaFgniTA=="
                },
                {
                    "created_at": "2022-12-27T21:25:54Z",
                    "duration": 60,
                    "host_id": "uJiZN-O7Rp6Jp_995FpZGg",
                    "id": 88468901206,
                    "join_url": "https://us06web.zoom.us/j/88468901206?pwd=RXZYQlWCtpS3l1MHUxZz09",
                    "start_time": "2022-12-27T21:25:00Z",
                    "timezone": "Asia/Jerusalem",
                    "topic": "efe",
                    "type": 8,
                    "uuid": "yHzCvl4Sry+C9LnCwdnwQ=="
                },
                {
                    "created_at": "2022-12-28T06:39:48Z",
                    "duration": 60,
                    "host_id": "uJiZN-O7Rp6Jp_995FpZGg",
                    "id": 87525048161,
                    "join_url": "https://us06web.zoom.us/j/87525048161?pwd=ZXlV3U0OUxxSlBkdz09",
                    "start_time": "2022-12-28T06:39:00Z",
                    "timezone": "Asia/Jerusalem",
                    "topic": "efe",
                    "type": 8,
                    "uuid": "Sblh/S1W+rTKUcojJjw=="
                },
                {
                    "created_at": "2022-12-28T06:42:25Z",
                    "duration": 60,
                    "host_id": "uJiZN-O7Rp6Jp_995FpZGg",
                    "id": 83877839723,
                    "join_url": "https://us06web.zoom.us/j/83877839723?pwd=WySkY4Zkc4Zz09",
                    "start_time": "2022-12-28T06:42:00Z",
                    "timezone": "Asia/Jerusalem",
                    "topic": "efe",
                    "type": 8,
                    "uuid": "iLXDe4HsR6uMb+x8GyybTA=="
                }
            ],
            "next_page_token": "N58N4bhqiBFapzndJocx6cc8NKr2",
            "page_size": 7,
            "total_records": 60
        },
        "Metadata": {
            "Size": 7,
            "Total": 60
        }
    }
}

Human Readable Output

Meeting list

uuid id host_id topic type start time duration timezone created_at join_url
z93Dc6KjSo20Wr3jx+zaYg== 83810397585 uJiZN-O7Rp6Jp_995FpZGg 2 8   60 Asia/Jerusalem 2022-12-04T10:41:27Z https://us06web.zoom.us/j/83810397585?pwd=OGFiZjRYNGhwWkVvMWZzdDBoaXlLdz09
4kZQ+Hl2RFOAz0VBPHoCYg== 84540166459 uJiZN-O7Rp6Jp_995FpZGg My recurring Meeting -Dima 8   60 Asia/Jerusalem 2022-12-06T07:59:02Z https://us06web.zoom.us/j/84540166459?pwd=ZzdmUEJ5QkZaaUZaaVpFYlBVYnFoUT09
RABXyk81T02D4hA1rgpDgQ== 89824497327 uJiZN-O7Rp6Jp_995FpZGg efe 8   60 Asia/Jerusalem 2022-12-27T21:05:41Z https://us06web.zoom.us/j/89824497327?pwd=SWpvK0I0L3pQcTNnWlF3b3VDRVhmQT09
qOXvlLOoSamJjjFaFgniTA== 83245658341 uJiZN-O7Rp6Jp_995FpZGg efe 8   60 Asia/Jerusalem 2022-12-27T21:11:01Z https://us06web.zoom.us/j/83245658341?pwd=SmNGMHI0R1hndnNlRXRDNkZ2Yms3Zz09
yHzCvl4USry+C9LnCwdnwQ== 88468901206 uJiZN-O7Rp6Jp_995FpZGg efe 8   60 Asia/Jerusalem 2022-12-27T21:25:54Z https://us06web.zoom.us/j/88468901206?pwd=RXZYQlhVbWJKZ1pLWCtpS3l1MHUxZz09
Sblh/I34S1W+rTKUcojJjw== 87525048161 uJiZN-O7Rp6Jp_995FpZGg efe 8   60 Asia/Jerusalem 2022-12-28T06:39:48Z https://us06web.zoom.us/j/87525048161?pwd=ZXlXdXl0QWlLOFVyV3U0OUxxSlBkdz09
iLXDe4HsR6uMb+x8GyybTA== 83877839723 uJiZN-O7Rp6Jp_995FpZGg efe 8   60 Asia/Jerusalem 2022-12-28T06:42:25Z https://us06web.zoom.us/j/83877839723?pwd=WU9xNmp5RW5KRDhsZ1RySkY4Zkc4Zz09

Metadata

total_records
60

Command example

Human Readable Output

Channels

Channel ID Channel JID Channel name Channel type
f7ce414a24634240ae0a7894823d8707 f7ce414a24634240ae0a7894823d8707@conference.xmpp.zoom.us Channel1 3
e82e99ac9b0c40b08449c76766cf398d e82e99ac9b0c40b08449c76766cf398d@conference.xmpp.zoom.us Channel2 3
e7e2c5e1ba854056906af1c9dc36148f e7e2c5e1ba854056906af1c9dc36148f@conference.xmpp.zoom.us channel3 3
e6388c9667c245c3844009ae995664d5 e6388c9667c245c3844009ae995664d5@conference.xmpp.zoom.us Channel4 3

zoom-list-user-channels


List the existing channels

Base Command

zoom-list-user-channels

Input

Argument Name Description Required
page-size Number of channels to return. Max 300. The default is 50. Optional
next_page_token The next page token is used to get the next page. IMPORTANT: You must pass the same page size that you passed in the first call. Optional
page-number Which page of results to return. The default = 1. Note: This argument is in a deprecate process by the API. As an alternative use “next_page_token” or “limit”. Optional
limit The total amunt of results to show. Optional
channel_id A channel ID. This is for a single channel. Optional
user_id A user ID. This is for a single user. Required

Context Output

Path Type Description
Zoom.Channel.id string The ID of the created channel.
Zoom.Channel.name string The name of the created channel.
Zoom.Channel.type string The created channel type.
Zoom.Channel.url string The created channel URL.

Command example

!zoom-list-user-channels user_id=uJiZN-O7Rp6Jp_995FpZGg channel_id=88f2f20f4abd415cba2429538be58025

Context Example

{
    "Zoom": {
        "Channel": {
            "channel_settings": {
                "add_member_permissions": 1,
                "allow_to_add_external_users": 0,
                "mention_all_permissions": 1,
                "new_members_can_see_previous_messages_files": true,
                "posting_permissions": 1
            },
            "channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiI4OGYyZjIwZjRhYmQ0MTVjYmEyNDI5NTM4YmU1ODAyNUBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
            "id": "88f2f20f4abd415cba2429538be58025",
            "jid": "88f2f20f4abd415cba2429538be58025@conference.xmpp.zoom.us",
            "name": "Channel-Updated5",
            "type": 3
        },
        "UserChannelsNextToken": null
    }
}

Human Readable Output

Channels

Channel ID Channel name Channel type Channel url User id channel JID
88f2f20f4abd415cba2429538be58025 Channel-Updated5 3 https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiI4OGYyZjIwZjRhYmQ0MTVjYmEyNDI5NTM4YmU1ODAyNUBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9 uJiZN-O7Rp6Jp_995FpZGg 88f2f20f4abd415cba2429538be58025@conference.xmpp.zoom.us

Command example

!zoom-list-user-channels user_id=uJiZN-O7Rp6Jp_995FpZGg

Context Example

{
    "Zoom": {
        "Channel": {
            "channels": [
                {
                    "channel_settings": {
                        "add_member_permissions": 1,
                        "allow_to_add_external_users": 0,
                        "mention_all_permissions": 1,
                        "new_members_can_see_previous_messages_files": false,
                        "posting_permissions": 1
                    },
                    "channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiJlN2UyYzVlMWJhODU0MDU2OTA2YWYxYzlkYzM2MTQ4ZkBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
                    "id": "e7e2c5e1ba854056906af1c9dc36148f",
                    "jid": "e7e2c5e1ba854056906af1c9dc36148f@conference.xmpp.zoom.us",
                    "name": "TestChannel1",
                    "type": 3
                },
                {
                    "channel_settings": {
                        "add_member_permissions": 1,
                        "allow_to_add_external_users": 0,
                        "mention_all_permissions": 1,
                        "new_members_can_see_previous_messages_files": true,
                        "posting_permissions": 1
                    },
                    "channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiI3ODI4YTFiMjgzYmQ0MjYxOTkwOTRlNWVhMGFhOTM1M0Bjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
                    "id": "7828a1b283bd426199094e5ea0aa9353",
                    "jid": "7828a1b283bd426199094e5ea0aa9353@conference.xmpp.zoom.us",
                    "name": "Channel",
                    "type": 3
                },
                {
                    "channel_settings": {
                        "add_member_permissions": 1,
                        "allow_to_add_external_users": 0,
                        "mention_all_permissions": 1,
                        "new_members_can_see_previous_messages_files": true,
                        "posting_permissions": 1
                    },
                    "channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiIwOGE0OWVmY2I5YTA0N2MzYmU5NWMwNDc4NzI1NjJjZkBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
                    "id": "08a49efcb9a047c3be95c047872562cf",
                    "jid": "08a49efcb9a047c3be95c047872562cf@conference.xmpp.zoom.us",
                    "name": "DemoChannel-Updated",
                    "type": 3
                },
                {
                    "channel_settings": {
                        "add_member_permissions": 1,
                        "allow_to_add_external_users": 0,
                        "mention_all_permissions": 1,
                        "new_members_can_see_previous_messages_files": false,
                        "posting_permissions": 1
                    },
                    "channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiI5MmIwMjY4YWFmOGQ0MDM5OTQ4YjE3ZDc4M2IwODE5OEBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
                    "id": "92b0268aaf8d4039948b17d783b08198",
                    "jid": "92b0268aaf8d4039948b17d783b08198@conference.xmpp.zoom.us",
                    "name": "TestGroupChannel1",
                    "type": 3
                },
                {
                    "channel_settings": {
                        "add_member_permissions": 1,
                        "allow_to_add_external_users": 0,
                        "mention_all_permissions": 1,
                        "new_members_can_see_previous_messages_files": true,
                        "posting_permissions": 1
                    },
                    "channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiIzZDRjZjFiNDkzNDk0NGFkODM5YzEwOWJhYWM5MzEyNkBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
                    "id": "3d4cf1b4934944ad839c109baac93126",
                    "jid": "3d4cf1b4934944ad839c109baac93126@conference.xmpp.zoom.us",
                    "name": "Admins1",
                    "type": 2
                },
                {
                    "channel_settings": {
                        "add_member_permissions": 1,
                        "allow_to_add_external_users": 0,
                        "mention_all_permissions": 1,
                        "new_members_can_see_previous_messages_files": true,
                        "posting_permissions": 1
                    },
                    "channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiJlODJlOTlhYzliMGM0MGIwODQ0OWM3Njc2NmNmMzk4ZEBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
                    "id": "e82e99ac9b0c40b08449c76766cf398d",
                    "jid": "e82e99ac9b0c40b08449c76766cf398d@conference.xmpp.zoom.us",
                    "name": "Admins_to_delete_2",
                    "type": 3
                },
                {
                    "channel_settings": {
                        "add_member_permissions": 1,
                        "allow_to_add_external_users": 0,
                        "mention_all_permissions": 1,
                        "new_members_can_see_previous_messages_files": true,
                        "posting_permissions": 1
                    },
                    "channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiIwZWJlNzEwMDNlYjI0ZjVmODU3N2U1YTEyNGYwNjQyOEBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
                    "id": "0ebe71003eb24f5f8577e5a124f06428",
                    "jid": "0ebe71003eb24f5f8577e5a124f06428@conference.xmpp.zoom.us",
                    "name": "Admins_to_delete_2_updated",
                    "type": 3
                },
                {
                    "channel_settings": {
                        "add_member_permissions": 1,
                        "allow_to_add_external_users": 1,
                        "mention_all_permissions": 1,
                        "new_members_can_see_previous_messages_files": true,
                        "posting_permissions": 1
                    },
                    "channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiIyZTk5YTdlMDdkZTA0ZjUyYmYyYzQ0OGNkMmIxNTFmY0Bjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
                    "id": "2e99a7e07de04f52bf2c448cd2b151fc",
                    "jid": "2e99a7e07de04f52bf2c448cd2b151fc@conference.xmpp.zoom.us",
                    "name": "BotChannel",
                    "type": 5
                },
                {
                    "channel_settings": {
                        "add_member_permissions": 1,
                        "allow_to_add_external_users": 0,
                        "mention_all_permissions": 1,
                        "new_members_can_see_previous_messages_files": true,
                        "posting_permissions": 1
                    },
                    "channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiJiMThkMTUxNDBjMjU0NTQ5YTgwYWY2NTcyYjNiNTUyZUBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
                    "id": "b18d15140c254549a80af6572b3b552e",
                    "jid": "b18d15140c254549a80af6572b3b552e@conference.xmpp.zoom.us",
                    "name": "ChannelName",
                    "type": 3
                },
                {
                    "channel_settings": {
                        "add_member_permissions": 1,
                        "allow_to_add_external_users": 0,
                        "mention_all_permissions": 1,
                        "new_members_can_see_previous_messages_files": true,
                        "posting_permissions": 1
                    },
                    "channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiIzNjQxYzNmZGMxZGM0Zjc4OGU4ZWIzNDA3YTQwYzQ3MkBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
                    "id": "3641c3fdc1dc4f788e8eb3407a40c472",
                    "jid": "3641c3fdc1dc4f788e8eb3407a40c472@conference.xmpp.zoom.us",
                    "name": "Admins",
                    "type": 2
                },
                {
                    "channel_settings": {
                        "add_member_permissions": 1,
                        "allow_to_add_external_users": 0,
                        "mention_all_permissions": 1,
                        "new_members_can_see_previous_messages_files": true,
                        "posting_permissions": 1
                    },
                    "channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiJmN2NlNDE0YTI0NjM0MjQwYWUwYTc4OTQ4MjNkODcwN0Bjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
                    "id": "f7ce414a24634240ae0a7894823d8707",
                    "jid": "f7ce414a24634240ae0a7894823d8707@conference.xmpp.zoom.us",
                    "name": "TestChannel3",
                    "type": 3
                }
            ],
            "next_page_token": "",
            "page_size": 50,
            "total_records": 11
        },
        "UserChannelsNextToken": ""
    }
}

Human Readable Output

Channels

Channel ID Channel name Channel type Channel url User id channel JID
e7e2c5e1ba854056906af1c9dc36148f TestChannel1 3 https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiJlN2UyYzVlMWJhODU0MDU2OTA2YWYxYzlkYzM2MTQ4ZkBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9 uJiZN-O7Rp6Jp_995FpZGg e7e2c5e1ba854056906af1c9dc36148f@conference.xmpp.zoom.us
7828a1b283bd426199094e5ea0aa9353 Channel 3 https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiI3ODI4YTFiMjgzYmQ0MjYxOTkwOTRlNWVhMGFhOTM1M0Bjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9 uJiZN-O7Rp6Jp_995FpZGg 7828a1b283bd426199094e5ea0aa9353@conference.xmpp.zoom.us
08a49efcb9a047c3be95c047872562cf DemoChannel-Updated 3 https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiIwOGE0OWVmY2I5YTA0N2MzYmU5NWMwNDc4NzI1NjJjZkBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9 uJiZN-O7Rp6Jp_995FpZGg 08a49efcb9a047c3be95c047872562cf@conference.xmpp.zoom.us
92b0268aaf8d4039948b17d783b08198 TestGroupChannel1 3 https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiI5MmIwMjY4YWFmOGQ0MDM5OTQ4YjE3ZDc4M2IwODE5OEBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9 uJiZN-O7Rp6Jp_995FpZGg 92b0268aaf8d4039948b17d783b08198@conference.xmpp.zoom.us
3d4cf1b4934944ad839c109baac93126 Admins1 2 https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiIzZDRjZjFiNDkzNDk0NGFkODM5YzEwOWJhYWM5MzEyNkBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9 uJiZN-O7Rp6Jp_995FpZGg 3d4cf1b4934944ad839c109baac93126@conference.xmpp.zoom.us
e82e99ac9b0c40b08449c76766cf398d Admins_to_delete_2 3 https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiJlODJlOTlhYzliMGM0MGIwODQ0OWM3Njc2NmNmMzk4ZEBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9 uJiZN-O7Rp6Jp_995FpZGg e82e99ac9b0c40b08449c76766cf398d@conference.xmpp.zoom.us
0ebe71003eb24f5f8577e5a124f06428 Admins_to_delete_2_updated 3 https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiIwZWJlNzEwMDNlYjI0ZjVmODU3N2U1YTEyNGYwNjQyOEBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9 uJiZN-O7Rp6Jp_995FpZGg 0ebe71003eb24f5f8577e5a124f06428@conference.xmpp.zoom.us
2e99a7e07de04f52bf2c448cd2b151fc BotChannel 5 https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiIyZTk5YTdlMDdkZTA0ZjUyYmYyYzQ0OGNkMmIxNTFmY0Bjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9 uJiZN-O7Rp6Jp_995FpZGg 2e99a7e07de04f52bf2c448cd2b151fc@conference.xmpp.zoom.us
b18d15140c254549a80af6572b3b552e ChannelName 3 https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiJiMThkMTUxNDBjMjU0NTQ5YTgwYWY2NTcyYjNiNTUyZUBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9 uJiZN-O7Rp6Jp_995FpZGg b18d15140c254549a80af6572b3b552e@conference.xmpp.zoom.us
3641c3fdc1dc4f788e8eb3407a40c472 Admins 2 https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiIzNjQxYzNmZGMxZGM0Zjc4OGU4ZWIzNDA3YTQwYzQ3MkBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9 uJiZN-O7Rp6Jp_995FpZGg 3641c3fdc1dc4f788e8eb3407a40c472@conference.xmpp.zoom.us
f7ce414a24634240ae0a7894823d8707 TestChannel3 3 https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiJmN2NlNDE0YTI0NjM0MjQwYWUwYTc4OTQ4MjNkODcwN0Bjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9 uJiZN-O7Rp6Jp_995FpZGg f7ce414a24634240ae0a7894823d8707@conference.xmpp.zoom.us

zoom-create-channel


Creates a channel for a user

Base Command

zoom-create-channel

Input

Argument Name Description Required
user_id The user’s unique identifier. Required
member_emails The member(s) to include in the channel. A maximum of 20 members can be added to the channel at once with this API. Required
add_member_permissions Who can add new channel members: 1 - All channel members can add new members. 2 - Only channel owner and administrators can add new members. Note: This setting can only be modified by the channel owner. Default: 1.  
posting_permissions The channel members’ posting permissions: 1 — All chat channel members can post to the channel. 2 — Only the channel owner and administrators can post to the channel. * 3 — Only the channel owner, administrators and certain members can post to the channel. Default: 1. Optional
new_members_can_see_prev_msgs Whether new channel members can view messages and files previously posted in the channel. Possible values are: true, false. Default is True. Optional
channel_name The name of the channel. Maximum of 128 characters. Required
channel_type The type of the channel. The value can be one of the following: 1: Private channel. In this type of channel, members must be invited to join a channel. 2: Private channel with members that belong to one Zoom account. Members in this channel should be invited and the members should be from the same organization. 3: Public channel. Anyone can search for this channel and join the channel. 4: New chat. This is an instant channel which can be created by adding members to a new chat. Required

Context Output

Path Type Description
Zoom.Channel.id string the channel’s unique identifier.
Zoom.Channel.jid string The channel JID.
Zoom.Channel.name string The channel name.
Zoom.Channel.type string The type of the channel. The value can be one of the following: 1: Private channel. In this type of channel, members must be invited to join a channel. 2: Private channel with members that belong to one Zoom account. Members in this channel should be invited and the members should be from the same organization. 3: Public channel. Anyone can search for this channel and join the channel. 4: Group chat. This is an instant channel which can be created by adding members to a new chat.
     
Zoom.Channel.url string The URL of the Zoom chat channel.

Command example

!zoom-create-channel user_id=uJiZN-O7Rp6Jp_995FpZGg member_emails=example@example.com channel_name=ChannelName channel_type="Public channel"

Context Example

{
    "Zoom": {
        "Channel": {
            "channel_url": "https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiJiMThkMTUxNDBjMjU0NTQ5YTgwYWY2NTcyYjNiNTUyZUBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9",
            "id": "b18d15140c254549a80af6572b3b552e",
            "jid": "b18d15140c254549a80af6572b3b552e@conference.xmpp.zoom.us",
            "name": "ChannelName",
            "type": 3
        }
    }
}

Human Readable Output

Channel details

Channel ID Channel name Channel type Channel url User id
b18d15140c254549a80af6572b3b552e ChannelName 3 https://us06web.zoom.us/launch/chat/v2/eyJzaWQiOiJiMThkMTUxNDBjMjU0NTQ5YTgwYWY2NTcyYjNiNTUyZUBjb25mZXJlbmNlLnhtcHAuem9vbS51cyJ9 uJiZN-O7Rp6Jp_995FpZGg

zoom-delete-channel


Deletes a specific Zoom channel

Base Command

zoom-delete-channel

Input

Argument Name Description Required
channel_id Unique identifier of a channel. Required
user_id User unique identifier. Required

Context Output

There is no context output for this command.

Command example

!zoom-delete-channel user_id=uJiZN-O7Rp6Jp_995FpZGg channel_id=88f2f20f4abd415cba2429538be58025

Human Readable Output

Channel 88f2f20f4abd415cba2429538be58025 was deleted successfully

zoom-update-channel


Update an existing channel in a Zoom account.

Base Command

zoom-update-channel

Input

Argument Name Description Required
channel_id The channel ID. Required
user_id User unique identifier. Required
add_member_permissions Who can add new channel members: 1 - All channel members can add new members. 2 - Only channel owner and administrators can add new members. Note: This setting can only be modified by the channel owner. Optional
posting_permissions The channel members’ posting permissions: 1 — All chat channel members can post to the channel. 2 — Only the channel owner and administrators can post to the channel. * 3 — Only the channel owner, administrators and certain members can post to the channel. Optional
new_members_can_see_prev_msgs Whether new channel members can view messages and files previously posted in the channel. Possible values are: true, false. Default is True. Optional
channel_name A new name for the channel. Optional

Context Output

There is no context output for this command.

Command example

!zoom-update-channel user_id=uJiZN-O7Rp6Jp_995FpZGg channel_name=Channel-Updated5 channel_id=88f2f20f4abd415cba2429538be58025

Human Readable Output

Channel 88f2f20f4abd415cba2429538be58025 was updated successfully

zoom-invite-to-channel


Invites members that are in a user’s contact list to a channel. A channel can have one or multiple members. The maximum number of members that can be added at once with this API is 5.

Base Command

zoom-invite-to-channel

Input

Argument Name Description Required
channel_id The channel’s unique identifier. Required
user_id User unique identifier. Required
members The member’s email address. Required

Context Output

Path Type Description
Zoom.Channel.ids string A comma-separated list of user IDs of the members added to the channel. User IDs of those who are not from the same account will be omitted from the list.
     
Zoom.Channel.added_at string The date and time when the members are added to the channel.
Zoom.Channel.member_ids string A comma-separated list of member IDs of the members added to the channel.

Command example

!zoom-invite-to-channel user_id=uJiZN-O7Rp6Jp_995FpZGg members=example@example.com channel_id=88f2f20f4abd415cba2429538be58025

Context Example

{
    "Zoom": {
        "Channel": {
            "added_at": "2023-05-22T08:36:57Z",
            "ids": "pq0t1uvlrqmi_p_-cg2ugq",
            "member_ids": "1vqMC-BQdfok1tpAnSw8OT6FtcMiXBaUPNoRhTIzcvJjtbxgPXQRLmDm-10C2Ggg"
        }
    }
}

Human Readable Output

Channel details

Added at date and time Channel ID User id
2023-05-22T08:36:57Z 88f2f20f4abd415cba2429538be58025 pq0t1uvlrqmi_p_-cg2ugq

zoom-remove-from-channel


Removes a member from a chat channel. A channel can have one or more members.

Base Command

zoom-remove-from-channel

Input

Argument Name Description Required
channel_id The unique identifier of the channel from where you would like to remove a member. Required
user_id User unique identifier. Required
member_id The email address or user ID or member ID of the member to remove from the channel. Required

Context Output

There is no context output for this command.

Command example

!zoom-remove-from-channel user_id=uJiZN-O7Rp6Jp_995FpZGg member_id=example@example.com channel_id=88f2f20f4abd415cba2429538be58025

Human Readable Output

Member example@example.com was successfully removed from channel 88f2f20f4abd415cba2429538be58025

zoom-send-file


Sends a file on Zoom to either an individual user in your contact list or a channel of which you are a member.

Base Command

zoom-send-file

Input

Argument Name Description Required
to_channel The channel ID of the channel to which to send the chat file. Optional
user_id The user’s ID. Required
to_contact The user ID or member ID of the contact to send the chat file. Optional
entry_id Cortex XSOAR internal file ID. Required

Context Output

There is no context output for this command.

zoom-send-message


Sends chat messages on Zoom to either an individual user who is in your contact list or to a channel of which you are a member.

Base Command

zoom-send-message

Input

Argument Name Description Required
user_id Unique identifier of the user. Required
at_contact Email address of the mention contact. Optional
is_markdown if a markdown message provide in the message argument Optional
message The message to be sent. Maximum of 1024 characters. Required
entry_ids A list of the file IDs to send. This field only accepts a maximum of six file IDs. Optional
reply_main_message_id The reply message’s ID. This field only returns if the message is a reply message. Optional
to_channel The channel ID of the channel to send a message. Optional
to_contact The email address or user ID or member ID of the person to send a message. Optional

Context Output

Path Type Description
Zoom.ChatMessage.id number Unique identifier of the message.

Command example

!zoom-send-message user_id=uJiZN-O7Rp6Jp_995FpZGg message="message" to_contact=example@example.com

Context Example

{
    "Zoom": {
        "ChatMessage": {
            "id": "7df8cc5b-efc4-4e08-9083-9823b8871c82"
        }
    }
}

Human Readable Output

Message

Contact Message ID
example@example.com 7df8cc5b-efc4-4e08-9083-9823b8871c82

zoom-delete-message


Deletes a chat message previously sent to a contact or a channel.

Base Command

zoom-delete-message

Input

Argument Name Description Required
user_id Unique identifier of the user. Required
message_id Unique identifier of the message. Required
to_channel The channel ID where the message was sent. You must provide this parameter or the to_contact parameter. Optional
to_contact The member ID or user ID or email address of a chat contact to whom the message was sent. You must provide this parameter or the to_channel parameter. Optional

Context Output

There is no context output for this command.

Command example

!zoom-delete-message user_id=uJiZN-O7Rp6Jp_995FpZGg to_contact=example@example.com message_id=4a59df4a-9668-46bd-bff2-3e1f3462ecc3

Human Readable Output

Message 4a59df4a-9668-46bd-bff2-3e1f3462ecc3 was deleted successfully

zoom-update-message


Edits a chat message that you previously sent to either a contact or a channel in Zoom by providing the ID of the message as the value of the messageId parameter. As a query parameter, you must provide either the contact’s email address or the Channel ID of the channel where the message was sent.

Base Command

zoom-update-message

Input

Argument Name Description Required
user_id Unique identifier of the user. Required
message_id Unique identifier of the message. Required
message The edited message. Required
to_channel The channel ID of the channel where you sent the message. You must provide either to_contact or to_channel parameter in the API request. Channel ID can be retrieved from List User’s Channels API. Optional
to_contact The email address or user ID or member ID of the contact to whom the message was sent. You must provide either this parameter or the to_channel parameter in the API request. Optional
entry_ids A list of Cortex XSOAR file entry IDs to send. Optional

Context Output

There is no context output for this command.

Command example

!zoom-update-message user_id=uJiZN-O7Rp6Jp_995FpZGg message="message2" to_contact=example@example.com message_id=4a59df4a-9668-46bd-bff2-3e1f3462ecc3

Human Readable Output

Message 4a59df4a-9668-46bd-bff2-3e1f3462ecc3 was successfully updated

zoom-list-messages


Searches chat messages or shared files between a user and an individual contact or a chat channel.

Base Command

zoom-list-messages

Input

Argument Name Description Required
user_id Unique identifier of the user. Required
to_contact This field allows you to query by the email address or user ID or member ID of a chat contact with whom the user communicated. The API only returns messages sent and/or received between the user and the queried contact. Optional
to_channel This field queries by the channel ID of a channel in which the user had chat conversations. The API only returns messages sent and/or received by the user in the queried channel. Optional
date The query date from which to retrieve the chat messages. This value defaults to the current date. Format %Y-%m-%dT%H:%M:%S.. Optional
from Start date. Format %Y-%m-%dT%H:%M:%S. Optional
to End date. Format %Y-%m-%dT%H:%M:%S. Optional
include_deleted_and_edited_message Whether to include deleted and edited messages. Default false. Optional
search_type The type of search: message — Search messages. file — Search files.. Possible values are: message, file. Optional
search_key Key for search in messages. Optional
exclude_child_message Whether to exclude returning all child messages in a chat, leaving only the parent messages. Default: false. Optional
next_page_token The next page token paginates through a large set of results. A next page token is returned whenever the set of available results exceeds the current page size. This token’s expiration period is 15 minutes. Optional
page_size Number of records returned from a single API call. Default 50. Optional
page_number The page of results to return. Default 1. Optional
limit Total amount of results to show. Optional

Context Output

Path Type Description
Zoom.ChatMessage.date date The queried date value.
Zoom.ChatMessage.id string The channel’s unique identifier.
Zoom.Channel.jid string The channel JID.
Zoom.Channel.name string The channel name.
Zoom.Channel.type string The type of the channel. The value can be one of the following: 1: Private channel. In this type of channel, members must be invited to join a channel. 2: Private channel with members that belong to one Zoom account. Members in this channel should be invited and the members should be from the same organization. 3: Public channel. Anyone can search for this channel and join the channel. 4: Group chat. This is an instant channel which can be created by adding members to a new chat.
     
Zoom.ChatMessage.date date The queried date value.
Zoom.ChatMessage.from date-time The queried from value. (Returned only if the from query parameter is used)
Zoom.ChatMessage.messages array of object Information about received messages and files.
Zoom.ChatMessage.messages.bot_message object The chatbot’s message in JSON format.
Zoom.ChatMessage.messages.bot_message.date_time date-time The date and time when the message was sent.
Zoom.ChatMessage.messages.files array of object Information about chat files (if multiple files exist).
Zoom.ChatMessage.messages.files.download_url string The download URL of the chat file.
Zoom.ChatMessage.messages.files.file_id string The unique ID of the chat file.
Zoom.ChatMessage.messages.files.file_name string The name and file extension of the chat file.
Zoom.ChatMessage.messages.files.file_size integer The size of the chat file in bytes.
Zoom.ChatMessage.messages.rich_text array of object Rich text formatting information.
Zoom.ChatMessage.messages.rich_text.start_position integer The start position of the rich text in the message string.
Zoom.ChatMessage.messages.rich_text.end_position integer The end position of the rich text.
Zoom.ChatMessage.messages.rich_text.format_type enum The type of rich text format.
Zoom.ChatMessage.messages.rich_text.format_attr string The attribute values of a specific format_type.
Zoom.ChatMessage.messages.rich_text.download_url string The download URL of the first file.
Zoom.ChatMessage.messages.rich_text.file_id string The unique ID of the first file.
Zoom.ChatMessage.messages.rich_text.file_name string The name of the first file.
Zoom.ChatMessage.messages.rich_text.file_size integer The size of the first file in bytes.
Zoom.ChatMessage.messages.id string Unique identifier of the message.
Zoom.ChatMessage.messages.message string The message content.
Zoom.ChatMessage.messages.reply_main_message_id string The unique identifier of a reply message. (Returned only for reply messages)
Zoom.ChatMessage.messages.reply_main_message_timestamp integer The timestamp of when the reply message was sent. (Returned only for reply messages)
Zoom.ChatMessage.messages.sender string The email address of the message sender. Empty if the sender does not belong to the same account as the current user or is not a contact.
Zoom.ChatMessage.messages.sender_member_id string The member ID of the message sender.
Zoom.ChatMessage.messages.sender_display_name string The display name of the message sender.
Zoom.ChatMessage.messages.status enum Indicates the status of the message. Allowed values Deleted, Edited, Normal. (Returned only when include_deleted_and_edited_message query parameter is set to true)
Zoom.ChatMessage.messages.timestamp integer The timestamp of the message in microseconds.
Zoom.ChatMessage.at_items array of object Information about mentions.
Zoom.ChatMessage.at_items.at_contact string The user ID of the mentioned contact. Empty if the contact does not belong to the same account as the current user.
Zoom.ChatMessage.at_items.at_contact_member_id string The member ID of the mentioned contact.
Zoom.ChatMessage.at_items.at_type integer The type of mention. Allowed values 1 (Contact), 2 (Channel).
Zoom.ChatMessage.at_items.end_position integer The end position of the mention.
Zoom.ChatMessage.at_items.start_position integer The start position of the mention.
Zoom.ChatMessageNextToken.user_id string The user ID associated with the next page token.
Zoom.ChatMessageNextToken.to_channel string The channel ID associated with the next page token.
Zoom.ChatMessageNextToken.include_deleted_and_edited_message boolean Indicates whether deleted and edited messages are included in the next page token request.
Zoom.ChatMessageNextToken.search_type string The search type associated with the next page token.
Zoom.ChatMessageNextToken.to string The recipient associated with the next page token.
Zoom.ChatMessageNextToken.date string The date associated with the next page token.
Zoom.ChatMessageNextToken.page_size integer The page size associated with the next page token.
Zoom.ChatMessageNextToken.next_page_token string The next page token for pagination.
Zoom.ChatMessageNextToken.from string The sender associated with the next page token.
Zoom.ChatMessageNextToken.search_key string The search key associated with the next page token.
Zoom.ChatMessageNextToken.exclude_child_message boolean Indicates whether child messages are excluded in the next page token request.
Zoom.ChatMessageNextToken.to_contact string The contact ID associated with the next page token.

Command example

!zoom-list-messages user_id=uJiZN-O7Rp6Jp_995FpZGg to_contact=example@example.com date=today

Context Example

{
    "Zoom": {
        "ChatMessage": {
            "ChatMessage": [
                {
                    "date_time": "2023-05-22T08:24:14Z",
                    "id": "a62636c8-b6c1-4135-9352-88ac61eafc31",
                    "message": "message",
                    "send_member_id": "1vrdvnC1gHuxZtpVLR7Oz1_A1dcCrBf0PNoRhTIzcvJjtbxgPXQRLmDm-10C2Ggg",
                    "sender": "example@example.com",
                    "sender_display_name": "admin zoom",
                    "timestamp": 1684743854543
                },
                {
                    "date_time": "2023-05-22T08:20:22Z",
                    "id": "4a59df4a-9668-46bd-bff2-3e1f3462ecc3",
                    "message": "my message",
                    "send_member_id": "1vrdvnC1gHuxZtpVLR7Oz1_A1dcCrBf0PNoRhTIzcvJjtbxgPXQRLmDm-10C2Ggg",
                    "sender": "example@example.com",
                    "sender_display_name": "admin zoom",
                    "timestamp": 1684743622899
                }
            ],
            "ChatMessageNextToken": ""
        }
    }
}

Human Readable Output

Messages

Date Time From Message Id Message sender Message text Sender display name To User id
2023-05-22T08:24:14Z None a62636c8-b6c1-4135-9352-88ac61eafc31 example@example.com message admin zoom None uJiZN-O7Rp6Jp_995FpZGg
2023-05-22T08:20:22Z None 4a59df4a-9668-46bd-bff2-3e1f3462ecc3 example@example.com my message admin zoom None uJiZN-O7Rp6Jp_995FpZGg

zoom-delete-user-token


Revoke a user’s Zoom SSO session.
To list all available users use the zoom-list-users command.

Base Command

zoom-delete-user-token

Input

Argument Name Description Required
user_id The user ID or email to be revoked. Required

Command example

!zoom-delete-user-token user_id=useremail@myself.com

Context Output

There is no context output for this command.

Human Readable Output

Message

User SSO token for user useremail@myself.com is deleted

send-notification


Sends messages from your Marketplace Chatbot app on Zoom to either an individual user or to a channel.

Base Command

send-notification

Input

Argument Name Description Required
to The email address or user ID or member ID of the person to send a message. Required
channel_id The channel ID of the channel to send a message. Optional
message The message to be sent. Maximum of 1024 characters. Required
visible_to_user The UserID that allows a Chatbot to send a message to a group channel when it has only one designated person in that group channel to see the message. Optional

Context Output

There is no context output for this command.

Command example

!send-notification message=hi to=example@example.com

Context Output

There is no context output for this command.

Human Readable Output

Message

Message sent to Zoom successfully. Message ID is: 20230815153245201_BPK3S3S_aw1

mirror-investigation


Mirrors the investigation between Zoom and the Cortex XSOAR War Room.

Base Command

mirror-investigation

Input

Argument Name Description Required
type The mirroring type. Can be “all”, which mirrors everything, “chat”, which mirrors only chats (not commands), or “none”, which stops all mirroring. Possible values are: all, chat, none. Default is all. Optional
autoclose Whether the channel is auto-closed when an investigation is closed. Can be “true” or “false”. Default is “true”. Optional
direction The mirroring direction. Can be “FromDemisto”, “ToDemisto”, or “Both”. Default value is “Both”. Optional
channelName The name of the channel. The default is “incident-<incidentID>”. Optional

Context Output

There is no context output for this command.

Command Example

!mirror-investigation direction="FromDemisto" channelName="example"

Human Readable Output

Investigation mirrored successfully, channel:example

close-channel


Delete a mirrored Zoom channel.

Base Command

close-channel

Input

Argument Name Description Required
channel The name of the channel to delete. If not provided, the mirrored investigation channel is deleted (if the channel exists). Optional
channel_id The ID of the channel to delete. If not provided, the mirrored investigation channel is deleted (if the channel exists). Optional

Context Output

There is no context output for this command.

Command Example

!close-channel channel=new-zoom-channel

Human Readable Output

Channel successfully deleted.

Configuration parameters

  • url — Server URL (e.g. 'https://api.zoom.us/v2/') (required)
  • account_id — Account ID (OAuth) (required)
  • credentials — Client ID (OAuth) (required)
  • botJID — Bot JID
  • bot_credentials — Bot Client ID ((Team Chat App))
  • secret_token
  • verification_token
  • longRunning — Long running instance
  • longRunningPort — Listen Port
  • mirroring — Enable Incident Mirroring
  • proxy — Use system proxy settings
  • insecure — Trust any certificate (not secure)
  • certificate — Certificate (Required for HTTPS)
  • key — Private Key (Required for HTTPS)

Commands (23)

  • close-channel

    Delete a mirrored Zoom channel.

  • mirror-investigation

    Mirrors the investigation between Zoom and the Cortex XSOAR War Room.

  • send-notification

    Send a message using a chatbot app.

  • zoom-create-channel

    Creates a channel for a user. Use the existing command zoom-list-users to get the user ID by email (only if the user has an email address as part of the user parameters).

  • zoom-create-meeting

    Create a new Zoom meeting (scheduled, instant, or recurring).

  • zoom-create-user

    Create a new user in zoom account.

  • zoom-delete-channel

    Deletes a specific Zoom channel. Use the command zoom-list-account-public-channels in order to fetch the channel ID by the channel name.

  • zoom-delete-message

    Deletes a chat message previously sent to a contact or a channel. Use the command zoom-list-user-channels to get the channel ID by the channel name (for to_channel). See the existing command zoom-list-users to get the user ID by email (for to_contact). In order to update messages (or a single message using messageId), you need to provide to_contact (contact to send) or to_channel (channel to send to), but not both of them.

  • zoom-delete-user

    Delete a user from Zoom.

  • zoom-delete-user-token

    Revoke a user's Zoom SSO session. Use the zoom-list-users command to get the user ID or user email.

  • zoom-fetch-recording

    Get the meeting record and save it as a file in the War Room.

  • zoom-invite-to-channel

    Invites members that are in a user's contact list to a channel. A channel can have one or more members. The maximum number of members that can be added at once with this API is 5. Use the command zoom-list-account-public-channels in order to fetch the channel ID by the channel name.

  • zoom-list-account-public-channels

    List the existing channels You can only retrieve the channel information for the authorized user. In order to get a public channel by its name (for example Admins_to_delete_4) you need to run the command zoom-list-account-public-channels without the channel_id param and find which channel_id fits the channel name.

  • zoom-list-messages

    Searches chat messages or shared files between a user and an individual contact or a chat channel.

  • zoom-list-user-channels

    List the existing channels. In order get the user ID by user email - use the existing command zoom-list-users. In order to get the user channel by its name, run the command zoom-list-user-channels without the channel_id param and find which channel_id fits the channel name.

  • zoom-list-users

    List the existing users.

  • zoom-meeting-get

    Get the information of an existing Zoom meeting.

  • zoom-meeting-list

    Show all the meetings of a given user. Note: only scheduled and unexpired meetings will appear.

  • zoom-remove-from-channel

    Removes a member from a chat channel. A channel can have one or more members. Use the command zoom-list-account-public-channels in order to fetch the channel ID by the channel name. In order get the user ID by the user email - use the existing command zoom-list-users.

  • zoom-send-file

    Sends a file on Zoom to either an individual user in your contact list or a channel of which you are a member. Use existing command zoom-list-users to get the user ID by the user email (for to_contact). Use the command zoom-list-user-channels in order to fetch the channel ID by the channel name (for to_channel).

  • zoom-send-message

    Sends chat messages on Zoom to either an individual user who is in your contact list or to a channel of which you are a member. Use the command zoom-list-users to get the user id by the user email (for to_contact). Use the command zoom-list-user-channels in order to fetch the channel ID by the channel name (for to_channel). In order to send a message, you need to provide at least a message (message text) and to_contact (contact to send) or to_channel (channel to send to), but not both of them. In order to send a style message you need to provide is-markdown=true and the message can contain a markdown format. If you are using mention markdown in a message, provide the email address in the at_contact argument.

  • zoom-update-channel

    Update an existing channel in a Zoom account. Use the command zoom-list-account-public-channels in order to fetch the channel ID by the channel name. "Need to provide at least one of the following arguments: posting_permissions or channnel_name.".

  • zoom-update-message

    Edits a chat message that you previously sent to either a contact or a channel in Zoom by providing the ID of the message as the value of the messageId parameter. As a query parameter, you must provide either the contact's email address of the contact or the Channel ID of the channel where the message was sent. Use the command zoom-list-user-channels to get the channel ID by the channel name (for to_channel). Use the existing command zoom-list-users to get the user ID by email (for to_contact). In order to update messages (or a single message using messageId), you need to provide to_contact (contact to send) or to_channel (channel to send to), but not both of them.

import json
from unittest.mock import patch

import demistomock as demisto
import pytest
import Zoom
from CommonServerPython import CommandResults, DemistoException
from fastapi import Request, status
from fastapi.security import HTTPBasicCredentials
from freezegun import freeze_time
from Zoom import Client


def test_zoom_list_users_command__limit(mocker):
    """
    Given -
       client
    When -
        asking for a limit of results
    Then -
        Validate that a func that runs a pagination has been called
    """
    manual_list_user_pagination_mock = mocker.patch.object(Zoom, "manual_list_user_pagination")
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    from Zoom import zoom_list_users_command

    zoom_list_users_command(client=client, limit=50)
    assert manual_list_user_pagination_mock.called


def test_zoom_list_users_command__no_limit(mocker):
    """
    Given -
       client
    When -
        asking for one page results (the default)
    Then -
        Validate that a func that runs a pagination has not been called
        Validate that a func that returns the first page is called
    """
    manual_list_user_pagination_mock = mocker.patch.object(Zoom, "manual_list_user_pagination", return_value=[{"None": None}])
    returned_dict = {
        "page_count": 1,
        "page_number": 1,
        "page_size": 30,
        "total_records": 2,
        "next_page_token": "",
        "users": [
            {
                "id": "1234",
                "first_name": "as",
                "last_name": "bla",
                "email": "example@example.com",
                "type": 1,
                "pmi": 1234,
                "timezone": "Asia/Jerusalem",
                "verified": 1,
                "dept": "",
            }
        ],
    }
    zoom_list_users_mock = mocker.patch.object(Client, "zoom_list_users", return_value=returned_dict)
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    from Zoom import zoom_list_users_command

    zoom_list_users_command(
        client=client, page_size=30, user_id=None, status="active", next_page_token=None, role_id=None, limit=None
    )
    assert not manual_list_user_pagination_mock.called
    assert zoom_list_users_mock.called


def test_zoom_list_users_command__limit_and_page_size(mocker):
    """
    When -
        asking for a limit of results and for a user_id
    Then -
        Validate that an error message will be returned
    """
    returned_dict = {
        "page_count": 1,
        "page_number": 1,
        "page_size": 30,
        "total_records": 2,
        "next_page_token": "",
        "users": [
            {
                "id": "1234",
                "first_name": "as",
                "last_name": "bla",
                "email": "example@example.com",
                "type": 1,
                "pmi": 1234,
                "timezone": "Asia/Jerusalem",
                "verified": 1,
                "dept": "",
            }
        ],
    }
    mocker.patch.object(Client, "zoom_list_users", return_value=returned_dict)
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    from Zoom import zoom_list_users_command

    with pytest.raises(DemistoException) as e:
        zoom_list_users_command(
            client=client, page_size=30, user_id="fdghdf", status="active", next_page_token=None, role_id=None, limit=50
        )

    assert (
        e.value.message
        == """Too many arguments. If you choose a limit,
                                       don't enter a user_id or page_size or next_page_token or page_number."""
    )


def test_zoom_list_users_command__user_id(mocker):
    """
    Given -
       client
    When -
        asking for a specific user
    Then -
        Validate that the API call will be for a specific user
        and the url_suffix has changed to the right value
    """
    returned_dict = {
        "page_count": 1,
        "page_number": 1,
        "page_size": 30,
        "total_records": 2,
        "next_page_token": "",
        "users": [
            {
                "id": "1234",
                "first_name": "as",
                "last_name": "bla",
                "email": "example@example.com",
                "type": 1,
                "pmi": 1234,
                "timezone": "Asia/Jerusalem",
                "verified": 1,
                "dept": "",
            }
        ],
    }
    zoom_list_users_mocker = mocker.patch.object(Client, "zoom_list_users", return_value=returned_dict)
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    from Zoom import zoom_list_users_command

    zoom_list_users_command(
        client=client, page_size=30, user_id="bla@bla.com", status="active", next_page_token=None, role_id=None, limit=None
    )

    assert zoom_list_users_mocker.call_args[1].get("url_suffix") == "users/bla@bla.com"


def test_manual_list_user_pagination__small_limit(mocker):
    """
    Given -
       client
    When -
        limit > 0 < MAX_RECORDS_PER_PAGE
    Then -
        Validate that the page_size == limit
    """
    mocker.patch.object(Client, "generate_oauth_token")
    returned_dict = {
        "page_count": 1,
        "page_number": 1,
        "page_size": 30,
        "total_records": 2,
        "next_page_token": "",
        "users": [
            {
                "id": "1234",
                "first_name": "as",
                "last_name": "bla",
                "email": "example@example.com",
                "type": 1,
                "pmi": 1234,
                "timezone": "Asia/Jerusalem",
                "verified": 1,
                "dept": "",
            }
        ],
    }
    zoom_list_users_mocker = mocker.patch.object(Client, "zoom_list_users", return_value=returned_dict)
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    limit = 5
    from Zoom import manual_list_user_pagination

    manual_list_user_pagination(client=client, next_page_token="None", limit=limit, status="None", role_id="None")
    assert zoom_list_users_mocker.call_args[1].get("page_size") == limit


def test_manual_list_user_pagination__large_limit(mocker):
    """
    Given -
       client
    When -
        limit >  MAX_RECORDS_PER_PAGE
    Then -
        Validate that the page_size at the last call == MAX_RECORDS_PER_PAGE (currently 300)
    """
    mocker.patch.object(Client, "generate_oauth_token")
    returned_dict = {
        "page_count": 1,
        "page_number": 1,
        "page_size": 30,
        "total_records": 2,
        "next_page_token": "",
        "users": [
            {
                "id": "1234",
                "first_name": "as",
                "last_name": "bla",
                "email": "example@example.com",
                "type": 1,
                "pmi": 1234,
                "timezone": "Asia/Jerusalem",
                "verified": 1,
                "dept": "",
            }
        ],
    }
    zoom_list_users_mocker = mocker.patch.object(Client, "zoom_list_users", return_value=returned_dict)
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    limit = 2000
    from Zoom import manual_list_user_pagination

    manual_list_user_pagination(client=client, next_page_token="None", limit=limit, status="None", role_id="None")
    assert zoom_list_users_mocker.call_args[1].get("page_size") == 300


def test_zoom_create_user_command(mocker):
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    user_type = ("Basic",)
    email = ("mock@moker.com",)
    first_name = ("John",)
    last_name = "Smith"

    zoom_create_user_mock = mocker.patch.object(client, "zoom_create_user")
    from Zoom import zoom_create_user_command

    zoom_create_user_command(client, email=email, user_type=user_type, first_name=first_name, last_name=last_name)

    zoom_create_user_mock.assert_called()


def test_zoom_create_user__basic_user_type(mocker):
    """
    Given -
       client
    When -
        asking for a basic user type
    Then -
        Validate that the right type is sent to the API
    """
    mocker.patch.object(Client, "generate_oauth_token")
    http_request_mocker = mocker.patch.object(Client, "error_handled_http_request", return_value=None)
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    client.zoom_create_user(user_type_num=1, email="mock@moker.com", first_name="John", last_name="Smith")
    assert http_request_mocker.call_args[1].get("json_data").get("user_info").get("type") == 1


def test_zoom_user_create__pro_user_type(mocker):
    """
    Given -
       client
    When -
        asking for a pro user type
    Then -
        Validate that the right type is sent in the error_handled_http_request
    """
    mocker.patch.object(Client, "generate_oauth_token")
    http_request_mocker = mocker.patch.object(Client, "error_handled_http_request", return_value=None)
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    client.zoom_create_user(user_type_num=2, email="mock@moker.com", first_name="John", last_name="Smith")
    assert http_request_mocker.call_args[1].get("json_data").get("user_info").get("type") == 2


def test_zoom_user_create__Corporate_user_type(mocker):
    """
    Given -
       client
    When -
        asking for a Corporate user type
    Then -
        Validate that the right type is sent in the http_request
    """
    mocker.patch.object(Client, "generate_oauth_token")
    http_request_mocker = mocker.patch.object(Client, "error_handled_http_request", return_value=None)
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    client.zoom_create_user(user_type_num=3, email="mock@moker.com", first_name="John", last_name="Smith")
    assert http_request_mocker.call_args[1].get("json_data").get("user_info").get("type") == 3


def test_zoom_delete_user_command(mocker):
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    user_id = "user_id"

    zoom_delete_user_mock = mocker.patch.object(client, "zoom_delete_user")
    from Zoom import zoom_delete_user_command

    zoom_delete_user_command(client, user_id=user_id)

    zoom_delete_user_mock.assert_called()


def test_zoom__create_meeting_command__instant_meeting(mocker):
    """
    Given -
       client
    When -
        asking for a instant meeting
    Then -
        Validate that the right type is sent in the API
    """
    zoom_create_meeting_mocker = mocker.patch.object(Client, "zoom_create_meeting", return_value={"bla": "bla"})
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    from Zoom import zoom_create_meeting_command

    zoom_create_meeting_command(
        client=client,
        user_id="mock@moker.com",
        topic="nonsense",
        type="Instant",
    )
    assert zoom_create_meeting_mocker.call_args[1]["json_data"].get("type") == 1


def test_zoom_meeting_create_command__scheduled_meeting(mocker):
    """
    Given -
       client
    When -
        asking for a scheduled meeting
    Then -
        Validate that the right type is sent in the API
    """
    zoom_create_meeting_mocker = mocker.patch.object(Client, "zoom_create_meeting", return_value={"bla": "bla"})
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    from Zoom import zoom_create_meeting_command

    zoom_create_meeting_command(client=client, user_id="mock@moker.com", topic="nonsense", type="Scheduled")
    assert zoom_create_meeting_mocker.call_args[1]["json_data"].get("type") == 2


def test_zoom_create_meeting_command_too_many_arguments(mocker):
    """
    Given -
       client
    When -
        asking for a meeting with join_before_host_and_waiting_room
    Then -
        Validate that the right error will return
    """
    mocker.patch.object(Client, "zoom_create_meeting", return_value={"bla": "bla"})
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    from Zoom import zoom_create_meeting_command

    with pytest.raises(DemistoException) as e:
        zoom_create_meeting_command(
            client=client, user_id="mock@moker.com", topic="nonsense", type="Scheduled", waiting_room=True, join_before_host=True
        )
    assert e.value.message == "Collision arguments. join_before_host argument can be used only if waiting_room is 'False'."


def test_zoom_create_meeting__too_meny_arguments(mocker):
    """
    Given -
       client
    When -
        asking for a meeting with join_before_host_time ant not join_before_host
    Then -
        Validate that the right error will return
    """
    mocker.patch.object(Client, "zoom_create_meeting", return_value={"bla": "bla"})
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    from Zoom import zoom_create_meeting_command

    with pytest.raises(DemistoException) as e:
        zoom_create_meeting_command(
            client=client,
            user_id="mock@moker.com",
            topic="nonsense",
            type="Scheduled",
            join_before_host_time=5,
            join_before_host=False,
        )
    assert (
        e.value.message
        == """Collision arguments.
join_before_host_time argument can be used only if join_before_host is 'True'."""
    )


def test_zoom_create_meeting_command__too_meny_arguments1(mocker):
    """
    Given -
       client
    When -
        asking for a meeting with instant type ant start_time
    Then -
        Validate that the right error will return
    """
    mocker.patch.object(Client, "zoom_create_meeting", return_value={"bla": "bla"})
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    from Zoom import zoom_create_meeting_command

    with pytest.raises(DemistoException) as e:
        zoom_create_meeting_command(
            client=client, type="Instant", topic="nonsense", user_id="mock@moker.com", start_time="2022-10-04T15:59:00Z"
        )
    assert e.value.message == "Too many arguments.Use start_time and timezone for scheduled meetings only."


def test_zoom_create_meeting_command__too_many_arguments2(mocker):
    """
    Given -
       client
    When -
        asking for a instant meeting with end_times and monthly_week :
    Then -
        Validate that the right error will return
    """
    mocker.patch.object(Client, "zoom_create_meeting", return_value={"bla": "bla"})
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    from Zoom import zoom_create_meeting_command

    with pytest.raises(DemistoException) as e:
        zoom_create_meeting_command(
            client=client,
            type="Instant",
            recurrence_type=3,
            topic="nonsense",
            user_id="mock@moker.com",
            end_date_time="2022-10-04T15:59:00Z",
            monthly_week=2,
            monthly_week_day=3,
            end_times=7,
        )
    assert e.value.message == "Collision arguments. Choose only one of these two arguments, end_time or end_date_time."


def test_zoom_create_meeting_command__too_meny_arguments3(mocker):
    """
    Given -
       client
    When -
        asking for a recurring meeting with fixed time and recurrence_type = 3,
         with no monthly_week :
    Then -
        Validate that the right error will return
    """
    mocker.patch.object(Client, "zoom_create_meeting", return_value={"bla": "bla"})
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    from Zoom import zoom_create_meeting_command

    with pytest.raises(DemistoException) as e:
        zoom_create_meeting_command(
            client=client,
            type="Recurring meeting with fixed time",
            recurrence_type="Monthly",
            topic="nonsense",
            user_id="mock@moker.com",
            end_date_time="2022-10-04T15:59:00Z",
            end_times=None,
        )
    assert (
        e.value.message
        == """Missing arguments. A recurring meeting with a fixed time and monthly recurrence_type
            must have the following arguments: monthly_week and monthly_week_day."""
    )


def test_zoom_create_meeting_command__too_meny_arguments4(mocker):
    """
    Given -
       client
    When -
        asking for a recurring meeting with fixed time and recurrence_type = 3,
         with no monthly_week :
    Then -
        Validate that the right error will return
    """
    mocker.patch.object(Client, "zoom_create_meeting", return_value={"bla": "bla"})
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    from Zoom import zoom_create_meeting_command

    with pytest.raises(DemistoException) as e:
        zoom_create_meeting_command(
            client=client, type="Recurring meeting with fixed time", topic="nonsense", user_id="mock@moker.com"
        )
    assert (
        e.value.message
        == """Missing arguments. A recurring meeting with a fixed
time is missing this argument: recurrence_type."""
    )


def test_zoom_create_meeting_command__too_many_arguments5(mocker):
    """
    Given -
       client
    When -
        asking for a instant meeting with end_times:
    Then -
        Validate that the right error will return
    """
    mocker.patch.object(Client, "zoom_create_meeting", return_value={"bla": "bla"})
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    from Zoom import zoom_create_meeting_command

    with pytest.raises(DemistoException) as e:
        zoom_create_meeting_command(client=client, type="Instant", end_times=7)
    assert e.value.message == "One or more arguments that were filed\nare used for a recurring meeting with a fixed time only."


def test_meeting_get_command__show_previous_occurrences_is_false(mocker):
    """
    Given -
       client
    When -
        asking to get a meeting, and the previous_occurrences
    Then -
        Validate that the right argument is sent in the API
    """
    returned_dict = {
        "uuid": "u=",
        "id": 847,
        "host_id": "u",
        "host_email": "example@example.com",
        "assistant_id": "",
        "topic": "My Meeting",
        "type": 2,
        "status": "waiting",
        "start_time": "5Z",
        "duration": 60,
        "timezone": "lem",
        "agenda": "",
        "created_at": "48Z",
        "start_url": ".2-dio1Se7o",
    }
    zoom_meeting_get_mocker = mocker.patch.object(Client, "zoom_meeting_get", return_value=returned_dict)
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    from Zoom import zoom_meeting_get_command

    zoom_meeting_get_command(client=client, meeting_id="1234", show_previous_occurrences=True)
    assert zoom_meeting_get_mocker.call_args[0][2] is True


def test_zoom_meeting_list_command__limit(mocker):
    """
    Given -
       client
    When -
        asking for a limit of results
    Then -
        Validate that a func that runs a pagination has been called
    """

    manual_meeting_list_pagination_mock = mocker.patch.object(Zoom, "manual_meeting_list_pagination")
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    from Zoom import zoom_meeting_list_command

    zoom_meeting_list_command(client=client, user_id="blabla", limit=50)
    assert manual_meeting_list_pagination_mock.called


def test_zoom_meeting_list_command__no_limit(mocker):
    """
    Given -
       client
    When -
        asking for one page results (the default)
    Then -
        Validate that a func that runs a pagination has not been called
        Validate that a func that returns the first page is called
    """
    manual_meeting_list_pagination_mock = mocker.patch.object(Zoom, "manual_meeting_list_pagination")
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    returned_dict = {
        "uuid": "u=",
        "id": 847,
        "host_id": "u",
        "host_email": "example@example.com",
        "assistant_id": "",
        "topic": "My Meeting",
        "type": 2,
        "status": "waiting",
        "start_time": "5Z",
        "duration": 60,
        "timezone": "lem",
        "agenda": "",
        "created_at": "48Z",
        "start_url": ".2-dio1Se7o",
    }
    zoom_meeting_list_mock = mocker.patch.object(Client, "zoom_meeting_list", return_value=returned_dict)

    from Zoom import zoom_meeting_list_command

    zoom_meeting_list_command(client=client, user_id="blabla")
    assert not manual_meeting_list_pagination_mock.called
    assert zoom_meeting_list_mock.called


def test_manual_meeting_list_pagination__small_limit(mocker):
    """
    Given -
       client
    When -
        limit > 0 < MAX_RECORDS_PER_PAGE
    Then -
        Validate that the page_size == limit
    """
    mocker.patch.object(Client, "generate_oauth_token")
    returned_dict = {
        "page_count": 1,
        "page_number": 1,
        "page_size": 30,
        "total_records": 2,
        "next_page_token": "",
        "users": [
            {
                "id": "1234",
                "first_name": "as",
                "last_name": "bla",
                "email": "example@example.com",
                "type": 1,
                "pmi": 1234,
                "timezone": "Asia/Jerusalem",
                "verified": 1,
                "dept": "",
            }
        ],
    }
    zoom_meeting_list_mocker = mocker.patch.object(Client, "zoom_meeting_list", return_value=returned_dict)
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    limit = 5
    from Zoom import manual_meeting_list_pagination

    manual_meeting_list_pagination(client=client, user_id="bla", next_page_token=None, limit=limit, type="all")
    assert zoom_meeting_list_mocker.call_args[1].get("page_size") == limit


def test_manual_meeting_list_pagination__large_limit(mocker):
    """
    Given -
       client
    When -
        limit >  MAX_RECORDS_PER_PAGE
    Then -
        Validate that the page_size at the last call == MAX_RECORDS_PER_PAGE (currently 300)
    """
    mocker.patch.object(Client, "generate_oauth_token")
    returned_dict = {
        "page_count": 1,
        "page_number": 1,
        "page_size": 30,
        "total_records": 2,
        "next_page_token": "",
        "users": [
            {
                "id": "1234",
                "first_name": "as",
                "last_name": "bla",
                "email": "example@example.com",
                "type": 1,
                "pmi": 1234,
                "timezone": "Asia/Jerusalem",
                "verified": 1,
                "dept": "",
            }
        ],
    }
    zoom_meeting_list_mocker = mocker.patch.object(Client, "zoom_meeting_list", return_value=returned_dict)
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    limit = 2000
    from Zoom import manual_meeting_list_pagination

    manual_meeting_list_pagination(client=client, user_id="bla", next_page_token=None, limit=limit, type="all")
    assert zoom_meeting_list_mocker.call_args[1].get("page_size") == 300


def test_check_authentication_type_parameters_with_extra_jwt_member(mocker):
    """
    Given -
       client
    When -
        creating a client with an extra authentication type argument
    Then -
        Validate that the error wil raise as excepted
    """
    with pytest.raises(DemistoException) as e:
        Zoom.check_authentication_type_parameters(
            account_id="mockaccount", client_id="mockclient", client_secret="mocksecret", api_key="blabla", api_secret=""
        )
    assert (
        e.value.message
        == """Too many fields were filled.
You should fill the Account ID, Client ID, and Client Secret fields (OAuth),
OR the API Key and API Secret fields (JWT - Deprecated)."""
    )


def test_check_authentication_type_parameters__with_extra_AOuth_member():
    """
    Given -

    When -
        creating a client with an extra authentication type argument
    Then -
        Validate that the error wil raise as excepted
    """
    with pytest.raises(DemistoException) as e:
        Zoom.check_authentication_type_parameters(
            account_id="", client_id="", client_secret="mocksecret", api_key="blabla", api_secret="ertert"
        )
    assert (
        e.value.message
        == """Too many fields were filled.
You should fill the Account ID, Client ID, and Client Secret fields (OAuth),
OR the API Key and API Secret fields (JWT - Deprecated)."""
    )


def test_zoom_user_list_command__when_user_id(mocker):
    """
    Given -
    a response from a client
    When -
        a user_id argument was passed
    Then -
        Validate that the parsing is as expected
    """
    to_md = {
        "id": "C",
        "first_name": "Ye",
        "last_name": "Ro",
        "email": "y@gmail.com",
        "type": 1,
        "role_name": "Member",
        "pmi": 9,
        "use_pmi": False,
        "personal_meeting_url": "hts://us0",
        "timezone": "Asia/Jerusalem",
        "verified": 1,
        "dept": "",
        "created_at": "2022-12-01T07:40:02Z",
        "last_login_time": "2022-12-14T08:14:29Z",
    }

    mocker.patch.object(Client, "zoom_list_users", return_value=to_md)
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    from Zoom import zoom_list_users_command

    res = zoom_list_users_command(client, user_id="bla")
    assert len(res.readable_output) == 159  # type: ignore[arg-type]


def test_zoom_meeting_list_command__when_user_id(mocker):
    """
    Given -
    a response from a client
    When -
        a user_id argument was passed
    Then -
        Validate that the parsing is as expected
    """
    to_md = {
        "id": "CTJ7hG",
        "first_name": "Ye",
        "last_name": "Ro",
        "email": "y@gmail.com",
        "type": 1,
        "role_name": "Member",
        "pmi": 98,
        "use_pmi": False,
        "personal_meeting_url": "https://",
        "timezone": "Asia/Jerusalem",
        "verified": 1,
        "dept": "",
        "created_at": "2022-12-01T07:40:02Z",
        "last_login_time": "2022-12-14T08:14:29Z",
    }

    mocker.patch.object(Client, "zoom_meeting_list", return_value=to_md)
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    from Zoom import zoom_meeting_list_command

    res = zoom_meeting_list_command(client, user_id="bla")
    assert len(res.readable_output) == 133  # type: ignore[arg-type]


def test_remove_None_values_from_dict():
    from Zoom import remove_None_values_from_dict

    """
        Given -
        a nested dict
        When -
            some values == None
        Then -
            Validate that the keys with value None are removed
    """
    dict_input = {
        "settings": {
            "allow_multiple_devices": "tuyytu",
            "auto_recording": "dyj",
            "encryption_type": "jy",
            "focus_mode": False,
            "host_video": None,
            "jbh_time": "jdfd",
            "join_before_host": "join_before_host",
            "meeting_authentication": "meeting_authentication",
            "meeting_invitees": "meeting_invitees",
            "waiting_room": False,
        },
        "start_time": "start_time",
        "timezone": None,
        "type": "num_type",
        "topic": False,
    }
    dict_expected_output = {
        "settings": {
            "allow_multiple_devices": "tuyytu",
            "auto_recording": "dyj",
            "encryption_type": "jy",
            "focus_mode": False,
            "jbh_time": "jdfd",
            "join_before_host": "join_before_host",
            "meeting_authentication": "meeting_authentication",
            "meeting_invitees": "meeting_invitees",
            "waiting_room": False,
        },
        "start_time": "start_time",
        "type": "num_type",
        "topic": False,
    }

    assert remove_None_values_from_dict(dict_input) == dict_expected_output


def test_check_start_time_format__wrong_format():
    """Given -
        a time format
    When -
        missing a field
    Then -
        veryfy that the right error wil raise
    """

    from Zoom import check_start_time_format

    with pytest.raises(DemistoException) as e:
        check_start_time_format("2022-13-26T22:22:Z")
    assert e.value.message == "Wrong time format. Use this format: 'yyyy-MM-ddTHH:mm:ssZ' or 'yyyy-MM-ddTHH:mm:ss' "


def test_test_moudle__reciving_errors(mocker):
    mocker.patch.object(Client, "get_oauth_token", return_value=("token", None))
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    mocker.patch.object(Client, "zoom_list_users", side_effect=DemistoException("Invalid access token"))

    from Zoom import test_module

    assert test_module(client=client) == "Invalid credentials. Please verify that your credentials are valid."


def test_test_moudle__reciving_errors1(mocker):
    mocker.patch.object(Client, "get_oauth_token", return_value=("token", None))
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    mocker.patch.object(Client, "zoom_list_users", side_effect=DemistoException("The Token's Signature resulted invalid"))

    from Zoom import test_module

    assert test_module(client=client) == "Invalid API Secret. Please verify that your API Secret is valid."


def test_test_moudle__reciving_errors2(mocker):
    mocker.patch.object(Client, "get_oauth_token", return_value=("token", None))
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    mocker.patch.object(Client, "zoom_list_users", side_effect=DemistoException("Invalid client_id or client_secret"))

    from Zoom import test_module

    assert test_module(client=client) == "Invalid Client ID or Client Secret. Please verify that your ID and Secret is valid."


def test_test_moudle__reciving_errors3(mocker):
    mocker.patch.object(Client, "get_oauth_token", return_value=("token", None))
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    mocker.patch.object(Client, "zoom_list_users", side_effect=DemistoException("mockerror"))

    from Zoom import test_module

    assert test_module(client=client) == "Problem reaching Zoom API, check your credentials. Error message: mockerror"


def test_manual_list_user_pagination__next_page_token_None(mocker):
    """
    Given -
       client
    When -
        limit > 0 and next_page_token == None
    Then -
        # Validate that the pagination process will start
    """
    mocker.patch.object(Client, "generate_oauth_token")
    returned_dict = {
        "page_count": 1,
        "page_number": 1,
        "page_size": 30,
        "total_records": 2,
        "next_page_token": None,
        "users": [
            {
                "id": "1234",
                "first_name": "as",
                "last_name": "bla",
                "email": "example@example.com",
                "type": 1,
                "pmi": 1234,
                "timezone": "Asia/Jerusalem",
                "verified": 1,
                "dept": "",
            }
        ],
    }
    zoom_list_users_mocker = mocker.patch.object(Client, "zoom_list_users", return_value=returned_dict)
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    limit = 5
    from Zoom import manual_list_user_pagination

    manual_list_user_pagination(client=client, next_page_token=None, limit=limit, status="None", role_id="None")
    assert zoom_list_users_mocker.called


def test_manual_meeting_list_pagination__next_page_token_None(mocker):
    """
    Given -
       client
    When -
        limit > 0 and next_page_token == None
    Then -
        # Validate that the pagination process will start
    """
    mocker.patch.object(Client, "generate_oauth_token")
    returned_dict = {
        "page_count": 1,
        "page_number": 1,
        "page_size": 30,
        "total_records": 2,
        "next_page_token": None,
        "users": [
            {
                "id": "1234",
                "first_name": "as",
                "last_name": "bla",
                "email": "example@example.com",
                "type": 1,
                "pmi": 1234,
                "timezone": "Asia/Jerusalem",
                "verified": 1,
                "dept": "",
            }
        ],
    }
    zoom_meeting_list_mocker = mocker.patch.object(Client, "zoom_meeting_list", return_value=returned_dict)
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    limit = 5
    from Zoom import manual_meeting_list_pagination

    manual_meeting_list_pagination(client=client, user_id="bla", next_page_token=None, limit=limit, type="all")
    assert zoom_meeting_list_mocker.called


class MockResponse:
    def __init__(self, text="", content="", raw="", decode_content: bool = False):
        self.text = text
        self.content = content
        self.raw = raw
        self.decode_content = decode_content


def test_zoom_fetch_recording__download_success(mocker):
    """
    Given -
       client
    When -
        asking for a specific recording
    Then:
        Validate that the successfull messege is added to the commandResults
        and the writing function was called.
    """
    import shutil

    from Zoom import zoom_fetch_recording_command

    mocker.patch.object(demisto, "debug")
    mocker.patch.object(shutil, "copyfileobj")
    mocker.patch.object(
        Client,
        "zoom_fetch_recording",
        side_effect=[
            {
                "recording_files": [
                    {
                        "id": "29c7tc",
                        "meeting_id": "Y",
                        "play_url": "hsy",
                        "download_url": "htsy",
                        "status": "completed",
                        "recording_type": "t",
                    }
                ]
            },
            MockResponse(raw=MockResponse(decode_content=False)),
        ],
    )
    mocker.patch.object(Client, "generate_oauth_token")

    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    res = zoom_fetch_recording_command(client=client, meeting_id="000000", delete_after="false")

    assert res[1].readable_output == "The None file recording_000000_29c7tc.None was downloaded successfully"


def test_zoom_fetch_recording_command__delete_success(mocker):
    """
    Given -
       client
    When -
        asking for a specific recording and deleting that recording from the cloud
    Then -
        Validate that the successfull deleting messege is added to the commandResults
    """
    import shutil

    from Zoom import zoom_fetch_recording_command

    mocker.patch.object(demisto, "debug")
    mocker.patch.object(shutil, "copyfileobj")
    mocker.patch.object(
        Client,
        "zoom_fetch_recording",
        side_effect=[
            {
                "recording_files": [
                    {
                        "id": "29c7tc",
                        "meeting_id": "Y",
                        "play_url": "hsy",
                        "download_url": "htsy",
                        "status": "completed",
                        "recording_type": "t",
                    }
                ]
            },
            MockResponse(raw=MockResponse(decode_content=False)),
            MockResponse(text="sff"),
        ],
    )
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    res = zoom_fetch_recording_command(client=client, meeting_id="000000", delete_after="true")

    assert res[2].readable_output == "The None file recording_000000_29c7tc.None was successfully removed from the cloud."


def test_zoom_fetch_recording_command__recording_dose_not_exist(mocker):
    """
    Given -
       client
    When -
        asking for a specific recording that dose not exist
    Then -
        Validate that right error will return
    """
    import shutil

    from Zoom import zoom_fetch_recording_command

    mocker.patch.object(demisto, "debug")
    mocker.patch.object(shutil, "copyfileobj")
    mocker.patch.object(Client, "zoom_fetch_recording", side_effect=[DemistoException("mockerror")])
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    with pytest.raises(DemistoException) as e:
        zoom_fetch_recording_command(client=client, meeting_id="000000", delete_after="true")
    assert e.value.message == "mockerror"


def test_zoom_fetch_recording_command__not_able_to_download(mocker):
    """
    Given -
       client
    When -
        asking for a specific recording that exist, but unable to download
    Then -
        Validate that right error will return
    """
    import shutil

    from Zoom import zoom_fetch_recording_command

    mocker.patch.object(demisto, "debug")
    mocker.patch.object(shutil, "copyfileobj")
    mocker.patch.object(
        Client,
        "zoom_fetch_recording",
        side_effect=[
            {
                "recording_files": [
                    {
                        "id": "29c7tc",
                        "meeting_id": "Y",
                        "play_url": "hsy",
                        "download_url": "htsy",
                        "status": "completed",
                        "recording_type": "t",
                    }
                ]
            },
            DemistoException("mockerror"),
        ],
    )
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    with pytest.raises(DemistoException) as e:
        zoom_fetch_recording_command(client=client, meeting_id="000000", delete_after="true")
    assert e.value.message == "Unable to download recording for meeting 000000: mockerror"


def test_zoom_fetch_recording_command__not_able_to_delete(mocker):
    """
    Given -
       client
    When -
        asking for a specific recording that exist,
        successfull downloading, but but unable to download
    Then -
        Validate that right error will return
    """
    import shutil

    from Zoom import zoom_fetch_recording_command

    mocker.patch.object(demisto, "debug")
    mocker.patch.object(shutil, "copyfileobj")
    mocker.patch.object(
        Client,
        "zoom_fetch_recording",
        side_effect=[
            {
                "recording_files": [
                    {
                        "id": "29c7tc",
                        "meeting_id": "Y",
                        "play_url": "hsy",
                        "download_url": "htsy",
                        "status": "completed",
                        "recording_type": "t",
                    }
                ]
            },
            MockResponse(raw=MockResponse(decode_content=False)),
            DemistoException("mockerror"),
        ],
    )
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    res = zoom_fetch_recording_command(client=client, meeting_id="000000", delete_after="true")
    assert res[2].readable_output == "Failed to delete file recording_000000_29c7tc.None. mockerror"


def test_zoom_list_user_channels_command(mocker):
    """
    Given -
       client
    When -
        asking for a list public channels
    Then -
        Validate that a func has been called
    """
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    channel_id = "channel_id"
    user_id = "user_id"

    expected_url_suffix = f"users/{user_id}/channels/{channel_id}" if channel_id else f"users/{user_id}/channels"

    expected_raw_data = {
        "channels": [
            {
                "jid": "channel_jid_1_t",
                "id": "channel_id_1",
                "name": "Channel 1",
                "type": "public",
                "channel_url": "https://test1.com",
                "next_page_token": "token1",
            },
            {
                "jid": "channel_jid_2",
                "id": "channel_id_2",
                "name": "Channel 2",
                "type": "public",
                "channel_url": "https://test1.com",
                "next_page_token": "token2",
            },
        ]
    }

    expected_results = {
        "UserChannelsNextToken": None,
        "channels": [
            {
                "jid": "channel_jid_1_t",
                "id": "channel_id_1",
                "name": "Channel 1",
                "type": "public",
                "channel_url": "https://test1.com",
                "next_page_token": "token1",
            },
            {
                "jid": "channel_jid_2",
                "id": "channel_id_2",
                "name": "Channel 2",
                "type": "public",
                "channel_url": "https://test1.com",
                "next_page_token": "token2",
            },
        ],
    }

    zoom_list_user_channels_mock = mocker.patch.object(client, "zoom_list_user_channels")
    zoom_list_user_channels_mock.return_value = expected_raw_data

    from Zoom import zoom_list_user_channels_command

    result = zoom_list_user_channels_command(client, channel_id=channel_id, user_id=user_id)

    zoom_list_user_channels_mock.assert_called_with(
        user_id=user_id, page_size=50, next_page_token=None, url_suffix=expected_url_suffix, page_number=1
    )

    assert result.outputs == expected_results
    assert result.outputs["channels"][0]["id"] == expected_results["channels"][0]["id"]
    assert result.outputs["channels"][0]["jid"] == expected_results["channels"][0]["jid"]


def test_zoom_list_user_channels_command__limit(mocker):
    """
    Given -
       client
    When -
        asking for a limit of results
    Then -
        Validate that a func that runs a pagination has been called
    """
    manual_list_user_channel_pagination_mock = mocker.patch.object(Zoom, "manual_list_user_channel_pagination")
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    from Zoom import zoom_list_user_channels_command

    zoom_list_user_channels_command(client=client, user_id="user_id", limit=5)
    assert manual_list_user_channel_pagination_mock.called


def test_zoom_create_channel_command(mocker):
    """
    Given -
        client
    When -
        creating a Zoom channel
    Then -
        Validate that the zoom_create_channel function is called with the correct arguments
        Validate the command results including outputs and readable output
    """
    # Mock the response from zoom_create_channel
    response = {"id": "channel_id", "name": "TestChannel3", "type": "1", "channel_url": "https://zoom.us/channel/channel_id"}
    zoom_create_channel_mock = mocker.patch.object(Client, "zoom_create_channel", return_value=response)

    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    from Zoom import zoom_create_channel_command

    # Set up the inputs
    user_id = "u12345"
    member_emails = ["user2@example.com", "user1@example.com"]
    add_member_permissions = "All channel members can add"
    posting_permissions = "All members can post"
    new_members_can_see_prev_msgs = True
    channel_name = "TestChannel"
    channel_type = "Private channel"

    zoom_create_channel_command(
        client=client,
        user_id=user_id,
        member_emails=member_emails,
        add_member_permissions=add_member_permissions,
        posting_permissions=posting_permissions,
        new_members_can_see_prev_msgs=new_members_can_see_prev_msgs,
        channel_name=channel_name,
        channel_type=channel_type,
    )

    # Verify the API call
    expected_url_suffix = f"/chat/users/{user_id}/channels"
    expected_json_data = {
        "channel_settings": {
            "add_member_permissions": 1,
            "new_members_can_see_previous_messages_files": True,
            "posting_permissions": 1,
        },
        "members": [{"email": "user2@example.com"}, {"email": "user1@example.com"}],
        "name": "TestChannel",
        "type": 1,
    }
    zoom_create_channel_mock.assert_called_with(expected_url_suffix, expected_json_data)


def test_zoom_delete_channel_command(mocker):
    """
    Given -
        client
    When -
        deleting a Zoom channel
    Then -
        Validate that the zoom_delete_channel function is called with the correct arguments
    """
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    channel_id = "channel_id"
    user_id = "user_id"
    expected_url_suffix = f"/chat/users/{user_id}/channels/{channel_id}"

    zoom_delete_channel_mock = mocker.patch.object(client, "zoom_delete_channel")
    from Zoom import zoom_delete_channel_command

    zoom_delete_channel_command(client, channel_id=channel_id, user_id=user_id)

    zoom_delete_channel_mock.assert_called_with(expected_url_suffix)


def test_zoom_update_channel_command(mocker):
    """
    Given -
        client
    When -
        updating a Zoom channel
    Then -
        Validate that the zoom_update_channel function is called with the correct arguments
    """
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    add_member_permissions = "All channel members can add"
    posting_permissions = "All members can post"
    new_members_can_see_prev_msgs = True
    channel_name = "TestChannel"
    channel_id = "channel_id"
    user_id = "user_id"

    expected_url_suffix = f"/chat/users/{user_id}/channels/{channel_id}"
    expected_json_data = {
        "name": channel_name,
        "channel_settings": {
            "add_member_permissions": 1,
            "new_members_can_see_previous_messages_files": new_members_can_see_prev_msgs,
            "posting_permissions": 1,
        },
    }

    zoom_update_channel_mock = mocker.patch.object(client, "zoom_update_channel")
    from Zoom import zoom_update_channel_command

    zoom_update_channel_command(
        client,
        add_member_permissions=add_member_permissions,
        posting_permissions=posting_permissions,
        new_members_can_see_prev_msgs=new_members_can_see_prev_msgs,
        channel_name=channel_name,
        channel_id=channel_id,
        user_id=user_id,
    )

    zoom_update_channel_mock.assert_called_with(expected_url_suffix, expected_json_data)


def test_zoom_invite_to_channel_command(mocker):
    """
    Given -
        client
    When -
        Invite user to a Zoom channel
    Then -
        Validate that the zoom_invite_to_channel function is called with the correct arguments
    """
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    channel_id = "channel_id"
    user_id = "user_id"
    members = ["user1@example.com", "user2@example.com"]
    expected_url_suffix = f"/chat/users/{user_id}/channels/{channel_id}/members"
    expected_json_data = {"members": [{"email": "user1@example.com"}, {"email": "user2@example.com"}]}
    from Zoom import zoom_invite_to_channel_command

    zoom_invite_to_channel_mock = mocker.patch.object(client, "zoom_invite_to_channel")

    # Convert MagicMock to dictionary
    zoom_invite_to_channel_mock.return_value = expected_json_data

    zoom_invite_to_channel_command(client, channel_id=channel_id, user_id=user_id, members=members)

    zoom_invite_to_channel_mock.assert_called_with(expected_json_data, expected_url_suffix)


def test_zoom_remove_from_channel_command(mocker):
    """
    Given -
        client
    When -
        Remove user from a Zoom channel
    Then -
        Validate that the zoom_remove_from_channel function is called with the correct arguments
    """
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    channel_id = "channel_id"
    member_id = "member_id"
    user_id = "user_id"
    expected_url_suffix = f"/chat/users/{user_id}/channels/{channel_id}/members/{member_id}"

    zoom_remove_from_channel_mock = mocker.patch.object(client, "zoom_remove_from_channel")
    from Zoom import zoom_remove_from_channel_command

    zoom_remove_from_channel_command(client, channel_id=channel_id, member_id=member_id, user_id=user_id)

    zoom_remove_from_channel_mock.assert_called_with(expected_url_suffix)


def test_zoom_send_file_command(mocker):
    """
    Given -
        client
    When -
        Zoom send file to channel
    Then -
        Validate that the zoom_send_file function is called with the correct arguments
        Validate the command results including outputs and readable output

    """
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    user_id = "user_id"
    to_channel = "channel_id"
    entry_id = "entry_id"

    expected_upload_url = f"https://file.zoom.us/v2/chat/users/{user_id}/messages/files"
    expected_file_info = {"name": "test_file.txt", "path": "/path/to/test_file.txt"}
    expected_json_data = {"to_channel": to_channel}
    expected_upload_response = {"id": "file_id"}

    mocker.patch("Zoom.demisto.getFilePath", return_value=expected_file_info)

    zoom_send_file_mock = mocker.patch.object(client, "zoom_send_file", return_value=expected_upload_response)

    from Zoom import zoom_send_file_command

    results = zoom_send_file_command(client, user_id=user_id, to_channel=to_channel, entry_id=entry_id)

    # Assert function calls
    Zoom.demisto.getFilePath.assert_called_with(entry_id)
    zoom_send_file_mock.assert_called_with(expected_upload_url, expected_file_info, expected_json_data)

    # Assert results
    assert results.readable_output == "Message with id file_id was successfully sent"


def test_zoom_list_account_public_channels_command(mocker):
    """
    Given -
       client
    When -
        asking for a list public channels
    Then -
        Validate that a func has been called
    """
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    page_size = 50
    channel_id = "channel_id"
    next_page_token = "next_page_token"
    page_number = 2

    expected_url_suffix = f"channels/{channel_id}" if channel_id else "channels"
    expected_raw_data = {
        "channels": [
            {
                "jid": "channel_jid_1",
                "id": "channel_id_1",
                "name": "Channel 1",
                "type": "public",
                "channel_url": "https://test1.com",
                "next_page_token": "token1",
            },
            {
                "jid": "channel_jid_2",
                "id": "channel_id_2",
                "name": "Channel 2",
                "type": "public",
                "channel_url": "https://test1.com",
                "next_page_token": "token2",
            },
        ]
    }

    zoom_list_channels_mock = mocker.patch.object(client, "zoom_list_channels")
    zoom_list_channels_mock.return_value = expected_raw_data

    from Zoom import zoom_list_account_public_channels_command

    result = zoom_list_account_public_channels_command(
        client, page_size=page_size, channel_id=channel_id, next_page_token=next_page_token, page_number=page_number
    )

    zoom_list_channels_mock.assert_called_with(
        page_size=page_size, next_page_token=next_page_token, url_suffix=expected_url_suffix, page_number=page_number
    )

    expected_results = {
        "channels": [
            {
                "jid": "channel_jid_1",
                "id": "channel_id_1",
                "name": "Channel 1",
                "type": "public",
                "channel_url": "https://test1.com",
                "next_page_token": "token1",
            },
            {
                "jid": "channel_jid_2",
                "id": "channel_id_2",
                "name": "Channel 2",
                "type": "public",
                "channel_url": "https://test1.com",
                "next_page_token": "token2",
            },
        ],
        "ChannelsNextToken": None,
    }

    assert result.outputs == expected_results
    assert result.outputs["channels"][0]["id"] == expected_results["channels"][0]["id"]
    assert result.outputs["channels"][0]["jid"] == expected_results["channels"][0]["jid"]


def test_zoom_list_account_public_channels_command__limit(mocker):
    """
    Given -
       client
    When -
        zoom list public account with limit of results
    Then -
        Validate that a func that runs a pagination has been called
    """
    manual_manual_list_channel_paginatio_mock = mocker.patch.object(Zoom, "manual_list_channel_pagination")
    mocker.patch.object(Client, "generate_oauth_token")
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    from Zoom import zoom_list_account_public_channels_command

    zoom_list_account_public_channels_command(client=client, user_id="example@example.com", limit=5)
    assert manual_manual_list_channel_paginatio_mock.called


def test_zoom_send_message_command_with_file(mocker):
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    entry_id = "entry_id"
    user_id = "user1"

    expected_file_info = {"name": "test_file.txt", "path": "/path/to/test_file.txt"}
    expected_upload_response = {"id": "file_id"}
    expected_uplaod_file_url = f"https://file.zoom.us/v2/chat/users/{user_id}/files"

    expected_response = {"id": "message_id", "contact": "user2@example.com", "channel_name": "channel_name"}

    mocker.patch("Zoom.demisto.getFilePath", return_value=expected_file_info)
    zoom_send_file_mock = mocker.patch.object(client, "zoom_upload_file", return_value=expected_upload_response)
    mock_send_chat_message = mocker.patch.object(client, "zoom_send_message")
    mock_send_chat_message.return_value = expected_response
    from Zoom import zoom_send_message_command

    zoom_send_message_command(client, user_id=user_id, message="Hello from @dima!", to_channel="channel1", entry_ids="entry_id")
    # Assert function calls
    Zoom.demisto.getFilePath.assert_called_with(entry_id)
    zoom_send_file_mock.assert_called_with(expected_uplaod_file_url, expected_file_info)


def test_zoom_send_message_command(mocker):
    """
    Given -
        client
    When -
        send message to channel
    Then -
        Validate that the zoom_send_message function is called with the correct arguments
        Validate the command results including outputs and readable output
    """
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    expected_request_payload = {"message": "Hello from @dima!", "to_channel": "channel1", "file_ids": []}

    expected_response = {"id": "message_id", "contact": "user2@example.com", "channel_name": "channel_name"}

    mock_send_chat_message = mocker.patch.object(client, "zoom_send_message")
    mock_send_chat_message.return_value = expected_response
    from Zoom import zoom_send_message_command

    result = zoom_send_message_command(
        client,
        user_id="user1",
        message="Hello from @dima!",
        to_channel="channel1",
    )

    assert result.outputs == expected_response
    assert mock_send_chat_message.call_args[0][1] == expected_request_payload


def test_zoom_send_message_markdown_command(mocker):
    """
    Given -
        client
    When -
        send message to channel with markdown
    Then -
        Validate that the zoom_send_message function is called with the correct arguments
        Validate the command results including outputs and readable output
    """
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    expected_request_payload = {
        "message": "HI \n@John, please review the following report",
        "to_channel": "channel1",
        "at_items": [{"text": "@John", "at_contact": "user2@example.com", "at_type": 1, "start_position": 4, "end_position": 8}],
        "rich_text": [
            {
                "text": "report",
                "format_type": "AddLink",
                "format_attr": "https://example.com",
                "start_position": 39,
                "end_position": 44,
            },
            {"text": "HI ", "format_type": "paragraph", "format_attr": "h1", "start_position": 0, "end_position": 2},
            {
                "text": "@John, please review the following report",
                "format_type": "LeftIndent",
                "format_attr": 40,
                "start_position": 4,
                "end_position": 44,
            },
        ],
        "file_ids": [],
    }

    expected_response = {"id": "message_id", "contact": "user2@example.com", "channel_name": "channel_name"}

    mock_send_chat_message = mocker.patch.object(client, "zoom_send_message")
    mock_send_chat_message.return_value = expected_response
    from Zoom import zoom_send_message_command

    result = zoom_send_message_command(
        client,
        user_id="user1",
        at_contact="user2@example.com",
        is_markdown=True,
        message="# HI \n>> @John, please review the following [report](https://example.com)",
        to_channel="channel1",
    )

    assert result.outputs == expected_response
    assert mock_send_chat_message.call_args[0][1] == expected_request_payload


def test_zoom_send_message_markdown_command_error_mentions(mocker):
    """
    Given -
        client
    When -
        send message to channel with invalid markdown
    Then -
        Validate that an exception is raised
    """
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    from Zoom import zoom_send_message_command

    with pytest.raises(Exception) as e:
        zoom_send_message_command(
            client,
            user_id="user1",
            at_contact="user2@example.com",
            is_markdown=True,
            message="@user This is an @invalid markdown",
            to_channel="channel1",
        )

    assert str(e.value) == "Too many mentions in text. you can provide only one mention in each message"


def test_zoom_list_messages_command(mocker):
    """
    Given -
        client
    When -
        get all messages in date
    Then -
        Validate that the zoom_list_messages_command function is called with the correct arguments
        Validate the command results including outputs and readable output
    """
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    channel_id = "channel_id"
    user_id = "user_id"
    limit = 100
    to_contact = "contact@example.com"
    to_channel = "channel_id"
    date_arg = "2023-03-07T00:49:01Z"
    include_deleted_and_edited_message = True
    search_type = "message"
    search_key = "keyword"
    exclude_child_message = False

    expected_raw_data = {
        "messages": [
            {
                "id": "message_id_1",
                "message": "Message 1",
                "sender": "sender_1",
                "sender_display_name": "Sender 1",
                "date_time": "2023-03-07T10:30:00Z",
            },
            {
                "id": "message_id_2",
                "message": "Message 2",
                "sender": "sender_2",
                "sender_display_name": "Sender 2",
                "date_time": "2023-03-08T09:15:00Z",
            },
        ]
    }
    expacted_result = {
        "ChatMessage": {
            "messages": [
                {
                    "id": "message_id_1",
                    "message": "Message 1",
                    "sender": "sender_1",
                    "sender_display_name": "Sender 1",
                    "date_time": "2023-03-07T10:30:00Z",
                },
                {
                    "id": "message_id_2",
                    "message": "Message 2",
                    "sender": "sender_2",
                    "sender_display_name": "Sender 2",
                    "date_time": "2023-03-08T09:15:00Z",
                },
            ]
        },
        "ChatMessageNextToken": None,
    }
    client.zoom_list_user_messages = mocker.MagicMock(return_value=expected_raw_data)
    from Zoom import zoom_list_messages_command

    result = zoom_list_messages_command(
        client,
        channel_id=channel_id,
        user_id=user_id,
        next_page_token="next_page_token",
        limit=limit,
        to_contact=to_contact,
        to_channel=to_channel,
        date=date_arg,
        include_deleted_and_edited_message=include_deleted_and_edited_message,
        search_type=search_type,
        search_key=search_key,
        exclude_child_message=exclude_child_message,
    )

    assert result.outputs == expacted_result
    assert result.outputs["ChatMessage"]["messages"][0]["id"] == expacted_result["ChatMessage"]["messages"][0]["id"]
    assert result.outputs["ChatMessage"]["messages"][0]["message"] == expacted_result["ChatMessage"]["messages"][0]["message"]
    assert result.outputs["ChatMessage"]["messages"][0]["sender"] == expacted_result["ChatMessage"]["messages"][0]["sender"]
    assert (
        result.outputs["ChatMessage"]["messages"][0]["sender_display_name"]
        == expacted_result["ChatMessage"]["messages"][0]["sender_display_name"]
    )  # noqa: E501
    assert result.outputs["ChatMessage"]["messages"][0]["date_time"] == expacted_result["ChatMessage"]["messages"][0]["date_time"]


def test_zoom_list_messages_command_pageination(mocker):
    """
    Given -
        client
    When -
        get all messages in date
    Then -
        Validate that the zoom_list_messages_command function is called with the correct arguments
        Validate the command results including outputs and readable output
    """
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    channel_id = "channel_id"
    user_id = "user_id"
    limit = 1
    to_contact = "contact@example.com"
    to_channel = "channel_id"
    date_arg = "2023-03-07T00:49:01Z"
    include_deleted_and_edited_message = True
    search_type = "message"
    search_key = "keyword"
    exclude_child_message = False

    expected_raw_data = {
        "messages": [
            {
                "id": "message_id_1",
                "message": "Message 1",
                "sender": "sender_1",
                "sender_display_name": "Sender 1",
                "date_time": "2023-03-07T10:30:00Z",
            }
        ],
        "next_page_token": "xxxxxxxxxxx",
    }
    expacted_result = {
        "ChatMessage": {
            "messages": [
                {
                    "id": "message_id_1",
                    "message": "Message 1",
                    "sender": "sender_1",
                    "sender_display_name": "Sender 1",
                    "date_time": "2023-03-07T10:30:00Z",
                }
            ]
        },
        "ChatMessageNextToken": {
            "user_id": "user_id",
            "to_contact": "contact@example.com",
            "to_channel": "channel_id",
            "date": "2023-03-07T00:49:01Z",
            "include_deleted_and_edited_message": True,
            "search_type": "message",
            "search_key": "keyword",
            "exclude_child_message": False,
            "page_size": 1,
            "next_page_token": "xxxxxxxxxxx",
        },
    }
    client.zoom_list_user_messages = mocker.MagicMock(return_value=expected_raw_data)
    from Zoom import zoom_list_messages_command

    result = zoom_list_messages_command(
        client,
        channel_id=channel_id,
        user_id=user_id,
        next_page_token="next_page_token",
        limit=limit,
        to_contact=to_contact,
        to_channel=to_channel,
        date=date_arg,
        include_deleted_and_edited_message=include_deleted_and_edited_message,
        search_type=search_type,
        search_key=search_key,
        exclude_child_message=exclude_child_message,
    )

    assert result.outputs == expacted_result
    assert result.outputs["ChatMessageNextToken"]["user_id"] == expacted_result["ChatMessageNextToken"]["user_id"]
    assert result.outputs["ChatMessageNextToken"]["date"] == expacted_result["ChatMessageNextToken"]["date"]


def test_zoom_update_message_command(mocker):
    """
    Given -
        client
    When -
        update a message that was send
    Then -
        Validate that the zoom_update_message function is called with the correct arguments
        Validate the command results including outputs and readable output
    """
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    mocker.patch.object(Client, "generate_oauth_token")

    user_id = "user1"
    message_id = "2d12042d-1823-4b0c-b26d-3f5ef7a89d68"
    message = "Hello! this is message for all"
    to_channel = "channel1"
    to_contact = "user2@example.com"
    # entry_ids = ["file_entry_id1", "file_entry_id2"]

    expected_payload = {"message": message, "file_ids": [], "to_channel": to_channel, "to_contact": to_contact}

    zoom_update_message_mock = mocker.patch.object(client, "zoom_update_message")

    from Zoom import zoom_update_message_command

    result = zoom_update_message_command(
        client,
        user_id=user_id,
        message_id=message_id,
        message=message,
        to_channel=to_channel,
        to_contact=to_contact,
        # entry_ids=entry_ids
    )

    # Test case: Update message with to_channel
    zoom_update_message_mock.assert_called_with(f"/chat/users/{user_id}/messages/{message_id}", expected_payload)

    assert result.readable_output == "Message 2d12042d-1823-4b0c-b26d-3f5ef7a89d68 was successfully updated"


def test_zoom_delete_message_command(mocker):
    """
    Given -
        client
    When -
       delete zoom message
    Then -
        Validate that the zoom_delete_message function is called with the correct arguments
        Validate the command results including outputs and readable output
    """
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    mocker.patch.object(Client, "generate_oauth_token")

    user_id = "user1"
    message_id = "2d12042d-1823-4b0c-b26d-3f5ef7a89d68"
    to_channel = "channel1"
    # entry_ids = ["file_entry_id1", "file_entry_id2"]

    zoom_delete_message_mock = mocker.patch.object(client, "zoom_delete_message")

    from Zoom import zoom_delete_message_command

    result_to_channel = zoom_delete_message_command(
        client,
        user_id=user_id,
        message_id=message_id,
        to_channel=to_channel,
        # entry_ids=entry_ids
    )
    # Test case: Update message with to_channel
    zoom_delete_message_mock.assert_called_with(f"/chat/users/{user_id}/messages/{message_id}?to_channel={to_channel}")

    assert result_to_channel.readable_output == "Message 2d12042d-1823-4b0c-b26d-3f5ef7a89d68 was deleted successfully"


def test_zoom_get_user_id_by_email(mocker):
    """
    Given -
        client
    When -
        get userID by his email
    Then -
        Validate that the zoom_get_user_id_by_email function is called with the correct arguments
        Validate the command results
    """
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    email = "user@example.com"

    expected_user_id = "user_id"
    expected_response = {"id": expected_user_id}

    mock_zoom_list_users = mocker.patch.object(client, "zoom_list_users", return_value=expected_response)
    from Zoom import zoom_get_user_id_by_email

    result = zoom_get_user_id_by_email(client, email)
    mock_zoom_list_users.assert_called_with(page_size=50, url_suffix=f"users/{email}")
    assert result == expected_user_id


def test_zoom_get_user_email_by_id(mocker):
    """
    Given -
        client
    When -
        get user email address by their user ID
    Then -
        Validate that the get_user_email_by_id function is called with the correct arguments
        Validate the command results
    """
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    user_id = "user_id"
    expected_user_email = "user@example.com"
    expected_response = {"email": expected_user_email}

    mock_zoom_list_users = mocker.patch.object(client, "zoom_list_users", return_value=expected_response)
    from Zoom import zoom_get_user_email_by_id

    result = zoom_get_user_email_by_id(client, user_id)
    mock_zoom_list_users.assert_called_with(page_size=1, url_suffix=f"users/{user_id}")
    assert result == expected_user_email


def test_zoom_send_notification_command(mocker):
    """
    Given -
        client
    When -
        send message to channel
    Then -
        Validate that the zoom_send_message function is called with the correct arguments
        Validate the command results including outputs and readable output
    """
    client = Client(
        base_url="https://test.com",
        account_id="mockaccount",
        client_id="mockclient",
        client_secret="mocksecret",
        bot_client_id="mockclient",
        bot_client_secret="mocksecret",
    )
    client.bot_jid = "mock_bot"

    expected_request_payload = {
        "robot_jid": "mock_bot",
        "to_jid": "channel1@xmpp.zoom.us",
        "account_id": "mockaccount",
        "content": {"head": {"type": "message", "text": "Hello"}},
    }

    expected_response = {
        "message_id": "message_id",
    }

    mock_send_chat_message = mocker.patch.object(client, "zoom_send_notification")
    mock_send_chat_message.return_value = expected_response
    from Zoom import send_notification

    result = send_notification(
        client,
        user_id="user1",
        message="Hello",
        to="channel1",
    )

    assert result.readable_output == "Message sent to Zoom successfully. Message ID is: message_id"
    assert mock_send_chat_message.call_args[0][1] == expected_request_payload


def test_zoom_delete_user_token_command(mocker):
    """
    Given -
        Zoom client
    When -
       zoom-delete-user-token has called
    Then -
        Validate that the zoom_delete_user_token function is called with the correct arguments
        Validate the command results return the correct readable output
    """

    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    mocker.patch.object(Client, "generate_oauth_token")

    user_id = "mock_user_id"
    zoom_delete_user_token_mock = mocker.patch.object(client, "zoom_delete_user_token")

    from Zoom import zoom_delete_user_token_command

    result = zoom_delete_user_token_command(client, user_id=user_id)
    zoom_delete_user_token_mock.assert_called_with(f"/users/{user_id}/token")
    assert result.readable_output == "User SSO token for user mock_user_id is deleted"


@pytest.mark.parametrize(
    "channel_name, investigation_id, expected_result",
    [
        ("Channel1", None, "JID1"),  # Scenario 1: Find by channel_name
        (None, "Incident123", "JID1"),  # Scenario 2: Find by investigation_id
        ("NonExistentChannel", None, None),  # Scenario 3: Channel not found
    ],
)
def test_get_channel_jid_by_channel_name(channel_name, investigation_id, expected_result, mocker):
    """
    Given different scenarios with channel_name and investigation_id parameters,
    When calling the get_channel_jid_from_context function,
    Then validate that the function returns the expected result.
    """
    # Mock integration context
    Zoom.CACHE_EXPIRY = False
    mock_integration_context = {
        "mirrors": json.dumps(
            [
                {"channel_name": "Channel1", "channel_jid": "JID1", "investigation_id": "Incident123"},
                {"channel_name": "Channel2", "channel_jid": "JID2", "investigation_id": "Incident123"},
            ]
        )
    }
    mocker.patch.object(demisto, "getIntegrationContext", return_value=mock_integration_context)

    # Call the function
    from Zoom import get_channel_jid_from_context

    result = get_channel_jid_from_context(channel_name, investigation_id)

    # Assert the result
    assert result == expected_result


# Test cases for check_authentication_bot_parameters
@pytest.mark.parametrize(
    "bot_Jid, client_id, client_secret, expected_exception",
    [
        ("bot_Jid", "client_id", "client_secret", None),  # Scenario 1: All parameters provided
        (None, None, None, None),  # Scenario 2: All parameters None
        ("bot_Jid", None, None, DemistoException),  # Scenario 3: bot_Jid provided, others None
        (None, "client_id", None, DemistoException),  # Scenario 4: client_id provided, others None
        (None, None, "client_secret", DemistoException),  # Scenario 5: client_secret provided, others None
    ],
)
def test_check_authentication_bot_parameters(bot_Jid, client_id, client_secret, expected_exception):
    """
    Given different scenarios with bot_Jid, client_id, and client_secret parameters,
    When calling the check_authentication_bot_parameters function,
    Then validate that the function raises the expected exception or returns without raising an exception.
    """
    from Zoom import check_authentication_bot_parameters

    if expected_exception:
        with pytest.raises(expected_exception):
            check_authentication_bot_parameters(bot_Jid, client_id, client_secret)
    else:
        check_authentication_bot_parameters(bot_Jid, client_id, client_secret)


def test_get_admin_user_id_from_token(mocker):
    """
    Given a mock client with a zoom_get_admin_user_id_from_token method,
    When calling the get_admin_user_id_from_token function,
    Then validate that the function returns the expected user ID.
    """
    # Create a mock client
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    mocker.patch.object(client, "zoom_get_admin_user_id_from_token", return_value={"id": "mock_user_id"})
    # Call the function
    from Zoom import get_admin_user_id_from_token

    result = get_admin_user_id_from_token(client)

    # Assert the result
    assert result == "mock_user_id"


def test_mirror_investigation_create_new_channel(mocker):
    """
    Given a mock client and relevant arguments,
    When calling the mirror_investigation function to create a new channel,
    Then validate that the function returns the expected CommandResults.
    """
    Zoom.MIRRORING_ENABLED = True
    Zoom.LONG_RUNNING = True
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    client.bot_jid = "mock_jid"
    mocker.patch.object(client, "zoom_send_notification")
    mocker.patch.object(Zoom, "get_admin_user_id_from_token", return_value="mock_user_id")
    mocker.patch.object(
        Zoom, "zoom_create_channel_command", return_value=CommandResults(outputs={"jid": "mock_jid", "id": "mock_id"})
    )
    mocker.patch.object(demisto, "demistoUrls", return_value={"server": "mock_server_url"})
    # mocker.patch.object(client, 'botJid', return_value='bot_jid_mock')

    # Test data
    args = {
        "type": "all",
        "direction": "Both",
        "channelName": "mirror-channel",
        "autoclose": True,
    }

    # Call the function
    from Zoom import mirror_investigation

    result = mirror_investigation(client, **args)

    # Assert the result
    assert "Investigation mirrored successfully" in result.readable_output


@pytest.mark.asyncio
async def test_check_and_handle_entitlement(mocker):
    """
    Test the asynchronous function check_and_handle_entitlement.
    Given:
    - Input parameters for the function: text, message_id, user_name.
    When:
    - Calling the asynchronous function check_and_handle_entitlement with the given input parameters.
    Then:
    - Validate that the function behaves as expected and returns the expected result.
    """
    # Mock integration context
    mock_integration_context = {
        "messages": json.dumps(
            [
                {
                    "message_id": "MessageID123",
                    "entitlement": "3dcaae6d-d4d2-45b3-81a7-834bce779009@2b03d219-bbac-4333-84a2-d329d7296baa",
                    "reply": "thanks",
                    "expiry": "2023-08-29 12:32:40",
                    "sent": "2023-08-29 12:27:42",
                    "default_response": "NoResponse",
                }
            ]
        )
    }
    mocker.patch.object(demisto, "getIntegrationContext", return_value=mock_integration_context)
    Zoom.CACHE_EXPIRY = False
    # Define the input parameters for the function
    text = "Entitlement Text"
    message_id = "MessageID123"
    user_name = "User123"
    user_id = "user123@example.com"

    # Call the async function and await its result
    from Zoom import check_and_handle_entitlement

    result = await check_and_handle_entitlement(text, message_id, user_name, user_id)

    assert result == "thanks"  # Adjust the expected reply as needed


@pytest.mark.parametrize(
    "entitlement, expected_result",
    [
        ("guid123@incident456|task789", ("guid123", "incident456", "task789")),  # Scenario 1: Full entitlement
        ("guid123@incident456", ("guid123", "incident456", "")),  # Scenario 2: No task ID
        ("guid123@", ("guid123", "", "")),  # Scenario 3: No incident ID or task ID
    ],
)
def test_extract_entitlement(entitlement, expected_result):
    """
    Test the extract_entitlement function.
    Given:
    - Input entitlement string.
    When:
    - Calling the extract_entitlement function with the given input entitlement.
    Then:
    - Validate that the function correctly extracts the entitlement components: guid, incident_id, and task_id.
    """
    from Zoom import extract_entitlement

    result = extract_entitlement(entitlement)

    # Assert the result against the expected outcome
    assert result == expected_result


# @pytest.mark.asyncio
# async def test_check_for_unanswered_questions(mocker):
#     mock_integration_context = {
#         'messages': json.dumps([
#             {
#                 'message_id': 'MessageID1',
#                 'expiry': '2023-08-29 12:00:00',
#                 'default_response': 'DefaultResponse1'
#             },
#             {
#                 'message_id': 'MessageID2',
#                 'expiry': '2023-08-29 14:00:00',
#                 'default_response': 'DefaultResponse2'
#             },
#         ])
#     }
#     mocker.patch.object(demisto, 'getIntegrationContext', return_value=mock_integration_context)


@pytest.mark.asyncio
async def test_answer_question(mocker):
    """
    Test the answer_question function.
    Given:
    - A mocked question dictionary.
    When:
    - Calling the answer_question function with the mocked question.
    Then:
    - Validate that the function correctly handles the entitlement and returns the incident_id.
    """

    mock_question = {"entitlement": "guid123@incident456|task789", "to_jid": "ToJID123"}
    Zoom.CLIENT = Client(
        base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret"
    )
    Zoom.CLIENT.bot_jid = "mock_bot_id"
    mocker.patch.object(Zoom, "process_entitlement_reply")

    from Zoom import answer_question

    result = await answer_question("Answer123", mock_question, "user@example.com")
    assert result == "incident456"


@pytest.mark.asyncio
async def test_process_entitlement_reply(mocker):
    """
    Test the process_entitlement_reply function.

    Given:
    - Mocked input parameters.

    When:
    - Calling the process_entitlement_reply function with the mocked parameters.

    Then:
    - Validate that the function correctly prepares and sends a Zoom notification.
    """
    # Mocked input parameters
    mock_entitlement_reply = "Entitlement Reply"
    mock_account_id = "mock_account_id"
    mock_robot_jid = "mock_robot_jid"
    mock_to_jid = "mock_to_jid"
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")
    # Mock the CLIENT.zoom_send_notification function
    Zoom.CLIENT = client
    mock_zoom_send_notification = mocker.AsyncMock()
    mock_zoom_send_notification = mocker.patch.object(Zoom, "zoom_send_notification_async")

    # Call the function with the mocked parameters
    from Zoom import process_entitlement_reply

    await process_entitlement_reply(mock_entitlement_reply, mock_account_id, mock_robot_jid, mock_to_jid)

    # Assert that the CLIENT.zoom_send_notification function was called with the correct arguments
    mock_zoom_send_notification.assert_called_with(
        client,
        "/im/chat/messages",
        {
            "content": {"body": [{"type": "message", "text": mock_entitlement_reply}]},
            "to_jid": mock_to_jid,
            "robot_jid": mock_robot_jid,
            "account_id": mock_account_id,
        },
    )


# Test cases
@pytest.mark.asyncio
async def test_close_channel(mocker):
    """
    Test the close_channel function
    Given:
    - Mocked input parameters.
    When:
    - Calling the close_channel function.
    Then:
    - Ensure that the function successfully closes the channel.
    """
    mock_integration_context = {
        "mirrors": json.dumps(
            [
                {
                    "channel_name": "Channel1",
                    "channel_jid": "JID1",
                    "channel_id": "ID1",
                    "investigation_id": "Incident123",
                    "mirror_direction": "both",
                    "auto_close": True,
                },
                {
                    "channel_name": "Channel2",
                    "channel_jid": "JID2",
                    "channel_id": "ID2",
                    "investigation_id": "Incident123",
                    "mirror_direction": "both",
                    "auto_close": True,
                },
            ]
        )
    }
    client = Client(base_url="https://test.com", account_id="mockaccount", client_id="mockclient", client_secret="mocksecret")

    mocker.patch.object(Zoom, "zoom_delete_channel_command")
    mocker.patch.object(demisto, "mirrorInvestigation")
    mocker.patch.object(Zoom, "get_integration_context", return_value=mock_integration_context)
    mocker.patch.object(Zoom, "set_to_integration_context_with_retries")
    mocker.patch.object(Zoom, "get_admin_user_id_from_token", return_value="mock_user_id")
    mocker.patch.object(Zoom, "find_mirror_by_investigation", return_value={"channel_id": "ID1"})

    from Zoom import close_channel

    result = close_channel(client)

    assert result == "Channel successfully deleted."


@pytest.mark.parametrize(
    "event_type, expected_status",
    [
        ("endpoint.url_validation", status.HTTP_200_OK),
        ("interactive_message_actions", status.HTTP_200_OK),
        ("invalid_event_type", status.HTTP_400_BAD_REQUEST),
    ],
)
@pytest.mark.asyncio
async def test_handle_zoom_response(event_type, expected_status, mocker):
    """
    Test the handle_zoom_response function with different event types and payload conditions.

    Given:
    - Mocked request object.
    - Mocked event_url_validation, check_and_handle_entitlement, process_entitlement_reply, and handle_mirroring functions.
    - Parameters for event types and payload conditions.

    When:
    - Calling the handle_zoom_response function with different event types and payload conditions.

    Then:
    - Ensure that the function returns the expected response status code.
    """
    mock_request = mocker.Mock(spec=Request)
    json_res = {"plainToken": 123, "encryptedToken": 123}
    mocker.patch("Zoom.event_url_validation", return_value=json_res)
    mocker.patch("Zoom.check_and_handle_entitlement")
    mocker.patch("Zoom.process_entitlement_reply")
    mocker.patch("Zoom.handle_mirroring")
    mocker.patch("Zoom.zoom_get_user_email_by_id", return_value="mock_user_email")
    mocker.patch.object(demisto, "params", return_value={"credentials": {"identifier": "test", "password": "testpass"}})

    # Create a mock HTTPBasicCredentials object
    mock_credentials = HTTPBasicCredentials(username="test", password="testpass")

    Zoom.SECRET_TOKEN = "token"

    from Zoom import handle_zoom_response

    mock_request.json.return_value = {
        "event": event_type,
        "payload": {
            "accountId": "mock_accountid",
            "actionItem": {"text": "no", "value": "no", "action": "command"},
            "messageId": "message_id",
            "robotJid": "robot_jid",
            "toJid": "mock_jid",
            "userName": "admin zoom",
            "userId": "mock_userId",
        },
    }

    response = await handle_zoom_response(mock_request, mock_credentials)

    assert response.status_code == expected_status


@pytest.mark.asyncio
async def test_event_url_validation():
    Zoom.SECRET_TOKEN = "secret_token"

    # Define the payload for testing
    payload = {"plainToken": "plain_token"}

    # Calculate the expected signature
    import hashlib
    import hmac

    hash_object = hmac.new(Zoom.SECRET_TOKEN.encode("utf-8"), msg=payload["plainToken"].encode("utf-8"), digestmod=hashlib.sha256)
    expected_signature = hash_object.hexdigest()

    from Zoom import event_url_validation

    response = await event_url_validation(payload)

    # Verify that the response matches the expected signature
    assert response == {"plainToken": payload["plainToken"], "encryptedToken": expected_signature}


@pytest.mark.asyncio
async def test_handle_text(mocker):
    # Create mock arguments
    investigation_id = "123"
    text = "Hello, this is a test message"
    operator_email = "test@example.com"
    operator_name = "Test User"
    MESSAGE_FOOTER = "\n**From Zoom**"
    from Zoom import handle_text_received_from_zoom

    with patch("Zoom.demisto") as mock_demisto:
        # Call the function
        await handle_text_received_from_zoom(investigation_id, text, operator_email, operator_name)
        # Assert that the `demisto.addEntry` method was called with the expected arguments
        mock_demisto.addEntry.assert_called_once_with(
            id=investigation_id,
            entry=text,
            username=operator_name,
            email=operator_email,
            footer=MESSAGE_FOOTER,  # Assuming MESSAGE_FOOTER is defined in your module
        )


def test_save_entitlement():
    # Define test inputs
    entitlement = "Test Entitlement"
    message_id = "123"
    reply = "Test Reply"
    expiry = "2023-09-09"
    default_response = "Default Response"
    to_jid = "user@example.com"
    SYNC_CONTEXT = True
    OBJECTS_TO_KEYS = {
        "messages": "entitlement",
    }
    # Mock the required functions (get_integration_context, set_to_integration_context_with_retries) and any other dependencies
    with (
        patch("Zoom.get_integration_context") as mock_get_integration_context,
        patch("Zoom.set_to_integration_context_with_retries") as mock_set_integration_context,
    ):
        # Mock the return values of the mocked functions
        mock_get_integration_context.return_value = {"messages": []}
        fixed_timestamp = "2023-09-09 20:08:50"

        with freeze_time(fixed_timestamp):
            from Zoom import save_entitlement

            # Call the function to be tested
            save_entitlement(entitlement, message_id, reply, expiry, default_response, to_jid)

        # Define the expected data to be added to integration context
        expected_data = {
            "messages": [
                {
                    "message_id": message_id,
                    "entitlement": entitlement,
                    "reply": reply,
                    "expiry": expiry,
                    "sent": fixed_timestamp,
                    "default_response": default_response,
                    "to_jid": to_jid,
                }
            ]
        }

        # Assert that the mocked functions were called with the expected arguments
        mock_get_integration_context.assert_called_once_with(SYNC_CONTEXT)
        mock_set_integration_context.assert_called_once_with(expected_data, OBJECTS_TO_KEYS, SYNC_CONTEXT)