kbot-py-client 2.0.2__tar.gz → 2.0.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kbot-py-client
3
- Version: 2.0.2
3
+ Version: 2.0.4
4
4
  Summary: Client for Konverso Kbot
5
5
  Home-page: https://www.konverso.ai
6
6
  Author: Konverso
@@ -146,6 +146,37 @@ In this example, we create a conversation between the logged in user and the bot
146
146
  else:
147
147
  print("Could not create conversation due to: ", r.text)
148
148
 
149
+ ## Uploading one file to kbot
150
+
151
+
152
+ ### Prerequisites
153
+ * A local file that you wish to send
154
+ * The UUID of the folder that will receive the files you want to upload
155
+
156
+ ### Code sample
157
+ ```
158
+ current_top_folder = "uuid-of-a-folder"
159
+ filepath = "/tmp/test.pdf"
160
+ filename = os.path.basename(filepath)
161
+
162
+ # Upload to remote filemanager
163
+ with open(filepath, "rb") as fd:
164
+ files = {
165
+ "upload_files": fd
166
+ }
167
+ params= {
168
+ "override": False
169
+ }
170
+ data = {
171
+ "folder": current_top_folder,
172
+ "name": file_name,
173
+ }
174
+ response = self.client.post_file("attachment",
175
+ data=data,
176
+ params=params,
177
+ files=files)
178
+ ```
179
+
149
180
  ## Uploading a batch of files to the file manager
150
181
 
151
182
  ### Prerequisites
@@ -162,5 +193,5 @@ In this example, we simply upload the content of a directory to a folder in the
162
193
  client = Client("mybot.konverso.ai", api_key="17ebXXXXXXXXXXXXXXXXXXXXX")
163
194
 
164
195
  syncer = FolderSync(client)
165
- syncer.sync("/tmp/my_source_folder/", "1831fXXXXXXXXXXXXXXXXXXXXXXX")
196
+ syncer.sync("/tmp/my_source_folder/", "1831f-XXXXXXXXXXXXXXXXXXXXXXX")
166
197
  print("Syncing is done :)")
@@ -131,6 +131,37 @@ In this example, we create a conversation between the logged in user and the bot
131
131
  else:
132
132
  print("Could not create conversation due to: ", r.text)
133
133
 
134
+ ## Uploading one file to kbot
135
+
136
+
137
+ ### Prerequisites
138
+ * A local file that you wish to send
139
+ * The UUID of the folder that will receive the files you want to upload
140
+
141
+ ### Code sample
142
+ ```
143
+ current_top_folder = "uuid-of-a-folder"
144
+ filepath = "/tmp/test.pdf"
145
+ filename = os.path.basename(filepath)
146
+
147
+ # Upload to remote filemanager
148
+ with open(filepath, "rb") as fd:
149
+ files = {
150
+ "upload_files": fd
151
+ }
152
+ params= {
153
+ "override": False
154
+ }
155
+ data = {
156
+ "folder": current_top_folder,
157
+ "name": file_name,
158
+ }
159
+ response = self.client.post_file("attachment",
160
+ data=data,
161
+ params=params,
162
+ files=files)
163
+ ```
164
+
134
165
  ## Uploading a batch of files to the file manager
135
166
 
136
167
  ### Prerequisites
@@ -147,5 +178,5 @@ In this example, we simply upload the content of a directory to a folder in the
147
178
  client = Client("mybot.konverso.ai", api_key="17ebXXXXXXXXXXXXXXXXXXXXX")
148
179
 
149
180
  syncer = FolderSync(client)
150
- syncer.sync("/tmp/my_source_folder/", "1831fXXXXXXXXXXXXXXXXXXXXXXX")
181
+ syncer.sync("/tmp/my_source_folder/", "1831f-XXXXXXXXXXXXXXXXXXXXXXX")
151
182
  print("Syncing is done :)")
