diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 428c180..7bcd849 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,11 +1,11 @@ repos: - repo: https://github.com/phantomcyber/dev-cicd-tools - rev: v1.17 + rev: v1.23 hooks: - id: org-hook - id: package-app-dependencies - repo: https://github.com/Yelp/detect-secrets - rev: v1.4.0 + rev: v1.5.0 hooks: - id: detect-secrets args: ['--no-verify', '--exclude-files', '^microsoftteams.json$'] diff --git a/LICENSE b/LICENSE index 271de55..c0cc138 100644 --- a/LICENSE +++ b/LICENSE @@ -198,4 +198,4 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file + limitations under the License. diff --git a/NOTICE b/NOTICE index 4996805..665256d 100644 --- a/NOTICE +++ b/NOTICE @@ -1,27 +1,2 @@ Splunk SOAR Microsoft Teams Copyright (c) 2019-2024 Splunk Inc. - -Third-party Software Attributions: - -Library: Django -Version: 3.2.5 -License: BSD 3 -License: Python 2.0 -0.9.0 thru 1.2 1991-1995 CWI yes -1.3 thru 1.5.2 1.2 1995-1999 CNRI yes -Copyright 1991-1995 Stichting Mathematisch Centrum Amsterdam -Copyright 2001 Python Software Foundation; All Rights Reserved -Copyright 2012-2020 , -Copyright Django Software Foundation and individual contributors - -Library: beautifulsoup4 -Version: 4.9.1 -License: MIT -Copyright 2004-2017 Leonard Richardson -Copyright 2004-2019 Leonard Richardson -Copyright 2018 Isaac Muse - -Library: requests -Version: 2.25.0 -License: Apache 2.0 -Kenneth Reitz diff --git a/README.md b/README.md index 98f9b70..969712f 100644 --- a/README.md +++ b/README.md @@ -219,14 +219,17 @@ VARIABLE | REQUIRED | TYPE | DESCRIPTION [test connectivity](#action-test-connectivity) - Validate the asset configuration for connectivity using supplied configuration [get admin consent](#action-get-admin-consent) - Get the admin consent for a non-admin user [list users](#action-list-users) - List all users -[send message](#action-send-message) - Send a message to a channel of a group +[send channel message](#action-send-channel-message) - Send a message to a channel of a group [list chats](#action-list-chats) - List chats for authenticated user [send direct message](#action-send-direct-message) - Send a direct message to a user [send chat message](#action-send-chat-message) - Send a message to specific chat [list channels](#action-list-channels) - Lists all channels of a group [list groups](#action-list-groups) - List all Azure Groups [list teams](#action-list-teams) - List all Microsoft Teams -[create meeting](#action-create-meeting) - Create a microsoft teams meeting +[create meeting](#action-create-meeting) - Create a microsoft teams meeting +[get channel message](#action-get-channel-message) - Get a message from the channel +[get chat message](#action-get-chat-message) - Get a message from the chat +[get response message](#action-get-response-message) - Get response on message in a chat ## action: 'test connectivity' Validate the asset configuration for connectivity using supplied configuration @@ -332,7 +335,7 @@ action_result.message | string | | Total users: 5 summary.total_objects | numeric | | 1 summary.total_objects_successful | numeric | | 1 -## action: 'send message' +## action: 'send channel message' Send a message to a channel of a group Type: **generic** @@ -666,6 +669,312 @@ PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS **attendees** | optional | Email-id of the users to send the meeting invitation | string | `email` #### Action Output +DATA PATH | TYPE | CONTAINS +--------- | ---- | -------- +action\_result\.status | string | +action\_result\.parameter\.add\_calendar\_event | boolean | +action\_result\.parameter\.attendees | string | `email` +action\_result\.parameter\.description | string | +action\_result\.parameter\.end\_time | string | +action\_result\.parameter\.start\_time | string | +action\_result\.parameter\.subject | string | +action\_result\.data\.\*\.\@odata\.context | string | `url` +action\_result\.data\.\*\.\@odata\.etag | string | +action\_result\.data\.\*\.allowNewTimeProposals | boolean | +action\_result\.data\.\*\.attendees\.\*\.emailAddress\.address | string | `email` +action\_result\.data\.\*\.attendees\.\*\.emailAddress\.name | string | `email` +action\_result\.data\.\*\.attendees\.\*\.status\.response | string | +action\_result\.data\.\*\.attendees\.\*\.status\.time | string | +action\_result\.data\.\*\.attendees\.\*\.type | string | +action\_result\.data\.\*\.body\.content | string | +action\_result\.data\.\*\.body\.contentType | string | +action\_result\.data\.\*\.bodyPreview | string | +action\_result\.data\.\*\.changeKey | string | +action\_result\.data\.\*\.createdDateTime | string | +action\_result\.data\.\*\.end\.dateTime | string | +action\_result\.data\.\*\.end\.timeZone | string | +action\_result\.data\.\*\.hasAttachments | boolean | +action\_result\.data\.\*\.hideAttendees | numeric | +action\_result\.data\.\*\.iCalUId | string | +action\_result\.data\.\*\.id | string | +action\_result\.data\.\*\.importance | string | +action\_result\.data\.\*\.isAllDay | boolean | +action\_result\.data\.\*\.isCancelled | boolean | +action\_result\.data\.\*\.isDraft | boolean | +action\_result\.data\.\*\.isOnlineMeeting | boolean | +action\_result\.data\.\*\.isOrganizer | boolean | +action\_result\.data\.\*\.isReminderOn | boolean | +action\_result\.data\.\*\.lastModifiedDateTime | string | +action\_result\.data\.\*\.location\.displayName | string | +action\_result\.data\.\*\.location\.locationType | string | +action\_result\.data\.\*\.location\.uniqueIdType | string | +action\_result\.data\.\*\.occurrenceId | string | +action\_result\.data\.\*\.onlineMeeting\.joinUrl | string | `url` +action\_result\.data\.\*\.onlineMeetingProvider | string | +action\_result\.data\.\*\.onlineMeetingUrl | string | +action\_result\.data\.\*\.organizer\.emailAddress\.address | string | `email` +action\_result\.data\.\*\.organizer\.emailAddress\.name | string | +action\_result\.data\.\*\.originalEndTimeZone | string | +action\_result\.data\.\*\.originalStartTimeZone | string | +action\_result\.data\.\*\.recurrence | string | +action\_result\.data\.\*\.reminderMinutesBeforeStart | numeric | +action\_result\.data\.\*\.responseRequested | boolean | +action\_result\.data\.\*\.responseStatus\.response | string | +action\_result\.data\.\*\.responseStatus\.time | string | +action\_result\.data\.\*\.sensitivity | string | +action\_result\.data\.\*\.seriesMasterId | string | +action\_result\.data\.\*\.showAs | string | +action\_result\.data\.\*\.start\.dateTime | string | +action\_result\.data\.\*\.start\.timeZone | string | +action\_result\.data\.\*\.subject | string | +action\_result\.data\.\*\.transactionId | string | +action\_result\.data\.\*\.type | string | +action\_result\.data\.\*\.webLink | string | `url` +action\_result\.data\.\*\.joinUrl | string | `url` +action\_result\.data\.\*\.chatInfo\.threadId | string | +action\_result\.data\.\*\.chatInfo\.messageId | string | +action\_result\.data\.\*\.chatInfo\.replyChainMessageId | string | +action\_result\.data\.\*\.externalId | string | +action\_result\.data\.\*\.joinWebUrl | string | `url` +action\_result\.data\.\*\.endDateTime | string | +action\_result\.data\.\*\.isBroadcast | numeric | +action\_result\.data\.\*\.meetingCode | string | +action\_result\.data\.\*\.meetingInfo | string | +action\_result\.data\.\*\.participants\.organizer\.upn | string | `email` +action\_result\.data\.\*\.participants\.organizer\.role | string | +action\_result\.data\.\*\.participants\.organizer\.identity\.user\.id | string | +action\_result\.data\.\*\.participants\.organizer\.identity\.user\.tenantId | string | +action\_result\.data\.\*\.participants\.organizer\.identity\.user\.displayName | string | +action\_result\.data\.\*\.participants\.organizer\.identity\.user\.registrantId | string | +action\_result\.data\.\*\.participants\.organizer\.identity\.user\.identityProvider | string | +action\_result\.data\.\*\.participants\.organizer\.identity\.guest | string | +action\_result\.data\.\*\.participants\.organizer\.identity\.phone | string | +action\_result\.data\.\*\.participants\.organizer\.identity\.device | string | +action\_result\.data\.\*\.participants\.organizer\.identity\.acsUser | string | +action\_result\.data\.\*\.participants\.organizer\.identity\.encrypted | string | +action\_result\.data\.\*\.participants\.organizer\.identity\.spoolUser | string | +action\_result\.data\.\*\.participants\.organizer\.identity\.onPremises | string | +action\_result\.data\.\*\.participants\.organizer\.identity\.application | string | +action\_result\.data\.\*\.participants\.organizer\.identity\.applicationInstance | string | +action\_result\.data\.\*\.participants\.organizer\.identity\.acsApplicationInstance | string | +action\_result\.data\.\*\.participants\.organizer\.identity\.spoolApplicationInstance | string | +action\_result\.data\.\*\.startDateTime | string | +action\_result\.data\.\*\.joinInformation\.content | string | +action\_result\.data\.\*\.joinInformation\.contentType | string | +action\_result\.data\.\*\.allowMeetingChat | string | +action\_result\.data\.\*\.creationDateTime | string | +action\_result\.data\.\*\.allowedPresenters | string | +action\_result\.data\.\*\.audioConferencing | string | +action\_result\.data\.\*\.autoAdmittedUsers | string | +action\_result\.data\.\*\.broadcastSettings | string | +action\_result\.data\.\*\.lobbyBypassSettings\.scope | boolean | +action\_result\.data\.\*\.lobbyBypassSettings\.isDialInBypassEnabled | boolean | +action\_result\.data\.\*\.recordAutomatically | boolean | +action\_result\.data\.\*\.isEntryExitAnnounced | boolean | +action\_result\.data\.\*\.joinMeetingIdSettings | string | +action\_result\.data\.\*\.videoTeleconferenceId | string | +action\_result\.data\.\*\.allowTeamworkReactions | boolean | +action\_result\.data\.\*\.allowAttendeeToEnableMic | boolean | +action\_result\.data\.\*\.allowAttendeeToEnableCamera | boolean | +action\_result\.data\.\*\.outerMeetingAutoAdmittedUsers | string | +action\_result\.summary | string | +action\_result\.message | string | +summary\.total\_objects | numeric | +summary\.total\_objects\_successful | numeric | + +## action: 'send chat message' +Send message to the chat + +Type: **generic** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**chat\_id** | required | ID of the chat | string | +**message** | required | Message to send (HTML is supported) | string | + +#### Action Output +DATA PATH | TYPE | CONTAINS +--------- | ---- | -------- +action\_result\.status | string | +action\_result\.parameter\.chat\_id | string | +action\_result\.parameter\.message | string | +action\_result\.data\.\@odata\.context | string | `url` +action\_result\.data\.body\.content | string | +action\_result\.data\.body\.contentType | string | +action\_result\.data\.createdDateTime | string | +action\_result\.data\.deletedDateTime | string | +action\_result\.data\.etag | string | +action\_result\.data\.from\.application | string | +action\_result\.data\.from\.device | string | +action\_result\.data\.from\.user\.displayName | string | +action\_result\.data\.from\.user\.id | string | +action\_result\.data\.from\.user\.userIdentityType | string | +action\_result\.data\.id | string | +action\_result\.data\.importance | string | +action\_result\.data\.lastEditedDateTime | string | +action\_result\.data\.lastModifiedDateTime | string | +action\_result\.data\.locale | string | +action\_result\.data\.messageType | string | +action\_result\.data\.policyViolation | string | +action\_result\.data\.replyToId | string | +action\_result\.data\.subject | string | +action\_result\.data\.summary | string | +action\_result\.data\.webUrl | string | +action\_result\.summary | string | +action\_result\.message | string | +summary\.total\_objects | numeric | +summary\.total\_objects\_successful | numeric | + +## action: 'get channel message' +Get a message from the channel + +Type: **generic** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**group\_id** | required | ID of the group | string | +**channel\_id** | required | ID of the channel | string | +**message\_id** | required | ID of the message | string | + +#### Action Output +DATA PATH | TYPE | CONTAINS +--------- | ---- | -------- +action\_result\.status | string | +action\_result\.parameter\.chat\_id | string | +action\_result\.parameter\.channel\_id | string | +action\_result\.parameter\.message\_id | string | +action\_result\.data\.\@odata\.context | string | `url` +action\_result\.data\.body\.content | string | +action\_result\.data\.body\.contentType | string | +action\_result\.data\.createdDateTime | string | +action\_result\.data\.deletedDateTime | string | +action\_result\.data\.etag | string | +action\_result\.data\.eventDetail\.\@odata\.type | string | +action\_result\.data\.eventDetail\.visibleHistoryStartDateTime | string | +action\_result\.data\.eventDetail\.members\.*\.id| string | +action\_result\.data\.eventDetail\.members\.*\.displayName| string | +action\_result\.data\.eventDetail\.members\.*\.userIdentityType| string | +action\_result\.data\.eventDetail\.members\.*\.tenantId| string | +action\_result\.data\.eventDetail\.initiator\.*\.device| string | +action\_result\.data\.eventDetail\.initiator\.*\.user| string | +action\_result\.data\.eventDetail\.initiator\.*\.application| string | +action\_result\.data\.eventDetail\.initiator\.*\.\@odata.type| string | +action\_result\.data\.eventDetail\.initiator\.*\.application\.id| string | +action\_result\.data\.eventDetail\.initiator\.*\.application\.displayName| string | +action\_result\.data\.eventDetail\.initiator\.*\.application\.applicationIdentityType| string | +action\_result\.data\.id | string | +action\_result\.data\.importance | string | +action\_result\.data\.lastEditedDateTime | string | +action\_result\.data\.lastModifiedDateTime | string | +action\_result\.data\.locale | string | +action\_result\.data\.messageType | string | +action\_result\.data\.policyViolation | string | +action\_result\.data\.replyToId | string | +action\_result\.data\.subject | string | +action\_result\.data\.summary | string | +action\_result\.data\.webUrl | string | +action\_result\.summary | string | +action\_result\.message | string | +summary\.total\_objects | numeric | +summary\.total\_objects\_successful | numeric | + +## action: 'get chat message' +Get a message from the chat + +Type: **generic** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**chat\_id** | required | ID of the chat | string | +**message\_id** | required | ID of the message | string | + +#### Action Output +DATA PATH | TYPE | CONTAINS +--------- | ---- | -------- +action\_result\.status | string | +action\_result\.parameter\.chat\_id | string | +action\_result\.parameter\.message\_id | string | +action\_result\.data\.\@odata\.context | string | `url` +action\_result\.data\.body\.content | string | +action\_result\.data\.body\.contentType | string | +action\_result\.data\.createdDateTime | string | +action\_result\.data\.deletedDateTime | string | +action\_result\.data\.etag | string | +action\_result\.data\.from\.application | string | +action\_result\.data\.from\.device | string | +action\_result\.data\.from\.user\.\@odata\.type | string | +action\_result\.data\.from\.user\.displayName | string | +action\_result\.data\.from\.user\.id | string | +action\_result\.data\.from\.user\.userIdentityType | string | +action\_result\.data\.from\.user\.tenantId | string | +action\_result\.data\.id | string | +action\_result\.data\.importance | string | +action\_result\.data\.lastEditedDateTime | string | +action\_result\.data\.lastModifiedDateTime | string | +action\_result\.data\.locale | string | +action\_result\.data\.messageType | string | +action\_result\.data\.policyViolation | string | +action\_result\.data\.replyToId | string | +action\_result\.data\.subject | string | +action\_result\.data\.summary | string | +action\_result\.data\.webUrl | string | +action\_result\.summary | string | +action\_result\.message | string | + +## action: 'get response message' +Get response on message in a chat + +Type: **generic** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**chat\_id** | required | ID of the chat | string | +**message\_id** | required | ID of the message | string | +**wait\_time** | optional | The amount of time in minutes to wait for response | numeric | + +#### Action Output +DATA PATH | TYPE | CONTAINS +--------- | ---- | -------- +action\_result\.status | string | +action\_result\.parameter\.chat\_id | string | +action\_result\.parameter\.message\_id | string | +action\_result\.parameter\.wait\_time | numeric | +action\_result\.data\.\@odata\.context | string | `url` +action\_result\.data\.body\.content | string | +action\_result\.data\.body\.contentType | string | +action\_result\.data\.body\.message\_reply | string | +action\_result\.data\.createdDateTime | string | +action\_result\.data\.deletedDateTime | string | +action\_result\.data\.etag | string | +action\_result\.data\.from\.application | string | +action\_result\.data\.from\.device | string | +action\_result\.data\.from\.user\.\@odata\.type | string | +action\_result\.data\.from\.user\.displayName | string | +action\_result\.data\.from\.user\.id | string | +action\_result\.data\.from\.user\.userIdentityType | string | +action\_result\.data\.from\.user\.tenantId | string | +action\_result\.data\.id | string | +action\_result\.data\.importance | string | +action\_result\.data\.lastEditedDateTime | string | +action\_result\.data\.lastModifiedDateTime | string | +action\_result\.data\.locale | string | +action\_result\.data\.messageType | string | +action\_result\.data\.policyViolation | string | +action\_result\.data\.replyToId | string | +action\_result\.data\.subject | string | +action\_result\.data\.summary | string | +action\_result\.data\.webUrl | string | +action\_result\.summary | string | +action\_result\.message | string | +======= DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES --------- | ---- | -------- | -------------- action_result.status | string | | success failed @@ -777,4 +1086,4 @@ action_result.data.\*.outerMeetingAutoAdmittedUsers | string | | action_result.summary | string | | action_result.message | string | | Meeting Created Successfully summary.total_objects | numeric | | 1 -summary.total_objects_successful | numeric | | 1 \ No newline at end of file +summary.total_objects_successful | numeric | | 1 diff --git a/manual_readme_content.md b/manual_readme_content.md index ebcbcdb..d250615 100644 --- a/manual_readme_content.md +++ b/manual_readme_content.md @@ -13,6 +13,10 @@ [comment]: # "either express or implied. See the License for the specific language governing permissions" [comment]: # "and limitations under the License." [comment]: # "" +## Playbook Backward Compatibility + +- With version 3.0.0 of the connector, the 'send message' action has been renamed to 'send channel message'. Please update any existing playbooks by modifying the action name accordingly. + ## Note - For an admin user, you can run the test connectivity directly. @@ -53,7 +57,9 @@ This app requires creating an app in the Azure Active Directory. | OnlineMeetings.ReadWrite | create meeting | Allows an app to create, read online meetings on behalf of the signed-in user. | No | Calendars.ReadWrite | create meeting (while add_calendar_event parameter is set to True) | Allows the app to create, read, update, and delete events in user calendars. | No | Channel.ReadBasic.All | list channels | Read channel names and channel descriptions, on behalf of the signed-in user. | No - | ChannelMessage.Send | send message | Allows an app to send channel messages in Microsoft Teams, on behalf of the signed-in user. | No + | ChannelMessage.Send | send channel message | Allows an app to send channel messages in Microsoft Teams, on behalf of the signed-in user. | No + | Chat.Read, Chat.ReadWrite | get chat message | Read single message or message reply in chat, on behalf of the signed-in user. | No + | ChatMessage.Send | send chat message | Allows an app to send new chat message in specified chat in Microsoft Teams, on behalf of the signed-in user. | No | GroupMember.Read.All | list groups, list teams | Allows the app to list groups, read basic group properties and read membership of all groups the signed-in user has access to. | Yes | Chat.ReadWrite | read and send chat messages | Allows the app to read and send messages in chats on behalf of the signed-in user. | No | diff --git a/microsoftteams.json b/microsoftteams.json index ad99c3f..293573b 100644 --- a/microsoftteams.json +++ b/microsoftteams.json @@ -10,11 +10,11 @@ "product_version_regex": ".*", "publisher": "Splunk", "license": "Copyright (c) 2019-2024 Splunk Inc.", - "app_version": "2.6.2", + "app_version": "3.0.0", "utctime_updated": "2024-04-10T10:46:03.000000Z", "package_name": "phantom_microsoftteams", "main_module": "microsoftteams_connector.py", - "min_phantom_version": "6.2.2", + "min_phantom_version": "6.3.0", "app_wizard_version": "1.0.0", "rest_handler": "microsoftteams_connector._handle_rest_request", "python_version": "3", @@ -486,10 +486,10 @@ "versions": "EQ(*)" }, { - "action": "send message", + "action": "send channel message", "description": "Send a message to a channel of a group", "type": "generic", - "identifier": "send_message", + "identifier": "send_channel_message", "read_only": false, "parameters": { "group_id": { @@ -537,7 +537,7 @@ "column_name": "Channel ID", "column_order": 1, "example_values": [ - "cd6f5efb-39f8-492e-80cd-c228c211cf17" + "10:2daiuhf4c29f6d7041eca70b67979r245437@thread.v2" ] }, { @@ -549,7 +549,7 @@ "column_name": "Group ID", "column_order": 0, "example_values": [ - "594101ba-1fde-482d-8e24-3bbab23a3ca8" + "caf444a0-0e0e-426b-98ea-db67ff6b0b25" ] }, { @@ -558,8 +558,7 @@ "column_name": "Message", "column_order": 2, "example_values": [ - "This is a test message", - " Test link " + "This is a test message" ] }, { @@ -627,7 +626,7 @@ "data_path": "action_result.data.*.from.user.id", "data_type": "string", "example_values": [ - "eeb3645f-df19-47a1-8e8c-fcd234cb5f6f" + "hu45nfhf-df19-47a1-8e8c-fcd234cb5f6f" ] }, { @@ -683,6 +682,42 @@ "data_path": "action_result.data.*.replyToId", "data_type": "string" }, + { + "data_path": "action_result.data.*.from.user.tenantId", + "data_type": "string", + "example_values": [ + "149y9r6d-819d-4b6d-b7ef-1c0a827792970f4f0" + ] + }, + { + "data_path": "action_result.data.*.from.user.@odata.type", + "data_type": "string", + "example_values": [ + "#microsoft.graph.teamworkUserIdentity" + ] + }, + { + "data_path": "action_result.data.*.chatId", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.eventDetail", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.channelIdentity.teamId", + "data_type": "string", + "example_values": [ + "hfyr6hdhyr6s-d42a-452b-9155-379764077e25" + ] + }, + { + "data_path": "action_result.data.*.channelIdentity.channelId", + "data_type": "string", + "example_values": [ + "19:391631e7f5984005811c658217ea8f23@thread.tacv2" + ] + }, { "data_path": "action_result.data.*.subject", "data_type": "string" @@ -758,6 +793,10 @@ "data_path": "action_result.parameter.user", "data_type": "string" }, + { + "data_path":"action_result.parameter.chat_type", + "data_type":"string" + }, { "data_path": "action_result.data.*.id", "data_type": "string", @@ -1283,6 +1322,28 @@ "data_path": "action_result.data.*.email", "data_type": "string" }, + { + "data_path": "action_result.data.*.tenantId", + "data_type": "string", + "example_values": [ + "149y9r6d-819d-4b6d-b7ef-1c0a827792970f4f0" + ] + }, + { + "data_path": "action_result.data.*.isArchived", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.createdDateTime", + "data_type": "string", + "example_values": [ + "2020-07-13T12:39:21.573Z" + ] + }, { "data_path": "action_result.data.*.id", "data_type": "string", @@ -1398,6 +1459,10 @@ "team2" ] }, + { + "data_path": "action_result.data.*.uniqueName", + "data_type": "string" + }, { "data_path": "action_result.data.*.expirationDateTime", "data_type": "string" @@ -1423,7 +1488,7 @@ }, { "data_path": "action_result.data.*.isAssignableToRole", - "data_type": "string" + "data_type": "boolean" }, { "data_path": "action_result.data.*.mail", @@ -1493,7 +1558,7 @@ }, { "data_path": "action_result.data.*.onPremisesSyncEnabled", - "data_type": "string" + "data_type": "boolean" }, { "data_path": "action_result.data.*.preferredDataLocation", @@ -1943,8 +2008,8 @@ "data_path": "action_result.data.*.@odata.context", "data_type": "string", "example_values": [ - "https://graph.microsoft.com/v1.0/$metadata#users('eeb3645f-df19-47a1-8e8c-fcd234cb5f6f')/calendar/events/$entity", - "https://graph.microsoft.com/v1.0/$metadata#users('eeb3645f-df19-47a1-8e8c-fcd234cb5f6f')/onlineMeetings/$entity" + "https://graph.microsoft.com/v1.0/$metadata#users('hu45nfhf-df19-47a1-8e8c-fcd234cb5f6f')/calendar/events/$entity", + "https://graph.microsoft.com/v1.0/$metadata#users('hu45nfhf-df19-47a1-8e8c-fcd234cb5f6f')/onlineMeetings/$entity" ], "contains": [ "url" @@ -2401,14 +2466,14 @@ "data_path": "action_result.data.*.participants.organizer.identity.user.id", "data_type": "string", "example_values": [ - "eeb3645f-df19-47a1-8e8c-fcd234cb5f6f" + "hu45nfhf-df19-47a1-8e8c-fcd234cb5f6f" ] }, { "data_path": "action_result.data.*.participants.organizer.identity.user.tenantId", "data_type": "string", "example_values": [ - "140fe46d-819d-4b6d-b7ef-1c0a8270f4f0" + "149y9r6d-819d-4b6d-b7ef-1c0a827792970f4f0" ] }, { @@ -2623,30 +2688,947 @@ "view": "microsoftteams_view.display_meeting" }, "versions": "EQ(*)" - } - ], - "pip_dependencies": { - "wheel": [ - { - "module": "beautifulsoup4", - "input_file": "wheels/py3/beautifulsoup4-4.9.1-py3-none-any.whl" - }, - { - "module": "soupsieve", - "input_file": "wheels/py3/soupsieve-2.3.2.post1-py3-none-any.whl" - } - ] - }, - "pip39_dependencies": { - "wheel": [ - { - "module": "beautifulsoup4", - "input_file": "wheels/py3/beautifulsoup4-4.9.1-py3-none-any.whl" + }, + { + "action": "get channel message", + "description": "Get message in a channel", + "type": "investigate", + "identifier": "get_channel_message", + "read_only": true, + "parameters": { + "group_id": { + "description": "ID of group", + "data_type": "string", + "required": true, + "primary": true, + "contains": [ + "ms teams group id" + ], + "order": 0 + }, + "channel_id": { + "description": "ID of channel", + "data_type": "string", + "required": true, + "primary": true, + "contains": [ + "ms teams channel id" + ], + "order": 1 + }, + "message_id": { + "description": "ID of message", + "data_type": "string", + "required": true, + "order": 2 + } }, - { - "module": "soupsieve", - "input_file": "wheels/py3/soupsieve-2.5-py3-none-any.whl" - } - ] + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ] + }, + { + "data_path": "action_result.parameter.channel_id", + "data_type": "string", + "contains": [ + "ms teams channel id" + ], + "column_name": "Channel ID", + "column_order": 1, + "example_values": [ + "10:2daiuhf4c29f6d7041eca70b67979r245437@thread.v2" + ] + }, + { + "data_path": "action_result.parameter.group_id", + "data_type": "string", + "contains": [ + "ms teams group id" + ], + "column_name": "Group ID", + "column_order": 0, + "example_values": [ + "caf444a0-0e0e-426b-98ea-db67ff6b0b25" + ] + }, + { + "data_path": "action_result.parameter.message_id", + "data_type": "string", + "example_values": [ + "1688719160710" + ] + }, + { + "data_path": "action_result.data.*.@odata.context", + "data_type": "string", + "example_values": [ + "https://test.link.com/beta/$metadata#chatThreads/$entity" + ], + "contains": [ + "url" + ] + }, + { + "data_path": "action_result.data.*.body.content", + "data_type": "string", + "example_values": [ + "test message" + ] + }, + { + "data_path": "action_result.data.body.*.contentType", + "data_type": "string", + "example_values": [ + "text" + ] + }, + { + "data_path": "action_result.data.*.createdDateTime", + "data_type": "string", + "example_values": [ + "2021-03-12T06:02:01.352Z" + ] + }, + { + "data_path": "action_result.data.*.deletedDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.etag", + "data_type": "string", + "example_values": [ + "1615528921352" + ] + }, + { + "data_path": "action_result.data.*.eventDetail.@odata.type", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.eventDetail.visibleHistoryStartDateTime", + "data_type": "string", + "example_values": [ + "0001-01-01T00:00:00Z" + ] + }, + { + "data_path": "action_result.data.*.eventDetail.members.*.id", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.eventDetail.members.*.displayName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.eventDetail.members.*.userIdentityType", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.eventDetail.members.*.tenantId", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.eventDetail.initiator.device", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.eventDetail.initiator.user", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.eventDetail.initiator.application", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.eventDetail.initiator.application.@odata.type", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.eventDetail.initiator.application.id", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.eventDetail.initiator.application.displayName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.eventDetail.initiator.application.applicationIdentityType", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.from.user.tenantId", + "data_type": "string", + "example_values": [ + "149y9r6d-819d-4b6d-b7ef-1c0a827792970f4f0" + ] + }, + { + "data_path": "action_result.data.*.from.user.@odata.type", + "data_type": "string", + "example_values": [ + "#microsoft.graph.teamworkUserIdentity" + ] + }, + { + "data_path": "action_result.data.*.chatId", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.eventDetail", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.channelIdentity.teamId", + "data_type": "string", + "example_values": [ + "hfyr6hdhyr6s-d42a-452b-9155-379764077e25" + ] + }, + { + "data_path": "action_result.data.*.channelIdentity.channelId", + "data_type": "string", + "example_values": [ + "10:2daiuhf4c29f6d7041eca70b67979r245437@thread.v2" + ] + }, + { + "data_path": "action_result.data.*.id", + "data_type": "string", + "example_values": [ + "1517826451101" + ], + "column_name": "Message ID", + "column_order": 2 + }, + { + "data_path": "action_result.data.*.importance", + "data_type": "string", + "example_values": [ + "normal" + ] + }, + { + "data_path": "action_result.data.*.lastEditedDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.lastModifiedDateTime", + "data_type": "string", + "example_values": [ + "2021-03-12T06:02:01.352Z" + ] + }, + { + "data_path": "action_result.data.*.locale", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.messageType", + "data_type": "string", + "example_values": [ + "message" + ] + }, + { + "data_path": "action_result.data.*.policyViolation", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.replyToId", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.subject", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.summary", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.webUrl", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.body.contentType", + "data_type": "string", + "example_values": [ + "html" + ] + }, + { + "data_path": "action_result.data.*.from.user.id", + "data_type": "string", + "example_values": [ + "hu45nfhf-df19-47a1-8e8c-fcd234cb5f6f" + ] + }, + { + "data_path": "action_result.data.*.from.user.tenantId", + "data_type": "string", + "example_values": [ + "149y9r6d-819d-4b6d-b7ef-1c0a827792970f4f0" + ] + }, + { + "data_path": "action_result.data.*.from.user.@odata.type", + "data_type": "string", + "example_values": [ + "#microsoft.graph.teamworkUserIdentity" + ] + }, + { + "data_path": "action_result.data.*.from.user.displayName", + "data_type": "string", + "example_values": [ + "Test User" + ] + }, + { + "data_path": "action_result.data.*.from.user.userIdentityType", + "data_type": "string", + "example_values": [ + "aadUser" + ] + }, + { + "data_path": "action_result.data.*.from.device", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.from.application", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.chatId", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.eventDetail", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.channelIdentity.teamId", + "data_type": "string", + "example_values": [ + "hfyr6hdhyr6s-d42a-452b-9155-379764077e25" + ] + }, + { + "data_path": "action_result.data.*.channelIdentity.channelId", + "data_type": "string", + "example_values": [ + "10:2daiuhf4c29f6d7041eca70b67979r245437@thread.v2" + ] + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "action_result.summary", + "data_type": "string" + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Message sent" + ] + } + ], + "render": { + "type": "table" + }, + "versions": "EQ(*)" + }, + { + "action": "get chat message", + "description": "Get message in a chat", + "type": "investigate", + "identifier": "get_chat_message", + "read_only": true, + "parameters": { + "chat_id": { + "description": "ID of chat", + "data_type": "string", + "required": true, + "primary": true, + "contains": [ + "ms teams chat id" + ], + "order": 0 + }, + "message_id": { + "description": "ID of message", + "data_type": "string", + "required": true, + "order": 1 + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ] + }, + { + "data_path": "action_result.parameter.chat_id", + "data_type": "string", + "contains": [ + "ms teams chat id" + ], + "column_name": "Chat ID", + "column_order": 0, + "example_values": [ + "10:1c06006a-1885-401b-8dd2-b23e21dtest1_cbb6948d6abeeac89ae@unq.gbl.spaces" + ] + }, + { + "data_path": "action_result.parameter.message_id", + "data_type": "string", + "example_values": [ + "1688719160100" + ] + }, + { + "data_path": "action_result.data.*.@odata.context", + "data_type": "string", + "example_values": [ + "https://test.link.com/beta/$metadata#chatThreads/$entity" + ], + "contains": [ + "url" + ] + }, + { + "data_path": "action_result.data.*.body.content", + "data_type": "string", + "example_values": [ + "test message" + ] + }, + { + "data_path": "action_result.data.*.body.contentType", + "data_type": "string", + "example_values": [ + "text" + ] + }, + { + "data_path": "action_result.data.*.createdDateTime", + "data_type": "string", + "example_values": [ + "2021-03-12T06:02:01.352Z" + ] + }, + { + "data_path": "action_result.data.*.deletedDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.etag", + "data_type": "string", + "example_values": [ + "1615528921765" + ] + }, + { + "data_path": "action_result.data.*.from.application", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.from.device", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.from.user.@odata.type", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.from.user.displayName", + "data_type": "string", + "example_values": [ + "Test User" + ] + }, + { + "data_path": "action_result.data.*.from.user.id", + "data_type": "string", + "example_values": [ + "hu45nfhf-df19-47a1-8e8c-fcd234cb5f6f" + ] + }, + { + "data_path": "action_result.data.*.from.user.userIdentityType", + "data_type": "string", + "example_values": [ + "aadUser" + ] + }, + { + "data_path": "action_result.data.*.from.user.tenantId", + "data_type": "string", + "example_values": [ + "aadUser" + ] + }, + { + "data_path": "action_result.data.*.id", + "data_type": "string", + "example_values": [ + "1517826451101" + ], + "column_name": "Message ID", + "column_order": 1 + }, + { + "data_path": "action_result.data.*.importance", + "data_type": "string", + "example_values": [ + "normal" + ] + }, + { + "data_path": "action_result.data.*.lastEditedDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.lastModifiedDateTime", + "data_type": "string", + "example_values": [ + "2021-03-12T06:02:01.352Z" + ] + }, + { + "data_path": "action_result.data.*.locale", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.messageType", + "data_type": "string", + "example_values": [ + "message" + ] + }, + { + "data_path": "action_result.data.*.policyViolation", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.replyToId", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.subject", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.summary", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.webUrl", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.chatId", + "data_type": "string", + "example_values": [ + "10:1c06006a-1885-401b-8dd2-b23e21dtest1_cbb6948d6abeeac89ae@unq.gbl.spaces" + ] + }, + { + "data_path": "action_result.data.*.attachments.*.id", + "data_type": "string", + "example_values": [ + "1722330920100" + ] + }, + { + "data_path": "action_result.data.*.attachments.*.name", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.attachments.*.content", + "data_type": "string", + "example_values": [ + "{\"messageId\":\"1722330920117\",\"messagePreview\":\"How are you?\",\"messageSender\":{\"application\":null,\"device\":null,\"user\":{\"userIdentityType\":\"aadUser\",\"tenantId\":\"149y9r6d-819d-4b6d-b7ef-1c0a827792970f4f0\",\"id\":\"hu45nfhf-df19-47a1-8e8c-fcd234cb5f6f\",\"displayName\":\"Test User\"}}}" + ] + }, + { + "data_path": "action_result.data.*.attachments.*.contentUrl", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.attachments.*.teamsAppId", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.attachments.*.contentType", + "data_type": "string", + "example_values": [ + "messageReference" + ] + }, + { + "data_path": "action_result.data.*.attachments.*.thumbnailUrl", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.eventDetail", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.channelIdentity", + "data_type": "string" + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "action_result.summary", + "data_type": "string" + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Message sent" + ] + } + ], + "render": { + "type": "table" + }, + "versions": "EQ(*)" + }, + { + "action": "get response message", + "description": "Get response on message in a chat", + "verbose":"Get response action retrieves replies from chat message. It can only find replies if they exist in the most recent 50 messages.", + "type": "investigate", + "identifier": "get_response", + "read_only": true, + "parameters": { + "chat_id": { + "description": "ID of chat", + "data_type": "string", + "required": true, + "primary": true, + "contains": [ + "ms teams chat id" + ], + "order": 0 + }, + "message_id": { + "description": "The ID of the message to be replied to", + "data_type": "string", + "required": true, + "order": 1 + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ] + }, + { + "data_path": "action_result.parameter.chat_id", + "data_type": "string", + "contains": [ + "ms teams chat id" + ], + "column_name": "Chat ID", + "column_order": 0, + "example_values": [ + "10:1c06006a-1885-401b-8dd2-b23e21dtest1_cbb6948d6abeeac89ae@unq.gbl.spaces" + ] + }, + { + "data_path": "action_result.parameter.message_id", + "data_type": "string", + "example_values": [ + "1688719160711" + ] + }, + { + "data_path": "action_result.data.*.@odata.context", + "data_type": "string", + "example_values": [ + "https://test.link.com/beta/$metadata#chatThreads/$entity" + ], + "contains": [ + "url" + ] + }, + { + "data_path": "action_result.data.*.body.content", + "data_type": "string", + "example_values": [ + "test message" + ] + }, + { + "data_path": "action_result.data.*.body.contentType", + "data_type": "string", + "example_values": [ + "text" + ] + }, + { + "data_path": "action_result.data.*.body.message_reply", + "data_type": "string", + "column_name": "Message Reply", + "column_order": 2, + "example_values": [ + "try it" + ] + }, + { + "data_path": "action_result.data.*.createdDateTime", + "data_type": "string", + "example_values": [ + "2021-03-12T06:02:01.352Z" + ] + }, + { + "data_path": "action_result.data.*.deletedDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.etag", + "data_type": "string", + "example_values": [ + "1615528921100" + ] + }, + { + "data_path": "action_result.data.*.from.application", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.from.device", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.from.user.@odata.type", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.from.user.displayName", + "data_type": "string", + "example_values": [ + "Test User" + ] + }, + { + "data_path": "action_result.data.*.from.user.id", + "data_type": "string", + "example_values": [ + "hu45nfhf-df19-47a1-8e8c-fcd234cb5f6f" + ] + }, + { + "data_path": "action_result.data.*.from.user.userIdentityType", + "data_type": "string", + "example_values": [ + "aadUser" + ] + }, + { + "data_path": "action_result.data.*.from.user.tenantId", + "data_type": "string", + "example_values": [ + "aadUser" + ] + }, + { + "data_path": "action_result.data.*.id", + "data_type": "string", + "example_values": [ + "1517826451101" + ], + "column_name": "Response Message ID", + "column_order": 1 + }, + { + "data_path": "action_result.data.*.importance", + "data_type": "string", + "example_values": [ + "normal" + ] + }, + { + "data_path": "action_result.data.*.contain_attachment", + "data_type": "string", + "column_name": "Contain Attachment?", + "column_order": 3 + + }, + { + "data_path": "action_result.data.*.lastEditedDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.lastModifiedDateTime", + "data_type": "string", + "example_values": [ + "2021-03-12T06:02:01.352Z" + ] + }, + { + "data_path": "action_result.data.*.locale", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.messageType", + "data_type": "string", + "example_values": [ + "message" + ] + }, + { + "data_path": "action_result.data.*.policyViolation", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.replyToId", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.subject", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.summary", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.webUrl", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.chatId", + "data_type": "string", + "example_values": [ + "10:1c06006a-1885-401b-8dd2-b23e21dtest1_cbb6948d6abeeac89ae@unq.gbl.spaces" + ] + }, + { + "data_path": "action_result.data.*.attachments.*.id", + "data_type": "string", + "example_values": [ + "1722330920117" + ] + }, + { + "data_path": "action_result.data.*.attachments.*.name", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.attachments.*.content", + "data_type": "string", + "example_values": [ + "{\"messageId\":\"1722330920117\",\"messagePreview\":\"How are you?\",\"messageSender\":{\"application\":null,\"device\":null,\"user\":{\"userIdentityType\":\"aadUser\",\"tenantId\":\"149y9r6d-819d-4b6d-b7ef-1c0a827792970f4f0\",\"id\":\"eeb3645f-df19-47a1-8e8c-fcd234cbuste\",\"displayName\":\"Test User\"}}}" + ] + }, + { + "data_path": "action_result.data.*.attachments.*.contentUrl", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.attachments.*.teamsAppId", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.attachments.*.contentType", + "data_type": "string", + "example_values": [ + "messageReference" + ] + }, + { + "data_path": "action_result.data.*.attachments.*.thumbnailUrl", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.eventDetail", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.channelIdentity", + "data_type": "string" + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "action_result.summary", + "data_type": "string" + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Message sent" + ] + } + ], + "render": { + "type": "table" + }, + "versions": "EQ(*)" + } + ], + "pip_dependencies": { + "wheel": [] + }, + "pip39_dependencies": { + "wheel": [] } -} \ No newline at end of file +} diff --git a/microsoftteams_connector.py b/microsoftteams_connector.py index b24bd30..fcb7fdd 100644 --- a/microsoftteams_connector.py +++ b/microsoftteams_connector.py @@ -19,6 +19,7 @@ import json import os import pwd +import re import sys import time from typing import Any, Optional @@ -69,7 +70,7 @@ def _get_error_message_from_exception(e, app_connector): """ error_code = None - error_msg = ERROR_MSG_UNAVAILABLE + error_message = ERROR_MSG_UNAVAILABLE app_connector.error_print("Error occurred.", e) @@ -77,16 +78,16 @@ def _get_error_message_from_exception(e, app_connector): if hasattr(e, "args"): if len(e.args) > 1: error_code = e.args[0] - error_msg = e.args[1] + error_message = e.args[1] elif len(e.args) == 1: - error_msg = e.args[0] + error_message = e.args[0] except Exception as e: app_connector.error_print("Error occurred while fetching exception information. Details: {}".format(str(e))) if not error_code: - error_text = "Error Message: {}".format(error_msg) + error_text = "Error Message: {}".format(error_message) else: - error_text = "Error Code: {}. Error Message: {}".format(error_code, error_msg) + error_text = "Error Code: {}. Error Message: {}".format(error_code, error_message) return error_text @@ -455,6 +456,7 @@ def _update_request(self, action_result, endpoint, headers=None, params=None, da # In pagination, URL of next page contains complete URL # So no need to modify them + if endpoint.startswith(MSTEAMS_MSGRAPH_TEAMS_ENDPOINT): endpoint = "{0}{1}".format(MSTEAMS_MSGRAPH_BETA_API_BASE_URL, endpoint) elif not endpoint.startswith(MSTEAMS_MSGRAPH_API_BASE_URL): @@ -923,8 +925,8 @@ def _verify_parameters(self, group_id, channel_id, action_result) -> bool: return phantom.APP_SUCCESS - def _handle_send_message(self, param): - """This function is used to send the message in a group. + def _handle_send_channel_message(self, param: dict) -> str: + """This function is used to Sends a message to a specified channel in a Microsoft Teams group. :param param: Dictionary of input parameters :return: status success/failure @@ -945,7 +947,7 @@ def _handle_send_message(self, param): error_message = error_message.replace("teamId", "'group_id'") return action_result.set_status(phantom.APP_ERROR, error_message) - endpoint = MSTEAMS_MSGRAPH_SEND_MSG_ENDPOINT.format(group_id=group_id, channel_id=channel_id) + endpoint = MSTEAMS_MSGRAPH_SEND_CHANNEL_MSG_ENDPOINT.format(group_id=group_id, channel_id=channel_id) data = {"body": {"contentType": "html", "content": message}} @@ -1113,6 +1115,148 @@ def _handle_create_meeting(self, param): return action_result.set_status(phantom.APP_SUCCESS, status_message="Meeting Created Successfully") + def _handle_get_channel_message(self, param: dict) -> str: + """This function is used to get message from specified channel in a Microsoft Teams group. + + :param param: Dictionary of input parameters + :return: status success/failure + """ + + self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) + action_result = self.add_action_result(ActionResult(dict(param))) + + group_id = param[MSTEAMS_JSON_GROUP_ID] + channel_id = param[MSTEAMS_JSON_CHANNEL_ID] + message_id = param[MSTEAMS_JSON_MSG_ID] + + status = self._verify_parameters(group_id=group_id, channel_id=channel_id, action_result=action_result) + + if phantom.is_fail(status): + error_message = action_result.get_message() + if "teamId" in error_message: + error_message = error_message.replace("teamId", "'group_id'") + return action_result.set_status(phantom.APP_ERROR, error_message) + + endpoint = MSTEAMS_MSGRAPH_GET_CHANNEL_MSG_ENDPOINT.format(group_id=group_id, channel_id=channel_id, message_id=message_id) + + # make rest call + ret_val, response = self._update_request(endpoint=endpoint, action_result=action_result, method="get") + + if phantom.is_fail(ret_val): + error_message = action_result.get_message() + if "teamId" in error_message: + error_message = error_message.replace("teamId", "'group_id'") + return action_result.set_status(phantom.APP_ERROR, error_message) + + action_result.add_data(response) + + return action_result.set_status(phantom.APP_SUCCESS, status_message="Message successfully retrieved") + + def _handle_get_chat_message(self, param: dict) -> str: + """This function is used to get the message from the specified chat. + + :param param: Dictionary of input parameters + :return: status success/failure + """ + + self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) + action_result = self.add_action_result(ActionResult(dict(param))) + + chat_id = param[MSTEAMS_JSON_CHAT_ID] + message_id = param[MSTEAMS_JSON_MSG_ID] + + endpoint = MSTEAMS_MSGRAPH_GET_CHAT_MSG_ENDPOINT.format(chat_id=chat_id, message_id=message_id) + + # make rest call + ret_val, response = self._update_request(endpoint=endpoint, action_result=action_result, method="get") + + if phantom.is_fail(ret_val): + return action_result.set_status(phantom.APP_ERROR, action_result.get_message()) + + action_result.add_data(response) + + return action_result.set_status(phantom.APP_SUCCESS, status_message="Message successfully retrieved") + + def _handle_get_response(self, param: dict) -> str: + """This function is used to get reply messages from chat. + + :param param: Dictionary of input parameters + :return: status success/failure + """ + + self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) + action_result = self.add_action_result(ActionResult(dict(param))) + + chat_id = param[MSTEAMS_JSON_CHAT_ID] + message_id = param[MSTEAMS_JSON_MSG_ID] + + endpoint = MSTEAMS_MSGRAPH_SEND_DIRECT_MSG_ENDPOINT.format(chat_id=chat_id) + + endpoint += "?$orderby=createdDateTime+desc&$top=50" + + all_replies = [] + + while True: + + # make rest call + ret_val, response = self._update_request(endpoint=endpoint, action_result=action_result, method="get") + + if phantom.is_fail(ret_val): + return action_result.set_status(phantom.APP_ERROR, action_result.get_message()) + + replies = response.get("value", []) + + if not replies: + return action_result.set_status(phantom.APP_ERROR, action_result.get_message()) + + message_list = [] + + try: + for reply in replies: + message_list.append(reply.get("id")) + attachments = reply.get("attachments", []) + attachment_count = len(attachments) + + if attachment_count > 0: + attachment_ids = [attachment.get("id") for attachment in attachments] + + if message_id in attachment_ids: + reply["contain_attachment"] = "Yes" if attachment_count > 1 else "No" + all_replies.append(reply) + + except Exception as exc: + return action_result.set_status(phantom.APP_ERROR, f"An error occurred: {exc}") + + if message_id in message_list: + break + + if response.get(MSTEAMS_NEXT_LINK_STRING): + endpoint = response.get(MSTEAMS_NEXT_LINK_STRING) + else: + break + + if not all_replies: + return action_result.set_status( + phantom.APP_ERROR, + f"get response action did not find reply for {message_id} message", + ) + + for reply in all_replies: + try: + body = reply.get("body") + + if body is None or body.get("content") is None: + continue + + text = re.findall(r"\n(.*?)\n
", body.get("content")) + reply.get("body")["message_reply"] = "".join(text).strip() + action_result.add_data(reply) + + except Exception as exc: + return action_result.set_status(phantom.APP_ERROR, f"Cannot find message text in body.content object. {exc}") + + return action_result.set_status(phantom.APP_SUCCESS, status_message="Successfully found a reply to the message") + def _handle_list_chats(self, param): """This function is used to list all chats for the current user with optional filters. @@ -1197,6 +1341,7 @@ def _handle_send_chat_message(self, param): action_result = self.add_action_result(ActionResult(dict(param))) chat_id = param[MSTEAMS_JSON_CHAT_ID] + message = param[MSTEAMS_JSON_MSG] status, response = self._send_chat_message(action_result, chat_id, message) @@ -1294,16 +1439,19 @@ def handle_action(self, param): # Dictionary mapping each action with its corresponding actions action_mapping = { "test_connectivity": self._handle_test_connectivity, - "send_message": self._handle_send_message, + "send_channel_message": self._handle_send_channel_message, "send_direct_message": self._handle_send_direct_message, "send_chat_message": self._handle_send_chat_message, "list_groups": self._handle_list_groups, "list_teams": self._handle_list_teams, "list_users": self._handle_list_users, "list_channels": self._handle_list_channels, - "list_chats": self._handle_list_chats, "get_admin_consent": self._handle_get_admin_consent, "create_meeting": self._handle_create_meeting, + "get_channel_message": self._handle_get_channel_message, + "get_chat_message": self._handle_get_chat_message, + "get_response": self._handle_get_response, + "list_chats": self._handle_list_chats, } action = self.get_action_identifier() diff --git a/microsoftteams_consts.py b/microsoftteams_consts.py index f97520e..9997a10 100644 --- a/microsoftteams_consts.py +++ b/microsoftteams_consts.py @@ -28,11 +28,13 @@ MSTEAMS_MSGRAPH_TEAMS_ENDPOINT = "/groups?$filter=resourceProvisioningOptions/Any(x:x eq 'Team')" MSTEAMS_MSGRAPH_LIST_USERS_ENDPOINT = "/users" MSTEAMS_MSGRAPH_LIST_CHANNELS_ENDPOINT = "/teams/{group_id}/channels" -MSTEAMS_MSGRAPH_SEND_MSG_ENDPOINT = "/teams/{group_id}/channels/{channel_id}/messages" +MSTEAMS_MSGRAPH_SEND_CHANNEL_MSG_ENDPOINT = "/teams/{group_id}/channels/{channel_id}/messages" MSTEAMS_MSGRAPH_LIST_CHATS_ENDPOINT = "/me/chats" MSTEAMS_MSGRAPH_LIST_ME_ENDPOINT = "/me" MSTEAMS_MSGRAPH_LIST_USER_CHATS_ENDPOINT = "/users/{user_id}/chats" MSTEAMS_MSGRAPH_SEND_DIRECT_MSG_ENDPOINT = "/chats/{chat_id}/messages" +MSTEAMS_MSGRAPH_GET_CHANNEL_MSG_ENDPOINT = "/teams/{group_id}/channels/{channel_id}/messages/{message_id}" +MSTEAMS_MSGRAPH_GET_CHAT_MSG_ENDPOINT = "/chats/{chat_id}/messages/{message_id}" MSTEAMS_MSGRAPH_CALENDER_EVENT_ENDPOINT = "/me/calendar/events" MSTEAMS_MSGRAPH_ONLINE_MEETING_ENDPOINT = "/me/onlineMeetings" MSTEAMS_TC_FILE = "oauth_task.out" @@ -61,14 +63,18 @@ MSTEAMS_GOT_CURRENT_USER_INFO_MSG = "Got current user info" MSTEAMS_INVALID_CHANNEL_MSG = "Channel {channel_id} does not belongs to group {group_id}" MSTEAMS_TOKEN_EXPIRED_MSG = "Current access token has expired. New one will be generated." -MSTEAMS_TOKEN_EXPIRED_MARKER = "the token is expired" +MSTEAMS_TOKEN_EXPIRED_MARKER = "the token is expired." MSTEAMS_TOKEN_GENERATED_MSG = "New access token successfully generated." MSTEAMS_STATE_FILE_CORRUPT_ERROR = ( "Error occurred while loading the state file due to it's unexpected format. " "Resetting the state file with the default format. Please test the connectivity." ) + +MSTEAMS_GET_RESPONSE_WAIT_TIME_INVALID = "{} Invalid wait time provided. Must be one of [1, 5, 10]. Default is 1 minute." +MSTEAMS_GET_RESPONSE_WAIT_TIME_LIST = [1, 5, 10] MSTEAMS_JSON_GROUP_ID = "group_id" MSTEAMS_JSON_CHANNEL_ID = "channel_id" +MSTEAMS_JSON_MSG_ID = "message_id" MSTEAMS_JSON_CHAT_ID = "chat_id" MSTEAMS_JSON_USER_ID = "user_id" MSTEAMS_JSON_USER_FILTER = "user" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..4c594fc --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,8 @@ +[tool.black] +line-length = 145 +target-version = ['py39'] +verbose = true + +[tool.isort] +line_length = 145 +profile = "black" diff --git a/release_notes/unreleased.md b/release_notes/unreleased.md index fbcb2fd..16aa123 100644 --- a/release_notes/unreleased.md +++ b/release_notes/unreleased.md @@ -1 +1,3 @@ **Unreleased** +* Updated action name 'send message' to 'send channel message'. +* Added new actions - 'get chat message', 'get channel message', 'get response message'. \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index e861161..e69de29 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +0,0 @@ -beautifulsoup4==4.9.1 diff --git a/tox.ini b/tox.ini index c4644ad..720a141 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,4 @@ [flake8] max-line-length = 145 max-complexity = 28 -extend-ignore = F403,E128,E126,E111,E121,E127,E731,E201,E202,F405,E722,D,W292 - -[isort] -line_length = 145 +extend-ignore = F403,E128,E126,E121,E127,E731,E201,E202,E203,E701,F405,E722,D,W503