From 4316016f4b9ca1c9992588d1e83be42e2ab61ee6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthew=28=EB=A7=A4=ED=8A=9C=29?=
<130636633+kimbs5899@users.noreply.github.com>
Date: Wed, 27 Mar 2024 17:37:14 +0900
Subject: [PATCH 01/24] =?UTF-8?q?docs:=20apiKey=20ignore=20=EC=B6=94?=
=?UTF-8?q?=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index baa8870d..c0e6c4fb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -100,6 +100,7 @@ iOSInjectionProject/
### DS_Store ###
.DS_Store
+Private.plist
### Secret.xcconfig
BoxOffice/Secret.xcconfig
From 33a4996859e61cfc029c2f86601969b53b1ec3f4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthew=28=EB=A7=A4=ED=8A=9C=29?=
<130636633+kimbs5899@users.noreply.github.com>
Date: Wed, 27 Mar 2024 17:37:46 +0900
Subject: [PATCH 02/24] =?UTF-8?q?chore:=20=ED=8C=8C=EC=9D=BC=EB=AA=85=20?=
=?UTF-8?q?=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.gitignore b/.gitignore
index c0e6c4fb..975d65af 100644
--- a/.gitignore
+++ b/.gitignore
@@ -100,7 +100,7 @@ iOSInjectionProject/
### DS_Store ###
.DS_Store
-Private.plist
+APIToken.plist
### Secret.xcconfig
BoxOffice/Secret.xcconfig
From 5f863310d1b3423ac68e8541d80803e8273c734f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthew=28=EB=A7=A4=ED=8A=9C=29?=
<130636633+kimbs5899@users.noreply.github.com>
Date: Wed, 27 Mar 2024 17:38:08 +0900
Subject: [PATCH 03/24] =?UTF-8?q?remove:=20APIToken=20=EC=82=AD=EC=A0=9C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
ChatBot/ChatBot/Resource/APIToken.plist | 8 --------
1 file changed, 8 deletions(-)
delete mode 100644 ChatBot/ChatBot/Resource/APIToken.plist
diff --git a/ChatBot/ChatBot/Resource/APIToken.plist b/ChatBot/ChatBot/Resource/APIToken.plist
deleted file mode 100644
index 5bc13607..00000000
--- a/ChatBot/ChatBot/Resource/APIToken.plist
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
- API_Token
- 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
-
-
From f485a63de545c4cb836a5af5b08d9637a6e60d8c Mon Sep 17 00:00:00 2001
From: LeeSe0ngYe0n
Date: Tue, 2 Apr 2024 17:02:49 +0900
Subject: [PATCH 04/24] test: APIToken Test
---
ChatBot/ChatBot.xcodeproj/project.pbxproj | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/ChatBot/ChatBot.xcodeproj/project.pbxproj b/ChatBot/ChatBot.xcodeproj/project.pbxproj
index bc17e3cd..b40f2f87 100644
--- a/ChatBot/ChatBot.xcodeproj/project.pbxproj
+++ b/ChatBot/ChatBot.xcodeproj/project.pbxproj
@@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
+ 9B76B2B02BBBF2F00089676F /* APIToken.plist in Resources */ = {isa = PBXBuildFile; fileRef = 9B76B2AF2BBBF2F00089676F /* APIToken.plist */; };
C12E66D32BB3F28800F3F441 /* ChatManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66B82BB3F28800F3F441 /* ChatManager.swift */; };
C12E66D42BB3F28800F3F441 /* ChatRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66B92BB3F28800F3F441 /* ChatRepository.swift */; };
C12E66D52BB3F28800F3F441 /* RequestChatDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66BA2BB3F28800F3F441 /* RequestChatDTO.swift */; };
@@ -28,11 +29,11 @@
C12E66EC2BB4291A00F3F441 /* ResponseChoiceDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66EB2BB4291A00F3F441 /* ResponseChoiceDTO.swift */; };
C12E66EE2BB4294300F3F441 /* Usage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66ED2BB4294300F3F441 /* Usage.swift */; };
C12E66F02BB429AA00F3F441 /* JSONNull.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66EF2BB429AA00F3F441 /* JSONNull.swift */; };
- C1A0CBCC2BB55663009A000F /* APIToken.plist in Resources */ = {isa = PBXBuildFile; fileRef = C1A0CBCB2BB55663009A000F /* APIToken.plist */; };
C1E416662BB9888C00D8C836 /* UIViewController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1E416652BB9888C00D8C836 /* UIViewController+Extension.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
+ 9B76B2AF2BBBF2F00089676F /* APIToken.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = APIToken.plist; path = ../../../../../APIToken.plist; sourceTree = ""; };
B4B3E2B92B42D1BB00818B3C /* ChatBot.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ChatBot.app; sourceTree = BUILT_PRODUCTS_DIR; };
C12E66B82BB3F28800F3F441 /* ChatManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatManager.swift; sourceTree = ""; };
C12E66B92BB3F28800F3F441 /* ChatRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatRepository.swift; sourceTree = ""; };
@@ -56,7 +57,6 @@
C12E66EB2BB4291A00F3F441 /* ResponseChoiceDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResponseChoiceDTO.swift; sourceTree = ""; };
C12E66ED2BB4294300F3F441 /* Usage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Usage.swift; sourceTree = ""; };
C12E66EF2BB429AA00F3F441 /* JSONNull.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONNull.swift; sourceTree = ""; };
- C1A0CBCB2BB55663009A000F /* APIToken.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = APIToken.plist; path = ../../../../../../Matthew/Desktop/APIToken.plist; sourceTree = ""; };
C1E416652BB9888C00D8C836 /* UIViewController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Extension.swift"; sourceTree = ""; };
/* End PBXFileReference section */
@@ -139,7 +139,7 @@
children = (
C12E66C32BB3F28800F3F441 /* Assets.xcassets */,
C12E66C42BB3F28800F3F441 /* Info.plist */,
- C1A0CBCB2BB55663009A000F /* APIToken.plist */,
+ 9B76B2AF2BBBF2F00089676F /* APIToken.plist */,
);
path = Resource;
sourceTree = "";
@@ -232,9 +232,9 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- C1A0CBCC2BB55663009A000F /* APIToken.plist in Resources */,
C12E66DB2BB3F28800F3F441 /* Assets.xcassets in Resources */,
C12E66E52BB3F28800F3F441 /* LaunchScreen.storyboard in Resources */,
+ 9B76B2B02BBBF2F00089676F /* APIToken.plist in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
From 0cb1b0c6ac21028aa959bd341b35110500625080 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthew=28=EB=A7=A4=ED=8A=9C=29?=
Date: Thu, 4 Apr 2024 20:35:18 +0900
Subject: [PATCH 05/24] =?UTF-8?q?feat:=20RxSwift,=20Snapkit,=20Then,=20RxA?=
=?UTF-8?q?lamofire=20=EB=9D=BC=EC=9D=B4=EB=B8=8C=EB=9F=AC=EB=A6=AC=20?=
=?UTF-8?q?=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
ChatBot/ChatBot.xcodeproj/project.pbxproj | 156 ++++++++++++++----
ChatBot/ChatBot/App/SceneDelegate.swift | 4 +-
.../Controller/ChatBotViewController.swift | 54 ------
.../Extension/URLSession+Extension.swift | 14 --
ChatBot/ChatBot/Model/ChatManager.swift | 26 ---
.../{UserMessage.swift => Message.swift} | 0
ChatBot/ChatBot/Network/ChatBotNetwork.swift | 8 +
ChatBot/ChatBot/Network/Network.swift | 8 +
ChatBot/ChatBot/Network/NetworkProvider.swift | 8 +
.../ChatBot/Network/URLSessionProtocol.swift | 13 --
.../ChatBot/View/ChatBotViewController.swift | 70 ++++++++
.../ChatBot/ViewModel/ChatBotViewModel.swift | 41 +++++
12 files changed, 260 insertions(+), 142 deletions(-)
delete mode 100644 ChatBot/ChatBot/Controller/ChatBotViewController.swift
delete mode 100644 ChatBot/ChatBot/Extension/URLSession+Extension.swift
delete mode 100644 ChatBot/ChatBot/Model/ChatManager.swift
rename ChatBot/ChatBot/Model/{UserMessage.swift => Message.swift} (100%)
create mode 100644 ChatBot/ChatBot/Network/ChatBotNetwork.swift
create mode 100644 ChatBot/ChatBot/Network/Network.swift
create mode 100644 ChatBot/ChatBot/Network/NetworkProvider.swift
delete mode 100644 ChatBot/ChatBot/Network/URLSessionProtocol.swift
create mode 100644 ChatBot/ChatBot/View/ChatBotViewController.swift
create mode 100644 ChatBot/ChatBot/ViewModel/ChatBotViewModel.swift
diff --git a/ChatBot/ChatBot.xcodeproj/project.pbxproj b/ChatBot/ChatBot.xcodeproj/project.pbxproj
index b40f2f87..75b4cc16 100644
--- a/ChatBot/ChatBot.xcodeproj/project.pbxproj
+++ b/ChatBot/ChatBot.xcodeproj/project.pbxproj
@@ -7,13 +7,11 @@
objects = {
/* Begin PBXBuildFile section */
- 9B76B2B02BBBF2F00089676F /* APIToken.plist in Resources */ = {isa = PBXBuildFile; fileRef = 9B76B2AF2BBBF2F00089676F /* APIToken.plist */; };
- C12E66D32BB3F28800F3F441 /* ChatManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66B82BB3F28800F3F441 /* ChatManager.swift */; };
+ C12E66D32BB3F28800F3F441 /* ChatBotViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66B82BB3F28800F3F441 /* ChatBotViewModel.swift */; };
C12E66D42BB3F28800F3F441 /* ChatRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66B92BB3F28800F3F441 /* ChatRepository.swift */; };
C12E66D52BB3F28800F3F441 /* RequestChatDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66BA2BB3F28800F3F441 /* RequestChatDTO.swift */; };
- C12E66D62BB3F28800F3F441 /* UserMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66BB2BB3F28800F3F441 /* UserMessage.swift */; };
+ C12E66D62BB3F28800F3F441 /* Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66BB2BB3F28800F3F441 /* Message.swift */; };
C12E66D72BB3F28800F3F441 /* Bundle+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66BD2BB3F28800F3F441 /* Bundle+Extension.swift */; };
- C12E66D82BB3F28800F3F441 /* URLSession+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66BE2BB3F28800F3F441 /* URLSession+Extension.swift */; };
C12E66D92BB3F28800F3F441 /* ChatBotViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66C02BB3F28800F3F441 /* ChatBotViewController.swift */; };
C12E66DB2BB3F28800F3F441 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C12E66C32BB3F28800F3F441 /* Assets.xcassets */; };
C12E66DD2BB3F28800F3F441 /* APIService.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66C62BB3F28800F3F441 /* APIService.swift */; };
@@ -21,7 +19,6 @@
C12E66DF2BB3F28800F3F441 /* HttpMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66C82BB3F28800F3F441 /* HttpMethod.swift */; };
C12E66E02BB3F28800F3F441 /* NetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66C92BB3F28800F3F441 /* NetworkError.swift */; };
C12E66E12BB3F28800F3F441 /* NetworkURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66CA2BB3F28800F3F441 /* NetworkURL.swift */; };
- C12E66E22BB3F28800F3F441 /* URLSessionProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66CB2BB3F28800F3F441 /* URLSessionProtocol.swift */; };
C12E66E32BB3F28800F3F441 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66CD2BB3F28800F3F441 /* AppDelegate.swift */; };
C12E66E42BB3F28800F3F441 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66CE2BB3F28800F3F441 /* SceneDelegate.swift */; };
C12E66E52BB3F28800F3F441 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C12E66D12BB3F28800F3F441 /* LaunchScreen.storyboard */; };
@@ -29,18 +26,25 @@
C12E66EC2BB4291A00F3F441 /* ResponseChoiceDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66EB2BB4291A00F3F441 /* ResponseChoiceDTO.swift */; };
C12E66EE2BB4294300F3F441 /* Usage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66ED2BB4294300F3F441 /* Usage.swift */; };
C12E66F02BB429AA00F3F441 /* JSONNull.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66EF2BB429AA00F3F441 /* JSONNull.swift */; };
+ C1865DA12BBE945000DD99C9 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = C1865DA02BBE945000DD99C9 /* SnapKit */; };
+ C1865DA32BBE945000DD99C9 /* SnapKit-Dynamic in Frameworks */ = {isa = PBXBuildFile; productRef = C1865DA22BBE945000DD99C9 /* SnapKit-Dynamic */; };
+ C1865DA62BBE945D00DD99C9 /* Then in Frameworks */ = {isa = PBXBuildFile; productRef = C1865DA52BBE945D00DD99C9 /* Then */; };
+ C1865DA92BBE946D00DD99C9 /* RxAlamofire in Frameworks */ = {isa = PBXBuildFile; productRef = C1865DA82BBE946D00DD99C9 /* RxAlamofire */; };
+ C1865DB22BBE948000DD99C9 /* RxSwift in Frameworks */ = {isa = PBXBuildFile; productRef = C1865DB12BBE948000DD99C9 /* RxSwift */; };
+ C1865DB62BBE94A600DD99C9 /* APIToken.plist in Resources */ = {isa = PBXBuildFile; fileRef = C1865DB52BBE94A600DD99C9 /* APIToken.plist */; };
+ C1865DB82BBE9C3400DD99C9 /* Network.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1865DB72BBE9C3400DD99C9 /* Network.swift */; };
+ C1865DBA2BBE9E8600DD99C9 /* NetworkProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1865DB92BBE9E8600DD99C9 /* NetworkProvider.swift */; };
+ C1865DBC2BBEB72900DD99C9 /* ChatBotNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1865DBB2BBEB72900DD99C9 /* ChatBotNetwork.swift */; };
C1E416662BB9888C00D8C836 /* UIViewController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1E416652BB9888C00D8C836 /* UIViewController+Extension.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
- 9B76B2AF2BBBF2F00089676F /* APIToken.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = APIToken.plist; path = ../../../../../APIToken.plist; sourceTree = ""; };
B4B3E2B92B42D1BB00818B3C /* ChatBot.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ChatBot.app; sourceTree = BUILT_PRODUCTS_DIR; };
- C12E66B82BB3F28800F3F441 /* ChatManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatManager.swift; sourceTree = ""; };
+ C12E66B82BB3F28800F3F441 /* ChatBotViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatBotViewModel.swift; sourceTree = ""; };
C12E66B92BB3F28800F3F441 /* ChatRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatRepository.swift; sourceTree = ""; };
C12E66BA2BB3F28800F3F441 /* RequestChatDTO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestChatDTO.swift; sourceTree = ""; };
- C12E66BB2BB3F28800F3F441 /* UserMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserMessage.swift; sourceTree = ""; };
+ C12E66BB2BB3F28800F3F441 /* Message.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Message.swift; sourceTree = ""; };
C12E66BD2BB3F28800F3F441 /* Bundle+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Bundle+Extension.swift"; sourceTree = ""; };
- C12E66BE2BB3F28800F3F441 /* URLSession+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "URLSession+Extension.swift"; sourceTree = ""; };
C12E66C02BB3F28800F3F441 /* ChatBotViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatBotViewController.swift; sourceTree = ""; };
C12E66C32BB3F28800F3F441 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
C12E66C42BB3F28800F3F441 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
@@ -49,7 +53,6 @@
C12E66C82BB3F28800F3F441 /* HttpMethod.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HttpMethod.swift; sourceTree = ""; };
C12E66C92BB3F28800F3F441 /* NetworkError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkError.swift; sourceTree = ""; };
C12E66CA2BB3F28800F3F441 /* NetworkURL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkURL.swift; sourceTree = ""; };
- C12E66CB2BB3F28800F3F441 /* URLSessionProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLSessionProtocol.swift; sourceTree = ""; };
C12E66CD2BB3F28800F3F441 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
C12E66CE2BB3F28800F3F441 /* SceneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
C12E66D02BB3F28800F3F441 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
@@ -57,6 +60,10 @@
C12E66EB2BB4291A00F3F441 /* ResponseChoiceDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResponseChoiceDTO.swift; sourceTree = ""; };
C12E66ED2BB4294300F3F441 /* Usage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Usage.swift; sourceTree = ""; };
C12E66EF2BB429AA00F3F441 /* JSONNull.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONNull.swift; sourceTree = ""; };
+ C1865DB52BBE94A600DD99C9 /* APIToken.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = APIToken.plist; sourceTree = ""; };
+ C1865DB72BBE9C3400DD99C9 /* Network.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Network.swift; sourceTree = ""; };
+ C1865DB92BBE9E8600DD99C9 /* NetworkProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProvider.swift; sourceTree = ""; };
+ C1865DBB2BBEB72900DD99C9 /* ChatBotNetwork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatBotNetwork.swift; sourceTree = ""; };
C1E416652BB9888C00D8C836 /* UIViewController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Extension.swift"; sourceTree = ""; };
/* End PBXFileReference section */
@@ -65,6 +72,11 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ C1865DA12BBE945000DD99C9 /* SnapKit in Frameworks */,
+ C1865DA92BBE946D00DD99C9 /* RxAlamofire in Frameworks */,
+ C1865DA62BBE945D00DD99C9 /* Then in Frameworks */,
+ C1865DA32BBE945000DD99C9 /* SnapKit-Dynamic in Frameworks */,
+ C1865DB22BBE948000DD99C9 /* RxSwift in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -91,12 +103,12 @@
isa = PBXGroup;
children = (
C12E66CF2BB3F28800F3F441 /* App */,
- C12E66C12BB3F28800F3F441 /* Controller */,
- C12E66BF2BB3F28800F3F441 /* Extension */,
C12E66BC2BB3F28800F3F441 /* Model */,
+ C12E66D22BB3F28800F3F441 /* View */,
+ C1865DBD2BBEC71B00DD99C9 /* ViewModel */,
+ C12E66BF2BB3F28800F3F441 /* Extension */,
C12E66CC2BB3F28800F3F441 /* Network */,
C12E66C52BB3F28800F3F441 /* Resource */,
- C12E66D22BB3F28800F3F441 /* View */,
);
path = ChatBot;
sourceTree = "";
@@ -104,10 +116,9 @@
C12E66BC2BB3F28800F3F441 /* Model */ = {
isa = PBXGroup;
children = (
- C12E66B82BB3F28800F3F441 /* ChatManager.swift */,
C12E66B92BB3F28800F3F441 /* ChatRepository.swift */,
C12E66BA2BB3F28800F3F441 /* RequestChatDTO.swift */,
- C12E66BB2BB3F28800F3F441 /* UserMessage.swift */,
+ C12E66BB2BB3F28800F3F441 /* Message.swift */,
C12E66E92BB4283100F3F441 /* ResponseChatDTO.swift */,
C12E66EB2BB4291A00F3F441 /* ResponseChoiceDTO.swift */,
C12E66ED2BB4294300F3F441 /* Usage.swift */,
@@ -120,26 +131,17 @@
isa = PBXGroup;
children = (
C12E66BD2BB3F28800F3F441 /* Bundle+Extension.swift */,
- C12E66BE2BB3F28800F3F441 /* URLSession+Extension.swift */,
C1E416652BB9888C00D8C836 /* UIViewController+Extension.swift */,
);
path = Extension;
sourceTree = "";
};
- C12E66C12BB3F28800F3F441 /* Controller */ = {
- isa = PBXGroup;
- children = (
- C12E66C02BB3F28800F3F441 /* ChatBotViewController.swift */,
- );
- path = Controller;
- sourceTree = "";
- };
C12E66C52BB3F28800F3F441 /* Resource */ = {
isa = PBXGroup;
children = (
C12E66C32BB3F28800F3F441 /* Assets.xcassets */,
C12E66C42BB3F28800F3F441 /* Info.plist */,
- 9B76B2AF2BBBF2F00089676F /* APIToken.plist */,
+ C1865DB52BBE94A600DD99C9 /* APIToken.plist */,
);
path = Resource;
sourceTree = "";
@@ -147,12 +149,14 @@
C12E66CC2BB3F28800F3F441 /* Network */ = {
isa = PBXGroup;
children = (
- C12E66C62BB3F28800F3F441 /* APIService.swift */,
C12E66C72BB3F28800F3F441 /* APIType.swift */,
+ C12E66CA2BB3F28800F3F441 /* NetworkURL.swift */,
+ C1865DB72BBE9C3400DD99C9 /* Network.swift */,
C12E66C82BB3F28800F3F441 /* HttpMethod.swift */,
+ C1865DBB2BBEB72900DD99C9 /* ChatBotNetwork.swift */,
+ C12E66C62BB3F28800F3F441 /* APIService.swift */,
C12E66C92BB3F28800F3F441 /* NetworkError.swift */,
- C12E66CA2BB3F28800F3F441 /* NetworkURL.swift */,
- C12E66CB2BB3F28800F3F441 /* URLSessionProtocol.swift */,
+ C1865DB92BBE9E8600DD99C9 /* NetworkProvider.swift */,
);
path = Network;
sourceTree = "";
@@ -169,11 +173,20 @@
C12E66D22BB3F28800F3F441 /* View */ = {
isa = PBXGroup;
children = (
+ C12E66C02BB3F28800F3F441 /* ChatBotViewController.swift */,
C12E66D12BB3F28800F3F441 /* LaunchScreen.storyboard */,
);
path = View;
sourceTree = "";
};
+ C1865DBD2BBEC71B00DD99C9 /* ViewModel */ = {
+ isa = PBXGroup;
+ children = (
+ C12E66B82BB3F28800F3F441 /* ChatBotViewModel.swift */,
+ );
+ path = ViewModel;
+ sourceTree = "";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -190,6 +203,13 @@
dependencies = (
);
name = ChatBot;
+ packageProductDependencies = (
+ C1865DA02BBE945000DD99C9 /* SnapKit */,
+ C1865DA22BBE945000DD99C9 /* SnapKit-Dynamic */,
+ C1865DA52BBE945D00DD99C9 /* Then */,
+ C1865DA82BBE946D00DD99C9 /* RxAlamofire */,
+ C1865DB12BBE948000DD99C9 /* RxSwift */,
+ );
productName = ChatBot;
productReference = B4B3E2B92B42D1BB00818B3C /* ChatBot.app */;
productType = "com.apple.product-type.application";
@@ -218,6 +238,12 @@
Base,
);
mainGroup = B4B3E2B02B42D1BB00818B3C;
+ packageReferences = (
+ C1865D9F2BBE945000DD99C9 /* XCRemoteSwiftPackageReference "SnapKit" */,
+ C1865DA42BBE945D00DD99C9 /* XCRemoteSwiftPackageReference "Then" */,
+ C1865DA72BBE946D00DD99C9 /* XCRemoteSwiftPackageReference "RxAlamofire" */,
+ C1865DAA2BBE948000DD99C9 /* XCRemoteSwiftPackageReference "RxSwift" */,
+ );
productRefGroup = B4B3E2BA2B42D1BB00818B3C /* Products */;
projectDirPath = "";
projectRoot = "";
@@ -234,7 +260,7 @@
files = (
C12E66DB2BB3F28800F3F441 /* Assets.xcassets in Resources */,
C12E66E52BB3F28800F3F441 /* LaunchScreen.storyboard in Resources */,
- 9B76B2B02BBBF2F00089676F /* APIToken.plist in Resources */,
+ C1865DB62BBE94A600DD99C9 /* APIToken.plist in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -252,19 +278,20 @@
C12E66DD2BB3F28800F3F441 /* APIService.swift in Sources */,
C12E66D72BB3F28800F3F441 /* Bundle+Extension.swift in Sources */,
C12E66E12BB3F28800F3F441 /* NetworkURL.swift in Sources */,
- C12E66D32BB3F28800F3F441 /* ChatManager.swift in Sources */,
+ C12E66D32BB3F28800F3F441 /* ChatBotViewModel.swift in Sources */,
C12E66E42BB3F28800F3F441 /* SceneDelegate.swift in Sources */,
- C12E66D82BB3F28800F3F441 /* URLSession+Extension.swift in Sources */,
- C12E66E22BB3F28800F3F441 /* URLSessionProtocol.swift in Sources */,
+ C1865DBA2BBE9E8600DD99C9 /* NetworkProvider.swift in Sources */,
C12E66EE2BB4294300F3F441 /* Usage.swift in Sources */,
C1E416662BB9888C00D8C836 /* UIViewController+Extension.swift in Sources */,
+ C1865DBC2BBEB72900DD99C9 /* ChatBotNetwork.swift in Sources */,
C12E66D52BB3F28800F3F441 /* RequestChatDTO.swift in Sources */,
+ C1865DB82BBE9C3400DD99C9 /* Network.swift in Sources */,
C12E66F02BB429AA00F3F441 /* JSONNull.swift in Sources */,
C12E66EC2BB4291A00F3F441 /* ResponseChoiceDTO.swift in Sources */,
C12E66EA2BB4283100F3F441 /* ResponseChatDTO.swift in Sources */,
C12E66D42BB3F28800F3F441 /* ChatRepository.swift in Sources */,
C12E66E32BB3F28800F3F441 /* AppDelegate.swift in Sources */,
- C12E66D62BB3F28800F3F441 /* UserMessage.swift in Sources */,
+ C12E66D62BB3F28800F3F441 /* Message.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -488,6 +515,69 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
+
+/* Begin XCRemoteSwiftPackageReference section */
+ C1865D9F2BBE945000DD99C9 /* XCRemoteSwiftPackageReference "SnapKit" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/SnapKit/SnapKit.git";
+ requirement = {
+ kind = upToNextMajorVersion;
+ minimumVersion = 5.7.1;
+ };
+ };
+ C1865DA42BBE945D00DD99C9 /* XCRemoteSwiftPackageReference "Then" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/devxoul/Then.git";
+ requirement = {
+ kind = upToNextMajorVersion;
+ minimumVersion = 3.0.0;
+ };
+ };
+ C1865DA72BBE946D00DD99C9 /* XCRemoteSwiftPackageReference "RxAlamofire" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/RxSwiftCommunity/RxAlamofire.git";
+ requirement = {
+ kind = upToNextMajorVersion;
+ minimumVersion = 5.2.0;
+ };
+ };
+ C1865DAA2BBE948000DD99C9 /* XCRemoteSwiftPackageReference "RxSwift" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/ReactiveX/RxSwift.git";
+ requirement = {
+ kind = upToNextMajorVersion;
+ minimumVersion = 6.6.0;
+ };
+ };
+/* End XCRemoteSwiftPackageReference section */
+
+/* Begin XCSwiftPackageProductDependency section */
+ C1865DA02BBE945000DD99C9 /* SnapKit */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = C1865D9F2BBE945000DD99C9 /* XCRemoteSwiftPackageReference "SnapKit" */;
+ productName = SnapKit;
+ };
+ C1865DA22BBE945000DD99C9 /* SnapKit-Dynamic */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = C1865D9F2BBE945000DD99C9 /* XCRemoteSwiftPackageReference "SnapKit" */;
+ productName = "SnapKit-Dynamic";
+ };
+ C1865DA52BBE945D00DD99C9 /* Then */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = C1865DA42BBE945D00DD99C9 /* XCRemoteSwiftPackageReference "Then" */;
+ productName = Then;
+ };
+ C1865DA82BBE946D00DD99C9 /* RxAlamofire */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = C1865DA72BBE946D00DD99C9 /* XCRemoteSwiftPackageReference "RxAlamofire" */;
+ productName = RxAlamofire;
+ };
+ C1865DB12BBE948000DD99C9 /* RxSwift */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = C1865DAA2BBE948000DD99C9 /* XCRemoteSwiftPackageReference "RxSwift" */;
+ productName = RxSwift;
+ };
+/* End XCSwiftPackageProductDependency section */
};
rootObject = B4B3E2B12B42D1BB00818B3C /* Project object */;
}
diff --git a/ChatBot/ChatBot/App/SceneDelegate.swift b/ChatBot/ChatBot/App/SceneDelegate.swift
index cfbb53c4..6ca7c1c5 100644
--- a/ChatBot/ChatBot/App/SceneDelegate.swift
+++ b/ChatBot/ChatBot/App/SceneDelegate.swift
@@ -10,7 +10,7 @@ import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
- let chatManger = ChatManager()
+ let chatManger = ChatBotViewModel()
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard
@@ -20,7 +20,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
}
window = UIWindow(windowScene: windowScene)
- let mainViewController = ChatBotViewController(chatManager: chatManger)
+ let mainViewController = ChatBotViewController(chatBotViewModel: chatManger)
window?.rootViewController = mainViewController
window?.makeKeyAndVisible()
}
diff --git a/ChatBot/ChatBot/Controller/ChatBotViewController.swift b/ChatBot/ChatBot/Controller/ChatBotViewController.swift
deleted file mode 100644
index 55da037e..00000000
--- a/ChatBot/ChatBot/Controller/ChatBotViewController.swift
+++ /dev/null
@@ -1,54 +0,0 @@
-//
-// ViewController.swift
-// ChatBot
-//
-// Created by Tacocat on 1/1/24.
-//
-
-import UIKit
-
-class ChatBotViewController: UIViewController {
- private let chatManager: ChatManager?
-
- init(chatManager: ChatManager?) {
- self.chatManager = chatManager
- super.init(nibName: nil, bundle: nil)
- }
-
- required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
-}
-
-// MARK: - Life Cycle
-extension ChatBotViewController {
- override func viewDidLoad() {
- super.viewDidLoad()
- configureBackground()
- chatGPT(userMessage: "집에 가고싶어욧..")
- }
-}
-
-// MARK: - Private Method
-private extension ChatBotViewController {
- func configureBackground() {
- view.backgroundColor = .white
- }
-
- func chatGPT(userMessage: String) {
- Task{
- do {
- guard
- let result = try await chatManager?.requestChatResultData(userMessage: userMessage)
- else {
- return
- }
- print("질문 : \(userMessage)")
- print("결과 : \(result.choices[0].message.content)")
- } catch {
- let okAction = UIAlertAction(title: "닫기", style: .default)
- showMessageAlert(message: "\(error.localizedDescription)", action: [okAction])
- }
- }
- }
-}
diff --git a/ChatBot/ChatBot/Extension/URLSession+Extension.swift b/ChatBot/ChatBot/Extension/URLSession+Extension.swift
deleted file mode 100644
index f878744f..00000000
--- a/ChatBot/ChatBot/Extension/URLSession+Extension.swift
+++ /dev/null
@@ -1,14 +0,0 @@
-//
-// URLSession+Extension.swift
-// ChatBot
-//
-// Created by LeeSeongYeon on 3/26/24.
-//
-
-import Foundation
-
-extension URLSession: URLSessionProtocol {
- func requestData(with request: URLRequest) async throws -> (Data, URLResponse) {
- return try await data(for: request)
- }
-}
diff --git a/ChatBot/ChatBot/Model/ChatManager.swift b/ChatBot/ChatBot/Model/ChatManager.swift
deleted file mode 100644
index ee640110..00000000
--- a/ChatBot/ChatBot/Model/ChatManager.swift
+++ /dev/null
@@ -1,26 +0,0 @@
-//
-// ChatManager.swift
-// ChatBot
-//
-// Created by LeeSeongYeon on 3/27/24.
-//
-
-import Foundation
-
-final class ChatManager {
- var chatData: [ResponseChatDTO]?
- private let chatRepository: ChatRepository = ChatRepository()
-}
-
-extension ChatManager {
- func requestChatResultData(userMessage: String) async throws -> ResponseChatDTO {
- let result = try await chatRepository.requestChatResultData(userMessage: userMessage)
- switch result {
- case .success(let data):
- self.chatData?.append(data)
- return data
- case .failure(let error):
- throw error
- }
- }
-}
diff --git a/ChatBot/ChatBot/Model/UserMessage.swift b/ChatBot/ChatBot/Model/Message.swift
similarity index 100%
rename from ChatBot/ChatBot/Model/UserMessage.swift
rename to ChatBot/ChatBot/Model/Message.swift
diff --git a/ChatBot/ChatBot/Network/ChatBotNetwork.swift b/ChatBot/ChatBot/Network/ChatBotNetwork.swift
new file mode 100644
index 00000000..50cf5fe4
--- /dev/null
+++ b/ChatBot/ChatBot/Network/ChatBotNetwork.swift
@@ -0,0 +1,8 @@
+//
+// ChatBotNetwork.swift
+// ChatBot
+//
+// Created by Matthew on 4/4/24.
+//
+
+import Foundation
diff --git a/ChatBot/ChatBot/Network/Network.swift b/ChatBot/ChatBot/Network/Network.swift
new file mode 100644
index 00000000..ed1ff211
--- /dev/null
+++ b/ChatBot/ChatBot/Network/Network.swift
@@ -0,0 +1,8 @@
+//
+// Network.swift
+// ChatBot
+//
+// Created by Matthew on 4/4/24.
+//
+
+import Foundation
diff --git a/ChatBot/ChatBot/Network/NetworkProvider.swift b/ChatBot/ChatBot/Network/NetworkProvider.swift
new file mode 100644
index 00000000..ab6cd451
--- /dev/null
+++ b/ChatBot/ChatBot/Network/NetworkProvider.swift
@@ -0,0 +1,8 @@
+//
+// NetworkProvider.swift
+// ChatBot
+//
+// Created by Matthew on 4/4/24.
+//
+
+import Foundation
diff --git a/ChatBot/ChatBot/Network/URLSessionProtocol.swift b/ChatBot/ChatBot/Network/URLSessionProtocol.swift
deleted file mode 100644
index 16251168..00000000
--- a/ChatBot/ChatBot/Network/URLSessionProtocol.swift
+++ /dev/null
@@ -1,13 +0,0 @@
-//
-// URLSessionProtocol.swift
-// ChatBot
-//
-// Created by LeeSeongYeon on 3/26/24.
-//
-
-import Foundation
-
-protocol URLSessionProtocol {
- func requestData(with request: URLRequest) async throws -> (Data, URLResponse)
-}
-
diff --git a/ChatBot/ChatBot/View/ChatBotViewController.swift b/ChatBot/ChatBot/View/ChatBotViewController.swift
new file mode 100644
index 00000000..4374aae9
--- /dev/null
+++ b/ChatBot/ChatBot/View/ChatBotViewController.swift
@@ -0,0 +1,70 @@
+//
+// ViewController.swift
+// ChatBot
+//
+// Created by Tacocat on 1/1/24.
+//
+
+import UIKit
+import Then
+import SnapKit
+import RxSwift
+
+class ChatBotViewController: UIViewController {
+ let button = UIButton().then {
+ $0.setTitle("이거", for: .normal)
+ $0.setTitleColor(.red, for: .normal)
+ }
+ private let chatBotViewModel: ChatBotViewModel
+ let disposeBag = DisposeBag()
+ let chatTrigger = PublishSubject()
+
+ init(chatBotViewModel: ChatBotViewModel) {
+ self.chatBotViewModel = chatBotViewModel
+ super.init(nibName: nil, bundle: nil)
+ }
+
+ required init?(coder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+}
+
+// MARK: - Life Cycle
+extension ChatBotViewController {
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ configureBackground()
+ bindViewModel()
+ bindView()
+ }
+}
+
+// MARK: - Private Method
+private extension ChatBotViewController {
+ func configureBackground() {
+ view.backgroundColor = .white
+ self.view.addSubview(button)
+ button.snp.makeConstraints { make in
+ make.centerY.centerX.equalToSuperview()
+ }
+ }
+
+ func bindViewModel() {
+ let input = ChatBotViewModel.Input(chatTigger: chatTrigger)
+ let output = chatBotViewModel.transform(input: input)
+ output.resultChat.bind { result in
+ switch result {
+ case .success(let chat):
+ print(chat)
+ case .failure(let error):
+ print(error)
+ }
+ }.disposed(by: disposeBag)
+ }
+
+ func bindView() {
+ button.rx.tap.bind { [weak self] _ in
+ self?.chatTrigger.onNext(Void())
+ }.disposed(by: disposeBag)
+ }
+}
diff --git a/ChatBot/ChatBot/ViewModel/ChatBotViewModel.swift b/ChatBot/ChatBot/ViewModel/ChatBotViewModel.swift
new file mode 100644
index 00000000..48c7927b
--- /dev/null
+++ b/ChatBot/ChatBot/ViewModel/ChatBotViewModel.swift
@@ -0,0 +1,41 @@
+//
+// ChatManager.swift
+// ChatBot
+//
+// Created by LeeSeongYeon on 3/27/24.
+//
+
+import Foundation
+import RxSwift
+
+final class ChatBotViewModel {
+ private let chatBotNetwork: ChatBotNetwork
+
+ init() {
+ let chat = RequestChatDTO(messages: [
+ Message(role: "system", content: "나는 병신이야"),
+ Message(role: "user", content: "집에가고싶어요..")
+ ])
+ self.chatBotNetwork = ChatBotNetwork(network: Network(NetworkURL.makeURLRequest(type: .chatGPT, chat: chat, httpMethod: .post)!))
+ }
+
+ struct Input {
+ let chatTigger: Observable
+ }
+
+ struct Output {
+ let resultChat: Observable>
+ }
+
+ func transform(input: Input) -> Output {
+ let resultChat = input.chatTigger.flatMapLatest { [unowned self] _ -> Observable> in
+ self.chatBotNetwork.requestChatBotMessage().map {
+ return .success($0)
+ }
+ .catchError { error in
+ return Observable.just(.failure(error))
+ }
+ }
+ return Output(resultChat: resultChat)
+ }
+}
From e80553bd750f5a51adfa35adb3bff0d282564bef Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthew=28=EB=A7=A4=ED=8A=9C=29?=
Date: Thu, 4 Apr 2024 20:35:56 +0900
Subject: [PATCH 06/24] =?UTF-8?q?feat:=20RxAlamofire=EB=A5=BC=20=ED=99=9C?=
=?UTF-8?q?=EC=9A=A9=ED=95=98=EC=97=AC=20Network=20=EA=B8=B0=EB=8A=A5=20?=
=?UTF-8?q?=EA=B5=AC=ED=98=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../xcshareddata/swiftpm/Package.resolved | 60 ++++++++++++++
ChatBot/ChatBot/Model/ChatRepository.swift | 41 ++++-----
ChatBot/ChatBot/Network/APIService.swift | 83 +++++++++----------
ChatBot/ChatBot/Network/ChatBotNetwork.swift | 14 ++++
ChatBot/ChatBot/Network/Network.swift | 21 +++++
ChatBot/ChatBot/Network/NetworkProvider.swift | 13 +++
ChatBot/ChatBot/Network/NetworkURL.swift | 3 +-
7 files changed, 172 insertions(+), 63 deletions(-)
create mode 100644 ChatBot/ChatBot.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
diff --git a/ChatBot/ChatBot.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ChatBot/ChatBot.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
new file mode 100644
index 00000000..6113c9f6
--- /dev/null
+++ b/ChatBot/ChatBot.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -0,0 +1,60 @@
+{
+ "originHash" : "49f99251b083029aceba100c19348cc708f09dda9dd89fd947a14b1267b66431",
+ "pins" : [
+ {
+ "identity" : "alamofire",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/Alamofire/Alamofire.git",
+ "state" : {
+ "revision" : "f455c2975872ccd2d9c81594c658af65716e9b9a",
+ "version" : "5.9.1"
+ }
+ },
+ {
+ "identity" : "ohhttpstubs",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/AliSoftware/OHHTTPStubs.git",
+ "state" : {
+ "revision" : "12f19662426d0434d6c330c6974d53e2eb10ecd9",
+ "version" : "9.1.0"
+ }
+ },
+ {
+ "identity" : "rxalamofire",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/RxSwiftCommunity/RxAlamofire.git",
+ "state" : {
+ "revision" : "16858a7955ff8bc3caa51212fd7624f168586773",
+ "version" : "5.7.1"
+ }
+ },
+ {
+ "identity" : "rxswift",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/ReactiveX/RxSwift.git",
+ "state" : {
+ "revision" : "cec68169a048a079f461ba203fe85636548d7a89",
+ "version" : "5.1.3"
+ }
+ },
+ {
+ "identity" : "snapkit",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/SnapKit/SnapKit.git",
+ "state" : {
+ "revision" : "2842e6e84e82eb9a8dac0100ca90d9444b0307f4",
+ "version" : "5.7.1"
+ }
+ },
+ {
+ "identity" : "then",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/devxoul/Then.git",
+ "state" : {
+ "revision" : "d41ef523faef0f911369f79c0b96815d9dbb6d7a",
+ "version" : "3.0.0"
+ }
+ }
+ ],
+ "version" : 3
+}
diff --git a/ChatBot/ChatBot/Model/ChatRepository.swift b/ChatBot/ChatBot/Model/ChatRepository.swift
index d7c6049d..a4cda9b5 100644
--- a/ChatBot/ChatBot/Model/ChatRepository.swift
+++ b/ChatBot/ChatBot/Model/ChatRepository.swift
@@ -6,29 +6,32 @@
//
import Foundation
+import RxSwift
struct ChatRepository {
- private let apiService: APIService = APIService(session: URLSession.shared)
- func requestChatResultData(userMessage: String) async throws -> (Result) {
-
- let chat = RequestChatDTO(messages: [
- Message(role: "system", content: "너는 연애고수야"),
- Message(role: "user", content: "\(userMessage)")
- ])
+// private let apiService: APIService = APIService(session: URLSession.shared)
+ let network: Network
+
+ init(network: Network) {
+ self.network = network
+ }
+
+ func requestChatResultData(userMessage: String)-> Observable {
- guard
- let urlRequest = NetworkURL.makeURLRequest(type: .chatGPT, chat: chat, httpMethod: .post)
- else {
- return .failure(.invalidURLRequestError)
- }
+// let chat = RequestChatDTO(messages: [
+// Message(role: "system", content: "너는 연애고수야"),
+// Message(role: "user", content: "\(userMessage)")
+// ])
- let result = try await apiService.fetchData(with: urlRequest)
- switch result {
- case .success(let success):
- return handleDecodedData(data: success)
- case .failure(let failure):
- return .failure(failure)
- }
+ return network.fetchData()
+//
+// let result = try await apiService.fetchData(with: urlRequest)
+// switch result {
+// case .success(let success):
+// return handleDecodedData(data: success)
+// case .failure(let failure):
+// return .failure(failure)
+// }
}
}
diff --git a/ChatBot/ChatBot/Network/APIService.swift b/ChatBot/ChatBot/Network/APIService.swift
index ddffd5cf..b26d9475 100644
--- a/ChatBot/ChatBot/Network/APIService.swift
+++ b/ChatBot/ChatBot/Network/APIService.swift
@@ -7,45 +7,44 @@
import Foundation
-struct APIService {
- typealias APIResult = (Result)
- private let session: URLSessionProtocol
-
- init(session: URLSessionProtocol) {
- self.session = session
- }
-
- func fetchData(with urlRequest: URLRequest) async throws -> APIResult {
- let (data, response) = try await session.requestData(with: urlRequest)
- return handleDataTaskCompletion(data: data, response: response)
- }
-}
-
-private extension APIService {
- func handleDataTaskCompletion(data: Data?, response: URLResponse?) -> APIResult {
- guard
- let httpResponse = response as? HTTPURLResponse
- else {
- return .failure(.invalidResponseError)
- }
- return self.handleHTTPResponse(data: data, httpResponse: httpResponse)
- }
-
- func handleHTTPResponse(data: Data?, httpResponse: HTTPURLResponse) -> APIResult {
- guard
- let data = data
- else {
- return .failure(.noDataError)
- }
- switch httpResponse.statusCode {
- case 300..<400:
- return .failure(.redirectionError)
- case 400..<500:
- return .failure(.clientError)
- case 500..<600:
- return .failure(.serverError)
- default:
- return .success(data)
- }
- }
-}
+//struct APIService {
+// typealias APIResult = (Result)
+// let session: URLSession
+// init() {
+// self.session = URLSession.shared
+// }
+//
+// func fetchData(with urlRequest: URLRequest) async throws -> APIResult {
+// let (data, response) = try await session.data(for: urlRequest)
+// return handleDataTaskCompletion(data: data, response: response)
+// }
+//}
+//
+//private extension APIService {
+// func handleDataTaskCompletion(data: Data?, response: URLResponse?) -> APIResult {
+// guard
+// let httpResponse = response as? HTTPURLResponse
+// else {
+// return .failure(.invalidResponseError)
+// }
+// return self.handleHTTPResponse(data: data, httpResponse: httpResponse)
+// }
+//
+// func handleHTTPResponse(data: Data?, httpResponse: HTTPURLResponse) -> APIResult {
+// guard
+// let data = data
+// else {
+// return .failure(.noDataError)
+// }
+// switch httpResponse.statusCode {
+// case 300..<400:
+// return .failure(.redirectionError)
+// case 400..<500:
+// return .failure(.clientError)
+// case 500..<600:
+// return .failure(.serverError)
+// default:
+// return .success(data)
+// }
+// }
+//}
diff --git a/ChatBot/ChatBot/Network/ChatBotNetwork.swift b/ChatBot/ChatBot/Network/ChatBotNetwork.swift
index 50cf5fe4..552aa449 100644
--- a/ChatBot/ChatBot/Network/ChatBotNetwork.swift
+++ b/ChatBot/ChatBot/Network/ChatBotNetwork.swift
@@ -6,3 +6,17 @@
//
import Foundation
+import RxSwift
+
+final class ChatBotNetwork {
+ private let network: Network
+
+ init(network: Network) {
+ self.network = network
+ }
+
+ func requestChatBotMessage() -> Observable {
+ return network.fetchData()
+ }
+}
+
diff --git a/ChatBot/ChatBot/Network/Network.swift b/ChatBot/ChatBot/Network/Network.swift
index ed1ff211..596a6cbf 100644
--- a/ChatBot/ChatBot/Network/Network.swift
+++ b/ChatBot/ChatBot/Network/Network.swift
@@ -5,4 +5,25 @@
// Created by Matthew on 4/4/24.
//
+import RxSwift
+import RxAlamofire
import Foundation
+
+class Network {
+ private let urlRequest: URLRequest
+ private let queue: ConcurrentDispatchQueueScheduler
+
+ init(_ urlRequst: URLRequest) {
+ self.urlRequest = urlRequst
+ self.queue = ConcurrentDispatchQueueScheduler(qos: .background)
+ }
+
+ func fetchData() -> Observable {
+ RxAlamofire.requestData(urlRequest)
+ .observeOn(queue)
+ .debug()
+ .map { (response, data) -> T in
+ return try JSONDecoder().decode(T.self, from: data)
+ }
+ }
+}
diff --git a/ChatBot/ChatBot/Network/NetworkProvider.swift b/ChatBot/ChatBot/Network/NetworkProvider.swift
index ab6cd451..8ace1a0c 100644
--- a/ChatBot/ChatBot/Network/NetworkProvider.swift
+++ b/ChatBot/ChatBot/Network/NetworkProvider.swift
@@ -6,3 +6,16 @@
//
import Foundation
+
+//final class NetworkProvider {
+// private let urlRequest: URLRequest
+//
+// init(type: APIType, chat: RequestChatDTO, userMessage: String) {
+// self.urlRequest = NetworkURL.makeURLRequest(type: type, chat: chat)!
+// }
+//
+// func makeChatNetwork() -> ChatBotNetwork {
+// let network = Network(urlRequest)
+// return ChatBotNetwork(network: network)
+// }
+//}
diff --git a/ChatBot/ChatBot/Network/NetworkURL.swift b/ChatBot/ChatBot/Network/NetworkURL.swift
index e3819dda..0a37c795 100644
--- a/ChatBot/ChatBot/Network/NetworkURL.swift
+++ b/ChatBot/ChatBot/Network/NetworkURL.swift
@@ -8,8 +8,7 @@
import Foundation
enum NetworkURL {
- static func makeURLRequest(type: APIType, chat: RequestChatDTO, httpMethod: HttpMethod = .get) -> URLRequest? {
-
+ static func makeURLRequest(type: APIType, chat: RequestChatDTO, httpMethod: HttpMethod = .get) -> URLRequest? {
let urlComponents = makeURLComponents(type: type)
guard
From 801a84676b40d2a7aa7beef67303671561883ff6 Mon Sep 17 00:00:00 2001
From: LeeSe0ngYe0n
Date: Thu, 4 Apr 2024 21:33:26 +0900
Subject: [PATCH 07/24] =?UTF-8?q?refactor:=20Network=20=EC=83=9D=EC=84=B1?=
=?UTF-8?q?=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
ChatBot/ChatBot/Network/NetworkProvider.swift | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)
diff --git a/ChatBot/ChatBot/Network/NetworkProvider.swift b/ChatBot/ChatBot/Network/NetworkProvider.swift
index 8ace1a0c..81b03c5c 100644
--- a/ChatBot/ChatBot/Network/NetworkProvider.swift
+++ b/ChatBot/ChatBot/Network/NetworkProvider.swift
@@ -7,15 +7,9 @@
import Foundation
-//final class NetworkProvider {
-// private let urlRequest: URLRequest
-//
-// init(type: APIType, chat: RequestChatDTO, userMessage: String) {
-// self.urlRequest = NetworkURL.makeURLRequest(type: type, chat: chat)!
-// }
-//
-// func makeChatNetwork() -> ChatBotNetwork {
-// let network = Network(urlRequest)
-// return ChatBotNetwork(network: network)
-// }
-//}
+final class NetworkProvider {
+ func makeChatNetwork() -> ChatBotNetwork {
+ let network = Network()
+ return ChatBotNetwork(network: network)
+ }
+}
From 876e834ece386f9c7f9790a773156dc368c1abb6 Mon Sep 17 00:00:00 2001
From: LeeSe0ngYe0n
Date: Thu, 4 Apr 2024 21:34:07 +0900
Subject: [PATCH 08/24] =?UTF-8?q?refactor:=20=EB=A9=94=EC=84=B8=EC=A7=80?=
=?UTF-8?q?=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
ChatBot/ChatBot/Network/ChatBotNetwork.swift | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/ChatBot/ChatBot/Network/ChatBotNetwork.swift b/ChatBot/ChatBot/Network/ChatBotNetwork.swift
index 552aa449..ae2f03f1 100644
--- a/ChatBot/ChatBot/Network/ChatBotNetwork.swift
+++ b/ChatBot/ChatBot/Network/ChatBotNetwork.swift
@@ -15,8 +15,8 @@ final class ChatBotNetwork {
self.network = network
}
- func requestChatBotMessage() -> Observable {
- return network.fetchData()
+ func requestChatBotMessage(message: Message) -> Observable {
+ return network.fetchData(message: message)
}
}
From 59cca5b740aa7dce82cca79352ff9171fea74abb Mon Sep 17 00:00:00 2001
From: LeeSe0ngYe0n
Date: Thu, 4 Apr 2024 21:35:37 +0900
Subject: [PATCH 09/24] =?UTF-8?q?refactor:=20=EB=84=A4=ED=8A=B8=EC=9B=8C?=
=?UTF-8?q?=ED=81=AC=20request=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
ChatBot/ChatBot/Network/Network.swift | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/ChatBot/ChatBot/Network/Network.swift b/ChatBot/ChatBot/Network/Network.swift
index 596a6cbf..06a31c75 100644
--- a/ChatBot/ChatBot/Network/Network.swift
+++ b/ChatBot/ChatBot/Network/Network.swift
@@ -10,20 +10,20 @@ import RxAlamofire
import Foundation
class Network {
- private let urlRequest: URLRequest
private let queue: ConcurrentDispatchQueueScheduler
- init(_ urlRequst: URLRequest) {
- self.urlRequest = urlRequst
+ init() {
self.queue = ConcurrentDispatchQueueScheduler(qos: .background)
}
- func fetchData() -> Observable {
- RxAlamofire.requestData(urlRequest)
+ func fetchData(message: Message) -> Observable {
+ let urlRequest = NetworkURL.makeURLRequest(type: .chatGPT, chat: RequestChatDTO(messages: [message]), httpMethod: .post)!
+ let result = RxAlamofire.requestData(urlRequest)
.observeOn(queue)
.debug()
.map { (response, data) -> T in
return try JSONDecoder().decode(T.self, from: data)
}
+ return result
}
}
From bdf568dfd544b49763f53ba859bd2a9626c02944 Mon Sep 17 00:00:00 2001
From: LeeSe0ngYe0n
Date: Thu, 4 Apr 2024 21:36:10 +0900
Subject: [PATCH 10/24] =?UTF-8?q?refactor:=20=ED=8A=B8=EB=A6=AC=EA=B1=B0?=
=?UTF-8?q?=20=ED=83=80=EC=9E=85=20=EB=B3=80=EA=B2=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
ChatBot/ChatBot/View/ChatBotViewController.swift | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/ChatBot/ChatBot/View/ChatBotViewController.swift b/ChatBot/ChatBot/View/ChatBotViewController.swift
index 4374aae9..818e689b 100644
--- a/ChatBot/ChatBot/View/ChatBotViewController.swift
+++ b/ChatBot/ChatBot/View/ChatBotViewController.swift
@@ -17,7 +17,7 @@ class ChatBotViewController: UIViewController {
}
private let chatBotViewModel: ChatBotViewModel
let disposeBag = DisposeBag()
- let chatTrigger = PublishSubject()
+ let chatTrigger = PublishSubject()
init(chatBotViewModel: ChatBotViewModel) {
self.chatBotViewModel = chatBotViewModel
@@ -64,7 +64,7 @@ private extension ChatBotViewController {
func bindView() {
button.rx.tap.bind { [weak self] _ in
- self?.chatTrigger.onNext(Void())
+ self?.chatTrigger.onNext(Message(role: "user", content: "집언제감?"))
}.disposed(by: disposeBag)
}
}
From b9f4b882f4b9d5cd7af477f892ff7981d4deb43a Mon Sep 17 00:00:00 2001
From: LeeSe0ngYe0n
Date: Thu, 4 Apr 2024 21:36:33 +0900
Subject: [PATCH 11/24] =?UTF-8?q?refactor:=20=EB=84=A4=ED=8A=B8=EC=9B=8C?=
=?UTF-8?q?=ED=81=AC=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
ChatBot/ChatBot.xcodeproj/project.pbxproj | 90 +++++++++----------
.../xcshareddata/swiftpm/Package.resolved | 2 +-
ChatBot/ChatBot/Model/ChatRepository.swift | 6 +-
.../ChatBot/ViewModel/ChatBotViewModel.swift | 13 ++-
4 files changed, 54 insertions(+), 57 deletions(-)
diff --git a/ChatBot/ChatBot.xcodeproj/project.pbxproj b/ChatBot/ChatBot.xcodeproj/project.pbxproj
index 75b4cc16..c9e3093c 100644
--- a/ChatBot/ChatBot.xcodeproj/project.pbxproj
+++ b/ChatBot/ChatBot.xcodeproj/project.pbxproj
@@ -7,6 +7,12 @@
objects = {
/* Begin PBXBuildFile section */
+ 9B9289152BBECEDC00185E35 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 9B9289142BBECEDC00185E35 /* SnapKit */; };
+ 9B9289182BBECEEB00185E35 /* RxAlamofire in Frameworks */ = {isa = PBXBuildFile; productRef = 9B9289172BBECEEB00185E35 /* RxAlamofire */; };
+ 9B92891B2BBECEF900185E35 /* Then in Frameworks */ = {isa = PBXBuildFile; productRef = 9B92891A2BBECEF900185E35 /* Then */; };
+ 9B92891E2BBECF2300185E35 /* RxCocoa in Frameworks */ = {isa = PBXBuildFile; productRef = 9B92891D2BBECF2300185E35 /* RxCocoa */; };
+ 9B9289202BBECF2300185E35 /* RxSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 9B92891F2BBECF2300185E35 /* RxSwift */; };
+ 9B9289222BBECF5B00185E35 /* APIToken.plist in Resources */ = {isa = PBXBuildFile; fileRef = 9B9289212BBECF5B00185E35 /* APIToken.plist */; };
C12E66D32BB3F28800F3F441 /* ChatBotViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66B82BB3F28800F3F441 /* ChatBotViewModel.swift */; };
C12E66D42BB3F28800F3F441 /* ChatRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66B92BB3F28800F3F441 /* ChatRepository.swift */; };
C12E66D52BB3F28800F3F441 /* RequestChatDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66BA2BB3F28800F3F441 /* RequestChatDTO.swift */; };
@@ -26,12 +32,6 @@
C12E66EC2BB4291A00F3F441 /* ResponseChoiceDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66EB2BB4291A00F3F441 /* ResponseChoiceDTO.swift */; };
C12E66EE2BB4294300F3F441 /* Usage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66ED2BB4294300F3F441 /* Usage.swift */; };
C12E66F02BB429AA00F3F441 /* JSONNull.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66EF2BB429AA00F3F441 /* JSONNull.swift */; };
- C1865DA12BBE945000DD99C9 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = C1865DA02BBE945000DD99C9 /* SnapKit */; };
- C1865DA32BBE945000DD99C9 /* SnapKit-Dynamic in Frameworks */ = {isa = PBXBuildFile; productRef = C1865DA22BBE945000DD99C9 /* SnapKit-Dynamic */; };
- C1865DA62BBE945D00DD99C9 /* Then in Frameworks */ = {isa = PBXBuildFile; productRef = C1865DA52BBE945D00DD99C9 /* Then */; };
- C1865DA92BBE946D00DD99C9 /* RxAlamofire in Frameworks */ = {isa = PBXBuildFile; productRef = C1865DA82BBE946D00DD99C9 /* RxAlamofire */; };
- C1865DB22BBE948000DD99C9 /* RxSwift in Frameworks */ = {isa = PBXBuildFile; productRef = C1865DB12BBE948000DD99C9 /* RxSwift */; };
- C1865DB62BBE94A600DD99C9 /* APIToken.plist in Resources */ = {isa = PBXBuildFile; fileRef = C1865DB52BBE94A600DD99C9 /* APIToken.plist */; };
C1865DB82BBE9C3400DD99C9 /* Network.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1865DB72BBE9C3400DD99C9 /* Network.swift */; };
C1865DBA2BBE9E8600DD99C9 /* NetworkProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1865DB92BBE9E8600DD99C9 /* NetworkProvider.swift */; };
C1865DBC2BBEB72900DD99C9 /* ChatBotNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1865DBB2BBEB72900DD99C9 /* ChatBotNetwork.swift */; };
@@ -39,6 +39,7 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
+ 9B9289212BBECF5B00185E35 /* APIToken.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = APIToken.plist; sourceTree = ""; };
B4B3E2B92B42D1BB00818B3C /* ChatBot.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ChatBot.app; sourceTree = BUILT_PRODUCTS_DIR; };
C12E66B82BB3F28800F3F441 /* ChatBotViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatBotViewModel.swift; sourceTree = ""; };
C12E66B92BB3F28800F3F441 /* ChatRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatRepository.swift; sourceTree = ""; };
@@ -60,7 +61,6 @@
C12E66EB2BB4291A00F3F441 /* ResponseChoiceDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResponseChoiceDTO.swift; sourceTree = ""; };
C12E66ED2BB4294300F3F441 /* Usage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Usage.swift; sourceTree = ""; };
C12E66EF2BB429AA00F3F441 /* JSONNull.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONNull.swift; sourceTree = ""; };
- C1865DB52BBE94A600DD99C9 /* APIToken.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = APIToken.plist; sourceTree = ""; };
C1865DB72BBE9C3400DD99C9 /* Network.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Network.swift; sourceTree = ""; };
C1865DB92BBE9E8600DD99C9 /* NetworkProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProvider.swift; sourceTree = ""; };
C1865DBB2BBEB72900DD99C9 /* ChatBotNetwork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatBotNetwork.swift; sourceTree = ""; };
@@ -72,11 +72,11 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- C1865DA12BBE945000DD99C9 /* SnapKit in Frameworks */,
- C1865DA92BBE946D00DD99C9 /* RxAlamofire in Frameworks */,
- C1865DA62BBE945D00DD99C9 /* Then in Frameworks */,
- C1865DA32BBE945000DD99C9 /* SnapKit-Dynamic in Frameworks */,
- C1865DB22BBE948000DD99C9 /* RxSwift in Frameworks */,
+ 9B9289152BBECEDC00185E35 /* SnapKit in Frameworks */,
+ 9B92891B2BBECEF900185E35 /* Then in Frameworks */,
+ 9B9289202BBECF2300185E35 /* RxSwift in Frameworks */,
+ 9B92891E2BBECF2300185E35 /* RxCocoa in Frameworks */,
+ 9B9289182BBECEEB00185E35 /* RxAlamofire in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -141,7 +141,7 @@
children = (
C12E66C32BB3F28800F3F441 /* Assets.xcassets */,
C12E66C42BB3F28800F3F441 /* Info.plist */,
- C1865DB52BBE94A600DD99C9 /* APIToken.plist */,
+ 9B9289212BBECF5B00185E35 /* APIToken.plist */,
);
path = Resource;
sourceTree = "";
@@ -204,11 +204,11 @@
);
name = ChatBot;
packageProductDependencies = (
- C1865DA02BBE945000DD99C9 /* SnapKit */,
- C1865DA22BBE945000DD99C9 /* SnapKit-Dynamic */,
- C1865DA52BBE945D00DD99C9 /* Then */,
- C1865DA82BBE946D00DD99C9 /* RxAlamofire */,
- C1865DB12BBE948000DD99C9 /* RxSwift */,
+ 9B9289142BBECEDC00185E35 /* SnapKit */,
+ 9B9289172BBECEEB00185E35 /* RxAlamofire */,
+ 9B92891A2BBECEF900185E35 /* Then */,
+ 9B92891D2BBECF2300185E35 /* RxCocoa */,
+ 9B92891F2BBECF2300185E35 /* RxSwift */,
);
productName = ChatBot;
productReference = B4B3E2B92B42D1BB00818B3C /* ChatBot.app */;
@@ -239,10 +239,10 @@
);
mainGroup = B4B3E2B02B42D1BB00818B3C;
packageReferences = (
- C1865D9F2BBE945000DD99C9 /* XCRemoteSwiftPackageReference "SnapKit" */,
- C1865DA42BBE945D00DD99C9 /* XCRemoteSwiftPackageReference "Then" */,
- C1865DA72BBE946D00DD99C9 /* XCRemoteSwiftPackageReference "RxAlamofire" */,
- C1865DAA2BBE948000DD99C9 /* XCRemoteSwiftPackageReference "RxSwift" */,
+ 9B9289132BBECEDC00185E35 /* XCRemoteSwiftPackageReference "SnapKit" */,
+ 9B9289162BBECEEB00185E35 /* XCRemoteSwiftPackageReference "RxAlamofire" */,
+ 9B9289192BBECEF900185E35 /* XCRemoteSwiftPackageReference "Then" */,
+ 9B92891C2BBECF2300185E35 /* XCRemoteSwiftPackageReference "RxSwift" */,
);
productRefGroup = B4B3E2BA2B42D1BB00818B3C /* Products */;
projectDirPath = "";
@@ -258,9 +258,9 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 9B9289222BBECF5B00185E35 /* APIToken.plist in Resources */,
C12E66DB2BB3F28800F3F441 /* Assets.xcassets in Resources */,
C12E66E52BB3F28800F3F441 /* LaunchScreen.storyboard in Resources */,
- C1865DB62BBE94A600DD99C9 /* APIToken.plist in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -435,7 +435,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_TEAM = T92LV6HV88;
+ DEVELOPMENT_TEAM = 7VXN2294AY;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = ChatBot/Resource/Info.plist;
"INFOPLIST_FILE[sdk=*]" = ChatBot/Resource/Info.plist;
@@ -468,7 +468,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_TEAM = T92LV6HV88;
+ DEVELOPMENT_TEAM = 7VXN2294AY;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = ChatBot/Resource/Info.plist;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
@@ -517,7 +517,7 @@
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
- C1865D9F2BBE945000DD99C9 /* XCRemoteSwiftPackageReference "SnapKit" */ = {
+ 9B9289132BBECEDC00185E35 /* XCRemoteSwiftPackageReference "SnapKit" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/SnapKit/SnapKit.git";
requirement = {
@@ -525,23 +525,23 @@
minimumVersion = 5.7.1;
};
};
- C1865DA42BBE945D00DD99C9 /* XCRemoteSwiftPackageReference "Then" */ = {
+ 9B9289162BBECEEB00185E35 /* XCRemoteSwiftPackageReference "RxAlamofire" */ = {
isa = XCRemoteSwiftPackageReference;
- repositoryURL = "https://github.com/devxoul/Then.git";
+ repositoryURL = "https://github.com/RxSwiftCommunity/RxAlamofire.git";
requirement = {
kind = upToNextMajorVersion;
- minimumVersion = 3.0.0;
+ minimumVersion = 5.2.0;
};
};
- C1865DA72BBE946D00DD99C9 /* XCRemoteSwiftPackageReference "RxAlamofire" */ = {
+ 9B9289192BBECEF900185E35 /* XCRemoteSwiftPackageReference "Then" */ = {
isa = XCRemoteSwiftPackageReference;
- repositoryURL = "https://github.com/RxSwiftCommunity/RxAlamofire.git";
+ repositoryURL = "https://github.com/devxoul/Then.git";
requirement = {
kind = upToNextMajorVersion;
- minimumVersion = 5.2.0;
+ minimumVersion = 3.0.0;
};
};
- C1865DAA2BBE948000DD99C9 /* XCRemoteSwiftPackageReference "RxSwift" */ = {
+ 9B92891C2BBECF2300185E35 /* XCRemoteSwiftPackageReference "RxSwift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/ReactiveX/RxSwift.git";
requirement = {
@@ -552,29 +552,29 @@
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
- C1865DA02BBE945000DD99C9 /* SnapKit */ = {
+ 9B9289142BBECEDC00185E35 /* SnapKit */ = {
isa = XCSwiftPackageProductDependency;
- package = C1865D9F2BBE945000DD99C9 /* XCRemoteSwiftPackageReference "SnapKit" */;
+ package = 9B9289132BBECEDC00185E35 /* XCRemoteSwiftPackageReference "SnapKit" */;
productName = SnapKit;
};
- C1865DA22BBE945000DD99C9 /* SnapKit-Dynamic */ = {
+ 9B9289172BBECEEB00185E35 /* RxAlamofire */ = {
isa = XCSwiftPackageProductDependency;
- package = C1865D9F2BBE945000DD99C9 /* XCRemoteSwiftPackageReference "SnapKit" */;
- productName = "SnapKit-Dynamic";
+ package = 9B9289162BBECEEB00185E35 /* XCRemoteSwiftPackageReference "RxAlamofire" */;
+ productName = RxAlamofire;
};
- C1865DA52BBE945D00DD99C9 /* Then */ = {
+ 9B92891A2BBECEF900185E35 /* Then */ = {
isa = XCSwiftPackageProductDependency;
- package = C1865DA42BBE945D00DD99C9 /* XCRemoteSwiftPackageReference "Then" */;
+ package = 9B9289192BBECEF900185E35 /* XCRemoteSwiftPackageReference "Then" */;
productName = Then;
};
- C1865DA82BBE946D00DD99C9 /* RxAlamofire */ = {
+ 9B92891D2BBECF2300185E35 /* RxCocoa */ = {
isa = XCSwiftPackageProductDependency;
- package = C1865DA72BBE946D00DD99C9 /* XCRemoteSwiftPackageReference "RxAlamofire" */;
- productName = RxAlamofire;
+ package = 9B92891C2BBECF2300185E35 /* XCRemoteSwiftPackageReference "RxSwift" */;
+ productName = RxCocoa;
};
- C1865DB12BBE948000DD99C9 /* RxSwift */ = {
+ 9B92891F2BBECF2300185E35 /* RxSwift */ = {
isa = XCSwiftPackageProductDependency;
- package = C1865DAA2BBE948000DD99C9 /* XCRemoteSwiftPackageReference "RxSwift" */;
+ package = 9B92891C2BBECF2300185E35 /* XCRemoteSwiftPackageReference "RxSwift" */;
productName = RxSwift;
};
/* End XCSwiftPackageProductDependency section */
diff --git a/ChatBot/ChatBot.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ChatBot/ChatBot.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
index 6113c9f6..fc378417 100644
--- a/ChatBot/ChatBot.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ b/ChatBot/ChatBot.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -1,5 +1,5 @@
{
- "originHash" : "49f99251b083029aceba100c19348cc708f09dda9dd89fd947a14b1267b66431",
+ "originHash" : "434d8fd556075b3fea154ef6be6a87b866cff70e8199cd257890d217ec0cfe6a",
"pins" : [
{
"identity" : "alamofire",
diff --git a/ChatBot/ChatBot/Model/ChatRepository.swift b/ChatBot/ChatBot/Model/ChatRepository.swift
index a4cda9b5..ce578fc3 100644
--- a/ChatBot/ChatBot/Model/ChatRepository.swift
+++ b/ChatBot/ChatBot/Model/ChatRepository.swift
@@ -16,15 +16,15 @@ struct ChatRepository {
self.network = network
}
- func requestChatResultData(userMessage: String)-> Observable {
+ func requestChatResultData(message: Message)-> Observable {
// let chat = RequestChatDTO(messages: [
// Message(role: "system", content: "너는 연애고수야"),
// Message(role: "user", content: "\(userMessage)")
// ])
- return network.fetchData()
-//
+ return network.fetchData(message: message)
+//
// let result = try await apiService.fetchData(with: urlRequest)
// switch result {
// case .success(let success):
diff --git a/ChatBot/ChatBot/ViewModel/ChatBotViewModel.swift b/ChatBot/ChatBot/ViewModel/ChatBotViewModel.swift
index 48c7927b..a6dc8f4a 100644
--- a/ChatBot/ChatBot/ViewModel/ChatBotViewModel.swift
+++ b/ChatBot/ChatBot/ViewModel/ChatBotViewModel.swift
@@ -12,15 +12,12 @@ final class ChatBotViewModel {
private let chatBotNetwork: ChatBotNetwork
init() {
- let chat = RequestChatDTO(messages: [
- Message(role: "system", content: "나는 병신이야"),
- Message(role: "user", content: "집에가고싶어요..")
- ])
- self.chatBotNetwork = ChatBotNetwork(network: Network(NetworkURL.makeURLRequest(type: .chatGPT, chat: chat, httpMethod: .post)!))
+ let provider = NetworkProvider()
+ self.chatBotNetwork = provider.makeChatNetwork()
}
struct Input {
- let chatTigger: Observable
+ let chatTigger: Observable
}
struct Output {
@@ -28,8 +25,8 @@ final class ChatBotViewModel {
}
func transform(input: Input) -> Output {
- let resultChat = input.chatTigger.flatMapLatest { [unowned self] _ -> Observable> in
- self.chatBotNetwork.requestChatBotMessage().map {
+ let resultChat = input.chatTigger.flatMapLatest { [unowned self] message -> Observable> in
+ self.chatBotNetwork.requestChatBotMessage(message: message).map {
return .success($0)
}
.catchError { error in
From a4f0abe8a1c0728f262577a45417664564ead923 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthew=28=EB=A7=A4=ED=8A=9C=29?=
Date: Fri, 5 Apr 2024 11:17:45 +0900
Subject: [PATCH 12/24] =?UTF-8?q?feat:=20RxAlamofire=EB=A5=BC=20=ED=99=9C?=
=?UTF-8?q?=EC=9A=A9=ED=95=98=EC=97=AC=20Network=20=EA=B8=B0=EB=8A=A5=20?=
=?UTF-8?q?=EA=B5=AC=ED=98=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
ChatBot/ChatBot.xcodeproj/project.pbxproj | 84 +++++++++----------
.../xcshareddata/swiftpm/Package.resolved | 2 +-
ChatBot/ChatBot/App/SceneDelegate.swift | 6 +-
ChatBot/ChatBot/Model/ChatRepository.swift | 52 ------------
.../ChatBot/ViewModel/ChatBotViewModel.swift | 14 +---
.../ChatBot/ViewModel/ChatRepository.swift | 26 ++++++
6 files changed, 75 insertions(+), 109 deletions(-)
delete mode 100644 ChatBot/ChatBot/Model/ChatRepository.swift
create mode 100644 ChatBot/ChatBot/ViewModel/ChatRepository.swift
diff --git a/ChatBot/ChatBot.xcodeproj/project.pbxproj b/ChatBot/ChatBot.xcodeproj/project.pbxproj
index c9e3093c..d80ffb50 100644
--- a/ChatBot/ChatBot.xcodeproj/project.pbxproj
+++ b/ChatBot/ChatBot.xcodeproj/project.pbxproj
@@ -7,11 +7,6 @@
objects = {
/* Begin PBXBuildFile section */
- 9B9289152BBECEDC00185E35 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = 9B9289142BBECEDC00185E35 /* SnapKit */; };
- 9B9289182BBECEEB00185E35 /* RxAlamofire in Frameworks */ = {isa = PBXBuildFile; productRef = 9B9289172BBECEEB00185E35 /* RxAlamofire */; };
- 9B92891B2BBECEF900185E35 /* Then in Frameworks */ = {isa = PBXBuildFile; productRef = 9B92891A2BBECEF900185E35 /* Then */; };
- 9B92891E2BBECF2300185E35 /* RxCocoa in Frameworks */ = {isa = PBXBuildFile; productRef = 9B92891D2BBECF2300185E35 /* RxCocoa */; };
- 9B9289202BBECF2300185E35 /* RxSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 9B92891F2BBECF2300185E35 /* RxSwift */; };
9B9289222BBECF5B00185E35 /* APIToken.plist in Resources */ = {isa = PBXBuildFile; fileRef = 9B9289212BBECF5B00185E35 /* APIToken.plist */; };
C12E66D32BB3F28800F3F441 /* ChatBotViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66B82BB3F28800F3F441 /* ChatBotViewModel.swift */; };
C12E66D42BB3F28800F3F441 /* ChatRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66B92BB3F28800F3F441 /* ChatRepository.swift */; };
@@ -32,6 +27,11 @@
C12E66EC2BB4291A00F3F441 /* ResponseChoiceDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66EB2BB4291A00F3F441 /* ResponseChoiceDTO.swift */; };
C12E66EE2BB4294300F3F441 /* Usage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66ED2BB4294300F3F441 /* Usage.swift */; };
C12E66F02BB429AA00F3F441 /* JSONNull.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66EF2BB429AA00F3F441 /* JSONNull.swift */; };
+ C176AB4A2BBEDD97004DEA01 /* Then in Frameworks */ = {isa = PBXBuildFile; productRef = C176AB492BBEDD97004DEA01 /* Then */; };
+ C176AB4D2BBEDDA5004DEA01 /* RxAlamofire in Frameworks */ = {isa = PBXBuildFile; productRef = C176AB4C2BBEDDA5004DEA01 /* RxAlamofire */; };
+ C176AB502BBEDDB1004DEA01 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = C176AB4F2BBEDDB1004DEA01 /* SnapKit */; };
+ C176AB532BBEDDC1004DEA01 /* RxCocoa in Frameworks */ = {isa = PBXBuildFile; productRef = C176AB522BBEDDC1004DEA01 /* RxCocoa */; };
+ C176AB552BBEDDC1004DEA01 /* RxSwift in Frameworks */ = {isa = PBXBuildFile; productRef = C176AB542BBEDDC1004DEA01 /* RxSwift */; };
C1865DB82BBE9C3400DD99C9 /* Network.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1865DB72BBE9C3400DD99C9 /* Network.swift */; };
C1865DBA2BBE9E8600DD99C9 /* NetworkProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1865DB92BBE9E8600DD99C9 /* NetworkProvider.swift */; };
C1865DBC2BBEB72900DD99C9 /* ChatBotNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1865DBB2BBEB72900DD99C9 /* ChatBotNetwork.swift */; };
@@ -72,11 +72,11 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- 9B9289152BBECEDC00185E35 /* SnapKit in Frameworks */,
- 9B92891B2BBECEF900185E35 /* Then in Frameworks */,
- 9B9289202BBECF2300185E35 /* RxSwift in Frameworks */,
- 9B92891E2BBECF2300185E35 /* RxCocoa in Frameworks */,
- 9B9289182BBECEEB00185E35 /* RxAlamofire in Frameworks */,
+ C176AB502BBEDDB1004DEA01 /* SnapKit in Frameworks */,
+ C176AB4A2BBEDD97004DEA01 /* Then in Frameworks */,
+ C176AB552BBEDDC1004DEA01 /* RxSwift in Frameworks */,
+ C176AB532BBEDDC1004DEA01 /* RxCocoa in Frameworks */,
+ C176AB4D2BBEDDA5004DEA01 /* RxAlamofire in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -116,7 +116,6 @@
C12E66BC2BB3F28800F3F441 /* Model */ = {
isa = PBXGroup;
children = (
- C12E66B92BB3F28800F3F441 /* ChatRepository.swift */,
C12E66BA2BB3F28800F3F441 /* RequestChatDTO.swift */,
C12E66BB2BB3F28800F3F441 /* Message.swift */,
C12E66E92BB4283100F3F441 /* ResponseChatDTO.swift */,
@@ -183,6 +182,7 @@
isa = PBXGroup;
children = (
C12E66B82BB3F28800F3F441 /* ChatBotViewModel.swift */,
+ C12E66B92BB3F28800F3F441 /* ChatRepository.swift */,
);
path = ViewModel;
sourceTree = "";
@@ -204,11 +204,11 @@
);
name = ChatBot;
packageProductDependencies = (
- 9B9289142BBECEDC00185E35 /* SnapKit */,
- 9B9289172BBECEEB00185E35 /* RxAlamofire */,
- 9B92891A2BBECEF900185E35 /* Then */,
- 9B92891D2BBECF2300185E35 /* RxCocoa */,
- 9B92891F2BBECF2300185E35 /* RxSwift */,
+ C176AB492BBEDD97004DEA01 /* Then */,
+ C176AB4C2BBEDDA5004DEA01 /* RxAlamofire */,
+ C176AB4F2BBEDDB1004DEA01 /* SnapKit */,
+ C176AB522BBEDDC1004DEA01 /* RxCocoa */,
+ C176AB542BBEDDC1004DEA01 /* RxSwift */,
);
productName = ChatBot;
productReference = B4B3E2B92B42D1BB00818B3C /* ChatBot.app */;
@@ -239,10 +239,10 @@
);
mainGroup = B4B3E2B02B42D1BB00818B3C;
packageReferences = (
- 9B9289132BBECEDC00185E35 /* XCRemoteSwiftPackageReference "SnapKit" */,
- 9B9289162BBECEEB00185E35 /* XCRemoteSwiftPackageReference "RxAlamofire" */,
- 9B9289192BBECEF900185E35 /* XCRemoteSwiftPackageReference "Then" */,
- 9B92891C2BBECF2300185E35 /* XCRemoteSwiftPackageReference "RxSwift" */,
+ C176AB482BBEDD97004DEA01 /* XCRemoteSwiftPackageReference "Then" */,
+ C176AB4B2BBEDDA5004DEA01 /* XCRemoteSwiftPackageReference "RxAlamofire" */,
+ C176AB4E2BBEDDB1004DEA01 /* XCRemoteSwiftPackageReference "SnapKit" */,
+ C176AB512BBEDDC1004DEA01 /* XCRemoteSwiftPackageReference "RxSwift" */,
);
productRefGroup = B4B3E2BA2B42D1BB00818B3C /* Products */;
projectDirPath = "";
@@ -435,7 +435,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_TEAM = 7VXN2294AY;
+ DEVELOPMENT_TEAM = T92LV6HV88;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = ChatBot/Resource/Info.plist;
"INFOPLIST_FILE[sdk=*]" = ChatBot/Resource/Info.plist;
@@ -468,7 +468,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_TEAM = 7VXN2294AY;
+ DEVELOPMENT_TEAM = T92LV6HV88;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = ChatBot/Resource/Info.plist;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
@@ -517,15 +517,15 @@
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
- 9B9289132BBECEDC00185E35 /* XCRemoteSwiftPackageReference "SnapKit" */ = {
+ C176AB482BBEDD97004DEA01 /* XCRemoteSwiftPackageReference "Then" */ = {
isa = XCRemoteSwiftPackageReference;
- repositoryURL = "https://github.com/SnapKit/SnapKit.git";
+ repositoryURL = "https://github.com/devxoul/Then.git";
requirement = {
kind = upToNextMajorVersion;
- minimumVersion = 5.7.1;
+ minimumVersion = 3.0.0;
};
};
- 9B9289162BBECEEB00185E35 /* XCRemoteSwiftPackageReference "RxAlamofire" */ = {
+ C176AB4B2BBEDDA5004DEA01 /* XCRemoteSwiftPackageReference "RxAlamofire" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/RxSwiftCommunity/RxAlamofire.git";
requirement = {
@@ -533,15 +533,15 @@
minimumVersion = 5.2.0;
};
};
- 9B9289192BBECEF900185E35 /* XCRemoteSwiftPackageReference "Then" */ = {
+ C176AB4E2BBEDDB1004DEA01 /* XCRemoteSwiftPackageReference "SnapKit" */ = {
isa = XCRemoteSwiftPackageReference;
- repositoryURL = "https://github.com/devxoul/Then.git";
+ repositoryURL = "https://github.com/SnapKit/SnapKit.git";
requirement = {
kind = upToNextMajorVersion;
- minimumVersion = 3.0.0;
+ minimumVersion = 5.7.1;
};
};
- 9B92891C2BBECF2300185E35 /* XCRemoteSwiftPackageReference "RxSwift" */ = {
+ C176AB512BBEDDC1004DEA01 /* XCRemoteSwiftPackageReference "RxSwift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/ReactiveX/RxSwift.git";
requirement = {
@@ -552,29 +552,29 @@
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
- 9B9289142BBECEDC00185E35 /* SnapKit */ = {
+ C176AB492BBEDD97004DEA01 /* Then */ = {
isa = XCSwiftPackageProductDependency;
- package = 9B9289132BBECEDC00185E35 /* XCRemoteSwiftPackageReference "SnapKit" */;
- productName = SnapKit;
+ package = C176AB482BBEDD97004DEA01 /* XCRemoteSwiftPackageReference "Then" */;
+ productName = Then;
};
- 9B9289172BBECEEB00185E35 /* RxAlamofire */ = {
+ C176AB4C2BBEDDA5004DEA01 /* RxAlamofire */ = {
isa = XCSwiftPackageProductDependency;
- package = 9B9289162BBECEEB00185E35 /* XCRemoteSwiftPackageReference "RxAlamofire" */;
+ package = C176AB4B2BBEDDA5004DEA01 /* XCRemoteSwiftPackageReference "RxAlamofire" */;
productName = RxAlamofire;
};
- 9B92891A2BBECEF900185E35 /* Then */ = {
+ C176AB4F2BBEDDB1004DEA01 /* SnapKit */ = {
isa = XCSwiftPackageProductDependency;
- package = 9B9289192BBECEF900185E35 /* XCRemoteSwiftPackageReference "Then" */;
- productName = Then;
+ package = C176AB4E2BBEDDB1004DEA01 /* XCRemoteSwiftPackageReference "SnapKit" */;
+ productName = SnapKit;
};
- 9B92891D2BBECF2300185E35 /* RxCocoa */ = {
+ C176AB522BBEDDC1004DEA01 /* RxCocoa */ = {
isa = XCSwiftPackageProductDependency;
- package = 9B92891C2BBECF2300185E35 /* XCRemoteSwiftPackageReference "RxSwift" */;
+ package = C176AB512BBEDDC1004DEA01 /* XCRemoteSwiftPackageReference "RxSwift" */;
productName = RxCocoa;
};
- 9B92891F2BBECF2300185E35 /* RxSwift */ = {
+ C176AB542BBEDDC1004DEA01 /* RxSwift */ = {
isa = XCSwiftPackageProductDependency;
- package = 9B92891C2BBECF2300185E35 /* XCRemoteSwiftPackageReference "RxSwift" */;
+ package = C176AB512BBEDDC1004DEA01 /* XCRemoteSwiftPackageReference "RxSwift" */;
productName = RxSwift;
};
/* End XCSwiftPackageProductDependency section */
diff --git a/ChatBot/ChatBot.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ChatBot/ChatBot.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
index fc378417..1141d972 100644
--- a/ChatBot/ChatBot.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ b/ChatBot/ChatBot.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -1,5 +1,5 @@
{
- "originHash" : "434d8fd556075b3fea154ef6be6a87b866cff70e8199cd257890d217ec0cfe6a",
+ "originHash" : "4f59d014461f30b3b54708c61616f21472f63b7383d229842af8de6b8dc507d8",
"pins" : [
{
"identity" : "alamofire",
diff --git a/ChatBot/ChatBot/App/SceneDelegate.swift b/ChatBot/ChatBot/App/SceneDelegate.swift
index 6ca7c1c5..cc386a86 100644
--- a/ChatBot/ChatBot/App/SceneDelegate.swift
+++ b/ChatBot/ChatBot/App/SceneDelegate.swift
@@ -9,8 +9,7 @@ import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
-
- let chatManger = ChatBotViewModel()
+ let chatViewModel = ChatBotViewModel(chatRepository: ChatRepository(provider: NetworkProvider()))
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard
@@ -19,8 +18,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
return
}
window = UIWindow(windowScene: windowScene)
-
- let mainViewController = ChatBotViewController(chatBotViewModel: chatManger)
+ let mainViewController = ChatBotViewController(chatBotViewModel: chatViewModel)
window?.rootViewController = mainViewController
window?.makeKeyAndVisible()
}
diff --git a/ChatBot/ChatBot/Model/ChatRepository.swift b/ChatBot/ChatBot/Model/ChatRepository.swift
deleted file mode 100644
index ce578fc3..00000000
--- a/ChatBot/ChatBot/Model/ChatRepository.swift
+++ /dev/null
@@ -1,52 +0,0 @@
-//
-// Repository.swift
-// ChatBot
-//
-// Created by LeeSeongYeon on 3/26/24.
-//
-
-import Foundation
-import RxSwift
-
-struct ChatRepository {
-// private let apiService: APIService = APIService(session: URLSession.shared)
- let network: Network
-
- init(network: Network) {
- self.network = network
- }
-
- func requestChatResultData(message: Message)-> Observable {
-
-// let chat = RequestChatDTO(messages: [
-// Message(role: "system", content: "너는 연애고수야"),
-// Message(role: "user", content: "\(userMessage)")
-// ])
-
- return network.fetchData(message: message)
-//
-// let result = try await apiService.fetchData(with: urlRequest)
-// switch result {
-// case .success(let success):
-// return handleDecodedData(data: success)
-// case .failure(let failure):
-// return .failure(failure)
-// }
- }
-}
-
-private extension ChatRepository {
- func handleDecodedData(data: Data?) -> (Result) {
- guard
- let data = data
- else {
- return .failure(.noDataError)
- }
- do {
- let decodedData = try JSONDecoder().decode(T.self, from: data)
- return .success(decodedData)
- } catch {
- return .failure(.decodingError)
- }
- }
-}
diff --git a/ChatBot/ChatBot/ViewModel/ChatBotViewModel.swift b/ChatBot/ChatBot/ViewModel/ChatBotViewModel.swift
index a6dc8f4a..3269b913 100644
--- a/ChatBot/ChatBot/ViewModel/ChatBotViewModel.swift
+++ b/ChatBot/ChatBot/ViewModel/ChatBotViewModel.swift
@@ -9,11 +9,10 @@ import Foundation
import RxSwift
final class ChatBotViewModel {
- private let chatBotNetwork: ChatBotNetwork
+ private let chatRepository: ChatRepository
- init() {
- let provider = NetworkProvider()
- self.chatBotNetwork = provider.makeChatNetwork()
+ init(chatRepository: ChatRepository) {
+ self.chatRepository = chatRepository
}
struct Input {
@@ -26,12 +25,7 @@ final class ChatBotViewModel {
func transform(input: Input) -> Output {
let resultChat = input.chatTigger.flatMapLatest { [unowned self] message -> Observable> in
- self.chatBotNetwork.requestChatBotMessage(message: message).map {
- return .success($0)
- }
- .catchError { error in
- return Observable.just(.failure(error))
- }
+ return self.chatRepository.requestChatResultData(message: message)
}
return Output(resultChat: resultChat)
}
diff --git a/ChatBot/ChatBot/ViewModel/ChatRepository.swift b/ChatBot/ChatBot/ViewModel/ChatRepository.swift
new file mode 100644
index 00000000..be86cbc1
--- /dev/null
+++ b/ChatBot/ChatBot/ViewModel/ChatRepository.swift
@@ -0,0 +1,26 @@
+//
+// Repository.swift
+// ChatBot
+//
+// Created by LeeSeongYeon on 3/26/24.
+//
+
+import Foundation
+import RxSwift
+
+struct ChatRepository {
+ private let chatBotNetwork: ChatBotNetwork
+
+ init(provider: NetworkProvider) {
+ self.chatBotNetwork = provider.makeChatNetwork()
+ }
+
+ func requestChatResultData(message: Message)-> Observable> {
+ self.chatBotNetwork.requestChatBotMessage(message: message).map {
+ return .success($0)
+ }
+ .catchError { error in
+ return Observable.just(.failure(error))
+ }
+ }
+}
From 9dc283f1ccbab4f0d8daf25181e25c2dcf06880b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthew=28=EB=A7=A4=ED=8A=9C=29?=
<130636633+kimbs5899@users.noreply.github.com>
Date: Fri, 5 Apr 2024 11:33:27 +0900
Subject: [PATCH 13/24] =?UTF-8?q?docs:=20gitignore=20Pods=20=EC=82=AD?=
=?UTF-8?q?=EC=A0=9C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 8 --------
1 file changed, 8 deletions(-)
diff --git a/.gitignore b/.gitignore
index 47a47430..2b25befd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,14 +1,6 @@
# Created by https://www.toptal.com/developers/gitignore/api/xcode,swift,cocoapods
# Edit at https://www.toptal.com/developers/gitignore?templates=xcode,swift,cocoapods
-### CocoaPods ###
-## CocoaPods GitIgnore Template
-
-# CocoaPods - Only use to conserve bandwidth / Save time on Pushing
-# - Also handy if you have a large number of dependant pods
-# - AS PER https://guides.cocoapods.org/using/using-cocoapods.html NEVER IGNORE THE LOCK FILE
-Pods/
-
### Swift ###
# Xcode
#
From a34ffb12a6cdb9a42d51c5c8310e7e0ac3befe25 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthew=28=EB=A7=A4=ED=8A=9C=29?=
Date: Fri, 5 Apr 2024 16:07:26 +0900
Subject: [PATCH 14/24] =?UTF-8?q?feat:=20RxAlamofire=20Network=20Error=20A?=
=?UTF-8?q?lert=EB=8C=80=EC=9D=91=20=EA=B5=AC=ED=98=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
ChatBot/ChatBot.xcodeproj/project.pbxproj | 166 +-
.../xcshareddata/swiftpm/Package.resolved | 60 -
.../contents.xcworkspacedata | 10 +
.../xcshareddata/IDEWorkspaceChecks.plist | 8 +
ChatBot/ChatBot/Model/RequestChatDTO.swift | 2 +-
ChatBot/ChatBot/Network/APIService.swift | 50 -
ChatBot/ChatBot/Network/Network.swift | 2 +-
ChatBot/ChatBot/Network/NetworkError.swift | 43 -
.../ChatBot/View/ChatBotViewController.swift | 17 +-
.../ChatBot/ViewModel/ChatBotViewModel.swift | 4 +
.../ChatBot/ViewModel/ChatRepository.swift | 9 +-
ChatBot/Podfile | 14 +
ChatBot/Podfile.lock | 45 +
ChatBot/Pods/Alamofire/LICENSE | 19 +
ChatBot/Pods/Alamofire/README.md | 269 ++
ChatBot/Pods/Alamofire/Source/Alamofire.swift | 43 +
.../Pods/Alamofire/Source/Core/AFError.swift | 874 +++++
.../Alamofire/Source/Core/DataRequest.swift | 448 +++
.../Source/Core/DataStreamRequest.swift | 584 +++
.../Source/Core/DownloadRequest.swift | 588 +++
.../Alamofire/Source/Core/HTTPHeaders.swift | 466 +++
.../Alamofire/Source/Core/HTTPMethod.swift | 56 +
.../Alamofire/Source/Core/Notifications.swift | 115 +
.../Source/Core/ParameterEncoder.swift | 213 +
.../Source/Core/ParameterEncoding.swift | 349 ++
.../Alamofire/Source/Core/Protected.swift | 168 +
.../Pods/Alamofire/Source/Core/Request.swift | 1090 ++++++
.../Source/Core/RequestTaskMap.swift | 150 +
.../Pods/Alamofire/Source/Core/Response.swift | 453 +++
.../Pods/Alamofire/Source/Core/Session.swift | 1350 +++++++
.../Source/Core/SessionDelegate.swift | 387 ++
...URLConvertible+URLRequestConvertible.swift | 105 +
.../Alamofire/Source/Core/UploadRequest.swift | 174 +
.../Source/Core/WebSocketRequest.swift | 564 +++
.../Extensions/DispatchQueue+Alamofire.swift | 37 +
.../Extensions/OperationQueue+Alamofire.swift | 49 +
.../Source/Extensions/Result+Alamofire.swift | 120 +
.../Extensions/StringEncoding+Alamofire.swift | 55 +
.../Extensions/URLRequest+Alamofire.swift | 39 +
.../URLSessionConfiguration+Alamofire.swift | 46 +
.../Source/Features/AlamofireExtended.swift | 61 +
.../Features/AuthenticationInterceptor.swift | 402 ++
.../Features/CachedResponseHandler.swift | 107 +
.../Alamofire/Source/Features/Combine.swift | 652 ++++
.../Source/Features/Concurrency.swift | 962 +++++
.../Source/Features/EventMonitor.swift | 907 +++++
.../Source/Features/MultipartFormData.swift | 601 +++
.../Source/Features/MultipartUpload.swift | 89 +
.../Features/NetworkReachabilityManager.swift | 292 ++
.../Source/Features/RedirectHandler.swift | 111 +
.../Source/Features/RequestCompression.swift | 146 +
.../Source/Features/RequestInterceptor.swift | 351 ++
.../Features/ResponseSerialization.swift | 525 +++
.../Source/Features/RetryPolicy.swift | 430 +++
.../Features/ServerTrustEvaluation.swift | 768 ++++
.../Features/URLEncodedFormEncoder.swift | 1151 ++++++
.../Source/Features/Validation.swift | 302 ++
.../Alamofire/Source/PrivacyInfo.xcprivacy | 23 +
ChatBot/Pods/Manifest.lock | 45 +
ChatBot/Pods/Pods.xcodeproj/project.pbxproj | 3416 +++++++++++++++++
ChatBot/Pods/RxAlamofire/LICENSE.md | 21 +
ChatBot/Pods/RxAlamofire/README.md | 232 ++
.../Sources/RxAlamofire/RxAlamofire.swift | 1589 ++++++++
ChatBot/Pods/RxCocoa/LICENSE.md | 9 +
.../RxCocoa/Platform/DataStructures/Bag.swift | 181 +
.../DataStructures/InfiniteSequence.swift | 23 +
.../DataStructures/PriorityQueue.swift | 111 +
.../Platform/DataStructures/Queue.swift | 148 +
.../Platform/DispatchQueue+Extensions.swift | 21 +
.../RxCocoa/Platform/Platform.Darwin.swift | 35 +
.../RxCocoa/Platform/Platform.Linux.swift | 32 +
.../Pods/RxCocoa/Platform/RecursiveLock.swift | 34 +
ChatBot/Pods/RxCocoa/README.md | 254 ++
.../RxCocoa/Common/ControlTarget.swift | 88 +
.../RxCocoa/Common/DelegateProxy.swift | 294 ++
.../RxCocoa/Common/DelegateProxyType.swift | 435 +++
.../RxCocoa/Common/Infallible+Bind.swift | 148 +
.../RxCocoa/Common/Observable+Bind.swift | 103 +
.../RxCocoaObjCRuntimeError+Extensions.swift | 161 +
.../RxCocoa/RxCocoa/Common/RxTarget.swift | 43 +
.../Common/SectionedViewDataSourceType.swift | 20 +
.../RxCocoa/RxCocoa/Common/TextInput.swift | 78 +
.../KVORepresentable+CoreGraphics.swift | 68 +
.../Foundation/KVORepresentable+Swift.swift | 88 +
.../RxCocoa/Foundation/KVORepresentable.swift | 28 +
.../NSObject+Rx+KVORepresentable.swift | 60 +
.../NSObject+Rx+RawRepresentable.swift | 52 +
.../RxCocoa/Foundation/NSObject+Rx.swift | 569 +++
.../Foundation/NotificationCenter+Rx.swift | 31 +
.../RxCocoa/Foundation/URLSession+Rx.swift | 240 ++
ChatBot/Pods/RxCocoa/RxCocoa/Runtime/_RX.m | 10 +
.../RxCocoa/Runtime/_RXDelegateProxy.m | 147 +
.../RxCocoa/RxCocoa/Runtime/_RXKVOObserver.m | 54 +
.../RxCocoa/RxCocoa/Runtime/_RXObjCRuntime.m | 1062 +++++
.../RxCocoa/Runtime/include/RxCocoaRuntime.h | 19 +
.../RxCocoa/RxCocoa/Runtime/include/_RX.h | 93 +
.../Runtime/include/_RXDelegateProxy.h | 27 +
.../RxCocoa/Runtime/include/_RXKVOObserver.h | 28 +
.../RxCocoa/Runtime/include/_RXObjCRuntime.h | 102 +
ChatBot/Pods/RxCocoa/RxCocoa/RxCocoa.h | 19 +
ChatBot/Pods/RxCocoa/RxCocoa/RxCocoa.swift | 155 +
.../RxCocoa/RxCocoa/Traits/ControlEvent.swift | 68 +
.../RxCocoa/Traits/ControlProperty.swift | 118 +
.../Traits/Driver/BehaviorRelay+Driver.swift | 21 +
.../Traits/Driver/ControlEvent+Driver.swift | 24 +
.../Driver/ControlProperty+Driver.swift | 24 +
.../Traits/Driver/Driver+Subscription.swift | 203 +
.../RxCocoa/Traits/Driver/Driver.swift | 53 +
.../ObservableConvertibleType+Driver.swift | 57 +
...rvableConvertibleType+SharedSequence.swift | 57 +
.../SchedulerType+SharedSequence.swift | 62 +
.../SharedSequence+Concurrency.swift | 42 +
.../SharedSequence+Operators+arity.swift | 656 ++++
.../SharedSequence+Operators.swift | 584 +++
.../SharedSequence/SharedSequence.swift | 226 ++
.../Traits/Signal/ControlEvent+Signal.swift | 25 +
.../ObservableConvertibleType+Signal.swift | 57 +
.../Traits/Signal/PublishRelay+Signal.swift | 21 +
.../Traits/Signal/Signal+Subscription.swift | 178 +
.../RxCocoa/Traits/Signal/Signal.swift | 45 +
...ollectionViewReactiveArrayDataSource.swift | 108 +
.../iOS/DataSources/RxPickerViewAdapter.swift | 92 +
.../RxTableViewReactiveArrayDataSource.swift | 101 +
.../RxCocoa/iOS/Events/ItemEvents.swift | 15 +
.../RxCocoa/iOS/NSTextStorage+Rx.swift | 35 +
.../RxCollectionViewDataSourceType.swift | 27 +
.../RxPickerViewDataSourceType.swift | 26 +
.../Protocols/RxTableViewDataSourceType.swift | 27 +
...ectionViewDataSourcePrefetchingProxy.swift | 92 +
.../RxCollectionViewDataSourceProxy.swift | 75 +
.../RxCollectionViewDelegateProxy.swift | 32 +
.../RxNavigationControllerDelegateProxy.swift | 39 +
.../Proxies/RxPickerViewDataSourceProxy.swift | 72 +
.../Proxies/RxPickerViewDelegateProxy.swift | 38 +
.../Proxies/RxScrollViewDelegateProxy.swift | 91 +
.../Proxies/RxSearchBarDelegateProxy.swift | 40 +
.../RxSearchControllerDelegateProxy.swift | 40 +
.../RxTabBarControllerDelegateProxy.swift | 40 +
.../iOS/Proxies/RxTabBarDelegateProxy.swift | 50 +
...xTableViewDataSourcePrefetchingProxy.swift | 93 +
.../Proxies/RxTableViewDataSourceProxy.swift | 73 +
.../Proxies/RxTableViewDelegateProxy.swift | 31 +
.../Proxies/RxTextStorageDelegateProxy.swift | 38 +
.../iOS/Proxies/RxTextViewDelegateProxy.swift | 42 +
.../Proxies/RxWKNavigationDelegateProxy.swift | 45 +
.../iOS/UIActivityIndicatorView+Rx.swift | 27 +
.../RxCocoa/iOS/UIApplication+Rx.swift | 106 +
.../RxCocoa/iOS/UIBarButtonItem+Rx.swift | 72 +
.../RxCocoa/RxCocoa/iOS/UIButton+Rx.swift | 82 +
.../RxCocoa/iOS/UICollectionView+Rx.swift | 380 ++
.../RxCocoa/RxCocoa/iOS/UIControl+Rx.swift | 86 +
.../RxCocoa/RxCocoa/iOS/UIDatePicker+Rx.swift | 43 +
.../RxCocoa/iOS/UIGestureRecognizer+Rx.swift | 75 +
.../iOS/UINavigationController+Rx.swift | 49 +
.../RxCocoa/RxCocoa/iOS/UIPickerView+Rx.swift | 224 ++
.../RxCocoa/iOS/UIRefreshControl+Rx.swift | 28 +
.../RxCocoa/RxCocoa/iOS/UIScrollView+Rx.swift | 131 +
.../RxCocoa/RxCocoa/iOS/UISearchBar+Rx.swift | 136 +
.../RxCocoa/iOS/UISearchController+Rx.swift | 58 +
.../RxCocoa/iOS/UISegmentedControl+Rx.swift | 54 +
.../RxCocoa/RxCocoa/iOS/UISlider+Rx.swift | 29 +
.../RxCocoa/RxCocoa/iOS/UIStepper+Rx.swift | 29 +
.../RxCocoa/RxCocoa/iOS/UISwitch+Rx.swift | 38 +
.../RxCocoa/RxCocoa/iOS/UITabBar+Rx.swift | 92 +
.../RxCocoa/iOS/UITabBarController+Rx.swift | 79 +
.../RxCocoa/RxCocoa/iOS/UITableView+Rx.swift | 429 +++
.../RxCocoa/RxCocoa/iOS/UITextField+Rx.swift | 55 +
.../RxCocoa/RxCocoa/iOS/UITextView+Rx.swift | 125 +
.../RxCocoa/RxCocoa/iOS/WKWebView+Rx.swift | 57 +
.../RxCocoa/RxCocoa/macOS/NSButton+Rx.swift | 33 +
.../RxCocoa/RxCocoa/macOS/NSControl+Rx.swift | 87 +
.../RxCocoa/RxCocoa/macOS/NSSlider+Rx.swift | 30 +
.../RxCocoa/macOS/NSTextField+Rx.swift | 87 +
.../RxCocoa/RxCocoa/macOS/NSTextView+Rx.swift | 94 +
.../RxCocoa/RxCocoa/macOS/NSView+Rx.swift | 21 +
ChatBot/Pods/RxRelay/LICENSE.md | 9 +
ChatBot/Pods/RxRelay/README.md | 254 ++
.../Pods/RxRelay/RxRelay/BehaviorRelay.swift | 42 +
.../RxRelay/RxRelay/Observable+Bind.swift | 149 +
.../Pods/RxRelay/RxRelay/PublishRelay.swift | 36 +
.../Pods/RxRelay/RxRelay/ReplayRelay.swift | 50 +
ChatBot/Pods/RxRelay/RxRelay/Utils.swift | 17 +
ChatBot/Pods/RxSwift/LICENSE.md | 9 +
ChatBot/Pods/RxSwift/Platform/AtomicInt.swift | 71 +
.../RxSwift/Platform/DataStructures/Bag.swift | 181 +
.../DataStructures/InfiniteSequence.swift | 23 +
.../DataStructures/PriorityQueue.swift | 111 +
.../Platform/DataStructures/Queue.swift | 148 +
.../Platform/DispatchQueue+Extensions.swift | 21 +
.../RxSwift/Platform/Platform.Darwin.swift | 35 +
.../RxSwift/Platform/Platform.Linux.swift | 32 +
.../Pods/RxSwift/Platform/RecursiveLock.swift | 34 +
ChatBot/Pods/RxSwift/README.md | 254 ++
.../Pods/RxSwift/RxSwift/AnyObserver.swift | 69 +
ChatBot/Pods/RxSwift/RxSwift/Binder.swift | 59 +
ChatBot/Pods/RxSwift/RxSwift/Cancelable.swift | 13 +
.../RxSwift/Concurrency/AsyncLock.swift | 100 +
.../RxSwift/RxSwift/Concurrency/Lock.swift | 23 +
.../RxSwift/Concurrency/LockOwnerType.swift | 16 +
.../Concurrency/SynchronizedDisposeType.swift | 18 +
.../Concurrency/SynchronizedOnType.swift | 18 +
.../SynchronizedUnsubscribeType.swift | 13 +
.../RxSwift/ConnectableObservableType.swift | 19 +
.../Pods/RxSwift/RxSwift/Date+Dispatch.swift | 64 +
ChatBot/Pods/RxSwift/RxSwift/Disposable.swift | 13 +
.../Disposables/AnonymousDisposable.swift | 59 +
.../Disposables/BinaryDisposable.swift | 53 +
.../Disposables/BooleanDisposable.swift | 33 +
.../Disposables/CompositeDisposable.swift | 147 +
.../RxSwift/Disposables/Disposables.swift | 13 +
.../RxSwift/Disposables/DisposeBag.swift | 144 +
.../RxSwift/Disposables/DisposeBase.swift | 22 +
.../RxSwift/Disposables/NopDisposable.swift | 30 +
.../Disposables/RefCountDisposable.swift | 112 +
.../Disposables/ScheduledDisposable.swift | 50 +
.../Disposables/SerialDisposable.swift | 73 +
.../SingleAssignmentDisposable.swift | 72 +
.../Disposables/SubscriptionDisposable.swift | 21 +
ChatBot/Pods/RxSwift/RxSwift/Errors.swift | 52 +
ChatBot/Pods/RxSwift/RxSwift/Event.swift | 104 +
.../RxSwift/RxSwift/Extensions/Bag+Rx.swift | 50 +
.../RxSwift/RxSwift/GroupedObservable.swift | 35 +
.../RxSwift/ImmediateSchedulerType.swift | 36 +
.../RxSwift/Observable+Concurrency.swift | 68 +
ChatBot/Pods/RxSwift/RxSwift/Observable.swift | 31 +
.../RxSwift/ObservableConvertibleType.swift | 18 +
.../RxSwift/ObservableType+Extensions.swift | 174 +
.../Pods/RxSwift/RxSwift/ObservableType.swift | 45 +
.../RxSwift/RxSwift/Observables/AddRef.swift | 44 +
.../RxSwift/RxSwift/Observables/Amb.swift | 157 +
.../RxSwift/RxSwift/Observables/AsMaybe.swift | 48 +
.../RxSwift/Observables/AsSingle.swift | 51 +
.../RxSwift/RxSwift/Observables/Buffer.swift | 138 +
.../RxSwift/RxSwift/Observables/Catch.swift | 275 ++
.../CombineLatest+Collection.swift | 165 +
.../Observables/CombineLatest+arity.swift | 843 ++++
.../RxSwift/Observables/CombineLatest.swift | 131 +
.../RxSwift/Observables/CompactMap.swift | 76 +
.../RxSwift/RxSwift/Observables/Concat.swift | 131 +
.../RxSwift/RxSwift/Observables/Create.swift | 78 +
.../RxSwift/Observables/Debounce.swift | 119 +
.../RxSwift/RxSwift/Observables/Debug.swift | 102 +
.../RxSwift/RxSwift/Observables/Decode.swift | 34 +
.../RxSwift/Observables/DefaultIfEmpty.swift | 66 +
.../RxSwift/Observables/Deferred.swift | 75 +
.../RxSwift/RxSwift/Observables/Delay.swift | 174 +
.../Observables/DelaySubscription.swift | 58 +
.../RxSwift/Observables/Dematerialize.swift | 51 +
.../Observables/DistinctUntilChanged.swift | 137 +
.../Pods/RxSwift/RxSwift/Observables/Do.swift | 112 +
.../RxSwift/Observables/ElementAt.swift | 105 +
.../RxSwift/RxSwift/Observables/Empty.swift | 27 +
.../RxSwift/Observables/Enumerated.swift | 61 +
.../RxSwift/RxSwift/Observables/Error.swift | 33 +
.../RxSwift/RxSwift/Observables/Filter.swift | 86 +
.../RxSwift/RxSwift/Observables/First.swift | 41 +
.../RxSwift/Observables/Generate.swift | 87 +
.../RxSwift/RxSwift/Observables/GroupBy.swift | 133 +
.../RxSwift/RxSwift/Observables/Just.swift | 87 +
.../RxSwift/RxSwift/Observables/Map.swift | 77 +
.../RxSwift/Observables/Materialize.swift | 44 +
.../RxSwift/RxSwift/Observables/Merge.swift | 600 +++
.../RxSwift/Observables/Multicast.swift | 405 ++
.../RxSwift/RxSwift/Observables/Never.swift | 27 +
.../RxSwift/Observables/ObserveOn.swift | 243 ++
.../RxSwift/Observables/Optional.swift | 95 +
.../RxSwift/Observables/Producer.swift | 92 +
.../RxSwift/RxSwift/Observables/Range.swift | 73 +
.../RxSwift/RxSwift/Observables/Reduce.swift | 109 +
.../RxSwift/RxSwift/Observables/Repeat.swift | 57 +
.../RxSwift/Observables/RetryWhen.swift | 211 +
.../RxSwift/RxSwift/Observables/Sample.swift | 139 +
.../RxSwift/RxSwift/Observables/Scan.swift | 100 +
.../RxSwift/Observables/Sequence.swift | 89 +
.../Observables/ShareReplayScope.swift | 443 +++
.../RxSwift/Observables/SingleAsync.swift | 104 +
.../RxSwift/RxSwift/Observables/Sink.swift | 75 +
.../RxSwift/RxSwift/Observables/Skip.swift | 158 +
.../RxSwift/Observables/SkipUntil.swift | 152 +
.../RxSwift/Observables/SkipWhile.swift | 87 +
.../RxSwift/Observables/StartWith.swift | 42 +
.../RxSwift/Observables/SubscribeOn.swift | 103 +
.../RxSwift/RxSwift/Observables/Switch.swift | 251 ++
.../RxSwift/Observables/SwitchIfEmpty.swift | 104 +
.../RxSwift/RxSwift/Observables/Take.swift | 193 +
.../RxSwift/Observables/TakeLast.swift | 78 +
.../Observables/TakeWithPredicate.swift | 285 ++
.../RxSwift/Observables/Throttle.swift | 160 +
.../RxSwift/RxSwift/Observables/Timeout.swift | 151 +
.../RxSwift/RxSwift/Observables/Timer.swift | 117 +
.../RxSwift/RxSwift/Observables/ToArray.swift | 64 +
.../RxSwift/RxSwift/Observables/Using.swift | 90 +
.../RxSwift/RxSwift/Observables/Window.swift | 168 +
.../RxSwift/Observables/WithLatestFrom.swift | 151 +
.../RxSwift/Observables/WithUnretained.swift | 58 +
.../RxSwift/Observables/Zip+Collection.swift | 168 +
.../RxSwift/Observables/Zip+arity.swift | 934 +++++
.../RxSwift/RxSwift/Observables/Zip.swift | 135 +
.../Pods/RxSwift/RxSwift/ObserverType.swift | 40 +
.../RxSwift/Observers/AnonymousObserver.swift | 30 +
.../RxSwift/Observers/ObserverBase.swift | 32 +
.../RxSwift/Observers/TailRecursiveSink.swift | 151 +
ChatBot/Pods/RxSwift/RxSwift/Reactive.swift | 80 +
ChatBot/Pods/RxSwift/RxSwift/Rx.swift | 142 +
.../Pods/RxSwift/RxSwift/RxMutableBox.swift | 53 +
.../Pods/RxSwift/RxSwift/SchedulerType.swift | 71 +
.../ConcurrentDispatchQueueScheduler.swift | 82 +
.../Schedulers/ConcurrentMainScheduler.swift | 87 +
.../Schedulers/CurrentThreadScheduler.swift | 131 +
.../Schedulers/HistoricalScheduler.swift | 22 +
.../HistoricalSchedulerTimeConverter.swift | 67 +
.../Internal/DispatchQueueConfiguration.swift | 97 +
.../Internal/InvocableScheduledItem.swift | 22 +
.../Schedulers/Internal/InvocableType.swift | 17 +
.../Schedulers/Internal/ScheduledItem.swift | 35 +
.../Internal/ScheduledItemType.swift | 13 +
.../RxSwift/Schedulers/MainScheduler.swift | 80 +
.../Schedulers/OperationQueueScheduler.swift | 54 +
.../Schedulers/RecursiveScheduler.swift | 220 ++
.../SchedulerServices+Emulation.swift | 61 +
.../SerialDispatchQueueScheduler.swift | 131 +
.../Schedulers/VirtualTimeConverterType.swift | 97 +
.../Schedulers/VirtualTimeScheduler.swift | 267 ++
.../RxSwift/Subjects/AsyncSubject.swift | 154 +
.../RxSwift/Subjects/BehaviorSubject.swift | 157 +
.../RxSwift/Subjects/PublishSubject.swift | 140 +
.../RxSwift/Subjects/ReplaySubject.swift | 271 ++
.../RxSwift/Subjects/SubjectType.swift | 21 +
.../RxSwift/SwiftSupport/SwiftSupport.swift | 18 +
.../Infallible+CombineLatest+arity.swift | 151 +
.../Infallible/Infallible+Concurrency.swift | 37 +
.../Traits/Infallible/Infallible+Create.swift | 44 +
.../Infallible/Infallible+Operators.swift | 711 ++++
.../Infallible/Infallible+Zip+arity.swift | 138 +
.../Traits/Infallible/Infallible.swift | 92 +
...ObservableConvertibleType+Infallible.swift | 35 +
.../Completable+AndThen.swift | 132 +
.../PrimitiveSequence/Completable.swift | 320 ++
.../Traits/PrimitiveSequence/Maybe.swift | 387 ++
.../ObservableType+PrimitiveSequence.swift | 55 +
.../PrimitiveSequence+Concurrency.swift | 132 +
.../PrimitiveSequence+Zip+arity.swift | 521 +++
.../PrimitiveSequence/PrimitiveSequence.swift | 342 ++
.../Traits/PrimitiveSequence/Single.swift | 403 ++
ChatBot/Pods/SnapKit/LICENSE | 19 +
ChatBot/Pods/SnapKit/README.md | 155 +
ChatBot/Pods/SnapKit/Sources/Constraint.swift | 341 ++
.../Sources/ConstraintAttributes.swift | 203 +
.../SnapKit/Sources/ConstraintConfig.swift | 37 +
.../Sources/ConstraintConstantTarget.swift | 213 +
.../Pods/SnapKit/Sources/ConstraintDSL.swift | 209 +
.../Sources/ConstraintDescription.swift | 69 +
.../ConstraintDirectionalInsetTarget.swift | 49 +
.../Sources/ConstraintDirectionalInsets.swift | 34 +
.../Sources/ConstraintInsetTarget.swift | 72 +
.../SnapKit/Sources/ConstraintInsets.swift | 35 +
.../Pods/SnapKit/Sources/ConstraintItem.swift | 61 +
.../ConstraintLayoutGuide+Extensions.swift | 36 +
.../Sources/ConstraintLayoutGuide.swift | 37 +
.../Sources/ConstraintLayoutGuideDSL.swift | 66 +
.../Sources/ConstraintLayoutSupport.swift | 36 +
.../Sources/ConstraintLayoutSupportDSL.swift | 56 +
.../SnapKit/Sources/ConstraintMaker.swift | 224 ++
.../Sources/ConstraintMakerEditable.swift | 64 +
.../Sources/ConstraintMakerExtendable.swift | 195 +
.../Sources/ConstraintMakerFinalizable.swift | 49 +
.../ConstraintMakerPrioritizable.swift | 70 +
.../ConstraintMakerRelatable+Extensions.swift | 57 +
.../Sources/ConstraintMakerRelatable.swift | 115 +
.../Sources/ConstraintMultiplierTarget.swift | 75 +
.../Sources/ConstraintOffsetTarget.swift | 69 +
.../SnapKit/Sources/ConstraintPriority.swift | 77 +
.../Sources/ConstraintPriorityTarget.swift | 85 +
.../Sources/ConstraintRelatableTarget.swift | 72 +
.../SnapKit/Sources/ConstraintRelation.swift | 48 +
.../Sources/ConstraintView+Extensions.swift | 152 +
.../Pods/SnapKit/Sources/ConstraintView.swift | 35 +
.../SnapKit/Sources/ConstraintViewDSL.swift | 101 +
ChatBot/Pods/SnapKit/Sources/Debugging.swift | 169 +
.../SnapKit/Sources/LayoutConstraint.swift | 61 +
.../Sources/LayoutConstraintItem.swift | 93 +
.../SnapKit/Sources/PrivacyInfo.xcprivacy | 14 +
.../Pods/SnapKit/Sources/Typealiases.swift | 42 +
.../Sources/UILayoutSupport+Extensions.swift | 36 +
.../Alamofire/Alamofire-Info.plist | 26 +
.../Alamofire/Alamofire-dummy.m | 5 +
.../Alamofire/Alamofire-prefix.pch | 12 +
.../Alamofire/Alamofire-umbrella.h | 16 +
.../Alamofire/Alamofire.debug.xcconfig | 15 +
.../Alamofire/Alamofire.modulemap | 6 +
.../Alamofire/Alamofire.release.xcconfig | 15 +
...ourceBundle-Alamofire-Alamofire-Info.plist | 24 +
.../Pods-ChatBot/Pods-ChatBot-Info.plist | 26 +
.../Pods-ChatBot-acknowledgements.markdown | 137 +
.../Pods-ChatBot-acknowledgements.plist | 205 +
.../Pods-ChatBot/Pods-ChatBot-dummy.m | 5 +
...ot-frameworks-Debug-input-files.xcfilelist | 8 +
...t-frameworks-Debug-output-files.xcfilelist | 7 +
...-frameworks-Release-input-files.xcfilelist | 8 +
...frameworks-Release-output-files.xcfilelist | 7 +
.../Pods-ChatBot/Pods-ChatBot-frameworks.sh | 198 +
.../Pods-ChatBot/Pods-ChatBot-umbrella.h | 16 +
.../Pods-ChatBot/Pods-ChatBot.debug.xcconfig | 15 +
.../Pods-ChatBot/Pods-ChatBot.modulemap | 6 +
.../Pods-ChatBot.release.xcconfig | 15 +
.../RxAlamofire/RxAlamofire-Info.plist | 26 +
.../RxAlamofire/RxAlamofire-dummy.m | 5 +
.../RxAlamofire/RxAlamofire-prefix.pch | 12 +
.../RxAlamofire/RxAlamofire-umbrella.h | 16 +
.../RxAlamofire/RxAlamofire.debug.xcconfig | 16 +
.../RxAlamofire/RxAlamofire.modulemap | 6 +
.../RxAlamofire/RxAlamofire.release.xcconfig | 16 +
.../RxCocoa/RxCocoa-Info.plist | 26 +
.../RxCocoa/RxCocoa-dummy.m | 5 +
.../RxCocoa/RxCocoa-prefix.pch | 12 +
.../RxCocoa/RxCocoa-umbrella.h | 22 +
.../RxCocoa/RxCocoa.debug.xcconfig | 16 +
.../RxCocoa/RxCocoa.modulemap | 6 +
.../RxCocoa/RxCocoa.release.xcconfig | 16 +
.../RxRelay/RxRelay-Info.plist | 26 +
.../RxRelay/RxRelay-dummy.m | 5 +
.../RxRelay/RxRelay-prefix.pch | 12 +
.../RxRelay/RxRelay-umbrella.h | 16 +
.../RxRelay/RxRelay.debug.xcconfig | 16 +
.../RxRelay/RxRelay.modulemap | 6 +
.../RxRelay/RxRelay.release.xcconfig | 16 +
.../RxSwift/RxSwift-Info.plist | 26 +
.../RxSwift/RxSwift-dummy.m | 5 +
.../RxSwift/RxSwift-prefix.pch | 12 +
.../RxSwift/RxSwift-umbrella.h | 16 +
.../RxSwift/RxSwift.debug.xcconfig | 14 +
.../RxSwift/RxSwift.modulemap | 6 +
.../RxSwift/RxSwift.release.xcconfig | 14 +
...eBundle-SnapKit_Privacy-SnapKit-Info.plist | 24 +
.../SnapKit/SnapKit-Info.plist | 26 +
.../SnapKit/SnapKit-dummy.m | 5 +
.../SnapKit/SnapKit-prefix.pch | 12 +
.../SnapKit/SnapKit-umbrella.h | 16 +
.../SnapKit/SnapKit.debug.xcconfig | 15 +
.../SnapKit/SnapKit.modulemap | 6 +
.../SnapKit/SnapKit.release.xcconfig | 15 +
.../Target Support Files/Then/Then-Info.plist | 26 +
.../Target Support Files/Then/Then-dummy.m | 5 +
.../Target Support Files/Then/Then-prefix.pch | 12 +
.../Target Support Files/Then/Then-umbrella.h | 16 +
.../Then/Then.debug.xcconfig | 14 +
.../Target Support Files/Then/Then.modulemap | 6 +
.../Then/Then.release.xcconfig | 14 +
ChatBot/Pods/Then/LICENSE | 21 +
ChatBot/Pods/Then/README.md | 124 +
ChatBot/Pods/Then/Sources/Then/Then.swift | 98 +
451 files changed, 59244 insertions(+), 260 deletions(-)
delete mode 100644 ChatBot/ChatBot.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
create mode 100644 ChatBot/ChatBot.xcworkspace/contents.xcworkspacedata
create mode 100644 ChatBot/ChatBot.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
delete mode 100644 ChatBot/ChatBot/Network/APIService.swift
delete mode 100644 ChatBot/ChatBot/Network/NetworkError.swift
create mode 100644 ChatBot/Podfile
create mode 100644 ChatBot/Podfile.lock
create mode 100644 ChatBot/Pods/Alamofire/LICENSE
create mode 100644 ChatBot/Pods/Alamofire/README.md
create mode 100644 ChatBot/Pods/Alamofire/Source/Alamofire.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Core/AFError.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Core/DataRequest.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Core/DataStreamRequest.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Core/DownloadRequest.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Core/HTTPHeaders.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Core/HTTPMethod.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Core/Notifications.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Core/ParameterEncoder.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Core/ParameterEncoding.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Core/Protected.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Core/Request.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Core/RequestTaskMap.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Core/Response.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Core/Session.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Core/SessionDelegate.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Core/URLConvertible+URLRequestConvertible.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Core/UploadRequest.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Core/WebSocketRequest.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Extensions/DispatchQueue+Alamofire.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Extensions/OperationQueue+Alamofire.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Extensions/Result+Alamofire.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Extensions/StringEncoding+Alamofire.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Extensions/URLRequest+Alamofire.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Extensions/URLSessionConfiguration+Alamofire.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Features/AlamofireExtended.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Features/AuthenticationInterceptor.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Features/CachedResponseHandler.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Features/Combine.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Features/Concurrency.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Features/EventMonitor.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Features/MultipartFormData.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Features/MultipartUpload.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Features/NetworkReachabilityManager.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Features/RedirectHandler.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Features/RequestCompression.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Features/RequestInterceptor.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Features/ResponseSerialization.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Features/RetryPolicy.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Features/ServerTrustEvaluation.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Features/URLEncodedFormEncoder.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/Features/Validation.swift
create mode 100644 ChatBot/Pods/Alamofire/Source/PrivacyInfo.xcprivacy
create mode 100644 ChatBot/Pods/Manifest.lock
create mode 100644 ChatBot/Pods/Pods.xcodeproj/project.pbxproj
create mode 100644 ChatBot/Pods/RxAlamofire/LICENSE.md
create mode 100644 ChatBot/Pods/RxAlamofire/README.md
create mode 100644 ChatBot/Pods/RxAlamofire/Sources/RxAlamofire/RxAlamofire.swift
create mode 100644 ChatBot/Pods/RxCocoa/LICENSE.md
create mode 100644 ChatBot/Pods/RxCocoa/Platform/DataStructures/Bag.swift
create mode 100644 ChatBot/Pods/RxCocoa/Platform/DataStructures/InfiniteSequence.swift
create mode 100644 ChatBot/Pods/RxCocoa/Platform/DataStructures/PriorityQueue.swift
create mode 100644 ChatBot/Pods/RxCocoa/Platform/DataStructures/Queue.swift
create mode 100644 ChatBot/Pods/RxCocoa/Platform/DispatchQueue+Extensions.swift
create mode 100644 ChatBot/Pods/RxCocoa/Platform/Platform.Darwin.swift
create mode 100644 ChatBot/Pods/RxCocoa/Platform/Platform.Linux.swift
create mode 100644 ChatBot/Pods/RxCocoa/Platform/RecursiveLock.swift
create mode 100644 ChatBot/Pods/RxCocoa/README.md
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Common/ControlTarget.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Common/DelegateProxy.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Common/DelegateProxyType.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Common/Infallible+Bind.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Common/Observable+Bind.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Common/RxCocoaObjCRuntimeError+Extensions.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Common/RxTarget.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Common/SectionedViewDataSourceType.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Common/TextInput.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Foundation/KVORepresentable+CoreGraphics.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Foundation/KVORepresentable+Swift.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Foundation/KVORepresentable.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Foundation/NSObject+Rx+KVORepresentable.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Foundation/NSObject+Rx+RawRepresentable.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Foundation/NSObject+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Foundation/NotificationCenter+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Foundation/URLSession+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Runtime/_RX.m
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Runtime/_RXDelegateProxy.m
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Runtime/_RXKVOObserver.m
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Runtime/_RXObjCRuntime.m
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Runtime/include/RxCocoaRuntime.h
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Runtime/include/_RX.h
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Runtime/include/_RXDelegateProxy.h
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Runtime/include/_RXKVOObserver.h
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Runtime/include/_RXObjCRuntime.h
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/RxCocoa.h
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/RxCocoa.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Traits/ControlEvent.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Traits/ControlProperty.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Traits/Driver/BehaviorRelay+Driver.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Traits/Driver/ControlEvent+Driver.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Traits/Driver/ControlProperty+Driver.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Traits/Driver/Driver+Subscription.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Traits/Driver/Driver.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Traits/Driver/ObservableConvertibleType+Driver.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Traits/SharedSequence/ObservableConvertibleType+SharedSequence.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Traits/SharedSequence/SchedulerType+SharedSequence.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Traits/SharedSequence/SharedSequence+Concurrency.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Traits/SharedSequence/SharedSequence+Operators+arity.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Traits/SharedSequence/SharedSequence+Operators.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Traits/SharedSequence/SharedSequence.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Traits/Signal/ControlEvent+Signal.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Traits/Signal/ObservableConvertibleType+Signal.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Traits/Signal/PublishRelay+Signal.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Traits/Signal/Signal+Subscription.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/Traits/Signal/Signal.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/DataSources/RxCollectionViewReactiveArrayDataSource.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/DataSources/RxPickerViewAdapter.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/DataSources/RxTableViewReactiveArrayDataSource.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/Events/ItemEvents.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/NSTextStorage+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/Protocols/RxCollectionViewDataSourceType.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/Protocols/RxPickerViewDataSourceType.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/Protocols/RxTableViewDataSourceType.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/Proxies/RxCollectionViewDataSourcePrefetchingProxy.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/Proxies/RxCollectionViewDataSourceProxy.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/Proxies/RxCollectionViewDelegateProxy.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/Proxies/RxNavigationControllerDelegateProxy.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/Proxies/RxPickerViewDataSourceProxy.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/Proxies/RxPickerViewDelegateProxy.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/Proxies/RxScrollViewDelegateProxy.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/Proxies/RxSearchBarDelegateProxy.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/Proxies/RxSearchControllerDelegateProxy.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/Proxies/RxTabBarControllerDelegateProxy.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/Proxies/RxTabBarDelegateProxy.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/Proxies/RxTableViewDataSourcePrefetchingProxy.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/Proxies/RxTableViewDataSourceProxy.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/Proxies/RxTableViewDelegateProxy.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/Proxies/RxTextStorageDelegateProxy.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/Proxies/RxTextViewDelegateProxy.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/Proxies/RxWKNavigationDelegateProxy.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/UIActivityIndicatorView+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/UIApplication+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/UIBarButtonItem+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/UIButton+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/UICollectionView+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/UIControl+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/UIDatePicker+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/UIGestureRecognizer+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/UINavigationController+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/UIPickerView+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/UIRefreshControl+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/UIScrollView+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/UISearchBar+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/UISearchController+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/UISegmentedControl+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/UISlider+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/UIStepper+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/UISwitch+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/UITabBar+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/UITabBarController+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/UITableView+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/UITextField+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/UITextView+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/iOS/WKWebView+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/macOS/NSButton+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/macOS/NSControl+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/macOS/NSSlider+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/macOS/NSTextField+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/macOS/NSTextView+Rx.swift
create mode 100644 ChatBot/Pods/RxCocoa/RxCocoa/macOS/NSView+Rx.swift
create mode 100644 ChatBot/Pods/RxRelay/LICENSE.md
create mode 100644 ChatBot/Pods/RxRelay/README.md
create mode 100644 ChatBot/Pods/RxRelay/RxRelay/BehaviorRelay.swift
create mode 100644 ChatBot/Pods/RxRelay/RxRelay/Observable+Bind.swift
create mode 100644 ChatBot/Pods/RxRelay/RxRelay/PublishRelay.swift
create mode 100644 ChatBot/Pods/RxRelay/RxRelay/ReplayRelay.swift
create mode 100644 ChatBot/Pods/RxRelay/RxRelay/Utils.swift
create mode 100644 ChatBot/Pods/RxSwift/LICENSE.md
create mode 100644 ChatBot/Pods/RxSwift/Platform/AtomicInt.swift
create mode 100644 ChatBot/Pods/RxSwift/Platform/DataStructures/Bag.swift
create mode 100644 ChatBot/Pods/RxSwift/Platform/DataStructures/InfiniteSequence.swift
create mode 100644 ChatBot/Pods/RxSwift/Platform/DataStructures/PriorityQueue.swift
create mode 100644 ChatBot/Pods/RxSwift/Platform/DataStructures/Queue.swift
create mode 100644 ChatBot/Pods/RxSwift/Platform/DispatchQueue+Extensions.swift
create mode 100644 ChatBot/Pods/RxSwift/Platform/Platform.Darwin.swift
create mode 100644 ChatBot/Pods/RxSwift/Platform/Platform.Linux.swift
create mode 100644 ChatBot/Pods/RxSwift/Platform/RecursiveLock.swift
create mode 100644 ChatBot/Pods/RxSwift/README.md
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/AnyObserver.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Binder.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Cancelable.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Concurrency/AsyncLock.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Concurrency/Lock.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Concurrency/LockOwnerType.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Concurrency/SynchronizedDisposeType.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Concurrency/SynchronizedOnType.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Concurrency/SynchronizedUnsubscribeType.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/ConnectableObservableType.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Date+Dispatch.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Disposable.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Disposables/AnonymousDisposable.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Disposables/BinaryDisposable.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Disposables/BooleanDisposable.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Disposables/CompositeDisposable.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Disposables/Disposables.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Disposables/DisposeBag.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Disposables/DisposeBase.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Disposables/NopDisposable.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Disposables/RefCountDisposable.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Disposables/ScheduledDisposable.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Disposables/SerialDisposable.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Disposables/SingleAssignmentDisposable.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Disposables/SubscriptionDisposable.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Errors.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Event.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Extensions/Bag+Rx.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/GroupedObservable.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/ImmediateSchedulerType.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observable+Concurrency.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observable.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/ObservableConvertibleType.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/ObservableType+Extensions.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/ObservableType.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/AddRef.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Amb.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/AsMaybe.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/AsSingle.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Buffer.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Catch.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/CombineLatest+Collection.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/CombineLatest+arity.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/CombineLatest.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/CompactMap.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Concat.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Create.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Debounce.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Debug.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Decode.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/DefaultIfEmpty.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Deferred.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Delay.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/DelaySubscription.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Dematerialize.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/DistinctUntilChanged.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Do.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/ElementAt.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Empty.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Enumerated.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Error.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Filter.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/First.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Generate.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/GroupBy.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Just.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Map.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Materialize.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Merge.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Multicast.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Never.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/ObserveOn.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Optional.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Producer.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Range.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Reduce.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Repeat.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/RetryWhen.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Sample.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Scan.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Sequence.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/ShareReplayScope.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/SingleAsync.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Sink.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Skip.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/SkipUntil.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/SkipWhile.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/StartWith.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/SubscribeOn.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Switch.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/SwitchIfEmpty.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Take.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/TakeLast.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/TakeWithPredicate.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Throttle.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Timeout.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Timer.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/ToArray.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Using.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Window.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/WithLatestFrom.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/WithUnretained.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Zip+Collection.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Zip+arity.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observables/Zip.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/ObserverType.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observers/AnonymousObserver.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observers/ObserverBase.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Observers/TailRecursiveSink.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Reactive.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Rx.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/RxMutableBox.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/SchedulerType.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Schedulers/ConcurrentDispatchQueueScheduler.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Schedulers/ConcurrentMainScheduler.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Schedulers/CurrentThreadScheduler.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Schedulers/HistoricalScheduler.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Schedulers/HistoricalSchedulerTimeConverter.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Schedulers/Internal/DispatchQueueConfiguration.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Schedulers/Internal/InvocableScheduledItem.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Schedulers/Internal/InvocableType.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Schedulers/Internal/ScheduledItem.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Schedulers/Internal/ScheduledItemType.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Schedulers/MainScheduler.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Schedulers/OperationQueueScheduler.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Schedulers/RecursiveScheduler.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Schedulers/SchedulerServices+Emulation.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Schedulers/SerialDispatchQueueScheduler.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Schedulers/VirtualTimeConverterType.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Schedulers/VirtualTimeScheduler.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Subjects/AsyncSubject.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Subjects/BehaviorSubject.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Subjects/PublishSubject.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Subjects/ReplaySubject.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Subjects/SubjectType.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/SwiftSupport/SwiftSupport.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Traits/Infallible/Infallible+CombineLatest+arity.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Traits/Infallible/Infallible+Concurrency.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Traits/Infallible/Infallible+Create.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Traits/Infallible/Infallible+Operators.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Traits/Infallible/Infallible+Zip+arity.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Traits/Infallible/Infallible.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Traits/Infallible/ObservableConvertibleType+Infallible.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Traits/PrimitiveSequence/Completable+AndThen.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Traits/PrimitiveSequence/Completable.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Traits/PrimitiveSequence/Maybe.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Traits/PrimitiveSequence/ObservableType+PrimitiveSequence.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Traits/PrimitiveSequence/PrimitiveSequence+Concurrency.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Traits/PrimitiveSequence/PrimitiveSequence+Zip+arity.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Traits/PrimitiveSequence/PrimitiveSequence.swift
create mode 100644 ChatBot/Pods/RxSwift/RxSwift/Traits/PrimitiveSequence/Single.swift
create mode 100644 ChatBot/Pods/SnapKit/LICENSE
create mode 100644 ChatBot/Pods/SnapKit/README.md
create mode 100644 ChatBot/Pods/SnapKit/Sources/Constraint.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintAttributes.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintConfig.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintConstantTarget.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintDSL.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintDescription.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintDirectionalInsetTarget.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintDirectionalInsets.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintInsetTarget.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintInsets.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintItem.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintLayoutGuide+Extensions.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintLayoutGuide.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintLayoutGuideDSL.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintLayoutSupport.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintLayoutSupportDSL.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintMaker.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintMakerEditable.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintMakerExtendable.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintMakerFinalizable.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintMakerPrioritizable.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintMakerRelatable+Extensions.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintMakerRelatable.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintMultiplierTarget.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintOffsetTarget.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintPriority.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintPriorityTarget.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintRelatableTarget.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintRelation.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintView+Extensions.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintView.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/ConstraintViewDSL.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/Debugging.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/LayoutConstraint.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/LayoutConstraintItem.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/PrivacyInfo.xcprivacy
create mode 100644 ChatBot/Pods/SnapKit/Sources/Typealiases.swift
create mode 100644 ChatBot/Pods/SnapKit/Sources/UILayoutSupport+Extensions.swift
create mode 100644 ChatBot/Pods/Target Support Files/Alamofire/Alamofire-Info.plist
create mode 100644 ChatBot/Pods/Target Support Files/Alamofire/Alamofire-dummy.m
create mode 100644 ChatBot/Pods/Target Support Files/Alamofire/Alamofire-prefix.pch
create mode 100644 ChatBot/Pods/Target Support Files/Alamofire/Alamofire-umbrella.h
create mode 100644 ChatBot/Pods/Target Support Files/Alamofire/Alamofire.debug.xcconfig
create mode 100644 ChatBot/Pods/Target Support Files/Alamofire/Alamofire.modulemap
create mode 100644 ChatBot/Pods/Target Support Files/Alamofire/Alamofire.release.xcconfig
create mode 100644 ChatBot/Pods/Target Support Files/Alamofire/ResourceBundle-Alamofire-Alamofire-Info.plist
create mode 100644 ChatBot/Pods/Target Support Files/Pods-ChatBot/Pods-ChatBot-Info.plist
create mode 100644 ChatBot/Pods/Target Support Files/Pods-ChatBot/Pods-ChatBot-acknowledgements.markdown
create mode 100644 ChatBot/Pods/Target Support Files/Pods-ChatBot/Pods-ChatBot-acknowledgements.plist
create mode 100644 ChatBot/Pods/Target Support Files/Pods-ChatBot/Pods-ChatBot-dummy.m
create mode 100644 ChatBot/Pods/Target Support Files/Pods-ChatBot/Pods-ChatBot-frameworks-Debug-input-files.xcfilelist
create mode 100644 ChatBot/Pods/Target Support Files/Pods-ChatBot/Pods-ChatBot-frameworks-Debug-output-files.xcfilelist
create mode 100644 ChatBot/Pods/Target Support Files/Pods-ChatBot/Pods-ChatBot-frameworks-Release-input-files.xcfilelist
create mode 100644 ChatBot/Pods/Target Support Files/Pods-ChatBot/Pods-ChatBot-frameworks-Release-output-files.xcfilelist
create mode 100755 ChatBot/Pods/Target Support Files/Pods-ChatBot/Pods-ChatBot-frameworks.sh
create mode 100644 ChatBot/Pods/Target Support Files/Pods-ChatBot/Pods-ChatBot-umbrella.h
create mode 100644 ChatBot/Pods/Target Support Files/Pods-ChatBot/Pods-ChatBot.debug.xcconfig
create mode 100644 ChatBot/Pods/Target Support Files/Pods-ChatBot/Pods-ChatBot.modulemap
create mode 100644 ChatBot/Pods/Target Support Files/Pods-ChatBot/Pods-ChatBot.release.xcconfig
create mode 100644 ChatBot/Pods/Target Support Files/RxAlamofire/RxAlamofire-Info.plist
create mode 100644 ChatBot/Pods/Target Support Files/RxAlamofire/RxAlamofire-dummy.m
create mode 100644 ChatBot/Pods/Target Support Files/RxAlamofire/RxAlamofire-prefix.pch
create mode 100644 ChatBot/Pods/Target Support Files/RxAlamofire/RxAlamofire-umbrella.h
create mode 100644 ChatBot/Pods/Target Support Files/RxAlamofire/RxAlamofire.debug.xcconfig
create mode 100644 ChatBot/Pods/Target Support Files/RxAlamofire/RxAlamofire.modulemap
create mode 100644 ChatBot/Pods/Target Support Files/RxAlamofire/RxAlamofire.release.xcconfig
create mode 100644 ChatBot/Pods/Target Support Files/RxCocoa/RxCocoa-Info.plist
create mode 100644 ChatBot/Pods/Target Support Files/RxCocoa/RxCocoa-dummy.m
create mode 100644 ChatBot/Pods/Target Support Files/RxCocoa/RxCocoa-prefix.pch
create mode 100644 ChatBot/Pods/Target Support Files/RxCocoa/RxCocoa-umbrella.h
create mode 100644 ChatBot/Pods/Target Support Files/RxCocoa/RxCocoa.debug.xcconfig
create mode 100644 ChatBot/Pods/Target Support Files/RxCocoa/RxCocoa.modulemap
create mode 100644 ChatBot/Pods/Target Support Files/RxCocoa/RxCocoa.release.xcconfig
create mode 100644 ChatBot/Pods/Target Support Files/RxRelay/RxRelay-Info.plist
create mode 100644 ChatBot/Pods/Target Support Files/RxRelay/RxRelay-dummy.m
create mode 100644 ChatBot/Pods/Target Support Files/RxRelay/RxRelay-prefix.pch
create mode 100644 ChatBot/Pods/Target Support Files/RxRelay/RxRelay-umbrella.h
create mode 100644 ChatBot/Pods/Target Support Files/RxRelay/RxRelay.debug.xcconfig
create mode 100644 ChatBot/Pods/Target Support Files/RxRelay/RxRelay.modulemap
create mode 100644 ChatBot/Pods/Target Support Files/RxRelay/RxRelay.release.xcconfig
create mode 100644 ChatBot/Pods/Target Support Files/RxSwift/RxSwift-Info.plist
create mode 100644 ChatBot/Pods/Target Support Files/RxSwift/RxSwift-dummy.m
create mode 100644 ChatBot/Pods/Target Support Files/RxSwift/RxSwift-prefix.pch
create mode 100644 ChatBot/Pods/Target Support Files/RxSwift/RxSwift-umbrella.h
create mode 100644 ChatBot/Pods/Target Support Files/RxSwift/RxSwift.debug.xcconfig
create mode 100644 ChatBot/Pods/Target Support Files/RxSwift/RxSwift.modulemap
create mode 100644 ChatBot/Pods/Target Support Files/RxSwift/RxSwift.release.xcconfig
create mode 100644 ChatBot/Pods/Target Support Files/SnapKit/ResourceBundle-SnapKit_Privacy-SnapKit-Info.plist
create mode 100644 ChatBot/Pods/Target Support Files/SnapKit/SnapKit-Info.plist
create mode 100644 ChatBot/Pods/Target Support Files/SnapKit/SnapKit-dummy.m
create mode 100644 ChatBot/Pods/Target Support Files/SnapKit/SnapKit-prefix.pch
create mode 100644 ChatBot/Pods/Target Support Files/SnapKit/SnapKit-umbrella.h
create mode 100644 ChatBot/Pods/Target Support Files/SnapKit/SnapKit.debug.xcconfig
create mode 100644 ChatBot/Pods/Target Support Files/SnapKit/SnapKit.modulemap
create mode 100644 ChatBot/Pods/Target Support Files/SnapKit/SnapKit.release.xcconfig
create mode 100644 ChatBot/Pods/Target Support Files/Then/Then-Info.plist
create mode 100644 ChatBot/Pods/Target Support Files/Then/Then-dummy.m
create mode 100644 ChatBot/Pods/Target Support Files/Then/Then-prefix.pch
create mode 100644 ChatBot/Pods/Target Support Files/Then/Then-umbrella.h
create mode 100644 ChatBot/Pods/Target Support Files/Then/Then.debug.xcconfig
create mode 100644 ChatBot/Pods/Target Support Files/Then/Then.modulemap
create mode 100644 ChatBot/Pods/Target Support Files/Then/Then.release.xcconfig
create mode 100644 ChatBot/Pods/Then/LICENSE
create mode 100644 ChatBot/Pods/Then/README.md
create mode 100644 ChatBot/Pods/Then/Sources/Then/Then.swift
diff --git a/ChatBot/ChatBot.xcodeproj/project.pbxproj b/ChatBot/ChatBot.xcodeproj/project.pbxproj
index d80ffb50..e3fed599 100644
--- a/ChatBot/ChatBot.xcodeproj/project.pbxproj
+++ b/ChatBot/ChatBot.xcodeproj/project.pbxproj
@@ -15,10 +15,8 @@
C12E66D72BB3F28800F3F441 /* Bundle+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66BD2BB3F28800F3F441 /* Bundle+Extension.swift */; };
C12E66D92BB3F28800F3F441 /* ChatBotViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66C02BB3F28800F3F441 /* ChatBotViewController.swift */; };
C12E66DB2BB3F28800F3F441 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C12E66C32BB3F28800F3F441 /* Assets.xcassets */; };
- C12E66DD2BB3F28800F3F441 /* APIService.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66C62BB3F28800F3F441 /* APIService.swift */; };
C12E66DE2BB3F28800F3F441 /* APIType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66C72BB3F28800F3F441 /* APIType.swift */; };
C12E66DF2BB3F28800F3F441 /* HttpMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66C82BB3F28800F3F441 /* HttpMethod.swift */; };
- C12E66E02BB3F28800F3F441 /* NetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66C92BB3F28800F3F441 /* NetworkError.swift */; };
C12E66E12BB3F28800F3F441 /* NetworkURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66CA2BB3F28800F3F441 /* NetworkURL.swift */; };
C12E66E32BB3F28800F3F441 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66CD2BB3F28800F3F441 /* AppDelegate.swift */; };
C12E66E42BB3F28800F3F441 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66CE2BB3F28800F3F441 /* SceneDelegate.swift */; };
@@ -27,18 +25,15 @@
C12E66EC2BB4291A00F3F441 /* ResponseChoiceDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66EB2BB4291A00F3F441 /* ResponseChoiceDTO.swift */; };
C12E66EE2BB4294300F3F441 /* Usage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66ED2BB4294300F3F441 /* Usage.swift */; };
C12E66F02BB429AA00F3F441 /* JSONNull.swift in Sources */ = {isa = PBXBuildFile; fileRef = C12E66EF2BB429AA00F3F441 /* JSONNull.swift */; };
- C176AB4A2BBEDD97004DEA01 /* Then in Frameworks */ = {isa = PBXBuildFile; productRef = C176AB492BBEDD97004DEA01 /* Then */; };
- C176AB4D2BBEDDA5004DEA01 /* RxAlamofire in Frameworks */ = {isa = PBXBuildFile; productRef = C176AB4C2BBEDDA5004DEA01 /* RxAlamofire */; };
- C176AB502BBEDDB1004DEA01 /* SnapKit in Frameworks */ = {isa = PBXBuildFile; productRef = C176AB4F2BBEDDB1004DEA01 /* SnapKit */; };
- C176AB532BBEDDC1004DEA01 /* RxCocoa in Frameworks */ = {isa = PBXBuildFile; productRef = C176AB522BBEDDC1004DEA01 /* RxCocoa */; };
- C176AB552BBEDDC1004DEA01 /* RxSwift in Frameworks */ = {isa = PBXBuildFile; productRef = C176AB542BBEDDC1004DEA01 /* RxSwift */; };
C1865DB82BBE9C3400DD99C9 /* Network.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1865DB72BBE9C3400DD99C9 /* Network.swift */; };
C1865DBA2BBE9E8600DD99C9 /* NetworkProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1865DB92BBE9E8600DD99C9 /* NetworkProvider.swift */; };
C1865DBC2BBEB72900DD99C9 /* ChatBotNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1865DBB2BBEB72900DD99C9 /* ChatBotNetwork.swift */; };
C1E416662BB9888C00D8C836 /* UIViewController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1E416652BB9888C00D8C836 /* UIViewController+Extension.swift */; };
+ D28AA74380D6F3CE129AC66D /* Pods_ChatBot.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8913FA7C9B8C251C7E4CD5F /* Pods_ChatBot.framework */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
+ 6F46BD03BD10D03BC697E016 /* Pods-ChatBot.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChatBot.release.xcconfig"; path = "Target Support Files/Pods-ChatBot/Pods-ChatBot.release.xcconfig"; sourceTree = ""; };
9B9289212BBECF5B00185E35 /* APIToken.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = APIToken.plist; sourceTree = ""; };
B4B3E2B92B42D1BB00818B3C /* ChatBot.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ChatBot.app; sourceTree = BUILT_PRODUCTS_DIR; };
C12E66B82BB3F28800F3F441 /* ChatBotViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatBotViewModel.swift; sourceTree = ""; };
@@ -49,10 +44,8 @@
C12E66C02BB3F28800F3F441 /* ChatBotViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatBotViewController.swift; sourceTree = ""; };
C12E66C32BB3F28800F3F441 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
C12E66C42BB3F28800F3F441 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
- C12E66C62BB3F28800F3F441 /* APIService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = APIService.swift; sourceTree = ""; };
C12E66C72BB3F28800F3F441 /* APIType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = APIType.swift; sourceTree = ""; };
C12E66C82BB3F28800F3F441 /* HttpMethod.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HttpMethod.swift; sourceTree = ""; };
- C12E66C92BB3F28800F3F441 /* NetworkError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkError.swift; sourceTree = ""; };
C12E66CA2BB3F28800F3F441 /* NetworkURL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkURL.swift; sourceTree = ""; };
C12E66CD2BB3F28800F3F441 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
C12E66CE2BB3F28800F3F441 /* SceneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
@@ -65,6 +58,8 @@
C1865DB92BBE9E8600DD99C9 /* NetworkProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProvider.swift; sourceTree = ""; };
C1865DBB2BBEB72900DD99C9 /* ChatBotNetwork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatBotNetwork.swift; sourceTree = ""; };
C1E416652BB9888C00D8C836 /* UIViewController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Extension.swift"; sourceTree = ""; };
+ EF8D881E2721E9C8810C312E /* Pods-ChatBot.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChatBot.debug.xcconfig"; path = "Target Support Files/Pods-ChatBot/Pods-ChatBot.debug.xcconfig"; sourceTree = ""; };
+ F8913FA7C9B8C251C7E4CD5F /* Pods_ChatBot.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ChatBot.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -72,22 +67,37 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- C176AB502BBEDDB1004DEA01 /* SnapKit in Frameworks */,
- C176AB4A2BBEDD97004DEA01 /* Then in Frameworks */,
- C176AB552BBEDDC1004DEA01 /* RxSwift in Frameworks */,
- C176AB532BBEDDC1004DEA01 /* RxCocoa in Frameworks */,
- C176AB4D2BBEDDA5004DEA01 /* RxAlamofire in Frameworks */,
+ D28AA74380D6F3CE129AC66D /* Pods_ChatBot.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
+ 82CD0E3CB81B67DDFC983DD6 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ F8913FA7C9B8C251C7E4CD5F /* Pods_ChatBot.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ 9FAE753BD9621E64B55604ED /* Pods */ = {
+ isa = PBXGroup;
+ children = (
+ EF8D881E2721E9C8810C312E /* Pods-ChatBot.debug.xcconfig */,
+ 6F46BD03BD10D03BC697E016 /* Pods-ChatBot.release.xcconfig */,
+ );
+ path = Pods;
+ sourceTree = "";
+ };
B4B3E2B02B42D1BB00818B3C = {
isa = PBXGroup;
children = (
B4B3E2BB2B42D1BB00818B3C /* ChatBot */,
B4B3E2BA2B42D1BB00818B3C /* Products */,
+ 9FAE753BD9621E64B55604ED /* Pods */,
+ 82CD0E3CB81B67DDFC983DD6 /* Frameworks */,
);
sourceTree = "";
};
@@ -153,8 +163,6 @@
C1865DB72BBE9C3400DD99C9 /* Network.swift */,
C12E66C82BB3F28800F3F441 /* HttpMethod.swift */,
C1865DBB2BBEB72900DD99C9 /* ChatBotNetwork.swift */,
- C12E66C62BB3F28800F3F441 /* APIService.swift */,
- C12E66C92BB3F28800F3F441 /* NetworkError.swift */,
C1865DB92BBE9E8600DD99C9 /* NetworkProvider.swift */,
);
path = Network;
@@ -194,22 +202,17 @@
isa = PBXNativeTarget;
buildConfigurationList = B4B3E2CD2B42D1BC00818B3C /* Build configuration list for PBXNativeTarget "ChatBot" */;
buildPhases = (
+ E671F0AE038BE9FF535377E8 /* [CP] Check Pods Manifest.lock */,
B4B3E2B52B42D1BB00818B3C /* Sources */,
B4B3E2B62B42D1BB00818B3C /* Frameworks */,
B4B3E2B72B42D1BB00818B3C /* Resources */,
+ CD92C4DE6D105F60783833F7 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = ChatBot;
- packageProductDependencies = (
- C176AB492BBEDD97004DEA01 /* Then */,
- C176AB4C2BBEDDA5004DEA01 /* RxAlamofire */,
- C176AB4F2BBEDDB1004DEA01 /* SnapKit */,
- C176AB522BBEDDC1004DEA01 /* RxCocoa */,
- C176AB542BBEDDC1004DEA01 /* RxSwift */,
- );
productName = ChatBot;
productReference = B4B3E2B92B42D1BB00818B3C /* ChatBot.app */;
productType = "com.apple.product-type.application";
@@ -238,12 +241,6 @@
Base,
);
mainGroup = B4B3E2B02B42D1BB00818B3C;
- packageReferences = (
- C176AB482BBEDD97004DEA01 /* XCRemoteSwiftPackageReference "Then" */,
- C176AB4B2BBEDDA5004DEA01 /* XCRemoteSwiftPackageReference "RxAlamofire" */,
- C176AB4E2BBEDDB1004DEA01 /* XCRemoteSwiftPackageReference "SnapKit" */,
- C176AB512BBEDDC1004DEA01 /* XCRemoteSwiftPackageReference "RxSwift" */,
- );
productRefGroup = B4B3E2BA2B42D1BB00818B3C /* Products */;
projectDirPath = "";
projectRoot = "";
@@ -266,16 +263,56 @@
};
/* End PBXResourcesBuildPhase section */
+/* Begin PBXShellScriptBuildPhase section */
+ CD92C4DE6D105F60783833F7 /* [CP] Embed Pods Frameworks */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-ChatBot/Pods-ChatBot-frameworks-${CONFIGURATION}-input-files.xcfilelist",
+ );
+ name = "[CP] Embed Pods Frameworks";
+ outputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-ChatBot/Pods-ChatBot-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ChatBot/Pods-ChatBot-frameworks.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
+ E671F0AE038BE9FF535377E8 /* [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-ChatBot-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 */
B4B3E2B52B42D1BB00818B3C /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C12E66D92BB3F28800F3F441 /* ChatBotViewController.swift in Sources */,
- C12E66E02BB3F28800F3F441 /* NetworkError.swift in Sources */,
C12E66DF2BB3F28800F3F441 /* HttpMethod.swift in Sources */,
C12E66DE2BB3F28800F3F441 /* APIType.swift in Sources */,
- C12E66DD2BB3F28800F3F441 /* APIService.swift in Sources */,
C12E66D72BB3F28800F3F441 /* Bundle+Extension.swift in Sources */,
C12E66E12BB3F28800F3F441 /* NetworkURL.swift in Sources */,
C12E66D32BB3F28800F3F441 /* ChatBotViewModel.swift in Sources */,
@@ -430,12 +467,14 @@
};
B4B3E2CE2B42D1BC00818B3C /* Debug */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = EF8D881E2721E9C8810C312E /* Pods-ChatBot.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = T92LV6HV88;
+ ENABLE_USER_SCRIPT_SANDBOXING = NO;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = ChatBot/Resource/Info.plist;
"INFOPLIST_FILE[sdk=*]" = ChatBot/Resource/Info.plist;
@@ -463,12 +502,14 @@
};
B4B3E2CF2B42D1BC00818B3C /* Release */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 6F46BD03BD10D03BC697E016 /* Pods-ChatBot.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = T92LV6HV88;
+ ENABLE_USER_SCRIPT_SANDBOXING = NO;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = ChatBot/Resource/Info.plist;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
@@ -515,69 +556,6 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
-
-/* Begin XCRemoteSwiftPackageReference section */
- C176AB482BBEDD97004DEA01 /* XCRemoteSwiftPackageReference "Then" */ = {
- isa = XCRemoteSwiftPackageReference;
- repositoryURL = "https://github.com/devxoul/Then.git";
- requirement = {
- kind = upToNextMajorVersion;
- minimumVersion = 3.0.0;
- };
- };
- C176AB4B2BBEDDA5004DEA01 /* XCRemoteSwiftPackageReference "RxAlamofire" */ = {
- isa = XCRemoteSwiftPackageReference;
- repositoryURL = "https://github.com/RxSwiftCommunity/RxAlamofire.git";
- requirement = {
- kind = upToNextMajorVersion;
- minimumVersion = 5.2.0;
- };
- };
- C176AB4E2BBEDDB1004DEA01 /* XCRemoteSwiftPackageReference "SnapKit" */ = {
- isa = XCRemoteSwiftPackageReference;
- repositoryURL = "https://github.com/SnapKit/SnapKit.git";
- requirement = {
- kind = upToNextMajorVersion;
- minimumVersion = 5.7.1;
- };
- };
- C176AB512BBEDDC1004DEA01 /* XCRemoteSwiftPackageReference "RxSwift" */ = {
- isa = XCRemoteSwiftPackageReference;
- repositoryURL = "https://github.com/ReactiveX/RxSwift.git";
- requirement = {
- kind = upToNextMajorVersion;
- minimumVersion = 6.6.0;
- };
- };
-/* End XCRemoteSwiftPackageReference section */
-
-/* Begin XCSwiftPackageProductDependency section */
- C176AB492BBEDD97004DEA01 /* Then */ = {
- isa = XCSwiftPackageProductDependency;
- package = C176AB482BBEDD97004DEA01 /* XCRemoteSwiftPackageReference "Then" */;
- productName = Then;
- };
- C176AB4C2BBEDDA5004DEA01 /* RxAlamofire */ = {
- isa = XCSwiftPackageProductDependency;
- package = C176AB4B2BBEDDA5004DEA01 /* XCRemoteSwiftPackageReference "RxAlamofire" */;
- productName = RxAlamofire;
- };
- C176AB4F2BBEDDB1004DEA01 /* SnapKit */ = {
- isa = XCSwiftPackageProductDependency;
- package = C176AB4E2BBEDDB1004DEA01 /* XCRemoteSwiftPackageReference "SnapKit" */;
- productName = SnapKit;
- };
- C176AB522BBEDDC1004DEA01 /* RxCocoa */ = {
- isa = XCSwiftPackageProductDependency;
- package = C176AB512BBEDDC1004DEA01 /* XCRemoteSwiftPackageReference "RxSwift" */;
- productName = RxCocoa;
- };
- C176AB542BBEDDC1004DEA01 /* RxSwift */ = {
- isa = XCSwiftPackageProductDependency;
- package = C176AB512BBEDDC1004DEA01 /* XCRemoteSwiftPackageReference "RxSwift" */;
- productName = RxSwift;
- };
-/* End XCSwiftPackageProductDependency section */
};
rootObject = B4B3E2B12B42D1BB00818B3C /* Project object */;
}
diff --git a/ChatBot/ChatBot.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ChatBot/ChatBot.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
deleted file mode 100644
index 1141d972..00000000
--- a/ChatBot/ChatBot.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ /dev/null
@@ -1,60 +0,0 @@
-{
- "originHash" : "4f59d014461f30b3b54708c61616f21472f63b7383d229842af8de6b8dc507d8",
- "pins" : [
- {
- "identity" : "alamofire",
- "kind" : "remoteSourceControl",
- "location" : "https://github.com/Alamofire/Alamofire.git",
- "state" : {
- "revision" : "f455c2975872ccd2d9c81594c658af65716e9b9a",
- "version" : "5.9.1"
- }
- },
- {
- "identity" : "ohhttpstubs",
- "kind" : "remoteSourceControl",
- "location" : "https://github.com/AliSoftware/OHHTTPStubs.git",
- "state" : {
- "revision" : "12f19662426d0434d6c330c6974d53e2eb10ecd9",
- "version" : "9.1.0"
- }
- },
- {
- "identity" : "rxalamofire",
- "kind" : "remoteSourceControl",
- "location" : "https://github.com/RxSwiftCommunity/RxAlamofire.git",
- "state" : {
- "revision" : "16858a7955ff8bc3caa51212fd7624f168586773",
- "version" : "5.7.1"
- }
- },
- {
- "identity" : "rxswift",
- "kind" : "remoteSourceControl",
- "location" : "https://github.com/ReactiveX/RxSwift.git",
- "state" : {
- "revision" : "cec68169a048a079f461ba203fe85636548d7a89",
- "version" : "5.1.3"
- }
- },
- {
- "identity" : "snapkit",
- "kind" : "remoteSourceControl",
- "location" : "https://github.com/SnapKit/SnapKit.git",
- "state" : {
- "revision" : "2842e6e84e82eb9a8dac0100ca90d9444b0307f4",
- "version" : "5.7.1"
- }
- },
- {
- "identity" : "then",
- "kind" : "remoteSourceControl",
- "location" : "https://github.com/devxoul/Then.git",
- "state" : {
- "revision" : "d41ef523faef0f911369f79c0b96815d9dbb6d7a",
- "version" : "3.0.0"
- }
- }
- ],
- "version" : 3
-}
diff --git a/ChatBot/ChatBot.xcworkspace/contents.xcworkspacedata b/ChatBot/ChatBot.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 00000000..f1bd9fb7
--- /dev/null
+++ b/ChatBot/ChatBot.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/ChatBot/ChatBot.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ChatBot/ChatBot.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 00000000..18d98100
--- /dev/null
+++ b/ChatBot/ChatBot.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/ChatBot/ChatBot/Model/RequestChatDTO.swift b/ChatBot/ChatBot/Model/RequestChatDTO.swift
index de369565..a511a44d 100644
--- a/ChatBot/ChatBot/Model/RequestChatDTO.swift
+++ b/ChatBot/ChatBot/Model/RequestChatDTO.swift
@@ -8,7 +8,7 @@
import Foundation
struct RequestChatDTO: Encodable {
- let model: String = "gpt-3.5-turbo-1106"
+ let model: String = "gpt-3.5-turbo-1106ss"
let stream: Bool = false
var messages: [Message]
}
diff --git a/ChatBot/ChatBot/Network/APIService.swift b/ChatBot/ChatBot/Network/APIService.swift
deleted file mode 100644
index b26d9475..00000000
--- a/ChatBot/ChatBot/Network/APIService.swift
+++ /dev/null
@@ -1,50 +0,0 @@
-//
-// APIService.swift
-// ChatBot
-//
-// Created by LeeSeongYeon on 3/26/24.
-//
-
-import Foundation
-
-//struct APIService {
-// typealias APIResult = (Result)
-// let session: URLSession
-// init() {
-// self.session = URLSession.shared
-// }
-//
-// func fetchData(with urlRequest: URLRequest) async throws -> APIResult {
-// let (data, response) = try await session.data(for: urlRequest)
-// return handleDataTaskCompletion(data: data, response: response)
-// }
-//}
-//
-//private extension APIService {
-// func handleDataTaskCompletion(data: Data?, response: URLResponse?) -> APIResult {
-// guard
-// let httpResponse = response as? HTTPURLResponse
-// else {
-// return .failure(.invalidResponseError)
-// }
-// return self.handleHTTPResponse(data: data, httpResponse: httpResponse)
-// }
-//
-// func handleHTTPResponse(data: Data?, httpResponse: HTTPURLResponse) -> APIResult {
-// guard
-// let data = data
-// else {
-// return .failure(.noDataError)
-// }
-// switch httpResponse.statusCode {
-// case 300..<400:
-// return .failure(.redirectionError)
-// case 400..<500:
-// return .failure(.clientError)
-// case 500..<600:
-// return .failure(.serverError)
-// default:
-// return .success(data)
-// }
-// }
-//}
diff --git a/ChatBot/ChatBot/Network/Network.swift b/ChatBot/ChatBot/Network/Network.swift
index 06a31c75..98389be6 100644
--- a/ChatBot/ChatBot/Network/Network.swift
+++ b/ChatBot/ChatBot/Network/Network.swift
@@ -19,7 +19,7 @@ class Network {
func fetchData(message: Message) -> Observable {
let urlRequest = NetworkURL.makeURLRequest(type: .chatGPT, chat: RequestChatDTO(messages: [message]), httpMethod: .post)!
let result = RxAlamofire.requestData(urlRequest)
- .observeOn(queue)
+ .observe(on: queue)
.debug()
.map { (response, data) -> T in
return try JSONDecoder().decode(T.self, from: data)
diff --git a/ChatBot/ChatBot/Network/NetworkError.swift b/ChatBot/ChatBot/Network/NetworkError.swift
deleted file mode 100644
index 49c7c809..00000000
--- a/ChatBot/ChatBot/Network/NetworkError.swift
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// NetworkError.swift
-// ChatBot
-//
-// Created by LeeSeongYeon on 3/26/24.
-//
-
-import Foundation
-
-enum NetworkError: LocalizedError {
- case invalidURLError
- case invalidURLRequestError
- case noDataError
- case requestFailError
- case invalidResponseError
- case redirectionError
- case clientError
- case serverError
- case decodingError
-
- var errorDescription: String? {
- switch self {
- case .invalidURLError:
- return "잘못된 URL 주소입니다."
- case .invalidURLRequestError:
- return "잘못된 URL 요청입니다."
- case .noDataError:
- return "데이터가 존재하지 않습니다."
- case .requestFailError:
- return "요청에 실패 했습니다."
- case .invalidResponseError:
- return "잘못된 요청 입니다."
- case .redirectionError:
- return "리다이렉션 에러 발생"
- case .clientError:
- return "사용자 요청 에러 발생"
- case .serverError:
- return "서버 에러 발생"
- case .decodingError:
- return "JSON 디코딩 에러 발생"
- }
- }
-}
diff --git a/ChatBot/ChatBot/View/ChatBotViewController.swift b/ChatBot/ChatBot/View/ChatBotViewController.swift
index 818e689b..10557d7c 100644
--- a/ChatBot/ChatBot/View/ChatBotViewController.swift
+++ b/ChatBot/ChatBot/View/ChatBotViewController.swift
@@ -9,12 +9,14 @@ import UIKit
import Then
import SnapKit
import RxSwift
+import RxCocoa
class ChatBotViewController: UIViewController {
let button = UIButton().then {
$0.setTitle("이거", for: .normal)
$0.setTitleColor(.red, for: .normal)
}
+
private let chatBotViewModel: ChatBotViewModel
let disposeBag = DisposeBag()
let chatTrigger = PublishSubject()
@@ -51,15 +53,20 @@ private extension ChatBotViewController {
func bindViewModel() {
let input = ChatBotViewModel.Input(chatTigger: chatTrigger)
+
let output = chatBotViewModel.transform(input: input)
- output.resultChat.bind { result in
+ output.resultChat
+ .observe(on: MainScheduler.instance)
+ .bind { result in
switch result {
- case .success(let chat):
- print(chat)
+ case .success(let data):
+ print("RESULT === \(data)")
case .failure(let error):
- print(error)
+ let okAction = UIAlertAction(title: "확인", style: .default)
+ self.showMessageAlert(message: "\(error.localizedDescription)", action: [okAction])
}
- }.disposed(by: disposeBag)
+ }
+ .disposed(by: disposeBag)
}
func bindView() {
diff --git a/ChatBot/ChatBot/ViewModel/ChatBotViewModel.swift b/ChatBot/ChatBot/ViewModel/ChatBotViewModel.swift
index 3269b913..1ad48cd4 100644
--- a/ChatBot/ChatBot/ViewModel/ChatBotViewModel.swift
+++ b/ChatBot/ChatBot/ViewModel/ChatBotViewModel.swift
@@ -7,6 +7,7 @@
import Foundation
import RxSwift
+import RxCocoa
final class ChatBotViewModel {
private let chatRepository: ChatRepository
@@ -26,6 +27,9 @@ final class ChatBotViewModel {
func transform(input: Input) -> Output {
let resultChat = input.chatTigger.flatMapLatest { [unowned self] message -> Observable> in
return self.chatRepository.requestChatResultData(message: message)
+ .map { return .success($0) }
+ }.catch { error in
+ return Observable.just(.failure(error))
}
return Output(resultChat: resultChat)
}
diff --git a/ChatBot/ChatBot/ViewModel/ChatRepository.swift b/ChatBot/ChatBot/ViewModel/ChatRepository.swift
index be86cbc1..beb8f083 100644
--- a/ChatBot/ChatBot/ViewModel/ChatRepository.swift
+++ b/ChatBot/ChatBot/ViewModel/ChatRepository.swift
@@ -15,12 +15,9 @@ struct ChatRepository {
self.chatBotNetwork = provider.makeChatNetwork()
}
- func requestChatResultData(message: Message)-> Observable> {
+ func requestChatResultData(message: Message) -> Observable {
self.chatBotNetwork.requestChatBotMessage(message: message).map {
- return .success($0)
- }
- .catchError { error in
- return Observable.just(.failure(error))
- }
+ return $0
+ }
}
}
diff --git a/ChatBot/Podfile b/ChatBot/Podfile
new file mode 100644
index 00000000..942af9a0
--- /dev/null
+++ b/ChatBot/Podfile
@@ -0,0 +1,14 @@
+# Uncomment the next line to define a global platform for your project
+# platform :ios, '9.0'
+
+target 'ChatBot' do
+ # Comment the next line if you don't want to use dynamic frameworks
+ use_frameworks!
+pod 'RxSwift', '~> 6.5.0'
+pod 'RxCocoa', '~> 6.5.0'
+pod 'RxAlamofire'
+pod 'SnapKit', '~> 5.7.0'
+pod 'Then'
+ # Pods for ChatBot
+
+end
diff --git a/ChatBot/Podfile.lock b/ChatBot/Podfile.lock
new file mode 100644
index 00000000..7f3fbab7
--- /dev/null
+++ b/ChatBot/Podfile.lock
@@ -0,0 +1,45 @@
+PODS:
+ - Alamofire (5.9.1)
+ - RxAlamofire (6.1.1):
+ - RxAlamofire/Core (= 6.1.1)
+ - RxAlamofire/Core (6.1.1):
+ - Alamofire (~> 5.4)
+ - RxSwift (~> 6.0)
+ - RxCocoa (6.5.0):
+ - RxRelay (= 6.5.0)
+ - RxSwift (= 6.5.0)
+ - RxRelay (6.5.0):
+ - RxSwift (= 6.5.0)
+ - RxSwift (6.5.0)
+ - SnapKit (5.7.1)
+ - Then (3.0.0)
+
+DEPENDENCIES:
+ - RxAlamofire
+ - RxCocoa (~> 6.5.0)
+ - RxSwift (~> 6.5.0)
+ - SnapKit (~> 5.7.0)
+ - Then
+
+SPEC REPOS:
+ trunk:
+ - Alamofire
+ - RxAlamofire
+ - RxCocoa
+ - RxRelay
+ - RxSwift
+ - SnapKit
+ - Then
+
+SPEC CHECKSUMS:
+ Alamofire: f36a35757af4587d8e4f4bfa223ad10be2422b8c
+ RxAlamofire: beb75a1c452d0de225651db4903f5d29d034a620
+ RxCocoa: 94f817b71c07517321eb4f9ad299112ca8af743b
+ RxRelay: 1de1523e604c72b6c68feadedd1af3b1b4d0ecbd
+ RxSwift: 5710a9e6b17f3c3d6e40d6e559b9fa1e813b2ef8
+ SnapKit: d612e99e678a2d3b95bf60b0705ed0a35c03484a
+ Then: 844265ae87834bbe1147d91d5d41a404da2ec27d
+
+PODFILE CHECKSUM: 7e0d07ea5c428039c896d73e099e3982d8244715
+
+COCOAPODS: 1.14.3
diff --git a/ChatBot/Pods/Alamofire/LICENSE b/ChatBot/Pods/Alamofire/LICENSE
new file mode 100644
index 00000000..cae030a0
--- /dev/null
+++ b/ChatBot/Pods/Alamofire/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2014-2022 Alamofire Software Foundation (http://alamofire.org/)
+
+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.
diff --git a/ChatBot/Pods/Alamofire/README.md b/ChatBot/Pods/Alamofire/README.md
new file mode 100644
index 00000000..3a454ab1
--- /dev/null
+++ b/ChatBot/Pods/Alamofire/README.md
@@ -0,0 +1,269 @@
+
+
+[](https://img.shields.io/badge/Swift-5.7_5.8_5.9-Orange?style=flat-square)
+[](https://img.shields.io/badge/Platforms-macOS_iOS_tvOS_watchOS_vision_OS_Linux_Windows_Android-Green?style=flat-square)
+[](https://img.shields.io/cocoapods/v/Alamofire.svg)
+[](https://github.com/Carthage/Carthage)
+[](https://img.shields.io/badge/Swift_Package_Manager-compatible-orange?style=flat-square)
+[](https://forums.swift.org/c/related-projects/alamofire/37)
+
+Alamofire is an HTTP networking library written in Swift.
+
+- [Features](#features)
+- [Component Libraries](#component-libraries)
+- [Requirements](#requirements)
+- [Migration Guides](#migration-guides)
+- [Communication](#communication)
+- [Installation](#installation)
+- [Contributing](#contributing)
+- [Usage](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#using-alamofire)
+ - [**Introduction -**](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#introduction) [Making Requests](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#making-requests), [Response Handling](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#response-handling), [Response Validation](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#response-validation), [Response Caching](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#response-caching)
+ - **HTTP -** [HTTP Methods](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#http-methods), [Parameters and Parameter Encoder](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md##request-parameters-and-parameter-encoders), [HTTP Headers](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#http-headers), [Authentication](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#authentication)
+ - **Large Data -** [Downloading Data to a File](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#downloading-data-to-a-file), [Uploading Data to a Server](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#uploading-data-to-a-server)
+ - **Tools -** [Statistical Metrics](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#statistical-metrics), [cURL Command Output](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#curl-command-output)
+- [Advanced Usage](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md)
+ - **URL Session -** [Session Manager](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#session), [Session Delegate](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#sessiondelegate), [Request](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#request)
+ - **Routing -** [Routing Requests](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#routing-requests), [Adapting and Retrying Requests](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#adapting-and-retrying-requests-with-requestinterceptor)
+ - **Model Objects -** [Custom Response Handlers](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#customizing-response-handlers)
+ - **Advanced Concurrency -** [Swift Concurrency](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#using-alamofire-with-swift-concurrency) and [Combine](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#using-alamofire-with-combine)
+ - **Connection -** [Security](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#security), [Network Reachability](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#network-reachability)
+- [Open Radars](#open-radars)
+- [FAQ](#faq)
+- [Credits](#credits)
+- [Donations](#donations)
+- [License](#license)
+
+## Features
+
+- [x] Chainable Request / Response Methods
+- [x] Swift Concurrency Support Back to iOS 13, macOS 10.15, tvOS 13, and watchOS 6.
+- [x] Combine Support
+- [x] URL / JSON Parameter Encoding
+- [x] Upload File / Data / Stream / MultipartFormData
+- [x] Download File using Request or Resume Data
+- [x] Authentication with `URLCredential`
+- [x] HTTP Response Validation
+- [x] Upload and Download Progress Closures with Progress
+- [x] cURL Command Output
+- [x] Dynamically Adapt and Retry Requests
+- [x] TLS Certificate and Public Key Pinning
+- [x] Network Reachability
+- [x] Comprehensive Unit and Integration Test Coverage
+- [x] [Complete Documentation](https://alamofire.github.io/Alamofire)
+
+## Write Requests Fast!
+
+Alamofire's compact syntax and extensive feature set allow requests with powerful features like automatic retry to be written in just a few lines of code.
+
+```swift
+// Automatic String to URL conversion, Swift concurrency support, and automatic retry.
+let response = await AF.request("https://httpbin.org/get", interceptor: .retryPolicy)
+ // Automatic HTTP Basic Auth.
+ .authenticate(username: "user", password: "pass")
+ // Caching customization.
+ .cacheResponse(using: .cache)
+ // Redirect customization.
+ .redirect(using: .follow)
+ // Validate response code and Content-Type.
+ .validate()
+ // Produce a cURL command for the request.
+ .cURLDescription { description in
+ print(description)
+ }
+ // Automatic Decodable support with background parsing.
+ .serializingDecodable(DecodableType.self)
+ // Await the full response with metrics and a parsed body.
+ .response
+// Detailed response description for easy debugging.
+debugPrint(response)
+```
+
+## Component Libraries
+
+In order to keep Alamofire focused specifically on core networking implementations, additional component libraries have been created by the [Alamofire Software Foundation](https://github.com/Alamofire/Foundation) to bring additional functionality to the Alamofire ecosystem.
+
+- [AlamofireImage](https://github.com/Alamofire/AlamofireImage) - An image library including image response serializers, `UIImage` and `UIImageView` extensions, custom image filters, an auto-purging in-memory cache, and a priority-based image downloading system.
+- [AlamofireNetworkActivityIndicator](https://github.com/Alamofire/AlamofireNetworkActivityIndicator) - Controls the visibility of the network activity indicator on iOS using Alamofire. It contains configurable delay timers to help mitigate flicker and can support `URLSession` instances not managed by Alamofire.
+
+## Requirements
+
+| Platform | Minimum Swift Version | Installation | Status |
+| ---------------------------------------------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------------------ |
+| iOS 10.0+ / macOS 10.12+ / tvOS 10.0+ / watchOS 3.0+ | 5.7.1 / Xcode 14.1 | [CocoaPods](#cocoapods), [Carthage](#carthage), [Swift Package Manager](#swift-package-manager), [Manual](#manually) | Fully Tested |
+| Linux | Latest Only | [Swift Package Manager](#swift-package-manager) | Building But Unsupported |
+| Windows | Latest Only | [Swift Package Manager](#swift-package-manager) | Building But Unsupported |
+| Android | Latest Only | [Swift Package Manager](#swift-package-manager) | Building But Unsupported |
+
+#### Known Issues on Linux and Windows
+
+Alamofire builds on Linux, Windows, and Android but there are missing features and many issues in the underlying `swift-corelibs-foundation` that prevent full functionality and may cause crashes. These include:
+
+- `ServerTrustManager` and associated certificate functionality is unavailable, so there is no certificate pinning and no client certificate support.
+- Various methods of HTTP authentication may crash, including HTTP Basic and HTTP Digest. Crashes may occur if responses contain server challenges.
+- Cache control through `CachedResponseHandler` and associated APIs is unavailable, as the underlying delegate methods aren't called.
+- `URLSessionTaskMetrics` are never gathered.
+- `WebSocketRequest` is not available.
+
+Due to these issues, Alamofire is unsupported on Linux, Windows, and Android. Please report any crashes to the [Swift bug reporter](https://bugs.swift.org).
+
+## Migration Guides
+
+- [Alamofire 5.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%205.0%20Migration%20Guide.md)
+- [Alamofire 4.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%204.0%20Migration%20Guide.md)
+- [Alamofire 3.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%203.0%20Migration%20Guide.md)
+- [Alamofire 2.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%202.0%20Migration%20Guide.md)
+
+## Communication
+
+- If you **need help with making network requests** using Alamofire, use [Stack Overflow](https://stackoverflow.com/questions/tagged/alamofire) and tag `alamofire`.
+- If you need to **find or understand an API**, check [our documentation](http://alamofire.github.io/Alamofire/) or [Apple's documentation for `URLSession`](https://developer.apple.com/documentation/foundation/url_loading_system), on top of which Alamofire is built.
+- If you need **help with an Alamofire feature**, use [our forum on swift.org](https://forums.swift.org/c/related-projects/alamofire).
+- If you'd like to **discuss Alamofire best practices**, use [our forum on swift.org](https://forums.swift.org/c/related-projects/alamofire).
+- If you'd like to **discuss a feature request**, use [our forum on swift.org](https://forums.swift.org/c/related-projects/alamofire).
+- If you **found a bug**, open an issue here on GitHub and follow the guide. The more detail the better!
+
+## Installation
+
+### Swift Package Manager
+
+The [Swift Package Manager](https://swift.org/package-manager/) is a tool for automating the distribution of Swift code and is integrated into the `swift` compiler.
+
+Once you have your Swift package set up, adding Alamofire as a dependency is as easy as adding it to the `dependencies` value of your `Package.swift` or the Package list in Xcode.
+
+```swift
+dependencies: [
+ .package(url: "https://github.com/Alamofire/Alamofire.git", .upToNextMajor(from: "5.9.1"))
+]
+```
+
+Normally you'll want to depend on the `Alamofire` target:
+
+```swift
+.product(name: "Alamofire", package: "Alamofire")
+```
+
+But if you want to force Alamofire to be dynamically linked (do not do this unless you're sure you need it), you can depend on the `AlamofireDynamic` target:
+
+```swift
+.product(name: "AlamofireDynamic", package: "Alamofire")
+```
+
+### CocoaPods
+
+[CocoaPods](https://cocoapods.org) is a dependency manager for Cocoa projects. For usage and installation instructions, visit their website. To integrate Alamofire into your Xcode project using CocoaPods, specify it in your `Podfile`:
+
+```ruby
+pod 'Alamofire'
+```
+
+### Carthage
+
+[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. To integrate Alamofire into your Xcode project using Carthage, specify it in your `Cartfile`:
+
+```ogdl
+github "Alamofire/Alamofire"
+```
+
+### Manually
+
+If you prefer not to use any of the aforementioned dependency managers, you can integrate Alamofire into your project manually.
+
+#### Embedded Framework
+
+- Open up Terminal, `cd` into your top-level project directory, and run the following command "if" your project is not initialized as a git repository:
+
+ ```bash
+ $ git init
+ ```
+
+- Add Alamofire as a git [submodule](https://git-scm.com/docs/git-submodule) by running the following command:
+
+ ```bash
+ $ git submodule add https://github.com/Alamofire/Alamofire.git
+ ```
+
+- Open the new `Alamofire` folder, and drag the `Alamofire.xcodeproj` into the Project Navigator of your application's Xcode project.
+
+ > It should appear nested underneath your application's blue project icon. Whether it is above or below all the other Xcode groups does not matter.
+
+- Select the `Alamofire.xcodeproj` in the Project Navigator and verify the deployment target matches that of your application target.
+- Next, select your application project in the Project Navigator (blue project icon) to navigate to the target configuration window and select the application target under the "Targets" heading in the sidebar.
+- In the tab bar at the top of that window, open the "General" panel.
+- Click on the `+` button under the "Embedded Binaries" section.
+- You will see two different `Alamofire.xcodeproj` folders each with two different versions of the `Alamofire.framework` nested inside a `Products` folder.
+
+ > It does not matter which `Products` folder you choose from, but it does matter whether you choose the top or bottom `Alamofire.framework`.
+
+- Select the top `Alamofire.framework` for iOS and the bottom one for macOS.
+
+ > You can verify which one you selected by inspecting the build log for your project. The build target for `Alamofire` will be listed as `Alamofire iOS`, `Alamofire macOS`, `Alamofire tvOS`, or `Alamofire watchOS`.
+
+- And that's it!
+
+ > The `Alamofire.framework` is automagically added as a target dependency, linked framework and embedded framework in a copy files build phase which is all you need to build on the simulator and a device.
+
+## Contributing
+
+Before contributing to Alamofire, please read the instructions detailed in our [contribution guide](https://github.com/Alamofire/Alamofire/blob/master/CONTRIBUTING.md).
+
+## Open Radars
+
+The following radars have some effect on the current implementation of Alamofire.
+
+- [`rdar://21349340`](http://www.openradar.me/radar?id=5517037090635776) - Compiler throwing warning due to toll-free bridging issue in the test case
+- `rdar://26870455` - Background URL Session Configurations do not work in the simulator
+- `rdar://26849668` - Some URLProtocol APIs do not properly handle `URLRequest`
+
+## Resolved Radars
+
+The following radars have been resolved over time after being filed against the Alamofire project.
+
+- [`rdar://26761490`](http://www.openradar.me/radar?id=5010235949318144) - Swift string interpolation causing memory leak with common usage.
+ - (Resolved): 9/1/17 in Xcode 9 beta 6.
+- [`rdar://36082113`](http://openradar.appspot.com/radar?id=4942308441063424) - `URLSessionTaskMetrics` failing to link on watchOS 3.0+
+ - (Resolved): Just add `CFNetwork` to your linked frameworks.
+- `FB7624529` - `urlSession(_:task:didFinishCollecting:)` never called on watchOS
+ - (Resolved): Metrics now collected on watchOS 7+.
+
+## FAQ
+
+### What's the origin of the name Alamofire?
+
+Alamofire is named after the [Alamo Fire flower](https://aggie-horticulture.tamu.edu/wildseed/alamofire.html), a hybrid variant of the Bluebonnet, the official state flower of Texas.
+
+## Credits
+
+Alamofire is owned and maintained by the [Alamofire Software Foundation](http://alamofire.org). You can follow them on Twitter at [@AlamofireSF](https://twitter.com/AlamofireSF) for project updates and releases.
+
+### Security Disclosure
+
+If you believe you have identified a security vulnerability with Alamofire, you should report it as soon as possible via email to security@alamofire.org. Please do not post it to a public issue tracker.
+
+## Sponsorship
+
+The [ASF](https://github.com/Alamofire/Foundation#members) is looking to raise money to officially stay registered as a federal non-profit organization.
+Registering will allow Foundation members to gain some legal protections and also allow us to put donations to use, tax-free.
+Sponsoring the ASF will enable us to:
+
+- Pay our yearly legal fees to keep the non-profit in good status
+- Pay for our mail servers to help us stay on top of all questions and security issues
+- Potentially fund test servers to make it easier for us to test the edge cases
+- Potentially fund developers to work on one of our projects full-time
+
+The community adoption of the ASF libraries has been amazing.
+We are greatly humbled by your enthusiasm around the projects and want to continue to do everything we can to move the needle forward.
+With your continued support, the ASF will be able to improve its reach and also provide better legal safety for the core members.
+If you use any of our libraries for work, see if your employers would be interested in donating.
+Any amount you can donate, whether once or monthly, to help us reach our goal would be greatly appreciated.
+
+[Sponsor Alamofire](https://github.com/sponsors/Alamofire)
+
+## Supporters
+
+[MacStadium](https://macstadium.com) provides Alamofire with a free, hosted Mac mini.
+
+
+
+## License
+
+Alamofire is released under the MIT license. [See LICENSE](https://github.com/Alamofire/Alamofire/blob/master/LICENSE) for details.
diff --git a/ChatBot/Pods/Alamofire/Source/Alamofire.swift b/ChatBot/Pods/Alamofire/Source/Alamofire.swift
new file mode 100644
index 00000000..46071970
--- /dev/null
+++ b/ChatBot/Pods/Alamofire/Source/Alamofire.swift
@@ -0,0 +1,43 @@
+//
+// Alamofire.swift
+//
+// Copyright (c) 2014-2021 Alamofire Software Foundation (http://alamofire.org/)
+//
+// 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 Dispatch
+import Foundation
+#if canImport(FoundationNetworking)
+@_exported import FoundationNetworking
+#endif
+
+// Enforce minimum Swift version for all platforms and build systems.
+#if swift(<5.7.1)
+#error("Alamofire doesn't support Swift versions below 5.7.1.")
+#endif
+
+/// Reference to `Session.default` for quick bootstrapping and examples.
+public let AF = Session.default
+
+/// Namespace for informational Alamofire values.
+public enum AFInfo {
+ /// Current Alamofire version.
+ public static let version = "5.9.1"
+}
diff --git a/ChatBot/Pods/Alamofire/Source/Core/AFError.swift b/ChatBot/Pods/Alamofire/Source/Core/AFError.swift
new file mode 100644
index 00000000..cb7aa40b
--- /dev/null
+++ b/ChatBot/Pods/Alamofire/Source/Core/AFError.swift
@@ -0,0 +1,874 @@
+//
+// AFError.swift
+//
+// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+// 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 Foundation
+
+#if canImport(Security)
+import Security
+#endif
+
+/// `AFError` is the error type returned by Alamofire. It encompasses a few different types of errors, each with
+/// their own associated reasons.
+public enum AFError: Error {
+ /// The underlying reason the `.multipartEncodingFailed` error occurred.
+ public enum MultipartEncodingFailureReason {
+ /// The `fileURL` provided for reading an encodable body part isn't a file `URL`.
+ case bodyPartURLInvalid(url: URL)
+ /// The filename of the `fileURL` provided has either an empty `lastPathComponent` or `pathExtension`.
+ case bodyPartFilenameInvalid(in: URL)
+ /// The file at the `fileURL` provided was not reachable.
+ case bodyPartFileNotReachable(at: URL)
+ /// Attempting to check the reachability of the `fileURL` provided threw an error.
+ case bodyPartFileNotReachableWithError(atURL: URL, error: Error)
+ /// The file at the `fileURL` provided is actually a directory.
+ case bodyPartFileIsDirectory(at: URL)
+ /// The size of the file at the `fileURL` provided was not returned by the system.
+ case bodyPartFileSizeNotAvailable(at: URL)
+ /// The attempt to find the size of the file at the `fileURL` provided threw an error.
+ case bodyPartFileSizeQueryFailedWithError(forURL: URL, error: Error)
+ /// An `InputStream` could not be created for the provided `fileURL`.
+ case bodyPartInputStreamCreationFailed(for: URL)
+ /// An `OutputStream` could not be created when attempting to write the encoded data to disk.
+ case outputStreamCreationFailed(for: URL)
+ /// The encoded body data could not be written to disk because a file already exists at the provided `fileURL`.
+ case outputStreamFileAlreadyExists(at: URL)
+ /// The `fileURL` provided for writing the encoded body data to disk is not a file `URL`.
+ case outputStreamURLInvalid(url: URL)
+ /// The attempt to write the encoded body data to disk failed with an underlying error.
+ case outputStreamWriteFailed(error: Error)
+ /// The attempt to read an encoded body part `InputStream` failed with underlying system error.
+ case inputStreamReadFailed(error: Error)
+ }
+
+ /// Represents unexpected input stream length that occur when encoding the `MultipartFormData`. Instances will be
+ /// embedded within an `AFError.multipartEncodingFailed` `.inputStreamReadFailed` case.
+ public struct UnexpectedInputStreamLength: Error {
+ /// The expected byte count to read.
+ public var bytesExpected: UInt64
+ /// The actual byte count read.
+ public var bytesRead: UInt64
+ }
+
+ /// The underlying reason the `.parameterEncodingFailed` error occurred.
+ public enum ParameterEncodingFailureReason {
+ /// The `URLRequest` did not have a `URL` to encode.
+ case missingURL
+ /// JSON serialization failed with an underlying system error during the encoding process.
+ case jsonEncodingFailed(error: Error)
+ /// Custom parameter encoding failed due to the associated `Error`.
+ case customEncodingFailed(error: Error)
+ }
+
+ /// The underlying reason the `.parameterEncoderFailed` error occurred.
+ public enum ParameterEncoderFailureReason {
+ /// Possible missing components.
+ public enum RequiredComponent {
+ /// The `URL` was missing or unable to be extracted from the passed `URLRequest` or during encoding.
+ case url
+ /// The `HTTPMethod` could not be extracted from the passed `URLRequest`.
+ case httpMethod(rawValue: String)
+ }
+
+ /// A `RequiredComponent` was missing during encoding.
+ case missingRequiredComponent(RequiredComponent)
+ /// The underlying encoder failed with the associated error.
+ case encoderFailed(error: Error)
+ }
+
+ /// The underlying reason the `.responseValidationFailed` error occurred.
+ public enum ResponseValidationFailureReason {
+ /// The data file containing the server response did not exist.
+ case dataFileNil
+ /// The data file containing the server response at the associated `URL` could not be read.
+ case dataFileReadFailed(at: URL)
+ /// The response did not contain a `Content-Type` and the `acceptableContentTypes` provided did not contain a
+ /// wildcard type.
+ case missingContentType(acceptableContentTypes: [String])
+ /// The response `Content-Type` did not match any type in the provided `acceptableContentTypes`.
+ case unacceptableContentType(acceptableContentTypes: [String], responseContentType: String)
+ /// The response status code was not acceptable.
+ case unacceptableStatusCode(code: Int)
+ /// Custom response validation failed due to the associated `Error`.
+ case customValidationFailed(error: Error)
+ }
+
+ /// The underlying reason the response serialization error occurred.
+ public enum ResponseSerializationFailureReason {
+ /// The server response contained no data or the data was zero length.
+ case inputDataNilOrZeroLength
+ /// The file containing the server response did not exist.
+ case inputFileNil
+ /// The file containing the server response could not be read from the associated `URL`.
+ case inputFileReadFailed(at: URL)
+ /// String serialization failed using the provided `String.Encoding`.
+ case stringSerializationFailed(encoding: String.Encoding)
+ /// JSON serialization failed with an underlying system error.
+ case jsonSerializationFailed(error: Error)
+ /// A `DataDecoder` failed to decode the response due to the associated `Error`.
+ case decodingFailed(error: Error)
+ /// A custom response serializer failed due to the associated `Error`.
+ case customSerializationFailed(error: Error)
+ /// Generic serialization failed for an empty response that wasn't type `Empty` but instead the associated type.
+ case invalidEmptyResponse(type: String)
+ }
+
+ #if canImport(Security)
+ /// Underlying reason a server trust evaluation error occurred.
+ public enum ServerTrustFailureReason {
+ /// The output of a server trust evaluation.
+ public struct Output {
+ /// The host for which the evaluation was performed.
+ public let host: String
+ /// The `SecTrust` value which was evaluated.
+ public let trust: SecTrust
+ /// The `OSStatus` of evaluation operation.
+ public let status: OSStatus
+ /// The result of the evaluation operation.
+ public let result: SecTrustResultType
+
+ /// Creates an `Output` value from the provided values.
+ init(_ host: String, _ trust: SecTrust, _ status: OSStatus, _ result: SecTrustResultType) {
+ self.host = host
+ self.trust = trust
+ self.status = status
+ self.result = result
+ }
+ }
+
+ /// No `ServerTrustEvaluator` was found for the associated host.
+ case noRequiredEvaluator(host: String)
+ /// No certificates were found with which to perform the trust evaluation.
+ case noCertificatesFound
+ /// No public keys were found with which to perform the trust evaluation.
+ case noPublicKeysFound
+ /// During evaluation, application of the associated `SecPolicy` failed.
+ case policyApplicationFailed(trust: SecTrust, policy: SecPolicy, status: OSStatus)
+ /// During evaluation, setting the associated anchor certificates failed.
+ case settingAnchorCertificatesFailed(status: OSStatus, certificates: [SecCertificate])
+ /// During evaluation, creation of the revocation policy failed.
+ case revocationPolicyCreationFailed
+ /// `SecTrust` evaluation failed with the associated `Error`, if one was produced.
+ case trustEvaluationFailed(error: Error?)
+ /// Default evaluation failed with the associated `Output`.
+ case defaultEvaluationFailed(output: Output)
+ /// Host validation failed with the associated `Output`.
+ case hostValidationFailed(output: Output)
+ /// Revocation check failed with the associated `Output` and options.
+ case revocationCheckFailed(output: Output, options: RevocationTrustEvaluator.Options)
+ /// Certificate pinning failed.
+ case certificatePinningFailed(host: String, trust: SecTrust, pinnedCertificates: [SecCertificate], serverCertificates: [SecCertificate])
+ /// Public key pinning failed.
+ case publicKeyPinningFailed(host: String, trust: SecTrust, pinnedKeys: [SecKey], serverKeys: [SecKey])
+ /// Custom server trust evaluation failed due to the associated `Error`.
+ case customEvaluationFailed(error: Error)
+ }
+ #endif
+
+ /// The underlying reason the `.urlRequestValidationFailed` error occurred.
+ public enum URLRequestValidationFailureReason {
+ /// URLRequest with GET method had body data.
+ case bodyDataInGETRequest(Data)
+ }
+
+ /// `UploadableConvertible` threw an error in `createUploadable()`.
+ case createUploadableFailed(error: Error)
+ /// `URLRequestConvertible` threw an error in `asURLRequest()`.
+ case createURLRequestFailed(error: Error)
+ /// `SessionDelegate` threw an error while attempting to move downloaded file to destination URL.
+ case downloadedFileMoveFailed(error: Error, source: URL, destination: URL)
+ /// `Request` was explicitly cancelled.
+ case explicitlyCancelled
+ /// `URLConvertible` type failed to create a valid `URL`.
+ case invalidURL(url: URLConvertible)
+ /// Multipart form encoding failed.
+ case multipartEncodingFailed(reason: MultipartEncodingFailureReason)
+ /// `ParameterEncoding` threw an error during the encoding process.
+ case parameterEncodingFailed(reason: ParameterEncodingFailureReason)
+ /// `ParameterEncoder` threw an error while running the encoder.
+ case parameterEncoderFailed(reason: ParameterEncoderFailureReason)
+ /// `RequestAdapter` threw an error during adaptation.
+ case requestAdaptationFailed(error: Error)
+ /// `RequestRetrier` threw an error during the request retry process.
+ case requestRetryFailed(retryError: Error, originalError: Error)
+ /// Response validation failed.
+ case responseValidationFailed(reason: ResponseValidationFailureReason)
+ /// Response serialization failed.
+ case responseSerializationFailed(reason: ResponseSerializationFailureReason)
+ #if canImport(Security)
+ /// `ServerTrustEvaluating` instance threw an error during trust evaluation.
+ case serverTrustEvaluationFailed(reason: ServerTrustFailureReason)
+ #endif
+ /// `Session` which issued the `Request` was deinitialized, most likely because its reference went out of scope.
+ case sessionDeinitialized
+ /// `Session` was explicitly invalidated, possibly with the `Error` produced by the underlying `URLSession`.
+ case sessionInvalidated(error: Error?)
+ /// `URLSessionTask` completed with error.
+ case sessionTaskFailed(error: Error)
+ /// `URLRequest` failed validation.
+ case urlRequestValidationFailed(reason: URLRequestValidationFailureReason)
+}
+
+extension Error {
+ /// Returns the instance cast as an `AFError`.
+ public var asAFError: AFError? {
+ self as? AFError
+ }
+
+ /// Returns the instance cast as an `AFError`. If casting fails, a `fatalError` with the specified `message` is thrown.
+ public func asAFError(orFailWith message: @autoclosure () -> String, file: StaticString = #file, line: UInt = #line) -> AFError {
+ guard let afError = self as? AFError else {
+ fatalError(message(), file: file, line: line)
+ }
+ return afError
+ }
+
+ /// Casts the instance as `AFError` or returns `defaultAFError`
+ func asAFError(or defaultAFError: @autoclosure () -> AFError) -> AFError {
+ self as? AFError ?? defaultAFError()
+ }
+}
+
+// MARK: - Error Booleans
+
+extension AFError {
+ /// Returns whether the instance is `.sessionDeinitialized`.
+ public var isSessionDeinitializedError: Bool {
+ if case .sessionDeinitialized = self { return true }
+ return false
+ }
+
+ /// Returns whether the instance is `.sessionInvalidated`.
+ public var isSessionInvalidatedError: Bool {
+ if case .sessionInvalidated = self { return true }
+ return false
+ }
+
+ /// Returns whether the instance is `.explicitlyCancelled`.
+ public var isExplicitlyCancelledError: Bool {
+ if case .explicitlyCancelled = self { return true }
+ return false
+ }
+
+ /// Returns whether the instance is `.invalidURL`.
+ public var isInvalidURLError: Bool {
+ if case .invalidURL = self { return true }
+ return false
+ }
+
+ /// Returns whether the instance is `.parameterEncodingFailed`. When `true`, the `underlyingError` property will
+ /// contain the associated value.
+ public var isParameterEncodingError: Bool {
+ if case .parameterEncodingFailed = self { return true }
+ return false
+ }
+
+ /// Returns whether the instance is `.parameterEncoderFailed`. When `true`, the `underlyingError` property will
+ /// contain the associated value.
+ public var isParameterEncoderError: Bool {
+ if case .parameterEncoderFailed = self { return true }
+ return false
+ }
+
+ /// Returns whether the instance is `.multipartEncodingFailed`. When `true`, the `url` and `underlyingError`
+ /// properties will contain the associated values.
+ public var isMultipartEncodingError: Bool {
+ if case .multipartEncodingFailed = self { return true }
+ return false
+ }
+
+ /// Returns whether the instance is `.requestAdaptationFailed`. When `true`, the `underlyingError` property will
+ /// contain the associated value.
+ public var isRequestAdaptationError: Bool {
+ if case .requestAdaptationFailed = self { return true }
+ return false
+ }
+
+ /// Returns whether the instance is `.responseValidationFailed`. When `true`, the `acceptableContentTypes`,
+ /// `responseContentType`, `responseCode`, and `underlyingError` properties will contain the associated values.
+ public var isResponseValidationError: Bool {
+ if case .responseValidationFailed = self { return true }
+ return false
+ }
+
+ /// Returns whether the instance is `.responseSerializationFailed`. When `true`, the `failedStringEncoding` and
+ /// `underlyingError` properties will contain the associated values.
+ public var isResponseSerializationError: Bool {
+ if case .responseSerializationFailed = self { return true }
+ return false
+ }
+
+ #if canImport(Security)
+ /// Returns whether the instance is `.serverTrustEvaluationFailed`. When `true`, the `underlyingError` property will
+ /// contain the associated value.
+ public var isServerTrustEvaluationError: Bool {
+ if case .serverTrustEvaluationFailed = self { return true }
+ return false
+ }
+ #endif
+
+ /// Returns whether the instance is `requestRetryFailed`. When `true`, the `underlyingError` property will
+ /// contain the associated value.
+ public var isRequestRetryError: Bool {
+ if case .requestRetryFailed = self { return true }
+ return false
+ }
+
+ /// Returns whether the instance is `createUploadableFailed`. When `true`, the `underlyingError` property will
+ /// contain the associated value.
+ public var isCreateUploadableError: Bool {
+ if case .createUploadableFailed = self { return true }
+ return false
+ }
+
+ /// Returns whether the instance is `createURLRequestFailed`. When `true`, the `underlyingError` property will
+ /// contain the associated value.
+ public var isCreateURLRequestError: Bool {
+ if case .createURLRequestFailed = self { return true }
+ return false
+ }
+
+ /// Returns whether the instance is `downloadedFileMoveFailed`. When `true`, the `destination` and `underlyingError` properties will
+ /// contain the associated values.
+ public var isDownloadedFileMoveError: Bool {
+ if case .downloadedFileMoveFailed = self { return true }
+ return false
+ }
+
+ /// Returns whether the instance is `createURLRequestFailed`. When `true`, the `underlyingError` property will
+ /// contain the associated value.
+ public var isSessionTaskError: Bool {
+ if case .sessionTaskFailed = self { return true }
+ return false
+ }
+}
+
+// MARK: - Convenience Properties
+
+extension AFError {
+ /// The `URLConvertible` associated with the error.
+ public var urlConvertible: URLConvertible? {
+ guard case let .invalidURL(url) = self else { return nil }
+ return url
+ }
+
+ /// The `URL` associated with the error.
+ public var url: URL? {
+ guard case let .multipartEncodingFailed(reason) = self else { return nil }
+ return reason.url
+ }
+
+ /// The underlying `Error` responsible for generating the failure associated with `.sessionInvalidated`,
+ /// `.parameterEncodingFailed`, `.parameterEncoderFailed`, `.multipartEncodingFailed`, `.requestAdaptationFailed`,
+ /// `.responseSerializationFailed`, `.requestRetryFailed` errors.
+ public var underlyingError: Error? {
+ switch self {
+ case let .multipartEncodingFailed(reason):
+ return reason.underlyingError
+ case let .parameterEncodingFailed(reason):
+ return reason.underlyingError
+ case let .parameterEncoderFailed(reason):
+ return reason.underlyingError
+ case let .requestAdaptationFailed(error):
+ return error
+ case let .requestRetryFailed(retryError, _):
+ return retryError
+ case let .responseValidationFailed(reason):
+ return reason.underlyingError
+ case let .responseSerializationFailed(reason):
+ return reason.underlyingError
+ #if canImport(Security)
+ case let .serverTrustEvaluationFailed(reason):
+ return reason.underlyingError
+ #endif
+ case let .sessionInvalidated(error):
+ return error
+ case let .createUploadableFailed(error):
+ return error
+ case let .createURLRequestFailed(error):
+ return error
+ case let .downloadedFileMoveFailed(error, _, _):
+ return error
+ case let .sessionTaskFailed(error):
+ return error
+ case .explicitlyCancelled,
+ .invalidURL,
+ .sessionDeinitialized,
+ .urlRequestValidationFailed:
+ return nil
+ }
+ }
+
+ /// The acceptable `Content-Type`s of a `.responseValidationFailed` error.
+ public var acceptableContentTypes: [String]? {
+ guard case let .responseValidationFailed(reason) = self else { return nil }
+ return reason.acceptableContentTypes
+ }
+
+ /// The response `Content-Type` of a `.responseValidationFailed` error.
+ public var responseContentType: String? {
+ guard case let .responseValidationFailed(reason) = self else { return nil }
+ return reason.responseContentType
+ }
+
+ /// The response code of a `.responseValidationFailed` error.
+ public var responseCode: Int? {
+ guard case let .responseValidationFailed(reason) = self else { return nil }
+ return reason.responseCode
+ }
+
+ /// The `String.Encoding` associated with a failed `.stringResponse()` call.
+ public var failedStringEncoding: String.Encoding? {
+ guard case let .responseSerializationFailed(reason) = self else { return nil }
+ return reason.failedStringEncoding
+ }
+
+ /// The `source` URL of a `.downloadedFileMoveFailed` error.
+ public var sourceURL: URL? {
+ guard case let .downloadedFileMoveFailed(_, source, _) = self else { return nil }
+ return source
+ }
+
+ /// The `destination` URL of a `.downloadedFileMoveFailed` error.
+ public var destinationURL: URL? {
+ guard case let .downloadedFileMoveFailed(_, _, destination) = self else { return nil }
+ return destination
+ }
+
+ #if canImport(Security)
+ /// The download resume data of any underlying network error. Only produced by `DownloadRequest`s.
+ public var downloadResumeData: Data? {
+ (underlyingError as? URLError)?.userInfo[NSURLSessionDownloadTaskResumeData] as? Data
+ }
+ #endif
+}
+
+extension AFError.ParameterEncodingFailureReason {
+ var underlyingError: Error? {
+ switch self {
+ case let .jsonEncodingFailed(error),
+ let .customEncodingFailed(error):
+ return error
+ case .missingURL:
+ return nil
+ }
+ }
+}
+
+extension AFError.ParameterEncoderFailureReason {
+ var underlyingError: Error? {
+ switch self {
+ case let .encoderFailed(error):
+ return error
+ case .missingRequiredComponent:
+ return nil
+ }
+ }
+}
+
+extension AFError.MultipartEncodingFailureReason {
+ var url: URL? {
+ switch self {
+ case let .bodyPartURLInvalid(url),
+ let .bodyPartFilenameInvalid(url),
+ let .bodyPartFileNotReachable(url),
+ let .bodyPartFileIsDirectory(url),
+ let .bodyPartFileSizeNotAvailable(url),
+ let .bodyPartInputStreamCreationFailed(url),
+ let .outputStreamCreationFailed(url),
+ let .outputStreamFileAlreadyExists(url),
+ let .outputStreamURLInvalid(url),
+ let .bodyPartFileNotReachableWithError(url, _),
+ let .bodyPartFileSizeQueryFailedWithError(url, _):
+ return url
+ case .outputStreamWriteFailed,
+ .inputStreamReadFailed:
+ return nil
+ }
+ }
+
+ var underlyingError: Error? {
+ switch self {
+ case let .bodyPartFileNotReachableWithError(_, error),
+ let .bodyPartFileSizeQueryFailedWithError(_, error),
+ let .outputStreamWriteFailed(error),
+ let .inputStreamReadFailed(error):
+ return error
+ case .bodyPartURLInvalid,
+ .bodyPartFilenameInvalid,
+ .bodyPartFileNotReachable,
+ .bodyPartFileIsDirectory,
+ .bodyPartFileSizeNotAvailable,
+ .bodyPartInputStreamCreationFailed,
+ .outputStreamCreationFailed,
+ .outputStreamFileAlreadyExists,
+ .outputStreamURLInvalid:
+ return nil
+ }
+ }
+}
+
+extension AFError.ResponseValidationFailureReason {
+ var acceptableContentTypes: [String]? {
+ switch self {
+ case let .missingContentType(types),
+ let .unacceptableContentType(types, _):
+ return types
+ case .dataFileNil,
+ .dataFileReadFailed,
+ .unacceptableStatusCode,
+ .customValidationFailed:
+ return nil
+ }
+ }
+
+ var responseContentType: String? {
+ switch self {
+ case let .unacceptableContentType(_, responseType):
+ return responseType
+ case .dataFileNil,
+ .dataFileReadFailed,
+ .missingContentType,
+ .unacceptableStatusCode,
+ .customValidationFailed:
+ return nil
+ }
+ }
+
+ var responseCode: Int? {
+ switch self {
+ case let .unacceptableStatusCode(code):
+ return code
+ case .dataFileNil,
+ .dataFileReadFailed,
+ .missingContentType,
+ .unacceptableContentType,
+ .customValidationFailed:
+ return nil
+ }
+ }
+
+ var underlyingError: Error? {
+ switch self {
+ case let .customValidationFailed(error):
+ return error
+ case .dataFileNil,
+ .dataFileReadFailed,
+ .missingContentType,
+ .unacceptableContentType,
+ .unacceptableStatusCode:
+ return nil
+ }
+ }
+}
+
+extension AFError.ResponseSerializationFailureReason {
+ var failedStringEncoding: String.Encoding? {
+ switch self {
+ case let .stringSerializationFailed(encoding):
+ return encoding
+ case .inputDataNilOrZeroLength,
+ .inputFileNil,
+ .inputFileReadFailed(_),
+ .jsonSerializationFailed(_),
+ .decodingFailed(_),
+ .customSerializationFailed(_),
+ .invalidEmptyResponse:
+ return nil
+ }
+ }
+
+ var underlyingError: Error? {
+ switch self {
+ case let .jsonSerializationFailed(error),
+ let .decodingFailed(error),
+ let .customSerializationFailed(error):
+ return error
+ case .inputDataNilOrZeroLength,
+ .inputFileNil,
+ .inputFileReadFailed,
+ .stringSerializationFailed,
+ .invalidEmptyResponse:
+ return nil
+ }
+ }
+}
+
+#if canImport(Security)
+extension AFError.ServerTrustFailureReason {
+ var output: AFError.ServerTrustFailureReason.Output? {
+ switch self {
+ case let .defaultEvaluationFailed(output),
+ let .hostValidationFailed(output),
+ let .revocationCheckFailed(output, _):
+ return output
+ case .noRequiredEvaluator,
+ .noCertificatesFound,
+ .noPublicKeysFound,
+ .policyApplicationFailed,
+ .settingAnchorCertificatesFailed,
+ .revocationPolicyCreationFailed,
+ .trustEvaluationFailed,
+ .certificatePinningFailed,
+ .publicKeyPinningFailed,
+ .customEvaluationFailed:
+ return nil
+ }
+ }
+
+ var underlyingError: Error? {
+ switch self {
+ case let .customEvaluationFailed(error):
+ return error
+ case let .trustEvaluationFailed(error):
+ return error
+ case .noRequiredEvaluator,
+ .noCertificatesFound,
+ .noPublicKeysFound,
+ .policyApplicationFailed,
+ .settingAnchorCertificatesFailed,
+ .revocationPolicyCreationFailed,
+ .defaultEvaluationFailed,
+ .hostValidationFailed,
+ .revocationCheckFailed,
+ .certificatePinningFailed,
+ .publicKeyPinningFailed:
+ return nil
+ }
+ }
+}
+#endif
+
+// MARK: - Error Descriptions
+
+extension AFError: LocalizedError {
+ public var errorDescription: String? {
+ switch self {
+ case .explicitlyCancelled:
+ return "Request explicitly cancelled."
+ case let .invalidURL(url):
+ return "URL is not valid: \(url)"
+ case let .parameterEncodingFailed(reason):
+ return reason.localizedDescription
+ case let .parameterEncoderFailed(reason):
+ return reason.localizedDescription
+ case let .multipartEncodingFailed(reason):
+ return reason.localizedDescription
+ case let .requestAdaptationFailed(error):
+ return "Request adaption failed with error: \(error.localizedDescription)"
+ case let .responseValidationFailed(reason):
+ return reason.localizedDescription
+ case let .responseSerializationFailed(reason):
+ return reason.localizedDescription
+ case let .requestRetryFailed(retryError, originalError):
+ return """
+ Request retry failed with retry error: \(retryError.localizedDescription), \
+ original error: \(originalError.localizedDescription)
+ """
+ case .sessionDeinitialized:
+ return """
+ Session was invalidated without error, so it was likely deinitialized unexpectedly. \
+ Be sure to retain a reference to your Session for the duration of your requests.
+ """
+ case let .sessionInvalidated(error):
+ return "Session was invalidated with error: \(error?.localizedDescription ?? "No description.")"
+ #if canImport(Security)
+ case let .serverTrustEvaluationFailed(reason):
+ return "Server trust evaluation failed due to reason: \(reason.localizedDescription)"
+ #endif
+ case let .urlRequestValidationFailed(reason):
+ return "URLRequest validation failed due to reason: \(reason.localizedDescription)"
+ case let .createUploadableFailed(error):
+ return "Uploadable creation failed with error: \(error.localizedDescription)"
+ case let .createURLRequestFailed(error):
+ return "URLRequest creation failed with error: \(error.localizedDescription)"
+ case let .downloadedFileMoveFailed(error, source, destination):
+ return "Moving downloaded file from: \(source) to: \(destination) failed with error: \(error.localizedDescription)"
+ case let .sessionTaskFailed(error):
+ return "URLSessionTask failed with error: \(error.localizedDescription)"
+ }
+ }
+}
+
+extension AFError.ParameterEncodingFailureReason {
+ var localizedDescription: String {
+ switch self {
+ case .missingURL:
+ return "URL request to encode was missing a URL"
+ case let .jsonEncodingFailed(error):
+ return "JSON could not be encoded because of error:\n\(error.localizedDescription)"
+ case let .customEncodingFailed(error):
+ return "Custom parameter encoder failed with error: \(error.localizedDescription)"
+ }
+ }
+}
+
+extension AFError.ParameterEncoderFailureReason {
+ var localizedDescription: String {
+ switch self {
+ case let .missingRequiredComponent(component):
+ return "Encoding failed due to a missing request component: \(component)"
+ case let .encoderFailed(error):
+ return "The underlying encoder failed with the error: \(error)"
+ }
+ }
+}
+
+extension AFError.MultipartEncodingFailureReason {
+ var localizedDescription: String {
+ switch self {
+ case let .bodyPartURLInvalid(url):
+ return "The URL provided is not a file URL: \(url)"
+ case let .bodyPartFilenameInvalid(url):
+ return "The URL provided does not have a valid filename: \(url)"
+ case let .bodyPartFileNotReachable(url):
+ return "The URL provided is not reachable: \(url)"
+ case let .bodyPartFileNotReachableWithError(url, error):
+ return """
+ The system returned an error while checking the provided URL for reachability.
+ URL: \(url)
+ Error: \(error)
+ """
+ case let .bodyPartFileIsDirectory(url):
+ return "The URL provided is a directory: \(url)"
+ case let .bodyPartFileSizeNotAvailable(url):
+ return "Could not fetch the file size from the provided URL: \(url)"
+ case let .bodyPartFileSizeQueryFailedWithError(url, error):
+ return """
+ The system returned an error while attempting to fetch the file size from the provided URL.
+ URL: \(url)
+ Error: \(error)
+ """
+ case let .bodyPartInputStreamCreationFailed(url):
+ return "Failed to create an InputStream for the provided URL: \(url)"
+ case let .outputStreamCreationFailed(url):
+ return "Failed to create an OutputStream for URL: \(url)"
+ case let .outputStreamFileAlreadyExists(url):
+ return "A file already exists at the provided URL: \(url)"
+ case let .outputStreamURLInvalid(url):
+ return "The provided OutputStream URL is invalid: \(url)"
+ case let .outputStreamWriteFailed(error):
+ return "OutputStream write failed with error: \(error)"
+ case let .inputStreamReadFailed(error):
+ return "InputStream read failed with error: \(error)"
+ }
+ }
+}
+
+extension AFError.ResponseSerializationFailureReason {
+ var localizedDescription: String {
+ switch self {
+ case .inputDataNilOrZeroLength:
+ return "Response could not be serialized, input data was nil or zero length."
+ case .inputFileNil:
+ return "Response could not be serialized, input file was nil."
+ case let .inputFileReadFailed(url):
+ return "Response could not be serialized, input file could not be read: \(url)."
+ case let .stringSerializationFailed(encoding):
+ return "String could not be serialized with encoding: \(encoding)."
+ case let .jsonSerializationFailed(error):
+ return "JSON could not be serialized because of error:\n\(error.localizedDescription)"
+ case let .invalidEmptyResponse(type):
+ return """
+ Empty response could not be serialized to type: \(type). \
+ Use Empty as the expected type for such responses.
+ """
+ case let .decodingFailed(error):
+ return "Response could not be decoded because of error:\n\(error.localizedDescription)"
+ case let .customSerializationFailed(error):
+ return "Custom response serializer failed with error:\n\(error.localizedDescription)"
+ }
+ }
+}
+
+extension AFError.ResponseValidationFailureReason {
+ var localizedDescription: String {
+ switch self {
+ case .dataFileNil:
+ return "Response could not be validated, data file was nil."
+ case let .dataFileReadFailed(url):
+ return "Response could not be validated, data file could not be read: \(url)."
+ case let .missingContentType(types):
+ return """
+ Response Content-Type was missing and acceptable content types \
+ (\(types.joined(separator: ","))) do not match "*/*".
+ """
+ case let .unacceptableContentType(acceptableTypes, responseType):
+ return """
+ Response Content-Type "\(responseType)" does not match any acceptable types: \
+ \(acceptableTypes.joined(separator: ",")).
+ """
+ case let .unacceptableStatusCode(code):
+ return "Response status code was unacceptable: \(code)."
+ case let .customValidationFailed(error):
+ return "Custom response validation failed with error: \(error.localizedDescription)"
+ }
+ }
+}
+
+#if canImport(Security)
+extension AFError.ServerTrustFailureReason {
+ var localizedDescription: String {
+ switch self {
+ case let .noRequiredEvaluator(host):
+ return "A ServerTrustEvaluating value is required for host \(host) but none was found."
+ case .noCertificatesFound:
+ return "No certificates were found or provided for evaluation."
+ case .noPublicKeysFound:
+ return "No public keys were found or provided for evaluation."
+ case .policyApplicationFailed:
+ return "Attempting to set a SecPolicy failed."
+ case .settingAnchorCertificatesFailed:
+ return "Attempting to set the provided certificates as anchor certificates failed."
+ case .revocationPolicyCreationFailed:
+ return "Attempting to create a revocation policy failed."
+ case let .trustEvaluationFailed(error):
+ return "SecTrust evaluation failed with error: \(error?.localizedDescription ?? "None")"
+ case let .defaultEvaluationFailed(output):
+ return "Default evaluation failed for host \(output.host)."
+ case let .hostValidationFailed(output):
+ return "Host validation failed for host \(output.host)."
+ case let .revocationCheckFailed(output, _):
+ return "Revocation check failed for host \(output.host)."
+ case let .certificatePinningFailed(host, _, _, _):
+ return "Certificate pinning failed for host \(host)."
+ case let .publicKeyPinningFailed(host, _, _, _):
+ return "Public key pinning failed for host \(host)."
+ case let .customEvaluationFailed(error):
+ return "Custom trust evaluation failed with error: \(error.localizedDescription)"
+ }
+ }
+}
+#endif
+
+extension AFError.URLRequestValidationFailureReason {
+ var localizedDescription: String {
+ switch self {
+ case let .bodyDataInGETRequest(data):
+ return """
+ Invalid URLRequest: Requests with GET method cannot have body data:
+ \(String(decoding: data, as: UTF8.self))
+ """
+ }
+ }
+}
diff --git a/ChatBot/Pods/Alamofire/Source/Core/DataRequest.swift b/ChatBot/Pods/Alamofire/Source/Core/DataRequest.swift
new file mode 100644
index 00000000..e282ee53
--- /dev/null
+++ b/ChatBot/Pods/Alamofire/Source/Core/DataRequest.swift
@@ -0,0 +1,448 @@
+//
+// DataRequest.swift
+//
+// Copyright (c) 2014-2024 Alamofire Software Foundation (http://alamofire.org/)
+//
+// 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 Foundation
+
+/// `Request` subclass which handles in-memory `Data` download using `URLSessionDataTask`.
+public class DataRequest: Request {
+ /// `URLRequestConvertible` value used to create `URLRequest`s for this instance.
+ public let convertible: URLRequestConvertible
+ /// `Data` read from the server so far.
+ public var data: Data? { dataMutableState.data }
+
+ private struct DataMutableState {
+ var data: Data?
+ var httpResponseHandler: (queue: DispatchQueue,
+ handler: (_ response: HTTPURLResponse,
+ _ completionHandler: @escaping (ResponseDisposition) -> Void) -> Void)?
+ }
+
+ private let dataMutableState = Protected(DataMutableState())
+
+ /// Creates a `DataRequest` using the provided parameters.
+ ///
+ /// - Parameters:
+ /// - id: `UUID` used for the `Hashable` and `Equatable` implementations. `UUID()` by default.
+ /// - convertible: `URLRequestConvertible` value used to create `URLRequest`s for this instance.
+ /// - underlyingQueue: `DispatchQueue` on which all internal `Request` work is performed.
+ /// - serializationQueue: `DispatchQueue` on which all serialization work is performed. By default targets
+ /// `underlyingQueue`, but can be passed another queue from a `Session`.
+ /// - eventMonitor: `EventMonitor` called for event callbacks from internal `Request` actions.
+ /// - interceptor: `RequestInterceptor` used throughout the request lifecycle.
+ /// - delegate: `RequestDelegate` that provides an interface to actions not performed by the `Request`.
+ init(id: UUID = UUID(),
+ convertible: URLRequestConvertible,
+ underlyingQueue: DispatchQueue,
+ serializationQueue: DispatchQueue,
+ eventMonitor: EventMonitor?,
+ interceptor: RequestInterceptor?,
+ delegate: RequestDelegate) {
+ self.convertible = convertible
+
+ super.init(id: id,
+ underlyingQueue: underlyingQueue,
+ serializationQueue: serializationQueue,
+ eventMonitor: eventMonitor,
+ interceptor: interceptor,
+ delegate: delegate)
+ }
+
+ override func reset() {
+ super.reset()
+
+ dataMutableState.write { mutableState in
+ mutableState.data = nil
+ }
+ }
+
+ /// Called when `Data` is received by this instance.
+ ///
+ /// - Note: Also calls `updateDownloadProgress`.
+ ///
+ /// - Parameter data: The `Data` received.
+ func didReceive(data: Data) {
+ dataMutableState.write { mutableState in
+ if mutableState.data == nil {
+ mutableState.data = data
+ } else {
+ mutableState.data?.append(data)
+ }
+ }
+
+ updateDownloadProgress()
+ }
+
+ func didReceiveResponse(_ response: HTTPURLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
+ dataMutableState.read { dataMutableState in
+ guard let httpResponseHandler = dataMutableState.httpResponseHandler else {
+ underlyingQueue.async { completionHandler(.allow) }
+ return
+ }
+
+ httpResponseHandler.queue.async {
+ httpResponseHandler.handler(response) { disposition in
+ if disposition == .cancel {
+ self.mutableState.write { mutableState in
+ mutableState.state = .cancelled
+ mutableState.error = mutableState.error ?? AFError.explicitlyCancelled
+ }
+ }
+
+ self.underlyingQueue.async {
+ completionHandler(disposition.sessionDisposition)
+ }
+ }
+ }
+ }
+ }
+
+ override func task(for request: URLRequest, using session: URLSession) -> URLSessionTask {
+ let copiedRequest = request
+ return session.dataTask(with: copiedRequest)
+ }
+
+ /// Called to update the `downloadProgress` of the instance.
+ func updateDownloadProgress() {
+ let totalBytesReceived = Int64(data?.count ?? 0)
+ let totalBytesExpected = task?.response?.expectedContentLength ?? NSURLSessionTransferSizeUnknown
+
+ downloadProgress.totalUnitCount = totalBytesExpected
+ downloadProgress.completedUnitCount = totalBytesReceived
+
+ downloadProgressHandler?.queue.async { self.downloadProgressHandler?.handler(self.downloadProgress) }
+ }
+
+ /// Validates the request, using the specified closure.
+ ///
+ /// - Note: If validation fails, subsequent calls to response handlers will have an associated error.
+ ///
+ /// - Parameter validation: `Validation` closure used to validate the response.
+ ///
+ /// - Returns: The instance.
+ @discardableResult
+ public func validate(_ validation: @escaping Validation) -> Self {
+ let validator: () -> Void = { [unowned self] in
+ guard error == nil, let response else { return }
+
+ let result = validation(request, response, data)
+
+ if case let .failure(error) = result { self.error = error.asAFError(or: .responseValidationFailed(reason: .customValidationFailed(error: error))) }
+
+ eventMonitor?.request(self,
+ didValidateRequest: request,
+ response: response,
+ data: data,
+ withResult: result)
+ }
+
+ validators.write { $0.append(validator) }
+
+ return self
+ }
+
+ /// Sets a closure called whenever the `DataRequest` produces an `HTTPURLResponse` and providing a completion
+ /// handler to return a `ResponseDisposition` value.
+ ///
+ /// - Parameters:
+ /// - queue: `DispatchQueue` on which the closure will be called. `.main` by default.
+ /// - handler: Closure called when the instance produces an `HTTPURLResponse`. The `completionHandler` provided
+ /// MUST be called, otherwise the request will never complete.
+ ///
+ /// - Returns: The instance.
+ @_disfavoredOverload
+ @discardableResult
+ public func onHTTPResponse(
+ on queue: DispatchQueue = .main,
+ perform handler: @escaping (_ response: HTTPURLResponse,
+ _ completionHandler: @escaping (ResponseDisposition) -> Void) -> Void
+ ) -> Self {
+ dataMutableState.write { mutableState in
+ mutableState.httpResponseHandler = (queue, handler)
+ }
+
+ return self
+ }
+
+ /// Sets a closure called whenever the `DataRequest` produces an `HTTPURLResponse`.
+ ///
+ /// - Parameters:
+ /// - queue: `DispatchQueue` on which the closure will be called. `.main` by default.
+ /// - handler: Closure called when the instance produces an `HTTPURLResponse`.
+ ///
+ /// - Returns: The instance.
+ @discardableResult
+ public func onHTTPResponse(on queue: DispatchQueue = .main,
+ perform handler: @escaping (HTTPURLResponse) -> Void) -> Self {
+ onHTTPResponse(on: queue) { response, completionHandler in
+ handler(response)
+ completionHandler(.allow)
+ }
+
+ return self
+ }
+
+ // MARK: Response Serialization
+
+ /// Adds a handler to be called once the request has finished.
+ ///
+ /// - Parameters:
+ /// - queue: The queue on which the completion handler is dispatched. `.main` by default.
+ /// - completionHandler: The code to be executed once the request has finished.
+ ///
+ /// - Returns: The request.
+ @discardableResult
+ public func response(queue: DispatchQueue = .main, completionHandler: @escaping (AFDataResponse) -> Void) -> Self {
+ appendResponseSerializer {
+ // Start work that should be on the serialization queue.
+ let result = AFResult(value: self.data, error: self.error)
+ // End work that should be on the serialization queue.
+
+ self.underlyingQueue.async {
+ let response = DataResponse(request: self.request,
+ response: self.response,
+ data: self.data,
+ metrics: self.metrics,
+ serializationDuration: 0,
+ result: result)
+
+ self.eventMonitor?.request(self, didParseResponse: response)
+
+ self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
+ }
+ }
+
+ return self
+ }
+
+ private func _response(queue: DispatchQueue = .main,
+ responseSerializer: Serializer,
+ completionHandler: @escaping (AFDataResponse) -> Void)
+ -> Self {
+ appendResponseSerializer {
+ // Start work that should be on the serialization queue.
+ let start = ProcessInfo.processInfo.systemUptime
+ let result: AFResult = Result {
+ try responseSerializer.serialize(request: self.request,
+ response: self.response,
+ data: self.data,
+ error: self.error)
+ }.mapError { error in
+ error.asAFError(or: .responseSerializationFailed(reason: .customSerializationFailed(error: error)))
+ }
+
+ let end = ProcessInfo.processInfo.systemUptime
+ // End work that should be on the serialization queue.
+
+ self.underlyingQueue.async {
+ let response = DataResponse(request: self.request,
+ response: self.response,
+ data: self.data,
+ metrics: self.metrics,
+ serializationDuration: end - start,
+ result: result)
+
+ self.eventMonitor?.request(self, didParseResponse: response)
+
+ guard !self.isCancelled, let serializerError = result.failure, let delegate = self.delegate else {
+ self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
+ return
+ }
+
+ delegate.retryResult(for: self, dueTo: serializerError) { retryResult in
+ var didComplete: (() -> Void)?
+
+ defer {
+ if let didComplete {
+ self.responseSerializerDidComplete { queue.async { didComplete() } }
+ }
+ }
+
+ switch retryResult {
+ case .doNotRetry:
+ didComplete = { completionHandler(response) }
+
+ case let .doNotRetryWithError(retryError):
+ let result: AFResult = .failure(retryError.asAFError(orFailWith: "Received retryError was not already AFError"))
+
+ let response = DataResponse(request: self.request,
+ response: self.response,
+ data: self.data,
+ metrics: self.metrics,
+ serializationDuration: end - start,
+ result: result)
+
+ didComplete = { completionHandler(response) }
+
+ case .retry, .retryWithDelay:
+ delegate.retryRequest(self, withDelay: retryResult.delay)
+ }
+ }
+ }
+ }
+
+ return self
+ }
+
+ /// Adds a handler to be called once the request has finished.
+ ///
+ /// - Parameters:
+ /// - queue: The queue on which the completion handler is dispatched. `.main` by default
+ /// - responseSerializer: The response serializer responsible for serializing the request, response, and data.
+ /// - completionHandler: The code to be executed once the request has finished.
+ ///
+ /// - Returns: The request.
+ @discardableResult
+ public func response(queue: DispatchQueue = .main,
+ responseSerializer: Serializer,
+ completionHandler: @escaping (AFDataResponse) -> Void)
+ -> Self {
+ _response(queue: queue, responseSerializer: responseSerializer, completionHandler: completionHandler)
+ }
+
+ /// Adds a handler to be called once the request has finished.
+ ///
+ /// - Parameters:
+ /// - queue: The queue on which the completion handler is dispatched. `.main` by default
+ /// - responseSerializer: The response serializer responsible for serializing the request, response, and data.
+ /// - completionHandler: The code to be executed once the request has finished.
+ ///
+ /// - Returns: The request.
+ @discardableResult
+ public func response(queue: DispatchQueue = .main,
+ responseSerializer: Serializer,
+ completionHandler: @escaping (AFDataResponse) -> Void)
+ -> Self {
+ _response(queue: queue, responseSerializer: responseSerializer, completionHandler: completionHandler)
+ }
+
+ /// Adds a handler using a `DataResponseSerializer` to be called once the request has finished.
+ ///
+ /// - Parameters:
+ /// - queue: The queue on which the completion handler is called. `.main` by default.
+ /// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the
+ /// `completionHandler`. `PassthroughPreprocessor()` by default.
+ /// - emptyResponseCodes: HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
+ /// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
+ /// - completionHandler: A closure to be executed once the request has finished.
+ ///
+ /// - Returns: The request.
+ @discardableResult
+ public func responseData(queue: DispatchQueue = .main,
+ dataPreprocessor: DataPreprocessor = DataResponseSerializer.defaultDataPreprocessor,
+ emptyResponseCodes: Set = DataResponseSerializer.defaultEmptyResponseCodes,
+ emptyRequestMethods: Set = DataResponseSerializer.defaultEmptyRequestMethods,
+ completionHandler: @escaping (AFDataResponse) -> Void) -> Self {
+ response(queue: queue,
+ responseSerializer: DataResponseSerializer(dataPreprocessor: dataPreprocessor,
+ emptyResponseCodes: emptyResponseCodes,
+ emptyRequestMethods: emptyRequestMethods),
+ completionHandler: completionHandler)
+ }
+
+ /// Adds a handler using a `StringResponseSerializer` to be called once the request has finished.
+ ///
+ /// - Parameters:
+ /// - queue: The queue on which the completion handler is dispatched. `.main` by default.
+ /// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the
+ /// `completionHandler`. `PassthroughPreprocessor()` by default.
+ /// - encoding: The string encoding. Defaults to `nil`, in which case the encoding will be determined
+ /// from the server response, falling back to the default HTTP character set, `ISO-8859-1`.
+ /// - emptyResponseCodes: HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
+ /// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
+ /// - completionHandler: A closure to be executed once the request has finished.
+ ///
+ /// - Returns: The request.
+ @discardableResult
+ public func responseString(queue: DispatchQueue = .main,
+ dataPreprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,
+ encoding: String.Encoding? = nil,
+ emptyResponseCodes: Set = StringResponseSerializer.defaultEmptyResponseCodes,
+ emptyRequestMethods: Set = StringResponseSerializer.defaultEmptyRequestMethods,
+ completionHandler: @escaping (AFDataResponse) -> Void) -> Self {
+ response(queue: queue,
+ responseSerializer: StringResponseSerializer(dataPreprocessor: dataPreprocessor,
+ encoding: encoding,
+ emptyResponseCodes: emptyResponseCodes,
+ emptyRequestMethods: emptyRequestMethods),
+ completionHandler: completionHandler)
+ }
+
+ /// Adds a handler using a `JSONResponseSerializer` to be called once the request has finished.
+ ///
+ /// - Parameters:
+ /// - queue: The queue on which the completion handler is dispatched. `.main` by default.
+ /// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the
+ /// `completionHandler`. `PassthroughPreprocessor()` by default.
+ /// - emptyResponseCodes: HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
+ /// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
+ /// - options: `JSONSerialization.ReadingOptions` used when parsing the response. `.allowFragments`
+ /// by default.
+ /// - completionHandler: A closure to be executed once the request has finished.
+ ///
+ /// - Returns: The request.
+ @available(*, deprecated, message: "responseJSON deprecated and will be removed in Alamofire 6. Use responseDecodable instead.")
+ @discardableResult
+ public func responseJSON(queue: DispatchQueue = .main,
+ dataPreprocessor: DataPreprocessor = JSONResponseSerializer.defaultDataPreprocessor,
+ emptyResponseCodes: Set = JSONResponseSerializer.defaultEmptyResponseCodes,
+ emptyRequestMethods: Set = JSONResponseSerializer.defaultEmptyRequestMethods,
+ options: JSONSerialization.ReadingOptions = .allowFragments,
+ completionHandler: @escaping (AFDataResponse) -> Void) -> Self {
+ response(queue: queue,
+ responseSerializer: JSONResponseSerializer(dataPreprocessor: dataPreprocessor,
+ emptyResponseCodes: emptyResponseCodes,
+ emptyRequestMethods: emptyRequestMethods,
+ options: options),
+ completionHandler: completionHandler)
+ }
+
+ /// Adds a handler using a `DecodableResponseSerializer` to be called once the request has finished.
+ ///
+ /// - Parameters:
+ /// - type: `Decodable` type to decode from response data.
+ /// - queue: The queue on which the completion handler is dispatched. `.main` by default.
+ /// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the
+ /// `completionHandler`. `PassthroughPreprocessor()` by default.
+ /// - decoder: `DataDecoder` to use to decode the response. `JSONDecoder()` by default.
+ /// - emptyResponseCodes: HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
+ /// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
+ /// - completionHandler: A closure to be executed once the request has finished.
+ ///
+ /// - Returns: The request.
+ @discardableResult
+ public func responseDecodable(of type: T.Type = T.self,
+ queue: DispatchQueue = .main,
+ dataPreprocessor: DataPreprocessor = DecodableResponseSerializer.defaultDataPreprocessor,
+ decoder: DataDecoder = JSONDecoder(),
+ emptyResponseCodes: Set = DecodableResponseSerializer.defaultEmptyResponseCodes,
+ emptyRequestMethods: Set = DecodableResponseSerializer.defaultEmptyRequestMethods,
+ completionHandler: @escaping (AFDataResponse) -> Void) -> Self {
+ response(queue: queue,
+ responseSerializer: DecodableResponseSerializer(dataPreprocessor: dataPreprocessor,
+ decoder: decoder,
+ emptyResponseCodes: emptyResponseCodes,
+ emptyRequestMethods: emptyRequestMethods),
+ completionHandler: completionHandler)
+ }
+}
diff --git a/ChatBot/Pods/Alamofire/Source/Core/DataStreamRequest.swift b/ChatBot/Pods/Alamofire/Source/Core/DataStreamRequest.swift
new file mode 100644
index 00000000..fd11ca00
--- /dev/null
+++ b/ChatBot/Pods/Alamofire/Source/Core/DataStreamRequest.swift
@@ -0,0 +1,584 @@
+//
+// DataStreamRequest.swift
+//
+// Copyright (c) 2014-2024 Alamofire Software Foundation (http://alamofire.org/)
+//
+// 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 Foundation
+
+/// `Request` subclass which streams HTTP response `Data` through a `Handler` closure.
+public final class DataStreamRequest: Request {
+ /// Closure type handling `DataStreamRequest.Stream` values.
+ public typealias Handler = (Stream) throws -> Void
+
+ /// Type encapsulating an `Event` as it flows through the stream, as well as a `CancellationToken` which can be used
+ /// to stop the stream at any time.
+ public struct Stream {
+ /// Latest `Event` from the stream.
+ public let event: Event
+ /// Token used to cancel the stream.
+ public let token: CancellationToken
+
+ /// Cancel the ongoing stream by canceling the underlying `DataStreamRequest`.
+ public func cancel() {
+ token.cancel()
+ }
+ }
+
+ /// Type representing an event flowing through the stream. Contains either the `Result` of processing streamed
+ /// `Data` or the completion of the stream.
+ public enum Event {
+ /// Output produced every time the instance receives additional `Data`. The associated value contains the
+ /// `Result` of processing the incoming `Data`.
+ case stream(Result)
+ /// Output produced when the instance has completed, whether due to stream end, cancellation, or an error.
+ /// Associated `Completion` value contains the final state.
+ case complete(Completion)
+ }
+
+ /// Value containing the state of a `DataStreamRequest` when the stream was completed.
+ public struct Completion {
+ /// Last `URLRequest` issued by the instance.
+ public let request: URLRequest?
+ /// Last `HTTPURLResponse` received by the instance.
+ public let response: HTTPURLResponse?
+ /// Last `URLSessionTaskMetrics` produced for the instance.
+ public let metrics: URLSessionTaskMetrics?
+ /// `AFError` produced for the instance, if any.
+ public let error: AFError?
+ }
+
+ /// Type used to cancel an ongoing stream.
+ public struct CancellationToken {
+ weak var request: DataStreamRequest?
+
+ init(_ request: DataStreamRequest) {
+ self.request = request
+ }
+
+ /// Cancel the ongoing stream by canceling the underlying `DataStreamRequest`.
+ public func cancel() {
+ request?.cancel()
+ }
+ }
+
+ /// `URLRequestConvertible` value used to create `URLRequest`s for this instance.
+ public let convertible: URLRequestConvertible
+ /// Whether or not the instance will be cancelled if stream parsing encounters an error.
+ public let automaticallyCancelOnStreamError: Bool
+
+ /// Internal mutable state specific to this type.
+ struct StreamMutableState {
+ /// `OutputStream` bound to the `InputStream` produced by `asInputStream`, if it has been called.
+ var outputStream: OutputStream?
+ /// Stream closures called as `Data` is received.
+ var streams: [(_ data: Data) -> Void] = []
+ /// Number of currently executing streams. Used to ensure completions are only fired after all streams are
+ /// enqueued.
+ var numberOfExecutingStreams = 0
+ /// Completion calls enqueued while streams are still executing.
+ var enqueuedCompletionEvents: [() -> Void] = []
+ /// Handler for any `HTTPURLResponse`s received.
+ var httpResponseHandler: (queue: DispatchQueue,
+ handler: (_ response: HTTPURLResponse,
+ _ completionHandler: @escaping (ResponseDisposition) -> Void) -> Void)?
+ }
+
+ let streamMutableState = Protected(StreamMutableState())
+
+ /// Creates a `DataStreamRequest` using the provided parameters.
+ ///
+ /// - Parameters:
+ /// - id: `UUID` used for the `Hashable` and `Equatable` implementations. `UUID()`
+ /// by default.
+ /// - convertible: `URLRequestConvertible` value used to create `URLRequest`s for this
+ /// instance.
+ /// - automaticallyCancelOnStreamError: `Bool` indicating whether the instance will be cancelled when an `Error`
+ /// is thrown while serializing stream `Data`.
+ /// - underlyingQueue: `DispatchQueue` on which all internal `Request` work is performed.
+ /// - serializationQueue: `DispatchQueue` on which all serialization work is performed. By default
+ /// targets
+ /// `underlyingQueue`, but can be passed another queue from a `Session`.
+ /// - eventMonitor: `EventMonitor` called for event callbacks from internal `Request` actions.
+ /// - interceptor: `RequestInterceptor` used throughout the request lifecycle.
+ /// - delegate: `RequestDelegate` that provides an interface to actions not performed by
+ /// the `Request`.
+ init(id: UUID = UUID(),
+ convertible: URLRequestConvertible,
+ automaticallyCancelOnStreamError: Bool,
+ underlyingQueue: DispatchQueue,
+ serializationQueue: DispatchQueue,
+ eventMonitor: EventMonitor?,
+ interceptor: RequestInterceptor?,
+ delegate: RequestDelegate) {
+ self.convertible = convertible
+ self.automaticallyCancelOnStreamError = automaticallyCancelOnStreamError
+
+ super.init(id: id,
+ underlyingQueue: underlyingQueue,
+ serializationQueue: serializationQueue,
+ eventMonitor: eventMonitor,
+ interceptor: interceptor,
+ delegate: delegate)
+ }
+
+ override func task(for request: URLRequest, using session: URLSession) -> URLSessionTask {
+ let copiedRequest = request
+ return session.dataTask(with: copiedRequest)
+ }
+
+ override func finish(error: AFError? = nil) {
+ streamMutableState.write { state in
+ state.outputStream?.close()
+ }
+
+ super.finish(error: error)
+ }
+
+ func didReceive(data: Data) {
+ streamMutableState.write { state in
+ #if !canImport(FoundationNetworking) // If we not using swift-corelibs-foundation.
+ if let stream = state.outputStream {
+ underlyingQueue.async {
+ var bytes = Array(data)
+ stream.write(&bytes, maxLength: bytes.count)
+ }
+ }
+ #endif
+ state.numberOfExecutingStreams += state.streams.count
+ let localState = state
+ underlyingQueue.async { localState.streams.forEach { $0(data) } }
+ }
+ }
+
+ func didReceiveResponse(_ response: HTTPURLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
+ streamMutableState.read { dataMutableState in
+ guard let httpResponseHandler = dataMutableState.httpResponseHandler else {
+ underlyingQueue.async { completionHandler(.allow) }
+ return
+ }
+
+ httpResponseHandler.queue.async {
+ httpResponseHandler.handler(response) { disposition in
+ if disposition == .cancel {
+ self.mutableState.write { mutableState in
+ mutableState.state = .cancelled
+ mutableState.error = mutableState.error ?? AFError.explicitlyCancelled
+ }
+ }
+
+ self.underlyingQueue.async {
+ completionHandler(disposition.sessionDisposition)
+ }
+ }
+ }
+ }
+ }
+
+ /// Validates the `URLRequest` and `HTTPURLResponse` received for the instance using the provided `Validation` closure.
+ ///
+ /// - Parameter validation: `Validation` closure used to validate the request and response.
+ ///
+ /// - Returns: The `DataStreamRequest`.
+ @discardableResult
+ public func validate(_ validation: @escaping Validation) -> Self {
+ let validator: () -> Void = { [unowned self] in
+ guard error == nil, let response else { return }
+
+ let result = validation(request, response)
+
+ if case let .failure(error) = result {
+ self.error = error.asAFError(or: .responseValidationFailed(reason: .customValidationFailed(error: error)))
+ }
+
+ eventMonitor?.request(self,
+ didValidateRequest: request,
+ response: response,
+ withResult: result)
+ }
+
+ validators.write { $0.append(validator) }
+
+ return self
+ }
+
+ #if !canImport(FoundationNetworking) // If we not using swift-corelibs-foundation.
+ /// Produces an `InputStream` that receives the `Data` received by the instance.
+ ///
+ /// - Note: The `InputStream` produced by this method must have `open()` called before being able to read `Data`.
+ /// Additionally, this method will automatically call `resume()` on the instance, regardless of whether or
+ /// not the creating session has `startRequestsImmediately` set to `true`.
+ ///
+ /// - Parameter bufferSize: Size, in bytes, of the buffer between the `OutputStream` and `InputStream`.
+ ///
+ /// - Returns: The `InputStream` bound to the internal `OutboundStream`.
+ public func asInputStream(bufferSize: Int = 1024) -> InputStream? {
+ defer { resume() }
+
+ var inputStream: InputStream?
+ streamMutableState.write { state in
+ Foundation.Stream.getBoundStreams(withBufferSize: bufferSize,
+ inputStream: &inputStream,
+ outputStream: &state.outputStream)
+ state.outputStream?.open()
+ }
+
+ return inputStream
+ }
+ #endif
+
+ /// Sets a closure called whenever the `DataRequest` produces an `HTTPURLResponse` and providing a completion
+ /// handler to return a `ResponseDisposition` value.
+ ///
+ /// - Parameters:
+ /// - queue: `DispatchQueue` on which the closure will be called. `.main` by default.
+ /// - handler: Closure called when the instance produces an `HTTPURLResponse`. The `completionHandler` provided
+ /// MUST be called, otherwise the request will never complete.
+ ///
+ /// - Returns: The instance.
+ @_disfavoredOverload
+ @discardableResult
+ public func onHTTPResponse(
+ on queue: DispatchQueue = .main,
+ perform handler: @escaping (_ response: HTTPURLResponse,
+ _ completionHandler: @escaping (ResponseDisposition) -> Void) -> Void
+ ) -> Self {
+ streamMutableState.write { mutableState in
+ mutableState.httpResponseHandler = (queue, handler)
+ }
+
+ return self
+ }
+
+ /// Sets a closure called whenever the `DataRequest` produces an `HTTPURLResponse`.
+ ///
+ /// - Parameters:
+ /// - queue: `DispatchQueue` on which the closure will be called. `.main` by default.
+ /// - handler: Closure called when the instance produces an `HTTPURLResponse`.
+ ///
+ /// - Returns: The instance.
+ @discardableResult
+ public func onHTTPResponse(on queue: DispatchQueue = .main,
+ perform handler: @escaping (HTTPURLResponse) -> Void) -> Self {
+ onHTTPResponse(on: queue) { response, completionHandler in
+ handler(response)
+ completionHandler(.allow)
+ }
+
+ return self
+ }
+
+ func capturingError(from closure: () throws -> Void) {
+ do {
+ try closure()
+ } catch {
+ self.error = error.asAFError(or: .responseSerializationFailed(reason: .customSerializationFailed(error: error)))
+ cancel()
+ }
+ }
+
+ func appendStreamCompletion(on queue: DispatchQueue,
+ stream: @escaping Handler) {
+ appendResponseSerializer {
+ self.underlyingQueue.async {
+ self.responseSerializerDidComplete {
+ self.streamMutableState.write { state in
+ guard state.numberOfExecutingStreams == 0 else {
+ state.enqueuedCompletionEvents.append {
+ self.enqueueCompletion(on: queue, stream: stream)
+ }
+
+ return
+ }
+
+ self.enqueueCompletion(on: queue, stream: stream)
+ }
+ }
+ }
+ }
+ }
+
+ func enqueueCompletion(on queue: DispatchQueue,
+ stream: @escaping Handler) {
+ queue.async {
+ do {
+ let completion = Completion(request: self.request,
+ response: self.response,
+ metrics: self.metrics,
+ error: self.error)
+ try stream(.init(event: .complete(completion), token: .init(self)))
+ } catch {
+ // Ignore error, as errors on Completion can't be handled anyway.
+ }
+ }
+ }
+
+ // MARK: Response Serialization
+
+ /// Adds a `StreamHandler` which performs no parsing on incoming `Data`.
+ ///
+ /// - Parameters:
+ /// - queue: `DispatchQueue` on which to perform `StreamHandler` closure.
+ /// - stream: `StreamHandler` closure called as `Data` is received. May be called multiple times.
+ ///
+ /// - Returns: The `DataStreamRequest`.
+ @discardableResult
+ public func responseStream(on queue: DispatchQueue = .main, stream: @escaping Handler) -> Self {
+ let parser = { [unowned self] (data: Data) in
+ queue.async {
+ self.capturingError {
+ try stream(.init(event: .stream(.success(data)), token: .init(self)))
+ }
+
+ self.updateAndCompleteIfPossible()
+ }
+ }
+
+ streamMutableState.write { $0.streams.append(parser) }
+ appendStreamCompletion(on: queue, stream: stream)
+
+ return self
+ }
+
+ /// Adds a `StreamHandler` which uses the provided `DataStreamSerializer` to process incoming `Data`.
+ ///
+ /// - Parameters:
+ /// - serializer: `DataStreamSerializer` used to process incoming `Data`. Its work is done on the `serializationQueue`.
+ /// - queue: `DispatchQueue` on which to perform `StreamHandler` closure.
+ /// - stream: `StreamHandler` closure called as `Data` is received. May be called multiple times.
+ ///
+ /// - Returns: The `DataStreamRequest`.
+ @discardableResult
+ public func responseStream(using serializer: Serializer,
+ on queue: DispatchQueue = .main,
+ stream: @escaping Handler) -> Self {
+ let parser = { [unowned self] (data: Data) in
+ serializationQueue.async {
+ // Start work on serialization queue.
+ let result = Result { try serializer.serialize(data) }
+ .mapError { $0.asAFError(or: .responseSerializationFailed(reason: .customSerializationFailed(error: $0))) }
+ // End work on serialization queue.
+ self.underlyingQueue.async {
+ self.eventMonitor?.request(self, didParseStream: result)
+
+ if result.isFailure, self.automaticallyCancelOnStreamError {
+ self.cancel()
+ }
+
+ queue.async {
+ self.capturingError {
+ try stream(.init(event: .stream(result), token: .init(self)))
+ }
+
+ self.updateAndCompleteIfPossible()
+ }
+ }
+ }
+ }
+
+ streamMutableState.write { $0.streams.append(parser) }
+ appendStreamCompletion(on: queue, stream: stream)
+
+ return self
+ }
+
+ /// Adds a `StreamHandler` which parses incoming `Data` as a UTF8 `String`.
+ ///
+ /// - Parameters:
+ /// - queue: `DispatchQueue` on which to perform `StreamHandler` closure.
+ /// - stream: `StreamHandler` closure called as `Data` is received. May be called multiple times.
+ ///
+ /// - Returns: The `DataStreamRequest`.
+ @discardableResult
+ public func responseStreamString(on queue: DispatchQueue = .main,
+ stream: @escaping Handler) -> Self {
+ let parser = { [unowned self] (data: Data) in
+ serializationQueue.async {
+ // Start work on serialization queue.
+ let string = String(decoding: data, as: UTF8.self)
+ // End work on serialization queue.
+ self.underlyingQueue.async {
+ self.eventMonitor?.request(self, didParseStream: .success(string))
+
+ queue.async {
+ self.capturingError {
+ try stream(.init(event: .stream(.success(string)), token: .init(self)))
+ }
+
+ self.updateAndCompleteIfPossible()
+ }
+ }
+ }
+ }
+
+ streamMutableState.write { $0.streams.append(parser) }
+ appendStreamCompletion(on: queue, stream: stream)
+
+ return self
+ }
+
+ private func updateAndCompleteIfPossible() {
+ streamMutableState.write { state in
+ state.numberOfExecutingStreams -= 1
+
+ guard state.numberOfExecutingStreams == 0, !state.enqueuedCompletionEvents.isEmpty else { return }
+
+ let completionEvents = state.enqueuedCompletionEvents
+ self.underlyingQueue.async { completionEvents.forEach { $0() } }
+ state.enqueuedCompletionEvents.removeAll()
+ }
+ }
+
+ /// Adds a `StreamHandler` which parses incoming `Data` using the provided `DataDecoder`.
+ ///
+ /// - Parameters:
+ /// - type: `Decodable` type to parse incoming `Data` into.
+ /// - queue: `DispatchQueue` on which to perform `StreamHandler` closure.
+ /// - decoder: `DataDecoder` used to decode the incoming `Data`.
+ /// - preprocessor: `DataPreprocessor` used to process the incoming `Data` before it's passed to the `decoder`.
+ /// - stream: `StreamHandler` closure called as `Data` is received. May be called multiple times.
+ ///
+ /// - Returns: The `DataStreamRequest`.
+ @discardableResult
+ public func responseStreamDecodable(of type: T.Type = T.self,
+ on queue: DispatchQueue = .main,
+ using decoder: DataDecoder = JSONDecoder(),
+ preprocessor: DataPreprocessor = PassthroughPreprocessor(),
+ stream: @escaping Handler) -> Self {
+ responseStream(using: DecodableStreamSerializer(decoder: decoder, dataPreprocessor: preprocessor),
+ stream: stream)
+ }
+}
+
+extension DataStreamRequest.Stream {
+ /// Incoming `Result` values from `Event.stream`.
+ public var result: Result? {
+ guard case let .stream(result) = event else { return nil }
+
+ return result
+ }
+
+ /// `Success` value of the instance, if any.
+ public var value: Success? {
+ guard case let .success(value) = result else { return nil }
+
+ return value
+ }
+
+ /// `Failure` value of the instance, if any.
+ public var error: Failure? {
+ guard case let .failure(error) = result else { return nil }
+
+ return error
+ }
+
+ /// `Completion` value of the instance, if any.
+ public var completion: DataStreamRequest.Completion? {
+ guard case let .complete(completion) = event else { return nil }
+
+ return completion
+ }
+}
+
+// MARK: - Serialization
+
+/// A type which can serialize incoming `Data`.
+public protocol DataStreamSerializer {
+ /// Type produced from the serialized `Data`.
+ associatedtype SerializedObject
+
+ /// Serializes incoming `Data` into a `SerializedObject` value.
+ ///
+ /// - Parameter data: `Data` to be serialized.
+ ///
+ /// - Throws: Any error produced during serialization.
+ func serialize(_ data: Data) throws -> SerializedObject
+}
+
+/// `DataStreamSerializer` which uses the provided `DataPreprocessor` and `DataDecoder` to serialize the incoming `Data`.
+public struct DecodableStreamSerializer: DataStreamSerializer {
+ /// `DataDecoder` used to decode incoming `Data`.
+ public let decoder: DataDecoder
+ /// `DataPreprocessor` incoming `Data` is passed through before being passed to the `DataDecoder`.
+ public let dataPreprocessor: DataPreprocessor
+
+ /// Creates an instance with the provided `DataDecoder` and `DataPreprocessor`.
+ /// - Parameters:
+ /// - decoder: ` DataDecoder` used to decode incoming `Data`. `JSONDecoder()` by default.
+ /// - dataPreprocessor: `DataPreprocessor` used to process incoming `Data` before it's passed through the
+ /// `decoder`. `PassthroughPreprocessor()` by default.
+ public init(decoder: DataDecoder = JSONDecoder(), dataPreprocessor: DataPreprocessor = PassthroughPreprocessor()) {
+ self.decoder = decoder
+ self.dataPreprocessor = dataPreprocessor
+ }
+
+ public func serialize(_ data: Data) throws -> T {
+ let processedData = try dataPreprocessor.preprocess(data)
+ do {
+ return try decoder.decode(T.self, from: processedData)
+ } catch {
+ throw AFError.responseSerializationFailed(reason: .decodingFailed(error: error))
+ }
+ }
+}
+
+/// `DataStreamSerializer` which performs no serialization on incoming `Data`.
+public struct PassthroughStreamSerializer: DataStreamSerializer {
+ /// Creates an instance.
+ public init() {}
+
+ public func serialize(_ data: Data) throws -> Data { data }
+}
+
+/// `DataStreamSerializer` which serializes incoming stream `Data` into `UTF8`-decoded `String` values.
+public struct StringStreamSerializer: DataStreamSerializer {
+ /// Creates an instance.
+ public init() {}
+
+ public func serialize(_ data: Data) throws -> String {
+ String(decoding: data, as: UTF8.self)
+ }
+}
+
+extension DataStreamSerializer {
+ /// Creates a `DecodableStreamSerializer` instance with the provided `DataDecoder` and `DataPreprocessor`.
+ ///
+ /// - Parameters:
+ /// - type: `Decodable` type to decode from stream data.
+ /// - decoder: ` DataDecoder` used to decode incoming `Data`. `JSONDecoder()` by default.
+ /// - dataPreprocessor: `DataPreprocessor` used to process incoming `Data` before it's passed through the
+ /// `decoder`. `PassthroughPreprocessor()` by default.
+ public static func decodable(of type: T.Type,
+ decoder: DataDecoder = JSONDecoder(),
+ dataPreprocessor: DataPreprocessor = PassthroughPreprocessor()) -> Self where Self == DecodableStreamSerializer {
+ DecodableStreamSerializer(decoder: decoder, dataPreprocessor: dataPreprocessor)
+ }
+}
+
+extension DataStreamSerializer where Self == PassthroughStreamSerializer {
+ /// Provides a `PassthroughStreamSerializer` instance.
+ public static var passthrough: PassthroughStreamSerializer { PassthroughStreamSerializer() }
+}
+
+extension DataStreamSerializer where Self == StringStreamSerializer {
+ /// Provides a `StringStreamSerializer` instance.
+ public static var string: StringStreamSerializer { StringStreamSerializer() }
+}
diff --git a/ChatBot/Pods/Alamofire/Source/Core/DownloadRequest.swift b/ChatBot/Pods/Alamofire/Source/Core/DownloadRequest.swift
new file mode 100644
index 00000000..556c43ea
--- /dev/null
+++ b/ChatBot/Pods/Alamofire/Source/Core/DownloadRequest.swift
@@ -0,0 +1,588 @@
+//
+// DownloadRequest.swift
+//
+// Copyright (c) 2014-2024 Alamofire Software Foundation (http://alamofire.org/)
+//
+// 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 Foundation
+
+/// `Request` subclass which downloads `Data` to a file on disk using `URLSessionDownloadTask`.
+public final class DownloadRequest: Request {
+ /// A set of options to be executed prior to moving a downloaded file from the temporary `URL` to the destination
+ /// `URL`.
+ public struct Options: OptionSet {
+ /// Specifies that intermediate directories for the destination URL should be created.
+ public static let createIntermediateDirectories = Options(rawValue: 1 << 0)
+ /// Specifies that any previous file at the destination `URL` should be removed.
+ public static let removePreviousFile = Options(rawValue: 1 << 1)
+
+ public let rawValue: Int
+
+ public init(rawValue: Int) {
+ self.rawValue = rawValue
+ }
+ }
+
+ // MARK: Destination
+
+ /// A closure executed once a `DownloadRequest` has successfully completed in order to determine where to move the
+ /// temporary file written to during the download process. The closure takes two arguments: the temporary file URL
+ /// and the `HTTPURLResponse`, and returns two values: the file URL where the temporary file should be moved and
+ /// the options defining how the file should be moved.
+ ///
+ /// - Note: Downloads from a local `file://` `URL`s do not use the `Destination` closure, as those downloads do not
+ /// return an `HTTPURLResponse`. Instead the file is merely moved within the temporary directory.
+ public typealias Destination = (_ temporaryURL: URL,
+ _ response: HTTPURLResponse) -> (destinationURL: URL, options: Options)
+
+ /// Creates a download file destination closure which uses the default file manager to move the temporary file to a
+ /// file URL in the first available directory with the specified search path directory and search path domain mask.
+ ///
+ /// - Parameters:
+ /// - directory: The search path directory. `.documentDirectory` by default.
+ /// - domain: The search path domain mask. `.userDomainMask` by default.
+ /// - options: `DownloadRequest.Options` used when moving the downloaded file to its destination. None by
+ /// default.
+ /// - Returns: The `Destination` closure.
+ public class func suggestedDownloadDestination(for directory: FileManager.SearchPathDirectory = .documentDirectory,
+ in domain: FileManager.SearchPathDomainMask = .userDomainMask,
+ options: Options = []) -> Destination {
+ { temporaryURL, response in
+ let directoryURLs = FileManager.default.urls(for: directory, in: domain)
+ let url = directoryURLs.first?.appendingPathComponent(response.suggestedFilename!) ?? temporaryURL
+
+ return (url, options)
+ }
+ }
+
+ /// Default `Destination` used by Alamofire to ensure all downloads persist. This `Destination` prepends
+ /// `Alamofire_` to the automatically generated download name and moves it within the temporary directory. Files
+ /// with this destination must be additionally moved if they should survive the system reclamation of temporary
+ /// space.
+ static let defaultDestination: Destination = { url, _ in
+ (defaultDestinationURL(url), [])
+ }
+
+ /// Default `URL` creation closure. Creates a `URL` in the temporary directory with `Alamofire_` prepended to the
+ /// provided file name.
+ static let defaultDestinationURL: (URL) -> URL = { url in
+ let filename = "Alamofire_\(url.lastPathComponent)"
+ let destination = url.deletingLastPathComponent().appendingPathComponent(filename)
+
+ return destination
+ }
+
+ // MARK: Downloadable
+
+ /// Type describing the source used to create the underlying `URLSessionDownloadTask`.
+ public enum Downloadable {
+ /// Download should be started from the `URLRequest` produced by the associated `URLRequestConvertible` value.
+ case request(URLRequestConvertible)
+ /// Download should be started from the associated resume `Data` value.
+ case resumeData(Data)
+ }
+
+ // MARK: Mutable State
+
+ /// Type containing all mutable state for `DownloadRequest` instances.
+ private struct DownloadRequestMutableState {
+ /// Possible resume `Data` produced when cancelling the instance.
+ var resumeData: Data?
+ /// `URL` to which `Data` is being downloaded.
+ var fileURL: URL?
+ }
+
+ /// Protected mutable state specific to `DownloadRequest`.
+ private let mutableDownloadState = Protected(DownloadRequestMutableState())
+
+ /// If the download is resumable and is eventually cancelled or fails, this value may be used to resume the download
+ /// using the `download(resumingWith data:)` API.
+ ///
+ /// - Note: For more information about `resumeData`, see [Apple's documentation](https://developer.apple.com/documentation/foundation/urlsessiondownloadtask/1411634-cancel).
+ public var resumeData: Data? {
+ #if !canImport(FoundationNetworking) // If we not using swift-corelibs-foundation.
+ return mutableDownloadState.resumeData ?? error?.downloadResumeData
+ #else
+ return mutableDownloadState.resumeData
+ #endif
+ }
+
+ /// If the download is successful, the `URL` where the file was downloaded.
+ public var fileURL: URL? { mutableDownloadState.fileURL }
+
+ // MARK: Initial State
+
+ /// `Downloadable` value used for this instance.
+ public let downloadable: Downloadable
+ /// The `Destination` to which the downloaded file is moved.
+ let destination: Destination
+
+ /// Creates a `DownloadRequest` using the provided parameters.
+ ///
+ /// - Parameters:
+ /// - id: `UUID` used for the `Hashable` and `Equatable` implementations. `UUID()` by default.
+ /// - downloadable: `Downloadable` value used to create `URLSessionDownloadTasks` for the instance.
+ /// - underlyingQueue: `DispatchQueue` on which all internal `Request` work is performed.
+ /// - serializationQueue: `DispatchQueue` on which all serialization work is performed. By default targets
+ /// `underlyingQueue`, but can be passed another queue from a `Session`.
+ /// - eventMonitor: `EventMonitor` called for event callbacks from internal `Request` actions.
+ /// - interceptor: `RequestInterceptor` used throughout the request lifecycle.
+ /// - delegate: `RequestDelegate` that provides an interface to actions not performed by the `Request`
+ /// - destination: `Destination` closure used to move the downloaded file to its final location.
+ init(id: UUID = UUID(),
+ downloadable: Downloadable,
+ underlyingQueue: DispatchQueue,
+ serializationQueue: DispatchQueue,
+ eventMonitor: EventMonitor?,
+ interceptor: RequestInterceptor?,
+ delegate: RequestDelegate,
+ destination: @escaping Destination) {
+ self.downloadable = downloadable
+ self.destination = destination
+
+ super.init(id: id,
+ underlyingQueue: underlyingQueue,
+ serializationQueue: serializationQueue,
+ eventMonitor: eventMonitor,
+ interceptor: interceptor,
+ delegate: delegate)
+ }
+
+ override func reset() {
+ super.reset()
+
+ mutableDownloadState.write {
+ $0.resumeData = nil
+ $0.fileURL = nil
+ }
+ }
+
+ /// Called when a download has finished.
+ ///
+ /// - Parameters:
+ /// - task: `URLSessionTask` that finished the download.
+ /// - result: `Result` of the automatic move to `destination`.
+ func didFinishDownloading(using task: URLSessionTask, with result: Result) {
+ eventMonitor?.request(self, didFinishDownloadingUsing: task, with: result)
+
+ switch result {
+ case let .success(url): mutableDownloadState.fileURL = url
+ case let .failure(error): self.error = error
+ }
+ }
+
+ /// Updates the `downloadProgress` using the provided values.
+ ///
+ /// - Parameters:
+ /// - bytesWritten: Total bytes written so far.
+ /// - totalBytesExpectedToWrite: Total bytes expected to write.
+ func updateDownloadProgress(bytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
+ downloadProgress.totalUnitCount = totalBytesExpectedToWrite
+ downloadProgress.completedUnitCount += bytesWritten
+
+ downloadProgressHandler?.queue.async { self.downloadProgressHandler?.handler(self.downloadProgress) }
+ }
+
+ override func task(for request: URLRequest, using session: URLSession) -> URLSessionTask {
+ session.downloadTask(with: request)
+ }
+
+ /// Creates a `URLSessionTask` from the provided resume data.
+ ///
+ /// - Parameters:
+ /// - data: `Data` used to resume the download.
+ /// - session: `URLSession` used to create the `URLSessionTask`.
+ ///
+ /// - Returns: The `URLSessionTask` created.
+ public func task(forResumeData data: Data, using session: URLSession) -> URLSessionTask {
+ session.downloadTask(withResumeData: data)
+ }
+
+ /// Cancels the instance. Once cancelled, a `DownloadRequest` can no longer be resumed or suspended.
+ ///
+ /// - Note: This method will NOT produce resume data. If you wish to cancel and produce resume data, use
+ /// `cancel(producingResumeData:)` or `cancel(byProducingResumeData:)`.
+ ///
+ /// - Returns: The instance.
+ @discardableResult
+ override public func cancel() -> Self {
+ cancel(producingResumeData: false)
+ }
+
+ /// Cancels the instance, optionally producing resume data. Once cancelled, a `DownloadRequest` can no longer be
+ /// resumed or suspended.
+ ///
+ /// - Note: If `producingResumeData` is `true`, the `resumeData` property will be populated with any resume data, if
+ /// available.
+ ///
+ /// - Returns: The instance.
+ @discardableResult
+ public func cancel(producingResumeData shouldProduceResumeData: Bool) -> Self {
+ cancel(optionallyProducingResumeData: shouldProduceResumeData ? { _ in } : nil)
+ }
+
+ /// Cancels the instance while producing resume data. Once cancelled, a `DownloadRequest` can no longer be resumed
+ /// or suspended.
+ ///
+ /// - Note: The resume data passed to the completion handler will also be available on the instance's `resumeData`
+ /// property.
+ ///
+ /// - Parameter completionHandler: The completion handler that is called when the download has been successfully
+ /// cancelled. It is not guaranteed to be called on a particular queue, so you may
+ /// want use an appropriate queue to perform your work.
+ ///
+ /// - Returns: The instance.
+ @discardableResult
+ public func cancel(byProducingResumeData completionHandler: @escaping (_ data: Data?) -> Void) -> Self {
+ cancel(optionallyProducingResumeData: completionHandler)
+ }
+
+ /// Internal implementation of cancellation that optionally takes a resume data handler. If no handler is passed,
+ /// cancellation is performed without producing resume data.
+ ///
+ /// - Parameter completionHandler: Optional resume data handler.
+ ///
+ /// - Returns: The instance.
+ private func cancel(optionallyProducingResumeData completionHandler: ((_ resumeData: Data?) -> Void)?) -> Self {
+ mutableState.write { mutableState in
+ guard mutableState.state.canTransitionTo(.cancelled) else { return }
+
+ mutableState.state = .cancelled
+
+ underlyingQueue.async { self.didCancel() }
+
+ guard let task = mutableState.tasks.last as? URLSessionDownloadTask, task.state != .completed else {
+ underlyingQueue.async { self.finish() }
+ return
+ }
+
+ if let completionHandler {
+ // Resume to ensure metrics are gathered.
+ task.resume()
+ task.cancel { resumeData in
+ self.mutableDownloadState.resumeData = resumeData
+ self.underlyingQueue.async { self.didCancelTask(task) }
+ completionHandler(resumeData)
+ }
+ } else {
+ // Resume to ensure metrics are gathered.
+ task.resume()
+ task.cancel()
+ self.underlyingQueue.async { self.didCancelTask(task) }
+ }
+ }
+
+ return self
+ }
+
+ /// Validates the request, using the specified closure.
+ ///
+ /// - Note: If validation fails, subsequent calls to response handlers will have an associated error.
+ ///
+ /// - Parameter validation: `Validation` closure to validate the response.
+ ///
+ /// - Returns: The instance.
+ @discardableResult
+ public func validate(_ validation: @escaping Validation) -> Self {
+ let validator: () -> Void = { [unowned self] in
+ guard error == nil, let response else { return }
+
+ let result = validation(request, response, fileURL)
+
+ if case let .failure(error) = result {
+ self.error = error.asAFError(or: .responseValidationFailed(reason: .customValidationFailed(error: error)))
+ }
+
+ eventMonitor?.request(self,
+ didValidateRequest: request,
+ response: response,
+ fileURL: fileURL,
+ withResult: result)
+ }
+
+ validators.write { $0.append(validator) }
+
+ return self
+ }
+
+ // MARK: - Response Serialization
+
+ /// Adds a handler to be called once the request has finished.
+ ///
+ /// - Parameters:
+ /// - queue: The queue on which the completion handler is dispatched. `.main` by default.
+ /// - completionHandler: The code to be executed once the request has finished.
+ ///
+ /// - Returns: The request.
+ @discardableResult
+ public func response(queue: DispatchQueue = .main,
+ completionHandler: @escaping (AFDownloadResponse) -> Void)
+ -> Self {
+ appendResponseSerializer {
+ // Start work that should be on the serialization queue.
+ let result = AFResult(value: self.fileURL, error: self.error)
+ // End work that should be on the serialization queue.
+
+ self.underlyingQueue.async {
+ let response = DownloadResponse(request: self.request,
+ response: self.response,
+ fileURL: self.fileURL,
+ resumeData: self.resumeData,
+ metrics: self.metrics,
+ serializationDuration: 0,
+ result: result)
+
+ self.eventMonitor?.request(self, didParseResponse: response)
+
+ self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
+ }
+ }
+
+ return self
+ }
+
+ private func _response(queue: DispatchQueue = .main,
+ responseSerializer: Serializer,
+ completionHandler: @escaping (AFDownloadResponse) -> Void)
+ -> Self {
+ appendResponseSerializer {
+ // Start work that should be on the serialization queue.
+ let start = ProcessInfo.processInfo.systemUptime
+ let result: AFResult = Result {
+ try responseSerializer.serializeDownload(request: self.request,
+ response: self.response,
+ fileURL: self.fileURL,
+ error: self.error)
+ }.mapError { error in
+ error.asAFError(or: .responseSerializationFailed(reason: .customSerializationFailed(error: error)))
+ }
+ let end = ProcessInfo.processInfo.systemUptime
+ // End work that should be on the serialization queue.
+
+ self.underlyingQueue.async {
+ let response = DownloadResponse(request: self.request,
+ response: self.response,
+ fileURL: self.fileURL,
+ resumeData: self.resumeData,
+ metrics: self.metrics,
+ serializationDuration: end - start,
+ result: result)
+
+ self.eventMonitor?.request(self, didParseResponse: response)
+
+ guard let serializerError = result.failure, let delegate = self.delegate else {
+ self.responseSerializerDidComplete { queue.async { completionHandler(response) } }
+ return
+ }
+
+ delegate.retryResult(for: self, dueTo: serializerError) { retryResult in
+ var didComplete: (() -> Void)?
+
+ defer {
+ if let didComplete {
+ self.responseSerializerDidComplete { queue.async { didComplete() } }
+ }
+ }
+
+ switch retryResult {
+ case .doNotRetry:
+ didComplete = { completionHandler(response) }
+
+ case let .doNotRetryWithError(retryError):
+ let result: AFResult = .failure(retryError.asAFError(orFailWith: "Received retryError was not already AFError"))
+
+ let response = DownloadResponse(request: self.request,
+ response: self.response,
+ fileURL: self.fileURL,
+ resumeData: self.resumeData,
+ metrics: self.metrics,
+ serializationDuration: end - start,
+ result: result)
+
+ didComplete = { completionHandler(response) }
+
+ case .retry, .retryWithDelay:
+ delegate.retryRequest(self, withDelay: retryResult.delay)
+ }
+ }
+ }
+ }
+
+ return self
+ }
+
+ /// Adds a handler to be called once the request has finished.
+ ///
+ /// - Parameters:
+ /// - queue: The queue on which the completion handler is dispatched. `.main` by default.
+ /// - responseSerializer: The response serializer responsible for serializing the request, response, and data
+ /// contained in the destination `URL`.
+ /// - completionHandler: The code to be executed once the request has finished.
+ ///
+ /// - Returns: The request.
+ @discardableResult
+ public func response(queue: DispatchQueue = .main,
+ responseSerializer: Serializer,
+ completionHandler: @escaping (AFDownloadResponse) -> Void)
+ -> Self {
+ _response(queue: queue, responseSerializer: responseSerializer, completionHandler: completionHandler)
+ }
+
+ /// Adds a handler to be called once the request has finished.
+ ///
+ /// - Parameters:
+ /// - queue: The queue on which the completion handler is dispatched. `.main` by default.
+ /// - responseSerializer: The response serializer responsible for serializing the request, response, and data
+ /// contained in the destination `URL`.
+ /// - completionHandler: The code to be executed once the request has finished.
+ ///
+ /// - Returns: The request.
+ @discardableResult
+ public func response(queue: DispatchQueue = .main,
+ responseSerializer: Serializer,
+ completionHandler: @escaping (AFDownloadResponse) -> Void)
+ -> Self {
+ _response(queue: queue, responseSerializer: responseSerializer, completionHandler: completionHandler)
+ }
+
+ /// Adds a handler using a `URLResponseSerializer` to be called once the request is finished.
+ ///
+ /// - Parameters:
+ /// - queue: The queue on which the completion handler is called. `.main` by default.
+ /// - completionHandler: A closure to be executed once the request has finished.
+ ///
+ /// - Returns: The request.
+ @discardableResult
+ public func responseURL(queue: DispatchQueue = .main,
+ completionHandler: @escaping (AFDownloadResponse) -> Void) -> Self {
+ response(queue: queue, responseSerializer: URLResponseSerializer(), completionHandler: completionHandler)
+ }
+
+ /// Adds a handler using a `DataResponseSerializer` to be called once the request has finished.
+ ///
+ /// - Parameters:
+ /// - queue: The queue on which the completion handler is called. `.main` by default.
+ /// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the
+ /// `completionHandler`. `PassthroughPreprocessor()` by default.
+ /// - emptyResponseCodes: HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
+ /// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
+ /// - completionHandler: A closure to be executed once the request has finished.
+ ///
+ /// - Returns: The request.
+ @discardableResult
+ public func responseData(queue: DispatchQueue = .main,
+ dataPreprocessor: DataPreprocessor = DataResponseSerializer.defaultDataPreprocessor,
+ emptyResponseCodes: Set = DataResponseSerializer.defaultEmptyResponseCodes,
+ emptyRequestMethods: Set = DataResponseSerializer.defaultEmptyRequestMethods,
+ completionHandler: @escaping (AFDownloadResponse) -> Void) -> Self {
+ response(queue: queue,
+ responseSerializer: DataResponseSerializer(dataPreprocessor: dataPreprocessor,
+ emptyResponseCodes: emptyResponseCodes,
+ emptyRequestMethods: emptyRequestMethods),
+ completionHandler: completionHandler)
+ }
+
+ /// Adds a handler using a `StringResponseSerializer` to be called once the request has finished.
+ ///
+ /// - Parameters:
+ /// - queue: The queue on which the completion handler is dispatched. `.main` by default.
+ /// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the
+ /// `completionHandler`. `PassthroughPreprocessor()` by default.
+ /// - encoding: The string encoding. Defaults to `nil`, in which case the encoding will be determined
+ /// from the server response, falling back to the default HTTP character set, `ISO-8859-1`.
+ /// - emptyResponseCodes: HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
+ /// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
+ /// - completionHandler: A closure to be executed once the request has finished.
+ ///
+ /// - Returns: The request.
+ @discardableResult
+ public func responseString(queue: DispatchQueue = .main,
+ dataPreprocessor: DataPreprocessor = StringResponseSerializer.defaultDataPreprocessor,
+ encoding: String.Encoding? = nil,
+ emptyResponseCodes: Set = StringResponseSerializer.defaultEmptyResponseCodes,
+ emptyRequestMethods: Set = StringResponseSerializer.defaultEmptyRequestMethods,
+ completionHandler: @escaping (AFDownloadResponse) -> Void) -> Self {
+ response(queue: queue,
+ responseSerializer: StringResponseSerializer(dataPreprocessor: dataPreprocessor,
+ encoding: encoding,
+ emptyResponseCodes: emptyResponseCodes,
+ emptyRequestMethods: emptyRequestMethods),
+ completionHandler: completionHandler)
+ }
+
+ /// Adds a handler using a `JSONResponseSerializer` to be called once the request has finished.
+ ///
+ /// - Parameters:
+ /// - queue: The queue on which the completion handler is dispatched. `.main` by default.
+ /// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the
+ /// `completionHandler`. `PassthroughPreprocessor()` by default.
+ /// - emptyResponseCodes: HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
+ /// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
+ /// - options: `JSONSerialization.ReadingOptions` used when parsing the response. `.allowFragments`
+ /// by default.
+ /// - completionHandler: A closure to be executed once the request has finished.
+ ///
+ /// - Returns: The request.
+ @available(*, deprecated, message: "responseJSON deprecated and will be removed in Alamofire 6. Use responseDecodable instead.")
+ @discardableResult
+ public func responseJSON(queue: DispatchQueue = .main,
+ dataPreprocessor: DataPreprocessor = JSONResponseSerializer.defaultDataPreprocessor,
+ emptyResponseCodes: Set = JSONResponseSerializer.defaultEmptyResponseCodes,
+ emptyRequestMethods: Set = JSONResponseSerializer.defaultEmptyRequestMethods,
+ options: JSONSerialization.ReadingOptions = .allowFragments,
+ completionHandler: @escaping (AFDownloadResponse) -> Void) -> Self {
+ response(queue: queue,
+ responseSerializer: JSONResponseSerializer(dataPreprocessor: dataPreprocessor,
+ emptyResponseCodes: emptyResponseCodes,
+ emptyRequestMethods: emptyRequestMethods,
+ options: options),
+ completionHandler: completionHandler)
+ }
+
+ /// Adds a handler using a `DecodableResponseSerializer` to be called once the request has finished.
+ ///
+ /// - Parameters:
+ /// - type: `Decodable` type to decode from response data.
+ /// - queue: The queue on which the completion handler is dispatched. `.main` by default.
+ /// - dataPreprocessor: `DataPreprocessor` which processes the received `Data` before calling the
+ /// `completionHandler`. `PassthroughPreprocessor()` by default.
+ /// - decoder: `DataDecoder` to use to decode the response. `JSONDecoder()` by default.
+ /// - emptyResponseCodes: HTTP status codes for which empty responses are always valid. `[204, 205]` by default.
+ /// - emptyRequestMethods: `HTTPMethod`s for which empty responses are always valid. `[.head]` by default.
+ /// - completionHandler: A closure to be executed once the request has finished.
+ ///
+ /// - Returns: The request.
+ @discardableResult
+ public func responseDecodable(of type: T.Type = T.self,
+ queue: DispatchQueue = .main,
+ dataPreprocessor: DataPreprocessor = DecodableResponseSerializer.defaultDataPreprocessor,
+ decoder: DataDecoder = JSONDecoder(),
+ emptyResponseCodes: Set = DecodableResponseSerializer.defaultEmptyResponseCodes,
+ emptyRequestMethods: Set = DecodableResponseSerializer.defaultEmptyRequestMethods,
+ completionHandler: @escaping (AFDownloadResponse) -> Void) -> Self {
+ response(queue: queue,
+ responseSerializer: DecodableResponseSerializer(dataPreprocessor: dataPreprocessor,
+ decoder: decoder,
+ emptyResponseCodes: emptyResponseCodes,
+ emptyRequestMethods: emptyRequestMethods),
+ completionHandler: completionHandler)
+ }
+}
diff --git a/ChatBot/Pods/Alamofire/Source/Core/HTTPHeaders.swift b/ChatBot/Pods/Alamofire/Source/Core/HTTPHeaders.swift
new file mode 100644
index 00000000..29ca43f6
--- /dev/null
+++ b/ChatBot/Pods/Alamofire/Source/Core/HTTPHeaders.swift
@@ -0,0 +1,466 @@
+//
+// HTTPHeaders.swift
+//
+// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+// 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 Foundation
+
+/// An order-preserving and case-insensitive representation of HTTP headers.
+public struct HTTPHeaders: Equatable, Hashable, Sendable {
+ private var headers: [HTTPHeader] = []
+
+ /// Creates an empty instance.
+ public init() {}
+
+ /// Creates an instance from an array of `HTTPHeader`s. Duplicate case-insensitive names are collapsed into the last
+ /// name and value encountered.
+ public init(_ headers: [HTTPHeader]) {
+ headers.forEach { update($0) }
+ }
+
+ /// Creates an instance from a `[String: String]`. Duplicate case-insensitive names are collapsed into the last name
+ /// and value encountered.
+ public init(_ dictionary: [String: String]) {
+ dictionary.forEach { update(HTTPHeader(name: $0.key, value: $0.value)) }
+ }
+
+ /// Case-insensitively updates or appends an `HTTPHeader` into the instance using the provided `name` and `value`.
+ ///
+ /// - Parameters:
+ /// - name: The `HTTPHeader` name.
+ /// - value: The `HTTPHeader` value.
+ public mutating func add(name: String, value: String) {
+ update(HTTPHeader(name: name, value: value))
+ }
+
+ /// Case-insensitively updates or appends the provided `HTTPHeader` into the instance.
+ ///
+ /// - Parameter header: The `HTTPHeader` to update or append.
+ public mutating func add(_ header: HTTPHeader) {
+ update(header)
+ }
+
+ /// Case-insensitively updates or appends an `HTTPHeader` into the instance using the provided `name` and `value`.
+ ///
+ /// - Parameters:
+ /// - name: The `HTTPHeader` name.
+ /// - value: The `HTTPHeader` value.
+ public mutating func update(name: String, value: String) {
+ update(HTTPHeader(name: name, value: value))
+ }
+
+ /// Case-insensitively updates or appends the provided `HTTPHeader` into the instance.
+ ///
+ /// - Parameter header: The `HTTPHeader` to update or append.
+ public mutating func update(_ header: HTTPHeader) {
+ guard let index = headers.index(of: header.name) else {
+ headers.append(header)
+ return
+ }
+
+ headers.replaceSubrange(index...index, with: [header])
+ }
+
+ /// Case-insensitively removes an `HTTPHeader`, if it exists, from the instance.
+ ///
+ /// - Parameter name: The name of the `HTTPHeader` to remove.
+ public mutating func remove(name: String) {
+ guard let index = headers.index(of: name) else { return }
+
+ headers.remove(at: index)
+ }
+
+ /// Sort the current instance by header name, case insensitively.
+ public mutating func sort() {
+ headers.sort { $0.name.lowercased() < $1.name.lowercased() }
+ }
+
+ /// Returns an instance sorted by header name.
+ ///
+ /// - Returns: A copy of the current instance sorted by name.
+ public func sorted() -> HTTPHeaders {
+ var headers = self
+ headers.sort()
+
+ return headers
+ }
+
+ /// Case-insensitively find a header's value by name.
+ ///
+ /// - Parameter name: The name of the header to search for, case-insensitively.
+ ///
+ /// - Returns: The value of header, if it exists.
+ public func value(for name: String) -> String? {
+ guard let index = headers.index(of: name) else { return nil }
+
+ return headers[index].value
+ }
+
+ /// Case-insensitively access the header with the given name.
+ ///
+ /// - Parameter name: The name of the header.
+ public subscript(_ name: String) -> String? {
+ get { value(for: name) }
+ set {
+ if let value = newValue {
+ update(name: name, value: value)
+ } else {
+ remove(name: name)
+ }
+ }
+ }
+
+ /// The dictionary representation of all headers.
+ ///
+ /// This representation does not preserve the current order of the instance.
+ public var dictionary: [String: String] {
+ let namesAndValues = headers.map { ($0.name, $0.value) }
+
+ return Dictionary(namesAndValues, uniquingKeysWith: { _, last in last })
+ }
+}
+
+extension HTTPHeaders: ExpressibleByDictionaryLiteral {
+ public init(dictionaryLiteral elements: (String, String)...) {
+ elements.forEach { update(name: $0.0, value: $0.1) }
+ }
+}
+
+extension HTTPHeaders: ExpressibleByArrayLiteral {
+ public init(arrayLiteral elements: HTTPHeader...) {
+ self.init(elements)
+ }
+}
+
+extension HTTPHeaders: Sequence {
+ public func makeIterator() -> IndexingIterator<[HTTPHeader]> {
+ headers.makeIterator()
+ }
+}
+
+extension HTTPHeaders: Collection {
+ public var startIndex: Int {
+ headers.startIndex
+ }
+
+ public var endIndex: Int {
+ headers.endIndex
+ }
+
+ public subscript(position: Int) -> HTTPHeader {
+ headers[position]
+ }
+
+ public func index(after i: Int) -> Int {
+ headers.index(after: i)
+ }
+}
+
+extension HTTPHeaders: CustomStringConvertible {
+ public var description: String {
+ headers.map(\.description)
+ .joined(separator: "\n")
+ }
+}
+
+// MARK: - HTTPHeader
+
+/// A representation of a single HTTP header's name / value pair.
+public struct HTTPHeader: Equatable, Hashable, Sendable {
+ /// Name of the header.
+ public let name: String
+
+ /// Value of the header.
+ public let value: String
+
+ /// Creates an instance from the given `name` and `value`.
+ ///
+ /// - Parameters:
+ /// - name: The name of the header.
+ /// - value: The value of the header.
+ public init(name: String, value: String) {
+ self.name = name
+ self.value = value
+ }
+}
+
+extension HTTPHeader: CustomStringConvertible {
+ public var description: String {
+ "\(name): \(value)"
+ }
+}
+
+extension HTTPHeader {
+ /// Returns an `Accept` header.
+ ///
+ /// - Parameter value: The `Accept` value.
+ /// - Returns: The header.
+ public static func accept(_ value: String) -> HTTPHeader {
+ HTTPHeader(name: "Accept", value: value)
+ }
+
+ /// Returns an `Accept-Charset` header.
+ ///
+ /// - Parameter value: The `Accept-Charset` value.
+ /// - Returns: The header.
+ public static func acceptCharset(_ value: String) -> HTTPHeader {
+ HTTPHeader(name: "Accept-Charset", value: value)
+ }
+
+ /// Returns an `Accept-Language` header.
+ ///
+ /// Alamofire offers a default Accept-Language header that accumulates and encodes the system's preferred languages.
+ /// Use `HTTPHeader.defaultAcceptLanguage`.
+ ///
+ /// - Parameter value: The `Accept-Language` value.
+ ///
+ /// - Returns: The header.
+ public static func acceptLanguage(_ value: String) -> HTTPHeader {
+ HTTPHeader(name: "Accept-Language", value: value)
+ }
+
+ /// Returns an `Accept-Encoding` header.
+ ///
+ /// Alamofire offers a default accept encoding value that provides the most common values. Use
+ /// `HTTPHeader.defaultAcceptEncoding`.
+ ///
+ /// - Parameter value: The `Accept-Encoding` value.
+ ///
+ /// - Returns: The header
+ public static func acceptEncoding(_ value: String) -> HTTPHeader {
+ HTTPHeader(name: "Accept-Encoding", value: value)
+ }
+
+ /// Returns a `Basic` `Authorization` header using the `username` and `password` provided.
+ ///
+ /// - Parameters:
+ /// - username: The username of the header.
+ /// - password: The password of the header.
+ ///
+ /// - Returns: The header.
+ public static func authorization(username: String, password: String) -> HTTPHeader {
+ let credential = Data("\(username):\(password)".utf8).base64EncodedString()
+
+ return authorization("Basic \(credential)")
+ }
+
+ /// Returns a `Bearer` `Authorization` header using the `bearerToken` provided.
+ ///
+ /// - Parameter bearerToken: The bearer token.
+ ///
+ /// - Returns: The header.
+ public static func authorization(bearerToken: String) -> HTTPHeader {
+ authorization("Bearer \(bearerToken)")
+ }
+
+ /// Returns an `Authorization` header.
+ ///
+ /// Alamofire provides built-in methods to produce `Authorization` headers. For a Basic `Authorization` header use
+ /// `HTTPHeader.authorization(username:password:)`. For a Bearer `Authorization` header, use
+ /// `HTTPHeader.authorization(bearerToken:)`.
+ ///
+ /// - Parameter value: The `Authorization` value.
+ ///
+ /// - Returns: The header.
+ public static func authorization(_ value: String) -> HTTPHeader {
+ HTTPHeader(name: "Authorization", value: value)
+ }
+
+ /// Returns a `Content-Disposition` header.
+ ///
+ /// - Parameter value: The `Content-Disposition` value.
+ ///
+ /// - Returns: The header.
+ public static func contentDisposition(_ value: String) -> HTTPHeader {
+ HTTPHeader(name: "Content-Disposition", value: value)
+ }
+
+ /// Returns a `Content-Encoding` header.
+ ///
+ /// - Parameter value: The `Content-Encoding`.
+ ///
+ /// - Returns: The header.
+ public static func contentEncoding(_ value: String) -> HTTPHeader {
+ HTTPHeader(name: "Content-Encoding", value: value)
+ }
+
+ /// Returns a `Content-Type` header.
+ ///
+ /// All Alamofire `ParameterEncoding`s and `ParameterEncoder`s set the `Content-Type` of the request, so it may not
+ /// be necessary to manually set this value.
+ ///
+ /// - Parameter value: The `Content-Type` value.
+ ///
+ /// - Returns: The header.
+ public static func contentType(_ value: String) -> HTTPHeader {
+ HTTPHeader(name: "Content-Type", value: value)
+ }
+
+ /// Returns a `User-Agent` header.
+ ///
+ /// - Parameter value: The `User-Agent` value.
+ ///
+ /// - Returns: The header.
+ public static func userAgent(_ value: String) -> HTTPHeader {
+ HTTPHeader(name: "User-Agent", value: value)
+ }
+
+ /// Returns a `Sec-WebSocket-Protocol` header.
+ ///
+ /// - Parameter value: The `Sec-WebSocket-Protocol` value.
+ /// - Returns: The header.
+ public static func websocketProtocol(_ value: String) -> HTTPHeader {
+ HTTPHeader(name: "Sec-WebSocket-Protocol", value: value)
+ }
+}
+
+extension [HTTPHeader] {
+ /// Case-insensitively finds the index of an `HTTPHeader` with the provided name, if it exists.
+ func index(of name: String) -> Int? {
+ let lowercasedName = name.lowercased()
+ return firstIndex { $0.name.lowercased() == lowercasedName }
+ }
+}
+
+// MARK: - Defaults
+
+extension HTTPHeaders {
+ /// The default set of `HTTPHeaders` used by Alamofire. Includes `Accept-Encoding`, `Accept-Language`, and
+ /// `User-Agent`.
+ public static let `default`: HTTPHeaders = [.defaultAcceptEncoding,
+ .defaultAcceptLanguage,
+ .defaultUserAgent]
+}
+
+extension HTTPHeader {
+ /// Returns Alamofire's default `Accept-Encoding` header, appropriate for the encodings supported by particular OS
+ /// versions.
+ ///
+ /// See the [Accept-Encoding HTTP header documentation](https://tools.ietf.org/html/rfc7230#section-4.2.3) .
+ public static let defaultAcceptEncoding: HTTPHeader = {
+ let encodings: [String]
+ if #available(iOS 11.0, macOS 10.13, tvOS 11.0, watchOS 4.0, *) {
+ encodings = ["br", "gzip", "deflate"]
+ } else {
+ encodings = ["gzip", "deflate"]
+ }
+
+ return .acceptEncoding(encodings.qualityEncoded())
+ }()
+
+ /// Returns Alamofire's default `Accept-Language` header, generated by querying `Locale` for the user's
+ /// `preferredLanguages`.
+ ///
+ /// See the [Accept-Language HTTP header documentation](https://tools.ietf.org/html/rfc7231#section-5.3.5).
+ public static let defaultAcceptLanguage: HTTPHeader = .acceptLanguage(Locale.preferredLanguages.prefix(6).qualityEncoded())
+
+ /// Returns Alamofire's default `User-Agent` header.
+ ///
+ /// See the [User-Agent header documentation](https://tools.ietf.org/html/rfc7231#section-5.5.3).
+ ///
+ /// Example: `iOS Example/1.0 (org.alamofire.iOS-Example; build:1; iOS 13.0.0) Alamofire/5.0.0`
+ public static let defaultUserAgent: HTTPHeader = {
+ let info = Bundle.main.infoDictionary
+ let executable = (info?["CFBundleExecutable"] as? String) ??
+ (ProcessInfo.processInfo.arguments.first?.split(separator: "/").last.map(String.init)) ??
+ "Unknown"
+ let bundle = info?["CFBundleIdentifier"] as? String ?? "Unknown"
+ let appVersion = info?["CFBundleShortVersionString"] as? String ?? "Unknown"
+ let appBuild = info?["CFBundleVersion"] as? String ?? "Unknown"
+
+ let osNameVersion: String = {
+ let version = ProcessInfo.processInfo.operatingSystemVersion
+ let versionString = "\(version.majorVersion).\(version.minorVersion).\(version.patchVersion)"
+ let osName: String = {
+ #if os(iOS)
+ #if targetEnvironment(macCatalyst)
+ return "macOS(Catalyst)"
+ #else
+ return "iOS"
+ #endif
+ #elseif os(watchOS)
+ return "watchOS"
+ #elseif os(tvOS)
+ return "tvOS"
+ #elseif os(macOS)
+ #if targetEnvironment(macCatalyst)
+ return "macOS(Catalyst)"
+ #else
+ return "macOS"
+ #endif
+ #elseif swift(>=5.9.2) && os(visionOS)
+ return "visionOS"
+ #elseif os(Linux)
+ return "Linux"
+ #elseif os(Windows)
+ return "Windows"
+ #elseif os(Android)
+ return "Android"
+ #else
+ return "Unknown"
+ #endif
+ }()
+
+ return "\(osName) \(versionString)"
+ }()
+
+ let alamofireVersion = "Alamofire/\(AFInfo.version)"
+
+ let userAgent = "\(executable)/\(appVersion) (\(bundle); build:\(appBuild); \(osNameVersion)) \(alamofireVersion)"
+
+ return .userAgent(userAgent)
+ }()
+}
+
+extension Collection {
+ func qualityEncoded() -> String {
+ enumerated().map { index, encoding in
+ let quality = 1.0 - (Double(index) * 0.1)
+ return "\(encoding);q=\(quality)"
+ }.joined(separator: ", ")
+ }
+}
+
+// MARK: - System Type Extensions
+
+extension URLRequest {
+ /// Returns `allHTTPHeaderFields` as `HTTPHeaders`.
+ public var headers: HTTPHeaders {
+ get { allHTTPHeaderFields.map(HTTPHeaders.init) ?? HTTPHeaders() }
+ set { allHTTPHeaderFields = newValue.dictionary }
+ }
+}
+
+extension HTTPURLResponse {
+ /// Returns `allHeaderFields` as `HTTPHeaders`.
+ public var headers: HTTPHeaders {
+ (allHeaderFields as? [String: String]).map(HTTPHeaders.init) ?? HTTPHeaders()
+ }
+}
+
+extension URLSessionConfiguration {
+ /// Returns `httpAdditionalHeaders` as `HTTPHeaders`.
+ public var headers: HTTPHeaders {
+ get { (httpAdditionalHeaders as? [String: String]).map(HTTPHeaders.init) ?? HTTPHeaders() }
+ set { httpAdditionalHeaders = newValue.dictionary }
+ }
+}
diff --git a/ChatBot/Pods/Alamofire/Source/Core/HTTPMethod.swift b/ChatBot/Pods/Alamofire/Source/Core/HTTPMethod.swift
new file mode 100644
index 00000000..ed51b689
--- /dev/null
+++ b/ChatBot/Pods/Alamofire/Source/Core/HTTPMethod.swift
@@ -0,0 +1,56 @@
+//
+// HTTPMethod.swift
+//
+// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+// 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.
+//
+
+/// Type representing HTTP methods. Raw `String` value is stored and compared case-sensitively, so
+/// `HTTPMethod.get != HTTPMethod(rawValue: "get")`.
+///
+/// See https://tools.ietf.org/html/rfc7231#section-4.3
+public struct HTTPMethod: RawRepresentable, Equatable, Hashable, Sendable {
+ /// `CONNECT` method.
+ public static let connect = HTTPMethod(rawValue: "CONNECT")
+ /// `DELETE` method.
+ public static let delete = HTTPMethod(rawValue: "DELETE")
+ /// `GET` method.
+ public static let get = HTTPMethod(rawValue: "GET")
+ /// `HEAD` method.
+ public static let head = HTTPMethod(rawValue: "HEAD")
+ /// `OPTIONS` method.
+ public static let options = HTTPMethod(rawValue: "OPTIONS")
+ /// `PATCH` method.
+ public static let patch = HTTPMethod(rawValue: "PATCH")
+ /// `POST` method.
+ public static let post = HTTPMethod(rawValue: "POST")
+ /// `PUT` method.
+ public static let put = HTTPMethod(rawValue: "PUT")
+ /// `QUERY` method.
+ public static let query = HTTPMethod(rawValue: "QUERY")
+ /// `TRACE` method.
+ public static let trace = HTTPMethod(rawValue: "TRACE")
+
+ public let rawValue: String
+
+ public init(rawValue: String) {
+ self.rawValue = rawValue
+ }
+}
diff --git a/ChatBot/Pods/Alamofire/Source/Core/Notifications.swift b/ChatBot/Pods/Alamofire/Source/Core/Notifications.swift
new file mode 100644
index 00000000..66434b6e
--- /dev/null
+++ b/ChatBot/Pods/Alamofire/Source/Core/Notifications.swift
@@ -0,0 +1,115 @@
+//
+// Notifications.swift
+//
+// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+// 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 Foundation
+
+extension Request {
+ /// Posted when a `Request` is resumed. The `Notification` contains the resumed `Request`.
+ public static let didResumeNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didResume")
+ /// Posted when a `Request` is suspended. The `Notification` contains the suspended `Request`.
+ public static let didSuspendNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didSuspend")
+ /// Posted when a `Request` is cancelled. The `Notification` contains the cancelled `Request`.
+ public static let didCancelNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didCancel")
+ /// Posted when a `Request` is finished. The `Notification` contains the completed `Request`.
+ public static let didFinishNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didFinish")
+
+ /// Posted when a `URLSessionTask` is resumed. The `Notification` contains the `Request` associated with the `URLSessionTask`.
+ public static let didResumeTaskNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didResumeTask")
+ /// Posted when a `URLSessionTask` is suspended. The `Notification` contains the `Request` associated with the `URLSessionTask`.
+ public static let didSuspendTaskNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didSuspendTask")
+ /// Posted when a `URLSessionTask` is cancelled. The `Notification` contains the `Request` associated with the `URLSessionTask`.
+ public static let didCancelTaskNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didCancelTask")
+ /// Posted when a `URLSessionTask` is completed. The `Notification` contains the `Request` associated with the `URLSessionTask`.
+ public static let didCompleteTaskNotification = Notification.Name(rawValue: "org.alamofire.notification.name.request.didCompleteTask")
+}
+
+// MARK: -
+
+extension Notification {
+ /// The `Request` contained by the instance's `userInfo`, `nil` otherwise.
+ public var request: Request? {
+ userInfo?[String.requestKey] as? Request
+ }
+
+ /// Convenience initializer for a `Notification` containing a `Request` payload.
+ ///
+ /// - Parameters:
+ /// - name: The name of the notification.
+ /// - request: The `Request` payload.
+ init(name: Notification.Name, request: Request) {
+ self.init(name: name, object: nil, userInfo: [String.requestKey: request])
+ }
+}
+
+extension NotificationCenter {
+ /// Convenience function for posting notifications with `Request` payloads.
+ ///
+ /// - Parameters:
+ /// - name: The name of the notification.
+ /// - request: The `Request` payload.
+ func postNotification(named name: Notification.Name, with request: Request) {
+ let notification = Notification(name: name, request: request)
+ post(notification)
+ }
+}
+
+extension String {
+ /// User info dictionary key representing the `Request` associated with the notification.
+ fileprivate static let requestKey = "org.alamofire.notification.key.request"
+}
+
+/// `EventMonitor` that provides Alamofire's notifications.
+public final class AlamofireNotifications: EventMonitor {
+ public func requestDidResume(_ request: Request) {
+ NotificationCenter.default.postNotification(named: Request.didResumeNotification, with: request)
+ }
+
+ public func requestDidSuspend(_ request: Request) {
+ NotificationCenter.default.postNotification(named: Request.didSuspendNotification, with: request)
+ }
+
+ public func requestDidCancel(_ request: Request) {
+ NotificationCenter.default.postNotification(named: Request.didCancelNotification, with: request)
+ }
+
+ public func requestDidFinish(_ request: Request) {
+ NotificationCenter.default.postNotification(named: Request.didFinishNotification, with: request)
+ }
+
+ public func request(_ request: Request, didResumeTask task: URLSessionTask) {
+ NotificationCenter.default.postNotification(named: Request.didResumeTaskNotification, with: request)
+ }
+
+ public func request(_ request: Request, didSuspendTask task: URLSessionTask) {
+ NotificationCenter.default.postNotification(named: Request.didSuspendTaskNotification, with: request)
+ }
+
+ public func request(_ request: Request, didCancelTask task: URLSessionTask) {
+ NotificationCenter.default.postNotification(named: Request.didCancelTaskNotification, with: request)
+ }
+
+ public func request(_ request: Request, didCompleteTask task: URLSessionTask, with error: AFError?) {
+ NotificationCenter.default.postNotification(named: Request.didCompleteTaskNotification, with: request)
+ }
+}
diff --git a/ChatBot/Pods/Alamofire/Source/Core/ParameterEncoder.swift b/ChatBot/Pods/Alamofire/Source/Core/ParameterEncoder.swift
new file mode 100644
index 00000000..3d30c3f3
--- /dev/null
+++ b/ChatBot/Pods/Alamofire/Source/Core/ParameterEncoder.swift
@@ -0,0 +1,213 @@
+//
+// ParameterEncoder.swift
+//
+// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+// 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 Foundation
+
+/// A type that can encode any `Encodable` type into a `URLRequest`.
+public protocol ParameterEncoder {
+ /// Encode the provided `Encodable` parameters into `request`.
+ ///
+ /// - Parameters:
+ /// - parameters: The `Encodable` parameter value.
+ /// - request: The `URLRequest` into which to encode the parameters.
+ ///
+ /// - Returns: A `URLRequest` with the result of the encoding.
+ /// - Throws: An `Error` when encoding fails. For Alamofire provided encoders, this will be an instance of
+ /// `AFError.parameterEncoderFailed` with an associated `ParameterEncoderFailureReason`.
+ func encode(_ parameters: Parameters?, into request: URLRequest) throws -> URLRequest
+}
+
+/// A `ParameterEncoder` that encodes types as JSON body data.
+///
+/// If no `Content-Type` header is already set on the provided `URLRequest`s, it's set to `application/json`.
+open class JSONParameterEncoder: ParameterEncoder {
+ /// Returns an encoder with default parameters.
+ public static var `default`: JSONParameterEncoder { JSONParameterEncoder() }
+
+ /// Returns an encoder with `JSONEncoder.outputFormatting` set to `.prettyPrinted`.
+ public static var prettyPrinted: JSONParameterEncoder {
+ let encoder = JSONEncoder()
+ encoder.outputFormatting = .prettyPrinted
+
+ return JSONParameterEncoder(encoder: encoder)
+ }
+
+ /// Returns an encoder with `JSONEncoder.outputFormatting` set to `.sortedKeys`.
+ @available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)
+ public static var sortedKeys: JSONParameterEncoder {
+ let encoder = JSONEncoder()
+ encoder.outputFormatting = .sortedKeys
+
+ return JSONParameterEncoder(encoder: encoder)
+ }
+
+ /// `JSONEncoder` used to encode parameters.
+ public let encoder: JSONEncoder
+
+ /// Creates an instance with the provided `JSONEncoder`.
+ ///
+ /// - Parameter encoder: The `JSONEncoder`. `JSONEncoder()` by default.
+ public init(encoder: JSONEncoder = JSONEncoder()) {
+ self.encoder = encoder
+ }
+
+ open func encode(_ parameters: Parameters?,
+ into request: URLRequest) throws -> URLRequest {
+ guard let parameters else { return request }
+
+ var request = request
+
+ do {
+ let data = try encoder.encode(parameters)
+ request.httpBody = data
+ if request.headers["Content-Type"] == nil {
+ request.headers.update(.contentType("application/json"))
+ }
+ } catch {
+ throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
+ }
+
+ return request
+ }
+}
+
+extension ParameterEncoder where Self == JSONParameterEncoder {
+ /// Provides a default `JSONParameterEncoder` instance.
+ public static var json: JSONParameterEncoder { JSONParameterEncoder() }
+
+ /// Creates a `JSONParameterEncoder` using the provided `JSONEncoder`.
+ ///
+ /// - Parameter encoder: `JSONEncoder` used to encode parameters. `JSONEncoder()` by default.
+ /// - Returns: The `JSONParameterEncoder`.
+ public static func json(encoder: JSONEncoder = JSONEncoder()) -> JSONParameterEncoder {
+ JSONParameterEncoder(encoder: encoder)
+ }
+}
+
+/// A `ParameterEncoder` that encodes types as URL-encoded query strings to be set on the URL or as body data, depending
+/// on the `Destination` set.
+///
+/// If no `Content-Type` header is already set on the provided `URLRequest`s, it will be set to
+/// `application/x-www-form-urlencoded; charset=utf-8`.
+///
+/// Encoding behavior can be customized by passing an instance of `URLEncodedFormEncoder` to the initializer.
+open class URLEncodedFormParameterEncoder: ParameterEncoder {
+ /// Defines where the URL-encoded string should be set for each `URLRequest`.
+ public enum Destination {
+ /// Applies the encoded query string to any existing query string for `.get`, `.head`, and `.delete` request.
+ /// Sets it to the `httpBody` for all other methods.
+ case methodDependent
+ /// Applies the encoded query string to any existing query string from the `URLRequest`.
+ case queryString
+ /// Applies the encoded query string to the `httpBody` of the `URLRequest`.
+ case httpBody
+
+ /// Determines whether the URL-encoded string should be applied to the `URLRequest`'s `url`.
+ ///
+ /// - Parameter method: The `HTTPMethod`.
+ ///
+ /// - Returns: Whether the URL-encoded string should be applied to a `URL`.
+ func encodesParametersInURL(for method: HTTPMethod) -> Bool {
+ switch self {
+ case .methodDependent: return [.get, .head, .delete].contains(method)
+ case .queryString: return true
+ case .httpBody: return false
+ }
+ }
+ }
+
+ /// Returns an encoder with default parameters.
+ public static var `default`: URLEncodedFormParameterEncoder { URLEncodedFormParameterEncoder() }
+
+ /// The `URLEncodedFormEncoder` to use.
+ public let encoder: URLEncodedFormEncoder
+
+ /// The `Destination` for the URL-encoded string.
+ public let destination: Destination
+
+ /// Creates an instance with the provided `URLEncodedFormEncoder` instance and `Destination` value.
+ ///
+ /// - Parameters:
+ /// - encoder: The `URLEncodedFormEncoder`. `URLEncodedFormEncoder()` by default.
+ /// - destination: The `Destination`. `.methodDependent` by default.
+ public init(encoder: URLEncodedFormEncoder = URLEncodedFormEncoder(), destination: Destination = .methodDependent) {
+ self.encoder = encoder
+ self.destination = destination
+ }
+
+ open func encode(_ parameters: Parameters?,
+ into request: URLRequest) throws -> URLRequest {
+ guard let parameters else { return request }
+
+ var request = request
+
+ guard let url = request.url else {
+ throw AFError.parameterEncoderFailed(reason: .missingRequiredComponent(.url))
+ }
+
+ guard let method = request.method else {
+ let rawValue = request.method?.rawValue ?? "nil"
+ throw AFError.parameterEncoderFailed(reason: .missingRequiredComponent(.httpMethod(rawValue: rawValue)))
+ }
+
+ if destination.encodesParametersInURL(for: method),
+ var components = URLComponents(url: url, resolvingAgainstBaseURL: false) {
+ let query: String = try Result { try encoder.encode(parameters) }
+ .mapError { AFError.parameterEncoderFailed(reason: .encoderFailed(error: $0)) }.get()
+ let newQueryString = [components.percentEncodedQuery, query].compactMap { $0 }.joinedWithAmpersands()
+ components.percentEncodedQuery = newQueryString.isEmpty ? nil : newQueryString
+
+ guard let newURL = components.url else {
+ throw AFError.parameterEncoderFailed(reason: .missingRequiredComponent(.url))
+ }
+
+ request.url = newURL
+ } else {
+ if request.headers["Content-Type"] == nil {
+ request.headers.update(.contentType("application/x-www-form-urlencoded; charset=utf-8"))
+ }
+
+ request.httpBody = try Result { try encoder.encode(parameters) }
+ .mapError { AFError.parameterEncoderFailed(reason: .encoderFailed(error: $0)) }.get()
+ }
+
+ return request
+ }
+}
+
+extension ParameterEncoder where Self == URLEncodedFormParameterEncoder {
+ /// Provides a default `URLEncodedFormParameterEncoder` instance.
+ public static var urlEncodedForm: URLEncodedFormParameterEncoder { URLEncodedFormParameterEncoder() }
+
+ /// Creates a `URLEncodedFormParameterEncoder` with the provided encoder and destination.
+ ///
+ /// - Parameters:
+ /// - encoder: `URLEncodedFormEncoder` used to encode the parameters. `URLEncodedFormEncoder()` by default.
+ /// - destination: `Destination` to which to encode the parameters. `.methodDependent` by default.
+ /// - Returns: The `URLEncodedFormParameterEncoder`.
+ public static func urlEncodedForm(encoder: URLEncodedFormEncoder = URLEncodedFormEncoder(),
+ destination: URLEncodedFormParameterEncoder.Destination = .methodDependent) -> URLEncodedFormParameterEncoder {
+ URLEncodedFormParameterEncoder(encoder: encoder, destination: destination)
+ }
+}
diff --git a/ChatBot/Pods/Alamofire/Source/Core/ParameterEncoding.swift b/ChatBot/Pods/Alamofire/Source/Core/ParameterEncoding.swift
new file mode 100644
index 00000000..5b7d680c
--- /dev/null
+++ b/ChatBot/Pods/Alamofire/Source/Core/ParameterEncoding.swift
@@ -0,0 +1,349 @@
+//
+// ParameterEncoding.swift
+//
+// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+// 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 Foundation
+
+/// A dictionary of parameters to apply to a `URLRequest`.
+public typealias Parameters = [String: Any]
+
+/// A type used to define how a set of parameters are applied to a `URLRequest`.
+public protocol ParameterEncoding {
+ /// Creates a `URLRequest` by encoding parameters and applying them on the passed request.
+ ///
+ /// - Parameters:
+ /// - urlRequest: `URLRequestConvertible` value onto which parameters will be encoded.
+ /// - parameters: `Parameters` to encode onto the request.
+ ///
+ /// - Returns: The encoded `URLRequest`.
+ /// - Throws: Any `Error` produced during parameter encoding.
+ func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest
+}
+
+// MARK: -
+
+/// Creates a url-encoded query string to be set as or appended to any existing URL query string or set as the HTTP
+/// body of the URL request. Whether the query string is set or appended to any existing URL query string or set as
+/// the HTTP body depends on the destination of the encoding.
+///
+/// The `Content-Type` HTTP header field of an encoded request with HTTP body is set to
+/// `application/x-www-form-urlencoded; charset=utf-8`.
+///
+/// There is no published specification for how to encode collection types. By default the convention of appending
+/// `[]` to the key for array values (`foo[]=1&foo[]=2`), and appending the key surrounded by square brackets for
+/// nested dictionary values (`foo[bar]=baz`) is used. Optionally, `ArrayEncoding` can be used to omit the
+/// square brackets appended to array keys.
+///
+/// `BoolEncoding` can be used to configure how boolean values are encoded. The default behavior is to encode
+/// `true` as 1 and `false` as 0.
+public struct URLEncoding: ParameterEncoding {
+ // MARK: Helper Types
+
+ /// Defines whether the url-encoded query string is applied to the existing query string or HTTP body of the
+ /// resulting URL request.
+ public enum Destination {
+ /// Applies encoded query string result to existing query string for `GET`, `HEAD` and `DELETE` requests and
+ /// sets as the HTTP body for requests with any other HTTP method.
+ case methodDependent
+ /// Sets or appends encoded query string result to existing query string.
+ case queryString
+ /// Sets encoded query string result as the HTTP body of the URL request.
+ case httpBody
+
+ func encodesParametersInURL(for method: HTTPMethod) -> Bool {
+ switch self {
+ case .methodDependent: return [.get, .head, .delete].contains(method)
+ case .queryString: return true
+ case .httpBody: return false
+ }
+ }
+ }
+
+ /// Configures how `Array` parameters are encoded.
+ public enum ArrayEncoding {
+ /// An empty set of square brackets is appended to the key for every value. This is the default behavior.
+ case brackets
+ /// No brackets are appended. The key is encoded as is.
+ case noBrackets
+ /// Brackets containing the item index are appended. This matches the jQuery and Node.js behavior.
+ case indexInBrackets
+ /// Provide a custom array key encoding with the given closure.
+ case custom((_ key: String, _ index: Int) -> String)
+
+ func encode(key: String, atIndex index: Int) -> String {
+ switch self {
+ case .brackets:
+ return "\(key)[]"
+ case .noBrackets:
+ return key
+ case .indexInBrackets:
+ return "\(key)[\(index)]"
+ case let .custom(encoding):
+ return encoding(key, index)
+ }
+ }
+ }
+
+ /// Configures how `Bool` parameters are encoded.
+ public enum BoolEncoding {
+ /// Encode `true` as `1` and `false` as `0`. This is the default behavior.
+ case numeric
+ /// Encode `true` and `false` as string literals.
+ case literal
+
+ func encode(value: Bool) -> String {
+ switch self {
+ case .numeric:
+ return value ? "1" : "0"
+ case .literal:
+ return value ? "true" : "false"
+ }
+ }
+ }
+
+ // MARK: Properties
+
+ /// Returns a default `URLEncoding` instance with a `.methodDependent` destination.
+ public static var `default`: URLEncoding { URLEncoding() }
+
+ /// Returns a `URLEncoding` instance with a `.queryString` destination.
+ public static var queryString: URLEncoding { URLEncoding(destination: .queryString) }
+
+ /// Returns a `URLEncoding` instance with an `.httpBody` destination.
+ public static var httpBody: URLEncoding { URLEncoding(destination: .httpBody) }
+
+ /// The destination defining where the encoded query string is to be applied to the URL request.
+ public let destination: Destination
+
+ /// The encoding to use for `Array` parameters.
+ public let arrayEncoding: ArrayEncoding
+
+ /// The encoding to use for `Bool` parameters.
+ public let boolEncoding: BoolEncoding
+
+ // MARK: Initialization
+
+ /// Creates an instance using the specified parameters.
+ ///
+ /// - Parameters:
+ /// - destination: `Destination` defining where the encoded query string will be applied. `.methodDependent` by
+ /// default.
+ /// - arrayEncoding: `ArrayEncoding` to use. `.brackets` by default.
+ /// - boolEncoding: `BoolEncoding` to use. `.numeric` by default.
+ public init(destination: Destination = .methodDependent,
+ arrayEncoding: ArrayEncoding = .brackets,
+ boolEncoding: BoolEncoding = .numeric) {
+ self.destination = destination
+ self.arrayEncoding = arrayEncoding
+ self.boolEncoding = boolEncoding
+ }
+
+ // MARK: Encoding
+
+ public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
+ var urlRequest = try urlRequest.asURLRequest()
+
+ guard let parameters else { return urlRequest }
+
+ if let method = urlRequest.method, destination.encodesParametersInURL(for: method) {
+ guard let url = urlRequest.url else {
+ throw AFError.parameterEncodingFailed(reason: .missingURL)
+ }
+
+ if var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false), !parameters.isEmpty {
+ let percentEncodedQuery = (urlComponents.percentEncodedQuery.map { $0 + "&" } ?? "") + query(parameters)
+ urlComponents.percentEncodedQuery = percentEncodedQuery
+ urlRequest.url = urlComponents.url
+ }
+ } else {
+ if urlRequest.headers["Content-Type"] == nil {
+ urlRequest.headers.update(.contentType("application/x-www-form-urlencoded; charset=utf-8"))
+ }
+
+ urlRequest.httpBody = Data(query(parameters).utf8)
+ }
+
+ return urlRequest
+ }
+
+ /// Creates a percent-escaped, URL encoded query string components from the given key-value pair recursively.
+ ///
+ /// - Parameters:
+ /// - key: Key of the query component.
+ /// - value: Value of the query component.
+ ///
+ /// - Returns: The percent-escaped, URL encoded query string components.
+ public func queryComponents(fromKey key: String, value: Any) -> [(String, String)] {
+ var components: [(String, String)] = []
+ switch value {
+ case let dictionary as [String: Any]:
+ for (nestedKey, value) in dictionary {
+ components += queryComponents(fromKey: "\(key)[\(nestedKey)]", value: value)
+ }
+ case let array as [Any]:
+ for (index, value) in array.enumerated() {
+ components += queryComponents(fromKey: arrayEncoding.encode(key: key, atIndex: index), value: value)
+ }
+ case let number as NSNumber:
+ if number.isBool {
+ components.append((escape(key), escape(boolEncoding.encode(value: number.boolValue))))
+ } else {
+ components.append((escape(key), escape("\(number)")))
+ }
+ case let bool as Bool:
+ components.append((escape(key), escape(boolEncoding.encode(value: bool))))
+ default:
+ components.append((escape(key), escape("\(value)")))
+ }
+ return components
+ }
+
+ /// Creates a percent-escaped string following RFC 3986 for a query string key or value.
+ ///
+ /// - Parameter string: `String` to be percent-escaped.
+ ///
+ /// - Returns: The percent-escaped `String`.
+ public func escape(_ string: String) -> String {
+ string.addingPercentEncoding(withAllowedCharacters: .afURLQueryAllowed) ?? string
+ }
+
+ private func query(_ parameters: [String: Any]) -> String {
+ var components: [(String, String)] = []
+
+ for key in parameters.keys.sorted(by: <) {
+ let value = parameters[key]!
+ components += queryComponents(fromKey: key, value: value)
+ }
+ return components.map { "\($0)=\($1)" }.joined(separator: "&")
+ }
+}
+
+// MARK: -
+
+/// Uses `JSONSerialization` to create a JSON representation of the parameters object, which is set as the body of the
+/// request. The `Content-Type` HTTP header field of an encoded request is set to `application/json`.
+public struct JSONEncoding: ParameterEncoding {
+ /// Error produced by `JSONEncoding`.
+ public enum Error: Swift.Error {
+ /// `JSONEncoding` attempted to encode an invalid JSON object. Usually this means the value included types not
+ /// representable in Objective-C. See `JSONSerialization.isValidJSONObject` for details.
+ case invalidJSONObject
+ }
+
+ // MARK: Properties
+
+ /// Returns a `JSONEncoding` instance with default writing options.
+ public static var `default`: JSONEncoding { JSONEncoding() }
+
+ /// Returns a `JSONEncoding` instance with `.prettyPrinted` writing options.
+ public static var prettyPrinted: JSONEncoding { JSONEncoding(options: .prettyPrinted) }
+
+ /// The options for writing the parameters as JSON data.
+ public let options: JSONSerialization.WritingOptions
+
+ // MARK: Initialization
+
+ /// Creates an instance using the specified `WritingOptions`.
+ ///
+ /// - Parameter options: `JSONSerialization.WritingOptions` to use.
+ public init(options: JSONSerialization.WritingOptions = []) {
+ self.options = options
+ }
+
+ // MARK: Encoding
+
+ public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
+ var urlRequest = try urlRequest.asURLRequest()
+
+ guard let parameters else { return urlRequest }
+
+ guard JSONSerialization.isValidJSONObject(parameters) else {
+ throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: Error.invalidJSONObject))
+ }
+
+ do {
+ let data = try JSONSerialization.data(withJSONObject: parameters, options: options)
+
+ if urlRequest.headers["Content-Type"] == nil {
+ urlRequest.headers.update(.contentType("application/json"))
+ }
+
+ urlRequest.httpBody = data
+ } catch {
+ throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
+ }
+
+ return urlRequest
+ }
+
+ /// Encodes any JSON compatible object into a `URLRequest`.
+ ///
+ /// - Parameters:
+ /// - urlRequest: `URLRequestConvertible` value into which the object will be encoded.
+ /// - jsonObject: `Any` value (must be JSON compatible) to be encoded into the `URLRequest`. `nil` by default.
+ ///
+ /// - Returns: The encoded `URLRequest`.
+ /// - Throws: Any `Error` produced during encoding.
+ public func encode(_ urlRequest: URLRequestConvertible, withJSONObject jsonObject: Any? = nil) throws -> URLRequest {
+ var urlRequest = try urlRequest.asURLRequest()
+
+ guard let jsonObject else { return urlRequest }
+
+ guard JSONSerialization.isValidJSONObject(jsonObject) else {
+ throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: Error.invalidJSONObject))
+ }
+
+ do {
+ let data = try JSONSerialization.data(withJSONObject: jsonObject, options: options)
+
+ if urlRequest.headers["Content-Type"] == nil {
+ urlRequest.headers.update(.contentType("application/json"))
+ }
+
+ urlRequest.httpBody = data
+ } catch {
+ throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
+ }
+
+ return urlRequest
+ }
+}
+
+extension JSONEncoding.Error {
+ public var localizedDescription: String {
+ """
+ Invalid JSON object provided for parameter or object encoding. \
+ This is most likely due to a value which can't be represented in Objective-C.
+ """
+ }
+}
+
+// MARK: -
+
+extension NSNumber {
+ fileprivate var isBool: Bool {
+ // Use Obj-C type encoding to check whether the underlying type is a `Bool`, as it's guaranteed as part of
+ // swift-corelibs-foundation, per [this discussion on the Swift forums](https://forums.swift.org/t/alamofire-on-linux-possible-but-not-release-ready/34553/22).
+ String(cString: objCType) == "c"
+ }
+}
diff --git a/ChatBot/Pods/Alamofire/Source/Core/Protected.swift b/ChatBot/Pods/Alamofire/Source/Core/Protected.swift
new file mode 100644
index 00000000..67560454
--- /dev/null
+++ b/ChatBot/Pods/Alamofire/Source/Core/Protected.swift
@@ -0,0 +1,168 @@
+//
+// Protected.swift
+//
+// Copyright (c) 2014-2020 Alamofire Software Foundation (http://alamofire.org/)
+//
+// 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 Foundation
+
+private protocol Lock {
+ func lock()
+ func unlock()
+}
+
+extension Lock {
+ /// Executes a closure returning a value while acquiring the lock.
+ ///
+ /// - Parameter closure: The closure to run.
+ ///
+ /// - Returns: The value the closure generated.
+ func around(_ closure: () throws -> T) rethrows -> T {
+ lock(); defer { unlock() }
+ return try closure()
+ }
+
+ /// Execute a closure while acquiring the lock.
+ ///
+ /// - Parameter closure: The closure to run.
+ func around(_ closure: () throws -> Void) rethrows {
+ lock(); defer { unlock() }
+ try closure()
+ }
+}
+
+#if canImport(Darwin)
+/// An `os_unfair_lock` wrapper.
+final class UnfairLock: Lock {
+ private let unfairLock: os_unfair_lock_t
+
+ init() {
+ unfairLock = .allocate(capacity: 1)
+ unfairLock.initialize(to: os_unfair_lock())
+ }
+
+ deinit {
+ unfairLock.deinitialize(count: 1)
+ unfairLock.deallocate()
+ }
+
+ fileprivate func lock() {
+ os_unfair_lock_lock(unfairLock)
+ }
+
+ fileprivate func unlock() {
+ os_unfair_lock_unlock(unfairLock)
+ }
+}
+
+#elseif canImport(Foundation)
+extension NSLock: Lock {}
+#else
+#error("This platform needs a Lock-conforming type without Foundation.")
+#endif
+
+/// A thread-safe wrapper around a value.
+@dynamicMemberLookup
+final class Protected {
+ #if canImport(Darwin)
+ private let lock = UnfairLock()
+ #elseif canImport(Foundation)
+ private let lock = NSLock()
+ #else
+ #error("This platform needs a Lock-conforming type without Foundation.")
+ #endif
+ private var value: Value
+
+ init(_ value: Value) {
+ self.value = value
+ }
+
+ /// Synchronously read or transform the contained value.
+ ///
+ /// - Parameter closure: The closure to execute.
+ ///
+ /// - Returns: The return value of the closure passed.
+ func read(_ closure: (Value) throws -> U) rethrows -> U {
+ try lock.around { try closure(self.value) }
+ }
+
+ /// Synchronously modify the protected value.
+ ///
+ /// - Parameter closure: The closure to execute.
+ ///
+ /// - Returns: The modified value.
+ @discardableResult
+ func write(_ closure: (inout Value) throws -> U) rethrows -> U {
+ try lock.around { try closure(&self.value) }
+ }
+
+ /// Synchronously update the protected value.
+ ///
+ /// - Parameter value: The `Value`.
+ func write(_ value: Value) {
+ write { $0 = value }
+ }
+
+ subscript(dynamicMember keyPath: WritableKeyPath) -> Property {
+ get { lock.around { value[keyPath: keyPath] } }
+ set { lock.around { value[keyPath: keyPath] = newValue } }
+ }
+
+ subscript(dynamicMember keyPath: KeyPath) -> Property {
+ lock.around { value[keyPath: keyPath] }
+ }
+}
+
+extension Protected where Value == Request.MutableState {
+ /// Attempts to transition to the passed `State`.
+ ///
+ /// - Parameter state: The `State` to attempt transition to.
+ ///
+ /// - Returns: Whether the transition occurred.
+ func attemptToTransitionTo(_ state: Request.State) -> Bool {
+ lock.around {
+ guard value.state.canTransitionTo(state) else { return false }
+
+ value.state = state
+
+ return true
+ }
+ }
+
+ /// Perform a closure while locked with the provided `Request.State`.
+ ///
+ /// - Parameter perform: The closure to perform while locked.
+ func withState(perform: (Request.State) -> Void) {
+ lock.around { perform(value.state) }
+ }
+}
+
+extension Protected: Equatable where Value: Equatable {
+ static func ==(lhs: Protected, rhs: Protected) -> Bool {
+ lhs.read { left in rhs.read { right in left == right }}
+ }
+}
+
+extension Protected: Hashable where Value: Hashable {
+ func hash(into hasher: inout Hasher) {
+ read { hasher.combine($0) }
+ }
+}
diff --git a/ChatBot/Pods/Alamofire/Source/Core/Request.swift b/ChatBot/Pods/Alamofire/Source/Core/Request.swift
new file mode 100644
index 00000000..e1df52e1
--- /dev/null
+++ b/ChatBot/Pods/Alamofire/Source/Core/Request.swift
@@ -0,0 +1,1090 @@
+//
+// Request.swift
+//
+// Copyright (c) 2014-2024 Alamofire Software Foundation (http://alamofire.org/)
+//
+// 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 Foundation
+
+/// `Request` is the common superclass of all Alamofire request types and provides common state, delegate, and callback
+/// handling.
+public class Request {
+ /// State of the `Request`, with managed transitions between states set when calling `resume()`, `suspend()`, or
+ /// `cancel()` on the `Request`.
+ public enum State {
+ /// Initial state of the `Request`.
+ case initialized
+ /// `State` set when `resume()` is called. Any tasks created for the `Request` will have `resume()` called on
+ /// them in this state.
+ case resumed
+ /// `State` set when `suspend()` is called. Any tasks created for the `Request` will have `suspend()` called on
+ /// them in this state.
+ case suspended
+ /// `State` set when `cancel()` is called. Any tasks created for the `Request` will have `cancel()` called on
+ /// them. Unlike `resumed` or `suspended`, once in the `cancelled` state, the `Request` can no longer transition
+ /// to any other state.
+ case cancelled
+ /// `State` set when all response serialization completion closures have been cleared on the `Request` and
+ /// enqueued on their respective queues.
+ case finished
+
+ /// Determines whether `self` can be transitioned to the provided `State`.
+ func canTransitionTo(_ state: State) -> Bool {
+ switch (self, state) {
+ case (.initialized, _):
+ return true
+ case (_, .initialized), (.cancelled, _), (.finished, _):
+ return false
+ case (.resumed, .cancelled), (.suspended, .cancelled), (.resumed, .suspended), (.suspended, .resumed):
+ return true
+ case (.suspended, .suspended), (.resumed, .resumed):
+ return false
+ case (_, .finished):
+ return true
+ }
+ }
+ }
+
+ // MARK: - Initial State
+
+ /// `UUID` providing a unique identifier for the `Request`, used in the `Hashable` and `Equatable` conformances.
+ public let id: UUID
+ /// The serial queue for all internal async actions.
+ public let underlyingQueue: DispatchQueue
+ /// The queue used for all serialization actions. By default it's a serial queue that targets `underlyingQueue`.
+ public let serializationQueue: DispatchQueue
+ /// `EventMonitor` used for event callbacks.
+ public let eventMonitor: EventMonitor?
+ /// The `Request`'s interceptor.
+ public let interceptor: RequestInterceptor?
+ /// The `Request`'s delegate.
+ public private(set) weak var delegate: RequestDelegate?
+
+ // MARK: - Mutable State
+
+ /// Type encapsulating all mutable state that may need to be accessed from anything other than the `underlyingQueue`.
+ struct MutableState {
+ /// State of the `Request`.
+ var state: State = .initialized
+ /// `ProgressHandler` and `DispatchQueue` provided for upload progress callbacks.
+ var uploadProgressHandler: (handler: ProgressHandler, queue: DispatchQueue)?
+ /// `ProgressHandler` and `DispatchQueue` provided for download progress callbacks.
+ var downloadProgressHandler: (handler: ProgressHandler, queue: DispatchQueue)?
+ /// `RedirectHandler` provided for to handle request redirection.
+ var redirectHandler: RedirectHandler?
+ /// `CachedResponseHandler` provided to handle response caching.
+ var cachedResponseHandler: CachedResponseHandler?
+ /// Queue and closure called when the `Request` is able to create a cURL description of itself.
+ var cURLHandler: (queue: DispatchQueue, handler: (String) -> Void)?
+ /// Queue and closure called when the `Request` creates a `URLRequest`.
+ var urlRequestHandler: (queue: DispatchQueue, handler: (URLRequest) -> Void)?
+ /// Queue and closure called when the `Request` creates a `URLSessionTask`.
+ var urlSessionTaskHandler: (queue: DispatchQueue, handler: (URLSessionTask) -> Void)?
+ /// Response serialization closures that handle response parsing.
+ var responseSerializers: [() -> Void] = []
+ /// Response serialization completion closures executed once all response serializers are complete.
+ var responseSerializerCompletions: [() -> Void] = []
+ /// Whether response serializer processing is finished.
+ var responseSerializerProcessingFinished = false
+ /// `URLCredential` used for authentication challenges.
+ var credential: URLCredential?
+ /// All `URLRequest`s created by Alamofire on behalf of the `Request`.
+ var requests: [URLRequest] = []
+ /// All `URLSessionTask`s created by Alamofire on behalf of the `Request`.
+ var tasks: [URLSessionTask] = []
+ /// All `URLSessionTaskMetrics` values gathered by Alamofire on behalf of the `Request`. Should correspond
+ /// exactly the the `tasks` created.
+ var metrics: [URLSessionTaskMetrics] = []
+ /// Number of times any retriers provided retried the `Request`.
+ var retryCount = 0
+ /// Final `AFError` for the `Request`, whether from various internal Alamofire calls or as a result of a `task`.
+ var error: AFError?
+ /// Whether the instance has had `finish()` called and is running the serializers. Should be replaced with a
+ /// representation in the state machine in the future.
+ var isFinishing = false
+ /// Actions to run when requests are finished. Use for concurrency support.
+ var finishHandlers: [() -> Void] = []
+ }
+
+ /// Protected `MutableState` value that provides thread-safe access to state values.
+ let mutableState = Protected(MutableState())
+
+ /// `State` of the `Request`.
+ public var state: State { mutableState.state }
+ /// Returns whether `state` is `.initialized`.
+ public var isInitialized: Bool { state == .initialized }
+ /// Returns whether `state` is `.resumed`.
+ public var isResumed: Bool { state == .resumed }
+ /// Returns whether `state` is `.suspended`.
+ public var isSuspended: Bool { state == .suspended }
+ /// Returns whether `state` is `.cancelled`.
+ public var isCancelled: Bool { state == .cancelled }
+ /// Returns whether `state` is `.finished`.
+ public var isFinished: Bool { state == .finished }
+
+ // MARK: Progress
+
+ /// Closure type executed when monitoring the upload or download progress of a request.
+ public typealias ProgressHandler = (Progress) -> Void
+
+ /// `Progress` of the upload of the body of the executed `URLRequest`. Reset to `0` if the `Request` is retried.
+ public let uploadProgress = Progress(totalUnitCount: 0)
+ /// `Progress` of the download of any response data. Reset to `0` if the `Request` is retried.
+ public let downloadProgress = Progress(totalUnitCount: 0)
+ /// `ProgressHandler` called when `uploadProgress` is updated, on the provided `DispatchQueue`.
+ public internal(set) var uploadProgressHandler: (handler: ProgressHandler, queue: DispatchQueue)? {
+ get { mutableState.uploadProgressHandler }
+ set { mutableState.uploadProgressHandler = newValue }
+ }
+
+ /// `ProgressHandler` called when `downloadProgress` is updated, on the provided `DispatchQueue`.
+ public internal(set) var downloadProgressHandler: (handler: ProgressHandler, queue: DispatchQueue)? {
+ get { mutableState.downloadProgressHandler }
+ set { mutableState.downloadProgressHandler = newValue }
+ }
+
+ // MARK: Redirect Handling
+
+ /// `RedirectHandler` set on the instance.
+ public internal(set) var redirectHandler: RedirectHandler? {
+ get { mutableState.redirectHandler }
+ set { mutableState.redirectHandler = newValue }
+ }
+
+ // MARK: Cached Response Handling
+
+ /// `CachedResponseHandler` set on the instance.
+ public internal(set) var cachedResponseHandler: CachedResponseHandler? {
+ get { mutableState.cachedResponseHandler }
+ set { mutableState.cachedResponseHandler = newValue }
+ }
+
+ // MARK: URLCredential
+
+ /// `URLCredential` used for authentication challenges. Created by calling one of the `authenticate` methods.
+ public internal(set) var credential: URLCredential? {
+ get { mutableState.credential }
+ set { mutableState.credential = newValue }
+ }
+
+ // MARK: Validators
+
+ /// `Validator` callback closures that store the validation calls enqueued.
+ let validators = Protected<[() -> Void]>([])
+
+ // MARK: URLRequests
+
+ /// All `URLRequest`s created on behalf of the `Request`, including original and adapted requests.
+ public var requests: [URLRequest] { mutableState.requests }
+ /// First `URLRequest` created on behalf of the `Request`. May not be the first one actually executed.
+ public var firstRequest: URLRequest? { requests.first }
+ /// Last `URLRequest` created on behalf of the `Request`.
+ public var lastRequest: URLRequest? { requests.last }
+ /// Current `URLRequest` created on behalf of the `Request`.
+ public var request: URLRequest? { lastRequest }
+
+ /// `URLRequest`s from all of the `URLSessionTask`s executed on behalf of the `Request`. May be different from
+ /// `requests` due to `URLSession` manipulation.
+ public var performedRequests: [URLRequest] { mutableState.read { $0.tasks.compactMap(\.currentRequest) } }
+
+ // MARK: HTTPURLResponse
+
+ /// `HTTPURLResponse` received from the server, if any. If the `Request` was retried, this is the response of the
+ /// last `URLSessionTask`.
+ public var response: HTTPURLResponse? { lastTask?.response as? HTTPURLResponse }
+
+ // MARK: Tasks
+
+ /// All `URLSessionTask`s created on behalf of the `Request`.
+ public var tasks: [URLSessionTask] { mutableState.tasks }
+ /// First `URLSessionTask` created on behalf of the `Request`.
+ public var firstTask: URLSessionTask? { tasks.first }
+ /// Last `URLSessionTask` created on behalf of the `Request`.
+ public var lastTask: URLSessionTask? { tasks.last }
+ /// Current `URLSessionTask` created on behalf of the `Request`.
+ public var task: URLSessionTask? { lastTask }
+
+ // MARK: Metrics
+
+ /// All `URLSessionTaskMetrics` gathered on behalf of the `Request`. Should correspond to the `tasks` created.
+ public var allMetrics: [URLSessionTaskMetrics] { mutableState.metrics }
+ /// First `URLSessionTaskMetrics` gathered on behalf of the `Request`.
+ public var firstMetrics: URLSessionTaskMetrics? { allMetrics.first }
+ /// Last `URLSessionTaskMetrics` gathered on behalf of the `Request`.
+ public var lastMetrics: URLSessionTaskMetrics? { allMetrics.last }
+ /// Current `URLSessionTaskMetrics` gathered on behalf of the `Request`.
+ public var metrics: URLSessionTaskMetrics? { lastMetrics }
+
+ // MARK: Retry Count
+
+ /// Number of times the `Request` has been retried.
+ public var retryCount: Int { mutableState.retryCount }
+
+ // MARK: Error
+
+ /// `Error` returned from Alamofire internally, from the network request directly, or any validators executed.
+ public internal(set) var error: AFError? {
+ get { mutableState.error }
+ set { mutableState.error = newValue }
+ }
+
+ /// Default initializer for the `Request` superclass.
+ ///
+ /// - Parameters:
+ /// - id: `UUID` used for the `Hashable` and `Equatable` implementations. `UUID()` by default.
+ /// - underlyingQueue: `DispatchQueue` on which all internal `Request` work is performed.
+ /// - serializationQueue: `DispatchQueue` on which all serialization work is performed. By default targets
+ /// `underlyingQueue`, but can be passed another queue from a `Session`.
+ /// - eventMonitor: `EventMonitor` called for event callbacks from internal `Request` actions.
+ /// - interceptor: `RequestInterceptor` used throughout the request lifecycle.
+ /// - delegate: `RequestDelegate` that provides an interface to actions not performed by the `Request`.
+ init(id: UUID = UUID(),
+ underlyingQueue: DispatchQueue,
+ serializationQueue: DispatchQueue,
+ eventMonitor: EventMonitor?,
+ interceptor: RequestInterceptor?,
+ delegate: RequestDelegate) {
+ self.id = id
+ self.underlyingQueue = underlyingQueue
+ self.serializationQueue = serializationQueue
+ self.eventMonitor = eventMonitor
+ self.interceptor = interceptor
+ self.delegate = delegate
+ }
+
+ // MARK: - Internal Event API
+
+ // All API must be called from underlyingQueue.
+
+ /// Called when an initial `URLRequest` has been created on behalf of the instance. If a `RequestAdapter` is active,
+ /// the `URLRequest` will be adapted before being issued.
+ ///
+ /// - Parameter request: The `URLRequest` created.
+ func didCreateInitialURLRequest(_ request: URLRequest) {
+ dispatchPrecondition(condition: .onQueue(underlyingQueue))
+
+ mutableState.write { $0.requests.append(request) }
+
+ eventMonitor?.request(self, didCreateInitialURLRequest: request)
+ }
+
+ /// Called when initial `URLRequest` creation has failed, typically through a `URLRequestConvertible`.
+ ///
+ /// - Note: Triggers retry.
+ ///
+ /// - Parameter error: `AFError` thrown from the failed creation.
+ func didFailToCreateURLRequest(with error: AFError) {
+ dispatchPrecondition(condition: .onQueue(underlyingQueue))
+
+ self.error = error
+
+ eventMonitor?.request(self, didFailToCreateURLRequestWithError: error)
+
+ callCURLHandlerIfNecessary()
+
+ retryOrFinish(error: error)
+ }
+
+ /// Called when a `RequestAdapter` has successfully adapted a `URLRequest`.
+ ///
+ /// - Parameters:
+ /// - initialRequest: The `URLRequest` that was adapted.
+ /// - adaptedRequest: The `URLRequest` returned by the `RequestAdapter`.
+ func didAdaptInitialRequest(_ initialRequest: URLRequest, to adaptedRequest: URLRequest) {
+ dispatchPrecondition(condition: .onQueue(underlyingQueue))
+
+ mutableState.write { $0.requests.append(adaptedRequest) }
+
+ eventMonitor?.request(self, didAdaptInitialRequest: initialRequest, to: adaptedRequest)
+ }
+
+ /// Called when a `RequestAdapter` fails to adapt a `URLRequest`.
+ ///
+ /// - Note: Triggers retry.
+ ///
+ /// - Parameters:
+ /// - request: The `URLRequest` the adapter was called with.
+ /// - error: The `AFError` returned by the `RequestAdapter`.
+ func didFailToAdaptURLRequest(_ request: URLRequest, withError error: AFError) {
+ dispatchPrecondition(condition: .onQueue(underlyingQueue))
+
+ self.error = error
+
+ eventMonitor?.request(self, didFailToAdaptURLRequest: request, withError: error)
+
+ callCURLHandlerIfNecessary()
+
+ retryOrFinish(error: error)
+ }
+
+ /// Final `URLRequest` has been created for the instance.
+ ///
+ /// - Parameter request: The `URLRequest` created.
+ func didCreateURLRequest(_ request: URLRequest) {
+ dispatchPrecondition(condition: .onQueue(underlyingQueue))
+
+ mutableState.read { state in
+ state.urlRequestHandler?.queue.async { state.urlRequestHandler?.handler(request) }
+ }
+
+ eventMonitor?.request(self, didCreateURLRequest: request)
+
+ callCURLHandlerIfNecessary()
+ }
+
+ /// Asynchronously calls any stored `cURLHandler` and then removes it from `mutableState`.
+ private func callCURLHandlerIfNecessary() {
+ mutableState.write { mutableState in
+ guard let cURLHandler = mutableState.cURLHandler else { return }
+
+ cURLHandler.queue.async { cURLHandler.handler(self.cURLDescription()) }
+
+ mutableState.cURLHandler = nil
+ }
+ }
+
+ /// Called when a `URLSessionTask` is created on behalf of the instance.
+ ///
+ /// - Parameter task: The `URLSessionTask` created.
+ func didCreateTask(_ task: URLSessionTask) {
+ dispatchPrecondition(condition: .onQueue(underlyingQueue))
+
+ mutableState.write { state in
+ state.tasks.append(task)
+
+ guard let urlSessionTaskHandler = state.urlSessionTaskHandler else { return }
+
+ urlSessionTaskHandler.queue.async { urlSessionTaskHandler.handler(task) }
+ }
+
+ eventMonitor?.request(self, didCreateTask: task)
+ }
+
+ /// Called when resumption is completed.
+ func didResume() {
+ dispatchPrecondition(condition: .onQueue(underlyingQueue))
+
+ eventMonitor?.requestDidResume(self)
+ }
+
+ /// Called when a `URLSessionTask` is resumed on behalf of the instance.
+ ///
+ /// - Parameter task: The `URLSessionTask` resumed.
+ func didResumeTask(_ task: URLSessionTask) {
+ dispatchPrecondition(condition: .onQueue(underlyingQueue))
+
+ eventMonitor?.request(self, didResumeTask: task)
+ }
+
+ /// Called when suspension is completed.
+ func didSuspend() {
+ dispatchPrecondition(condition: .onQueue(underlyingQueue))
+
+ eventMonitor?.requestDidSuspend(self)
+ }
+
+ /// Called when a `URLSessionTask` is suspended on behalf of the instance.
+ ///
+ /// - Parameter task: The `URLSessionTask` suspended.
+ func didSuspendTask(_ task: URLSessionTask) {
+ dispatchPrecondition(condition: .onQueue(underlyingQueue))
+
+ eventMonitor?.request(self, didSuspendTask: task)
+ }
+
+ /// Called when cancellation is completed, sets `error` to `AFError.explicitlyCancelled`.
+ func didCancel() {
+ dispatchPrecondition(condition: .onQueue(underlyingQueue))
+
+ mutableState.write { mutableState in
+ mutableState.error = mutableState.error ?? AFError.explicitlyCancelled
+ }
+
+ eventMonitor?.requestDidCancel(self)
+ }
+
+ /// Called when a `URLSessionTask` is cancelled on behalf of the instance.
+ ///
+ /// - Parameter task: The `URLSessionTask` cancelled.
+ func didCancelTask(_ task: URLSessionTask) {
+ dispatchPrecondition(condition: .onQueue(underlyingQueue))
+
+ eventMonitor?.request(self, didCancelTask: task)
+ }
+
+ /// Called when a `URLSessionTaskMetrics` value is gathered on behalf of the instance.
+ ///
+ /// - Parameter metrics: The `URLSessionTaskMetrics` gathered.
+ func didGatherMetrics(_ metrics: URLSessionTaskMetrics) {
+ dispatchPrecondition(condition: .onQueue(underlyingQueue))
+
+ mutableState.write { $0.metrics.append(metrics) }
+
+ eventMonitor?.request(self, didGatherMetrics: metrics)
+ }
+
+ /// Called when a `URLSessionTask` fails before it is finished, typically during certificate pinning.
+ ///
+ /// - Parameters:
+ /// - task: The `URLSessionTask` which failed.
+ /// - error: The early failure `AFError`.
+ func didFailTask(_ task: URLSessionTask, earlyWithError error: AFError) {
+ dispatchPrecondition(condition: .onQueue(underlyingQueue))
+
+ self.error = error
+
+ // Task will still complete, so didCompleteTask(_:with:) will handle retry.
+ eventMonitor?.request(self, didFailTask: task, earlyWithError: error)
+ }
+
+ /// Called when a `URLSessionTask` completes. All tasks will eventually call this method.
+ ///
+ /// - Note: Response validation is synchronously triggered in this step.
+ ///
+ /// - Parameters:
+ /// - task: The `URLSessionTask` which completed.
+ /// - error: The `AFError` `task` may have completed with. If `error` has already been set on the instance, this
+ /// value is ignored.
+ func didCompleteTask(_ task: URLSessionTask, with error: AFError?) {
+ dispatchPrecondition(condition: .onQueue(underlyingQueue))
+
+ self.error = self.error ?? error
+
+ let validators = validators.read { $0 }
+ validators.forEach { $0() }
+
+ eventMonitor?.request(self, didCompleteTask: task, with: error)
+
+ retryOrFinish(error: self.error)
+ }
+
+ /// Called when the `RequestDelegate` is going to retry this `Request`. Calls `reset()`.
+ func prepareForRetry() {
+ dispatchPrecondition(condition: .onQueue(underlyingQueue))
+
+ mutableState.write { $0.retryCount += 1 }
+
+ reset()
+
+ eventMonitor?.requestIsRetrying(self)
+ }
+
+ /// Called to determine whether retry will be triggered for the particular error, or whether the instance should
+ /// call `finish()`.
+ ///
+ /// - Parameter error: The possible `AFError` which may trigger retry.
+ func retryOrFinish(error: AFError?) {
+ dispatchPrecondition(condition: .onQueue(underlyingQueue))
+
+ guard !isCancelled, let error, let delegate else { finish(); return }
+
+ delegate.retryResult(for: self, dueTo: error) { retryResult in
+ switch retryResult {
+ case .doNotRetry:
+ self.finish()
+ case let .doNotRetryWithError(retryError):
+ self.finish(error: retryError.asAFError(orFailWith: "Received retryError was not already AFError"))
+ case .retry, .retryWithDelay:
+ delegate.retryRequest(self, withDelay: retryResult.delay)
+ }
+ }
+ }
+
+ /// Finishes this `Request` and starts the response serializers.
+ ///
+ /// - Parameter error: The possible `Error` with which the instance will finish.
+ func finish(error: AFError? = nil) {
+ dispatchPrecondition(condition: .onQueue(underlyingQueue))
+
+ guard !mutableState.isFinishing else { return }
+
+ mutableState.isFinishing = true
+
+ if let error { self.error = error }
+
+ // Start response handlers
+ processNextResponseSerializer()
+
+ eventMonitor?.requestDidFinish(self)
+ }
+
+ /// Appends the response serialization closure to the instance.
+ ///
+ /// - Note: This method will also `resume` the instance if `delegate.startImmediately` returns `true`.
+ ///
+ /// - Parameter closure: The closure containing the response serialization call.
+ func appendResponseSerializer(_ closure: @escaping () -> Void) {
+ mutableState.write { mutableState in
+ mutableState.responseSerializers.append(closure)
+
+ if mutableState.state == .finished {
+ mutableState.state = .resumed
+ }
+
+ if mutableState.responseSerializerProcessingFinished {
+ underlyingQueue.async { self.processNextResponseSerializer() }
+ }
+
+ if mutableState.state.canTransitionTo(.resumed) {
+ underlyingQueue.async { if self.delegate?.startImmediately == true { self.resume() } }
+ }
+ }
+ }
+
+ /// Returns the next response serializer closure to execute if there's one left.
+ ///
+ /// - Returns: The next response serialization closure, if there is one.
+ func nextResponseSerializer() -> (() -> Void)? {
+ var responseSerializer: (() -> Void)?
+
+ mutableState.write { mutableState in
+ let responseSerializerIndex = mutableState.responseSerializerCompletions.count
+
+ if responseSerializerIndex < mutableState.responseSerializers.count {
+ responseSerializer = mutableState.responseSerializers[responseSerializerIndex]
+ }
+ }
+
+ return responseSerializer
+ }
+
+ /// Processes the next response serializer and calls all completions if response serialization is complete.
+ func processNextResponseSerializer() {
+ guard let responseSerializer = nextResponseSerializer() else {
+ // Execute all response serializer completions and clear them
+ var completions: [() -> Void] = []
+
+ mutableState.write { mutableState in
+ completions = mutableState.responseSerializerCompletions
+
+ // Clear out all response serializers and response serializer completions in mutable state since the
+ // request is complete. It's important to do this prior to calling the completion closures in case
+ // the completions call back into the request triggering a re-processing of the response serializers.
+ // An example of how this can happen is by calling cancel inside a response completion closure.
+ mutableState.responseSerializers.removeAll()
+ mutableState.responseSerializerCompletions.removeAll()
+
+ if mutableState.state.canTransitionTo(.finished) {
+ mutableState.state = .finished
+ }
+
+ mutableState.responseSerializerProcessingFinished = true
+ mutableState.isFinishing = false
+ }
+
+ completions.forEach { $0() }
+
+ // Cleanup the request
+ cleanup()
+
+ return
+ }
+
+ serializationQueue.async { responseSerializer() }
+ }
+
+ /// Notifies the `Request` that the response serializer is complete.
+ ///
+ /// - Parameter completion: The completion handler provided with the response serializer, called when all serializers
+ /// are complete.
+ func responseSerializerDidComplete(completion: @escaping () -> Void) {
+ mutableState.write { $0.responseSerializerCompletions.append(completion) }
+ processNextResponseSerializer()
+ }
+
+ /// Resets all task and response serializer related state for retry.
+ func reset() {
+ error = nil
+
+ uploadProgress.totalUnitCount = 0
+ uploadProgress.completedUnitCount = 0
+ downloadProgress.totalUnitCount = 0
+ downloadProgress.completedUnitCount = 0
+
+ mutableState.write { state in
+ state.isFinishing = false
+ state.responseSerializerCompletions = []
+ }
+ }
+
+ /// Called when updating the upload progress.
+ ///
+ /// - Parameters:
+ /// - totalBytesSent: Total bytes sent so far.
+ /// - totalBytesExpectedToSend: Total bytes expected to send.
+ func updateUploadProgress(totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
+ uploadProgress.totalUnitCount = totalBytesExpectedToSend
+ uploadProgress.completedUnitCount = totalBytesSent
+
+ uploadProgressHandler?.queue.async { self.uploadProgressHandler?.handler(self.uploadProgress) }
+ }
+
+ /// Perform a closure on the current `state` while locked.
+ ///
+ /// - Parameter perform: The closure to perform.
+ func withState(perform: (State) -> Void) {
+ mutableState.withState(perform: perform)
+ }
+
+ // MARK: Task Creation
+
+ /// Called when creating a `URLSessionTask` for this `Request`. Subclasses must override.
+ ///
+ /// - Parameters:
+ /// - request: `URLRequest` to use to create the `URLSessionTask`.
+ /// - session: `URLSession` which creates the `URLSessionTask`.
+ ///
+ /// - Returns: The `URLSessionTask` created.
+ func task(for request: URLRequest, using session: URLSession) -> URLSessionTask {
+ fatalError("Subclasses must override.")
+ }
+
+ // MARK: - Public API
+
+ // These APIs are callable from any queue.
+
+ // MARK: State
+
+ /// Cancels the instance. Once cancelled, a `Request` can no longer be resumed or suspended.
+ ///
+ /// - Returns: The instance.
+ @discardableResult
+ public func cancel() -> Self {
+ mutableState.write { mutableState in
+ guard mutableState.state.canTransitionTo(.cancelled) else { return }
+
+ mutableState.state = .cancelled
+
+ underlyingQueue.async { self.didCancel() }
+
+ guard let task = mutableState.tasks.last, task.state != .completed else {
+ underlyingQueue.async { self.finish() }
+ return
+ }
+
+ // Resume to ensure metrics are gathered.
+ task.resume()
+ task.cancel()
+ underlyingQueue.async { self.didCancelTask(task) }
+ }
+
+ return self
+ }
+
+ /// Suspends the instance.
+ ///
+ /// - Returns: The instance.
+ @discardableResult
+ public func suspend() -> Self {
+ mutableState.write { mutableState in
+ guard mutableState.state.canTransitionTo(.suspended) else { return }
+
+ mutableState.state = .suspended
+
+ underlyingQueue.async { self.didSuspend() }
+
+ guard let task = mutableState.tasks.last, task.state != .completed else { return }
+
+ task.suspend()
+ underlyingQueue.async { self.didSuspendTask(task) }
+ }
+
+ return self
+ }
+
+ /// Resumes the instance.
+ ///
+ /// - Returns: The instance.
+ @discardableResult
+ public func resume() -> Self {
+ mutableState.write { mutableState in
+ guard mutableState.state.canTransitionTo(.resumed) else { return }
+
+ mutableState.state = .resumed
+
+ underlyingQueue.async { self.didResume() }
+
+ guard let task = mutableState.tasks.last, task.state != .completed else { return }
+
+ task.resume()
+ underlyingQueue.async { self.didResumeTask(task) }
+ }
+
+ return self
+ }
+
+ // MARK: - Closure API
+
+ /// Associates a credential using the provided values with the instance.
+ ///
+ /// - Parameters:
+ /// - username: The username.
+ /// - password: The password.
+ /// - persistence: The `URLCredential.Persistence` for the created `URLCredential`. `.forSession` by default.
+ ///
+ /// - Returns: The instance.
+ @discardableResult
+ public func authenticate(username: String, password: String, persistence: URLCredential.Persistence = .forSession) -> Self {
+ let credential = URLCredential(user: username, password: password, persistence: persistence)
+
+ return authenticate(with: credential)
+ }
+
+ /// Associates the provided credential with the instance.
+ ///
+ /// - Parameter credential: The `URLCredential`.
+ ///
+ /// - Returns: The instance.
+ @discardableResult
+ public func authenticate(with credential: URLCredential) -> Self {
+ mutableState.credential = credential
+
+ return self
+ }
+
+ /// Sets a closure to be called periodically during the lifecycle of the instance as data is read from the server.
+ ///
+ /// - Note: Only the last closure provided is used.
+ ///
+ /// - Parameters:
+ /// - queue: The `DispatchQueue` to execute the closure on. `.main` by default.
+ /// - closure: The closure to be executed periodically as data is read from the server.
+ ///
+ /// - Returns: The instance.
+ @discardableResult
+ public func downloadProgress(queue: DispatchQueue = .main, closure: @escaping ProgressHandler) -> Self {
+ mutableState.downloadProgressHandler = (handler: closure, queue: queue)
+
+ return self
+ }
+
+ /// Sets a closure to be called periodically during the lifecycle of the instance as data is sent to the server.
+ ///
+ /// - Note: Only the last closure provided is used.
+ ///
+ /// - Parameters:
+ /// - queue: The `DispatchQueue` to execute the closure on. `.main` by default.
+ /// - closure: The closure to be executed periodically as data is sent to the server.
+ ///
+ /// - Returns: The instance.
+ @discardableResult
+ public func uploadProgress(queue: DispatchQueue = .main, closure: @escaping ProgressHandler) -> Self {
+ mutableState.uploadProgressHandler = (handler: closure, queue: queue)
+
+ return self
+ }
+
+ // MARK: Redirects
+
+ /// Sets the redirect handler for the instance which will be used if a redirect response is encountered.
+ ///
+ /// - Note: Attempting to set the redirect handler more than once is a logic error and will crash.
+ ///
+ /// - Parameter handler: The `RedirectHandler`.
+ ///
+ /// - Returns: The instance.
+ @discardableResult
+ public func redirect(using handler: RedirectHandler) -> Self {
+ mutableState.write { mutableState in
+ precondition(mutableState.redirectHandler == nil, "Redirect handler has already been set.")
+ mutableState.redirectHandler = handler
+ }
+
+ return self
+ }
+
+ // MARK: Cached Responses
+
+ /// Sets the cached response handler for the `Request` which will be used when attempting to cache a response.
+ ///
+ /// - Note: Attempting to set the cache handler more than once is a logic error and will crash.
+ ///
+ /// - Parameter handler: The `CachedResponseHandler`.
+ ///
+ /// - Returns: The instance.
+ @discardableResult
+ public func cacheResponse(using handler: CachedResponseHandler) -> Self {
+ mutableState.write { mutableState in
+ precondition(mutableState.cachedResponseHandler == nil, "Cached response handler has already been set.")
+ mutableState.cachedResponseHandler = handler
+ }
+
+ return self
+ }
+
+ // MARK: - Lifetime APIs
+
+ /// Sets a handler to be called when the cURL description of the request is available.
+ ///
+ /// - Note: When waiting for a `Request`'s `URLRequest` to be created, only the last `handler` will be called.
+ ///
+ /// - Parameters:
+ /// - queue: `DispatchQueue` on which `handler` will be called.
+ /// - handler: Closure to be called when the cURL description is available.
+ ///
+ /// - Returns: The instance.
+ @discardableResult
+ public func cURLDescription(on queue: DispatchQueue, calling handler: @escaping (String) -> Void) -> Self {
+ mutableState.write { mutableState in
+ if mutableState.requests.last != nil {
+ queue.async { handler(self.cURLDescription()) }
+ } else {
+ mutableState.cURLHandler = (queue, handler)
+ }
+ }
+
+ return self
+ }
+
+ /// Sets a handler to be called when the cURL description of the request is available.
+ ///
+ /// - Note: When waiting for a `Request`'s `URLRequest` to be created, only the last `handler` will be called.
+ ///
+ /// - Parameter handler: Closure to be called when the cURL description is available. Called on the instance's
+ /// `underlyingQueue` by default.
+ ///
+ /// - Returns: The instance.
+ @discardableResult
+ public func cURLDescription(calling handler: @escaping (String) -> Void) -> Self {
+ cURLDescription(on: underlyingQueue, calling: handler)
+
+ return self
+ }
+
+ /// Sets a closure to called whenever Alamofire creates a `URLRequest` for this instance.
+ ///
+ /// - Note: This closure will be called multiple times if the instance adapts incoming `URLRequest`s or is retried.
+ ///
+ /// - Parameters:
+ /// - queue: `DispatchQueue` on which `handler` will be called. `.main` by default.
+ /// - handler: Closure to be called when a `URLRequest` is available.
+ ///
+ /// - Returns: The instance.
+ @discardableResult
+ public func onURLRequestCreation(on queue: DispatchQueue = .main, perform handler: @escaping (URLRequest) -> Void) -> Self {
+ mutableState.write { state in
+ if let request = state.requests.last {
+ queue.async { handler(request) }
+ }
+
+ state.urlRequestHandler = (queue, handler)
+ }
+
+ return self
+ }
+
+ /// Sets a closure to be called whenever the instance creates a `URLSessionTask`.
+ ///
+ /// - Note: This API should only be used to provide `URLSessionTask`s to existing API, like `NSFileProvider`. It
+ /// **SHOULD NOT** be used to interact with tasks directly, as that may be break Alamofire features.
+ /// Additionally, this closure may be called multiple times if the instance is retried.
+ ///
+ /// - Parameters:
+ /// - queue: `DispatchQueue` on which `handler` will be called. `.main` by default.
+ /// - handler: Closure to be called when the `URLSessionTask` is available.
+ ///
+ /// - Returns: The instance.
+ @discardableResult
+ public func onURLSessionTaskCreation(on queue: DispatchQueue = .main, perform handler: @escaping (URLSessionTask) -> Void) -> Self {
+ mutableState.write { state in
+ if let task = state.tasks.last {
+ queue.async { handler(task) }
+ }
+
+ state.urlSessionTaskHandler = (queue, handler)
+ }
+
+ return self
+ }
+
+ // MARK: Cleanup
+
+ /// Adds a `finishHandler` closure to be called when the request completes.
+ ///
+ /// - Parameter closure: Closure to be called when the request finishes.
+ func onFinish(perform finishHandler: @escaping () -> Void) {
+ guard !isFinished else { finishHandler(); return }
+
+ mutableState.write { state in
+ state.finishHandlers.append(finishHandler)
+ }
+ }
+
+ /// Final cleanup step executed when the instance finishes response serialization.
+ func cleanup() {
+ let handlers = mutableState.finishHandlers
+ handlers.forEach { $0() }
+ mutableState.write { state in
+ state.finishHandlers.removeAll()
+ }
+
+ delegate?.cleanup(after: self)
+ }
+}
+
+extension Request {
+ /// Type indicating how a `DataRequest` or `DataStreamRequest` should proceed after receiving an `HTTPURLResponse`.
+ public enum ResponseDisposition {
+ /// Allow the request to continue normally.
+ case allow
+ /// Cancel the request, similar to calling `cancel()`.
+ case cancel
+
+ var sessionDisposition: URLSession.ResponseDisposition {
+ switch self {
+ case .allow: return .allow
+ case .cancel: return .cancel
+ }
+ }
+ }
+}
+
+// MARK: - Protocol Conformances
+
+extension Request: Equatable {
+ public static func ==(lhs: Request, rhs: Request) -> Bool {
+ lhs.id == rhs.id
+ }
+}
+
+extension Request: Hashable {
+ public func hash(into hasher: inout Hasher) {
+ hasher.combine(id)
+ }
+}
+
+extension Request: CustomStringConvertible {
+ /// A textual representation of this instance, including the `HTTPMethod` and `URL` if the `URLRequest` has been
+ /// created, as well as the response status code, if a response has been received.
+ public var description: String {
+ guard let request = performedRequests.last ?? lastRequest,
+ let url = request.url,
+ let method = request.httpMethod else { return "No request created yet." }
+
+ let requestDescription = "\(method) \(url.absoluteString)"
+
+ return response.map { "\(requestDescription) (\($0.statusCode))" } ?? requestDescription
+ }
+}
+
+extension Request {
+ /// cURL representation of the instance.
+ ///
+ /// - Returns: The cURL equivalent of the instance.
+ public func cURLDescription() -> String {
+ guard
+ let request = lastRequest,
+ let url = request.url,
+ let host = url.host,
+ let method = request.httpMethod else { return "$ curl command could not be created" }
+
+ var components = ["$ curl -v"]
+
+ components.append("-X \(method)")
+
+ if let credentialStorage = delegate?.sessionConfiguration.urlCredentialStorage {
+ let protectionSpace = URLProtectionSpace(host: host,
+ port: url.port ?? 0,
+ protocol: url.scheme,
+ realm: host,
+ authenticationMethod: NSURLAuthenticationMethodHTTPBasic)
+
+ if let credentials = credentialStorage.credentials(for: protectionSpace)?.values {
+ for credential in credentials {
+ guard let user = credential.user, let password = credential.password else { continue }
+ components.append("-u \(user):\(password)")
+ }
+ } else {
+ if let credential, let user = credential.user, let password = credential.password {
+ components.append("-u \(user):\(password)")
+ }
+ }
+ }
+
+ if let configuration = delegate?.sessionConfiguration, configuration.httpShouldSetCookies {
+ if
+ let cookieStorage = configuration.httpCookieStorage,
+ let cookies = cookieStorage.cookies(for: url), !cookies.isEmpty {
+ let allCookies = cookies.map { "\($0.name)=\($0.value)" }.joined(separator: ";")
+
+ components.append("-b \"\(allCookies)\"")
+ }
+ }
+
+ var headers = HTTPHeaders()
+
+ if let sessionHeaders = delegate?.sessionConfiguration.headers {
+ for header in sessionHeaders where header.name != "Cookie" {
+ headers[header.name] = header.value
+ }
+ }
+
+ for header in request.headers where header.name != "Cookie" {
+ headers[header.name] = header.value
+ }
+
+ for header in headers {
+ let escapedValue = header.value.replacingOccurrences(of: "\"", with: "\\\"")
+ components.append("-H \"\(header.name): \(escapedValue)\"")
+ }
+
+ if let httpBodyData = request.httpBody {
+ let httpBody = String(decoding: httpBodyData, as: UTF8.self)
+ var escapedBody = httpBody.replacingOccurrences(of: "\\\"", with: "\\\\\"")
+ escapedBody = escapedBody.replacingOccurrences(of: "\"", with: "\\\"")
+
+ components.append("-d \"\(escapedBody)\"")
+ }
+
+ components.append("\"\(url.absoluteString)\"")
+
+ return components.joined(separator: " \\\n\t")
+ }
+}
+
+/// Protocol abstraction for `Request`'s communication back to the `SessionDelegate`.
+public protocol RequestDelegate: AnyObject {
+ /// `URLSessionConfiguration` used to create the underlying `URLSessionTask`s.
+ var sessionConfiguration: URLSessionConfiguration { get }
+
+ /// Determines whether the `Request` should automatically call `resume()` when adding the first response handler.
+ var startImmediately: Bool { get }
+
+ /// Notifies the delegate the `Request` has reached a point where it needs cleanup.
+ ///
+ /// - Parameter request: The `Request` to cleanup after.
+ func cleanup(after request: Request)
+
+ /// Asynchronously ask the delegate whether a `Request` will be retried.
+ ///
+ /// - Parameters:
+ /// - request: `Request` which failed.
+ /// - error: `Error` which produced the failure.
+ /// - completion: Closure taking the `RetryResult` for evaluation.
+ func retryResult(for request: Request, dueTo error: AFError, completion: @escaping (RetryResult) -> Void)
+
+ /// Asynchronously retry the `Request`.
+ ///
+ /// - Parameters:
+ /// - request: `Request` which will be retried.
+ /// - timeDelay: `TimeInterval` after which the retry will be triggered.
+ func retryRequest(_ request: Request, withDelay timeDelay: TimeInterval?)
+}
diff --git a/ChatBot/Pods/Alamofire/Source/Core/RequestTaskMap.swift b/ChatBot/Pods/Alamofire/Source/Core/RequestTaskMap.swift
new file mode 100644
index 00000000..e49e564a
--- /dev/null
+++ b/ChatBot/Pods/Alamofire/Source/Core/RequestTaskMap.swift
@@ -0,0 +1,150 @@
+//
+// RequestTaskMap.swift
+//
+// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+// 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 Foundation
+
+/// A type that maintains a two way, one to one map of `URLSessionTask`s to `Request`s.
+struct RequestTaskMap {
+ private typealias Events = (completed: Bool, metricsGathered: Bool)
+
+ private var tasksToRequests: [URLSessionTask: Request]
+ private var requestsToTasks: [Request: URLSessionTask]
+ private var taskEvents: [URLSessionTask: Events]
+
+ var requests: [Request] {
+ Array(tasksToRequests.values)
+ }
+
+ init(tasksToRequests: [URLSessionTask: Request] = [:],
+ requestsToTasks: [Request: URLSessionTask] = [:],
+ taskEvents: [URLSessionTask: (completed: Bool, metricsGathered: Bool)] = [:]) {
+ self.tasksToRequests = tasksToRequests
+ self.requestsToTasks = requestsToTasks
+ self.taskEvents = taskEvents
+ }
+
+ subscript(_ request: Request) -> URLSessionTask? {
+ get { requestsToTasks[request] }
+ set {
+ guard let newValue else {
+ guard let task = requestsToTasks[request] else {
+ fatalError("RequestTaskMap consistency error: no task corresponding to request found.")
+ }
+
+ requestsToTasks.removeValue(forKey: request)
+ tasksToRequests.removeValue(forKey: task)
+ taskEvents.removeValue(forKey: task)
+
+ return
+ }
+
+ requestsToTasks[request] = newValue
+ tasksToRequests[newValue] = request
+ taskEvents[newValue] = (completed: false, metricsGathered: false)
+ }
+ }
+
+ subscript(_ task: URLSessionTask) -> Request? {
+ get { tasksToRequests[task] }
+ set {
+ guard let newValue else {
+ guard let request = tasksToRequests[task] else {
+ fatalError("RequestTaskMap consistency error: no request corresponding to task found.")
+ }
+
+ tasksToRequests.removeValue(forKey: task)
+ requestsToTasks.removeValue(forKey: request)
+ taskEvents.removeValue(forKey: task)
+
+ return
+ }
+
+ tasksToRequests[task] = newValue
+ requestsToTasks[newValue] = task
+ taskEvents[task] = (completed: false, metricsGathered: false)
+ }
+ }
+
+ var count: Int {
+ precondition(tasksToRequests.count == requestsToTasks.count,
+ "RequestTaskMap.count invalid, requests.count: \(tasksToRequests.count) != tasks.count: \(requestsToTasks.count)")
+
+ return tasksToRequests.count
+ }
+
+ var eventCount: Int {
+ precondition(taskEvents.count == count, "RequestTaskMap.eventCount invalid, count: \(count) != taskEvents.count: \(taskEvents.count)")
+
+ return taskEvents.count
+ }
+
+ var isEmpty: Bool {
+ precondition(tasksToRequests.isEmpty == requestsToTasks.isEmpty,
+ "RequestTaskMap.isEmpty invalid, requests.isEmpty: \(tasksToRequests.isEmpty) != tasks.isEmpty: \(requestsToTasks.isEmpty)")
+
+ return tasksToRequests.isEmpty
+ }
+
+ var isEventsEmpty: Bool {
+ precondition(taskEvents.isEmpty == isEmpty, "RequestTaskMap.isEventsEmpty invalid, isEmpty: \(isEmpty) != taskEvents.isEmpty: \(taskEvents.isEmpty)")
+
+ return taskEvents.isEmpty
+ }
+
+ mutating func disassociateIfNecessaryAfterGatheringMetricsForTask(_ task: URLSessionTask) -> Bool {
+ guard let events = taskEvents[task] else {
+ fatalError("RequestTaskMap consistency error: no events corresponding to task found.")
+ }
+
+ switch (events.completed, events.metricsGathered) {
+ case (_, true): fatalError("RequestTaskMap consistency error: duplicate metricsGatheredForTask call.")
+ case (false, false): taskEvents[task] = (completed: false, metricsGathered: true); return false
+ case (true, false): self[task] = nil; return true
+ }
+ }
+
+ mutating func disassociateIfNecessaryAfterCompletingTask(_ task: URLSessionTask) -> Bool {
+ guard let events = taskEvents[task] else {
+ fatalError("RequestTaskMap consistency error: no events corresponding to task found.")
+ }
+
+ switch (events.completed, events.metricsGathered) {
+ case (true, _): fatalError("RequestTaskMap consistency error: duplicate completionReceivedForTask call.")
+ // swift-corelibs-foundation doesn't gather metrics, so unconditionally remove the reference and return true.
+ #if canImport(FoundationNetworking)
+ default: self[task] = nil; return true
+ #else
+ case (false, false):
+ if #available(macOS 10.12, iOS 10, watchOS 7, tvOS 10, *) {
+ taskEvents[task] = (completed: true, metricsGathered: false); return false
+ } else {
+ // watchOS < 7 doesn't gather metrics, so unconditionally remove the reference and return true.
+ self[task] = nil; return true
+ }
+ case (false, true):
+ self[task] = nil; return true
+ #endif
+ }
+ }
+}
diff --git a/ChatBot/Pods/Alamofire/Source/Core/Response.swift b/ChatBot/Pods/Alamofire/Source/Core/Response.swift
new file mode 100644
index 00000000..8a9f089a
--- /dev/null
+++ b/ChatBot/Pods/Alamofire/Source/Core/Response.swift
@@ -0,0 +1,453 @@
+//
+// Response.swift
+//
+// Copyright (c) 2014-2018 Alamofire Software Foundation (http://alamofire.org/)
+//
+// 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 Foundation
+
+/// Default type of `DataResponse` returned by Alamofire, with an `AFError` `Failure` type.
+public typealias AFDataResponse = DataResponse
+/// Default type of `DownloadResponse` returned by Alamofire, with an `AFError` `Failure` type.
+public typealias AFDownloadResponse = DownloadResponse
+
+/// Type used to store all values associated with a serialized response of a `DataRequest` or `UploadRequest`.
+public struct DataResponse {
+ /// The URL request sent to the server.
+ public let request: URLRequest?
+
+ /// The server's response to the URL request.
+ public let response: HTTPURLResponse?
+
+ /// The data returned by the server.
+ public let data: Data?
+
+ /// The final metrics of the response.
+ ///
+ /// - Note: Due to `FB7624529`, collection of `URLSessionTaskMetrics` on watchOS is currently disabled.`
+ ///
+ public let metrics: URLSessionTaskMetrics?
+
+ /// The time taken to serialize the response.
+ public let serializationDuration: TimeInterval
+
+ /// The result of response serialization.
+ public let result: Result
+
+ /// Returns the associated value of the result if it is a success, `nil` otherwise.
+ public var value: Success? { result.success }
+
+ /// Returns the associated error value if the result if it is a failure, `nil` otherwise.
+ public var error: Failure? { result.failure }
+
+ /// Creates a `DataResponse` instance with the specified parameters derived from the response serialization.
+ ///
+ /// - Parameters:
+ /// - request: The `URLRequest` sent to the server.
+ /// - response: The `HTTPURLResponse` from the server.
+ /// - data: The `Data` returned by the server.
+ /// - metrics: The `URLSessionTaskMetrics` of the `DataRequest` or `UploadRequest`.
+ /// - serializationDuration: The duration taken by serialization.
+ /// - result: The `Result` of response serialization.
+ public init(request: URLRequest?,
+ response: HTTPURLResponse?,
+ data: Data?,
+ metrics: URLSessionTaskMetrics?,
+ serializationDuration: TimeInterval,
+ result: Result) {
+ self.request = request
+ self.response = response
+ self.data = data
+ self.metrics = metrics
+ self.serializationDuration = serializationDuration
+ self.result = result
+ }
+}
+
+// MARK: -
+
+extension DataResponse: CustomStringConvertible, CustomDebugStringConvertible {
+ /// The textual representation used when written to an output stream, which includes whether the result was a
+ /// success or failure.
+ public var description: String {
+ "\(result)"
+ }
+
+ /// The debug textual representation used when written to an output stream, which includes (if available) a summary
+ /// of the `URLRequest`, the request's headers and body (if decodable as a `String` below 100KB); the
+ /// `HTTPURLResponse`'s status code, headers, and body; the duration of the network and serialization actions; and
+ /// the `Result` of serialization.
+ public var debugDescription: String {
+ guard let urlRequest = request else { return "[Request]: None\n[Result]: \(result)" }
+
+ let requestDescription = DebugDescription.description(of: urlRequest)
+
+ let responseDescription = response.map { response in
+ let responseBodyDescription = DebugDescription.description(for: data, headers: response.headers)
+
+ return """
+ \(DebugDescription.description(of: response))
+ \(responseBodyDescription.indentingNewlines())
+ """
+ } ?? "[Response]: None"
+
+ let networkDuration = metrics.map { "\($0.taskInterval.duration)s" } ?? "None"
+
+ return """
+ \(requestDescription)
+ \(responseDescription)
+ [Network Duration]: \(networkDuration)
+ [Serialization Duration]: \(serializationDuration)s
+ [Result]: \(result)
+ """
+ }
+}
+
+// MARK: -
+
+extension DataResponse {
+ /// Evaluates the specified closure when the result of this `DataResponse` is a success, passing the unwrapped
+ /// result value as a parameter.
+ ///
+ /// Use the `map` method with a closure that does not throw. For example:
+ ///
+ /// let possibleData: DataResponse = ...
+ /// let possibleInt = possibleData.map { $0.count }
+ ///
+ /// - parameter transform: A closure that takes the success value of the instance's result.
+ ///
+ /// - returns: A `DataResponse` whose result wraps the value returned by the given closure. If this instance's
+ /// result is a failure, returns a response wrapping the same failure.
+ public func map(_ transform: (Success) -> NewSuccess) -> DataResponse {
+ DataResponse(request: request,
+ response: response,
+ data: data,
+ metrics: metrics,
+ serializationDuration: serializationDuration,
+ result: result.map(transform))
+ }
+
+ /// Evaluates the given closure when the result of this `DataResponse` is a success, passing the unwrapped result
+ /// value as a parameter.
+ ///
+ /// Use the `tryMap` method with a closure that may throw an error. For example:
+ ///
+ /// let possibleData: DataResponse = ...
+ /// let possibleObject = possibleData.tryMap {
+ /// try JSONSerialization.jsonObject(with: $0)
+ /// }
+ ///
+ /// - parameter transform: A closure that takes the success value of the instance's result.
+ ///
+ /// - returns: A success or failure `DataResponse` depending on the result of the given closure. If this instance's
+ /// result is a failure, returns the same failure.
+ public func tryMap(_ transform: (Success) throws -> NewSuccess) -> DataResponse {
+ DataResponse(request: request,
+ response: response,
+ data: data,
+ metrics: metrics,
+ serializationDuration: serializationDuration,
+ result: result.tryMap(transform))
+ }
+
+ /// Evaluates the specified closure when the `DataResponse` is a failure, passing the unwrapped error as a parameter.
+ ///
+ /// Use the `mapError` function with a closure that does not throw. For example:
+ ///
+ /// let possibleData: DataResponse = ...
+ /// let withMyError = possibleData.mapError { MyError.error($0) }
+ ///
+ /// - Parameter transform: A closure that takes the error of the instance.
+ ///
+ /// - Returns: A `DataResponse` instance containing the result of the transform.
+ public func mapError(_ transform: (Failure) -> NewFailure) -> DataResponse {
+ DataResponse(request: request,
+ response: response,
+ data: data,
+ metrics: metrics,
+ serializationDuration: serializationDuration,
+ result: result.mapError(transform))
+ }
+
+ /// Evaluates the specified closure when the `DataResponse` is a failure, passing the unwrapped error as a parameter.
+ ///
+ /// Use the `tryMapError` function with a closure that may throw an error. For example:
+ ///
+ /// let possibleData: DataResponse = ...
+ /// let possibleObject = possibleData.tryMapError {
+ /// try someFailableFunction(taking: $0)
+ /// }
+ ///
+ /// - Parameter transform: A throwing closure that takes the error of the instance.
+ ///
+ /// - Returns: A `DataResponse` instance containing the result of the transform.
+ public func tryMapError(_ transform: (Failure) throws -> NewFailure) -> DataResponse {
+ DataResponse(request: request,
+ response: response,
+ data: data,
+ metrics: metrics,
+ serializationDuration: serializationDuration,
+ result: result.tryMapError(transform))
+ }
+}
+
+// MARK: -
+
+/// Used to store all data associated with a serialized response of a download request.
+public struct DownloadResponse {
+ /// The URL request sent to the server.
+ public let request: URLRequest?
+
+ /// The server's response to the URL request.
+ public let response: HTTPURLResponse?
+
+ /// The final destination URL of the data returned from the server after it is moved.
+ public let fileURL: URL?
+
+ /// The resume data generated if the request was cancelled.
+ public let resumeData: Data?
+
+ /// The final metrics of the response.
+ ///
+ /// - Note: Due to `FB7624529`, collection of `URLSessionTaskMetrics` on watchOS is currently disabled.`
+ ///
+ public let metrics: URLSessionTaskMetrics?
+
+ /// The time taken to serialize the response.
+ public let serializationDuration: TimeInterval
+
+ /// The result of response serialization.
+ public let result: Result
+
+ /// Returns the associated value of the result if it is a success, `nil` otherwise.
+ public var value: Success? { result.success }
+
+ /// Returns the associated error value if the result if it is a failure, `nil` otherwise.
+ public var error: Failure? { result.failure }
+
+ /// Creates a `DownloadResponse` instance with the specified parameters derived from response serialization.
+ ///
+ /// - Parameters:
+ /// - request: The `URLRequest` sent to the server.
+ /// - response: The `HTTPURLResponse` from the server.
+ /// - fileURL: The final destination URL of the data returned from the server after it is moved.
+ /// - resumeData: The resume `Data` generated if the request was cancelled.
+ /// - metrics: The `URLSessionTaskMetrics` of the `DownloadRequest`.
+ /// - serializationDuration: The duration taken by serialization.
+ /// - result: The `Result` of response serialization.
+ public init(request: URLRequest?,
+ response: HTTPURLResponse?,
+ fileURL: URL?,
+ resumeData: Data?,
+ metrics: URLSessionTaskMetrics?,
+ serializationDuration: TimeInterval,
+ result: Result) {
+ self.request = request
+ self.response = response
+ self.fileURL = fileURL
+ self.resumeData = resumeData
+ self.metrics = metrics
+ self.serializationDuration = serializationDuration
+ self.result = result
+ }
+}
+
+// MARK: -
+
+extension DownloadResponse: CustomStringConvertible, CustomDebugStringConvertible {
+ /// The textual representation used when written to an output stream, which includes whether the result was a
+ /// success or failure.
+ public var description: String {
+ "\(result)"
+ }
+
+ /// The debug textual representation used when written to an output stream, which includes the URL request, the URL
+ /// response, the temporary and destination URLs, the resume data, the durations of the network and serialization
+ /// actions, and the response serialization result.
+ public var debugDescription: String {
+ guard let urlRequest = request else { return "[Request]: None\n[Result]: \(result)" }
+
+ let requestDescription = DebugDescription.description(of: urlRequest)
+ let responseDescription = response.map(DebugDescription.description(of:)) ?? "[Response]: None"
+ let networkDuration = metrics.map { "\($0.taskInterval.duration)s" } ?? "None"
+ let resumeDataDescription = resumeData.map { "\($0)" } ?? "None"
+
+ return """
+ \(requestDescription)
+ \(responseDescription)
+ [File URL]: \(fileURL?.path ?? "None")
+ [Resume Data]: \(resumeDataDescription)
+ [Network Duration]: \(networkDuration)
+ [Serialization Duration]: \(serializationDuration)s
+ [Result]: \(result)
+ """
+ }
+}
+
+// MARK: -
+
+extension DownloadResponse {
+ /// Evaluates the given closure when the result of this `DownloadResponse` is a success, passing the unwrapped
+ /// result value as a parameter.
+ ///
+ /// Use the `map` method with a closure that does not throw. For example:
+ ///
+ /// let possibleData: DownloadResponse = ...
+ /// let possibleInt = possibleData.map { $0.count }
+ ///
+ /// - parameter transform: A closure that takes the success value of the instance's result.
+ ///
+ /// - returns: A `DownloadResponse` whose result wraps the value returned by the given closure. If this instance's
+ /// result is a failure, returns a response wrapping the same failure.
+ public func map(_ transform: (Success) -> NewSuccess) -> DownloadResponse {
+ DownloadResponse(request: request,
+ response: response,
+ fileURL: fileURL,
+ resumeData: resumeData,
+ metrics: metrics,
+ serializationDuration: serializationDuration,
+ result: result.map(transform))
+ }
+
+ /// Evaluates the given closure when the result of this `DownloadResponse` is a success, passing the unwrapped
+ /// result value as a parameter.
+ ///
+ /// Use the `tryMap` method with a closure that may throw an error. For example:
+ ///
+ /// let possibleData: DownloadResponse = ...
+ /// let possibleObject = possibleData.tryMap {
+ /// try JSONSerialization.jsonObject(with: $0)
+ /// }
+ ///
+ /// - parameter transform: A closure that takes the success value of the instance's result.
+ ///
+ /// - returns: A success or failure `DownloadResponse` depending on the result of the given closure. If this
+ /// instance's result is a failure, returns the same failure.
+ public func tryMap(_ transform: (Success) throws -> NewSuccess) -> DownloadResponse