@@ -0,0 +1,178 @@
1
+ import time
2
+ from abc import ABC, abstractmethod
3
+
4
+ class ChatClient(ABC):
5
+ def __init__(self, client,
6
+ render_types=("text", "html"),
7
+ prompt="{sender}> {message}",
8
+ user_prompt = "User> ",
9
+ bye = "Bye, hope to see you again soon",
10
+ exit_commands = ("stop", "exit")):
11
+
12
+ self._client = client
13
+ self._render_types = render_types
14
+ self._prompt = prompt
15
+ self._user_prompt = user_prompt
16
+ self._bye = bye
17
+ self._exit_commands = exit_commands
18
+
19
+ # Create a new conversation
20
+ #
21
+ response = self._client.post("conversation", data={"username": "bot"})
22
+ response.raise_for_status()
23
+
24
+ # Print the first welcome message
25
+ #
26
+ self._process_new_messages(response.json(), context="welcome")
27
+
28
+ # Loop waiting for user questions and then waiting for the bot response
29
+ #
30
+ self._start_question_answer_loop(response.json().get("id"))
31
+
32
+ def _process_new_messages(self, messages_json, context):
33
+ """Given a JSON response from the bot, extract two key information:
34
+ - sender: The name of the bot
35
+ - messages: A list of the JSON matching the type constraints such as:
36
+
37
+ Arguments:
38
+ - context: One of "welcome" or "response"
39
+
40
+ The input json of a Welcome (conversation creation) is expected to have format such as:
41
+ {
42
+ "sender": {...}
43
+ "messages": [{
44
+ "type": "message",
45
+ "message": [{
46
+ "format": "text",
47
+ "value": "Hello John",
48
+ ...
49
+
50
+ The input json of a Response (conversation response) is expected to have format such as:
51
+ [{
52
+ "sender": {...}
53
+ "type": "message",
54
+ "message": [{
55
+ "format": "text",
56
+ "value": "Hello John",
57
+ ...
58
+
59
+ Returns a tuple of two elements: sender, messages
60
+ """
61
+
62
+ stop = False
63
+ if context == "welcome":
64
+ self._sender = messages_json.get("sender").get("name")
65
+
66
+ for message in messages_json.get("messages"):
67
+ message_type = message.get("type")
68
+
69
+ if message.get("type") != "message":
70
+ continue
71
+
72
+ for message_content in message.get("message"):
73
+ if message_content.get("format") in self._render_types:
74
+ self._display_response(message_content)
75
+
76
+ elif context == "response":
77
+ #print(messages_json)
78
+
79
+ for one_message in messages_json.get("messages"):
80
+ self._sender = one_message.get("sender").get("name")
81
+ message_type = one_message.get("type")
82
+
83
+ if message_type == "stop_topic":
84
+ stop = True
85
+
86
+ if one_message.get("type") != "message":
87
+ continue
88
+
89
+ for message_content in one_message.get("message"):
90
+ if message_content.get("format") in self._render_types:
91
+ self._display_response(message_content)
92
+
93
+ return stop
94
+
95
+ def _display_response(self, message):
96
+ """Display to the user the message. The message argument is a json in the format:
97
+ {
98
+ "format": "text",
99
+ "value": "Hello John",
100
+ ...
101
+ """
102
+ print(self._prompt.format(sender=self._sender, message=message.get('value')))
103
+
104
+ def _start_question_answer_loop(self, conversation_id):
105
+
106
+ # Start the chatbot, in a loop
107
+ # We stop when user type "exit" or EOF (Ctrl D)
108
+ while True:
109
+
110
+ # Get the user sentence and check for the stop conditions
111
+ #
112
+ try:
113
+ question = input(self._user_prompt)
114
+ except EOFError:
115
+ print(self._bye)
116
+ break
117
+
118
+ if not question:
119
+ continue
120
+
121
+ if question.lower() in self._exit_commands:
122
+ print(self._bye)
123
+ break
124
+
125
+ self._send_question(question, conversation_id)
126
+ self._get_response(conversation_id)
127
+
128
+
129
+ def _send_question(self, question, conversation_id):
130
+ # Send the user question to Kbot.
131
+ #
132
+ data = {
133
+ "conversation_id": conversation_id,
134
+ "type":"message",
135
+ "message": question,
136
+ "fromUser": True,
137
+ }
138
+
139
+ response = self._client.post(f"conversation/{conversation_id}/message", data=data)
140
+ response.raise_for_status()
141
+
142
+ @abstractmethod
143
+ def _get_response(self, conversation_id):
144
+ """Collect the kbot response"""
145
+
146
+ class AsyncChatClient(ChatClient):
147
+ """A Chatbot client that will pull for updates and display responses
148
+ as they come
149
+ """
150
+ def __init__(self, client, pull_interval=0.5, pull_timeout=10, **kwargs):
151
+ self._pull_interval = pull_interval
152
+ self._pull_timeout = pull_timeout
153
+ super().__init__(client,**kwargs)
154
+
155
+ def _get_response(self, conversation_id):
156
+ # Wait for the response(s)
157
+ #
158
+ while True:
159
+ time.sleep(self._pull_interval)
160
+ response = self._client.get(f"conversation/{conversation_id}/messages", params={"timeout": self._pull_timeout})
161
+ response.raise_for_status()
162
+
163
+ stop = self._process_new_messages(response.json(), context="response")
164
+ if stop:
165
+ # Time to ask for a new question
166
+ break
167
+
168
+ class SyncChatClient(ChatClient):
169
+ """A Chatbot client that will wait for full response from the bot before displaying to the user
170
+ """
171
+
172
+ def _get_response(self, conversation_id):
173
+ # Wait for the response(s)
174
+ #
175
+ params = {"wait": "true"}
176
+ response = self._client.get(f"conversation/{conversation_id}/messages", params=params)
177
+ response.raise_for_status()
178
+ self._process_new_messages(response.json(), context="response")
@@ -176,7 +176,11 @@ class Client:
176
176
  self.__reset_headers(r.json())
