* 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:
knvsl 2021-02-08 13:04:24 -08:00 коммит произвёл GitHub
Родитель 8b04ebfcae
Коммит 41039cc13f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
105 изменённых файлов: 6626 добавлений и 2215 удалений

2
.gitignore поставляемый
Просмотреть файл

@ -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

Просмотреть файл

@ -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
Просмотреть файл

@ -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"}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше