Chat Preview3 (#687)
* Regenerate Chat SDK (#574) * [Communication] - [Package] - Exclude ObjC files (#572) * [Package] Exclude the obj-c in package, and include swift build command in CI script * [Package] Testing the removing files from exception should throw a CI error * [Package] bring back the excluded files for CI * [CI] making swift build its own job * fixup! [CI] making swift build its own job Co-authored-by: Brandon Siegel <brsiegel@microsoft.com> * Regenerate chat * Remove the old stuff * Manual fixes * Fix types * More type updates * Remove MergePatchObject * Update names, remove Custom folder * More rename member to participant * Remove comment * Regenerate again with latest autorest fixes * Revert readme * Typo again * Lint Co-authored-by: JoshuaLai <9044372+JoshuaLai@users.noreply.github.com> Co-authored-by: Brandon Siegel <brsiegel@microsoft.com> * Add ChatClient and ChatThreadClient convenience layer (#578) * Renaming for ios guidelines * More fixing up naming * Update references to old client * Swiftformat * Add dependency * Fix naming to be consistent * Fix name, update readme * Update naming, fix naming in docs * Format * Update README * Update with latest swagger - create thread changes (#581) * Regenerate SDK * Update README for create thread * Update response for adding participants * Revert change failing lint * Rename maxpagesize for get threads (#586) * Updated chatparticipants + maxPageSize naming (#598) * Add unit tests for ACS chat service (#606) * Run AzureCommunicationChat tests on CI. (#610) * Run tests on CI. * Temporarily switch scheme to just AzureCommunicationChat. * Update phone deployment target. * Restore `all` build schema. * Add integration tests with record/playback mode (#607) * Fix settings * Delete old recordings dir * Add record/playback tests * Generate chatClient recordings * Fix typo in unit test * Sanitize senderId from recordings, add getMessage stub * Linting * Revert change to all scheme * Revert local build setting * Revert merge changes * Remove unused files * Regenerate Chat * Add ChatMessageContent to project * Lint and update tests * Manually fix api-version * Remove mergepatch * Update recordings * Update mocks * Fix mock stubs conflicting with live tests * Revert readme * Add test coverage for list methods (#623) * Latest swagger updates for Chat SDK (#626) * Regenerate chat * Manual fixes * Fix tests * Update mocks/recordings * Update readme * add signaling test app (#634) add signaling test app * [Communication] - Auth - Removing a duplicate policy and replacing it with bearer auth policy (#633) * [CommunicationAuthenticationPolicy] Removing a duplicate policy * [CommunicationPolicyTokenCredential] adding documentation * [CommunicationPolicyTokenCredentialTests] Adding new unit tests testing the token credential * [CHANGELOG] updating the change log with breaking changes * Update naming CommuniCationUserCredential -> CommunicationTokenCredential * Fix changelog merge * Update Chat with latest swagger (#645) * Regenerate Chat * Remove try catch * Manual fix in generated code * Remove priority from chatmessage * Linting * Remove unused file * Update recordings * Remove priority from readme * Regenerate again * Chat SDK uses Communication identifiers (#656) * Add custom models * More models WIP * Update convenience layer to use custom models WIP * Convert paged collections, update usage * Remove todo * Update tests + recordings * Clean up duplicated code * Add comment * Fix docs * Update README * Fix comment * Remove Codable not needed on identifiers * Add test for HTML message, clean up tests (#661) * Chat sets repeatability-Request-ID if its not provided (#660) * Add repeatability-request-id * Remove header from mock response * Fix typo (#664) * Fix conflicts Keep preview3 generated Add deployment target Add null check, delete unused files Fix merge on build settings, revert package.swift Revert change Keep upgraded build settings Set missing deployment target failing archive * Update naming in comments for token credential (#684) * Build setting for running Chat tests (#685) * Revert deployment target to see if tests picked up on CI * Remove warning on pod install * WIP editing build settings * Add chat tests to sdk scheme * typo * Fix duplicate unit test * Remove swagger for dev purposes * gitignore files * Add back setting for pod install warning * Remove preview2 generated file * Cannot reference ohttpstubs removeall * Split unit and integration tests * Remove signalling test app * Remove signalling files * Update changelog * Update changelog * Update changelog * Add back file, fix changelog Co-authored-by: JoshuaLai <9044372+JoshuaLai@users.noreply.github.com> Co-authored-by: Brandon Siegel <brsiegel@microsoft.com> Co-authored-by: Jixing (Leo) Li <lijixing3377@gmail.com> Co-authored-by: Travis Prescott <tjprescott@users.noreply.github.com> Co-authored-by: glorialimicrosoft <67171398+glorialimicrosoft@users.noreply.github.com>
This commit is contained in:
Родитель
8b04ebfcae
Коммит
41039cc13f
|
@ -38,7 +38,7 @@ playground.xcworkspace
|
|||
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
|
||||
# Packages/
|
||||
# Package.pins
|
||||
# Package.resolved
|
||||
Package.resolved
|
||||
.build/
|
||||
.swiftpm/
|
||||
|
||||
|
|
|
@ -42,10 +42,10 @@
|
|||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "0A686488233E834D004B7E17"
|
||||
BuildableName = "AzureStorageBlob.framework"
|
||||
BlueprintName = "AzureStorageBlob"
|
||||
ReferencedContainer = "container:sdk/storage/AzureStorageBlob/AzureStorageBlob.xcodeproj">
|
||||
BlueprintIdentifier = "0A3A5EB72316DB1E00473FDA"
|
||||
BuildableName = "AzureCommunication.framework"
|
||||
BlueprintName = "AzureCommunication"
|
||||
ReferencedContainer = "container:sdk/communication/AzureCommunication/AzureCommunication.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
|
@ -56,10 +56,10 @@
|
|||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "0A3A5EB72316DB1E00473FDA"
|
||||
BuildableName = "AzureCommunication.framework"
|
||||
BlueprintName = "AzureCommunication"
|
||||
ReferencedContainer = "container:sdk/communication/AzureCommunication/AzureCommunication.xcodeproj">
|
||||
BlueprintIdentifier = "0A686488233E834D004B7E17"
|
||||
BuildableName = "AzureStorageBlob.framework"
|
||||
BlueprintName = "AzureStorageBlob"
|
||||
ReferencedContainer = "container:sdk/storage/AzureStorageBlob/AzureStorageBlob.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
|
@ -132,6 +132,48 @@
|
|||
ReferencedContainer = "container:sdk/communication/AzureCommunication/AzureCommunication.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "NO"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "0A3A5E892315E70600473FDA"
|
||||
BuildableName = "AzureSDKDemoSwiftTests.xctest"
|
||||
BlueprintName = "AzureSDKDemoSwiftTests"
|
||||
ReferencedContainer = "container:examples/AzureSDKDemoSwift/AzureSDKDemoSwift.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "NO"
|
||||
buildForProfiling = "NO"
|
||||
buildForArchiving = "NO"
|
||||
buildForAnalyzing = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "0A686491233E834D004B7E17"
|
||||
BuildableName = "AzureStorageBlobTests.xctest"
|
||||
BlueprintName = "AzureStorageBlobTests"
|
||||
ReferencedContainer = "container:sdk/storage/AzureStorageBlob/AzureStorageBlob.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "AzureCommunicationChat::AzureCommunicationChat"
|
||||
BuildableName = "AzureCommunicationChat.framework"
|
||||
BlueprintName = "AzureCommunicationChat"
|
||||
ReferencedContainer = "container:sdk/communication/AzureCommunicationChat/AzureCommunicationChat.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
|
@ -168,10 +210,10 @@
|
|||
parallelizable = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "0A686491233E834D004B7E17"
|
||||
BuildableName = "AzureStorageBlobTests.xctest"
|
||||
BlueprintName = "AzureStorageBlobTests"
|
||||
ReferencedContainer = "container:sdk/storage/AzureStorageBlob/AzureStorageBlob.xcodeproj">
|
||||
BlueprintIdentifier = "0A3A5EC02316DB1E00473FDA"
|
||||
BuildableName = "AzureCommunicationTests.xctest"
|
||||
BlueprintName = "AzureCommunicationTests"
|
||||
ReferencedContainer = "container:sdk/communication/AzureCommunication/AzureCommunication.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
|
@ -179,10 +221,30 @@
|
|||
parallelizable = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "0A3A5EC02316DB1E00473FDA"
|
||||
BuildableName = "AzureCommunicationTests.xctest"
|
||||
BlueprintName = "AzureCommunicationTests"
|
||||
ReferencedContainer = "container:sdk/communication/AzureCommunication/AzureCommunication.xcodeproj">
|
||||
BlueprintIdentifier = "D1B7EAEC257F02FC004F384A"
|
||||
BuildableName = "AzureCommunicationChatTests.xctest"
|
||||
BlueprintName = "AzureCommunicationChatTests"
|
||||
ReferencedContainer = "container:sdk/communication/AzureCommunicationChat/AzureCommunicationChat.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "0A3A5E892315E70600473FDA"
|
||||
BuildableName = "AzureSDKDemoSwiftTests.xctest"
|
||||
BlueprintName = "AzureSDKDemoSwiftTests"
|
||||
ReferencedContainer = "container:examples/AzureSDKDemoSwift/AzureSDKDemoSwift.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "0A686491233E834D004B7E17"
|
||||
BuildableName = "AzureStorageBlobTests.xctest"
|
||||
BlueprintName = "AzureStorageBlobTests"
|
||||
ReferencedContainer = "container:sdk/storage/AzureStorageBlob/AzureStorageBlob.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
|
|
|
@ -157,6 +157,28 @@
|
|||
ReferencedContainer = "container:sdk/communication/AzureCommunication/AzureCommunication.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO"
|
||||
parallelizable = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "D1B7EAEC257F02FC004F384A"
|
||||
BuildableName = "AzureCommunicationChatTests.xctest"
|
||||
BlueprintName = "AzureCommunicationChatTests"
|
||||
ReferencedContainer = "container:sdk/communication/AzureCommunicationChat/AzureCommunicationChat.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO"
|
||||
parallelizable = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "D147E62725CE242C001CFB5D"
|
||||
BuildableName = "AzureCommunicationChatUnitTests.xctest"
|
||||
BlueprintName = "AzureCommunicationChatUnitTests"
|
||||
ReferencedContainer = "container:sdk/communication/AzureCommunicationChat/AzureCommunicationChat.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
|
|
25
CHANGELOG.md
25
CHANGELOG.md
|
@ -1,14 +1,35 @@
|
|||
# Release History
|
||||
|
||||
## 1.0.0-beta.8 (Unreleased)
|
||||
### New Features
|
||||
|
||||
- Azure Communication Chat Library
|
||||
- Introduced ChatClient and ChatThreadClient to split operations on threads and operations within a particular thread
|
||||
- Create thread sets repeatability-Request-ID for idempotency if not provided
|
||||
- Introduced MessageContent model to replace string content property
|
||||
|
||||
### Breaking Changes
|
||||
- Azure Communication Common Library
|
||||
- Renamed the type `CommunicationUserCredential` to `CommunicationTokenCredential`, as it represents a token.
|
||||
- Communication identifier `MicrosoftTeamsUserIdentifier` property `identifier` renamed to `userId` since identifier was too generic.
|
||||
- Communication identifier `MicrosoftTeamsUserIdentifier` property `id` renamed to `rawId` to represent full MRI.
|
||||
- Communication identifier `PhoneNumberIdentifier` property `id` renamed to `rawId` to represent full MRI.
|
||||
- Removed `CallingApplicationIdentifier` as it is currently unused by any service.
|
||||
- Removed `CallingApplicationIdentifier` as it is currently unused by any service.
|
||||
- The protocol `CommunicationTokenCredential` has likewise been renamed to `CommunicationTokenCredentialProviding`.
|
||||
- All types that conform to the `CommunicationIdentifier` protocol now use the suffix `Identifier`. For example, the
|
||||
`PhoneNumber` type used to represent a phone number identifier is now named `PhoneNumberIdentifier`.
|
||||
- Updated the `CommunicationTokenCredential` initializer that automatically refreshes the token to accept a single
|
||||
`CommunicationTokenRefreshOptions` object instead of multiple parameters.
|
||||
|
||||
- Azure Communication Chat Library
|
||||
- ChatThreadMember renamed to Participant, uses CommunicationUserIdentifier
|
||||
- ChatMessage renamed to Message, uses CommunicationUserIdentifier
|
||||
- ChatThread renamed to Thread, uses CommunicationUserIdentifier
|
||||
|
||||
### Key Bug Fixes
|
||||
- Removing `CommunicationUserCredentialPolicy`, this policy was a duplicate of cores `BearerTokenCredentialPolicy`.
|
||||
Communication now has new ability to create `BearerTokenCredentialPolicy` using the new `CommunicationPolicyTokenCredential`.
|
||||
|
||||
## 1.0.0-beta.7 (2021-01-12)
|
||||
|
||||
### New Features
|
||||
|
@ -89,4 +110,4 @@ our efforts can be found in the
|
|||
|
||||
- Azure SDK for iOS core ([AzureCore](https://github.com/Azure/azure-sdk-for-ios/tree/master/sdk/core/AzureCore))
|
||||
- Azure Communication Services common ([AzureCommunication](https://github.com/Azure/azure-sdk-for-ios/tree/master/sdk/communication/AzureCommunication))
|
||||
- This library is used by other libraries in this SDK, as well as by libraries in the [Azure Communication SDKs](https://github.com/Azure/Communication).
|
||||
- This library is used by other libraries in this SDK, as well as by libraries in the [Azure Communication SDKs](https://github.com/Azure/Communication).
|
|
@ -39,7 +39,9 @@ let package = Package(
|
|||
.library(name: "AzureCommunication", targets: ["AzureCommunication"]),
|
||||
.library(name: "AzureCommunicationChat", targets: ["AzureCommunicationChat"]),
|
||||
],
|
||||
dependencies: [],
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/AliSoftware/OHHTTPStubs.git", from: "9.1.0")
|
||||
],
|
||||
targets: [
|
||||
// Build targets
|
||||
.target(
|
||||
|
@ -58,7 +60,7 @@ let package = Package(
|
|||
),
|
||||
.target(
|
||||
name: "AzureCommunicationChat",
|
||||
dependencies: ["AzureCore"],
|
||||
dependencies: ["AzureCore", "AzureCommunication"],
|
||||
path: "sdk/communication/AzureCommunicationChat",
|
||||
exclude: ["Source/Supporting Files"],
|
||||
sources: ["Source"]
|
||||
|
@ -69,8 +71,8 @@ let package = Package(
|
|||
dependencies: ["AzureCore"],
|
||||
path: "sdk/core/AzureCore",
|
||||
exclude: [
|
||||
"Tests/Info.plist",
|
||||
"Tests/Data Files"
|
||||
"Tests/Info.plist",
|
||||
"Tests/Data Files"
|
||||
],
|
||||
sources: ["Tests"]
|
||||
),
|
||||
|
@ -86,6 +88,21 @@ let package = Package(
|
|||
"Tests/ObjCTokenParserTests.m"
|
||||
],
|
||||
sources: ["Tests"]
|
||||
),
|
||||
.testTarget(
|
||||
name: "AzureCommunicationChatTests",
|
||||
dependencies: [
|
||||
"AzureCommunication",
|
||||
"AzureCommunicationChat",
|
||||
.product(name: "OHHTTPStubsSwift", package: "OHHTTPStubs"),
|
||||
],
|
||||
path: "sdk/communication/AzureCommunicationChat",
|
||||
exclude: [
|
||||
"Tests/Info.plist",
|
||||
"Tests/Util/Mocks",
|
||||
"Tests/Util/Recordings"
|
||||
],
|
||||
sources: ["Tests"]
|
||||
)
|
||||
],
|
||||
swiftLanguageVersions: [.v5]
|
||||
|
|
22
Podfile
22
Podfile
|
@ -28,6 +28,28 @@ use_frameworks!
|
|||
platform :ios, '12.0'
|
||||
workspace 'AzureSDK'
|
||||
|
||||
target 'AzureCommunication' do
|
||||
project 'sdk/communication/AzureCommunication/AzureCommunication'
|
||||
|
||||
target 'AzureCommunicationTests' do
|
||||
inherit! :search_paths
|
||||
end
|
||||
end
|
||||
|
||||
target 'AzureCommunicationChat' do
|
||||
project 'sdk/communication/AzureCommunicationChat/AzureCommunicationChat'
|
||||
|
||||
target 'AzureCommunicationChatTests' do
|
||||
inherit! :search_paths
|
||||
pod 'OHHTTPStubs/Swift'
|
||||
end
|
||||
|
||||
target 'AzureCommunicationChatUnitTests' do
|
||||
inherit! :search_paths
|
||||
pod 'OHHTTPStubs/Swift'
|
||||
end
|
||||
end
|
||||
|
||||
target 'AzureCore' do
|
||||
project 'sdk/core/AzureCore/AzureCore'
|
||||
|
||||
|
|
|
@ -12,12 +12,17 @@
|
|||
1D2E7F7024E4589100447964 /* Identifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D2E7F6F24E4589100447964 /* Identifiers.swift */; };
|
||||
1DE4DB7724C0FE8300631921 /* AutoRefreshTokenCredential.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DE4DB7624C0FE8300631921 /* AutoRefreshTokenCredential.swift */; };
|
||||
1DE4DB7924C1063E00631921 /* ThreadSafeRefreshableAccessTokenCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DE4DB7824C1063E00631921 /* ThreadSafeRefreshableAccessTokenCache.swift */; };
|
||||
7AAE2D17251444B600C9F897 /* CommunicationAuthenticationPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AAE2D16251444B600C9F897 /* CommunicationAuthenticationPolicy.swift */; };
|
||||
6BEEB9676DB4864DB30F6919 /* Pods_AzureCommunicationTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DE026FF4E92423EB0A935FD4 /* Pods_AzureCommunicationTests.framework */; };
|
||||
7AAE2D17251444B600C9F897 /* CommunicationPolicyTokenCredential.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AAE2D16251444B600C9F897 /* CommunicationPolicyTokenCredential.swift */; };
|
||||
882F28D425A632CA009689E3 /* CommunicationTokenRefreshOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 882F28D325A632CA009689E3 /* CommunicationTokenRefreshOptions.swift */; };
|
||||
883AEDB825AF623000E21497 /* CommunicationPolicyTokenCredentialTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 883AEDB725AF623000E21497 /* CommunicationPolicyTokenCredentialTests.swift */; };
|
||||
8856CEAC253A376D00044559 /* CommunicationAccessToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8856CEAB253A376D00044559 /* CommunicationAccessToken.swift */; };
|
||||
8856CEE5253E3AEF00044559 /* ObjCCommunicationTokenCredentialTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8856CEE4253E3AEF00044559 /* ObjCCommunicationTokenCredentialTests.m */; };
|
||||
88CC8C35254750260028977C /* ObjCCommunicationTokenCredentialAsyncTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 88CC8C34254750260028977C /* ObjCCommunicationTokenCredentialAsyncTests.m */; };
|
||||
88F1F570254A07BC00876BC4 /* ObjCTokenParserTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 88F1F56F254A07BC00876BC4 /* ObjCTokenParserTests.m */; };
|
||||
D112634825B7969B00F437C6 /* (null) in Sources */ = {isa = PBXBuildFile; };
|
||||
D1A42CF825CCA1C100408C0F /* CommunicationTokenCredential.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1A42CF725CCA1C100408C0F /* CommunicationTokenCredential.swift */; };
|
||||
DC294E02BC5156475835816E /* Pods_AzureCommunication.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E1FFD6B8DB6B306AC0F040BB /* Pods_AzureCommunication.framework */; };
|
||||
F11E5CC824B77F8900AA3A58 /* AzureCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A3A5ED62316DB8F00473FDA /* AzureCore.framework */; };
|
||||
F1540E9625BF83D80056B087 /* Enumerations.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1540E9325BF83D80056B087 /* Enumerations.swift */; };
|
||||
F1540E9725BF83D80056B087 /* CommunicationIdentifierModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1540E9425BF83D80056B087 /* CommunicationIdentifierModel.swift */; };
|
||||
|
@ -27,7 +32,6 @@
|
|||
F1540EC125BFD6910056B087 /* CommunicationIdentifierTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1540EC025BFD6910056B087 /* CommunicationIdentifierTest.swift */; };
|
||||
F183A5EB24AF9D9000F0E0D5 /* CommunicationTokenCredentialProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = F183A5EA24AF9D9000F0E0D5 /* CommunicationTokenCredentialProviding.swift */; };
|
||||
F183A5FA24AFB37900F0E0D5 /* StaticTokenCredential.swift in Sources */ = {isa = PBXBuildFile; fileRef = F183A5F924AFB37900F0E0D5 /* StaticTokenCredential.swift */; };
|
||||
F183A5FC24AFEF1400F0E0D5 /* CommunicationTokenCredential.swift in Sources */ = {isa = PBXBuildFile; fileRef = F183A5FB24AFEF1400F0E0D5 /* CommunicationTokenCredential.swift */; };
|
||||
F183A5FE24AFF1B100F0E0D5 /* JwtTokenParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = F183A5FD24AFF1B100F0E0D5 /* JwtTokenParser.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
|
@ -51,14 +55,22 @@
|
|||
1DC3550524D9F02D0095ABD9 /* Supporting Files */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "Supporting Files"; sourceTree = "<group>"; };
|
||||
1DE4DB7624C0FE8300631921 /* AutoRefreshTokenCredential.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoRefreshTokenCredential.swift; sourceTree = "<group>"; };
|
||||
1DE4DB7824C1063E00631921 /* ThreadSafeRefreshableAccessTokenCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadSafeRefreshableAccessTokenCache.swift; sourceTree = "<group>"; };
|
||||
7AAE2D16251444B600C9F897 /* CommunicationAuthenticationPolicy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommunicationAuthenticationPolicy.swift; sourceTree = "<group>"; };
|
||||
316382976240347BE77E907F /* Pods-AzureCommunication.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AzureCommunication.release.xcconfig"; path = "Target Support Files/Pods-AzureCommunication/Pods-AzureCommunication.release.xcconfig"; sourceTree = "<group>"; };
|
||||
73DFF8D8D93685E64E46AD1B /* Pods-AzureCommunication.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AzureCommunication.debug.xcconfig"; path = "Target Support Files/Pods-AzureCommunication/Pods-AzureCommunication.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
7AAE2D16251444B600C9F897 /* CommunicationPolicyTokenCredential.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommunicationPolicyTokenCredential.swift; sourceTree = "<group>"; };
|
||||
7AB0952825BF895B0026A2A5 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
|
||||
882F28D325A632CA009689E3 /* CommunicationTokenRefreshOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommunicationTokenRefreshOptions.swift; sourceTree = "<group>"; };
|
||||
883AEDB725AF623000E21497 /* CommunicationPolicyTokenCredentialTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommunicationPolicyTokenCredentialTests.swift; sourceTree = "<group>"; };
|
||||
8856CEAB253A376D00044559 /* CommunicationAccessToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommunicationAccessToken.swift; sourceTree = "<group>"; };
|
||||
8856CEE3253E3AEF00044559 /* AzureCommunicationTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AzureCommunicationTests-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
8856CEE4253E3AEF00044559 /* ObjCCommunicationTokenCredentialTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ObjCCommunicationTokenCredentialTests.m; sourceTree = "<group>"; };
|
||||
88CC8C34254750260028977C /* ObjCCommunicationTokenCredentialAsyncTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ObjCCommunicationTokenCredentialAsyncTests.m; sourceTree = "<group>"; };
|
||||
88F1F56F254A07BC00876BC4 /* ObjCTokenParserTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ObjCTokenParserTests.m; sourceTree = "<group>"; };
|
||||
C7FEC671B55120C7AFDF3B62 /* Pods-AzureCommunicationTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AzureCommunicationTests.debug.xcconfig"; path = "Target Support Files/Pods-AzureCommunicationTests/Pods-AzureCommunicationTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
D1A42CF725CCA1C100408C0F /* CommunicationTokenCredential.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommunicationTokenCredential.swift; sourceTree = "<group>"; };
|
||||
DE026FF4E92423EB0A935FD4 /* Pods_AzureCommunicationTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AzureCommunicationTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
E1FFD6B8DB6B306AC0F040BB /* Pods_AzureCommunication.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AzureCommunication.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
E5E66C937B734ADA8532CFC3 /* Pods-AzureCommunicationTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AzureCommunicationTests.release.xcconfig"; path = "Target Support Files/Pods-AzureCommunicationTests/Pods-AzureCommunicationTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
F1540E9325BF83D80056B087 /* Enumerations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Enumerations.swift; sourceTree = "<group>"; };
|
||||
F1540E9425BF83D80056B087 /* CommunicationIdentifierModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommunicationIdentifierModel.swift; sourceTree = "<group>"; };
|
||||
F1540E9525BF83D80056B087 /* CommunicationIdentifierSerializer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommunicationIdentifierSerializer.swift; sourceTree = "<group>"; };
|
||||
|
@ -67,7 +79,6 @@
|
|||
F1540EC025BFD6910056B087 /* CommunicationIdentifierTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommunicationIdentifierTest.swift; sourceTree = "<group>"; };
|
||||
F183A5EA24AF9D9000F0E0D5 /* CommunicationTokenCredentialProviding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommunicationTokenCredentialProviding.swift; sourceTree = "<group>"; };
|
||||
F183A5F924AFB37900F0E0D5 /* StaticTokenCredential.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticTokenCredential.swift; sourceTree = "<group>"; };
|
||||
F183A5FB24AFEF1400F0E0D5 /* CommunicationTokenCredential.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommunicationTokenCredential.swift; sourceTree = "<group>"; };
|
||||
F183A5FD24AFF1B100F0E0D5 /* JwtTokenParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JwtTokenParser.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
|
@ -77,6 +88,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F11E5CC824B77F8900AA3A58 /* AzureCore.framework in Frameworks */,
|
||||
DC294E02BC5156475835816E /* Pods_AzureCommunication.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -85,6 +97,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0A3A5EC22316DB1E00473FDA /* AzureCommunication.framework in Frameworks */,
|
||||
6BEEB9676DB4864DB30F6919 /* Pods_AzureCommunicationTests.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -99,6 +112,7 @@
|
|||
0A3A5EB92316DB1E00473FDA /* Products */,
|
||||
0A3A5ED52316DB5700473FDA /* Frameworks */,
|
||||
7AB0952825BF895B0026A2A5 /* README.md */,
|
||||
2D9F376773AE2A9C7A306867 /* Pods */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
|
@ -136,6 +150,7 @@
|
|||
8856CEE3253E3AEF00044559 /* AzureCommunicationTests-Bridging-Header.h */,
|
||||
88F1F56F254A07BC00876BC4 /* ObjCTokenParserTests.m */,
|
||||
F1540EC025BFD6910056B087 /* CommunicationIdentifierTest.swift */,
|
||||
883AEDB725AF623000E21497 /* CommunicationPolicyTokenCredentialTests.swift */,
|
||||
);
|
||||
path = Tests;
|
||||
sourceTree = "<group>";
|
||||
|
@ -144,6 +159,8 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
0A3A5ED62316DB8F00473FDA /* AzureCore.framework */,
|
||||
E1FFD6B8DB6B306AC0F040BB /* Pods_AzureCommunication.framework */,
|
||||
DE026FF4E92423EB0A935FD4 /* Pods_AzureCommunicationTests.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
|
@ -151,19 +168,31 @@
|
|||
1D2E7F6E24E4536500447964 /* Authentication */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D1A42CF725CCA1C100408C0F /* CommunicationTokenCredential.swift */,
|
||||
8856CEAB253A376D00044559 /* CommunicationAccessToken.swift */,
|
||||
F183A5EA24AF9D9000F0E0D5 /* CommunicationTokenCredentialProviding.swift */,
|
||||
F183A5F924AFB37900F0E0D5 /* StaticTokenCredential.swift */,
|
||||
F183A5FB24AFEF1400F0E0D5 /* CommunicationTokenCredential.swift */,
|
||||
F183A5FD24AFF1B100F0E0D5 /* JwtTokenParser.swift */,
|
||||
1DE4DB7624C0FE8300631921 /* AutoRefreshTokenCredential.swift */,
|
||||
1DE4DB7824C1063E00631921 /* ThreadSafeRefreshableAccessTokenCache.swift */,
|
||||
7AAE2D16251444B600C9F897 /* CommunicationAuthenticationPolicy.swift */,
|
||||
7AAE2D16251444B600C9F897 /* CommunicationPolicyTokenCredential.swift */,
|
||||
882F28D325A632CA009689E3 /* CommunicationTokenRefreshOptions.swift */,
|
||||
);
|
||||
path = Authentication;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2D9F376773AE2A9C7A306867 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
73DFF8D8D93685E64E46AD1B /* Pods-AzureCommunication.debug.xcconfig */,
|
||||
316382976240347BE77E907F /* Pods-AzureCommunication.release.xcconfig */,
|
||||
C7FEC671B55120C7AFDF3B62 /* Pods-AzureCommunicationTests.debug.xcconfig */,
|
||||
E5E66C937B734ADA8532CFC3 /* Pods-AzureCommunicationTests.release.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
path = ../../../Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
|
@ -181,6 +210,7 @@
|
|||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 0A3A5ECC2316DB1E00473FDA /* Build configuration list for PBXNativeTarget "AzureCommunication" */;
|
||||
buildPhases = (
|
||||
892BA074040FFB4A74C86592 /* [CP] Check Pods Manifest.lock */,
|
||||
0A3A5EB32316DB1E00473FDA /* Headers */,
|
||||
0A3A5EB42316DB1E00473FDA /* Sources */,
|
||||
0A3A5EB52316DB1E00473FDA /* Frameworks */,
|
||||
|
@ -200,6 +230,7 @@
|
|||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 0A3A5ECF2316DB1E00473FDA /* Build configuration list for PBXNativeTarget "AzureCommunicationTests" */;
|
||||
buildPhases = (
|
||||
DED08D1BF86630CC5BACF415 /* [CP] Check Pods Manifest.lock */,
|
||||
0A3A5EBD2316DB1E00473FDA /* Sources */,
|
||||
0A3A5EBE2316DB1E00473FDA /* Frameworks */,
|
||||
0A3A5EBF2316DB1E00473FDA /* Resources */,
|
||||
|
@ -290,6 +321,50 @@
|
|||
";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
892BA074040FFB4A74C86592 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-AzureCommunication-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
DED08D1BF86630CC5BACF415 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-AzureCommunicationTests-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
|
@ -305,9 +380,10 @@
|
|||
1DE4DB7724C0FE8300631921 /* AutoRefreshTokenCredential.swift in Sources */,
|
||||
F1540EBD25BF893C0056B087 /* CommunicationCloudEnvironment.swift in Sources */,
|
||||
882F28D425A632CA009689E3 /* CommunicationTokenRefreshOptions.swift in Sources */,
|
||||
F183A5FC24AFEF1400F0E0D5 /* CommunicationTokenCredential.swift in Sources */,
|
||||
7AAE2D17251444B600C9F897 /* CommunicationAuthenticationPolicy.swift in Sources */,
|
||||
7AAE2D17251444B600C9F897 /* CommunicationPolicyTokenCredential.swift in Sources */,
|
||||
F183A5FE24AFF1B100F0E0D5 /* JwtTokenParser.swift in Sources */,
|
||||
D112634825B7969B00F437C6 /* (null) in Sources */,
|
||||
D1A42CF825CCA1C100408C0F /* CommunicationTokenCredential.swift in Sources */,
|
||||
F183A5FA24AFB37900F0E0D5 /* StaticTokenCredential.swift in Sources */,
|
||||
F1540E9625BF83D80056B087 /* Enumerations.swift in Sources */,
|
||||
F1540E9725BF83D80056B087 /* CommunicationIdentifierModel.swift in Sources */,
|
||||
|
@ -324,6 +400,7 @@
|
|||
F1540EC125BFD6910056B087 /* CommunicationIdentifierTest.swift in Sources */,
|
||||
1D07222D24C8FB0F00C2EF4E /* CommunicationTokenCredentialTests.swift in Sources */,
|
||||
88CC8C35254750260028977C /* ObjCCommunicationTokenCredentialAsyncTests.m in Sources */,
|
||||
883AEDB825AF623000E21497 /* CommunicationPolicyTokenCredentialTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -464,6 +541,7 @@
|
|||
};
|
||||
0A3A5ECD2316DB1E00473FDA /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 73DFF8D8D93685E64E46AD1B /* Pods-AzureCommunication.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
APPLICATION_EXTENSION_API_ONLY = NO;
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
|
||||
|
@ -493,6 +571,7 @@
|
|||
};
|
||||
0A3A5ECE2316DB1E00473FDA /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 316382976240347BE77E907F /* Pods-AzureCommunication.release.xcconfig */;
|
||||
buildSettings = {
|
||||
APPLICATION_EXTENSION_API_ONLY = NO;
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
|
||||
|
@ -521,6 +600,7 @@
|
|||
};
|
||||
0A3A5ED02316DB1E00473FDA /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = C7FEC671B55120C7AFDF3B62 /* Pods-AzureCommunicationTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
|
@ -541,6 +621,7 @@
|
|||
};
|
||||
0A3A5ED12316DB1E00473FDA /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = E5E66C937B734ADA8532CFC3 /* Pods-AzureCommunicationTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
|
|
|
@ -101,14 +101,14 @@ $ pod install
|
|||
|
||||
## Key concepts
|
||||
|
||||
### CommunicationUserCredential
|
||||
A `CommunicationUserCredential` authenticates a user with Communication Services, such as Chat or Calling. It optionally
|
||||
### CommunicationTokenCredential
|
||||
A `CommunicationTokenCredential` authenticates a user with Communication Services, such as Chat or Calling. It optionally
|
||||
provides an auto-refresh mechanism to ensure a continuously stable authentication state during communications. User
|
||||
tokens are created by the application developer using the Communication Administration SDK - once created, they are
|
||||
provided to the various Communication Services client libraries by way of a `CommunicationUserCredential` object.
|
||||
provided to the various Communication Services client libraries by way of a `CommunicationTokenCredential` object.
|
||||
|
||||
## Examples
|
||||
The following sections provide several code snippets showing different ways to use a `CommunicationUserCredential`:
|
||||
The following sections provide several code snippets showing different ways to use a `CommunicationTokenCredential`:
|
||||
|
||||
* [Creating a credential with a static token](#creating-a-credential-with-a-static-token)
|
||||
* [Creating a credential that refreshes synchronously](#creating-a-credential-that-refreshes-synchronously)
|
||||
|
@ -117,7 +117,7 @@ The following sections provide several code snippets showing different ways to u
|
|||
### Creating a credential with a static token
|
||||
```swift
|
||||
let sampleToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjMyNTAzNjgwMDAwfQ.9i7FNNHHJT8cOzo-yrAUJyBSfJ-tPPk2emcHavOEpWc"
|
||||
let userCredential = try CommunicationUserCredential(token: sampleToken)
|
||||
let credential = try CommunicationTokenCredential(token: sampleToken)
|
||||
```
|
||||
|
||||
### Creating a credential that refreshes synchronously
|
||||
|
@ -130,12 +130,12 @@ func fetchTokenSync(completionHandler: TokenRefreshOnCompletion) {
|
|||
completionHandler(newToken, nil)
|
||||
}
|
||||
|
||||
let userCredential = try CommunicationUserCredential(initialToken: sampleExpiredToken,
|
||||
let credential = try CommunicationTokenCredential(initialToken: sampleExpiredToken,
|
||||
refreshProactively: false,
|
||||
tokenRefresher: fetchTokenSync)
|
||||
|
||||
DispatchQueue.global(qos: .utility).async {
|
||||
userCredential.token { (accessToken: AccessToken?, error: Error?) in
|
||||
credential.token { (accessToken: AccessToken?, error: Error?) in
|
||||
...
|
||||
}
|
||||
}
|
||||
|
@ -156,12 +156,12 @@ func fetchTokenAsync(completionHandler: @escaping TokenRefreshOnCompletion) {
|
|||
}
|
||||
}
|
||||
|
||||
let userCredential = try CommunicationUserCredential(initialToken: sampleExpiredToken,
|
||||
let credential = try CommunicationTokenCredential(initialToken: sampleExpiredToken,
|
||||
refreshProactively: false,
|
||||
tokenRefresher: fetchTokenAsync)
|
||||
|
||||
DispatchQueue.global(qos: .utility).async {
|
||||
userCredential.token { (accessToken: AccessToken?, error: Error?) in
|
||||
credential.token { (accessToken: AccessToken?, error: Error?) in
|
||||
...
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,44 +29,47 @@ import AzureCore
|
|||
#endif
|
||||
import Foundation
|
||||
/**
|
||||
The Azure Communication Services authentication policy.
|
||||
The Azure Communication Services token credential used to authenticate pipeline requests.
|
||||
*/
|
||||
public class CommunicationTokenCredentialPolicy: Authenticating {
|
||||
public var next: PipelineStage?
|
||||
|
||||
public class CommunicationPolicyTokenCredential: TokenCredential {
|
||||
private let credential: CommunicationTokenCredential
|
||||
|
||||
var error: AzureError? = nil
|
||||
/**
|
||||
Creates a credential policy that authenticates requests using the provided `CommunicationTokenCredential`.
|
||||
Creates a token credential that authenticates requests using the provided `CommunicationTokenCredential`.
|
||||
|
||||
- Parameter credential: The `CommunicationTokenCredential` that will be used to authenticate requests.
|
||||
|
||||
- SeeAlso: `CommunicationTokenCredential.init(...)`
|
||||
- Parameter credential: The token credential to authenticate with.
|
||||
*/
|
||||
public init(credential: CommunicationTokenCredential) {
|
||||
public init(_ credential: CommunicationTokenCredential) {
|
||||
self.credential = credential
|
||||
}
|
||||
|
||||
/**
|
||||
Authenticates an HTTP `PipelineRequest` with a token retrieved from the credential.
|
||||
Retrieve a token for the provided scope.
|
||||
|
||||
- Parameters:
|
||||
- request:A `PipelineRequest` object.
|
||||
- completionHandler: A completion handler that forwards the modified pipeline request.
|
||||
- scopes: A list of a scope strings for which to retrieve the token.
|
||||
- completionHandler: A completion handler which forwards the access token.
|
||||
*/
|
||||
public func authenticate(request: PipelineRequest, completionHandler: @escaping OnRequestCompletionHandler) {
|
||||
credential.token { token, error in
|
||||
if let error = error {
|
||||
completionHandler(request, AzureError.client("Error while retrieving access token", error))
|
||||
public func token(forScopes scopes: [String], completionHandler: @escaping TokenCompletionHandler) {
|
||||
credential.token { (communicationAccessToken, error) in
|
||||
guard let communicationAccessToken = communicationAccessToken else {
|
||||
self.error = AzureError.client("Communication Token Failure", error)
|
||||
completionHandler(nil, self.error)
|
||||
return
|
||||
}
|
||||
|
||||
guard let token = token?.token else {
|
||||
completionHandler(request, AzureError.client("Token cannot be empty"))
|
||||
return
|
||||
}
|
||||
|
||||
request.httpRequest.headers[.authorization] = "Bearer \(token)"
|
||||
completionHandler(request, nil)
|
||||
|
||||
let accessToken = AccessToken(token: communicationAccessToken.token,
|
||||
expiresOn: communicationAccessToken.expiresOn)
|
||||
|
||||
completionHandler(accessToken, nil)
|
||||
}
|
||||
}
|
||||
/**
|
||||
Validates throws an error if token creating had any errors
|
||||
- Throws: Azure error with the error from the get token call.
|
||||
*/
|
||||
public func validate() throws {
|
||||
if let error = error {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,8 +28,8 @@ import Foundation
|
|||
|
||||
public typealias TokenRefresherClosure = (@escaping TokenRefreshOnCompletion) -> Void
|
||||
/**
|
||||
The Communication Token Refresh Options. Used to initialize a `CommunicationUserCredential`
|
||||
- SeeAlso: ` CommunicationUserCredential.init(...)`
|
||||
The Communication Token Refresh Options. Used to initialize a `CommunicationTokenCredential`
|
||||
- SeeAlso: ` CommunicationTokenCredential.token(...)`
|
||||
*/
|
||||
@objcMembers public class CommunicationTokenRefreshOptions: NSObject {
|
||||
var initialToken: String?
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
// --------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the ""Software""), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import XCTest
|
||||
|
||||
#if canImport(AzureCommunication)
|
||||
@testable import AzureCommunication
|
||||
#endif
|
||||
#if canImport(AzureCore)
|
||||
@testable import AzureCore
|
||||
#endif
|
||||
|
||||
class CommunicationPolicyTokenCredentialTests: XCTestCase {
|
||||
let sampleToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjMyNTAzNjgwMDAwfQ.9i7FNNHHJT8cOzo-yrAUJyBSfJ-tPPk2emcHavOEpWc"
|
||||
let aampleTokenExpiry = 32503680000
|
||||
let expiredToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjEwMH0.1h_scYkNp-G98-O4cW6KvfJZwiz54uJMyeDACE4nypg"
|
||||
|
||||
func fetchTokenSync(completionHandler: TokenRefreshOnCompletion) {
|
||||
let newToken = sampleToken
|
||||
completionHandler(newToken, nil)
|
||||
}
|
||||
|
||||
func testCreateStaticToken() throws {
|
||||
let expectation = self.expectation(description: "Create static token")
|
||||
|
||||
let token = expiredToken
|
||||
let userCredential = try CommunicationTokenCredential(token: token)
|
||||
let communicationTokenPolicy = CommunicationPolicyTokenCredential(userCredential)
|
||||
communicationTokenPolicy.token(forScopes: [""]) { (accessToken, error) in
|
||||
XCTAssertNil(error)
|
||||
XCTAssertNotNil(accessToken)
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: 1000) { (error) in
|
||||
if let error = error {
|
||||
XCTFail("Create token timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testCreateRefreshableWithoutInitialToken() throws {
|
||||
let expectation = self.expectation(description: "Create refreshable without initial token")
|
||||
let options = CommunicationTokenRefreshOptions(
|
||||
refreshProactively: true,
|
||||
tokenRefresher: fetchTokenSync
|
||||
)
|
||||
let userCredential = try CommunicationTokenCredential(with: options)
|
||||
let communicationTokenPolicy = CommunicationPolicyTokenCredential(userCredential)
|
||||
|
||||
communicationTokenPolicy.token(forScopes: [""]) { (accessToken, error) in
|
||||
XCTAssertNil(error)
|
||||
XCTAssertNotNil(accessToken)
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: 1000) { (error) in
|
||||
if let error = error {
|
||||
XCTFail("Create token timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testCreateRefreshableWithInitialToken() throws {
|
||||
let expectation = self.expectation(description: "Create refreshable with initial token")
|
||||
let token = expiredToken
|
||||
let options = CommunicationTokenRefreshOptions(
|
||||
initialToken: token,
|
||||
refreshProactively: true,
|
||||
tokenRefresher: fetchTokenSync
|
||||
)
|
||||
let userCredential = try CommunicationTokenCredential(with: options)
|
||||
let communicationTokenPolicy = CommunicationPolicyTokenCredential(userCredential)
|
||||
|
||||
communicationTokenPolicy.token(forScopes: [""]) { (accessToken, error) in
|
||||
XCTAssertNil(error)
|
||||
XCTAssertNotNil(accessToken)
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: 1000) { (error) in
|
||||
if let error = error {
|
||||
XCTFail("Create token timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testDecodesToken() throws {
|
||||
let expectation = self.expectation(description: "Decode access token")
|
||||
let initialToken = sampleToken
|
||||
let userCredential = try CommunicationTokenCredential(token: initialToken)
|
||||
let communicationTokenPolicy = CommunicationPolicyTokenCredential(userCredential)
|
||||
|
||||
communicationTokenPolicy.token(forScopes: [""]) { (accessToken, error) in
|
||||
XCTAssertEqual(accessToken?.token, initialToken)
|
||||
XCTAssertEqual(accessToken?.expiresOn, accessToken?.expiresOn)
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: 1000) { (error) in
|
||||
if let error = error {
|
||||
XCTFail("Create token timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testStaticTokenReturnsExpiredToken() throws {
|
||||
let expectation = self.expectation(description: "Static token is expired")
|
||||
let initialToken = expiredToken
|
||||
let userCredential = try CommunicationTokenCredential(token: initialToken)
|
||||
let communicationTokenPolicy = CommunicationPolicyTokenCredential(userCredential)
|
||||
|
||||
communicationTokenPolicy.token(forScopes: [""]) { [weak self] (accessToken, error) in
|
||||
guard let self = self else { return }
|
||||
XCTAssertEqual(self.expiredToken, accessToken?.token)
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: 1000) { (error) in
|
||||
if let error = error {
|
||||
XCTFail("Create token timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -28,6 +28,26 @@
|
|||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "D1B7EAEC257F02FC004F384A"
|
||||
BuildableName = "AzureCommunicationChatTests.xctest"
|
||||
BlueprintName = "AzureCommunicationChatTests"
|
||||
ReferencedContainer = "container:AzureCommunicationChat.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "D147E62725CE242C001CFB5D"
|
||||
BuildableName = "AzureCommunicationChatUnitTests.xctest"
|
||||
BlueprintName = "AzureCommunicationChatUnitTests"
|
||||
ReferencedContainer = "container:AzureCommunicationChat.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
|
|
|
@ -24,7 +24,7 @@ let package = Package(
|
|||
dependencies: [
|
||||
.package(
|
||||
url: "https://github.com/Azure/azure-sdk-for-ios.git",
|
||||
.branch("dev/AzureCore")
|
||||
.branch("master")
|
||||
)
|
||||
],
|
||||
targets: [
|
||||
|
|
|
@ -93,54 +93,63 @@ target 'MyTarget' do
|
|||
end
|
||||
```
|
||||
|
||||
### Create the AzureCommunicationChatClient
|
||||
|
||||
Create an instance of `AzureCommunicationChatClient` by providing the base URL of the service, the authentication policy to use, and the set of options to use for the client.
|
||||
|
||||
```swift
|
||||
import AzureCommunication
|
||||
import AzureCommunicationChat
|
||||
import AzureCore
|
||||
|
||||
guard let baseUrl = URL(string: "https://<resource>.communication.azure.com") else {
|
||||
// Display error message
|
||||
}
|
||||
|
||||
let authPolicy = try CommunicationTokenCredentialPolicy(
|
||||
credential: credential ?? CommunicationTokenCredential(token: "<user_access_token>")
|
||||
)
|
||||
let options = AzureCommunicationChatClientOptions(
|
||||
logger: ClientLoggers.default,
|
||||
dispatchQueue: self.queue
|
||||
)
|
||||
let client = AzureCommunicationChatClient(baseUrl: baseUrl, authPolicy: authPolicy, withOptions: options)
|
||||
```
|
||||
|
||||
## Key concepts
|
||||
|
||||
### User and User Access Tokens
|
||||
|
||||
User access tokens enable you to build client applications that directly authenticate to Azure Communication Services. Refer [here](https://docs.microsoft.com/azure/communication-services/quickstarts/access-tokens) to learn how to create a user and issue a User Access Token.
|
||||
|
||||
The id for the user created above will be necessary later to add said user as a member of a new chat thread. The initiator of the create request must be in the list of members of the chat thread.
|
||||
The id for the user created above will be necessary later to add said user as a participant of a new chat thread. The initiator of the create request must be in the list of participants of the chat thread.
|
||||
|
||||
### Chat Thread
|
||||
|
||||
A chat conversation is represented by a chat thread. Each user in the thread is called a thread member. Thread members can chat with one another privately in a 1:1 chat or huddle up in a 1:N group chat.
|
||||
A chat conversation is represented by a chat thread. Each user in the thread is called a thread participant. Thread participants can chat with one another privately in a 1:1 chat or huddle up in a 1:N group chat.
|
||||
|
||||
Using the APIs, users can also send typing indicators when typing a message and read receipts for the messages they have read in a chat thread. To learn more, read about chat concepts [here](https://docs.microsoft.com/azure/communication-services/concepts/chat/concepts).
|
||||
|
||||
### Chat Operations
|
||||
### ChatClient
|
||||
|
||||
Once you initialize an `AzureCommunicationChatClient` class, you can perform the following chat operations:
|
||||
`ChatClient` is used for performing chat thread operations, listed below.
|
||||
|
||||
#### Initialization
|
||||
|
||||
To instantiate ChatClient you will need the CommunicationServices resource endpoint, a CommunicationUserCredential created from a User Access Token, and optional options to create the client with.
|
||||
|
||||
```swift
|
||||
import AzureCommunication
|
||||
import AzureCommunicationChat
|
||||
import AzureCore
|
||||
|
||||
let endpoint = "<communication_resource_endpoint>"
|
||||
|
||||
let credential = try CommunicationTokenCredential(<"user_access_token>")
|
||||
|
||||
let options = AzureCommunicationChatClientOptions(
|
||||
logger: ClientLoggers.default,
|
||||
dispatchQueue: self.queue
|
||||
)
|
||||
|
||||
let chatClient = ChatClient(endpoint: endpoint, credential: credential, withOptions: options)
|
||||
|
||||
```
|
||||
|
||||
#### Thread Operations
|
||||
|
||||
ChatClient supports the following methods, see the links below for examples.
|
||||
|
||||
- [Create a thread](#create-a-thread)
|
||||
- [Get a thread](#get-a-thread)
|
||||
- [List threads](#list-threads)
|
||||
- [Update a thread](#update-a-thread)
|
||||
- [Delete a thread](#delete-a-thread)
|
||||
- [Get a thread client](#get-a-thread-client)
|
||||
|
||||
### ChatThreadClient
|
||||
|
||||
`ChatThreadClient` provides methods for operations within a chat thread, such as messaging and managing participants.
|
||||
|
||||
#### Initialization
|
||||
|
||||
ChatThreadClients should be created through the ChatClient. A ChatThreadClient is associated with a specific chat thread and is used to perform operations within the thread. See the list below for examples of each operation that ChatThreadClient supports.
|
||||
|
||||
#### Message Operations
|
||||
|
||||
|
@ -150,11 +159,11 @@ Once you initialize an `AzureCommunicationChatClient` class, you can perform the
|
|||
- [Update a message](#update-a-message)
|
||||
- [Delete a message](#delete-a-message)
|
||||
|
||||
#### Thread Member Operations
|
||||
#### Thread Participant Operations
|
||||
|
||||
- [Get thread members](#get-thread-members)
|
||||
- [Add thread members](#add-thread-members)
|
||||
- [Remove a thread member](#remove-a-thread-member)
|
||||
- [Get thread participants](#get-thread-participants)
|
||||
- [Add thread participants](#add-thread-participants)
|
||||
- [Remove a thread participant](#remove-a-thread-participant)
|
||||
|
||||
#### Events Operations
|
||||
|
||||
|
@ -162,43 +171,36 @@ Once you initialize an `AzureCommunicationChatClient` class, you can perform the
|
|||
- [Send read receipt](#send-read-receipt)
|
||||
- [Get read receipts](#get-read-receipts)
|
||||
|
||||
#### Thread Update Operations
|
||||
- [Update the thread topic](#update-thread-topic)
|
||||
|
||||
## Examples
|
||||
|
||||
### Thread Operations
|
||||
|
||||
#### Create a thread
|
||||
|
||||
Use the `create` method to create a thread.
|
||||
Use the `create` method of `ChatClient` to create a new thread.
|
||||
|
||||
- `CreateChatThreadRequest` is the model to pass to this method.
|
||||
- `topic` is used to provide a topic for the thread.
|
||||
- `members` is used to list the `ChatThreadMember` to be added to the thread.
|
||||
- `id`, required, is the `CommunicationUser.identifier` you created before. Refer to [User and User Access Tokens](#user-and-user-access-tokens).
|
||||
- `displayName`, optional, is the display name for the thread member.
|
||||
- `shareHistoryTime`, optional, is the time from which the chat history is shared with the member.
|
||||
- `CreateThreadRequest` is the model to pass to this method. It contains the participants to add to the thread as well as the topic of the thread.
|
||||
|
||||
`MultiStatusResponse` is the result returned from creating a thread. It has a 'multipleStatus' property which represents a list of `IndividualStatusResponse`.
|
||||
- `CreateThreadResult` is the result returned from creating a thread.
|
||||
- `thread` is the chat Thread that was created
|
||||
- `errors` contains an array of errors for any invalid participants that failed to be added to the chat thread.
|
||||
|
||||
```swift
|
||||
let thread = CreateChatThreadRequest(
|
||||
let thread = CreateThreadRequest(
|
||||
topic: "General",
|
||||
members: [ChatThreadMember(
|
||||
participants: [Participant(
|
||||
id: <userId>,
|
||||
// Id of this needs to match with the Auth token
|
||||
displayName: "initial member"
|
||||
displayName: "initial participant"
|
||||
)]
|
||||
)
|
||||
|
||||
client.create(chatThread: thread) { result, _ in
|
||||
chatClient.create(thread: thread) { result, _ in
|
||||
switch result {
|
||||
case let .success(createThreadResponse):
|
||||
var threadId: String? = nil
|
||||
for response in createThreadResponse.multipleStatus ?? [] {
|
||||
if response.id?.hasSuffix("@thread.v2") ?? false,
|
||||
response.type ?? "" == "Thread" {
|
||||
threadId = response.id
|
||||
}
|
||||
}
|
||||
case let .success(chatThreadResult):
|
||||
// Take further action
|
||||
|
||||
case let .failure(error):
|
||||
|
@ -209,14 +211,14 @@ client.create(chatThread: thread) { result, _ in
|
|||
|
||||
#### Get a thread
|
||||
|
||||
Use the `getChatThread` method to retrieve a thread.
|
||||
Use the `get` method of `ChatClient` to retrieve a thread.
|
||||
|
||||
- `chatThreadId` is the unique ID of the thread.
|
||||
- `thread` is the unique ID of the thread.
|
||||
|
||||
```swift
|
||||
client.getChatThread(chatThreadId: threadId) { result, _ in
|
||||
chatClient.get(thread: threadId) { result, _ in
|
||||
switch result {
|
||||
case let .success(thread):
|
||||
case let .success(chatThread):
|
||||
// Take further action
|
||||
|
||||
case let .failure(error):
|
||||
|
@ -227,7 +229,7 @@ client.getChatThread(chatThreadId: threadId) { result, _ in
|
|||
|
||||
#### List threads
|
||||
|
||||
Use the `listChatThreads` method to retrieve a list of threads.
|
||||
Use the `listThreads` method to retrieve a list of threads.
|
||||
|
||||
- `ListChatThreadsOptions` is the object representing the options to pass.
|
||||
- `maxPageSize`, optional, is the maximum number of messages to be returned per page.
|
||||
|
@ -238,7 +240,7 @@ Use the `listChatThreads` method to retrieve a list of threads.
|
|||
```swift
|
||||
import AzureCore
|
||||
let options = ListChatThreadsOptions(maxPageSize: 1)
|
||||
client.listChatThreads(withOptions: options) { result, _ in
|
||||
chatClient.listThreads(withOptions: options) { result, _ in
|
||||
switch result {
|
||||
case let .success(listThreadsResponse):
|
||||
var iterator = listThreadsResponse.syncIterator
|
||||
|
@ -252,38 +254,15 @@ client.listChatThreads(withOptions: options) { result, _ in
|
|||
}
|
||||
```
|
||||
|
||||
#### Update a thread
|
||||
|
||||
Use the `update` method to update a thread's properties.
|
||||
|
||||
- `UpdateChatThreadRequest` is the model to pass to this method.
|
||||
- `topic` is used to give a thread a new topic.
|
||||
- `chatThreadId` is the unique ID of the thread.
|
||||
|
||||
```swift
|
||||
let thread = UpdateChatThreadRequest(
|
||||
topic: "A new topic update with update()"
|
||||
)
|
||||
|
||||
client.update(chatThread: thread, chatThreadId: threadId) { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
// Take further action
|
||||
|
||||
case let .failure(error):
|
||||
// Display error message
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Delete a thread
|
||||
|
||||
Use `deleteChatThread` method to delete a thread.
|
||||
Use the `delete` method of `ChatClient` to delete a thread.
|
||||
|
||||
- `chatThreadId` is the unique ID of the thread.
|
||||
- `thread` is the unique ID of the thread.
|
||||
|
||||
```swift
|
||||
client.deleteChatThread(chatThreadId: threadId) { result, httpResponse in
|
||||
chatClient.delete(thread: threadId) { result, httpResponse in
|
||||
switch result {
|
||||
case .success:
|
||||
// Take further action
|
||||
|
@ -298,24 +277,22 @@ client.deleteChatThread(chatThreadId: threadId) { result, httpResponse in
|
|||
|
||||
#### Send a message
|
||||
|
||||
Use the `send` method to send a message to a thread.
|
||||
Use the `send` method of `ChatThreadClient` to send a message to a thread.
|
||||
|
||||
- `SendChatMessageRequest` is the model to pass to this method.
|
||||
- `priority` is used to specify the message priority level, such as 'normal' or 'high', if not specified, 'normal' will be set.
|
||||
- `content`, required, is used to provide the chat message content.
|
||||
- `senderDisplayName` is used to specify the display name of the sender, if not specified, an empty name will be set.
|
||||
- `chatThreadId` is the unique ID of the thread.
|
||||
- `type` is the type of message being sent, the supported types are text and html.
|
||||
|
||||
`SendChatMessageResult` is the response returned from sending a message, it contains an id, which is the unique ID of the message.
|
||||
|
||||
```swift
|
||||
let message = SendChatMessageRequest(
|
||||
priority: ChatMessagePriority.high,
|
||||
content: "Test message 1",
|
||||
senderDisplayName: "An Important person"
|
||||
)
|
||||
|
||||
getClient().send(chatMessage: message, chatThreadId: threadId) { result, _ in
|
||||
chatThreadClient.send(message: message) { result, _ in
|
||||
switch result {
|
||||
case let .success(createMessageResponse):
|
||||
// Take further action
|
||||
|
@ -328,15 +305,14 @@ getClient().send(chatMessage: message, chatThreadId: threadId) { result, _ in
|
|||
|
||||
#### Get a message
|
||||
|
||||
Use the `getChatMessage` method to retrieve a message in a thread.
|
||||
Use the `get` method of `ChatThreadClient` to retrieve a message in a thread.
|
||||
|
||||
- `chatThreadId` is the unique ID of the thread.
|
||||
- `chatMessageId` is the unique ID of the message.
|
||||
- `message` is the unique ID of the message.
|
||||
|
||||
`ChatMessage` is the response returned from getting a message.
|
||||
`Message` is the response returned from getting a message.
|
||||
|
||||
```swift
|
||||
client.getChatMessage(chatThreadId: threadId, chatMessageId: messageId) { result, _ in
|
||||
chatThreadClient.get(message: messageId) { result, _ in
|
||||
switch result {
|
||||
case let .success(message):
|
||||
// Take further action
|
||||
|
@ -349,14 +325,13 @@ client.getChatMessage(chatThreadId: threadId, chatMessageId: messageId) { result
|
|||
|
||||
#### List messages
|
||||
|
||||
Use the `listChatMessages` method to retrieve messages in a thread.
|
||||
Use the `listMessages` method of `ChatThreadClient` to retrieve messages in a thread.
|
||||
|
||||
- `ListChatMessagesOptions` is the object representing the options to pass.
|
||||
- `ListChatMessagesOptions` is the optional object representing the options to pass.
|
||||
- `maxPageSize`, optional, is the maximum number of messages to be returned per page.
|
||||
- `startTime`, optional, is the thread start time to consider in the query.
|
||||
- `chatThreadId` is the unique ID of the thread.
|
||||
|
||||
`<PagedCollection<ChatMessage>` is the response returned from listing messages
|
||||
`<PagedCollection<Message>` is the response returned from listing messages
|
||||
|
||||
```swift
|
||||
let dateFormatter = DateFormatter()
|
||||
|
@ -369,7 +344,7 @@ if let date = dateFormatter.date(from: "2020-08-27T17:55:50Z") {
|
|||
)
|
||||
}
|
||||
|
||||
client.listChatMessages(chatThreadId: threadId, withOptions: options) { result, _ in
|
||||
client.listMessages(withOptions: options) { result, _ in
|
||||
switch result {
|
||||
case let .success(listMessagesResponse):
|
||||
var iterator = listMessagesResponse.syncIterator
|
||||
|
@ -385,20 +360,20 @@ client.listChatMessages(chatThreadId: threadId, withOptions: options) { result,
|
|||
|
||||
#### Update a message
|
||||
|
||||
Use the `update` method to update a message in a thread.
|
||||
Use the `update` method of `ChatThreadClient` to update a message in a thread.
|
||||
|
||||
- `UpdateChatMessageRequest` is the model to pass to this method.
|
||||
- `priority` is the chat message priority `ChatMessagePriority`, such as 'Normal' or 'High', if not specified, 'Normal' will be set.
|
||||
- `content` is the message content to be updated.
|
||||
- `chatThreadId` is the unique ID of the thread.
|
||||
- `chatMessageId` is the unique ID of the message.
|
||||
|
||||
-`messageId` is the unique id of the message.
|
||||
|
||||
```swift
|
||||
let message = UpdateChatMessageRequest(
|
||||
content: "A message content with update()"
|
||||
)
|
||||
|
||||
getClient().update(chatMessage: message, chatThreadId: threadId, chatMessageId: messageId) { result, _ in
|
||||
chatThreadClient.update(message: message, messageId: messageId) { result, _ in
|
||||
switch result {
|
||||
case .success(_):
|
||||
// Take further action
|
||||
|
@ -411,13 +386,12 @@ getClient().update(chatMessage: message, chatThreadId: threadId, chatMessageId:
|
|||
|
||||
#### Delete a message
|
||||
|
||||
Use the `deleteChatMessage` method to delete a message in a thread.
|
||||
Use the `delete` method of `ChatThreadClient` to delete a message in a thread.
|
||||
|
||||
- `chatThreadId` is the unique ID of the thread.
|
||||
- `chatMessageId` is the unique ID of the message.
|
||||
- `message` is the unique ID of the message.
|
||||
|
||||
```swift
|
||||
getClient().deleteChatMessage(chatThreadId: threadId, chatMessageId: messageId) { result, _ in
|
||||
chatThreadClient.delete(message: messageId) { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
// Take further action
|
||||
|
@ -428,22 +402,21 @@ getClient().deleteChatMessage(chatThreadId: threadId, chatMessageId: messageId)
|
|||
}
|
||||
```
|
||||
|
||||
### Thread Member Operations
|
||||
### Thread Participant Operations
|
||||
|
||||
#### Get thread members
|
||||
#### Get thread participants
|
||||
|
||||
Use the `listChatThreadMembers` method to retrieve the members participating in a thread.
|
||||
Use the `listParticipants` of `ChatThreadClient` method to retrieve the participants of the thread.
|
||||
|
||||
- `chatThreadId` is the unique ID of the thread.
|
||||
|
||||
`PagedCollection<ChatThreadMember>` is the response returned from listing members.
|
||||
`PagedCollection<Participant>` is the response returned from listing participants.
|
||||
|
||||
```swift
|
||||
client.listChatThreadMembers(chatThreadId: threadId) { result, _ in
|
||||
chatThreadClient.listParticipants() { result, _ in
|
||||
switch result {
|
||||
case let .success(threadmembers):
|
||||
var iterator = threadmembers.syncIterator
|
||||
while let threadMember = iterator.next() {
|
||||
case let .success(threadParticipants):
|
||||
var iterator = threadParticipants.syncIterator
|
||||
while let threadParticipants = iterator.next() {
|
||||
// Take further action
|
||||
}
|
||||
|
||||
|
@ -453,27 +426,23 @@ client.listChatThreadMembers(chatThreadId: threadId) { result, _ in
|
|||
}
|
||||
```
|
||||
|
||||
#### Add thread members
|
||||
#### Add thread participants
|
||||
|
||||
Use the `add` method to add members to a thread.
|
||||
Use the `add` method to add participants to a thread.
|
||||
|
||||
- `AddChatThreadMembersRequest` is used to list the `ChatThreadMember`s to be added to the thread.
|
||||
- `id`, required, is the `CommunicationUser.identifier` you created before. Refer to [User and User Access Tokens](#user-and-user-access-tokens).
|
||||
- `displayName`, optional, is the display name for the thread member.
|
||||
- `shareHistoryTime`, optional, is the time from which the chat history is shared with the member.
|
||||
- `chatThreadId` is the unique ID of the thread.
|
||||
- `participants` is an array of `Participant`'s to add
|
||||
- `AddChatParticipantsResult` is the model returned, it contains an errors property that has an array of any invalid participants that failed to be added to the chat.
|
||||
|
||||
```swift
|
||||
let threadMembers = AddChatThreadMembersRequest(
|
||||
members: [ChatThreadMember(
|
||||
let threadParticipants = [Participant(
|
||||
id: userId,
|
||||
displayName: "a new member"
|
||||
displayName: "a new participant"
|
||||
)]
|
||||
)
|
||||
client.add(chatThreadMembers: threadMembers, chatThreadId: threadId) { result, _ in
|
||||
|
||||
chatThreadClient.add(participants: threadParticipants) { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
// Take further action
|
||||
case let .success(result):
|
||||
// Check for invalid participants
|
||||
|
||||
case let .failure(error):
|
||||
// Display error message
|
||||
|
@ -481,15 +450,14 @@ client.add(chatThreadMembers: threadMembers, chatThreadId: threadId) { result, _
|
|||
}
|
||||
```
|
||||
|
||||
#### Remove a thread member
|
||||
#### Remove a thread participant
|
||||
|
||||
Use the `removeChatThreadMember` method to remove a member from a thread.
|
||||
Use the `remove` method of `ChatThreadClient` to remove a participant from a thread.
|
||||
|
||||
- `chatThreadId` is the unique ID of the thread.
|
||||
- `chatMemberId` is the user ID in the chat thread's member list.
|
||||
- `participant` is id of the participant to remove.
|
||||
|
||||
```swift
|
||||
client.removeChatThreadMember(chatThreadId: threadId, chatMemberId: memberId) { result, _ in
|
||||
chatThreadClient.remove(participant: participantId) { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
// Take further action
|
||||
|
@ -504,10 +472,10 @@ client.removeChatThreadMember(chatThreadId: threadId, chatMemberId: memberId) {
|
|||
|
||||
#### Send a typing notification
|
||||
|
||||
Use the `sendTypingNotification` method to post a typing notification event to a thread, on behalf of a user.
|
||||
Use the `sendTypingNotification` method of `ChatThreadClient` to post a typing notification event to a thread, on behalf of a user.
|
||||
|
||||
```swift
|
||||
client.sendTypingNotification(chatThreadId: threadId) { result, _ in
|
||||
chatThreadClient.sendTypingNotification() { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
// Take further action
|
||||
|
@ -520,16 +488,13 @@ client.sendTypingNotification(chatThreadId: threadId) { result, _ in
|
|||
|
||||
#### Send read receipt
|
||||
|
||||
Use the `send` method to post a read receipt event to a thread, on behalf of a user.
|
||||
Use the `sendReadReceipt` method of `ChatThreadClient` to post a read receipt event to a thread, on behalf of a user.
|
||||
|
||||
- `SendReadReceiptRequest` is the model to be passed to this method.
|
||||
- `chatMessageId` is the unique ID of the message.
|
||||
- `chatThreadId` is the unique ID of the thread.
|
||||
-`forMessage` refers to the unique ID of the message that the read receipt is for.
|
||||
|
||||
```swift
|
||||
let readReceipt = SendReadReceiptRequest(chatMessageId: messageId)
|
||||
|
||||
client.send(chatReadReceipt: readReceipt, chatThreadId: threadId) { result, _ in
|
||||
chatThreadClient.sendReadReceipt(forMessage: messageId) { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
// Take further action
|
||||
|
@ -542,14 +507,12 @@ client.send(chatReadReceipt: readReceipt, chatThreadId: threadId) { result, _ in
|
|||
|
||||
#### Get read receipts
|
||||
|
||||
Use the `listChatReadReceipts` method to retrieve read receipts for a thread.
|
||||
|
||||
- `chatThreadId` is the unique ID of the thread.
|
||||
Use the `listReadReceipts` method of `ChatThreadClient` to retrieve read receipts for a thread.
|
||||
|
||||
`PagedCollection<ReadReceipt>` is the response returned from listing read receipts.
|
||||
|
||||
```swift
|
||||
client.listChatReadReceipts(chatThreadId: threadId) { result, _ in
|
||||
chatThreadClient.listReadReceipts() { result, _ in
|
||||
switch result {
|
||||
case let .success(readReceipts):
|
||||
var iterator = readReceipts.syncIterator
|
||||
|
@ -563,12 +526,34 @@ client.listChatReadReceipts(chatThreadId: threadId) { result, _ in
|
|||
}
|
||||
```
|
||||
|
||||
### Thread Update Operations
|
||||
|
||||
#### Update the thread's topic
|
||||
|
||||
Use the `update` method of `ChatThreadClient` to update a thread's topic.
|
||||
|
||||
- `topic` is the thread's new topic.
|
||||
|
||||
```swift
|
||||
let newTopic = "My new thread topic"
|
||||
|
||||
chatThreadClient.update(topic: newTopic) { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
// Take further action
|
||||
|
||||
case let .failure(error):
|
||||
// Display error message
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
When an error occurs, the client calls the callback, passing in a `failure` result. You can use the provided error to act upon the failure.
|
||||
|
||||
```swift
|
||||
client.create(chatThread: thread) { result, _ in
|
||||
client.create(thread: thread) { result, _ in
|
||||
switch result {
|
||||
case let .failure(error):
|
||||
// Display error message
|
||||
|
@ -594,4 +579,4 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
|
|||
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact
|
||||
[opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
|
||||
![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-ios%2Fsdk%communication%2FAzureCommunicationChat%2FREADME.png)
|
||||
![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-ios%2Fsdk%communication%2FAzureCommunicationChat%2FREADME.png)
|
|
@ -1,340 +0,0 @@
|
|||
// --------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the ""Software""), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCore
|
||||
import Foundation
|
||||
|
||||
public extension AzureCommunicationChatClient {
|
||||
/// Gets read receipts for a thread.
|
||||
/// - Parameters:
|
||||
/// - chatThreadId : Thread id to get the read receipts for.
|
||||
/// - options: A list of options for the operation
|
||||
/// - completionHandler: A completion handler that receives a status code on
|
||||
/// success.
|
||||
func listChatReadReceipts(
|
||||
chatThreadId: String,
|
||||
withOptions options: AzureCommunicationChatService.ListChatReadReceiptsOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<PagedCollection<ReadReceipt>>
|
||||
) {
|
||||
return azureCommunicationChatService.listChatReadReceipts(
|
||||
chatThreadId: chatThreadId,
|
||||
withOptions: options,
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
}
|
||||
|
||||
/// Sends a read receipt event to a thread, on behalf of a user.
|
||||
/// - Parameters:
|
||||
/// - chatReadReceipt : Read receipt details.
|
||||
/// - chatThreadId : Thread id to send the read receipt event to.
|
||||
/// - options: A list of options for the operation
|
||||
/// - completionHandler: A completion handler that receives a status code on
|
||||
/// success.
|
||||
func send(
|
||||
chatReadReceipt: SendReadReceiptRequest,
|
||||
chatThreadId: String,
|
||||
withOptions options: AzureCommunicationChatService.SendChatReadReceiptOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<Void>
|
||||
) {
|
||||
return azureCommunicationChatService.send(
|
||||
chatReadReceipt: chatReadReceipt,
|
||||
chatThreadId: chatThreadId,
|
||||
withOptions: options,
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
}
|
||||
|
||||
/// Sends a message to a thread.
|
||||
/// - Parameters:
|
||||
/// - chatMessage : Details of the message to send.
|
||||
/// - chatThreadId : The thread id to send the message to.
|
||||
/// - options: A list of options for the operation
|
||||
/// - completionHandler: A completion handler that receives a status code on
|
||||
/// success.
|
||||
func send(
|
||||
chatMessage: SendChatMessageRequest,
|
||||
chatThreadId: String,
|
||||
withOptions options: AzureCommunicationChatService.SendChatMessageOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<SendChatMessageResult>
|
||||
) {
|
||||
return azureCommunicationChatService.send(
|
||||
chatMessage: chatMessage,
|
||||
chatThreadId: chatThreadId,
|
||||
withOptions: options,
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
}
|
||||
|
||||
/// Gets a list of messages from a thread.
|
||||
/// - Parameters:
|
||||
/// - chatThreadId : The thread id of the message.
|
||||
/// - options: A list of options for the operation
|
||||
/// - completionHandler: A completion handler that receives a status code on
|
||||
/// success.
|
||||
func listChatMessages(
|
||||
chatThreadId: String,
|
||||
withOptions options: AzureCommunicationChatService.ListChatMessagesOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<PagedCollection<ChatMessage>>
|
||||
) {
|
||||
return azureCommunicationChatService.listChatMessages(
|
||||
chatThreadId: chatThreadId,
|
||||
withOptions: options,
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
}
|
||||
|
||||
/// Gets a message by id.
|
||||
/// - Parameters:
|
||||
/// - chatThreadId : The thread id to which the message was sent.
|
||||
/// - chatMessageId : The message id.
|
||||
/// - options: A list of options for the operation
|
||||
/// - completionHandler: A completion handler that receives a status code on
|
||||
/// success.
|
||||
func getChatMessage(
|
||||
chatThreadId: String,
|
||||
chatMessageId: String,
|
||||
withOptions options: AzureCommunicationChatService.GetChatMessageOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<ChatMessage>
|
||||
) {
|
||||
return azureCommunicationChatService.getChatMessage(
|
||||
chatThreadId: chatThreadId,
|
||||
chatMessageId: chatMessageId,
|
||||
withOptions: options,
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
}
|
||||
|
||||
/// Updates a message.
|
||||
/// - Parameters:
|
||||
/// - chatMessage : Details of the request to update the message.
|
||||
/// - chatThreadId : The thread id to which the message was sent.
|
||||
/// - chatMessageId : The message id.
|
||||
/// - options: A list of options for the operation
|
||||
/// - completionHandler: A completion handler that receives a status code on
|
||||
/// success.
|
||||
func update(
|
||||
chatMessage: UpdateChatMessageRequest,
|
||||
chatThreadId: String,
|
||||
chatMessageId: String,
|
||||
withOptions options: AzureCommunicationChatService.UpdateChatMessageOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<Void>
|
||||
) {
|
||||
return azureCommunicationChatService.update(
|
||||
chatMessage: chatMessage,
|
||||
chatThreadId: chatThreadId,
|
||||
chatMessageId: chatMessageId,
|
||||
withOptions: options,
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
}
|
||||
|
||||
/// Deletes a message.
|
||||
/// - Parameters:
|
||||
/// - chatThreadId : The thread id to which the message was sent.
|
||||
/// - chatMessageId : The message id.
|
||||
/// - options: A list of options for the operation
|
||||
/// - completionHandler: A completion handler that receives a status code on
|
||||
/// success.
|
||||
func deleteChatMessage(
|
||||
chatThreadId: String,
|
||||
chatMessageId: String,
|
||||
withOptions options: AzureCommunicationChatService.DeleteChatMessageOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<Void>
|
||||
) {
|
||||
return azureCommunicationChatService.deleteChatMessage(
|
||||
chatThreadId: chatThreadId,
|
||||
chatMessageId: chatMessageId,
|
||||
withOptions: options,
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
}
|
||||
|
||||
/// Posts a typing event to a thread, on behalf of a user.
|
||||
/// - Parameters:
|
||||
/// - chatThreadId : Id of the thread.
|
||||
/// - options: A list of options for the operation
|
||||
/// - completionHandler: A completion handler that receives a status code on
|
||||
/// success.
|
||||
func sendTypingNotification(
|
||||
chatThreadId: String,
|
||||
withOptions options: AzureCommunicationChatService.SendTypingNotificationOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<Void>
|
||||
) {
|
||||
return azureCommunicationChatService.sendTypingNotification(
|
||||
chatThreadId: chatThreadId,
|
||||
withOptions: options,
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
}
|
||||
|
||||
/// Gets the members of a thread.
|
||||
/// - Parameters:
|
||||
/// - chatThreadId : Thread id to get members for.
|
||||
/// - options: A list of options for the operation
|
||||
/// - completionHandler: A completion handler that receives a status code on
|
||||
/// success.
|
||||
func listChatThreadMembers(
|
||||
chatThreadId: String,
|
||||
withOptions options: AzureCommunicationChatService.ListChatThreadMembersOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<PagedCollection<ChatThreadMember>>
|
||||
) {
|
||||
return azureCommunicationChatService.listChatThreadMembers(
|
||||
chatThreadId: chatThreadId,
|
||||
withOptions: options,
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
}
|
||||
|
||||
/// Adds thread members to a thread. If members already exist, no change occurs.
|
||||
/// - Parameters:
|
||||
/// - chatThreadMembers : Thread members to be added to the thread.
|
||||
/// - chatThreadId : Id of the thread to add members to.
|
||||
/// - options: A list of options for the operation
|
||||
/// - completionHandler: A completion handler that receives a status code on
|
||||
/// success.
|
||||
func add(
|
||||
chatThreadMembers: AddChatThreadMembersRequest,
|
||||
chatThreadId: String,
|
||||
withOptions options: AzureCommunicationChatService.AddChatThreadMembersOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<Void>
|
||||
) {
|
||||
return azureCommunicationChatService.add(
|
||||
chatThreadMembers: chatThreadMembers,
|
||||
chatThreadId: chatThreadId,
|
||||
withOptions: options,
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
}
|
||||
|
||||
/// Remove a member from a thread.
|
||||
/// - Parameters:
|
||||
/// - chatThreadId : Thread id to remove the member from.
|
||||
/// - chatMemberId : Id of the thread member to remove from the thread.
|
||||
/// - options: A list of options for the operation
|
||||
/// - completionHandler: A completion handler that receives a status code on
|
||||
/// success.
|
||||
func removeChatThreadMember(
|
||||
chatThreadId: String,
|
||||
chatMemberId: String,
|
||||
withOptions options: AzureCommunicationChatService.RemoveChatThreadMemberOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<Void>
|
||||
) {
|
||||
return azureCommunicationChatService.removeChatThreadMember(
|
||||
chatThreadId: chatThreadId,
|
||||
chatMemberId: chatMemberId,
|
||||
withOptions: options,
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates a chat thread.
|
||||
/// - Parameters:
|
||||
/// - chatThread : Request payload for creating a chat thread.
|
||||
/// - options: A list of options for the operation
|
||||
/// - completionHandler: A completion handler that receives a status code on
|
||||
/// success.
|
||||
func create(
|
||||
chatThread: CreateChatThreadRequest,
|
||||
withOptions options: AzureCommunicationChatService.CreateChatThreadOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<MultiStatusResponse>
|
||||
) {
|
||||
return azureCommunicationChatService.create(
|
||||
chatThread: chatThread,
|
||||
withOptions: options,
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
}
|
||||
|
||||
/// Gets the list of chat threads of a user.
|
||||
/// - Parameters:
|
||||
|
||||
/// - options: A list of options for the operation
|
||||
/// - completionHandler: A completion handler that receives a status code on
|
||||
/// success.
|
||||
func listChatThreads(
|
||||
withOptions options: AzureCommunicationChatService.ListChatThreadsOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<PagedCollection<ChatThreadInfo>>
|
||||
) {
|
||||
return azureCommunicationChatService.listChatThreads(withOptions: options, completionHandler: completionHandler)
|
||||
}
|
||||
|
||||
/// Updates a thread's properties.
|
||||
/// - Parameters:
|
||||
/// - chatThread : Request payload for updating a chat thread.
|
||||
/// - chatThreadId : The id of the thread to update.
|
||||
/// - options: A list of options for the operation
|
||||
/// - completionHandler: A completion handler that receives a status code on
|
||||
/// success.
|
||||
func update(
|
||||
chatThread: UpdateChatThreadRequest,
|
||||
chatThreadId: String,
|
||||
withOptions options: AzureCommunicationChatService.UpdateChatThreadOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<Void>
|
||||
) {
|
||||
return azureCommunicationChatService.update(
|
||||
chatThread: chatThread,
|
||||
chatThreadId: chatThreadId,
|
||||
withOptions: options,
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
}
|
||||
|
||||
/// Gets a chat thread.
|
||||
/// - Parameters:
|
||||
/// - chatThreadId : Thread id to get.
|
||||
/// - options: A list of options for the operation
|
||||
/// - completionHandler: A completion handler that receives a status code on
|
||||
/// success.
|
||||
func getChatThread(
|
||||
chatThreadId: String,
|
||||
withOptions options: AzureCommunicationChatService.GetChatThreadOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<ChatThread>
|
||||
) {
|
||||
return azureCommunicationChatService.getChatThread(
|
||||
chatThreadId: chatThreadId,
|
||||
withOptions: options,
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
}
|
||||
|
||||
/// Deletes a thread.
|
||||
/// - Parameters:
|
||||
/// - chatThreadId : Thread id to delete.
|
||||
/// - options: A list of options for the operation
|
||||
/// - completionHandler: A completion handler that receives a status code on
|
||||
/// success.
|
||||
func deleteChatThread(
|
||||
chatThreadId: String,
|
||||
withOptions options: AzureCommunicationChatService.DeleteChatThreadOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<Void>
|
||||
) {
|
||||
return azureCommunicationChatService.deleteChatThread(
|
||||
chatThreadId: chatThreadId,
|
||||
withOptions: options,
|
||||
completionHandler: completionHandler
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,190 @@
|
|||
// --------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the ""Software""), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCommunication
|
||||
import AzureCore
|
||||
import Foundation
|
||||
|
||||
public class ChatClient {
|
||||
// MARK: Properties
|
||||
|
||||
private let endpoint: String
|
||||
private let credential: CommunicationTokenCredential
|
||||
private let options: AzureCommunicationChatClientOptions
|
||||
private let service: Chat
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Create a ChatClient.
|
||||
/// - Parameters:
|
||||
/// - endpoint: The Communication Services endpoint.
|
||||
/// - credential: The user credential.
|
||||
/// - options: Options used to configure the client.
|
||||
public init(
|
||||
endpoint: String,
|
||||
credential: CommunicationTokenCredential,
|
||||
withOptions options: AzureCommunicationChatClientOptions
|
||||
) throws {
|
||||
self.endpoint = endpoint
|
||||
self.credential = credential
|
||||
self.options = options
|
||||
|
||||
guard let endpointUrl = URL(string: endpoint) else {
|
||||
throw AzureError.client("Unable to form base URL.")
|
||||
}
|
||||
|
||||
let communicationCredential = CommunicationPolicyTokenCredential(credential)
|
||||
let authPolicy = BearerTokenCredentialPolicy(credential: communicationCredential, scopes: [])
|
||||
|
||||
let client = try AzureCommunicationChatClient(
|
||||
endpoint: endpointUrl,
|
||||
authPolicy: authPolicy,
|
||||
withOptions: options
|
||||
)
|
||||
|
||||
self.service = client.chat
|
||||
}
|
||||
|
||||
// MARK: Public Methods
|
||||
|
||||
/// Create a ChatThreadClient for the ChatThread with id threadId.
|
||||
/// - Parameters:
|
||||
/// - threadId: The threadId.
|
||||
public func createClient(forThread threadId: String) throws -> ChatThreadClient {
|
||||
return try ChatThreadClient(
|
||||
endpoint: endpoint,
|
||||
credential: credential,
|
||||
threadId: threadId,
|
||||
withOptions: options
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new ChatThread.
|
||||
/// - Parameters:
|
||||
/// - thread: Request for creating a chat thread with the topic and members to add.
|
||||
/// - options: Create chat thread options.
|
||||
/// - completionHandler: A completion handler that receives a ChatThreadClient on success.
|
||||
public func create(
|
||||
thread: CreateThreadRequest,
|
||||
withOptions options: Chat.CreateChatThreadOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<CreateThreadResult>
|
||||
) {
|
||||
// Set the repeatabilityRequestID if it is not provided
|
||||
let requestOptions = ((options?.repeatabilityRequestID) != nil) ? options : Chat.CreateChatThreadOptions(
|
||||
repeatabilityRequestID: UUID().uuidString,
|
||||
clientRequestId: options?.clientRequestId,
|
||||
cancellationToken: options?.cancellationToken,
|
||||
dispatchQueue: options?.dispatchQueue,
|
||||
context: options?.context
|
||||
)
|
||||
|
||||
// Convert Participants to ChatParticipants
|
||||
let participants = thread.participants.map {
|
||||
ChatParticipant(
|
||||
id: $0.user.identifier,
|
||||
displayName: $0.displayName,
|
||||
shareHistoryTime: $0.shareHistoryTime
|
||||
)
|
||||
}
|
||||
|
||||
// Convert to CreateChatThreadRequest for generated code
|
||||
let request = CreateChatThreadRequest(
|
||||
topic: thread.topic,
|
||||
participants: participants
|
||||
)
|
||||
|
||||
service.create(chatThread: request, withOptions: requestOptions) { result, httpResponse in
|
||||
switch result {
|
||||
case let .success(chatThreadResult):
|
||||
completionHandler(.success(CreateThreadResult(from: chatThreadResult)), httpResponse)
|
||||
|
||||
case let .failure(error):
|
||||
completionHandler(.failure(error), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the Thread with given id.
|
||||
/// - Parameters:
|
||||
/// - threadId: The chat thread id.
|
||||
/// - options: Get chat thread options.
|
||||
/// - completionHandler: A completion handler that receives the chat thread on success.
|
||||
public func get(
|
||||
thread threadId: String,
|
||||
withOptions options: Chat.GetChatThreadOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<Thread>
|
||||
) {
|
||||
service.getChatThread(chatThreadId: threadId, withOptions: options) { result, httpResponse in
|
||||
switch result {
|
||||
case let .success(chatThread):
|
||||
completionHandler(.success(Thread(from: chatThread)), httpResponse)
|
||||
|
||||
case let .failure(error):
|
||||
completionHandler(.failure(error), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the list of ChatThreads for the user.
|
||||
/// - Parameters:
|
||||
/// - options: List chat threads options.
|
||||
/// - completionHandler: A completion handler that receives the list of chat thread info on success.
|
||||
public func listThreads(
|
||||
withOptions options: Chat.ListChatThreadsOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<PagedCollection<ChatThreadInfo>>
|
||||
) {
|
||||
service.listChatThreads(withOptions: options) { result, httpResponse in
|
||||
switch result {
|
||||
case let .success(chatThreads):
|
||||
completionHandler(.success(chatThreads), httpResponse)
|
||||
|
||||
case let .failure(error):
|
||||
completionHandler(.failure(error), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Delete the ChatThread with id chatThreadId.
|
||||
/// - Parameters:
|
||||
/// - threadId: The chat thread id.
|
||||
/// - options: Delete chat thread options.
|
||||
/// - completionHandler: A completion handler.
|
||||
public func delete(
|
||||
thread threadId: String,
|
||||
withOptions options: Chat.DeleteChatThreadOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<Void>
|
||||
) {
|
||||
service.deleteChatThread(chatThreadId: threadId, withOptions: options) { result, httpResponse in
|
||||
switch result {
|
||||
case .success:
|
||||
completionHandler(.success(()), httpResponse)
|
||||
|
||||
case let .failure(error):
|
||||
completionHandler(.failure(error), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,455 @@
|
|||
// --------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the ""Software""), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCommunication
|
||||
import AzureCore
|
||||
import Foundation
|
||||
|
||||
public class ChatThreadClient {
|
||||
// MARK: Properties
|
||||
|
||||
public let threadId: String
|
||||
private let endpoint: String
|
||||
private let credential: CommunicationTokenCredential
|
||||
private let options: AzureCommunicationChatClientOptions
|
||||
private let service: ChatThreadOperation
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Create a ChatThreadClient.
|
||||
/// - Parameters:
|
||||
/// - endpoint: The Communication Services endpoint.
|
||||
/// - credential: The user credential.
|
||||
/// - threadId: The chat thread id.
|
||||
/// - options: Options used to configure the client.
|
||||
public init(
|
||||
endpoint: String,
|
||||
credential: CommunicationTokenCredential,
|
||||
threadId: String,
|
||||
withOptions options: AzureCommunicationChatClientOptions
|
||||
) throws {
|
||||
self.threadId = threadId
|
||||
self.endpoint = endpoint
|
||||
self.credential = credential
|
||||
self.options = options
|
||||
|
||||
guard let endpointUrl = URL(string: endpoint) else {
|
||||
throw AzureError.client("Unable to form base URL")
|
||||
}
|
||||
|
||||
let communicationCredential = CommunicationPolicyTokenCredential(credential)
|
||||
let authPolicy = BearerTokenCredentialPolicy(credential: communicationCredential, scopes: [])
|
||||
|
||||
let client = try AzureCommunicationChatClient(
|
||||
endpoint: endpointUrl,
|
||||
authPolicy: authPolicy,
|
||||
withOptions: options
|
||||
)
|
||||
|
||||
self.service = client.chatThreadOperation
|
||||
}
|
||||
|
||||
// MARK: Private Methods
|
||||
|
||||
/// Creates a PagedCollection from the given data and request.
|
||||
/// - Parameters:
|
||||
/// - data: The data to initialize the PagedCollection with.
|
||||
/// - request: The HTTPRequest used to make the call.
|
||||
/// - type: The type of the elements in the PagedCollection.
|
||||
private func createPagedCollection<T: Codable>(
|
||||
from data: Data?,
|
||||
withRequest request: HTTPRequest?,
|
||||
of _: T.Type
|
||||
) throws -> PagedCollection<T> {
|
||||
guard let request = request else {
|
||||
throw AzureError.client("HTTPResponse does not contain httpRequest.")
|
||||
}
|
||||
|
||||
guard let data = data else {
|
||||
throw AzureError.client("HTTPResponse does not contain data.")
|
||||
}
|
||||
|
||||
let decoder = JSONDecoder()
|
||||
|
||||
let codingKeys = PagedCodingKeys(
|
||||
items: "value",
|
||||
continuationToken: "nextLink"
|
||||
)
|
||||
|
||||
let context = PipelineContext.of(keyValues: [
|
||||
ContextKey.allowedStatusCodes.rawValue: [200, 401, 403, 429, 503] as AnyObject
|
||||
])
|
||||
|
||||
return try PagedCollection<T>(
|
||||
client: service.client,
|
||||
request: request,
|
||||
context: context,
|
||||
data: data,
|
||||
codingKeys: codingKeys,
|
||||
decoder: decoder
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: Public Methods
|
||||
|
||||
/// Updates the ChatThread's topic.
|
||||
/// - Parameters:
|
||||
/// - topic: The topic.
|
||||
/// - options: Update chat thread options.
|
||||
/// - completionHandler: A completion handler that receives a status code on success.
|
||||
public func update(
|
||||
topic: String,
|
||||
withOptions options: ChatThreadOperation.UpdateChatThreadOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<Void>
|
||||
) {
|
||||
let updateChatThreadRequest = UpdateChatThreadRequest(topic: topic)
|
||||
|
||||
service
|
||||
.update(
|
||||
chatThread: updateChatThreadRequest,
|
||||
chatThreadId: threadId,
|
||||
withOptions: options
|
||||
) { result, httpResponse in
|
||||
switch result {
|
||||
case .success:
|
||||
completionHandler(.success(()), httpResponse)
|
||||
|
||||
case let .failure(error):
|
||||
completionHandler(.failure(error), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Sends a read receipt.
|
||||
/// - Parameters:
|
||||
/// - messageId: The id of the message to send a read receipt for.
|
||||
/// - options: Send read receipt options.
|
||||
/// - completionHandler: A completion handler that receives a status code on success.
|
||||
public func sendReadReceipt(
|
||||
forMessage messageId: String,
|
||||
withOptions options: ChatThreadOperation.SendChatReadReceiptOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<Void>
|
||||
) {
|
||||
let sendReadReceiptRequest = SendReadReceiptRequest(chatMessageId: messageId)
|
||||
|
||||
service
|
||||
.send(
|
||||
chatReadReceipt: sendReadReceiptRequest,
|
||||
chatThreadId: threadId,
|
||||
withOptions: options
|
||||
) { result, httpResponse in
|
||||
switch result {
|
||||
case .success:
|
||||
completionHandler(.success(()), httpResponse)
|
||||
|
||||
case let .failure(error):
|
||||
completionHandler(.failure(error), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Lists read receipts for the ChatThread.
|
||||
/// - Parameters:
|
||||
/// - options: List chat read receipts options.
|
||||
/// - completionHandler: A completion handler that receives the list of read receipts on success.
|
||||
public func listReadReceipts(
|
||||
withOptions options: ChatThreadOperation.ListChatReadReceiptsOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<PagedCollection<ReadReceipt>>
|
||||
) {
|
||||
service.listChatReadReceipts(chatThreadId: threadId, withOptions: options) { result, httpResponse in
|
||||
switch result {
|
||||
case .success:
|
||||
// TODO: https://github.com/Azure/azure-sdk-for-ios/issues/644
|
||||
// Construct a new PagedCollection of type ReadReceipt
|
||||
do {
|
||||
let readReceipts = try self.createPagedCollection(
|
||||
from: httpResponse?.data,
|
||||
withRequest: httpResponse?.httpRequest,
|
||||
of: ReadReceipt.self
|
||||
)
|
||||
|
||||
completionHandler(.success(readReceipts), httpResponse)
|
||||
} catch {
|
||||
let azureError = AzureError.client(error.localizedDescription, error)
|
||||
completionHandler(.failure(azureError), httpResponse)
|
||||
}
|
||||
|
||||
case let .failure(error):
|
||||
completionHandler(.failure(error), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Sends a typing notification.
|
||||
/// - Parameters:
|
||||
/// - options: Send typing notification options
|
||||
/// - completionHandler: A completion handler that receives a status code on success.
|
||||
public func sendTypingNotification(
|
||||
withOptions options: ChatThreadOperation.SendTypingNotificationOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<Void>
|
||||
) {
|
||||
service.sendTypingNotification(chatThreadId: threadId, withOptions: options) { result, httpResponse in
|
||||
switch result {
|
||||
case .success:
|
||||
completionHandler(.success(()), httpResponse)
|
||||
|
||||
case let .failure(error):
|
||||
completionHandler(.failure(error), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Sends a message to a ChatThread.
|
||||
/// - Parameters:
|
||||
/// - message : Request that contains the message properties.
|
||||
/// - options: A list of options for the operation.
|
||||
/// - completionHandler: A completion handler that receives a status code on success.
|
||||
public func send(
|
||||
message: SendChatMessageRequest,
|
||||
withOptions options: ChatThreadOperation.SendChatMessageOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<SendChatMessageResult>
|
||||
) {
|
||||
service.send(chatMessage: message, chatThreadId: threadId, withOptions: options) { result, httpResponse in
|
||||
switch result {
|
||||
case let .success(sendMessageResult):
|
||||
completionHandler(.success(sendMessageResult), httpResponse)
|
||||
|
||||
case let .failure(error):
|
||||
completionHandler(.failure(error), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a message by id.
|
||||
/// - Parameters:
|
||||
/// - messageId : The id of the message to get.
|
||||
/// - options: Get chat message options
|
||||
/// - completionHandler: A completion handler that receives the chat message on success.
|
||||
public func get(
|
||||
message messageId: String,
|
||||
withOptions options: ChatThreadOperation.GetChatMessageOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<Message>
|
||||
) {
|
||||
service
|
||||
.getChatMessage(
|
||||
chatThreadId: threadId,
|
||||
chatMessageId: messageId,
|
||||
withOptions: options
|
||||
) { result, httpResponse in
|
||||
switch result {
|
||||
case let .success(chatMessage):
|
||||
completionHandler(.success(Message(from: chatMessage)), httpResponse)
|
||||
|
||||
case let .failure(error):
|
||||
completionHandler(.failure(error), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates a message.
|
||||
/// - Parameters:
|
||||
/// - message: Request that contains the message properties to update.
|
||||
/// - messageId: The message id.
|
||||
/// - options: Update chat message options
|
||||
/// - completionHandler: A completion handler that receives a status code on success.
|
||||
public func update(
|
||||
message: UpdateChatMessageRequest,
|
||||
messageId: String,
|
||||
withOptions options: ChatThreadOperation.UpdateChatMessageOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<Void>
|
||||
) {
|
||||
service
|
||||
.update(
|
||||
chatMessage: message,
|
||||
chatThreadId: threadId,
|
||||
chatMessageId: messageId,
|
||||
withOptions: options
|
||||
) { result, httpResponse in
|
||||
switch result {
|
||||
case .success:
|
||||
completionHandler(.success(()), httpResponse)
|
||||
|
||||
case let .failure(error):
|
||||
completionHandler(.failure(error), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Deletes a message.
|
||||
/// - Parameters:
|
||||
/// - messageId : The message id.
|
||||
/// - options: Delete chat message options
|
||||
/// - completionHandler: A completion handler that receives a status code on success.
|
||||
public func delete(
|
||||
message messageId: String,
|
||||
options: ChatThreadOperation.DeleteChatMessageOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<Void>
|
||||
) {
|
||||
service
|
||||
.deleteChatMessage(
|
||||
chatThreadId: threadId,
|
||||
chatMessageId: messageId,
|
||||
withOptions: options
|
||||
) { result, httpResponse in
|
||||
switch result {
|
||||
case .success:
|
||||
completionHandler(.success(()), httpResponse)
|
||||
|
||||
case let .failure(error):
|
||||
completionHandler(.failure(error), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a list of messages from a ChatThread.
|
||||
/// - Parameters:
|
||||
/// - options: List messages options.
|
||||
/// - completionHandler: A completion handler that receives the list of messages on success.
|
||||
public func listMessages(
|
||||
withOptions options: ChatThreadOperation.ListChatMessagesOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<PagedCollection<Message>>
|
||||
) {
|
||||
service.listChatMessages(chatThreadId: threadId, withOptions: options) { result, httpResponse in
|
||||
switch result {
|
||||
case .success:
|
||||
// TODO: github.com/Azure/azure-sdk-for-ios/issues/644
|
||||
// Construct a new PagedCollection of type Message
|
||||
do {
|
||||
let messages = try self.createPagedCollection(
|
||||
from: httpResponse?.data,
|
||||
withRequest: httpResponse?.httpRequest,
|
||||
of: Message.self
|
||||
)
|
||||
|
||||
completionHandler(.success(messages), httpResponse)
|
||||
} catch {
|
||||
let azureError = AzureError.client(error.localizedDescription, error)
|
||||
completionHandler(.failure(azureError), httpResponse)
|
||||
}
|
||||
|
||||
case let .failure(error):
|
||||
completionHandler(.failure(error), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds thread participants to a Thread. If the participants already exist, no change occurs.
|
||||
/// - Parameters:
|
||||
/// - participants : An array of participants to add.
|
||||
/// - options: Add chat participants options.
|
||||
/// - completionHandler: A completion handler that receives a status code on success.
|
||||
public func add(
|
||||
participants: [Participant],
|
||||
withOptions options: ChatThreadOperation.AddChatParticipantsOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<AddChatParticipantsResult>
|
||||
) {
|
||||
// Convert Participants to ChatParticipants
|
||||
let chatParticipants = participants.map {
|
||||
ChatParticipant(
|
||||
id: $0.user.identifier,
|
||||
displayName: $0.displayName,
|
||||
shareHistoryTime: $0.shareHistoryTime
|
||||
)
|
||||
}
|
||||
// Convert to AddChatParticipantsRequest for generated code
|
||||
let addParticipantsRequest = AddChatParticipantsRequest(
|
||||
participants: chatParticipants
|
||||
)
|
||||
|
||||
service
|
||||
.add(
|
||||
chatParticipants: addParticipantsRequest,
|
||||
chatThreadId: threadId,
|
||||
withOptions: options
|
||||
) { result, httpResponse in
|
||||
switch result {
|
||||
case let .success(addParticipantsResult):
|
||||
completionHandler(.success(addParticipantsResult), httpResponse)
|
||||
|
||||
case let .failure(error):
|
||||
completionHandler(.failure(error), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes a participant from the thread.
|
||||
/// - Parameters:
|
||||
/// - participantId : Id of the participant to remove.
|
||||
/// - options: Remove participant options
|
||||
/// - completionHandler: A completion handler that receives a status code on success.
|
||||
public func remove(
|
||||
participant participantId: String,
|
||||
withOptions options: ChatThreadOperation.RemoveChatParticipantOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<Void>
|
||||
) {
|
||||
service
|
||||
.removeChatParticipant(
|
||||
chatThreadId: threadId,
|
||||
chatParticipantId: participantId,
|
||||
withOptions: options
|
||||
) { result, httpResponse in
|
||||
switch result {
|
||||
case .success:
|
||||
completionHandler(.success(()), httpResponse)
|
||||
|
||||
case let .failure(error):
|
||||
completionHandler(.failure(error), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the participants of the thread.
|
||||
/// - Parameters:
|
||||
/// - options: List chat participants options.
|
||||
/// - completionHandler: A completion handler that receives the list of members on success.
|
||||
public func listParticipants(
|
||||
withOptions options: ChatThreadOperation.ListChatParticipantsOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<PagedCollection<Participant>>
|
||||
) {
|
||||
service.listChatParticipants(chatThreadId: threadId, withOptions: options) { result, httpResponse in
|
||||
switch result {
|
||||
case .success:
|
||||
// TODO: https://github.com/Azure/azure-sdk-for-ios/issues/644
|
||||
// Construct a new PagedCollection of type Participant
|
||||
do {
|
||||
let participants = try self.createPagedCollection(
|
||||
from: httpResponse?.data,
|
||||
withRequest: httpResponse?.httpRequest,
|
||||
of: Participant.self
|
||||
)
|
||||
|
||||
completionHandler(.success(participants), httpResponse)
|
||||
} catch {
|
||||
let azureError = AzureError.client(error.localizedDescription, error)
|
||||
completionHandler(.failure(azureError), httpResponse)
|
||||
}
|
||||
|
||||
case let .failure(error):
|
||||
completionHandler(.failure(error), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,27 +25,27 @@ public final class AzureCommunicationChatClient: PipelineClient, PageableClient
|
|||
public enum ApiVersion: RequestStringConvertible {
|
||||
/// Custom value for unrecognized enum values
|
||||
case custom(String)
|
||||
/// API version "2020-09-21-preview2"
|
||||
case v20200921preview2
|
||||
/// API version "2020-11-01-preview3"
|
||||
case v20201101preview3
|
||||
|
||||
/// The most recent API version of the
|
||||
public static var latest: ApiVersion {
|
||||
return .v20200921preview2
|
||||
return .v20201101preview3
|
||||
}
|
||||
|
||||
public var requestString: String {
|
||||
switch self {
|
||||
case let .custom(val):
|
||||
return val
|
||||
case .v20200921preview2:
|
||||
return "2020-09-21-preview2"
|
||||
case .v20201101preview3:
|
||||
return "2020-11-01-preview3"
|
||||
}
|
||||
}
|
||||
|
||||
public init(_ val: String) {
|
||||
switch val.lowercased() {
|
||||
case "2020-09-21-preview2":
|
||||
self = .v20200921preview2
|
||||
case "2020-11-01-preview3":
|
||||
self = .v20201101preview3
|
||||
default:
|
||||
self = .custom(val)
|
||||
}
|
||||
|
@ -85,7 +85,8 @@ public final class AzureCommunicationChatClient: PipelineClient, PageableClient
|
|||
)
|
||||
}
|
||||
|
||||
public lazy var azureCommunicationChatService = AzureCommunicationChatService(client: self)
|
||||
public lazy var chat = Chat(client: self)
|
||||
public lazy var chatThreadOperation = ChatThreadOperation(client: self)
|
||||
|
||||
// MARK: Public Client Methods
|
||||
}
|
||||
|
|
|
@ -0,0 +1,563 @@
|
|||
// --------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for
|
||||
// license information.
|
||||
//
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
// Changes may cause incorrect behavior and will be lost if the code is
|
||||
// regenerated.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCore
|
||||
import Foundation
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable file_length
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
// swiftlint:disable function_body_length
|
||||
// swiftlint:disable type_body_length
|
||||
|
||||
public final class Chat {
|
||||
public let client: AzureCommunicationChatClient
|
||||
|
||||
init(client: AzureCommunicationChatClient) {
|
||||
self.client = client
|
||||
}
|
||||
|
||||
/// Creates a chat thread.
|
||||
/// - Parameters:
|
||||
/// - chatThread : Request payload for creating a chat thread.
|
||||
/// - options: A list of options for the operation
|
||||
/// - completionHandler: A completion handler that receives a status code on
|
||||
/// success.
|
||||
public func create(
|
||||
chatThread: CreateChatThreadRequest,
|
||||
withOptions options: CreateChatThreadOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<CreateChatThreadResult>
|
||||
) {
|
||||
let dispatchQueue = options?.dispatchQueue ?? client.commonOptions.dispatchQueue ?? DispatchQueue.main
|
||||
|
||||
// Create request parameters
|
||||
let params = RequestParameters(
|
||||
(.header, "repeatability-Request-ID", options?.repeatabilityRequestID, .encode), (
|
||||
.uri,
|
||||
"endpoint",
|
||||
client.endpoint.absoluteString,
|
||||
.skipEncoding
|
||||
), (.query, "api-version", client.options.apiVersion, .encode),
|
||||
(.header, "Content-Type", "application/json", .encode),
|
||||
(.header, "Accept", "application/json", .encode)
|
||||
)
|
||||
|
||||
// Construct request
|
||||
guard let requestBody = try? JSONEncoder().encode(chatThread) else {
|
||||
client.options.logger.error("Failed to encode request body as json.")
|
||||
return
|
||||
}
|
||||
let urlTemplate = "/chat/threads"
|
||||
guard let requestUrl = client.url(host: "{endpoint}", template: urlTemplate, params: params),
|
||||
let request = try? HTTPRequest(method: .post, url: requestUrl, headers: params.headers, data: requestBody)
|
||||
else {
|
||||
client.options.logger.error("Failed to construct HTTP request.")
|
||||
return
|
||||
}
|
||||
|
||||
// Send request
|
||||
let context = PipelineContext.of(keyValues: [
|
||||
ContextKey.allowedStatusCodes.rawValue: [201, 401, 403, 429, 503] as AnyObject
|
||||
])
|
||||
context.add(cancellationToken: options?.cancellationToken, applying: client.options)
|
||||
context.merge(with: options?.context)
|
||||
client.request(request, context: context) { result, httpResponse in
|
||||
guard let data = httpResponse?.data else {
|
||||
let noDataError = AzureError.client("Response data expected but not found.")
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(noDataError), httpResponse)
|
||||
}
|
||||
return
|
||||
}
|
||||
switch result {
|
||||
case .success:
|
||||
guard let statusCode = httpResponse?.statusCode else {
|
||||
let noStatusCodeError = AzureError.client("Expected a status code in response but didn't find one.")
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(noStatusCodeError), httpResponse)
|
||||
}
|
||||
return
|
||||
}
|
||||
if [
|
||||
201
|
||||
].contains(statusCode) {
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
let decoded = try decoder.decode(CreateChatThreadResult.self, from: data)
|
||||
dispatchQueue.async {
|
||||
completionHandler(.success(decoded), httpResponse)
|
||||
}
|
||||
} catch {
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.client("Decoding error.", error)), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
if [401].contains(statusCode) {
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
let decoded = try decoder.decode(CommunicationErrorResponse.self, from: data)
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.service("Unauthorized.", decoded)), httpResponse)
|
||||
}
|
||||
} catch {
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.client("Decoding error.", error)), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
if [403].contains(statusCode) {
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
let decoded = try decoder.decode(CommunicationErrorResponse.self, from: data)
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.service("Forbidden.", decoded)), httpResponse)
|
||||
}
|
||||
} catch {
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.client("Decoding error.", error)), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
if [429].contains(statusCode) {
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
let decoded = try decoder.decode(CommunicationErrorResponse.self, from: data)
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.service("Too many requests.", decoded)), httpResponse)
|
||||
}
|
||||
} catch {
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.client("Decoding error.", error)), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
if [503].contains(statusCode) {
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
let decoded = try decoder.decode(CommunicationErrorResponse.self, from: data)
|
||||
dispatchQueue.async {
|
||||
completionHandler(
|
||||
.failure(AzureError.service("Service unavailable.", decoded)),
|
||||
httpResponse
|
||||
)
|
||||
}
|
||||
} catch {
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.client("Decoding error.", error)), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
case let .failure(error):
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(error), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the list of chat threads of a user.
|
||||
/// - Parameters:
|
||||
|
||||
/// - options: A list of options for the operation
|
||||
/// - completionHandler: A completion handler that receives a status code on
|
||||
/// success.
|
||||
public func listChatThreads(
|
||||
withOptions options: ListChatThreadsOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<PagedCollection<ChatThreadInfo>>
|
||||
) {
|
||||
let dispatchQueue = options?.dispatchQueue ?? client.commonOptions.dispatchQueue ?? DispatchQueue.main
|
||||
|
||||
// Create request parameters
|
||||
let params = RequestParameters(
|
||||
(.query, "maxPageSize", options?.maxPageSize, .encode), (.query, "startTime", options?.startTime, .encode),
|
||||
(.uri, "endpoint", client.endpoint.absoluteString, .skipEncoding),
|
||||
(.query, "api-version", client.options.apiVersion, .encode),
|
||||
(.header, "Accept", "application/json", .encode)
|
||||
)
|
||||
|
||||
// Construct request
|
||||
let urlTemplate = "/chat/threads"
|
||||
guard let requestUrl = client.url(host: "{endpoint}", template: urlTemplate, params: params),
|
||||
let request = try? HTTPRequest(method: .get, url: requestUrl, headers: params.headers)
|
||||
else {
|
||||
client.options.logger.error("Failed to construct HTTP request.")
|
||||
return
|
||||
}
|
||||
|
||||
// Send request
|
||||
let context = PipelineContext.of(keyValues: [
|
||||
ContextKey.allowedStatusCodes.rawValue: [200, 401, 403, 429, 503] as AnyObject
|
||||
])
|
||||
context.add(cancellationToken: options?.cancellationToken, applying: client.options)
|
||||
context.merge(with: options?.context)
|
||||
client.request(request, context: context) { result, httpResponse in
|
||||
guard let data = httpResponse?.data else {
|
||||
let noDataError = AzureError.client("Response data expected but not found.")
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(noDataError), httpResponse)
|
||||
}
|
||||
return
|
||||
}
|
||||
switch result {
|
||||
case .success:
|
||||
guard let statusCode = httpResponse?.statusCode else {
|
||||
let noStatusCodeError = AzureError.client("Expected a status code in response but didn't find one.")
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(noStatusCodeError), httpResponse)
|
||||
}
|
||||
return
|
||||
}
|
||||
if [
|
||||
200
|
||||
].contains(statusCode) {
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
let codingKeys = PagedCodingKeys(
|
||||
items: "value",
|
||||
continuationToken: "nextLink"
|
||||
)
|
||||
let paged = try PagedCollection<ChatThreadInfo>(
|
||||
client: self.client,
|
||||
request: request,
|
||||
context: context,
|
||||
data: data,
|
||||
codingKeys: codingKeys,
|
||||
decoder: decoder
|
||||
)
|
||||
dispatchQueue.async {
|
||||
completionHandler(.success(paged), httpResponse)
|
||||
}
|
||||
} catch {
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.client("Decoding error.", error)), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if [401].contains(statusCode) {
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
let decoded = try decoder.decode(CommunicationErrorResponse.self, from: data)
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.service("Unauthorized.", decoded)), httpResponse)
|
||||
}
|
||||
} catch {
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.client("Decoding error.", error)), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
if [403].contains(statusCode) {
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
let decoded = try decoder.decode(CommunicationErrorResponse.self, from: data)
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.service("Forbidden.", decoded)), httpResponse)
|
||||
}
|
||||
} catch {
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.client("Decoding error.", error)), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
if [429].contains(statusCode) {
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
let decoded = try decoder.decode(CommunicationErrorResponse.self, from: data)
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.service("Too many requests.", decoded)), httpResponse)
|
||||
}
|
||||
} catch {
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.client("Decoding error.", error)), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
if [503].contains(statusCode) {
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
let decoded = try decoder.decode(CommunicationErrorResponse.self, from: data)
|
||||
dispatchQueue.async {
|
||||
completionHandler(
|
||||
.failure(AzureError.service("Service unavailable.", decoded)),
|
||||
httpResponse
|
||||
)
|
||||
}
|
||||
} catch {
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.client("Decoding error.", error)), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
case let .failure(error):
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(error), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a chat thread.
|
||||
/// - Parameters:
|
||||
/// - chatThreadId : Id of the thread.
|
||||
/// - options: A list of options for the operation
|
||||
/// - completionHandler: A completion handler that receives a status code on
|
||||
/// success.
|
||||
public func getChatThread(
|
||||
chatThreadId: String,
|
||||
withOptions options: GetChatThreadOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<ChatThread>
|
||||
) {
|
||||
let dispatchQueue = options?.dispatchQueue ?? client.commonOptions.dispatchQueue ?? DispatchQueue.main
|
||||
|
||||
// Create request parameters
|
||||
let params = RequestParameters(
|
||||
(.path, "chatThreadId", chatThreadId, .encode),
|
||||
(.uri, "endpoint", client.endpoint.absoluteString, .skipEncoding),
|
||||
(.query, "api-version", client.options.apiVersion, .encode),
|
||||
(.header, "Accept", "application/json", .encode)
|
||||
)
|
||||
|
||||
// Construct request
|
||||
let urlTemplate = "/chat/threads/{chatThreadId}"
|
||||
guard let requestUrl = client.url(host: "{endpoint}", template: urlTemplate, params: params),
|
||||
let request = try? HTTPRequest(method: .get, url: requestUrl, headers: params.headers)
|
||||
else {
|
||||
client.options.logger.error("Failed to construct HTTP request.")
|
||||
return
|
||||
}
|
||||
|
||||
// Send request
|
||||
let context = PipelineContext.of(keyValues: [
|
||||
ContextKey.allowedStatusCodes.rawValue: [200, 401, 403, 429, 503] as AnyObject
|
||||
])
|
||||
context.add(cancellationToken: options?.cancellationToken, applying: client.options)
|
||||
context.merge(with: options?.context)
|
||||
client.request(request, context: context) { result, httpResponse in
|
||||
guard let data = httpResponse?.data else {
|
||||
let noDataError = AzureError.client("Response data expected but not found.")
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(noDataError), httpResponse)
|
||||
}
|
||||
return
|
||||
}
|
||||
switch result {
|
||||
case .success:
|
||||
guard let statusCode = httpResponse?.statusCode else {
|
||||
let noStatusCodeError = AzureError.client("Expected a status code in response but didn't find one.")
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(noStatusCodeError), httpResponse)
|
||||
}
|
||||
return
|
||||
}
|
||||
if [
|
||||
200
|
||||
].contains(statusCode) {
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
let decoded = try decoder.decode(ChatThread.self, from: data)
|
||||
dispatchQueue.async {
|
||||
completionHandler(.success(decoded), httpResponse)
|
||||
}
|
||||
} catch {
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.client("Decoding error.", error)), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
if [401].contains(statusCode) {
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
let decoded = try decoder.decode(CommunicationErrorResponse.self, from: data)
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.service("Unauthorized.", decoded)), httpResponse)
|
||||
}
|
||||
} catch {
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.client("Decoding error.", error)), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
if [403].contains(statusCode) {
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
let decoded = try decoder.decode(CommunicationErrorResponse.self, from: data)
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.service("Forbidden.", decoded)), httpResponse)
|
||||
}
|
||||
} catch {
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.client("Decoding error.", error)), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
if [429].contains(statusCode) {
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
let decoded = try decoder.decode(CommunicationErrorResponse.self, from: data)
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.service("Too many requests.", decoded)), httpResponse)
|
||||
}
|
||||
} catch {
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.client("Decoding error.", error)), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
if [503].contains(statusCode) {
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
let decoded = try decoder.decode(CommunicationErrorResponse.self, from: data)
|
||||
dispatchQueue.async {
|
||||
completionHandler(
|
||||
.failure(AzureError.service("Service unavailable.", decoded)),
|
||||
httpResponse
|
||||
)
|
||||
}
|
||||
} catch {
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.client("Decoding error.", error)), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
case let .failure(error):
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(error), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Deletes a thread.
|
||||
/// - Parameters:
|
||||
/// - chatThreadId : Id of the thread to be deleted.
|
||||
/// - options: A list of options for the operation
|
||||
/// - completionHandler: A completion handler that receives a status code on
|
||||
/// success.
|
||||
public func deleteChatThread(
|
||||
chatThreadId: String,
|
||||
withOptions options: DeleteChatThreadOptions? = nil,
|
||||
completionHandler: @escaping HTTPResultHandler<Void>
|
||||
) {
|
||||
let dispatchQueue = options?.dispatchQueue ?? client.commonOptions.dispatchQueue ?? DispatchQueue.main
|
||||
|
||||
// Create request parameters
|
||||
let params = RequestParameters(
|
||||
(.path, "chatThreadId", chatThreadId, .encode),
|
||||
(.uri, "endpoint", client.endpoint.absoluteString, .skipEncoding),
|
||||
(.query, "api-version", client.options.apiVersion, .encode),
|
||||
(.header, "Accept", "application/json", .encode)
|
||||
)
|
||||
|
||||
// Construct request
|
||||
let urlTemplate = "/chat/threads/{chatThreadId}"
|
||||
guard let requestUrl = client.url(host: "{endpoint}", template: urlTemplate, params: params),
|
||||
let request = try? HTTPRequest(method: .delete, url: requestUrl, headers: params.headers)
|
||||
else {
|
||||
client.options.logger.error("Failed to construct HTTP request.")
|
||||
return
|
||||
}
|
||||
|
||||
// Send request
|
||||
let context = PipelineContext.of(keyValues: [
|
||||
ContextKey.allowedStatusCodes.rawValue: [204, 401, 403, 429, 503] as AnyObject
|
||||
])
|
||||
context.add(cancellationToken: options?.cancellationToken, applying: client.options)
|
||||
context.merge(with: options?.context)
|
||||
client.request(request, context: context) { result, httpResponse in
|
||||
guard let data = httpResponse?.data else {
|
||||
let noDataError = AzureError.client("Response data expected but not found.")
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(noDataError), httpResponse)
|
||||
}
|
||||
return
|
||||
}
|
||||
switch result {
|
||||
case .success:
|
||||
guard let statusCode = httpResponse?.statusCode else {
|
||||
let noStatusCodeError = AzureError.client("Expected a status code in response but didn't find one.")
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(noStatusCodeError), httpResponse)
|
||||
}
|
||||
return
|
||||
}
|
||||
if [
|
||||
204
|
||||
].contains(statusCode) {
|
||||
dispatchQueue.async {
|
||||
completionHandler(
|
||||
.success(()),
|
||||
httpResponse
|
||||
)
|
||||
}
|
||||
}
|
||||
if [401].contains(statusCode) {
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
let decoded = try decoder.decode(CommunicationErrorResponse.self, from: data)
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.service("Unauthorized.", decoded)), httpResponse)
|
||||
}
|
||||
} catch {
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.client("Decoding error.", error)), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
if [403].contains(statusCode) {
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
let decoded = try decoder.decode(CommunicationErrorResponse.self, from: data)
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.service("Forbidden.", decoded)), httpResponse)
|
||||
}
|
||||
} catch {
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.client("Decoding error.", error)), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
if [429].contains(statusCode) {
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
let decoded = try decoder.decode(CommunicationErrorResponse.self, from: data)
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.service("Too many requests.", decoded)), httpResponse)
|
||||
}
|
||||
} catch {
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.client("Decoding error.", error)), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
if [503].contains(statusCode) {
|
||||
do {
|
||||
let decoder = JSONDecoder()
|
||||
let decoded = try decoder.decode(CommunicationErrorResponse.self, from: data)
|
||||
dispatchQueue.async {
|
||||
completionHandler(
|
||||
.failure(AzureError.service("Service unavailable.", decoded)),
|
||||
httpResponse
|
||||
)
|
||||
}
|
||||
} catch {
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(AzureError.client("Decoding error.", error)), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
case let .failure(error):
|
||||
dispatchQueue.async {
|
||||
completionHandler(.failure(error), httpResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,53 @@
|
|||
// --------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for
|
||||
// license information.
|
||||
//
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
// Changes may cause incorrect behavior and will be lost if the code is
|
||||
// regenerated.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCore
|
||||
import Foundation
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
/// Errors encountered during the addition of the chat participant to the chat thread.
|
||||
public struct AddChatParticipantsErrors: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// The participants that failed to be added to the chat thread.
|
||||
public let invalidParticipants: [CommunicationError?]
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initialize a `AddChatParticipantsErrors` structure.
|
||||
/// - Parameters:
|
||||
/// - invalidParticipants: The participants that failed to be added to the chat thread.
|
||||
public init(
|
||||
invalidParticipants: [CommunicationError?]
|
||||
) {
|
||||
self.invalidParticipants = invalidParticipants
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case invalidParticipants = "invalidParticipants"
|
||||
}
|
||||
|
||||
/// Initialize a `AddChatParticipantsErrors` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.invalidParticipants = try container.decode([CommunicationError?].self, forKey: .invalidParticipants)
|
||||
}
|
||||
|
||||
/// Encode a `AddChatParticipantsErrors` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(invalidParticipants, forKey: .invalidParticipants)
|
||||
}
|
||||
}
|
|
@ -15,38 +15,39 @@ import Foundation
|
|||
// swiftlint:disable line_length
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
public struct MultiStatusResponse: Codable, Equatable {
|
||||
/// Participants to be added to the thread.
|
||||
public struct AddChatParticipantsRequest: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// The list of status information for each resource in the request.
|
||||
public let multipleStatus: [IndividualStatusResponse]?
|
||||
/// Participants to add to a chat thread.
|
||||
public let participants: [ChatParticipant]
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initialize a `MultiStatusResponse` structure.
|
||||
/// Initialize a `AddChatParticipantsRequest` structure.
|
||||
/// - Parameters:
|
||||
/// - multipleStatus: The list of status information for each resource in the request.
|
||||
/// - participants: Participants to add to a chat thread.
|
||||
public init(
|
||||
multipleStatus: [IndividualStatusResponse]? = nil
|
||||
participants: [ChatParticipant]
|
||||
) {
|
||||
self.multipleStatus = multipleStatus
|
||||
self.participants = participants
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case multipleStatus = "multipleStatus"
|
||||
case participants = "participants"
|
||||
}
|
||||
|
||||
/// Initialize a `MultiStatusResponse` structure from decoder
|
||||
/// Initialize a `AddChatParticipantsRequest` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.multipleStatus = try? container.decode([IndividualStatusResponse].self, forKey: .multipleStatus)
|
||||
self.participants = try container.decode([ChatParticipant].self, forKey: .participants)
|
||||
}
|
||||
|
||||
/// Encode a `MultiStatusResponse` structure
|
||||
/// Encode a `AddChatParticipantsRequest` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
if multipleStatus != nil { try? container.encode(multipleStatus, forKey: .multipleStatus) }
|
||||
try container.encode(participants, forKey: .participants)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
// --------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for
|
||||
// license information.
|
||||
//
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
// Changes may cause incorrect behavior and will be lost if the code is
|
||||
// regenerated.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCore
|
||||
import Foundation
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
/// Result of the add chat participants operation.
|
||||
public struct AddChatParticipantsResult: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// Errors encountered during the addition of the chat participant to the chat thread.
|
||||
public let errors: AddChatParticipantsErrors?
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initialize a `AddChatParticipantsResult` structure.
|
||||
/// - Parameters:
|
||||
/// - errors: Errors encountered during the addition of the chat participant to the chat thread.
|
||||
public init(
|
||||
errors: AddChatParticipantsErrors? = nil
|
||||
) {
|
||||
self.errors = errors
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case errors = "errors"
|
||||
}
|
||||
|
||||
/// Initialize a `AddChatParticipantsResult` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.errors = try? container.decode(AddChatParticipantsErrors.self, forKey: .errors)
|
||||
}
|
||||
|
||||
/// Encode a `AddChatParticipantsResult` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
if errors != nil { try? container.encode(errors, forKey: .errors) }
|
||||
}
|
||||
}
|
|
@ -15,34 +15,29 @@ import Foundation
|
|||
// swiftlint:disable line_length
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
public struct ChatMessage: Codable, Equatable {
|
||||
/// Chat message.
|
||||
public struct ChatMessage: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// The id of the chat message. This id is server generated.
|
||||
public let id: String?
|
||||
/// Type of the chat message.
|
||||
///
|
||||
/// Possible values:
|
||||
/// - Text
|
||||
/// - ThreadActivity/TopicUpdate
|
||||
/// - ThreadActivity/AddMember
|
||||
/// - ThreadActivity/DeleteMember
|
||||
public let type: String?
|
||||
/// The chat message priority.
|
||||
public let priority: ChatMessagePriority?
|
||||
public let id: String
|
||||
/// The chat message type.
|
||||
public let type: ChatMessageType
|
||||
/// Sequence of the chat message in the conversation.
|
||||
public let sequenceId: String
|
||||
/// Version of the chat message.
|
||||
public let version: String?
|
||||
/// Content of the chat message.
|
||||
public let content: String?
|
||||
public let version: String
|
||||
/// Content of a chat message.
|
||||
public let content: ChatMessageContent?
|
||||
/// The display name of the chat message sender. This property is used to populate sender name for push notifications.
|
||||
public let senderDisplayName: String?
|
||||
/// The timestamp when the chat message arrived at the server. The timestamp is in ISO8601 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public let createdOn: Iso8601Date?
|
||||
/// The timestamp when the chat message arrived at the server. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public let createdOn: Iso8601Date
|
||||
/// The id of the chat message sender.
|
||||
public let senderId: String?
|
||||
/// The timestamp when the chat message was deleted. The timestamp is in ISO8601 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
/// The timestamp (if applicable) when the message was deleted. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public let deletedOn: Iso8601Date?
|
||||
/// The timestamp when the chat message was edited. The timestamp is in ISO8601 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
/// The last timestamp (if applicable) when the message was edited. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public let editedOn: Iso8601Date?
|
||||
|
||||
// MARK: Initializers
|
||||
|
@ -50,29 +45,23 @@ public struct ChatMessage: Codable, Equatable {
|
|||
/// Initialize a `ChatMessage` structure.
|
||||
/// - Parameters:
|
||||
/// - id: The id of the chat message. This id is server generated.
|
||||
/// - type: Type of the chat message.
|
||||
///
|
||||
/// Possible values:
|
||||
/// - Text
|
||||
/// - ThreadActivity/TopicUpdate
|
||||
/// - ThreadActivity/AddMember
|
||||
/// - ThreadActivity/DeleteMember
|
||||
/// - priority: The chat message priority.
|
||||
/// - type: The chat message type.
|
||||
/// - sequenceId: Sequence of the chat message in the conversation.
|
||||
/// - version: Version of the chat message.
|
||||
/// - content: Content of the chat message.
|
||||
/// - content: Content of a chat message.
|
||||
/// - senderDisplayName: The display name of the chat message sender. This property is used to populate sender name for push notifications.
|
||||
/// - createdOn: The timestamp when the chat message arrived at the server. The timestamp is in ISO8601 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
/// - createdOn: The timestamp when the chat message arrived at the server. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
/// - senderId: The id of the chat message sender.
|
||||
/// - deletedOn: The timestamp when the chat message was deleted. The timestamp is in ISO8601 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
/// - editedOn: The timestamp when the chat message was edited. The timestamp is in ISO8601 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
/// - deletedOn: The timestamp (if applicable) when the message was deleted. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
/// - editedOn: The last timestamp (if applicable) when the message was edited. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public init(
|
||||
id: String? = nil, type: String? = nil, priority: ChatMessagePriority? = nil, version: String? = nil,
|
||||
content: String? = nil, senderDisplayName: String? = nil, createdOn: Iso8601Date? = nil,
|
||||
senderId: String? = nil, deletedOn: Iso8601Date? = nil, editedOn: Iso8601Date? = nil
|
||||
id: String, type: ChatMessageType, sequenceId: String, version: String, content: ChatMessageContent? = nil,
|
||||
senderDisplayName: String? = nil, createdOn: Iso8601Date, senderId: String? = nil,
|
||||
deletedOn: Iso8601Date? = nil, editedOn: Iso8601Date? = nil
|
||||
) {
|
||||
self.id = id
|
||||
self.type = type
|
||||
self.priority = priority
|
||||
self.sequenceId = sequenceId
|
||||
self.version = version
|
||||
self.content = content
|
||||
self.senderDisplayName = senderDisplayName
|
||||
|
@ -87,7 +76,7 @@ public struct ChatMessage: Codable, Equatable {
|
|||
enum CodingKeys: String, CodingKey {
|
||||
case id = "id"
|
||||
case type = "type"
|
||||
case priority = "priority"
|
||||
case sequenceId = "sequenceId"
|
||||
case version = "version"
|
||||
case content = "content"
|
||||
case senderDisplayName = "senderDisplayName"
|
||||
|
@ -100,13 +89,13 @@ public struct ChatMessage: Codable, Equatable {
|
|||
/// Initialize a `ChatMessage` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.id = try? container.decode(String.self, forKey: .id)
|
||||
self.type = try? container.decode(String.self, forKey: .type)
|
||||
self.priority = try? container.decode(ChatMessagePriority.self, forKey: .priority)
|
||||
self.version = try? container.decode(String.self, forKey: .version)
|
||||
self.content = try? container.decode(String.self, forKey: .content)
|
||||
self.id = try container.decode(String.self, forKey: .id)
|
||||
self.type = try container.decode(ChatMessageType.self, forKey: .type)
|
||||
self.sequenceId = try container.decode(String.self, forKey: .sequenceId)
|
||||
self.version = try container.decode(String.self, forKey: .version)
|
||||
self.content = try? container.decode(ChatMessageContent.self, forKey: .content)
|
||||
self.senderDisplayName = try? container.decode(String.self, forKey: .senderDisplayName)
|
||||
self.createdOn = try? container.decode(Iso8601Date.self, forKey: .createdOn)
|
||||
self.createdOn = try container.decode(Iso8601Date.self, forKey: .createdOn)
|
||||
self.senderId = try? container.decode(String.self, forKey: .senderId)
|
||||
self.deletedOn = try? container.decode(Iso8601Date.self, forKey: .deletedOn)
|
||||
self.editedOn = try? container.decode(Iso8601Date.self, forKey: .editedOn)
|
||||
|
@ -115,13 +104,13 @@ public struct ChatMessage: Codable, Equatable {
|
|||
/// Encode a `ChatMessage` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
if id != nil { try? container.encode(id, forKey: .id) }
|
||||
if type != nil { try? container.encode(type, forKey: .type) }
|
||||
if priority != nil { try? container.encode(priority, forKey: .priority) }
|
||||
if version != nil { try? container.encode(version, forKey: .version) }
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(type, forKey: .type)
|
||||
try container.encode(sequenceId, forKey: .sequenceId)
|
||||
try container.encode(version, forKey: .version)
|
||||
if content != nil { try? container.encode(content, forKey: .content) }
|
||||
if senderDisplayName != nil { try? container.encode(senderDisplayName, forKey: .senderDisplayName) }
|
||||
if createdOn != nil { try? container.encode(createdOn, forKey: .createdOn) }
|
||||
try container.encode(createdOn, forKey: .createdOn)
|
||||
if senderId != nil { try? container.encode(senderId, forKey: .senderId) }
|
||||
if deletedOn != nil { try? container.encode(deletedOn, forKey: .deletedOn) }
|
||||
if editedOn != nil { try? container.encode(editedOn, forKey: .editedOn) }
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
// --------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for
|
||||
// license information.
|
||||
//
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
// Changes may cause incorrect behavior and will be lost if the code is
|
||||
// regenerated.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCore
|
||||
import Foundation
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
/// Content of a chat message.
|
||||
public struct ChatMessageContent: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// Chat message content for messages of types text or html.
|
||||
public let message: String?
|
||||
/// Chat message content for messages of type topicUpdated.
|
||||
public let topic: String?
|
||||
/// Chat message content for messages of types participantAdded or participantRemoved.
|
||||
public let participants: [ChatParticipant]?
|
||||
/// Chat message initiator.
|
||||
public let initiator: String?
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initialize a `ChatMessageContent` structure.
|
||||
/// - Parameters:
|
||||
/// - message: Chat message content for messages of types text or html.
|
||||
/// - topic: Chat message content for messages of type topicUpdated.
|
||||
/// - participants: Chat message content for messages of types participantAdded or participantRemoved.
|
||||
/// - initiator: Chat message initiator.
|
||||
public init(
|
||||
message: String? = nil, topic: String? = nil, participants: [ChatParticipant]? = nil,
|
||||
initiator: String? = nil
|
||||
) {
|
||||
self.message = message
|
||||
self.topic = topic
|
||||
self.participants = participants
|
||||
self.initiator = initiator
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case message = "message"
|
||||
case topic = "topic"
|
||||
case participants = "participants"
|
||||
case initiator = "initiator"
|
||||
}
|
||||
|
||||
/// Initialize a `ChatMessageContent` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.message = try? container.decode(String.self, forKey: .message)
|
||||
self.topic = try? container.decode(String.self, forKey: .topic)
|
||||
self.participants = try? container.decode([ChatParticipant].self, forKey: .participants)
|
||||
self.initiator = try? container.decode(String.self, forKey: .initiator)
|
||||
}
|
||||
|
||||
/// Encode a `ChatMessageContent` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
if message != nil { try? container.encode(message, forKey: .message) }
|
||||
if topic != nil { try? container.encode(topic, forKey: .topic) }
|
||||
if participants != nil { try? container.encode(participants, forKey: .participants) }
|
||||
if initiator != nil { try? container.encode(initiator, forKey: .initiator) }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
// --------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for
|
||||
// license information.
|
||||
//
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
// Changes may cause incorrect behavior and will be lost if the code is
|
||||
// regenerated.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCore
|
||||
import Foundation
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
/// A chat message read receipt indicates the time a chat message was read by a recipient.
|
||||
public struct ChatMessageReadReceipt: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// Id of the participant who read the message.
|
||||
public let senderId: String
|
||||
/// Id of the chat message that has been read. This id is generated by the server.
|
||||
public let chatMessageId: String
|
||||
/// The time at which the message was read. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public let readOn: Iso8601Date
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initialize a `ChatMessageReadReceipt` structure.
|
||||
/// - Parameters:
|
||||
/// - senderId: Id of the participant who read the message.
|
||||
/// - chatMessageId: Id of the chat message that has been read. This id is generated by the server.
|
||||
/// - readOn: The time at which the message was read. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public init(
|
||||
senderId: String, chatMessageId: String, readOn: Iso8601Date
|
||||
) {
|
||||
self.senderId = senderId
|
||||
self.chatMessageId = chatMessageId
|
||||
self.readOn = readOn
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case senderId = "senderId"
|
||||
case chatMessageId = "chatMessageId"
|
||||
case readOn = "readOn"
|
||||
}
|
||||
|
||||
/// Initialize a `ChatMessageReadReceipt` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.senderId = try container.decode(String.self, forKey: .senderId)
|
||||
self.chatMessageId = try container.decode(String.self, forKey: .chatMessageId)
|
||||
self.readOn = try container.decode(Iso8601Date.self, forKey: .readOn)
|
||||
}
|
||||
|
||||
/// Encode a `ChatMessageReadReceipt` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(senderId, forKey: .senderId)
|
||||
try container.encode(chatMessageId, forKey: .chatMessageId)
|
||||
try container.encode(readOn, forKey: .readOn)
|
||||
}
|
||||
}
|
|
@ -15,23 +15,23 @@ import Foundation
|
|||
// swiftlint:disable line_length
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
/// Collection of thread members belong to a particular thread.
|
||||
public struct ChatThreadMembersCollection: Codable, Equatable {
|
||||
/// A paged collection of chat message read receipts.
|
||||
public struct ChatMessageReadReceiptsCollection: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// Chat thread members.
|
||||
public let value: [ChatThreadMember]?
|
||||
/// If there are more chat threads that can be retrieved, the next link will be populated.
|
||||
/// Collection of chat message read receipts.
|
||||
public let value: [ChatMessageReadReceipt]
|
||||
/// If there are more chat message read receipts that can be retrieved, the next link will be populated.
|
||||
public let nextLink: String?
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initialize a `ChatThreadMembersCollection` structure.
|
||||
/// Initialize a `ChatMessageReadReceiptsCollection` structure.
|
||||
/// - Parameters:
|
||||
/// - value: Chat thread members.
|
||||
/// - nextLink: If there are more chat threads that can be retrieved, the next link will be populated.
|
||||
/// - value: Collection of chat message read receipts.
|
||||
/// - nextLink: If there are more chat message read receipts that can be retrieved, the next link will be populated.
|
||||
public init(
|
||||
value: [ChatThreadMember]? = nil, nextLink: String? = nil
|
||||
value: [ChatMessageReadReceipt], nextLink: String? = nil
|
||||
) {
|
||||
self.value = value
|
||||
self.nextLink = nextLink
|
||||
|
@ -44,17 +44,17 @@ public struct ChatThreadMembersCollection: Codable, Equatable {
|
|||
case nextLink = "nextLink"
|
||||
}
|
||||
|
||||
/// Initialize a `ChatThreadMembersCollection` structure from decoder
|
||||
/// Initialize a `ChatMessageReadReceiptsCollection` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.value = try? container.decode([ChatThreadMember].self, forKey: .value)
|
||||
self.value = try container.decode([ChatMessageReadReceipt].self, forKey: .value)
|
||||
self.nextLink = try? container.decode(String.self, forKey: .nextLink)
|
||||
}
|
||||
|
||||
/// Encode a `ChatThreadMembersCollection` structure
|
||||
/// Encode a `ChatMessageReadReceiptsCollection` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
if value != nil { try? container.encode(value, forKey: .value) }
|
||||
try container.encode(value, forKey: .value)
|
||||
if nextLink != nil { try? container.encode(nextLink, forKey: .nextLink) }
|
||||
}
|
||||
}
|
|
@ -16,11 +16,11 @@ import Foundation
|
|||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
/// Collection of chat messages for a particular chat thread.
|
||||
public struct ChatMessagesCollection: Codable, Equatable {
|
||||
public struct ChatMessagesCollection: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// Collection of chat messages.
|
||||
public let value: [ChatMessage]?
|
||||
public let value: [ChatMessage]
|
||||
/// If there are more chat messages that can be retrieved, the next link will be populated.
|
||||
public let nextLink: String?
|
||||
|
||||
|
@ -31,7 +31,7 @@ public struct ChatMessagesCollection: Codable, Equatable {
|
|||
/// - value: Collection of chat messages.
|
||||
/// - nextLink: If there are more chat messages that can be retrieved, the next link will be populated.
|
||||
public init(
|
||||
value: [ChatMessage]? = nil, nextLink: String? = nil
|
||||
value: [ChatMessage], nextLink: String? = nil
|
||||
) {
|
||||
self.value = value
|
||||
self.nextLink = nextLink
|
||||
|
@ -47,14 +47,14 @@ public struct ChatMessagesCollection: Codable, Equatable {
|
|||
/// Initialize a `ChatMessagesCollection` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.value = try? container.decode([ChatMessage].self, forKey: .value)
|
||||
self.value = try container.decode([ChatMessage].self, forKey: .value)
|
||||
self.nextLink = try? container.decode(String.self, forKey: .nextLink)
|
||||
}
|
||||
|
||||
/// Encode a `ChatMessagesCollection` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
if value != nil { try? container.encode(value, forKey: .value) }
|
||||
try container.encode(value, forKey: .value)
|
||||
if nextLink != nil { try? container.encode(nextLink, forKey: .nextLink) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,24 +15,24 @@ import Foundation
|
|||
// swiftlint:disable line_length
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
/// A member of the chat thread.
|
||||
public struct ChatThreadMember: Codable, Equatable {
|
||||
/// A participant of the chat thread.
|
||||
public struct ChatParticipant: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// The id of the chat thread member in the format `8:acs:ResourceId_AcsUserId`.
|
||||
/// The id of the chat participant.
|
||||
public let id: String
|
||||
/// Display name for the chat thread member.
|
||||
/// Display name for the chat participant.
|
||||
public let displayName: String?
|
||||
/// Time from which the chat history is shared with the member. The timestamp is in ISO8601 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
/// Time from which the chat history is shared with the participant. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public let shareHistoryTime: Iso8601Date?
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initialize a `ChatThreadMember` structure.
|
||||
/// Initialize a `ChatParticipant` structure.
|
||||
/// - Parameters:
|
||||
/// - id: The id of the chat thread member in the format `8:acs:ResourceId_AcsUserId`.
|
||||
/// - displayName: Display name for the chat thread member.
|
||||
/// - shareHistoryTime: Time from which the chat history is shared with the member. The timestamp is in ISO8601 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
/// - id: The id of the chat participant.
|
||||
/// - displayName: Display name for the chat participant.
|
||||
/// - shareHistoryTime: Time from which the chat history is shared with the participant. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public init(
|
||||
id: String, displayName: String? = nil, shareHistoryTime: Iso8601Date? = nil
|
||||
) {
|
||||
|
@ -49,7 +49,7 @@ public struct ChatThreadMember: Codable, Equatable {
|
|||
case shareHistoryTime = "shareHistoryTime"
|
||||
}
|
||||
|
||||
/// Initialize a `ChatThreadMember` structure from decoder
|
||||
/// Initialize a `ChatParticipant` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.id = try container.decode(String.self, forKey: .id)
|
||||
|
@ -57,7 +57,7 @@ public struct ChatThreadMember: Codable, Equatable {
|
|||
self.shareHistoryTime = try? container.decode(Iso8601Date.self, forKey: .shareHistoryTime)
|
||||
}
|
||||
|
||||
/// Encode a `ChatThreadMember` structure
|
||||
/// Encode a `ChatParticipant` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
|
@ -15,22 +15,23 @@ import Foundation
|
|||
// swiftlint:disable line_length
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
public struct ReadReceiptsCollection: Codable, Equatable {
|
||||
/// Collection of participants belong to a particular thread.
|
||||
public struct ChatParticipantsCollection: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// Collection of read receipts.
|
||||
public let value: [ReadReceipt]?
|
||||
/// If there are more read receipts that can be retrieved, the next link will be populated.
|
||||
/// Chat participants.
|
||||
public let value: [ChatParticipant]
|
||||
/// If there are more chat participants that can be retrieved, the next link will be populated.
|
||||
public let nextLink: String?
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initialize a `ReadReceiptsCollection` structure.
|
||||
/// Initialize a `ChatParticipantsCollection` structure.
|
||||
/// - Parameters:
|
||||
/// - value: Collection of read receipts.
|
||||
/// - nextLink: If there are more read receipts that can be retrieved, the next link will be populated.
|
||||
/// - value: Chat participants.
|
||||
/// - nextLink: If there are more chat participants that can be retrieved, the next link will be populated.
|
||||
public init(
|
||||
value: [ReadReceipt]? = nil, nextLink: String? = nil
|
||||
value: [ChatParticipant], nextLink: String? = nil
|
||||
) {
|
||||
self.value = value
|
||||
self.nextLink = nextLink
|
||||
|
@ -43,17 +44,17 @@ public struct ReadReceiptsCollection: Codable, Equatable {
|
|||
case nextLink = "nextLink"
|
||||
}
|
||||
|
||||
/// Initialize a `ReadReceiptsCollection` structure from decoder
|
||||
/// Initialize a `ChatParticipantsCollection` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.value = try? container.decode([ReadReceipt].self, forKey: .value)
|
||||
self.value = try container.decode([ChatParticipant].self, forKey: .value)
|
||||
self.nextLink = try? container.decode(String.self, forKey: .nextLink)
|
||||
}
|
||||
|
||||
/// Encode a `ReadReceiptsCollection` structure
|
||||
/// Encode a `ChatParticipantsCollection` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
if value != nil { try? container.encode(value, forKey: .value) }
|
||||
try container.encode(value, forKey: .value)
|
||||
if nextLink != nil { try? container.encode(nextLink, forKey: .nextLink) }
|
||||
}
|
||||
}
|
|
@ -15,19 +15,20 @@ import Foundation
|
|||
// swiftlint:disable line_length
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
public struct ChatThread: Codable, Equatable {
|
||||
/// Chat thread.
|
||||
public struct ChatThread: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// Chat thread id.
|
||||
public let id: String?
|
||||
public let id: String
|
||||
/// Chat thread topic.
|
||||
public let topic: String?
|
||||
/// The timestamp when the chat thread was created. The timestamp is in ISO8601 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public let createdOn: Iso8601Date?
|
||||
public let topic: String
|
||||
/// The timestamp when the chat thread was created. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public let createdOn: Iso8601Date
|
||||
/// Id of the chat thread owner.
|
||||
public let createdBy: String?
|
||||
/// Chat thread members.
|
||||
public let members: [ChatThreadMember]?
|
||||
public let createdBy: String
|
||||
/// The timestamp when the chat thread was deleted. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public let deletedOn: Iso8601Date?
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
|
@ -35,18 +36,17 @@ public struct ChatThread: Codable, Equatable {
|
|||
/// - Parameters:
|
||||
/// - id: Chat thread id.
|
||||
/// - topic: Chat thread topic.
|
||||
/// - createdOn: The timestamp when the chat thread was created. The timestamp is in ISO8601 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
/// - createdOn: The timestamp when the chat thread was created. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
/// - createdBy: Id of the chat thread owner.
|
||||
/// - members: Chat thread members.
|
||||
/// - deletedOn: The timestamp when the chat thread was deleted. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public init(
|
||||
id: String? = nil, topic: String? = nil, createdOn: Iso8601Date? = nil, createdBy: String? = nil,
|
||||
members: [ChatThreadMember]? = nil
|
||||
id: String, topic: String, createdOn: Iso8601Date, createdBy: String, deletedOn: Iso8601Date? = nil
|
||||
) {
|
||||
self.id = id
|
||||
self.topic = topic
|
||||
self.createdOn = createdOn
|
||||
self.createdBy = createdBy
|
||||
self.members = members
|
||||
self.deletedOn = deletedOn
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
|
@ -56,26 +56,26 @@ public struct ChatThread: Codable, Equatable {
|
|||
case topic = "topic"
|
||||
case createdOn = "createdOn"
|
||||
case createdBy = "createdBy"
|
||||
case members = "members"
|
||||
case deletedOn = "deletedOn"
|
||||
}
|
||||
|
||||
/// Initialize a `ChatThread` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.id = try? container.decode(String.self, forKey: .id)
|
||||
self.topic = try? container.decode(String.self, forKey: .topic)
|
||||
self.createdOn = try? container.decode(Iso8601Date.self, forKey: .createdOn)
|
||||
self.createdBy = try? container.decode(String.self, forKey: .createdBy)
|
||||
self.members = try? container.decode([ChatThreadMember].self, forKey: .members)
|
||||
self.id = try container.decode(String.self, forKey: .id)
|
||||
self.topic = try container.decode(String.self, forKey: .topic)
|
||||
self.createdOn = try container.decode(Iso8601Date.self, forKey: .createdOn)
|
||||
self.createdBy = try container.decode(String.self, forKey: .createdBy)
|
||||
self.deletedOn = try? container.decode(Iso8601Date.self, forKey: .deletedOn)
|
||||
}
|
||||
|
||||
/// Encode a `ChatThread` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
if id != nil { try? container.encode(id, forKey: .id) }
|
||||
if topic != nil { try? container.encode(topic, forKey: .topic) }
|
||||
if createdOn != nil { try? container.encode(createdOn, forKey: .createdOn) }
|
||||
if createdBy != nil { try? container.encode(createdBy, forKey: .createdBy) }
|
||||
if members != nil { try? container.encode(members, forKey: .members) }
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(topic, forKey: .topic)
|
||||
try container.encode(createdOn, forKey: .createdOn)
|
||||
try container.encode(createdBy, forKey: .createdBy)
|
||||
if deletedOn != nil { try? container.encode(deletedOn, forKey: .deletedOn) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,16 +15,17 @@ import Foundation
|
|||
// swiftlint:disable line_length
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
public struct ChatThreadInfo: Codable, Equatable {
|
||||
/// Summary information of a chat thread.
|
||||
public struct ChatThreadInfo: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// Chat thread id.
|
||||
public let id: String?
|
||||
public let id: String
|
||||
/// Chat thread topic.
|
||||
public let topic: String?
|
||||
/// Flag if a chat thread is soft deleted.
|
||||
public let isDeleted: Bool?
|
||||
/// The timestamp when the last message arrived at the server. The timestamp is in ISO8601 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public let topic: String
|
||||
/// The timestamp when the chat thread was deleted. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public let deletedOn: Iso8601Date?
|
||||
/// The timestamp when the last message arrived at the server. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public let lastMessageReceivedOn: Iso8601Date?
|
||||
|
||||
// MARK: Initializers
|
||||
|
@ -33,14 +34,14 @@ public struct ChatThreadInfo: Codable, Equatable {
|
|||
/// - Parameters:
|
||||
/// - id: Chat thread id.
|
||||
/// - topic: Chat thread topic.
|
||||
/// - isDeleted: Flag if a chat thread is soft deleted.
|
||||
/// - lastMessageReceivedOn: The timestamp when the last message arrived at the server. The timestamp is in ISO8601 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
/// - deletedOn: The timestamp when the chat thread was deleted. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
/// - lastMessageReceivedOn: The timestamp when the last message arrived at the server. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public init(
|
||||
id: String? = nil, topic: String? = nil, isDeleted: Bool? = nil, lastMessageReceivedOn: Iso8601Date? = nil
|
||||
id: String, topic: String, deletedOn: Iso8601Date? = nil, lastMessageReceivedOn: Iso8601Date? = nil
|
||||
) {
|
||||
self.id = id
|
||||
self.topic = topic
|
||||
self.isDeleted = isDeleted
|
||||
self.deletedOn = deletedOn
|
||||
self.lastMessageReceivedOn = lastMessageReceivedOn
|
||||
}
|
||||
|
||||
|
@ -49,25 +50,25 @@ public struct ChatThreadInfo: Codable, Equatable {
|
|||
enum CodingKeys: String, CodingKey {
|
||||
case id = "id"
|
||||
case topic = "topic"
|
||||
case isDeleted = "isDeleted"
|
||||
case deletedOn = "deletedOn"
|
||||
case lastMessageReceivedOn = "lastMessageReceivedOn"
|
||||
}
|
||||
|
||||
/// Initialize a `ChatThreadInfo` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.id = try? container.decode(String.self, forKey: .id)
|
||||
self.topic = try? container.decode(String.self, forKey: .topic)
|
||||
self.isDeleted = try? container.decode(Bool.self, forKey: .isDeleted)
|
||||
self.id = try container.decode(String.self, forKey: .id)
|
||||
self.topic = try container.decode(String.self, forKey: .topic)
|
||||
self.deletedOn = try? container.decode(Iso8601Date.self, forKey: .deletedOn)
|
||||
self.lastMessageReceivedOn = try? container.decode(Iso8601Date.self, forKey: .lastMessageReceivedOn)
|
||||
}
|
||||
|
||||
/// Encode a `ChatThreadInfo` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
if id != nil { try? container.encode(id, forKey: .id) }
|
||||
if topic != nil { try? container.encode(topic, forKey: .topic) }
|
||||
if isDeleted != nil { try? container.encode(isDeleted, forKey: .isDeleted) }
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(topic, forKey: .topic)
|
||||
if deletedOn != nil { try? container.encode(deletedOn, forKey: .deletedOn) }
|
||||
if lastMessageReceivedOn != nil { try? container.encode(lastMessageReceivedOn, forKey: .lastMessageReceivedOn) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,11 +16,11 @@ import Foundation
|
|||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
/// Collection of chat threads.
|
||||
public struct ChatThreadsInfoCollection: Codable, Equatable {
|
||||
public struct ChatThreadsInfoCollection: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// Collection of chat threads.
|
||||
public let value: [ChatThreadInfo]?
|
||||
public let value: [ChatThreadInfo]
|
||||
/// If there are more chat threads that can be retrieved, the next link will be populated.
|
||||
public let nextLink: String?
|
||||
|
||||
|
@ -31,7 +31,7 @@ public struct ChatThreadsInfoCollection: Codable, Equatable {
|
|||
/// - value: Collection of chat threads.
|
||||
/// - nextLink: If there are more chat threads that can be retrieved, the next link will be populated.
|
||||
public init(
|
||||
value: [ChatThreadInfo]? = nil, nextLink: String? = nil
|
||||
value: [ChatThreadInfo], nextLink: String? = nil
|
||||
) {
|
||||
self.value = value
|
||||
self.nextLink = nextLink
|
||||
|
@ -47,14 +47,14 @@ public struct ChatThreadsInfoCollection: Codable, Equatable {
|
|||
/// Initialize a `ChatThreadsInfoCollection` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.value = try? container.decode([ChatThreadInfo].self, forKey: .value)
|
||||
self.value = try container.decode([ChatThreadInfo].self, forKey: .value)
|
||||
self.nextLink = try? container.decode(String.self, forKey: .nextLink)
|
||||
}
|
||||
|
||||
/// Encode a `ChatThreadsInfoCollection` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
if value != nil { try? container.encode(value, forKey: .value) }
|
||||
try container.encode(value, forKey: .value)
|
||||
if nextLink != nil { try? container.encode(nextLink, forKey: .nextLink) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
// --------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for
|
||||
// license information.
|
||||
//
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
// Changes may cause incorrect behavior and will be lost if the code is
|
||||
// regenerated.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCore
|
||||
import Foundation
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
/// The Communication Services error.
|
||||
public final class CommunicationError: Codable, Swift.Error {
|
||||
// MARK: Properties
|
||||
|
||||
/// The error code.
|
||||
public let code: String
|
||||
/// The error message.
|
||||
public let message: String
|
||||
/// The error target.
|
||||
public let target: String?
|
||||
/// Further details about specific errors that led to this error.
|
||||
public let details: [CommunicationError?]?
|
||||
/// The inner error if any.
|
||||
public let innerError: CommunicationError?
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initialize a `CommunicationError` structure.
|
||||
/// - Parameters:
|
||||
/// - code: The error code.
|
||||
/// - message: The error message.
|
||||
/// - target: The error target.
|
||||
/// - details: Further details about specific errors that led to this error.
|
||||
/// - innerError: The inner error if any.
|
||||
public init(
|
||||
code: String, message: String, target: String? = nil, details: [CommunicationError?]? = nil,
|
||||
innerError: CommunicationError? = nil
|
||||
) {
|
||||
self.code = code
|
||||
self.message = message
|
||||
self.target = target
|
||||
self.details = details
|
||||
self.innerError = innerError
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case code = "code"
|
||||
case message = "message"
|
||||
case target = "target"
|
||||
case details = "details"
|
||||
case innerError = "innererror"
|
||||
}
|
||||
|
||||
/// Initialize a `CommunicationError` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.code = try container.decode(String.self, forKey: .code)
|
||||
self.message = try container.decode(String.self, forKey: .message)
|
||||
self.target = try? container.decode(String.self, forKey: .target)
|
||||
self.details = try? container.decode([CommunicationError?].self, forKey: .details)
|
||||
self.innerError = try? container.decode(CommunicationError.self, forKey: .innerError)
|
||||
}
|
||||
|
||||
/// Encode a `CommunicationError` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(code, forKey: .code)
|
||||
try container.encode(message, forKey: .message)
|
||||
if target != nil { try? container.encode(target, forKey: .target) }
|
||||
if details != nil { try? container.encode(details, forKey: .details) }
|
||||
if innerError != nil { try? container.encode(innerError, forKey: .innerError) }
|
||||
}
|
||||
}
|
|
@ -15,39 +15,39 @@ import Foundation
|
|||
// swiftlint:disable line_length
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
/// Thread members to be added to the thread.
|
||||
public struct AddChatThreadMembersRequest: Codable, Equatable {
|
||||
/// The Communication Services error.
|
||||
public struct CommunicationErrorResponse: Codable, Swift.Error {
|
||||
// MARK: Properties
|
||||
|
||||
/// Members to add to a chat thread.
|
||||
public let members: [ChatThreadMember]
|
||||
/// The Communication Services error.
|
||||
public let error: CommunicationError
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initialize a `AddChatThreadMembersRequest` structure.
|
||||
/// Initialize a `CommunicationErrorResponse` structure.
|
||||
/// - Parameters:
|
||||
/// - members: Members to add to a chat thread.
|
||||
/// - error: The Communication Services error.
|
||||
public init(
|
||||
members: [ChatThreadMember]
|
||||
error: CommunicationError
|
||||
) {
|
||||
self.members = members
|
||||
self.error = error
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case members = "members"
|
||||
case error = "error"
|
||||
}
|
||||
|
||||
/// Initialize a `AddChatThreadMembersRequest` structure from decoder
|
||||
/// Initialize a `CommunicationErrorResponse` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.members = try container.decode([ChatThreadMember].self, forKey: .members)
|
||||
self.error = try container.decode(CommunicationError.self, forKey: .error)
|
||||
}
|
||||
|
||||
/// Encode a `AddChatThreadMembersRequest` structure
|
||||
/// Encode a `CommunicationErrorResponse` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(members, forKey: .members)
|
||||
try container.encode(error, forKey: .error)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
// --------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for
|
||||
// license information.
|
||||
//
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
// Changes may cause incorrect behavior and will be lost if the code is
|
||||
// regenerated.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCore
|
||||
import Foundation
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
/// Errors encountered during the creation of the chat thread.
|
||||
public struct CreateChatThreadErrors: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// The participants that failed to be added to the chat thread.
|
||||
public let invalidParticipants: [CommunicationError?]?
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initialize a `CreateChatThreadErrors` structure.
|
||||
/// - Parameters:
|
||||
/// - invalidParticipants: The participants that failed to be added to the chat thread.
|
||||
public init(
|
||||
invalidParticipants: [CommunicationError?]? = nil
|
||||
) {
|
||||
self.invalidParticipants = invalidParticipants
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case invalidParticipants = "invalidParticipants"
|
||||
}
|
||||
|
||||
/// Initialize a `CreateChatThreadErrors` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.invalidParticipants = try? container.decode([CommunicationError?].self, forKey: .invalidParticipants)
|
||||
}
|
||||
|
||||
/// Encode a `CreateChatThreadErrors` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
if invalidParticipants != nil { try? container.encode(invalidParticipants, forKey: .invalidParticipants) }
|
||||
}
|
||||
}
|
|
@ -16,45 +16,45 @@ import Foundation
|
|||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
/// Request payload for creating a chat thread.
|
||||
public struct CreateChatThreadRequest: Codable, Equatable {
|
||||
public struct CreateChatThreadRequest: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// The chat thread topic.
|
||||
public let topic: String
|
||||
/// Members to be added to the chat thread.
|
||||
public let members: [ChatThreadMember]
|
||||
/// Participants to be added to the chat thread.
|
||||
public let participants: [ChatParticipant]
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initialize a `CreateChatThreadRequest` structure.
|
||||
/// - Parameters:
|
||||
/// - topic: The chat thread topic.
|
||||
/// - members: Members to be added to the chat thread.
|
||||
/// - participants: Participants to be added to the chat thread.
|
||||
public init(
|
||||
topic: String, members: [ChatThreadMember]
|
||||
topic: String, participants: [ChatParticipant]
|
||||
) {
|
||||
self.topic = topic
|
||||
self.members = members
|
||||
self.participants = participants
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case topic = "topic"
|
||||
case members = "members"
|
||||
case participants = "participants"
|
||||
}
|
||||
|
||||
/// Initialize a `CreateChatThreadRequest` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.topic = try container.decode(String.self, forKey: .topic)
|
||||
self.members = try container.decode([ChatThreadMember].self, forKey: .members)
|
||||
self.participants = try container.decode([ChatParticipant].self, forKey: .participants)
|
||||
}
|
||||
|
||||
/// Encode a `CreateChatThreadRequest` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(topic, forKey: .topic)
|
||||
try container.encode(members, forKey: .members)
|
||||
try container.encode(participants, forKey: .participants)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
// --------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for
|
||||
// license information.
|
||||
//
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
// Changes may cause incorrect behavior and will be lost if the code is
|
||||
// regenerated.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCore
|
||||
import Foundation
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
/// Result of the create chat thread operation.
|
||||
public struct CreateChatThreadResult: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// Chat thread.
|
||||
public let chatThread: ChatThread?
|
||||
/// Errors encountered during the creation of the chat thread.
|
||||
public let errors: CreateChatThreadErrors?
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initialize a `CreateChatThreadResult` structure.
|
||||
/// - Parameters:
|
||||
/// - chatThread: Chat thread.
|
||||
/// - errors: Errors encountered during the creation of the chat thread.
|
||||
public init(
|
||||
chatThread: ChatThread? = nil, errors: CreateChatThreadErrors? = nil
|
||||
) {
|
||||
self.chatThread = chatThread
|
||||
self.errors = errors
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case chatThread = "chatThread"
|
||||
case errors = "errors"
|
||||
}
|
||||
|
||||
/// Initialize a `CreateChatThreadResult` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.chatThread = try? container.decode(ChatThread.self, forKey: .chatThread)
|
||||
self.errors = try? container.decode(CreateChatThreadErrors.self, forKey: .errors)
|
||||
}
|
||||
|
||||
/// Encode a `CreateChatThreadResult` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
if chatThread != nil { try? container.encode(chatThread, forKey: .chatThread) }
|
||||
if errors != nil { try? container.encode(errors, forKey: .errors) }
|
||||
}
|
||||
}
|
|
@ -11,32 +11,50 @@
|
|||
import AzureCore
|
||||
import Foundation
|
||||
|
||||
/// The chat message priority.
|
||||
public enum ChatMessagePriority: RequestStringConvertible, Codable, Equatable {
|
||||
/// The chat message type.
|
||||
public enum ChatMessageType: RequestStringConvertible, Codable, Equatable {
|
||||
/// Custom value for unrecognized enum values
|
||||
case custom(String)
|
||||
|
||||
case normal
|
||||
case text
|
||||
|
||||
case high
|
||||
case html
|
||||
|
||||
case topicUpdated
|
||||
|
||||
case participantAdded
|
||||
|
||||
case participantRemoved
|
||||
|
||||
public var requestString: String {
|
||||
switch self {
|
||||
case let .custom(val):
|
||||
return val
|
||||
case .normal:
|
||||
return "Normal"
|
||||
case .high:
|
||||
return "High"
|
||||
case .text:
|
||||
return "text"
|
||||
case .html:
|
||||
return "html"
|
||||
case .topicUpdated:
|
||||
return "topicUpdated"
|
||||
case .participantAdded:
|
||||
return "participantAdded"
|
||||
case .participantRemoved:
|
||||
return "participantRemoved"
|
||||
}
|
||||
}
|
||||
|
||||
public init(_ val: String) {
|
||||
switch val.lowercased() {
|
||||
case "normal":
|
||||
self = .normal
|
||||
case "high":
|
||||
self = .high
|
||||
case "text":
|
||||
self = .text
|
||||
case "html":
|
||||
self = .html
|
||||
case "topicupdated":
|
||||
self = .topicUpdated
|
||||
case "participantadded":
|
||||
self = .participantAdded
|
||||
case "participantremoved":
|
||||
self = .participantRemoved
|
||||
default:
|
||||
self = .custom(val)
|
||||
}
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
// --------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for
|
||||
// license information.
|
||||
//
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
// Changes may cause incorrect behavior and will be lost if the code is
|
||||
// regenerated.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCore
|
||||
import Foundation
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
public struct ErrorType: Codable, Swift.Error {
|
||||
// MARK: Properties
|
||||
|
||||
public let code: String?
|
||||
|
||||
public let message: String?
|
||||
|
||||
public let target: String?
|
||||
|
||||
public let innerErrors: [ErrorType]?
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initialize a `ErrorType` structure.
|
||||
/// - Parameters:
|
||||
/// - code:
|
||||
/// - message:
|
||||
/// - target:
|
||||
/// - innerErrors:
|
||||
public init(
|
||||
code: String? = nil, message: String? = nil, target: String? = nil, innerErrors: [ErrorType]? = nil
|
||||
) {
|
||||
self.code = code
|
||||
self.message = message
|
||||
self.target = target
|
||||
self.innerErrors = innerErrors
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case code = "code"
|
||||
case message = "message"
|
||||
case target = "target"
|
||||
case innerErrors = "innerErrors"
|
||||
}
|
||||
|
||||
/// Initialize a `ErrorType` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.code = try? container.decode(String.self, forKey: .code)
|
||||
self.message = try? container.decode(String.self, forKey: .message)
|
||||
self.target = try? container.decode(String.self, forKey: .target)
|
||||
self.innerErrors = try? container.decode([ErrorType].self, forKey: .innerErrors)
|
||||
}
|
||||
|
||||
/// Encode a `ErrorType` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
if code != nil { try? container.encode(code, forKey: .code) }
|
||||
if message != nil { try? container.encode(message, forKey: .message) }
|
||||
if target != nil { try? container.encode(target, forKey: .target) }
|
||||
if innerErrors != nil { try? container.encode(innerErrors, forKey: .innerErrors) }
|
||||
}
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
// --------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for
|
||||
// license information.
|
||||
//
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
// Changes may cause incorrect behavior and will be lost if the code is
|
||||
// regenerated.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCore
|
||||
import Foundation
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
public struct IndividualStatusResponse: Codable, Equatable {
|
||||
// MARK: Properties
|
||||
|
||||
/// Identifies the resource to which the individual status corresponds.
|
||||
public let id: String?
|
||||
/// The status code of the resource operation.
|
||||
///
|
||||
/// Possible values include:
|
||||
/// 200 for a successful update or delete,
|
||||
/// 201 for successful creation,
|
||||
/// 400 for a malformed input,
|
||||
/// 403 for lacking permission to execute the operation,
|
||||
/// 404 for resource not found.
|
||||
public let statusCode: Int32?
|
||||
/// The message explaining why the operation failed for the resource identified by the key; null if the operation succeeded.
|
||||
public let message: String?
|
||||
/// Identifies the type of the resource to which the individual status corresponds.
|
||||
public let type: String?
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initialize a `IndividualStatusResponse` structure.
|
||||
/// - Parameters:
|
||||
/// - id: Identifies the resource to which the individual status corresponds.
|
||||
/// - statusCode: The status code of the resource operation.
|
||||
///
|
||||
/// Possible values include:
|
||||
/// 200 for a successful update or delete,
|
||||
/// 201 for successful creation,
|
||||
/// 400 for a malformed input,
|
||||
/// 403 for lacking permission to execute the operation,
|
||||
/// 404 for resource not found.
|
||||
/// - message: The message explaining why the operation failed for the resource identified by the key; null if the operation succeeded.
|
||||
/// - type: Identifies the type of the resource to which the individual status corresponds.
|
||||
public init(
|
||||
id: String? = nil, statusCode: Int32? = nil, message: String? = nil, type: String? = nil
|
||||
) {
|
||||
self.id = id
|
||||
self.statusCode = statusCode
|
||||
self.message = message
|
||||
self.type = type
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id = "id"
|
||||
case statusCode = "statusCode"
|
||||
case message = "message"
|
||||
case type = "type"
|
||||
}
|
||||
|
||||
/// Initialize a `IndividualStatusResponse` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.id = try? container.decode(String.self, forKey: .id)
|
||||
self.statusCode = try? container.decode(Int32.self, forKey: .statusCode)
|
||||
self.message = try? container.decode(String.self, forKey: .message)
|
||||
self.type = try? container.decode(String.self, forKey: .type)
|
||||
}
|
||||
|
||||
/// Encode a `IndividualStatusResponse` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
if id != nil { try? container.encode(id, forKey: .id) }
|
||||
if statusCode != nil { try? container.encode(statusCode, forKey: .statusCode) }
|
||||
if message != nil { try? container.encode(message, forKey: .message) }
|
||||
if type != nil { try? container.encode(type, forKey: .type) }
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
// --------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for
|
||||
// license information.
|
||||
//
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
// Changes may cause incorrect behavior and will be lost if the code is
|
||||
// regenerated.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCore
|
||||
import Foundation
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
/// A read receipt indicates the time a chat message was read by a recipient.
|
||||
public struct ReadReceipt: Codable, Equatable {
|
||||
// MARK: Properties
|
||||
|
||||
/// Read receipt sender id.
|
||||
public let senderId: String?
|
||||
/// Id for the chat message that has been read. This id is generated by the server.
|
||||
public let chatMessageId: String?
|
||||
/// Read receipt timestamp. The timestamp is in ISO8601 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public let readOn: Iso8601Date?
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initialize a `ReadReceipt` structure.
|
||||
/// - Parameters:
|
||||
/// - senderId: Read receipt sender id.
|
||||
/// - chatMessageId: Id for the chat message that has been read. This id is generated by the server.
|
||||
/// - readOn: Read receipt timestamp. The timestamp is in ISO8601 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public init(
|
||||
senderId: String? = nil, chatMessageId: String? = nil, readOn: Iso8601Date? = nil
|
||||
) {
|
||||
self.senderId = senderId
|
||||
self.chatMessageId = chatMessageId
|
||||
self.readOn = readOn
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case senderId = "senderId"
|
||||
case chatMessageId = "chatMessageId"
|
||||
case readOn = "readOn"
|
||||
}
|
||||
|
||||
/// Initialize a `ReadReceipt` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.senderId = try? container.decode(String.self, forKey: .senderId)
|
||||
self.chatMessageId = try? container.decode(String.self, forKey: .chatMessageId)
|
||||
self.readOn = try? container.decode(Iso8601Date.self, forKey: .readOn)
|
||||
}
|
||||
|
||||
/// Encode a `ReadReceipt` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
if senderId != nil { try? container.encode(senderId, forKey: .senderId) }
|
||||
if chatMessageId != nil { try? container.encode(chatMessageId, forKey: .chatMessageId) }
|
||||
if readOn != nil { try? container.encode(readOn, forKey: .readOn) }
|
||||
}
|
||||
}
|
|
@ -16,52 +16,52 @@ import Foundation
|
|||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
/// Details of the message to send.
|
||||
public struct SendChatMessageRequest: Codable, Equatable {
|
||||
public struct SendChatMessageRequest: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// The chat message priority.
|
||||
public let priority: ChatMessagePriority?
|
||||
/// Chat message content.
|
||||
public let content: String
|
||||
/// The display name of the chat message sender. This property is used to populate sender name for push notifications.
|
||||
public let senderDisplayName: String?
|
||||
/// The chat message type.
|
||||
public let type: ChatMessageType?
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initialize a `SendChatMessageRequest` structure.
|
||||
/// - Parameters:
|
||||
/// - priority: The chat message priority.
|
||||
/// - content: Chat message content.
|
||||
/// - senderDisplayName: The display name of the chat message sender. This property is used to populate sender name for push notifications.
|
||||
/// - type: The chat message type.
|
||||
public init(
|
||||
priority: ChatMessagePriority? = nil, content: String, senderDisplayName: String? = nil
|
||||
content: String, senderDisplayName: String? = nil, type: ChatMessageType? = nil
|
||||
) {
|
||||
self.priority = priority
|
||||
self.content = content
|
||||
self.senderDisplayName = senderDisplayName
|
||||
self.type = type
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case priority = "priority"
|
||||
case content = "content"
|
||||
case senderDisplayName = "senderDisplayName"
|
||||
case type = "type"
|
||||
}
|
||||
|
||||
/// Initialize a `SendChatMessageRequest` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.priority = try? container.decode(ChatMessagePriority.self, forKey: .priority)
|
||||
self.content = try container.decode(String.self, forKey: .content)
|
||||
self.senderDisplayName = try? container.decode(String.self, forKey: .senderDisplayName)
|
||||
self.type = try? container.decode(ChatMessageType.self, forKey: .type)
|
||||
}
|
||||
|
||||
/// Encode a `SendChatMessageRequest` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
if priority != nil { try? container.encode(priority, forKey: .priority) }
|
||||
try container.encode(content, forKey: .content)
|
||||
if senderDisplayName != nil { try? container.encode(senderDisplayName, forKey: .senderDisplayName) }
|
||||
if type != nil { try? container.encode(type, forKey: .type) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,11 +16,11 @@ import Foundation
|
|||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
/// Result of the send message operation.
|
||||
public struct SendChatMessageResult: Codable, Equatable {
|
||||
public struct SendChatMessageResult: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// A server-generated message id.
|
||||
public let id: String?
|
||||
public let id: String
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
|
@ -28,7 +28,7 @@ public struct SendChatMessageResult: Codable, Equatable {
|
|||
/// - Parameters:
|
||||
/// - id: A server-generated message id.
|
||||
public init(
|
||||
id: String? = nil
|
||||
id: String
|
||||
) {
|
||||
self.id = id
|
||||
}
|
||||
|
@ -42,12 +42,12 @@ public struct SendChatMessageResult: Codable, Equatable {
|
|||
/// Initialize a `SendChatMessageResult` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.id = try? container.decode(String.self, forKey: .id)
|
||||
self.id = try container.decode(String.self, forKey: .id)
|
||||
}
|
||||
|
||||
/// Encode a `SendChatMessageResult` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
if id != nil { try? container.encode(id, forKey: .id) }
|
||||
try container.encode(id, forKey: .id)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import Foundation
|
|||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
/// Request payload for sending a read receipt.
|
||||
public struct SendReadReceiptRequest: Codable, Equatable {
|
||||
public struct SendReadReceiptRequest: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// Id of the latest chat message read by the user.
|
||||
|
|
|
@ -15,45 +15,39 @@ import Foundation
|
|||
// swiftlint:disable line_length
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
public struct UpdateChatMessageRequest: Codable, Equatable {
|
||||
/// Request payload for updating a chat message.
|
||||
public struct UpdateChatMessageRequest: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// Chat message content.
|
||||
public let content: String?
|
||||
/// The chat message priority.
|
||||
public let priority: ChatMessagePriority?
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initialize a `UpdateChatMessageRequest` structure.
|
||||
/// - Parameters:
|
||||
/// - content: Chat message content.
|
||||
/// - priority: The chat message priority.
|
||||
public init(
|
||||
content: String? = nil, priority: ChatMessagePriority? = nil
|
||||
content: String? = nil
|
||||
) {
|
||||
self.content = content
|
||||
self.priority = priority
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case content = "content"
|
||||
case priority = "priority"
|
||||
}
|
||||
|
||||
/// Initialize a `UpdateChatMessageRequest` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.content = try? container.decode(String.self, forKey: .content)
|
||||
self.priority = try? container.decode(ChatMessagePriority.self, forKey: .priority)
|
||||
}
|
||||
|
||||
/// Encode a `UpdateChatMessageRequest` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
if content != nil { try? container.encode(content, forKey: .content) }
|
||||
if priority != nil { try? container.encode(priority, forKey: .priority) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,8 @@ import Foundation
|
|||
// swiftlint:disable line_length
|
||||
// swiftlint:disable cyclomatic_complexity
|
||||
|
||||
public struct UpdateChatThreadRequest: Codable, Equatable {
|
||||
/// Request payload for updating a chat thread.
|
||||
public struct UpdateChatThreadRequest: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// Chat thread topic.
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
// --------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for
|
||||
// license information.
|
||||
//
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
// Changes may cause incorrect behavior and will be lost if the code is
|
||||
// regenerated.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCore
|
||||
import Foundation
|
||||
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
|
||||
extension AzureCommunicationChatService {
|
||||
/// User-configurable options for the `AzureCommunicationChatService.RemoveChatThreadMember` operation.
|
||||
public struct RemoveChatThreadMemberOptions: RequestOptions {
|
||||
/// A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
/// Highly recommended for correlating client-side activites with requests received by the server.
|
||||
public let clientRequestId: String?
|
||||
|
||||
/// A token used to make a best-effort attempt at canceling a request.
|
||||
public let cancellationToken: CancellationToken?
|
||||
|
||||
/// A dispatch queue on which to call the completion handler. Defaults to `DispatchQueue.main`.
|
||||
public var dispatchQueue: DispatchQueue?
|
||||
|
||||
/// A `PipelineContext` object to associate with the request.
|
||||
public var context: PipelineContext?
|
||||
|
||||
/// Initialize a `RemoveChatThreadMemberOptions` structure.
|
||||
/// - Parameters:
|
||||
/// - clientRequestId: A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
/// - cancellationToken: A token used to make a best-effort attempt at canceling a request.
|
||||
/// - dispatchQueue: A dispatch queue on which to call the completion handler. Defaults to `DispatchQueue.main`.
|
||||
/// - context: A `PipelineContext` object to associate with the request.
|
||||
public init(
|
||||
clientRequestId: String? = nil,
|
||||
cancellationToken: CancellationToken? = nil,
|
||||
dispatchQueue: DispatchQueue? = nil,
|
||||
context: PipelineContext? = nil
|
||||
) {
|
||||
self.clientRequestId = clientRequestId
|
||||
self.cancellationToken = cancellationToken
|
||||
self.dispatchQueue = dispatchQueue
|
||||
self.context = context
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,9 +15,12 @@ import Foundation
|
|||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
|
||||
extension AzureCommunicationChatService {
|
||||
/// User-configurable options for the `AzureCommunicationChatService.ListChatThreadMembers` operation.
|
||||
public struct ListChatThreadMembersOptions: RequestOptions {
|
||||
public extension Chat {
|
||||
/// User-configurable options for the `AzureCommunicationChatService.CreateChatThread` operation.
|
||||
struct CreateChatThreadOptions: RequestOptions {
|
||||
/// If specified, the client directs that the request is repeatable; that is, that the client can make the request multiple times with the same Repeatability-Request-ID and get back an appropriate response without the server executing the request multiple times. The value of the Repeatability-Request-ID is an opaque string representing a client-generated, globally unique for all time, identifier for the request. It is recommended to use version 4 (random) UUIDs.
|
||||
public let repeatabilityRequestID: String?
|
||||
|
||||
/// A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
/// Highly recommended for correlating client-side activites with requests received by the server.
|
||||
public let clientRequestId: String?
|
||||
|
@ -31,18 +34,21 @@ extension AzureCommunicationChatService {
|
|||
/// A `PipelineContext` object to associate with the request.
|
||||
public var context: PipelineContext?
|
||||
|
||||
/// Initialize a `ListChatThreadMembersOptions` structure.
|
||||
/// Initialize a `CreateChatThreadOptions` structure.
|
||||
/// - Parameters:
|
||||
/// - repeatabilityRequestID: If specified, the client directs that the request is repeatable; that is, that the client can make the request multiple times with the same Repeatability-Request-ID and get back an appropriate response without the server executing the request multiple times. The value of the Repeatability-Request-ID is an opaque string representing a client-generated, globally unique for all time, identifier for the request. It is recommended to use version 4 (random) UUIDs.
|
||||
/// - clientRequestId: A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
/// - cancellationToken: A token used to make a best-effort attempt at canceling a request.
|
||||
/// - dispatchQueue: A dispatch queue on which to call the completion handler. Defaults to `DispatchQueue.main`.
|
||||
/// - context: A `PipelineContext` object to associate with the request.
|
||||
public init(
|
||||
repeatabilityRequestID: String? = nil,
|
||||
clientRequestId: String? = nil,
|
||||
cancellationToken: CancellationToken? = nil,
|
||||
dispatchQueue: DispatchQueue? = nil,
|
||||
context: PipelineContext? = nil
|
||||
) {
|
||||
self.repeatabilityRequestID = repeatabilityRequestID
|
||||
self.clientRequestId = clientRequestId
|
||||
self.cancellationToken = cancellationToken
|
||||
self.dispatchQueue = dispatchQueue
|
|
@ -15,9 +15,9 @@ import Foundation
|
|||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
|
||||
extension AzureCommunicationChatService {
|
||||
public extension Chat {
|
||||
/// User-configurable options for the `AzureCommunicationChatService.DeleteChatThread` operation.
|
||||
public struct DeleteChatThreadOptions: RequestOptions {
|
||||
struct DeleteChatThreadOptions: RequestOptions {
|
||||
/// A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
/// Highly recommended for correlating client-side activites with requests received by the server.
|
||||
public let clientRequestId: String?
|
|
@ -15,9 +15,9 @@ import Foundation
|
|||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
|
||||
extension AzureCommunicationChatService {
|
||||
public extension Chat {
|
||||
/// User-configurable options for the `AzureCommunicationChatService.GetChatThread` operation.
|
||||
public struct GetChatThreadOptions: RequestOptions {
|
||||
struct GetChatThreadOptions: RequestOptions {
|
||||
/// A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
/// Highly recommended for correlating client-side activites with requests received by the server.
|
||||
public let clientRequestId: String?
|
|
@ -15,12 +15,12 @@ import Foundation
|
|||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
|
||||
extension AzureCommunicationChatService {
|
||||
public extension Chat {
|
||||
/// User-configurable options for the `AzureCommunicationChatService.ListChatThreads` operation.
|
||||
public struct ListChatThreadsOptions: RequestOptions {
|
||||
struct ListChatThreadsOptions: RequestOptions {
|
||||
/// The maximum number of chat threads returned per page.
|
||||
public let maxPageSize: Int32?
|
||||
/// The earliest point in time to get chat threads up to. The timestamp should be in ISO8601 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
/// The earliest point in time to get chat threads up to. The timestamp should be in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public let startTime: Iso8601Date?
|
||||
|
||||
/// A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
|
@ -39,7 +39,7 @@ extension AzureCommunicationChatService {
|
|||
/// Initialize a `ListChatThreadsOptions` structure.
|
||||
/// - Parameters:
|
||||
/// - maxPageSize: The maximum number of chat threads returned per page.
|
||||
/// - startTime: The earliest point in time to get chat threads up to. The timestamp should be in ISO8601 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
/// - startTime: The earliest point in time to get chat threads up to. The timestamp should be in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
/// - clientRequestId: A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
/// - cancellationToken: A token used to make a best-effort attempt at canceling a request.
|
||||
/// - dispatchQueue: A dispatch queue on which to call the completion handler. Defaults to `DispatchQueue.main`.
|
|
@ -0,0 +1,52 @@
|
|||
// --------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for
|
||||
// license information.
|
||||
//
|
||||
// Code generated by Microsoft (R) AutoRest Code Generator.
|
||||
// Changes may cause incorrect behavior and will be lost if the code is
|
||||
// regenerated.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCore
|
||||
import Foundation
|
||||
|
||||
// swiftlint:disable superfluous_disable_command
|
||||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
|
||||
public extension ChatThreadOperation {
|
||||
/// User-configurable options for the `AzureCommunicationChatService.AddChatParticipants` operation.
|
||||
struct AddChatParticipantsOptions: RequestOptions {
|
||||
/// A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
/// Highly recommended for correlating client-side activites with requests received by the server.
|
||||
public let clientRequestId: String?
|
||||
|
||||
/// A token used to make a best-effort attempt at canceling a request.
|
||||
public let cancellationToken: CancellationToken?
|
||||
|
||||
/// A dispatch queue on which to call the completion handler. Defaults to `DispatchQueue.main`.
|
||||
public var dispatchQueue: DispatchQueue?
|
||||
|
||||
/// A `PipelineContext` object to associate with the request.
|
||||
public var context: PipelineContext?
|
||||
|
||||
/// Initialize a `AddChatParticipantsOptions` structure.
|
||||
/// - Parameters:
|
||||
/// - clientRequestId: A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
/// - cancellationToken: A token used to make a best-effort attempt at canceling a request.
|
||||
/// - dispatchQueue: A dispatch queue on which to call the completion handler. Defaults to `DispatchQueue.main`.
|
||||
/// - context: A `PipelineContext` object to associate with the request.
|
||||
public init(
|
||||
clientRequestId: String? = nil,
|
||||
cancellationToken: CancellationToken? = nil,
|
||||
dispatchQueue: DispatchQueue? = nil,
|
||||
context: PipelineContext? = nil
|
||||
) {
|
||||
self.clientRequestId = clientRequestId
|
||||
self.cancellationToken = cancellationToken
|
||||
self.dispatchQueue = dispatchQueue
|
||||
self.context = context
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,9 +15,9 @@ import Foundation
|
|||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
|
||||
extension AzureCommunicationChatService {
|
||||
public extension ChatThreadOperation {
|
||||
/// User-configurable options for the `AzureCommunicationChatService.DeleteChatMessage` operation.
|
||||
public struct DeleteChatMessageOptions: RequestOptions {
|
||||
struct DeleteChatMessageOptions: RequestOptions {
|
||||
/// A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
/// Highly recommended for correlating client-side activites with requests received by the server.
|
||||
public let clientRequestId: String?
|
|
@ -15,9 +15,9 @@ import Foundation
|
|||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
|
||||
extension AzureCommunicationChatService {
|
||||
public extension ChatThreadOperation {
|
||||
/// User-configurable options for the `AzureCommunicationChatService.GetChatMessage` operation.
|
||||
public struct GetChatMessageOptions: RequestOptions {
|
||||
struct GetChatMessageOptions: RequestOptions {
|
||||
/// A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
/// Highly recommended for correlating client-side activites with requests received by the server.
|
||||
public let clientRequestId: String?
|
|
@ -15,12 +15,12 @@ import Foundation
|
|||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
|
||||
extension AzureCommunicationChatService {
|
||||
public extension ChatThreadOperation {
|
||||
/// User-configurable options for the `AzureCommunicationChatService.ListChatMessages` operation.
|
||||
public struct ListChatMessagesOptions: RequestOptions {
|
||||
struct ListChatMessagesOptions: RequestOptions {
|
||||
/// The maximum number of messages to be returned per page.
|
||||
public let maxPageSize: Int32?
|
||||
/// The earliest point in time to get messages up to. The timestamp should be in ISO8601 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
/// The earliest point in time to get messages up to. The timestamp should be in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public let startTime: Iso8601Date?
|
||||
|
||||
/// A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
|
@ -39,7 +39,7 @@ extension AzureCommunicationChatService {
|
|||
/// Initialize a `ListChatMessagesOptions` structure.
|
||||
/// - Parameters:
|
||||
/// - maxPageSize: The maximum number of messages to be returned per page.
|
||||
/// - startTime: The earliest point in time to get messages up to. The timestamp should be in ISO8601 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
/// - startTime: The earliest point in time to get messages up to. The timestamp should be in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
/// - clientRequestId: A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
/// - cancellationToken: A token used to make a best-effort attempt at canceling a request.
|
||||
/// - dispatchQueue: A dispatch queue on which to call the completion handler. Defaults to `DispatchQueue.main`.
|
|
@ -15,9 +15,14 @@ import Foundation
|
|||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
|
||||
extension AzureCommunicationChatService {
|
||||
/// User-configurable options for the `AzureCommunicationChatService.AddChatThreadMembers` operation.
|
||||
public struct AddChatThreadMembersOptions: RequestOptions {
|
||||
public extension ChatThreadOperation {
|
||||
/// User-configurable options for the `AzureCommunicationChatService.ListChatParticipants` operation.
|
||||
struct ListChatParticipantsOptions: RequestOptions {
|
||||
/// The maximum number of participants to be returned per page.
|
||||
public let maxPageSize: Int32?
|
||||
/// Skips participants up to a specified position in response.
|
||||
public let skip: Int32?
|
||||
|
||||
/// A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
/// Highly recommended for correlating client-side activites with requests received by the server.
|
||||
public let clientRequestId: String?
|
||||
|
@ -31,18 +36,24 @@ extension AzureCommunicationChatService {
|
|||
/// A `PipelineContext` object to associate with the request.
|
||||
public var context: PipelineContext?
|
||||
|
||||
/// Initialize a `AddChatThreadMembersOptions` structure.
|
||||
/// Initialize a `ListChatParticipantsOptions` structure.
|
||||
/// - Parameters:
|
||||
/// - maxPageSize: The maximum number of participants to be returned per page.
|
||||
/// - skip: Skips participants up to a specified position in response.
|
||||
/// - clientRequestId: A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
/// - cancellationToken: A token used to make a best-effort attempt at canceling a request.
|
||||
/// - dispatchQueue: A dispatch queue on which to call the completion handler. Defaults to `DispatchQueue.main`.
|
||||
/// - context: A `PipelineContext` object to associate with the request.
|
||||
public init(
|
||||
maxPageSize: Int32? = nil,
|
||||
skip: Int32? = nil,
|
||||
clientRequestId: String? = nil,
|
||||
cancellationToken: CancellationToken? = nil,
|
||||
dispatchQueue: DispatchQueue? = nil,
|
||||
context: PipelineContext? = nil
|
||||
) {
|
||||
self.maxPageSize = maxPageSize
|
||||
self.skip = skip
|
||||
self.clientRequestId = clientRequestId
|
||||
self.cancellationToken = cancellationToken
|
||||
self.dispatchQueue = dispatchQueue
|
|
@ -15,9 +15,14 @@ import Foundation
|
|||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
|
||||
extension AzureCommunicationChatService {
|
||||
public extension ChatThreadOperation {
|
||||
/// User-configurable options for the `AzureCommunicationChatService.ListChatReadReceipts` operation.
|
||||
public struct ListChatReadReceiptsOptions: RequestOptions {
|
||||
struct ListChatReadReceiptsOptions: RequestOptions {
|
||||
/// The maximum number of chat message read receipts to be returned per page.
|
||||
public let maxPageSize: Int32?
|
||||
/// Skips chat message read receipts up to a specified position in response.
|
||||
public let skip: Int32?
|
||||
|
||||
/// A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
/// Highly recommended for correlating client-side activites with requests received by the server.
|
||||
public let clientRequestId: String?
|
||||
|
@ -33,16 +38,22 @@ extension AzureCommunicationChatService {
|
|||
|
||||
/// Initialize a `ListChatReadReceiptsOptions` structure.
|
||||
/// - Parameters:
|
||||
/// - maxPageSize: The maximum number of chat message read receipts to be returned per page.
|
||||
/// - skip: Skips chat message read receipts up to a specified position in response.
|
||||
/// - clientRequestId: A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
/// - cancellationToken: A token used to make a best-effort attempt at canceling a request.
|
||||
/// - dispatchQueue: A dispatch queue on which to call the completion handler. Defaults to `DispatchQueue.main`.
|
||||
/// - context: A `PipelineContext` object to associate with the request.
|
||||
public init(
|
||||
maxPageSize: Int32? = nil,
|
||||
skip: Int32? = nil,
|
||||
clientRequestId: String? = nil,
|
||||
cancellationToken: CancellationToken? = nil,
|
||||
dispatchQueue: DispatchQueue? = nil,
|
||||
context: PipelineContext? = nil
|
||||
) {
|
||||
self.maxPageSize = maxPageSize
|
||||
self.skip = skip
|
||||
self.clientRequestId = clientRequestId
|
||||
self.cancellationToken = cancellationToken
|
||||
self.dispatchQueue = dispatchQueue
|
|
@ -15,9 +15,9 @@ import Foundation
|
|||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
|
||||
extension AzureCommunicationChatService {
|
||||
/// User-configurable options for the `AzureCommunicationChatService.CreateChatThread` operation.
|
||||
public struct CreateChatThreadOptions: RequestOptions {
|
||||
public extension ChatThreadOperation {
|
||||
/// User-configurable options for the `AzureCommunicationChatService.RemoveChatParticipant` operation.
|
||||
struct RemoveChatParticipantOptions: RequestOptions {
|
||||
/// A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
/// Highly recommended for correlating client-side activites with requests received by the server.
|
||||
public let clientRequestId: String?
|
||||
|
@ -31,7 +31,7 @@ extension AzureCommunicationChatService {
|
|||
/// A `PipelineContext` object to associate with the request.
|
||||
public var context: PipelineContext?
|
||||
|
||||
/// Initialize a `CreateChatThreadOptions` structure.
|
||||
/// Initialize a `RemoveChatParticipantOptions` structure.
|
||||
/// - Parameters:
|
||||
/// - clientRequestId: A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
/// - cancellationToken: A token used to make a best-effort attempt at canceling a request.
|
|
@ -15,9 +15,9 @@ import Foundation
|
|||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
|
||||
extension AzureCommunicationChatService {
|
||||
public extension ChatThreadOperation {
|
||||
/// User-configurable options for the `AzureCommunicationChatService.SendChatMessage` operation.
|
||||
public struct SendChatMessageOptions: RequestOptions {
|
||||
struct SendChatMessageOptions: RequestOptions {
|
||||
/// A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
/// Highly recommended for correlating client-side activites with requests received by the server.
|
||||
public let clientRequestId: String?
|
|
@ -15,9 +15,9 @@ import Foundation
|
|||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
|
||||
extension AzureCommunicationChatService {
|
||||
public extension ChatThreadOperation {
|
||||
/// User-configurable options for the `AzureCommunicationChatService.SendChatReadReceipt` operation.
|
||||
public struct SendChatReadReceiptOptions: RequestOptions {
|
||||
struct SendChatReadReceiptOptions: RequestOptions {
|
||||
/// A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
/// Highly recommended for correlating client-side activites with requests received by the server.
|
||||
public let clientRequestId: String?
|
|
@ -15,9 +15,9 @@ import Foundation
|
|||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
|
||||
extension AzureCommunicationChatService {
|
||||
public extension ChatThreadOperation {
|
||||
/// User-configurable options for the `AzureCommunicationChatService.SendTypingNotification` operation.
|
||||
public struct SendTypingNotificationOptions: RequestOptions {
|
||||
struct SendTypingNotificationOptions: RequestOptions {
|
||||
/// A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
/// Highly recommended for correlating client-side activites with requests received by the server.
|
||||
public let clientRequestId: String?
|
|
@ -15,9 +15,9 @@ import Foundation
|
|||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
|
||||
extension AzureCommunicationChatService {
|
||||
public extension ChatThreadOperation {
|
||||
/// User-configurable options for the `AzureCommunicationChatService.UpdateChatMessage` operation.
|
||||
public struct UpdateChatMessageOptions: RequestOptions {
|
||||
struct UpdateChatMessageOptions: RequestOptions {
|
||||
/// A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
/// Highly recommended for correlating client-side activites with requests received by the server.
|
||||
public let clientRequestId: String?
|
|
@ -15,9 +15,9 @@ import Foundation
|
|||
// swiftlint:disable identifier_name
|
||||
// swiftlint:disable line_length
|
||||
|
||||
extension AzureCommunicationChatService {
|
||||
public extension ChatThreadOperation {
|
||||
/// User-configurable options for the `AzureCommunicationChatService.UpdateChatThread` operation.
|
||||
public struct UpdateChatThreadOptions: RequestOptions {
|
||||
struct UpdateChatThreadOptions: RequestOptions {
|
||||
/// A client-generated, opaque value with 1KB character limit that is recorded in analytics logs.
|
||||
/// Highly recommended for correlating client-side activites with requests received by the server.
|
||||
public let clientRequestId: String?
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
// --------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
@ -25,6 +24,29 @@
|
|||
//
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCore
|
||||
import Foundation
|
||||
|
||||
// TODO: Custom Code Here
|
||||
/// Request payload for creating a chat thread.
|
||||
public struct CreateThreadRequest: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// The thread topic.
|
||||
public let topic: String
|
||||
/// Participants to be added to the thread.
|
||||
public let participants: [Participant]
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initialize a `CreateThreadRequest` structure.
|
||||
/// - Parameters:
|
||||
/// - topic: The thread topic.
|
||||
/// - participants: Participants to be added to the chat thread.
|
||||
public init(
|
||||
topic: String,
|
||||
participants: [Participant]
|
||||
) {
|
||||
self.topic = topic
|
||||
self.participants = participants
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
// --------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the ""Software""), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCore
|
||||
import Foundation
|
||||
|
||||
/// Result of the create thread operation.
|
||||
public struct CreateThreadResult: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// Chat thread.
|
||||
public let thread: Thread?
|
||||
/// Errors encountered during the creation of the chat thread.
|
||||
public let errors: CreateChatThreadErrors?
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
public init(
|
||||
from createChatThreadResult: CreateChatThreadResult
|
||||
) {
|
||||
self.thread = (createChatThreadResult.chatThread != nil) ? Thread(from: createChatThreadResult.chatThread!) : nil
|
||||
self.errors = createChatThreadResult.errors
|
||||
}
|
||||
|
||||
/// Initialize a `ChatThreadResult` structure.
|
||||
/// - Parameters:
|
||||
/// - thread: Chat thread.
|
||||
/// - errors: Errors encountered during the creation of the chat thread.
|
||||
public init(
|
||||
thread: Thread? = nil,
|
||||
errors: CreateChatThreadErrors? = nil
|
||||
) {
|
||||
self.thread = thread
|
||||
self.errors = errors
|
||||
}
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
// --------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the ""Software""), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCommunication
|
||||
import AzureCore
|
||||
import Foundation
|
||||
|
||||
/// Message.
|
||||
public struct Message: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// The id of the message. This id is server generated.
|
||||
public let id: String
|
||||
/// The message type.
|
||||
public let type: ChatMessageType
|
||||
/// Sequence of the message in the conversation.
|
||||
public let sequenceId: String
|
||||
/// Version of the message.
|
||||
public let version: String
|
||||
/// Content of the message.
|
||||
public let content: MessageContent?
|
||||
/// The display name of the message sender. This property is used to populate sender name for push notifications.
|
||||
public let senderDisplayName: String?
|
||||
/// The timestamp when the message arrived at the server. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public let createdOn: Iso8601Date
|
||||
/// The sender of the message.
|
||||
public let sender: CommunicationUserIdentifier?
|
||||
/// The timestamp (if applicable) when the message was deleted. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public let deletedOn: Iso8601Date?
|
||||
/// The last timestamp (if applicable) when the message was edited. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public let editedOn: Iso8601Date?
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initialize a `Message` structure from a ChatMessage.
|
||||
/// - Parameters:
|
||||
/// - chatMessage: The ChatMessage to initialize from.
|
||||
public init(
|
||||
from chatMessage: ChatMessage
|
||||
) {
|
||||
self.id = chatMessage.id
|
||||
self.type = chatMessage.type
|
||||
self.sequenceId = chatMessage.sequenceId
|
||||
self.version = chatMessage.version
|
||||
self.content = (chatMessage.content != nil) ? MessageContent(from: chatMessage.content!) : nil
|
||||
self.senderDisplayName = chatMessage.senderDisplayName
|
||||
self.createdOn = chatMessage.createdOn
|
||||
self.sender = (chatMessage.senderId != nil) ? CommunicationUserIdentifier(identifier: chatMessage.senderId!) : nil
|
||||
self.deletedOn = chatMessage.deletedOn
|
||||
self.editedOn = chatMessage.editedOn
|
||||
}
|
||||
|
||||
/// Initialize a `Message` structure.
|
||||
/// - Parameters:
|
||||
/// - id: The id of the message. This id is server generated.
|
||||
/// - type: The chat message type.
|
||||
/// - sequenceId: Sequence of the message in the conversation.
|
||||
/// - version: Version of the message.
|
||||
/// - content: Content of a message.
|
||||
/// - senderDisplayName: The display name of the message sender. This property is used to populate sender name for push notifications.
|
||||
/// - createdOn: The timestamp when the message arrived at the server. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
/// - sender: The id of the sender of the message.
|
||||
/// - deletedOn: The timestamp (if applicable) when the message was deleted. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
/// - editedOn: The last timestamp (if applicable) when the message was edited. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public init(
|
||||
id: String,
|
||||
type: ChatMessageType,
|
||||
sequenceId: String,
|
||||
version: String,
|
||||
content: MessageContent? = nil,
|
||||
senderDisplayName: String? = nil,
|
||||
createdOn: Iso8601Date,
|
||||
senderId: String? = nil,
|
||||
deletedOn: Iso8601Date? = nil,
|
||||
editedOn: Iso8601Date? = nil
|
||||
) {
|
||||
self.id = id
|
||||
self.type = type
|
||||
self.sequenceId = sequenceId
|
||||
self.version = version
|
||||
self.content = content
|
||||
self.senderDisplayName = senderDisplayName
|
||||
self.createdOn = createdOn
|
||||
self.sender = (senderId != nil) ? CommunicationUserIdentifier(identifier: senderId!) : nil
|
||||
self.deletedOn = deletedOn
|
||||
self.editedOn = editedOn
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case type
|
||||
case sequenceId
|
||||
case version
|
||||
case content
|
||||
case senderDisplayName
|
||||
case createdOn
|
||||
case sender = "senderId"
|
||||
case deletedOn
|
||||
case editedOn
|
||||
}
|
||||
|
||||
/// Initialize a `Message` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
self.id = try container.decode(String.self, forKey: .id)
|
||||
self.type = try container.decode(ChatMessageType.self, forKey: .type)
|
||||
self.sequenceId = try container.decode(String.self, forKey: .sequenceId)
|
||||
self.version = try container.decode(String.self, forKey: .version)
|
||||
|
||||
// Convert ChatMessageContent to MessageContent
|
||||
let content = try? container.decode(ChatMessageContent.self, forKey: .content)
|
||||
self.content = MessageContent(from: content!)
|
||||
|
||||
self.senderDisplayName = try? container.decode(String.self, forKey: .senderDisplayName)
|
||||
self.createdOn = try container.decode(Iso8601Date.self, forKey: .createdOn)
|
||||
|
||||
// Convert senderId to CommunicationUserIdentifier
|
||||
let senderId = try? container.decode(String.self, forKey: .sender)
|
||||
self.sender = (senderId != nil) ? CommunicationUserIdentifier(identifier: senderId!) : nil
|
||||
|
||||
self.deletedOn = try? container.decode(Iso8601Date.self, forKey: .deletedOn)
|
||||
self.editedOn = try? container.decode(Iso8601Date.self, forKey: .editedOn)
|
||||
}
|
||||
|
||||
/// Encode a `Message` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(type, forKey: .type)
|
||||
try container.encode(sequenceId, forKey: .sequenceId)
|
||||
try container.encode(version, forKey: .version)
|
||||
if content != nil { try? container.encode(content, forKey: .content) }
|
||||
if senderDisplayName != nil { try? container.encode(senderDisplayName, forKey: .senderDisplayName) }
|
||||
try container.encode(createdOn, forKey: .createdOn)
|
||||
|
||||
// Encode user object to senderId string
|
||||
if sender != nil { try? container.encode(sender?.identifier, forKey: .sender) }
|
||||
|
||||
if deletedOn != nil { try? container.encode(deletedOn, forKey: .deletedOn) }
|
||||
if editedOn != nil { try? container.encode(editedOn, forKey: .editedOn) }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
// --------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the ""Software""), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCore
|
||||
import Foundation
|
||||
|
||||
/// Content of a message.
|
||||
public struct MessageContent: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// Chat message content for messages of types text or html.
|
||||
public let message: String?
|
||||
/// Chat message content for messages of type topicUpdated.
|
||||
public let topic: String?
|
||||
/// Chat message content for messages of types participantAdded or participantRemoved.
|
||||
public let participants: [Participant]?
|
||||
/// Chat message content for messages of types participantAdded or participantRemoved.
|
||||
public let initiator: String?
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initializes a `MessageContent` structure from a ChatMessageContent.
|
||||
/// - Parameters:
|
||||
/// - chatMessageContent: ChatMessageContent to initialize from.
|
||||
public init(
|
||||
from chatMessageContent: ChatMessageContent
|
||||
) {
|
||||
self.message = chatMessageContent.message
|
||||
self.topic = chatMessageContent.topic
|
||||
self.participants = (chatMessageContent.participants != nil) ?
|
||||
chatMessageContent.participants!.map { Participant(from: $0) } : nil
|
||||
self.initiator = chatMessageContent.initiator
|
||||
}
|
||||
|
||||
/// Initialize a `MessageContent` structure.
|
||||
/// - Parameters:
|
||||
/// - message: Message content for messages of types text or html.
|
||||
/// - topic: Message content for messages of type topicUpdated.
|
||||
/// - participants: Message content for messages of types participantAdded or participantRemoved.
|
||||
/// - initiator: Message content for messages of types participantAdded or participantRemoved.
|
||||
public init(
|
||||
message: String? = nil,
|
||||
topic: String? = nil,
|
||||
participants: [Participant]? = nil,
|
||||
initiator: String? = nil
|
||||
) {
|
||||
self.message = message
|
||||
self.topic = topic
|
||||
self.participants = participants
|
||||
self.initiator = initiator
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case message
|
||||
case topic
|
||||
case participants
|
||||
case initiator
|
||||
}
|
||||
|
||||
/// Initialize a `MessageContent` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.message = try? container.decode(String.self, forKey: .message)
|
||||
self.topic = try? container.decode(String.self, forKey: .topic)
|
||||
|
||||
// Convert ChatParticipants to Participants
|
||||
let chatParticipants = try? container.decode([ChatParticipant].self, forKey: .participants)
|
||||
self.participants = (chatParticipants != nil) ? chatParticipants!.map { Participant(from: $0) } : nil
|
||||
|
||||
self.initiator = try? container.decode(String.self, forKey: .initiator)
|
||||
}
|
||||
|
||||
/// Encode a `MessageContent` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
if message != nil { try? container.encode(message, forKey: .message) }
|
||||
if topic != nil { try? container.encode(topic, forKey: .topic) }
|
||||
|
||||
// Encode Participant to ChatParticipant format
|
||||
if participants != nil {
|
||||
let test = participants!.map {
|
||||
ChatParticipant(
|
||||
id: $0.user.identifier,
|
||||
displayName: $0.displayName,
|
||||
shareHistoryTime: $0.shareHistoryTime
|
||||
)
|
||||
}
|
||||
try? container.encode(test, forKey: .participants)
|
||||
}
|
||||
|
||||
if initiator != nil { try? container.encode(initiator, forKey: .initiator) }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
// --------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the ""Software""), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCommunication
|
||||
import AzureCore
|
||||
import Foundation
|
||||
|
||||
/// A participant of the chat thread.
|
||||
public struct Participant: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// The CommunicationUserIdentifier for the participant.
|
||||
public let user: CommunicationUserIdentifier
|
||||
/// Display name for the participant.
|
||||
public let displayName: String?
|
||||
/// Time from which the chat history is shared with the participant. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public let shareHistoryTime: Iso8601Date?
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initialize a `Participant` structure from a ChatParticipant.
|
||||
/// - Parameters:
|
||||
/// - chatParticipant: The ChatParticipant to initialize from.
|
||||
public init(
|
||||
from chatParticipant: ChatParticipant
|
||||
) {
|
||||
self.user = CommunicationUserIdentifier(identifier: chatParticipant.id)
|
||||
self.displayName = chatParticipant.displayName
|
||||
self.shareHistoryTime = chatParticipant.shareHistoryTime
|
||||
}
|
||||
|
||||
/// Initialize a `Participant` structure.
|
||||
/// - Parameters:
|
||||
/// - id: The id of the participant.
|
||||
/// - displayName: Display name for the participant.
|
||||
/// - shareHistoryTime: Time from which the chat history is shared with the participant. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public init(
|
||||
id: String,
|
||||
displayName: String? = nil,
|
||||
shareHistoryTime: Iso8601Date? = nil
|
||||
) {
|
||||
self.user = CommunicationUserIdentifier(identifier: id)
|
||||
self.displayName = displayName
|
||||
self.shareHistoryTime = shareHistoryTime
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case user = "id"
|
||||
case displayName
|
||||
case shareHistoryTime
|
||||
}
|
||||
|
||||
/// Initialize a `Participant` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
// Convert id to CommunicationUserIdentifier
|
||||
let identifier = try? container.decode(String.self, forKey: .user)
|
||||
self.user = CommunicationUserIdentifier(identifier: identifier!)
|
||||
|
||||
self.displayName = try? container.decode(String.self, forKey: .displayName)
|
||||
self.shareHistoryTime = try? container.decode(Iso8601Date.self, forKey: .shareHistoryTime)
|
||||
}
|
||||
|
||||
/// Encode a `Participant` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
// Encode user object to id string
|
||||
try container.encode(user.identifier, forKey: .user)
|
||||
|
||||
if displayName != nil { try? container.encode(displayName, forKey: .displayName) }
|
||||
if shareHistoryTime != nil { try? container.encode(shareHistoryTime, forKey: .shareHistoryTime) }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
// --------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the ""Software""), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCommunication
|
||||
import AzureCore
|
||||
import Foundation
|
||||
|
||||
/// A read receipt indicates the time a message was read by a recipient.
|
||||
public struct ReadReceipt: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// The user who read the message.
|
||||
public let sender: CommunicationUserIdentifier
|
||||
/// Id of the message that has been read. This id is generated by the server.
|
||||
public let chatMessageId: String
|
||||
/// The time at which the message was read. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public let readOn: Iso8601Date
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initialize a `ReadReceipt` structure from a ChatMessageReadReceipt.
|
||||
/// - Parameters:
|
||||
/// - chatMessageReadReceipt: The ChatMessageReadReceipt to initialize from.
|
||||
public init(
|
||||
from chatMessageReadReceipt: ChatMessageReadReceipt
|
||||
) {
|
||||
self.sender = CommunicationUserIdentifier(identifier: chatMessageReadReceipt.senderId)
|
||||
self.chatMessageId = chatMessageReadReceipt.chatMessageId
|
||||
self.readOn = chatMessageReadReceipt.readOn
|
||||
}
|
||||
|
||||
/// Initialize a `ReadReceipt` structure.
|
||||
/// - Parameters:
|
||||
/// - senderId: Id of the participant who read the message.
|
||||
/// - chatMessageId: Id of the chat message that has been read. This id is generated by the server.
|
||||
/// - readOn: The time at which the message was read. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public init(
|
||||
senderId: String,
|
||||
chatMessageId: String,
|
||||
readOn: Iso8601Date
|
||||
) {
|
||||
self.sender = CommunicationUserIdentifier(identifier: senderId)
|
||||
self.chatMessageId = chatMessageId
|
||||
self.readOn = readOn
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case sender = "senderId"
|
||||
case chatMessageId
|
||||
case readOn
|
||||
}
|
||||
|
||||
/// Initialize a `ReadReceipt` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
// Convert senderId to CommunicationUserIdentifier
|
||||
let senderId = try container.decode(String.self, forKey: .sender)
|
||||
self.sender = CommunicationUserIdentifier(identifier: senderId)
|
||||
|
||||
self.chatMessageId = try container.decode(String.self, forKey: .chatMessageId)
|
||||
self.readOn = try container.decode(Iso8601Date.self, forKey: .readOn)
|
||||
}
|
||||
|
||||
/// Encode a `ReadReceipt` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
// Encode user object to senderId string
|
||||
try container.encode(sender.identifier, forKey: .sender)
|
||||
|
||||
try container.encode(chatMessageId, forKey: .chatMessageId)
|
||||
try container.encode(readOn, forKey: .readOn)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
// --------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the ""Software""), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCommunication
|
||||
import AzureCore
|
||||
import Foundation
|
||||
|
||||
/// Chat thread.
|
||||
public struct Thread: Codable {
|
||||
// MARK: Properties
|
||||
|
||||
/// Thread id.
|
||||
public let id: String
|
||||
/// Thread topic.
|
||||
public let topic: String
|
||||
/// The timestamp when the thread was created. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public let createdOn: Iso8601Date
|
||||
/// CommunicationUserIdentifier of the thread owner.
|
||||
public let createdBy: CommunicationUserIdentifier
|
||||
/// The timestamp when the thread was deleted. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public let deletedOn: Iso8601Date?
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Initialize a `ChatThread` structure from a ChatThread.
|
||||
/// - Parameters:
|
||||
/// - chatThread: The ChatThread to initialize from.
|
||||
public init(
|
||||
from chatThread: ChatThread
|
||||
) {
|
||||
self.id = chatThread.id
|
||||
self.topic = chatThread.topic
|
||||
self.createdOn = chatThread.createdOn
|
||||
self.createdBy = CommunicationUserIdentifier(identifier: chatThread.createdBy)
|
||||
self.deletedOn = chatThread.deletedOn
|
||||
}
|
||||
|
||||
/// Initialize a `ChatThread` structure.
|
||||
/// - Parameters:
|
||||
/// - id: Thread id.
|
||||
/// - topic: Thread topic.
|
||||
/// - createdOn: The timestamp when the thread was created. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
/// - createdBy: Id of the thread owner.
|
||||
/// - deletedOn: The timestamp when the thread was deleted. The timestamp is in RFC3339 format: `yyyy-MM-ddTHH:mm:ssZ`.
|
||||
public init(
|
||||
id: String,
|
||||
topic: String,
|
||||
createdOn: Iso8601Date,
|
||||
createdBy: String,
|
||||
deletedOn: Iso8601Date? = nil
|
||||
) {
|
||||
self.id = id
|
||||
self.topic = topic
|
||||
self.createdOn = createdOn
|
||||
self.createdBy = CommunicationUserIdentifier(identifier: createdBy)
|
||||
self.deletedOn = deletedOn
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case topic
|
||||
case createdOn
|
||||
case createdBy
|
||||
case deletedOn
|
||||
}
|
||||
|
||||
/// Initialize a `Thread` structure from decoder
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
self.id = try container.decode(String.self, forKey: .id)
|
||||
self.topic = try container.decode(String.self, forKey: .topic)
|
||||
self.createdOn = try container.decode(Iso8601Date.self, forKey: .createdOn)
|
||||
|
||||
// Convert createdBy to CommunicationUserIdentifier
|
||||
let createdBy = try container.decode(String.self, forKey: .createdBy)
|
||||
self.createdBy = CommunicationUserIdentifier(identifier: createdBy)
|
||||
|
||||
self.deletedOn = try? container.decode(Iso8601Date.self, forKey: .deletedOn)
|
||||
}
|
||||
|
||||
/// Encode a `Thread` structure
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(topic, forKey: .topic)
|
||||
try container.encode(createdOn, forKey: .createdOn)
|
||||
|
||||
// Encode user object to createdBy string
|
||||
try container.encode(createdBy.identifier, forKey: .createdBy)
|
||||
|
||||
if deletedOn != nil { try? container.encode(deletedOn, forKey: .deletedOn) }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,276 @@
|
|||
// --------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the ""Software""), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCommunication
|
||||
import AzureCommunicationChat
|
||||
import AzureCore
|
||||
import XCTest
|
||||
|
||||
class ChatClientTests: XCTestCase {
|
||||
/// ChatClient initialized in setup.
|
||||
private var chatClient: ChatClient!
|
||||
/// An ACS user id.
|
||||
private var user: String = TestUtil.user1
|
||||
/// Thread topic.
|
||||
private let topic: String = "General"
|
||||
|
||||
override class func setUp() {
|
||||
if TestUtil.mode == "playback" {
|
||||
// Register stubs for playback mode
|
||||
Recorder.registerStubs()
|
||||
}
|
||||
}
|
||||
|
||||
override func setUpWithError() throws {
|
||||
chatClient = try TestUtil.getChatClient()
|
||||
}
|
||||
|
||||
/// Helper to create a thread for tests that act on an existing thread.
|
||||
/// - Parameters:
|
||||
/// - id: The user id.
|
||||
/// - topic: The thread topic.
|
||||
/// - completionHandler: Completion handler that receives the thread id of the created thread.
|
||||
func createThread(
|
||||
withUser id: String,
|
||||
withTopic topic: String,
|
||||
completionHandler: @escaping (String) -> Void
|
||||
) {
|
||||
let participant = Participant(
|
||||
id: id,
|
||||
displayName: "User",
|
||||
shareHistoryTime: Iso8601Date(string: "2016-04-13T00:00:00Z")!
|
||||
)
|
||||
|
||||
let thread = CreateThreadRequest(
|
||||
topic: topic,
|
||||
participants: [
|
||||
participant
|
||||
]
|
||||
)
|
||||
|
||||
chatClient.create(thread: thread) { result, _ in
|
||||
switch result {
|
||||
case let .success(chatThreadResult):
|
||||
guard let threadId = chatThreadResult.thread?.id else {
|
||||
XCTFail("Failed to get thread id")
|
||||
return
|
||||
}
|
||||
|
||||
completionHandler(threadId)
|
||||
case let .failure(error):
|
||||
XCTFail("Error creating thread: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_CreateThread_ResultContainsChatThread() {
|
||||
let participant = Participant(
|
||||
id: user,
|
||||
displayName: "User",
|
||||
shareHistoryTime: Iso8601Date(string: "2016-04-13T00:00:00Z")!
|
||||
)
|
||||
|
||||
let thread = CreateThreadRequest(
|
||||
topic: topic,
|
||||
participants: [
|
||||
participant
|
||||
]
|
||||
)
|
||||
|
||||
let expectation = self.expectation(description: "Create thread")
|
||||
|
||||
chatClient.create(thread: thread) { result, httpResponse in
|
||||
switch result {
|
||||
case let .success(response):
|
||||
let chatThread = response.thread
|
||||
XCTAssertNotNil(response.thread)
|
||||
XCTAssertEqual(chatThread?.topic, thread.topic)
|
||||
XCTAssertNotNil(httpResponse?.httpRequest?.headers["repeatability-Request-ID"])
|
||||
|
||||
if TestUtil.mode == "record" {
|
||||
Recorder.record(name: Recording.createThread, httpResponse: httpResponse)
|
||||
}
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("Create thread failed with error: \(error)")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Create thread timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_CreateThread_WithOptions_SetsRepeatabilityRequestID() {
|
||||
let participant = Participant(
|
||||
id: user,
|
||||
displayName: "User",
|
||||
shareHistoryTime: Iso8601Date(string: "2016-04-13T00:00:00Z")!
|
||||
)
|
||||
|
||||
let thread = CreateThreadRequest(
|
||||
topic: topic,
|
||||
participants: [
|
||||
participant
|
||||
]
|
||||
)
|
||||
|
||||
// Create options without repeatabilityRequestID
|
||||
let options = Chat.CreateChatThreadOptions(clientRequestId: "test_id")
|
||||
|
||||
let expectation = self.expectation(description: "Create thread")
|
||||
|
||||
chatClient.create(thread: thread, withOptions: options) { result, httpResponse in
|
||||
switch result {
|
||||
case .success:
|
||||
XCTAssertNotNil(httpResponse?.httpRequest?.headers["repeatability-Request-ID"])
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("Create thread failed with error: \(error)")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Create thread timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_GetThread_ReturnsChatThread() {
|
||||
let expectation = self.expectation(description: "Get thread")
|
||||
|
||||
// Create a thread
|
||||
createThread(withUser: user, withTopic: topic) { threadId in
|
||||
// Get the thread
|
||||
self.chatClient.get(thread: threadId) { result, httpResponse in
|
||||
switch result {
|
||||
case let .success(thread):
|
||||
XCTAssert(thread.topic == self.topic)
|
||||
XCTAssertNotNil(thread.createdBy)
|
||||
|
||||
if TestUtil.mode == "record" {
|
||||
Recorder.record(name: Recording.getThread, httpResponse: httpResponse)
|
||||
}
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("Get thread failed with error: \(error)")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Get thread timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_DeleteThread() {
|
||||
let expectation = self.expectation(description: "Delete thread")
|
||||
|
||||
// Create a thread
|
||||
createThread(withUser: user, withTopic: topic) { threadId in
|
||||
// Delete the thread
|
||||
self.chatClient.delete(thread: threadId) { result, httpResponse in
|
||||
switch result {
|
||||
case .success:
|
||||
if TestUtil.mode == "record" {
|
||||
Recorder.record(name: Recording.deleteThread, httpResponse: httpResponse)
|
||||
}
|
||||
|
||||
// Get the thread and verify deleted
|
||||
if TestUtil.mode != "playback" {
|
||||
self.chatClient.get(thread: threadId) { result, _ in
|
||||
switch result {
|
||||
case let .success(thread):
|
||||
XCTAssertNotNil(thread.deletedOn)
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("Deleted thread failed with error: \(error)")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
} else {
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("Delete thread failed: \(error)")
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Delete thread timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_ListThreads_ReturnsThreads() {
|
||||
let expectation = self.expectation(description: "List threads")
|
||||
|
||||
// Create a thread
|
||||
createThread(withUser: user, withTopic: "Hello World") { _ in
|
||||
// List threads
|
||||
self.chatClient.listThreads { result, httpResponse in
|
||||
switch result {
|
||||
case let .success(listThreadsResult):
|
||||
if TestUtil.mode == "record" {
|
||||
Recorder.record(name: Recording.listThreads, httpResponse: httpResponse)
|
||||
}
|
||||
|
||||
let threads = listThreadsResult.items
|
||||
XCTAssertNotNil(threads)
|
||||
XCTAssertNotNil(threads?.count)
|
||||
XCTAssertNotEqual(threads?.count, 0)
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("List threads failed: \(error)")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("List threads timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,318 @@
|
|||
// --------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the ""Software""), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCommunication
|
||||
import AzureCommunicationChat
|
||||
import AzureCore
|
||||
import OHHTTPStubsSwift
|
||||
import XCTest
|
||||
|
||||
class ChatClientUnitTests: XCTestCase {
|
||||
private var chatClient: ChatClient!
|
||||
|
||||
private let participantId = "test_participant_id"
|
||||
private let threadId = "test_thread_id"
|
||||
private let topic = "test topic"
|
||||
|
||||
override func setUpWithError() throws {
|
||||
chatClient = try TestUtil.getChatClient()
|
||||
}
|
||||
|
||||
func test_CreateChatThreadClient_ReturnChatThreadClient() {
|
||||
do {
|
||||
let threadClient = try chatClient.createClient(forThread: threadId)
|
||||
XCTAssertEqual(threadClient.threadId, threadId)
|
||||
} catch _ {
|
||||
XCTFail("Failed in creating chat thread client")
|
||||
}
|
||||
}
|
||||
|
||||
func test_CreateChatThread_ReturnChatThread() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "CreateThreadResponse", ofType: "json") ?? ""
|
||||
stub(condition: isMethodPOST() && isPath("/chat/threads")) { _ in
|
||||
fixture(filePath: path, status: 201, headers: nil)
|
||||
}
|
||||
|
||||
let participant = Participant(
|
||||
id: "test_participant_id",
|
||||
displayName: "test name",
|
||||
shareHistoryTime: Iso8601Date(string: "2016-04-13T00:00:00Z")!
|
||||
)
|
||||
|
||||
let request = CreateThreadRequest(
|
||||
topic: "test topic",
|
||||
participants: [
|
||||
participant
|
||||
]
|
||||
)
|
||||
|
||||
let expectation = self.expectation(description: "Create chat thread")
|
||||
|
||||
chatClient.create(thread: request) { result, _ in
|
||||
switch result {
|
||||
case let .success(response):
|
||||
guard let thread = response.thread else {
|
||||
XCTFail("Failed to extract chatThread from response")
|
||||
return
|
||||
}
|
||||
XCTAssert(thread.id == self.threadId)
|
||||
XCTAssert(thread.topic == request.topic)
|
||||
XCTAssert(thread.createdBy.identifier == participant.user.identifier)
|
||||
|
||||
case .failure:
|
||||
XCTFail("Unexpected failure happened in create chat thread")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Create chat thread timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_CreateChatThread_ReturnError() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "UnauthorizedError", ofType: "json") ?? ""
|
||||
stub(condition: isMethodPOST() && isPath("/chat/threads")) { _ in
|
||||
fixture(filePath: path, status: 401, headers: nil)
|
||||
}
|
||||
|
||||
let participant = Participant(
|
||||
id: "test id",
|
||||
displayName: "test name",
|
||||
shareHistoryTime: Iso8601Date(string: "2016-04-13T00:00:00Z")!
|
||||
)
|
||||
|
||||
let request = CreateThreadRequest(
|
||||
topic: "test topic",
|
||||
participants: [
|
||||
participant
|
||||
]
|
||||
)
|
||||
|
||||
let expectation = self.expectation(description: "Create chat thread")
|
||||
|
||||
chatClient.create(thread: request) { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
XCTFail("Unexpected failure happened in create chat thread")
|
||||
|
||||
case let .failure(error):
|
||||
XCTAssertNotNil(error)
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Create chat thread timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_GetChatThread_ReturnChatThread() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "GetThreadResponse", ofType: "json") ?? ""
|
||||
stub(condition: isMethodGET()) { _ in
|
||||
fixture(filePath: path, status: 200, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "Get thread")
|
||||
|
||||
chatClient.get(thread: threadId) { result, _ in
|
||||
switch result {
|
||||
case let .success(chatThread):
|
||||
XCTAssertEqual(chatThread.id, self.threadId)
|
||||
XCTAssertEqual(chatThread.topic, self.topic)
|
||||
XCTAssertEqual(chatThread.createdBy.identifier, self.participantId)
|
||||
|
||||
case .failure:
|
||||
XCTFail()
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Get thread timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_GetChatThread_ReturnError() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "UnauthorizedError", ofType: "json") ?? ""
|
||||
stub(condition: isMethodGET()) { _ in
|
||||
fixture(filePath: path, status: 401, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "Get thread")
|
||||
|
||||
chatClient.get(thread: threadId) { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
XCTFail("Unexpected failure happened in get thread")
|
||||
|
||||
case let .failure(error):
|
||||
XCTAssertNotNil(error)
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Get thread timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_ListChatThreads_ReturnChatThreads() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "ListThreadsResponse", ofType: "json") ?? ""
|
||||
stub(condition: isMethodGET()) { _ in
|
||||
fixture(filePath: path, status: 200, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "List threads")
|
||||
|
||||
chatClient.listThreads { result, _ in
|
||||
switch result {
|
||||
case let .success(threads):
|
||||
threads.nextItem { result in
|
||||
switch result {
|
||||
case let .success(item):
|
||||
XCTAssert(item.topic == self.topic)
|
||||
XCTAssert(item.id == self.threadId)
|
||||
|
||||
case .failure:
|
||||
XCTFail("Unexpected failure happened in list chat threads")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
case .failure:
|
||||
XCTFail("Unexpected failure happened in list chat threads")
|
||||
}
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("List threads timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_ListChatThreads_ReturnError() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "UnauthorizedError", ofType: "json") ?? ""
|
||||
stub(condition: isMethodGET()) { _ in
|
||||
fixture(filePath: path, status: 401, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "List chat threads")
|
||||
|
||||
chatClient.listThreads { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
XCTFail("Unexpected failure happened in list chat threads")
|
||||
|
||||
case let .failure(error):
|
||||
XCTAssertNotNil(error)
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("List chat threads timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_DeleteChatThread_ReturnSuccess() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "NoContent", ofType: "json") ?? ""
|
||||
stub(condition: isMethodDELETE()) { _ in
|
||||
fixture(filePath: path, status: 204, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "Delete chat thread")
|
||||
|
||||
chatClient.delete(thread: threadId, completionHandler: { result, _ in
|
||||
switch result {
|
||||
case let .success(response):
|
||||
XCTAssertNotNil(response)
|
||||
|
||||
case .failure:
|
||||
XCTFail("Unexpected failure happened in delete chat thread")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Delete chat thread timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_DeleteChatThread_ReturnError() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "UnauthorizedError", ofType: "json") ?? ""
|
||||
stub(condition: isMethodDELETE()) { _ in
|
||||
fixture(filePath: path, status: 401, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "Delete chat thread")
|
||||
|
||||
chatClient.delete(thread: threadId, completionHandler: { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
XCTFail("Unexpected failure happened in delete chat thread")
|
||||
|
||||
case let .failure(error):
|
||||
XCTAssertNotNil(error)
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Delete chat thread timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,592 @@
|
|||
// --------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the ""Software""), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCommunication
|
||||
import AzureCommunicationChat
|
||||
import AzureCore
|
||||
import XCTest
|
||||
|
||||
// swiftlint:disable type_body_length
|
||||
// swiftlint:disable file_length
|
||||
|
||||
class ChatThreadClientTests: XCTestCase {
|
||||
/// An ACS user id.
|
||||
private var user1: String = TestUtil.user1
|
||||
/// An ACS user id.
|
||||
private var user2: String = TestUtil.user2
|
||||
/// Id of the thread created in setup.
|
||||
private var threadId: String = "testThreadId"
|
||||
/// ChatClient initialized in setup.
|
||||
private var chatClient: ChatClient!
|
||||
/// ChatThreadClient initialized in setup.
|
||||
private var chatThreadClient: ChatThreadClient!
|
||||
/// Initial thread topic.
|
||||
private let topic: String = "General"
|
||||
|
||||
override class func setUp() {
|
||||
if TestUtil.mode == "playback" {
|
||||
// Register stubs for playback mode
|
||||
Recorder.registerStubs()
|
||||
}
|
||||
}
|
||||
|
||||
override func setUpWithError() throws {
|
||||
// Initialize the chatClient
|
||||
chatClient = try TestUtil.getChatClient()
|
||||
|
||||
let participant = Participant(
|
||||
id: user1,
|
||||
displayName: "User 1",
|
||||
shareHistoryTime: Iso8601Date(string: "2016-04-13T00:00:00Z")!
|
||||
)
|
||||
|
||||
let thread = CreateThreadRequest(
|
||||
topic: topic,
|
||||
participants: [
|
||||
participant
|
||||
]
|
||||
)
|
||||
|
||||
let expectation = self.expectation(description: "Create thread")
|
||||
|
||||
// Create a thread for the test
|
||||
chatClient.create(thread: thread) { result, httpResponse in
|
||||
switch result {
|
||||
case let .success(createThreadResult):
|
||||
// Initialize threadId
|
||||
self.threadId = (createThreadResult.thread?.id)!
|
||||
|
||||
if TestUtil.mode == "record" {
|
||||
Recorder.record(name: Recording.createThread, httpResponse: httpResponse)
|
||||
}
|
||||
|
||||
case let .failure(error):
|
||||
print("Failed to create thread with error: \(error)")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
wait(for: [expectation], timeout: TestUtil.timeout)
|
||||
|
||||
// Initialize the ChatThreadClient
|
||||
chatThreadClient = try chatClient.createClient(forThread: threadId)
|
||||
}
|
||||
|
||||
func test_UpdateTopic() {
|
||||
let newTopic = "New topic"
|
||||
let expectation = self.expectation(description: "Update topic")
|
||||
|
||||
// Update topic
|
||||
chatThreadClient.update(topic: newTopic) { result, httpResponse in
|
||||
switch result {
|
||||
case .success:
|
||||
if TestUtil.mode == "record" {
|
||||
Recorder.record(name: Recording.updateTopic, httpResponse: httpResponse)
|
||||
}
|
||||
|
||||
// Get thread and verify topic updated
|
||||
if TestUtil.mode != "playback" {
|
||||
self.chatClient.get(thread: self.threadId) { result, _ in
|
||||
switch result {
|
||||
case let .success(chatThread):
|
||||
XCTAssertEqual(chatThread.topic, newTopic)
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("Failed to update topic: \(error)")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
} else {
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("Failed to update topic: \(error)")
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Update topic timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_SendMessage_ReturnsMessageId() {
|
||||
let testMessage = SendChatMessageRequest(
|
||||
content: "Hello World!",
|
||||
senderDisplayName: "User 1",
|
||||
type: .text
|
||||
)
|
||||
|
||||
let expectation = self.expectation(description: "Send message")
|
||||
|
||||
chatThreadClient.send(message: testMessage) { result, httpResponse in
|
||||
switch result {
|
||||
case let .success(sendMessageResult):
|
||||
if TestUtil.mode == "record" {
|
||||
Recorder.record(name: Recording.sendMessage, httpResponse: httpResponse)
|
||||
}
|
||||
XCTAssertNotNil(sendMessageResult.id)
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("Send message failed: \(error)")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Send message timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_SendMessage_SendsHTML() {
|
||||
let testMessage = SendChatMessageRequest(
|
||||
content: "<div>Hello</div>",
|
||||
senderDisplayName: "User 1",
|
||||
type: .html
|
||||
)
|
||||
|
||||
let expectation = self.expectation(description: "Send message")
|
||||
|
||||
chatThreadClient.send(message: testMessage) { result, _ in
|
||||
switch result {
|
||||
case let .success(sendMessageResult):
|
||||
XCTAssertNotNil(sendMessageResult.id)
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("Send message failed to send HTML: \(error)")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Send message timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_ListMessages_ReturnsMessages() {
|
||||
let testMessage = SendChatMessageRequest(
|
||||
content: "Hello World!",
|
||||
senderDisplayName: "User 1",
|
||||
type: .text
|
||||
)
|
||||
|
||||
let expectation = self.expectation(description: "List messages")
|
||||
|
||||
// Send a couple messages
|
||||
chatThreadClient.send(message: testMessage) { _, _ in
|
||||
self.chatThreadClient.send(message: testMessage) { _, _ in
|
||||
// List messages
|
||||
self.chatThreadClient.listMessages { result, httpResponse in
|
||||
switch result {
|
||||
case let .success(listMessagesResult):
|
||||
if TestUtil.mode == "record" {
|
||||
Recorder.record(name: Recording.listMessages, httpResponse: httpResponse)
|
||||
}
|
||||
|
||||
let messages = listMessagesResult.items
|
||||
messages?.forEach { message in
|
||||
if message.type == ChatMessageType.text {
|
||||
XCTAssertEqual(message.content?.message, testMessage.content)
|
||||
XCTAssertEqual(message.senderDisplayName, testMessage.senderDisplayName)
|
||||
}
|
||||
}
|
||||
|
||||
XCTAssertNotNil(messages)
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("List messages failed: \(error)")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("List messages timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_SendTypingNotification() {
|
||||
let expectation = self.expectation(description: "Send typing notification")
|
||||
|
||||
chatThreadClient.sendTypingNotification { result, httpResponse in
|
||||
switch result {
|
||||
case .success:
|
||||
if TestUtil.mode == "record" {
|
||||
Recorder.record(name: Recording.sendTypingNotification, httpResponse: httpResponse)
|
||||
}
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("Send typing notification failed: \(error)")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Send typing notification timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_SendReadReceipt() {
|
||||
let testMessage = SendChatMessageRequest(
|
||||
content: "Hello World!",
|
||||
senderDisplayName: "User 1",
|
||||
type: .text
|
||||
)
|
||||
|
||||
let expectation = self.expectation(description: "Send read receipt")
|
||||
|
||||
// Send message
|
||||
chatThreadClient.send(message: testMessage) { result, _ in
|
||||
switch result {
|
||||
case let .success(sendMessageResult):
|
||||
// Send read receipt
|
||||
self.chatThreadClient.sendReadReceipt(forMessage: sendMessageResult.id) { result, httpResponse in
|
||||
switch result {
|
||||
case .success:
|
||||
if TestUtil.mode == "record" {
|
||||
Recorder.record(name: Recording.sendReadReceipt, httpResponse: httpResponse)
|
||||
}
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("Send read receipt failed: \(error)")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("Send message failed: \(error)")
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Send message timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_ListReadReceipts_ReturnsReadReceipts() {
|
||||
let testMessage = SendChatMessageRequest(
|
||||
content: "Hello World!",
|
||||
senderDisplayName: "User 1",
|
||||
type: .text
|
||||
)
|
||||
|
||||
let expectation = self.expectation(description: "Send read receipt")
|
||||
|
||||
// Send message
|
||||
chatThreadClient.send(message: testMessage) { result, _ in
|
||||
switch result {
|
||||
case let .success(sendMessageResult):
|
||||
// Send read receipt
|
||||
self.chatThreadClient.sendReadReceipt(forMessage: sendMessageResult.id) { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
// List read receipts
|
||||
self.chatThreadClient.listReadReceipts { result, httpResponse in
|
||||
switch result {
|
||||
case let .success(readReceipts):
|
||||
if TestUtil.mode == "record" {
|
||||
Recorder.record(name: Recording.listReadReceipts, httpResponse: httpResponse)
|
||||
}
|
||||
|
||||
readReceipts.items?.forEach { readReceipt in
|
||||
XCTAssertNotNil(readReceipt.sender)
|
||||
XCTAssertEqual(readReceipt.chatMessageId, sendMessageResult.id)
|
||||
}
|
||||
|
||||
XCTAssertNotNil(readReceipts.items)
|
||||
case let .failure(error):
|
||||
XCTFail("List read receipts failed: \(error)")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("Send read receipt failed: \(error)")
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("Send message failed: \(error)")
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Send message timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_UpdateChatMessage() {
|
||||
let testMessage = SendChatMessageRequest(
|
||||
content: "Hello World!",
|
||||
senderDisplayName: "User 1",
|
||||
type: .text
|
||||
)
|
||||
|
||||
let expectation = self.expectation(description: "Update message")
|
||||
|
||||
// Send message
|
||||
chatThreadClient.send(message: testMessage) { result, _ in
|
||||
switch result {
|
||||
case let .success(sendMessageResult):
|
||||
let updatedMessage = UpdateChatMessageRequest(
|
||||
content: "Some new content"
|
||||
)
|
||||
|
||||
// Update message
|
||||
self.chatThreadClient
|
||||
.update(message: updatedMessage, messageId: sendMessageResult.id) { result, httpResponse in
|
||||
switch result {
|
||||
case .success:
|
||||
if TestUtil.mode == "record" {
|
||||
Recorder.record(name: Recording.updateMessage, httpResponse: httpResponse)
|
||||
}
|
||||
|
||||
// Get message and verify updated
|
||||
if TestUtil.mode != "playback" {
|
||||
self.chatThreadClient.get(message: sendMessageResult.id) { result, _ in
|
||||
switch result {
|
||||
case let .success(message):
|
||||
XCTAssertEqual(message.content?.message, updatedMessage.content)
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("Get message failed: \(error)")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
} else {
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("Update message failed: \(error)")
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("Send message failed: \(error)")
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Send message timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_DeleteMessage() {
|
||||
let testMessage = SendChatMessageRequest(
|
||||
content: "Hello World!",
|
||||
senderDisplayName: "User 1",
|
||||
type: .text
|
||||
)
|
||||
|
||||
let expectation = self.expectation(description: "Delete message")
|
||||
|
||||
// Send message
|
||||
chatThreadClient.send(message: testMessage) { result, _ in
|
||||
switch result {
|
||||
case let .success(sendMessageResult):
|
||||
// Delete message
|
||||
self.chatThreadClient.delete(message: sendMessageResult.id) { result, httpResponse in
|
||||
switch result {
|
||||
case .success:
|
||||
if TestUtil.mode == "record" {
|
||||
Recorder.record(name: Recording.deleteMessage, httpResponse: httpResponse)
|
||||
}
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("Delete message failed: \(error)")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("Send message failed: \(error)")
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Delete message timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_AddValidParticipant_ReturnsWithoutErrors() {
|
||||
let newParticipant = Participant(
|
||||
id: user2,
|
||||
displayName: "User 2",
|
||||
shareHistoryTime: Iso8601Date(string: "2016-04-13T00:00:00Z")!
|
||||
)
|
||||
|
||||
let expectation = self.expectation(description: "Add participant")
|
||||
|
||||
// Add a participant
|
||||
chatThreadClient.add(participants: [newParticipant]) { result, httpResponse in
|
||||
switch result {
|
||||
case let .success(addParticipantsResult):
|
||||
XCTAssertNil(addParticipantsResult.errors)
|
||||
if TestUtil.mode == "record" {
|
||||
Recorder.record(name: Recording.addParticipants, httpResponse: httpResponse)
|
||||
}
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("Add participants failed: \(error)")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Add participant timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_RemoveParticipant() {
|
||||
let removedParticipant = Participant(
|
||||
id: user2,
|
||||
displayName: "User 2",
|
||||
shareHistoryTime: Iso8601Date(string: "2016-04-13T00:00:00Z")!
|
||||
)
|
||||
|
||||
let expectation = self.expectation(description: "Remove participant")
|
||||
|
||||
// Add a participant
|
||||
chatThreadClient.add(participants: [removedParticipant]) { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
// Remove the participant
|
||||
self.chatThreadClient.remove(participant: removedParticipant.user.identifier) { result, httpResponse in
|
||||
switch result {
|
||||
case .success:
|
||||
if TestUtil.mode == "record" {
|
||||
Recorder.record(name: Recording.removeParticipant, httpResponse: httpResponse)
|
||||
}
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("Remove participant failed: \(error)")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("Remove participants failed: \(error)")
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Remove participant timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_ListParticipants_ReturnsParticipants() {
|
||||
let anotherParticipant = Participant(
|
||||
id: user2,
|
||||
displayName: "User 2",
|
||||
shareHistoryTime: Iso8601Date(string: "2016-04-13T00:00:00Z")!
|
||||
)
|
||||
|
||||
let expectation = self.expectation(description: "List participants")
|
||||
|
||||
// Add a participant
|
||||
chatThreadClient.add(participants: [anotherParticipant]) { result, httpResponse in
|
||||
switch result {
|
||||
case .success:
|
||||
// List participants
|
||||
self.chatThreadClient.listParticipants { result, httpResponse in
|
||||
if TestUtil.mode == "record" {
|
||||
Recorder.record(name: Recording.listParticipants, httpResponse: httpResponse)
|
||||
}
|
||||
|
||||
switch result {
|
||||
case let .success(participantsResult):
|
||||
let participants = participantsResult.pageItems
|
||||
participants?.forEach { participant in
|
||||
XCTAssertNotNil(participant.user.identifier)
|
||||
XCTAssertNotNil(participant.displayName)
|
||||
}
|
||||
|
||||
XCTAssertEqual(participants?.count, 2)
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("List participants failed: \(error)")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
||||
case let .failure(error):
|
||||
XCTFail("Add participants failed: \(error)")
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("List participants timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,788 @@
|
|||
// --------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the ""Software""), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCommunication
|
||||
import AzureCommunicationChat
|
||||
import AzureCore
|
||||
import OHHTTPStubsSwift
|
||||
import XCTest
|
||||
|
||||
// swiftlint:disable all
|
||||
class ChatThreadClientUnitTests: XCTestCase {
|
||||
private var chatClient: ChatClient!
|
||||
private var chatThreadClient: ChatThreadClient!
|
||||
|
||||
private let participantId = "test_participant_id"
|
||||
private let participantName = "test_participant_name"
|
||||
private let threadId = "test_thread_id"
|
||||
private let topic = "test topic"
|
||||
private let messageId = "test_message_id"
|
||||
|
||||
override func setUpWithError() throws {
|
||||
chatClient = try TestUtil.getChatClient()
|
||||
chatThreadClient = try chatClient.createClient(forThread: threadId)
|
||||
}
|
||||
|
||||
func test_UpdateThreadTopic_ReturnSuccess() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "NoContent", ofType: "json") ?? ""
|
||||
stub(condition: isMethodPATCH()) { _ in
|
||||
fixture(filePath: path, status: 204, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "Update thread topic")
|
||||
|
||||
chatThreadClient.update(topic: topic, completionHandler: { result, _ in
|
||||
switch result {
|
||||
case let .success(response):
|
||||
XCTAssertNotNil(response)
|
||||
|
||||
case .failure:
|
||||
XCTFail("Unexpected failure happened in update thread topic")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Update thread topic timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_UpdateThreadTopic_ReturnError() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "UnauthorizedError", ofType: "json") ?? ""
|
||||
stub(condition: isMethodPATCH()) { _ in
|
||||
fixture(filePath: path, status: 401, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "Update thread topic")
|
||||
|
||||
chatThreadClient.update(topic: topic, completionHandler: { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
XCTFail("Unexpected failure happened in update thread topic")
|
||||
|
||||
case let .failure(error):
|
||||
XCTAssertNotNil(error)
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Update thread topic timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_SendMessage_ReturnSuccess() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "SendMessageResponse", ofType: "json") ?? ""
|
||||
stub(condition: isMethodPOST()) { _ in
|
||||
fixture(filePath: path, status: 201, headers: nil)
|
||||
}
|
||||
|
||||
let messageRequest = SendChatMessageRequest(
|
||||
content: "Hello world!",
|
||||
senderDisplayName: "Leo"
|
||||
)
|
||||
|
||||
let expectation = self.expectation(description: "Send message")
|
||||
|
||||
chatThreadClient.send(message: messageRequest, completionHandler: { result, _ in
|
||||
switch result {
|
||||
case let .success(response):
|
||||
XCTAssertNotNil(response)
|
||||
XCTAssertEqual(response.id, self.messageId)
|
||||
|
||||
case .failure:
|
||||
XCTFail("Unexpected failure happened in send message")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Send message timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_SendMessage_ReturnError() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "UnauthorizedError", ofType: "json") ?? ""
|
||||
stub(condition: isMethodPOST()) { _ in
|
||||
fixture(filePath: path, status: 401, headers: nil)
|
||||
}
|
||||
|
||||
let messageRequest = SendChatMessageRequest(
|
||||
content: "Hello world!",
|
||||
senderDisplayName: "Leo"
|
||||
)
|
||||
|
||||
let expectation = self.expectation(description: "Send message")
|
||||
|
||||
chatThreadClient.send(message: messageRequest, completionHandler: { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
XCTFail("Unexpected failure happened in send message")
|
||||
|
||||
case let .failure(error):
|
||||
XCTAssertNotNil(error)
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Send message timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_GetMessage_ReturnSuccess() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "GetMessageResponse", ofType: "json") ?? ""
|
||||
stub(condition: isMethodGET()) { _ in
|
||||
fixture(filePath: path, status: 200, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "Get message")
|
||||
|
||||
chatThreadClient.get(message: messageId, completionHandler: { result, _ in
|
||||
switch result {
|
||||
case let .success(response):
|
||||
guard let content = response.content else {
|
||||
XCTFail("Failed to extract message content from response")
|
||||
return
|
||||
}
|
||||
XCTAssertNotNil(response)
|
||||
XCTAssertEqual(response.id, self.messageId)
|
||||
XCTAssertEqual(content.message, "Hello World!")
|
||||
|
||||
case .failure:
|
||||
XCTFail("Unexpected failure happened in get message")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Get message timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_GetMessage_ReturnError() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "UnauthorizedError", ofType: "json") ?? ""
|
||||
stub(condition: isMethodGET()) { _ in
|
||||
fixture(filePath: path, status: 401, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "Get message")
|
||||
|
||||
chatThreadClient.get(message: messageId, completionHandler: { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
XCTFail("Unexpected failure happened in get message")
|
||||
|
||||
case let .failure(error):
|
||||
XCTAssertNotNil(error)
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Get message timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_ListMessages_ReturnSuccess() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "ListMessagesResponse", ofType: "json") ?? ""
|
||||
stub(condition: isMethodGET()) { _ in
|
||||
fixture(filePath: path, status: 200, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "List messages")
|
||||
|
||||
chatThreadClient.listMessages(completionHandler: { result, _ in
|
||||
switch result {
|
||||
case let .success(response):
|
||||
XCTAssertNotNil(response)
|
||||
response.nextItem { result in
|
||||
switch result {
|
||||
case let .success(message):
|
||||
guard let content = message.content else {
|
||||
XCTFail("Failed to extract message content from response")
|
||||
return
|
||||
}
|
||||
XCTAssertEqual(message.id, self.messageId)
|
||||
XCTAssertEqual(content.message, "Hello world!")
|
||||
XCTAssertEqual(message.sender?.identifier, self.participantId)
|
||||
|
||||
case .failure:
|
||||
XCTFail("Unexpected failure happened in list messages")
|
||||
}
|
||||
}
|
||||
|
||||
case .failure:
|
||||
XCTFail("Unexpected failure happened in list messages")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("List messages timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_ListMessages_ReturnError() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "UnauthorizedError", ofType: "json") ?? ""
|
||||
stub(condition: isMethodGET()) { _ in
|
||||
fixture(filePath: path, status: 401, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "List messages")
|
||||
|
||||
chatThreadClient.listMessages(completionHandler: { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
XCTFail("Unexpected failure happened in list messages")
|
||||
|
||||
case let .failure(error):
|
||||
XCTAssertNotNil(error)
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("List messages timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_UpdateMessage_ReturnSuccess() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "NoContent", ofType: "json") ?? ""
|
||||
stub(condition: isMethodPATCH()) { _ in
|
||||
fixture(filePath: path, status: 204, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "Update message")
|
||||
|
||||
let message = UpdateChatMessageRequest(content: "update message")
|
||||
chatThreadClient.update(message: message, messageId: messageId, completionHandler: { result, _ in
|
||||
switch result {
|
||||
case let .success(response):
|
||||
XCTAssertNotNil(response)
|
||||
|
||||
case .failure:
|
||||
XCTFail("Unexpected failure happened in update message")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Update message timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_UpdateMessage_ReturnError() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "UnauthorizedError", ofType: "json") ?? ""
|
||||
stub(condition: isMethodPATCH()) { _ in
|
||||
fixture(filePath: path, status: 401, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "Update message")
|
||||
|
||||
chatThreadClient.update(topic: topic, completionHandler: { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
XCTFail("Unexpected failure happened in update message")
|
||||
|
||||
case let .failure(error):
|
||||
XCTAssertNotNil(error)
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Update message timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_DeleteMessage_ReturnSuccess() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "NoContent", ofType: "json") ?? ""
|
||||
stub(condition: isMethodDELETE()) { _ in
|
||||
fixture(filePath: path, status: 204, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "Delete message")
|
||||
|
||||
chatThreadClient.delete(message: messageId, completionHandler: { result, _ in
|
||||
switch result {
|
||||
case let .success(response):
|
||||
XCTAssertNotNil(response)
|
||||
|
||||
case .failure:
|
||||
XCTFail("Unexpected failure happened in delete message")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Delete message timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_DeleteMessage_ReturnError() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "UnauthorizedError", ofType: "json") ?? ""
|
||||
stub(condition: isMethodDELETE()) { _ in
|
||||
fixture(filePath: path, status: 401, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "Delete message")
|
||||
|
||||
chatThreadClient.delete(message: messageId, completionHandler: { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
XCTFail("Unexpected failure happened in delete message")
|
||||
|
||||
case let .failure(error):
|
||||
XCTAssertNotNil(error)
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Delete message timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_ListParticipants_ReturnSuccess() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "ListParticipantsResponse", ofType: "json") ?? ""
|
||||
stub(condition: isMethodGET()) { _ in
|
||||
fixture(filePath: path, status: 200, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "List participants")
|
||||
|
||||
chatThreadClient.listParticipants(completionHandler: { result, _ in
|
||||
switch result {
|
||||
case let .success(response):
|
||||
XCTAssertNotNil(response)
|
||||
response.nextItem { result in
|
||||
switch result {
|
||||
case let .success(participant):
|
||||
guard let displayName = participant.displayName else {
|
||||
XCTFail("Failed to extract senderDisplayName from response")
|
||||
return
|
||||
}
|
||||
XCTAssertEqual(participant.user.identifier, self.participantId)
|
||||
XCTAssertEqual(displayName, self.participantName)
|
||||
|
||||
case .failure:
|
||||
XCTFail("Unexpected failure happened in list participants")
|
||||
}
|
||||
}
|
||||
|
||||
case .failure:
|
||||
XCTFail("Unexpected failure happened in list participants")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("List participants timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_ListParticipants_ReturnError() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "UnauthorizedError", ofType: "json") ?? ""
|
||||
stub(condition: isMethodGET()) { _ in
|
||||
fixture(filePath: path, status: 401, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "List participants")
|
||||
|
||||
chatThreadClient.listParticipants(completionHandler: { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
XCTFail("Unexpected failure happened in list participants")
|
||||
|
||||
case let .failure(error):
|
||||
XCTAssertNotNil(error)
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("List participants timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_AddParticipant_ReturnSuccess() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "AddParticipantResponse", ofType: "json") ?? ""
|
||||
stub(condition: isMethodPOST()) { _ in
|
||||
fixture(filePath: path, status: 201, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "Add participant")
|
||||
|
||||
let participant = Participant(
|
||||
id: participantId,
|
||||
shareHistoryTime: Iso8601Date(string: "2016-04-13T00:00:00Z")!
|
||||
)
|
||||
|
||||
chatThreadClient.add(participants: [participant], completionHandler: { result, _ in
|
||||
switch result {
|
||||
case let .success(response):
|
||||
XCTAssertNotNil(response)
|
||||
|
||||
case .failure:
|
||||
XCTFail("Unexpected failure happened in Add participant")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Add participant timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_AddParticipant_ReturnError() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "UnauthorizedError", ofType: "json") ?? ""
|
||||
stub(condition: isMethodPOST()) { _ in
|
||||
fixture(filePath: path, status: 401, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "Add participant")
|
||||
|
||||
let participant = Participant(
|
||||
id: participantId,
|
||||
shareHistoryTime: Iso8601Date(string: "2016-04-13T00:00:00Z")!
|
||||
)
|
||||
|
||||
chatThreadClient.add(participants: [participant], completionHandler: { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
XCTFail("Unexpected failure happened in add participant")
|
||||
|
||||
case let .failure(error):
|
||||
XCTAssertNotNil(error)
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Add participant timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_RemoveParticipant_ReturnSuccess() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "NoContent", ofType: "json") ?? ""
|
||||
stub(condition: isMethodDELETE()) { _ in
|
||||
fixture(filePath: path, status: 204, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "Remove Participant")
|
||||
|
||||
chatThreadClient.remove(participant: participantId, completionHandler: { result, _ in
|
||||
switch result {
|
||||
case let .success(response):
|
||||
XCTAssertNotNil(response)
|
||||
|
||||
case .failure:
|
||||
XCTFail("Unexpected failure happened in remove participant")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Remove participant timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_RemoveParticipant_ReturnError() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "UnauthorizedError", ofType: "json") ?? ""
|
||||
stub(condition: isMethodDELETE()) { _ in
|
||||
fixture(filePath: path, status: 401, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "Remove Participant")
|
||||
|
||||
chatThreadClient.remove(participant: participantId, completionHandler: { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
XCTFail("Unexpected failure happened in remove participant")
|
||||
|
||||
case let .failure(error):
|
||||
XCTAssertNotNil(error)
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Remove participant timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_SendTypingNotification_ReturnSuccess() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "NoContent", ofType: "json") ?? ""
|
||||
stub(condition: isMethodPOST()) { _ in
|
||||
fixture(filePath: path, status: 200, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "Send typing notification")
|
||||
|
||||
chatThreadClient.sendTypingNotification(completionHandler: { result, _ in
|
||||
switch result {
|
||||
case let .success(response):
|
||||
XCTAssertNotNil(response)
|
||||
|
||||
case .failure:
|
||||
XCTFail("Unexpected failure happened in send typing notification")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Send typing notification timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_SendTypingNotification_ReturnError() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "UnauthorizedError", ofType: "json") ?? ""
|
||||
stub(condition: isMethodPOST()) { _ in
|
||||
fixture(filePath: path, status: 401, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "Send typing notification")
|
||||
|
||||
chatThreadClient.sendTypingNotification(completionHandler: { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
XCTFail("Unexpected failure happened in send typing notification")
|
||||
|
||||
case let .failure(error):
|
||||
XCTAssertNotNil(error)
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Send typing notification timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_SendReadReceipt_ReturnSuccess() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "NoContent", ofType: "json") ?? ""
|
||||
stub(condition: isMethodPOST()) { _ in
|
||||
fixture(filePath: path, status: 200, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "Send read receipt")
|
||||
|
||||
chatThreadClient.sendReadReceipt(forMessage: messageId, completionHandler: { result, _ in
|
||||
switch result {
|
||||
case let .success(response):
|
||||
XCTAssertNotNil(response)
|
||||
|
||||
case .failure:
|
||||
XCTFail("Unexpected failure happened in send read receipt")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Send read receipt timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_SendReadReceipt_ReturnError() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "UnauthorizedError", ofType: "json") ?? ""
|
||||
stub(condition: isMethodPOST()) { _ in
|
||||
fixture(filePath: path, status: 401, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "Send read receipt")
|
||||
|
||||
chatThreadClient.sendReadReceipt(forMessage: messageId, completionHandler: { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
XCTFail("Unexpected failure happened in send read receipt")
|
||||
|
||||
case let .failure(error):
|
||||
XCTAssertNotNil(error)
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("Send read receipt timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_ListReadReceipts_ReturnSuccess() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "ListReadReceiptResponse", ofType: "json") ?? ""
|
||||
stub(condition: isMethodGET()) { _ in
|
||||
fixture(filePath: path, status: 200, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "List read receipts")
|
||||
|
||||
chatThreadClient.listReadReceipts(completionHandler: { result, _ in
|
||||
switch result {
|
||||
case let .success(response):
|
||||
XCTAssertNotNil(response)
|
||||
response.nextItem { result in
|
||||
switch result {
|
||||
case let .success(readReceipt):
|
||||
XCTAssertEqual(readReceipt.sender.identifier, self.participantId)
|
||||
XCTAssertEqual(readReceipt.chatMessageId, self.messageId)
|
||||
XCTAssertNotNil(readReceipt.readOn)
|
||||
|
||||
case .failure:
|
||||
XCTFail("Unexpected failure happened in list read receipts")
|
||||
}
|
||||
}
|
||||
|
||||
case .failure:
|
||||
XCTFail("Unexpected failure happened in list read receipts")
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("List read receipts timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func test_ListReadReceipts_ReturnError() {
|
||||
let bundle = Bundle(for: type(of: self))
|
||||
let path = bundle.path(forResource: "UnauthorizedError", ofType: "json") ?? ""
|
||||
stub(condition: isMethodGET()) { _ in
|
||||
fixture(filePath: path, status: 401, headers: nil)
|
||||
}
|
||||
|
||||
let expectation = self.expectation(description: "List read receipts")
|
||||
|
||||
chatThreadClient.listReadReceipts(completionHandler: { result, _ in
|
||||
switch result {
|
||||
case .success:
|
||||
XCTFail("Unexpected failure happened in list read receipt")
|
||||
|
||||
case let .failure(error):
|
||||
XCTAssertNotNil(error)
|
||||
}
|
||||
|
||||
expectation.fulfill()
|
||||
})
|
||||
|
||||
waitForExpectations(timeout: TestUtil.timeout) { error in
|
||||
if let error = error {
|
||||
XCTFail("List read receipts timed out: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"chatThread": {
|
||||
"id": "test_thread_id",
|
||||
"topic": "test topic",
|
||||
"createdOn": "2021-01-08T01:49:05Z",
|
||||
"createdBy": "test_participant_id"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"id": "test_message_id",
|
||||
"type": "text",
|
||||
"sequenceId": "3",
|
||||
"version": "1610070518313",
|
||||
"content": {
|
||||
"message": "Hello World!"
|
||||
},
|
||||
"senderDisplayName": "User 1",
|
||||
"createdOn": "2021-01-08T01:48:38Z",
|
||||
"senderId": "test_sender_id"
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"id": "test_thread_id",
|
||||
"topic": "test topic",
|
||||
"createdOn": "2020-10-30T10:50:50Z",
|
||||
"createdBy": "test_participant_id",
|
||||
"deletedOn": "2020-10-30T10:50:50Z"
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"value": [
|
||||
{
|
||||
"id": "test_message_id",
|
||||
"type": "text",
|
||||
"sequenceId": "4",
|
||||
"version": "string",
|
||||
"content": {
|
||||
"message": "Hello world!"
|
||||
},
|
||||
"senderDisplayName": "Jane",
|
||||
"createdOn": "2020-10-30T10:50:50Z",
|
||||
"senderId": "test_participant_id",
|
||||
"deletedOn": "2020-10-30T10:50:50Z",
|
||||
"editedOn": "2020-10-30T10:50:50Z"
|
||||
}
|
||||
],
|
||||
"nextLink": "string"
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"value": [
|
||||
{
|
||||
"id": "test_participant_id",
|
||||
"displayName": "test_participant_name",
|
||||
"shareHistoryTime": "2020-10-30T10:50:50Z"
|
||||
}
|
||||
],
|
||||
"nextLink": "string"
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"value": [
|
||||
{
|
||||
"senderId": "test_participant_id",
|
||||
"chatMessageId": "test_message_id",
|
||||
"readOn": "2020-10-30T10:50:50Z"
|
||||
}
|
||||
],
|
||||
"nextLink": "string"
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"value": [
|
||||
{
|
||||
"id": "test_thread_id",
|
||||
"topic": "test topic",
|
||||
"deletedOn": "2020-10-30T10:50:50Z",
|
||||
"lastMessageReceivedOn": "2020-10-30T10:50:50Z"
|
||||
}
|
||||
],
|
||||
"nextLink": "string"
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"id": "test_message_id"
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"code": "401",
|
||||
"message": "Unauthorized",
|
||||
"target": "test_participant_id"
|
||||
}
|
|
@ -0,0 +1,206 @@
|
|||
// --------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the ""Software""), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
import AzureCore
|
||||
import Foundation
|
||||
import OHHTTPStubsSwift
|
||||
|
||||
class Recorder {
|
||||
/// Remove ids from response data
|
||||
/// - Parameter data: The string to sanitize.
|
||||
private static func sanitize(data: String) throws -> String {
|
||||
let patterns = [
|
||||
("\\\"id\\\":\\\".*?\\\"", "\\\"id\\\":\\\"sanitized\\\""),
|
||||
("\\\"createdBy\\\":\\\".*?\\\"", "\\\"createdBy\\\":\\\"sanitized\\\""),
|
||||
("\\\"senderId\\\":\\\".*?\\\"", "\\\"senderId\\\":\\\"sanitized\\\""),
|
||||
("\\\"initiator\\\":\\\".*?\\\"", "\\\"initator\\\":\\\"sanitized\\\""),
|
||||
("\\\"chatMessageId\\\":\\\".*?\\\"", "\\\"chatMessageId\\\":\\\"sanitized\\\"")
|
||||
]
|
||||
var sanitized = data
|
||||
for (pattern, template) in patterns {
|
||||
sanitized = try sanitize(data: sanitized, pattern: pattern, template: template)
|
||||
}
|
||||
return sanitized
|
||||
}
|
||||
|
||||
private static func sanitize(data: String, pattern: String, template: String) throws -> String {
|
||||
let regex = try NSRegularExpression(pattern: pattern, options: .caseInsensitive)
|
||||
return regex.stringByReplacingMatches(
|
||||
in: data,
|
||||
range: NSRange(0 ..< data.utf16.count),
|
||||
withTemplate: template
|
||||
)
|
||||
}
|
||||
|
||||
/// Writes an HTTPResponse to a file for playback.
|
||||
/// - Parameters:
|
||||
/// - name: The name of the recording, used as the filename.
|
||||
/// - httpResponse: The HTTPResponse returned by the request.
|
||||
public static func record(
|
||||
name: Recording,
|
||||
httpResponse: HTTPResponse?
|
||||
) {
|
||||
guard let response = httpResponse else {
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
// Get filepath
|
||||
var url = URL(fileURLWithPath: #filePath)
|
||||
url.deleteLastPathComponent()
|
||||
var path = url.path
|
||||
path.append("/Recordings/\(name).json")
|
||||
|
||||
// Create recording file, will overwrite existing
|
||||
FileManager.default.createFile(atPath: path, contents: nil)
|
||||
|
||||
// Get response body from data
|
||||
guard let responseData = String(data: response.data!, encoding: .utf8) else {
|
||||
return
|
||||
}
|
||||
|
||||
// Remove ids from the response
|
||||
let sanitized = try sanitize(data: responseData)
|
||||
|
||||
// Write response to file
|
||||
try sanitized.write(toFile: path, atomically: true, encoding: .utf8)
|
||||
} catch {
|
||||
print(error.localizedDescription)
|
||||
}
|
||||
}
|
||||
|
||||
/// Register a stub for each ACS call
|
||||
public static func registerStubs() {
|
||||
for recording in Recording.allCases {
|
||||
register(stub: recording)
|
||||
}
|
||||
}
|
||||
|
||||
/// Registers a stub for the given recording.
|
||||
/// - Parameter recording: The recording to stub
|
||||
private static func register(stub recording: Recording) {
|
||||
let bundle = Bundle(for: Self.self)
|
||||
let path = bundle.path(forResource: recording.rawValue, ofType: "json")!
|
||||
|
||||
switch recording {
|
||||
case Recording.addParticipants:
|
||||
stub(condition: isMethodPOST() && pathEndsWith("/participants/:add")) { _ in
|
||||
fixture(filePath: path, status: 201, headers: nil)
|
||||
}
|
||||
|
||||
case Recording.createThread:
|
||||
stub(condition: isMethodPOST() && pathEndsWith("/chat/threads")) { _ in
|
||||
fixture(filePath: path, status: 201, headers: nil)
|
||||
}
|
||||
|
||||
case Recording.deleteMessage:
|
||||
stub(condition: isMethodDELETE() && pathMatches("//messages//")) { _ in
|
||||
fixture(filePath: path, status: 204, headers: nil)
|
||||
}
|
||||
|
||||
case Recording.deleteThread:
|
||||
stub(condition: isMethodDELETE() && pathStartsWith("/chat/threads/")) { _ in
|
||||
fixture(filePath: path, status: 204, headers: nil)
|
||||
}
|
||||
|
||||
case Recording.getThread:
|
||||
stub(condition: isMethodGET() && pathStartsWith("/chat/threads/")) { _ in
|
||||
fixture(filePath: path, status: 200, headers: nil)
|
||||
}
|
||||
|
||||
case Recording.removeParticipant:
|
||||
stub(condition: isMethodDELETE() && pathMatches("//participants//")) { _ in
|
||||
fixture(filePath: path, status: 204, headers: nil)
|
||||
}
|
||||
|
||||
case Recording.sendMessage:
|
||||
stub(condition: isMethodPOST() && pathEndsWith("/messages")) { _ in
|
||||
fixture(filePath: path, status: 201, headers: nil)
|
||||
}
|
||||
|
||||
case Recording.sendReadReceipt:
|
||||
stub(condition: isMethodPOST() && pathEndsWith("/readReceipts")) { _ in
|
||||
fixture(filePath: path, status: 200, headers: nil)
|
||||
}
|
||||
|
||||
case Recording.sendTypingNotification:
|
||||
stub(condition: isMethodPOST() && pathEndsWith("/typing")) { _ in
|
||||
fixture(filePath: path, status: 200, headers: nil)
|
||||
}
|
||||
|
||||
case Recording.updateMessage:
|
||||
stub(condition: isMethodPATCH() && pathMatches("/messages/")) { _ in
|
||||
fixture(filePath: path, status: 204, headers: nil)
|
||||
}
|
||||
|
||||
case Recording.updateTopic:
|
||||
stub(condition: isMethodPATCH() && pathStartsWith("/chat/threads")) { _ in
|
||||
fixture(filePath: path, status: 204, headers: nil)
|
||||
}
|
||||
|
||||
case Recording.listParticipants:
|
||||
stub(condition: isMethodGET() && pathEndsWith("/participants")) { _ in
|
||||
fixture(filePath: path, status: 200, headers: nil)
|
||||
}
|
||||
|
||||
case Recording.listMessages:
|
||||
stub(condition: isMethodGET() && pathEndsWith("/messages")) { _ in
|
||||
fixture(filePath: path, status: 200, headers: nil)
|
||||
}
|
||||
|
||||
case Recording.listThreads:
|
||||
stub(condition: isMethodGET() && pathEndsWith("/threads")) { _ in
|
||||
fixture(filePath: path, status: 200, headers: nil)
|
||||
}
|
||||
|
||||
case Recording.listReadReceipts:
|
||||
stub(condition: isMethodGET() && pathEndsWith("/readReceipts")) { _ in
|
||||
fixture(filePath: path, status: 200, headers: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Names for stubbing network calls
|
||||
enum Recording: String, CaseIterable {
|
||||
// ChatClient
|
||||
case createThread
|
||||
case getThread
|
||||
case deleteThread
|
||||
// ChatThreadClient
|
||||
case updateTopic
|
||||
case sendReadReceipt
|
||||
case sendTypingNotification
|
||||
case sendMessage
|
||||
case updateMessage
|
||||
case deleteMessage
|
||||
case addParticipants
|
||||
case removeParticipant
|
||||
case listParticipants
|
||||
case listMessages
|
||||
case listThreads
|
||||
case listReadReceipts
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -0,0 +1 @@
|
|||
{"chatThread":{"id":"sanitized","topic":"General","createdOn":"2021-01-26T02:42:15Z","createdBy":"sanitized"}}
|
|
@ -0,0 +1 @@
|
|||
{"id":"sanitized","topic":"General","createdOn":"2021-01-26T02:41:36Z","createdBy":"sanitized"}
|
|
@ -0,0 +1 @@
|
|||
{"value":[{"id":"sanitized","type":"text","sequenceId":"4","version":"1611628909524","content":{"message":"Hello World!"},"senderDisplayName":"User 1","createdOn":"2021-01-26T02:41:49Z","senderId":"sanitized"},{"id":"sanitized","type":"text","sequenceId":"3","version":"1611628908993","content":{"message":"Hello World!"},"senderDisplayName":"User 1","createdOn":"2021-01-26T02:41:48Z","senderId":"sanitized"},{"id":"sanitized","type":"topicUpdated","sequenceId":"2","version":"1611628907883","content":{"topic":"General","initator":"sanitized"},"createdOn":"2021-01-26T02:41:47Z","senderId":"sanitized"},{"id":"sanitized","type":"participantAdded","sequenceId":"1","version":"1611628907852","content":{"participants":[{"id":"sanitized","displayName":"User 1","shareHistoryTime":"1970-01-01T00:00:00Z"}],"initator":"sanitized"},"createdOn":"2021-01-26T02:41:47Z","senderId":"sanitized"}]}
|
|
@ -0,0 +1 @@
|
|||
{"value":[{"id":"sanitized","displayName":"User 1","shareHistoryTime":"1970-01-01T00:00:00Z"},{"id":"sanitized","displayName":"User 2","shareHistoryTime":"2016-04-13T00:00:00Z"}]}
|
|
@ -0,0 +1 @@
|
|||
{"value":[{"senderId":"sanitized","chatMessageId":"sanitized","readOn":"2021-01-26T02:41:57Z"}]}
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -0,0 +1 @@
|
|||
{"id":"sanitized"}
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче