@botonic/core 1.0.0-dev.0 → 2.23.0

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.
Files changed (228) hide show
  1. package/CHANGELOG.md +226 -0
  2. package/README.md +7 -9
  3. package/package.json +19 -57
  4. package/src/index.d.ts +4 -0
  5. package/src/index.js +5 -0
  6. package/src/index.js.map +1 -0
  7. package/src/lib/core-bot/index.d.ts +33 -0
  8. package/src/lib/core-bot/index.js +113 -0
  9. package/src/lib/core-bot/index.js.map +1 -0
  10. package/src/lib/hubtype-service/handoff.d.ts +4 -0
  11. package/src/lib/hubtype-service/handoff.js +32 -0
  12. package/src/lib/hubtype-service/handoff.js.map +1 -0
  13. package/src/lib/hubtype-service/index.d.ts +10 -0
  14. package/src/lib/hubtype-service/index.js +96 -0
  15. package/src/lib/hubtype-service/index.js.map +1 -0
  16. package/src/lib/messages/button.d.ts +8 -0
  17. package/src/lib/messages/button.js +10 -0
  18. package/src/lib/messages/button.js.map +1 -0
  19. package/src/lib/plugins/index.d.ts +2 -0
  20. package/src/lib/plugins/index.js +23 -0
  21. package/src/lib/plugins/index.js.map +1 -0
  22. package/src/lib/routes/index.d.ts +0 -0
  23. package/src/lib/routes/index.js +2 -0
  24. package/src/lib/routes/index.js.map +1 -0
  25. package/src/lib/routes/router.d.ts +14 -0
  26. package/src/lib/routes/router.js +68 -0
  27. package/src/lib/routes/router.js.map +1 -0
  28. package/src/lib/routes/types.d.ts +15 -0
  29. package/src/lib/routes/types.js +2 -0
  30. package/src/lib/routes/types.js.map +1 -0
  31. package/src/lib/utils/index.d.ts +7 -0
  32. package/{lib/esm/utils.js → src/lib/utils/index.js} +6 -34
  33. package/src/lib/utils/index.js.map +1 -0
  34. package/lib/cjs/constants.d.ts +0 -15
  35. package/lib/cjs/constants.js +0 -19
  36. package/lib/cjs/constants.js.map +0 -1
  37. package/lib/cjs/core-bot.d.ts +0 -33
  38. package/lib/cjs/core-bot.js +0 -85
  39. package/lib/cjs/core-bot.js.map +0 -1
  40. package/lib/cjs/debug/index.d.ts +0 -1
  41. package/lib/cjs/debug/index.js +0 -9
  42. package/lib/cjs/debug/index.js.map +0 -1
  43. package/lib/cjs/debug/inspector.d.ts +0 -24
  44. package/lib/cjs/debug/inspector.js +0 -72
  45. package/lib/cjs/debug/inspector.js.map +0 -1
  46. package/lib/cjs/errors.d.ts +0 -5
  47. package/lib/cjs/errors.js +0 -11
  48. package/lib/cjs/errors.js.map +0 -1
  49. package/lib/cjs/handoff.d.ts +0 -67
  50. package/lib/cjs/handoff.js +0 -183
  51. package/lib/cjs/handoff.js.map +0 -1
  52. package/lib/cjs/hubtype-service.d.ts +0 -69
  53. package/lib/cjs/hubtype-service.js +0 -190
  54. package/lib/cjs/hubtype-service.js.map +0 -1
  55. package/lib/cjs/i18n.d.ts +0 -2
  56. package/lib/cjs/i18n.js +0 -11
  57. package/lib/cjs/i18n.js.map +0 -1
  58. package/lib/cjs/index.d.ts +0 -166
  59. package/lib/cjs/index.js +0 -58
  60. package/lib/cjs/index.js.map +0 -1
  61. package/lib/cjs/models/events/connections/index.d.ts +0 -9
  62. package/lib/cjs/models/events/connections/index.js +0 -9
  63. package/lib/cjs/models/events/connections/index.js.map +0 -1
  64. package/lib/cjs/models/events/index.d.ts +0 -21
  65. package/lib/cjs/models/events/index.js +0 -11
  66. package/lib/cjs/models/events/index.js.map +0 -1
  67. package/lib/cjs/models/events/message/buttons.d.ts +0 -18
  68. package/lib/cjs/models/events/message/buttons.js +0 -3
  69. package/lib/cjs/models/events/message/buttons.js.map +0 -1
  70. package/lib/cjs/models/events/message/carousel.d.ts +0 -11
  71. package/lib/cjs/models/events/message/carousel.js +0 -3
  72. package/lib/cjs/models/events/message/carousel.js.map +0 -1
  73. package/lib/cjs/models/events/message/custom.d.ts +0 -6
  74. package/lib/cjs/models/events/message/custom.js +0 -3
  75. package/lib/cjs/models/events/message/custom.js.map +0 -1
  76. package/lib/cjs/models/events/message/index.d.ts +0 -30
  77. package/lib/cjs/models/events/message/index.js +0 -32
  78. package/lib/cjs/models/events/message/index.js.map +0 -1
  79. package/lib/cjs/models/events/message/location.d.ts +0 -6
  80. package/lib/cjs/models/events/message/location.js +0 -3
  81. package/lib/cjs/models/events/message/location.js.map +0 -1
  82. package/lib/cjs/models/events/message/media.d.ts +0 -18
  83. package/lib/cjs/models/events/message/media.js +0 -11
  84. package/lib/cjs/models/events/message/media.js.map +0 -1
  85. package/lib/cjs/models/events/message/postback.d.ts +0 -4
  86. package/lib/cjs/models/events/message/postback.js +0 -3
  87. package/lib/cjs/models/events/message/postback.js.map +0 -1
  88. package/lib/cjs/models/events/message/replies.d.ts +0 -7
  89. package/lib/cjs/models/events/message/replies.js +0 -3
  90. package/lib/cjs/models/events/message/replies.js.map +0 -1
  91. package/lib/cjs/models/events/message/text.d.ts +0 -8
  92. package/lib/cjs/models/events/message/text.js +0 -3
  93. package/lib/cjs/models/events/message/text.js.map +0 -1
  94. package/lib/cjs/models/user.d.ts +0 -10
  95. package/lib/cjs/models/user.js +0 -3
  96. package/lib/cjs/models/user.js.map +0 -1
  97. package/lib/cjs/output-parser/factory.d.ts +0 -4
  98. package/lib/cjs/output-parser/factory.js +0 -33
  99. package/lib/cjs/output-parser/factory.js.map +0 -1
  100. package/lib/cjs/output-parser/index.d.ts +0 -16
  101. package/lib/cjs/output-parser/index.js +0 -37
  102. package/lib/cjs/output-parser/index.js.map +0 -1
  103. package/lib/cjs/output-parser/parsers.d.ts +0 -28
  104. package/lib/cjs/output-parser/parsers.js +0 -138
  105. package/lib/cjs/output-parser/parsers.js.map +0 -1
  106. package/lib/cjs/output-parser/util.d.ts +0 -2
  107. package/lib/cjs/output-parser/util.js +0 -14
  108. package/lib/cjs/output-parser/util.js.map +0 -1
  109. package/lib/cjs/plugins.d.ts +0 -7
  110. package/lib/cjs/plugins.js +0 -45
  111. package/lib/cjs/plugins.js.map +0 -1
  112. package/lib/cjs/router.d.ts +0 -35
  113. package/lib/cjs/router.js +0 -262
  114. package/lib/cjs/router.js.map +0 -1
  115. package/lib/cjs/utils.d.ts +0 -10
  116. package/lib/cjs/utils.js +0 -84
  117. package/lib/cjs/utils.js.map +0 -1
  118. package/lib/esm/constants.d.ts +0 -15
  119. package/lib/esm/constants.js +0 -16
  120. package/lib/esm/constants.js.map +0 -1
  121. package/lib/esm/core-bot.d.ts +0 -33
  122. package/lib/esm/core-bot.js +0 -81
  123. package/lib/esm/core-bot.js.map +0 -1
  124. package/lib/esm/debug/index.d.ts +0 -1
  125. package/lib/esm/debug/index.js +0 -2
  126. package/lib/esm/debug/index.js.map +0 -1
  127. package/lib/esm/debug/inspector.d.ts +0 -24
  128. package/lib/esm/debug/inspector.js +0 -65
  129. package/lib/esm/debug/inspector.js.map +0 -1
  130. package/lib/esm/errors.d.ts +0 -5
  131. package/lib/esm/errors.js +0 -7
  132. package/lib/esm/errors.js.map +0 -1
  133. package/lib/esm/handoff.d.ts +0 -67
  134. package/lib/esm/handoff.js +0 -170
  135. package/lib/esm/handoff.js.map +0 -1
  136. package/lib/esm/hubtype-service.d.ts +0 -69
  137. package/lib/esm/hubtype-service.js +0 -185
  138. package/lib/esm/hubtype-service.js.map +0 -1
  139. package/lib/esm/i18n.d.ts +0 -2
  140. package/lib/esm/i18n.js +0 -7
  141. package/lib/esm/i18n.js.map +0 -1
  142. package/lib/esm/index.d.ts +0 -166
  143. package/lib/esm/index.js +0 -49
  144. package/lib/esm/index.js.map +0 -1
  145. package/lib/esm/models/events/connections/index.d.ts +0 -9
  146. package/lib/esm/models/events/connections/index.js +0 -6
  147. package/lib/esm/models/events/connections/index.js.map +0 -1
  148. package/lib/esm/models/events/index.d.ts +0 -21
  149. package/lib/esm/models/events/index.js +0 -8
  150. package/lib/esm/models/events/index.js.map +0 -1
  151. package/lib/esm/models/events/message/buttons.d.ts +0 -18
  152. package/lib/esm/models/events/message/buttons.js +0 -2
  153. package/lib/esm/models/events/message/buttons.js.map +0 -1
  154. package/lib/esm/models/events/message/carousel.d.ts +0 -11
  155. package/lib/esm/models/events/message/carousel.js +0 -2
  156. package/lib/esm/models/events/message/carousel.js.map +0 -1
  157. package/lib/esm/models/events/message/custom.d.ts +0 -6
  158. package/lib/esm/models/events/message/custom.js +0 -2
  159. package/lib/esm/models/events/message/custom.js.map +0 -1
  160. package/lib/esm/models/events/message/index.d.ts +0 -30
  161. package/lib/esm/models/events/message/index.js +0 -29
  162. package/lib/esm/models/events/message/index.js.map +0 -1
  163. package/lib/esm/models/events/message/location.d.ts +0 -6
  164. package/lib/esm/models/events/message/location.js +0 -2
  165. package/lib/esm/models/events/message/location.js.map +0 -1
  166. package/lib/esm/models/events/message/media.d.ts +0 -18
  167. package/lib/esm/models/events/message/media.js +0 -8
  168. package/lib/esm/models/events/message/media.js.map +0 -1
  169. package/lib/esm/models/events/message/postback.d.ts +0 -4
  170. package/lib/esm/models/events/message/postback.js +0 -2
  171. package/lib/esm/models/events/message/postback.js.map +0 -1
  172. package/lib/esm/models/events/message/replies.d.ts +0 -7
  173. package/lib/esm/models/events/message/replies.js +0 -2
  174. package/lib/esm/models/events/message/replies.js.map +0 -1
  175. package/lib/esm/models/events/message/text.d.ts +0 -8
  176. package/lib/esm/models/events/message/text.js +0 -2
  177. package/lib/esm/models/events/message/text.js.map +0 -1
  178. package/lib/esm/models/user.d.ts +0 -10
  179. package/lib/esm/models/user.js +0 -2
  180. package/lib/esm/models/user.js.map +0 -1
  181. package/lib/esm/output-parser/factory.d.ts +0 -4
  182. package/lib/esm/output-parser/factory.js +0 -29
  183. package/lib/esm/output-parser/factory.js.map +0 -1
  184. package/lib/esm/output-parser/index.d.ts +0 -16
  185. package/lib/esm/output-parser/index.js +0 -33
  186. package/lib/esm/output-parser/index.js.map +0 -1
  187. package/lib/esm/output-parser/parsers.d.ts +0 -28
  188. package/lib/esm/output-parser/parsers.js +0 -123
  189. package/lib/esm/output-parser/parsers.js.map +0 -1
  190. package/lib/esm/output-parser/util.d.ts +0 -2
  191. package/lib/esm/output-parser/util.js +0 -9
  192. package/lib/esm/output-parser/util.js.map +0 -1
  193. package/lib/esm/plugins.d.ts +0 -7
  194. package/lib/esm/plugins.js +0 -40
  195. package/lib/esm/plugins.js.map +0 -1
  196. package/lib/esm/router.d.ts +0 -35
  197. package/lib/esm/router.js +0 -258
  198. package/lib/esm/router.js.map +0 -1
  199. package/lib/esm/utils.d.ts +0 -10
  200. package/lib/esm/utils.js.map +0 -1
  201. package/src/constants.ts +0 -15
  202. package/src/core-bot.ts +0 -144
  203. package/src/debug/index.ts +0 -6
  204. package/src/debug/inspector.ts +0 -102
  205. package/src/errors.ts +0 -11
  206. package/src/handoff.ts +0 -268
  207. package/src/hubtype-service.ts +0 -266
  208. package/src/i18n.ts +0 -12
  209. package/src/index.ts +0 -233
  210. package/src/models/events/connections/index.ts +0 -11
  211. package/src/models/events/index.ts +0 -39
  212. package/src/models/events/message/buttons.ts +0 -23
  213. package/src/models/events/message/carousel.ts +0 -13
  214. package/src/models/events/message/custom.ts +0 -7
  215. package/src/models/events/message/index.ts +0 -37
  216. package/src/models/events/message/location.ts +0 -7
  217. package/src/models/events/message/media.ts +0 -28
  218. package/src/models/events/message/postback.ts +0 -5
  219. package/src/models/events/message/replies.ts +0 -8
  220. package/src/models/events/message/text.ts +0 -12
  221. package/src/models/user.ts +0 -10
  222. package/src/output-parser/factory.ts +0 -40
  223. package/src/output-parser/index.ts +0 -38
  224. package/src/output-parser/parsers.ts +0 -190
  225. package/src/output-parser/util.ts +0 -8
  226. package/src/plugins.ts +0 -49
  227. package/src/router.ts +0 -316
  228. package/src/utils.ts +0 -84