177
177
 
178
178
  def __request(self, method: str, uri : str = None, data: dict = None, params: dict = None, files: dict = None, attempt=0):
179
- dump_data = json.dumps(data or {})
179
+ if files:
180
+ # For file upload, the data must be a dictionnary
181
+ dump_data = data
182
+ else:
183
+ dump_data = json.dumps(data or {})
180
184
 
181
185
  if files:
182
186
  headers = self._headers.copy()
@@ -185,7 +189,7 @@ class Client:
185
189
  else:
186
190
  headers = self._headers
187
191
 
188
- r = requests.request(method.upper(), self.url + '/api/%s/' % (uri), params=params, data=dump_data, headers=headers, verify=self.verify)
192
+ r = requests.request(method.upper(), self.url + '/api/%s/' % (uri), params=params, data=dump_data, headers=headers, files=files, verify=self.verify)
189
193
 
190
194
  if r.status_code == 401:
191
195
  # Refresh the token
@@ -204,8 +208,8 @@ class Client:
204
208
 
205
209
  return r
206
210
 
207
- def request(self, method: str, uri: str, data: dict = None, params: dict = None):
208
- return self.__request(method, uri=uri, data=data, params=params)
211
+ def request(self, method: str, uri: str, data: dict = None, params: dict = None, files: dict = None):
212
+ return self.__request(method, uri=uri, data=data, params=params, files=files)
209
213
 
210
214
  def unit(self, name: str, params=None) -> dict:
211
215
  r = self.get(name, params)
@@ -28,9 +28,7 @@ class Client:
28
28
  else:
29
29
  proto = 'http'
30
30
 
31
- if proto == "https" and port == 443:
32
- self.url = "%s://%s" % (proto, server)
33
- elif proto == "https" and port == 443:
31
+ if port in (80, 443):
34
32
  self.url = "%s://%s" % (proto, server)
35
33
  else:
36
34
  self.url = "%s://%s:%s" % (proto, server, port)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kbot-py-client
3
- Version: 2.0.2
3
+ Version: 2.0.4
4
4
  Summary: Client for Konverso Kbot
5
5
  Home-page: https://www.konverso.ai
6
6
  Author: Konverso
@@ -146,6 +146,37 @@ In this example, we create a conversation between the logged in user and the bot
146
146
  else:
147
147
  print("Could not create conversation due to: ", r.text)
148
148
 
149
+ ## Uploading one file to kbot
150
+
151
+
152
+ ### Prerequisites
153
+ * A local file that you wish to send
154
+ * The UUID of the folder that will receive the files you want to upload
155
+
156
+ ### Code sample
157
+ ```
158
+ current_top_folder = "uuid-of-a-folder"
159
+ filepath = "/tmp/test.pdf"
160
+ filename = os.path.basename(filepath)
161
+
162
+ # Upload to remote filemanager
163
+ with open(filepath, "rb") as fd:
164
+ files = {
165
+ "upload_files": fd
166
+ }
167
+ params= {
168
+ "override": False
169
+ }
170
+ data = {
171
+ "folder": current_top_folder,
172
+ "name": file_name,
173
+ }
174
+ response = self.client.post_file("attachment",
175
+ data=data,
176
+ params=params,
177
+ files=files)
178
+ ```
179
+
149
180
  ## Uploading a batch of files to the file manager
150
181
 
151
182
  ### Prerequisites
@@ -162,5 +193,5 @@ In this example, we simply upload the content of a directory to a folder in the
162
193
  client = Client("mybot.konverso.ai", api_key="17ebXXXXXXXXXXXXXXXXXXXXX")
163
194
 
164
195
  syncer = FolderSync(client)
165
- syncer.sync("/tmp/my_source_folder/", "1831fXXXXXXXXXXXXXXXXXXXXXXX")
196
+ syncer.sync("/tmp/my_source_folder/", "1831f-XXXXXXXXXXXXXXXXXXXXXXX")
166
197
  print("Syncing is done :)")
@@ -3,6 +3,7 @@ LICENSE
3
3
  README.md
4
4
  setup.py
5
5
  kbot_client/__init__.py
6
+ kbot_client/chat_client.py
6
7
  kbot_client/client.py
7
8
  kbot_client/client.recording.py
8
9
  kbot_client/client_group.py
@@ -5,7 +5,7 @@ with open("README.md", mode="r", encoding="utf-8") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name="kbot-py-client",
8
- version="2.0.2",
8
+ version="2.0.4",
9
9
  author="Konverso",
10
10
  author_email="contact@konverso.ai",
11
11
  description="Client for Konverso Kbot",
File without changes
File without changes