package/src/handoff.ts DELETED
@@ -1,268 +0,0 @@
1
- import axios from 'axios'
2
-
3
- import { Session } from './index'
4
-
5
- const HUBTYPE_API_URL = 'https://api.hubtype.com'
6
-
7
- export interface HubtypeAgentsInfo {
8
- attending_count: number
9
- email: string
10
- idle_count: number
11
- last_message_sent: string
12
- status: string
13
- }
14
- export interface HubtypeSession extends Session {
15
- _hubtype_api?: string
16
- _access_token: string
17
- }
18
-
19
- export interface SessionWithBotonicAction extends Session {
20
- _botonic_action: string
21
- }
22
- export interface BackendContext {
23
- timeoutMs: number
24
- }
25
-
26
- export interface VacationRange {
27
- end_date: number // timestamp
28
- id: number
29
- start_date: number // timestamp
30
- }
31
-
32
- function contextDefaults(context: any): BackendContext {
33
- return {
34
- timeoutMs: context.timeoutMs || 10000,
35
- }
36
- }
37
-
38
- export async function getOpenQueues(
39
- session: HubtypeSession,
40
- context = {}
41
- ): Promise<{ queues: string[] }> {
42
- //be aware of https://github.com/axios/axios/issues/1543
43
- const baseUrl = session._hubtype_api || HUBTYPE_API_URL
44
- const endpointUrl = `${baseUrl}/v1/queues/get_open_queues/`
45
- context = contextDefaults(context)
46
- const resp = await axios({
47
- headers: {
48
- Authorization: `Bearer ${session._access_token}`,
49
- },
50
- method: 'post',
51
- url: endpointUrl,
52
- data: { bot_id: session.bot.id },
53
- timeout: (context as BackendContext).timeoutMs,
54
- })
55
- return resp.data
56
- }
57
-
58
- export class HandOffBuilder {
59
- _session: SessionWithBotonicAction
60
- _queue: string
61
- _onFinish: string
62
- _email: string
63
- _agentId: string
64
- _note: string
65
- _caseInfo: string
66
- _shadowing: boolean
67
-
68
- constructor(session: SessionWithBotonicAction) {
69
- this._session = session
70
- }
71
-
72
- withQueue(queueNameOrId: string): this {
73
- this._queue = queueNameOrId
74
- return this
75
- }
76
-
77
- withOnFinishPayload(payload: string): this {
78
- this._onFinish = payload
79
- return this
80
- }
81
-
82
- withOnFinishPath(path: string): this {
83
- this._onFinish = `__PATH_PAYLOAD__${path}`
84
- return this
85
- }
86
-
87
- withAgentEmail(email: string): this {
88
- this._email = email
89
- return this
90
- }
91
-
92
- withAgentId(agentId: string): this {
93
- this._agentId = agentId
94
- return this
95
- }
96
-
97
- withNote(note: string): this {
98
- this._note = note
99
- return this
100
- }
101
-
102
- withCaseInfo(caseInfo: string): this {
103
- this._caseInfo = caseInfo
104
- return this
105
- }
106
-
107
- withShadowing(shadowing = true): this {
108
- this._shadowing = shadowing
109
- return this
110
- }
111
-
112
- async handOff(): Promise<void> {
113
- return _humanHandOff(
114
- this._session,
115
- this._queue,
116
- this._onFinish,
117
- this._email,
118
- this._agentId,
119
- this._caseInfo,
120
- this._note,
121
- this._shadowing
122
- )
123
- }
124
- }
125
-
126
- /**
127
- * @deprecated use {@link HandOffBuilder} class instead
128
- */
129
- export async function humanHandOff(session, queueNameOrId = '', onFinish) {
130
- const builder = new HandOffBuilder(session)
131
- if (queueNameOrId) {
132
- builder.withQueue(queueNameOrId)
133
- }
134
- if (onFinish) {
135
- if (onFinish.path) {
136
- builder.withOnFinishPath(onFinish.path)
137
- } else if (onFinish.payload) {
138
- builder.withOnFinishPayload(onFinish.payload)
139
- } else {
140
- throw new Error('onFinish requires payload or path field')
141
- }
142
- }
143
- return builder.handOff()
144
- }
145
-
146
- interface HubtypeHandoffParams {
147
- queue?: string
148
- agent_email?: string
149
- agent_id?: string
150
- case_info?: string
151
- note?: string
152
- shadowing?: boolean
153
- on_finish?: string
154
- }
155
- async function _humanHandOff(
156
- session: SessionWithBotonicAction,
157
- queueNameOrId = '',
158
- onFinish: string,
159
- agentEmail = '',
160
- agentId = '',
161
- caseInfo = '',
162
- note = '',
163
- shadowing = false
164
- ) {
165
- const params: HubtypeHandoffParams = {}
166
- if (queueNameOrId) {
167
- params.queue = queueNameOrId
168
- }
169
- if (agentEmail) {
170
- params.agent_email = agentEmail
171
- }
172
- if (agentId) {
173
- params.agent_id = agentId
174
- }
175
- if (caseInfo) {
176
- params.case_info = caseInfo
177
- }
178
- if (note) {
179
- params.note = note
180
- }
181
- if (shadowing) {
182
- params.shadowing = shadowing
183
- }
184
- if (onFinish) {
185
- params.on_finish = onFinish
186
- }
187
- session._botonic_action = `create_case:${JSON.stringify(params)}`
188
- }
189
-
190
- export async function storeCaseRating(
191
- session: HubtypeSession,
192
- rating: number,
193
- context: any = {}
194
- ): Promise<{ status: string }> {
195
- const baseUrl = session._hubtype_api || HUBTYPE_API_URL
196
- const chatId = session.user.id
197
- context = contextDefaults(context)
198
- const resp = await axios({
199
- headers: {
200
- Authorization: `Bearer ${session._access_token}`,
201
- },
202
- method: 'post',
203
- url: `${baseUrl}/v1/chats/${chatId}/store_case_rating/`,
204
- data: { chat_id: chatId, rating },
205
- timeout: (context as BackendContext).timeoutMs,
206
- })
207
- return resp.data
208
- }
209
-
210
- export async function getAvailableAgentsByQueue(
211
- session: HubtypeSession,
212
- queueId: string
213
- ): Promise<{ agents: string[] }> {
214
- const baseUrl = session._hubtype_api || HUBTYPE_API_URL
215
- const resp = await axios({
216
- headers: {
217
- Authorization: `Bearer ${session._access_token}`,
218
- },
219
- method: 'post',
220
- url: `${baseUrl}/v1/queues/${queueId}/get_available_agents/`,
221
- })
222
- return resp.data
223
- }
224
-
225
- export async function getAvailableAgents(
226
- session: HubtypeSession
227
- ): Promise<{ agents: HubtypeAgentsInfo[] }> {
228
- const baseUrl = session._hubtype_api || HUBTYPE_API_URL
229
- const botId = session.bot.id
230
- const resp = await axios({
231
- headers: {
232
- Authorization: `Bearer ${session._access_token}`,
233
- },
234
- method: 'post',
235
- url: `${baseUrl}/v1/bots/${botId}/get_agents/`,
236
- })
237
- return resp.data
238
- }
239
-
240
- export async function getAgentVacationRanges(
241
- session: HubtypeSession,
242
- { agentId, agentEmail }: { agentId?: string; agentEmail?: string }
243
- ): Promise<{ vacation_ranges: VacationRange[] }> {
244
- const baseUrl = session._hubtype_api || HUBTYPE_API_URL
245
- const botId = session.bot.id
246
- const resp = await axios({
247
- headers: {
248
- Authorization: `Bearer ${session._access_token}`,
249
- },
250
- method: 'get',
251
- url: `${baseUrl}/v1/bots/${botId}/get_agent_vacation_ranges/`,
252
- params: { agent_id: agentId, agent_email: agentEmail },
253
- })
254
- return resp.data
255
- }
256
-
257
- export function cancelHandoff(
258
- session: SessionWithBotonicAction,
259
- typification: string | null = null
260
- ): void {
261
- let action = 'discard_case'
262
- if (typification) action = `${action}:${JSON.stringify({ typification })}`
263
- session._botonic_action = action
264
- }
265
-
266
- export function deleteUser(session: SessionWithBotonicAction): void {
267
- session._botonic_action = `delete_user`
268
- }
@@ -1,266 +0,0 @@
1
- import axios, { AxiosResponse } from 'axios'
2
- import Pusher, { AuthOptions, Channel } from 'pusher-js'
3
- import Channels from 'pusher-js/types/src/core/channels/channels'
4
-
5
- import { Input, SessionUser } from './index'
6
- import { getWebpackEnvVar } from './utils'
7
-
8
- interface UnsentInput {
9
- id: string
10
- ack: number
11
- unsentInput: Input
12
- }
13
- interface BotonicHeaders {
14
- 'X-BOTONIC-USER-ID': string
15
- 'X-BOTONIC-LAST-MESSAGE-ID': string
16
- 'X-BOTONIC-LAST-MESSAGE-UPDATE-DATE': string
17
- }
18
- interface ServerConfig {
19
- activityTimeout?: number
20
- pongTimeout?: number
21
- }
22
- interface HubtypeServiceArgs {
23
- appId: string
24
- user: SessionUser
25
- lastMessageId: string
26
- lastMessageUpdateDate: string
27
- onEvent: any
28
- unsentInputs: () => UnsentInput[]
29
- server: ServerConfig
30
- }
31
-
32
- const _WEBCHAT_PUSHER_KEY_ = getWebpackEnvVar(
33
- // @ts-ignore
34
- typeof WEBCHAT_PUSHER_KEY !== 'undefined' && WEBCHAT_PUSHER_KEY,
35
- 'WEBCHAT_PUSHER_KEY',
36
- '434ca667c8e6cb3f641c'
37
- )
38
- const _HUBTYPE_API_URL_ = getWebpackEnvVar(
39
- // @ts-ignore
40
- typeof HUBTYPE_API_URL !== 'undefined' && HUBTYPE_API_URL,
41
- 'HUBTYPE_API_URL',
42
- 'https://api.hubtype.com'
43
- )
44
-
45
- const ACTIVITY_TIMEOUT = 20 * 1000 // https://pusher.com/docs/channels/using_channels/connection#activitytimeout-integer-
46
- const PONG_TIMEOUT = 5 * 1000 // https://pusher.com/docs/channels/using_channels/connection#pongtimeout-integer-
47
-
48
- /**
49
- * Calls Hubtype APIs from Webchat
50
- */
51
- export class HubtypeService {
52
- appId: string
53
- user: SessionUser
54
- lastMessageId: string
55
- lastMessageUpdateDate: string
56
- onEvent: any
57
- unsentInputs: () => UnsentInput[]
58
- pusher: Pusher | null
59
- channel: Channel
60
- server: ServerConfig
61
- PUSHER_CONNECT_TIMEOUT_MS = 10000
62
- constructor({
63
- appId,
64
- user,
65
- lastMessageId,
66
- lastMessageUpdateDate,
67
- onEvent,
68
- unsentInputs,
69
- server,
70
- }: HubtypeServiceArgs) {
71
- this.appId = appId
72
- this.user = user || {}
73
- this.lastMessageId = lastMessageId
74
- this.lastMessageUpdateDate = lastMessageUpdateDate
75
- this.onEvent = onEvent
76
- this.unsentInputs = unsentInputs
77
- this.server = server
78
- if (this.user.id && (lastMessageId || lastMessageUpdateDate)) {
79
- // It's safe not awaiting Promise because:
80
- // * it will never be called from AWS lambda
81
- // * though init() is called again from postMesage, it does nothing if Pusher already created
82
- // @ts-ignore
83
- this.init()
84
- }
85
- }
86
-
87
- /**
88
- * @returns {Promise<void>}
89
- */
90
- init(user, lastMessageId, lastMessageUpdateDate): Promise<void> {
91
- if (user) this.user = user
92
- if (lastMessageId) this.lastMessageId = lastMessageId
93
- if (lastMessageUpdateDate)
94
- this.lastMessageUpdateDate = lastMessageUpdateDate
95
- return this._initPusher()
96
- }
97
-
98
- /**
99
- * @returns {Promise<void>}
100
- */
101
- _initPusher(): Promise<void> {
102
- if (this.pusher) return Promise.resolve()
103
- if (!this.user.id || !this.appId) {
104
- // TODO recover user & appId somehow
105
- return Promise.reject('No User or appId. Clear cache and reload')
106
- }
107
- this.pusher = new Pusher(_WEBCHAT_PUSHER_KEY_, {
108
- cluster: 'eu',
109
- authEndpoint: `${_HUBTYPE_API_URL_}/v1/provider_accounts/webhooks/webchat/${this.appId}/auth/`,
110
- forceTLS: true,
111
- auth: {
112
- headers: this.constructHeaders(),
113
- } as AuthOptions,
114
- ...this.resolveServerConfig(),
115
- })
116
- this.channel = this.pusher.subscribe(this.pusherChannel)
117
- const connectionPromise = new Promise<void>((resolve, reject) => {
118
- const cleanAndReject = msg => {
119
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
120
- clearTimeout(connectTimeout)
121
- this.destroyPusher()
122
- reject(msg)
123
- }
124
- const connectTimeout = setTimeout(
125
- () => cleanAndReject('Connection Timeout'),
126
- this.PUSHER_CONNECT_TIMEOUT_MS
127
- )
128
- this.channel.bind('pusher:subscription_succeeded', () => {
129
- // Once subscribed, we know that authentication has been done: https://pusher.com/docs/channels/server_api/authenticating-users
130
- this.onConnectionRegained()
131
- clearTimeout(connectTimeout)
132
- resolve()
133
- })
134
- this.channel.bind('botonic_response', data => this.onPusherEvent(data))
135
- this.channel.bind('update_message_info', data => this.onPusherEvent(data))
136
-
137
- this.pusher &&
138
- this.pusher.connection.bind('error', event => {
139
- if (event.type == 'WebSocketError') this.handleConnectionChange(false)
140
- else {
141
- const errorMsg =
142
- event.error && event.error.data
143
- ? event.error.data.code || event.error.data.message
144
- : 'Connection error'
145
- cleanAndReject(`Pusher error (${errorMsg})`)
146
- }
147
- })
148
- })
149
- this.pusher.connection.bind('state_change', states => {
150
- if (states.current === 'connecting') this.updateAuthHeaders()
151
- if (states.current === 'connected') this.handleConnectionChange(true)
152
- if (states.current === 'unavailable') this.handleConnectionChange(false)
153
- })
154
-
155
- return connectionPromise
156
- }
157
-
158
- constructHeaders(): BotonicHeaders {
159
- const headers = {}
160
- if (this.user && this.user.id) headers['X-BOTONIC-USER-ID'] = this.user.id
161
- if (this.lastMessageId)
162
- headers['X-BOTONIC-LAST-MESSAGE-ID'] = this.lastMessageId
163
- if (this.lastMessageUpdateDate)
164
- headers['X-BOTONIC-LAST-MESSAGE-UPDATE-DATE'] = this.lastMessageUpdateDate
165
- return headers as BotonicHeaders
166
- }
167
-
168
- resolveServerConfig(): ServerConfig {
169
- if (!this.server) {
170
- return { activityTimeout: ACTIVITY_TIMEOUT, pongTimeout: PONG_TIMEOUT }
171
- }
172
- return {
173
- activityTimeout: this.server.activityTimeout || ACTIVITY_TIMEOUT,
174
- pongTimeout: this.server.pongTimeout || PONG_TIMEOUT,
175
- }
176
- }
177
-
178
- updateAuthHeaders(): void {
179
- if (this.pusher) {
180
- this.pusher.config.auth.headers = {
181
- ...this.pusher.config.auth.headers,
182
- ...this.constructHeaders(),
183
- }
184
- }
185
- }
186
-
187
- handleConnectionChange(online: boolean): void {
188
- this.onPusherEvent({ action: 'connectionChange', online })
189
- }
190
-
191
- onPusherEvent(event: any): void {
192
- if (this.onEvent && typeof this.onEvent === 'function') this.onEvent(event)
193
- }
194
-
195
- get pusherChannel(): string {
196
- return `private-encrypted-${this.appId}-${this.user.id}`
197
- }
198
-
199
- handleSentInput(message: any): void {
200
- this.onEvent({
201
- action: 'update_message_info',
202
- message: { id: message.id, ack: 1 },
203
- })
204
- }
205
-
206
- handleUnsentInput(message: any): void {
207
- this.onEvent({
208
- action: 'update_message_info',
209
- message: { id: message.id, ack: 0, unsentInput: message },
210
- })
211
- }
212
-
213
- /**
214
- * @return {Promise<void>}
215
- */
216
- async postMessage(user: SessionUser, message: any): Promise<void> {
217
- try {
218
- // @ts-ignore
219
- await this.init(user)
220
- await axios.post(
221
- `${_HUBTYPE_API_URL_}/v1/provider_accounts/webhooks/webchat/${this.appId}/`,
222
- {
223
- sender: this.user,
224
- message: message,
225
- },
226
- {
227
- validateStatus: status => status === 200,
228
- }
229
- )
230
- this.handleSentInput(message)
231
- } catch (e) {
232
- this.handleUnsentInput(message)
233
- }
234
- return Promise.resolve()
235
- }
236
-
237
- static async getWebchatVisibility({
238
- appId,
239
- }: {
240
- appId: string
241
- }): Promise<AxiosResponse<any>> {
242
- return axios.get(
243
- `${_HUBTYPE_API_URL_}/v1/provider_accounts/${appId}/visibility/`
244
- )
245
- }
246
-
247
- destroyPusher(): void {
248
- if (!this.pusher) return
249
- this.pusher.disconnect()
250
- this.pusher.unsubscribe(this.pusherChannel)
251
- this.pusher.unbind_all()
252
- this.pusher.channels = {} as Channels
253
- this.pusher = null
254
- }
255
-
256
- async onConnectionRegained(): Promise<void> {
257
- await this.resendUnsentInputs()
258
- }
259
-
260
- async resendUnsentInputs(): Promise<void> {
261
- for (const message of this.unsentInputs()) {
262
- message.unsentInput &&
263
- (await this.postMessage(this.user, message.unsentInput))
264
- }
265
- }
266
- }
package/src/i18n.ts DELETED
@@ -1,12 +0,0 @@
1
- // eslint-disable-next-line filenames/match-regex
2
- import { Locales } from './index'
3
-
4
- export const getString = (
5
- locales: Locales,
6
- locale: string,
7
- stringID: string
8
- ): string => {
9
- let l = stringID.split('.').reduce((o, i) => o[i], locales[locale])
10
- if (l instanceof Array) l = l[Math.floor(Math.random() * l.length)]
11
- return String(l)
12
- }