rn-kore-bot-socket-lib-v77
Version:
Description of Bot Scocket SDK library
1,515 lines (1,507 loc) • 53.5 kB
JavaScript
// bot-sdk/constants/Constant.tsx
var URL_VERSION = "/1.1";
var RTM_EVENT = {
CONNECTING: "connecting",
AUTHENTICATED: "authenticated",
ON_OPEN: "on_open",
ON_DISCONNECT: "disconnect",
ON_CLOSE: "on_close",
ON_ERROR: "on_error",
ON_MESSAGE: "on_message",
ON_FAILURE: "failure",
PING: "ping",
PONG: "pong",
ERROR: "error",
RECONNECTING: "reconnecting",
UNABLE_TO_RTM_START: "unable_to_rtm_start",
GET_HISTORY: "get_history",
GET_RESULT_VIEW_SETTINGS: "result_view_settings",
ON_ACK: "ack",
ON_EVENTS: "events",
ON_JWT_TOKEN_AUTHORIZED: "ON_JWT_TOKEN_AUTHORIZED"
};
var ConnectionState = {
CONNECTING: 0,
CONNECTED: 1,
DISCONNECTED: 2
};
var APP_STATE = {
ACTIVE: "active",
SLEEP: "sleep"
};
// bot-sdk/rtm/BotClient.tsx
import { EventEmitter } from "events";
// bot-sdk/model/BotInfoModel.tsx
import { Platform } from "react-native";
var BotInfoModel = class {
constructor(chatBot, taskBotId, customData, channelClient = Platform.OS) {
this.chatBot = chatBot;
this.taskBotId = taskBotId;
this.customData = customData;
this.channelClient = channelClient;
}
};
// bot-sdk/rtm/BotClient.tsx
import { Platform as Platform3 } from "react-native";
// bot-sdk/utils/Logger.tsx
var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
LogLevel2[LogLevel2["INFO"] = 1] = "INFO";
LogLevel2[LogLevel2["WARN"] = 2] = "WARN";
LogLevel2[LogLevel2["ERROR"] = 3] = "ERROR";
return LogLevel2;
})(LogLevel || {});
var Logger = class _Logger {
static instance;
logLevel = 1 /* INFO */;
logs = [];
maxLogs = 1e3;
constructor() {
}
static getInstance() {
if (!_Logger.instance) {
_Logger.instance = new _Logger();
}
return _Logger.instance;
}
setLogLevel(level) {
this.logLevel = level;
}
log(level, category, message, data, error) {
if (level < this.logLevel) {
return;
}
const logEntry = {
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
level,
category,
message,
data,
error
};
this.logs.push(logEntry);
if (this.logs.length > this.maxLogs) {
this.logs = this.logs.slice(-this.maxLogs);
}
const levelName = LogLevel[level];
const formattedMessage = `[${logEntry.timestamp}] [${levelName}] [${category}] ${message}`;
switch (level) {
case 0 /* DEBUG */:
console.debug(formattedMessage, data || "");
break;
case 1 /* INFO */:
console.info(formattedMessage, data || "");
break;
case 2 /* WARN */:
console.warn(formattedMessage, data || "");
if (error) console.warn("Error details:", error);
break;
case 3 /* ERROR */:
console.error(formattedMessage, data || "");
if (error) console.error("Error details:", error);
break;
}
}
// API specific logging methods
logApiRequest(endpoint, method, data) {
this.log(1 /* INFO */, "API_REQUEST", `${method} ${endpoint}`, data);
}
logApiSuccess(endpoint, method, responseData, duration) {
const message = duration ? `${method} ${endpoint} - Success (${duration}ms)` : `${method} ${endpoint} - Success`;
this.log(1 /* INFO */, "API_SUCCESS", message, responseData);
}
logApiError(endpoint, method, error, duration) {
const message = duration ? `${method} ${endpoint} - Error (${duration}ms)` : `${method} ${endpoint} - Error`;
this.log(3 /* ERROR */, "API_ERROR", message, {
status: error?.response?.status,
statusText: error?.response?.statusText,
message: error?.message
}, error);
}
// WebSocket specific logging
logWebSocketEvent(event, data) {
this.log(1 /* INFO */, "WEBSOCKET", `WebSocket ${event}`, data);
}
logWebSocketError(event, error) {
this.log(3 /* ERROR */, "WEBSOCKET_ERROR", `WebSocket ${event}`, void 0, error);
}
// Connection specific logging
logConnectionEvent(event, data) {
this.log(1 /* INFO */, "CONNECTION", event, data);
}
logConnectionError(event, error) {
this.log(3 /* ERROR */, "CONNECTION_ERROR", event, void 0, error);
}
// General logging methods
debug(message, data) {
this.log(0 /* DEBUG */, "DEBUG", message, data);
}
info(message, data) {
this.log(1 /* INFO */, "INFO", message, data);
}
warn(message, data, error) {
this.log(2 /* WARN */, "WARN", message, data, error);
}
error(message, data, error) {
this.log(3 /* ERROR */, "ERROR", message, data, error);
}
// Get logs for debugging
getLogs(level) {
if (level !== void 0) {
return this.logs.filter((log) => log.level >= level);
}
return [...this.logs];
}
// Clear logs
clearLogs() {
this.logs = [];
}
};
var Logger_default = Logger.getInstance();
// bot-sdk/api/ApiService.tsx
import { Platform as Platform2 } from "react-native";
var RECONNECT_ATTEMPT_LIMIT = 5;
var ApiService = class {
baseUrl;
botClient;
constructor(baseUrl, botClient) {
this.baseUrl = baseUrl;
this.botClient = botClient;
}
async fetchWithRetries(url, options, retries = 1, method = "POST") {
try {
return await fetch(url, options);
} catch (err) {
if (retries <= RECONNECT_ATTEMPT_LIMIT) {
const delay = Math.min(Math.pow(2, retries) / 4 + Math.random(), RECONNECT_ATTEMPT_LIMIT) * 1e3;
await new Promise((resolve) => setTimeout(() => resolve(void 0), delay));
Logger_default.logApiError(url, method, err, delay);
return this.fetchWithRetries(url, options, retries + 1, method);
} else {
throw new Error(`Max retries exceeded. error: ${err}`);
}
}
}
async getBotHistory(offset, limit, botConfig, onResponse) {
let historyUrl = this.baseUrl + (botConfig.isWebHook ? "/api/chathistory/" + botConfig.botId + "/ivr?&botId=" + botConfig.botId + "&limit=" + limit + "&offset=" + offset : "/api" + URL_VERSION + "/botmessages/rtm");
const startTime = Date.now();
Logger_default.logApiRequest(historyUrl, "GET", {
botId: botConfig.botId,
limit,
offset,
forward: true
});
const urlWithParams = new URL(historyUrl);
if (!botConfig.isWebHook) {
urlWithParams.searchParams.append("botId", botConfig.botId);
urlWithParams.searchParams.append("limit", limit + "");
urlWithParams.searchParams.append("offset", offset + "");
urlWithParams.searchParams.append("forward", "true");
}
try {
const response = await this.fetchWithRetries(urlWithParams.toString(), {
method: "GET",
headers: {
"Accept": "application/json",
Authorization: botConfig.isWebHook ? "bearer " + this.botClient.getJwtToken() : this.botClient.getAuthorization() + ""
}
}, 1, "GET");
const duration = Date.now() - startTime;
const responseData = await response.json();
if (!response.ok) {
const error = new Error(`HTTP ${response.status}`);
error.response = {
status: response.status,
statusText: response.statusText,
data: responseData
};
onResponse();
return;
}
Logger_default.logApiSuccess(historyUrl, "GET", {
messageCount: responseData?.length || 0,
hasData: !!responseData
}, duration);
const axiosResponse = {
data: this.processHistoryResponse(responseData, botConfig.botName || "", botConfig.botId),
status: response.status,
statusText: response.statusText,
headers: {}
};
onResponse(axiosResponse);
} catch (e) {
const duration = Date.now() - startTime;
Logger_default.logApiError(historyUrl, "GET", e, duration);
onResponse();
}
}
processHistoryResponse = (botHistory, botName, botId) => {
let msgs = [];
console.log("BotHistory >>> " + JSON.stringify(botHistory));
if (!botHistory.messages) return [];
const moreHistory = botHistory.moreAvailable;
const icon = botHistory.icon;
const messages = botHistory.messages;
if (messages) {
for (const msg of messages) {
const components = msg.components;
const data = (components[0].data.text ? components[0].data.text : "").replaceAll(""", '"');
let botMessage;
if (msg.type == "outgoing") {
if (!data) continue;
botMessage = this.createBotResponse(data, icon, msg.createdOn, msg._id, botName, botId);
} else {
const tags = msg.tags;
const altText = tags.altText;
const renderMsg = altText ? altText[0] ? altText[0].value : null : null;
botMessage = this.createBotRequest(msg._id, data, msg.createdOn, botName, botId, renderMsg);
}
msgs.push(botMessage);
}
}
msgs = [...msgs].sort((a, b) => b.timeMillis - a.timeMillis);
return { botHistory: msgs, moreAvailable: moreHistory };
};
createBotResponse = (data, icon, createdOn, msgId, botName, botId) => {
let payloadOuter;
try {
payloadOuter = JSON.parse(data);
} catch (exception) {
payloadOuter = { text: data };
}
const componentModel = { type: "template", payload: payloadOuter };
const componentInfo = { body: payloadOuter };
const messageArray = [];
const message = { type: "text", component: componentModel, cInfo: componentInfo };
messageArray.push(message);
const botInfo = { botName, taskBotId: botId, customData: null, channelClient: Platform2.OS };
return {
type: "bot_response",
timeMillis: new Date(createdOn).getTime(),
messageId: msgId,
message: messageArray,
from: "bot",
isSend: false,
icon,
createdOn,
botInfo
};
};
createBotRequest = (msgId, message, createdOn, botName, botId, renderMsg) => {
const component = {
type: "text",
payload: {
text: renderMsg ? renderMsg : message,
attachments: "",
createdOn
}
};
const botMessage = {
type: "text",
component,
clientMessageId: new Date(createdOn).getTime()
};
const botInfo = { botName, taskBotId: botId, customData: null, channelClient: Platform2.OS };
return {
type: "user_message",
timeMillis: new Date(createdOn).getTime(),
messageId: msgId,
message: [botMessage],
resourceId: "/bot.message",
botInfo,
createdOn,
client: Platform2.OS,
isSend: true
};
};
async subscribePushNotifications(deviceId) {
if (!deviceId) {
Logger_default.logConnectionError("Push notification subscription Failed", "deviceId is not VALID!");
return false;
}
Logger_default.debug("Subscribe notications", "is in-progress");
let url = `/api/users/${this.botClient.getUserId()}/sdknotifications/subscribe`;
let subscribeUrl = this.baseUrl + url;
const startTime = Date.now();
let payload = { osType: Platform2.OS, deviceId };
Logger_default.logApiRequest(subscribeUrl, "POST", {});
const headers = { Authorization: `bearer ${this.botClient.getAccessToken()}` };
try {
const response = await this.fetchWithRetries(subscribeUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
...headers
},
body: JSON.stringify(payload)
}, 1, "POST");
const duration = Date.now() - startTime;
if (!response.ok) {
const responseData = await response.json().catch(() => ({}));
const error = new Error(`HTTP ${response.status}`);
error.response = {
status: response.status,
statusText: response.statusText,
data: responseData
};
throw error;
}
Logger_default.logApiSuccess(subscribeUrl, "POST", {}, duration);
Logger_default.logConnectionEvent("Push notification subscription Success", {});
return true;
} catch (e) {
const duration = Date.now() - startTime;
Logger_default.logApiError(subscribeUrl, "POST", e, duration);
Logger_default.logConnectionError("Push notification subscription Failed", e);
return false;
}
}
async unsubscribePushNotifications(deviceId) {
if (!deviceId) {
Logger_default.logConnectionError("Push notification unsubscription Failed", "deviceId is not VALID!");
return false;
}
Logger_default.debug("Unsubscribe notications", "is in-progress");
let url = `/api/users/${this.botClient.getUserId()}/sdknotifications/unsubscribe`;
let subscribeUrl = this.baseUrl + url;
const startTime = Date.now();
let payload = { osType: Platform2.OS, deviceId };
Logger_default.logApiRequest(subscribeUrl, "POST", {});
const headers = {
Authorization: `bearer ${this.botClient.getAccessToken()}`,
"Content-type": "application/json",
"X-HTTP-Method-Override": "DELETE"
};
try {
const response = await this.fetchWithRetries(subscribeUrl, {
method: "POST",
headers: {
"Accept": "application/json",
...headers
},
body: JSON.stringify(payload)
}, 1, "POST");
const duration = Date.now() - startTime;
if (!response.ok) {
const responseData = await response.json().catch(() => ({}));
const error = new Error(`HTTP ${response.status}`);
error.response = {
status: response.status,
statusText: response.statusText,
data: responseData
};
throw error;
}
Logger_default.logApiSuccess(subscribeUrl, "POST", {}, duration);
Logger_default.logConnectionEvent("Push notification unsubscription Success", {});
return true;
} catch (e) {
const duration = Date.now() - startTime;
Logger_default.logApiError(subscribeUrl, "POST", e, duration);
Logger_default.logConnectionError("Push notification unsubscription Failed", e);
return false;
}
}
async getJwtToken(config, isFirstTime = true, onResponse, onError) {
const body = {
clientId: config.clientId,
clientSecret: config.clientSecret,
identity: config.identity,
aud: config.value_aud,
isAnonymous: false
};
const botUrl = this.botClient.getJwtServerUrl();
let jwtAuthorizationUrl = botUrl + "users/sts";
const startTime = Date.now();
Logger_default.logApiRequest(jwtAuthorizationUrl, "POST", {
clientId: body.clientId,
identity: body.identity,
aud: body.aud,
isAnonymous: body.isAnonymous
});
try {
const response = await this.fetchWithRetries(jwtAuthorizationUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify(body)
}, 1, "POST");
const duration = Date.now() - startTime;
const responseData = await response.json();
if (!response.ok) {
const error = new Error(`HTTP ${response.status}`);
error.response = {
status: response.status,
statusText: response.statusText,
data: responseData
};
throw error;
}
Logger_default.logApiSuccess(jwtAuthorizationUrl, "POST", {
hasJwtToken: !!responseData.jwt,
tokenLength: responseData.jwt?.length
}, duration);
onResponse(responseData.jwt);
return true;
} catch (e) {
const duration = Date.now() - startTime;
Logger_default.logApiError(jwtAuthorizationUrl, "POST", e, duration);
Logger_default.logConnectionError("JWT Token Generation Failed", e);
onError("Connection to the bot failed. Please ensure your configuration is valid and try again.");
return false;
}
}
async getJwtGrant(jwtToken, isReconnectionAttempt, onStatus, onResponse, onError) {
Logger_default.logConnectionEvent("JWT grant Authorization Started", {
isReconnectionAttempt,
tokenLength: jwtToken.length
});
onStatus(RTM_EVENT.CONNECTING);
this.baseUrl = this.botClient.getBotUrl();
let jwtAuthorizationUrl = this.baseUrl + "/api/oAuth/token/jwtgrant";
const startTime = Date.now();
let payload = { assertion: jwtToken, botInfo: this.botClient.getBotInfo() };
Logger_default.logApiRequest(jwtAuthorizationUrl, "POST", {
botId: this.botClient.getBotInfo()?.taskBotId,
botName: this.botClient.getBotInfo()?.botName
});
try {
const response = await this.fetchWithRetries(jwtAuthorizationUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify(payload)
}, 1, "POST");
const duration = Date.now() - startTime;
const responseData = await response.json();
if (!response.ok) {
const error = new Error(`HTTP ${response.status}`);
error.response = {
status: response.status,
statusText: response.statusText,
data: responseData
};
throw error;
}
Logger_default.logApiSuccess(jwtAuthorizationUrl, "POST", {
hasUserInfo: !!responseData.userInfo,
hasAuthorization: !!responseData.authorization,
userId: responseData.userInfo?.userId,
tokenType: responseData.authorization?.token_type
}, duration);
onResponse(responseData);
return true;
} catch (e) {
const duration = Date.now() - startTime;
Logger_default.logApiError(jwtAuthorizationUrl, "POST", e, duration);
Logger_default.logConnectionError("JWT Grant Authorization Failed", e);
onError("Connection to the bot failed. Please ensure your configuration is valid and try again.");
return false;
}
}
async getRtmUrl(isReconnectionAttempt, onResponse, onError) {
let rtmUrl = this.baseUrl + "/api/rtm/start";
let payload = { botInfo: this.botClient.getBotInfo() };
const startTime = Date.now();
Logger_default.logApiRequest(rtmUrl, "POST", {
botId: this.botClient.getBotInfo()?.taskBotId,
botName: this.botClient.getBotInfo()?.botName,
isReconnectionAttempt
});
try {
const response = await this.fetchWithRetries(rtmUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
Authorization: this.botClient.getAuthorization() + ""
},
body: JSON.stringify(payload)
}, 1, "POST");
const duration = Date.now() - startTime;
const responseData = await response.json();
if (!response.ok) {
const error = new Error(`HTTP ${response.status}`);
error.response = {
status: response.status,
statusText: response.statusText,
data: responseData
};
throw error;
}
Logger_default.logApiSuccess(rtmUrl, "POST", {
hasUrl: !!responseData.url,
url: responseData.url?.substring(0, 50) + "..."
}, duration);
Logger_default.logConnectionEvent("RTM URL Retrieved Successfully", {
isReconnectionAttempt,
hasWebSocketUrl: !!responseData.url
});
onResponse(responseData);
} catch (e) {
const duration = Date.now() - startTime;
Logger_default.logApiError(rtmUrl, "POST", e, duration);
onError(e);
}
}
async getSettings(onResponse) {
let urlString = this.baseUrl + "/searchassistapi/searchsdk/stream/" + this.botClient.getBotInfo().taskBotId + "/" + this.botClient.getBotInfo().searchIndexId + "/getresultviewsettings";
const startTime = Date.now();
Logger_default.logApiRequest(urlString, "GET", {
taskBotId: this.botClient.getBotInfo().taskBotId,
searchIndexId: this.botClient.getBotInfo().searchIndexId
});
try {
const response = await this.fetchWithRetries(urlString, {
method: "GET",
headers: {
"Accept": "application/json",
Authorization: this.botClient.getAuthorization() + "",
auth: ""
}
}, 1, "GET");
const duration = Date.now() - startTime;
const responseData = await response.json();
if (!response.ok) {
const error = new Error(`HTTP ${response.status}`);
error.response = {
status: response.status,
statusText: response.statusText,
data: responseData
};
throw error;
}
Logger_default.logApiSuccess(urlString, "GET", {
hasSettings: !!responseData?.settings,
settingsCount: responseData?.settings?.length || 0
}, duration);
if (responseData?.settings) {
onResponse(responseData?.settings);
}
} catch (e) {
const duration = Date.now() - startTime;
Logger_default.logApiError(urlString, "GET", e, duration);
}
}
async getWebHookBotMeta(jwtToken, botId, onResponse) {
let url = this.baseUrl + "/api/botmeta/" + botId;
const startTime = Date.now();
Logger_default.logApiRequest(url, "GET", { botId });
const urlWithParams = new URL(url);
try {
const response = await this.fetchWithRetries(urlWithParams.toString(), {
method: "GET",
headers: {
"Accept": "application/json",
Authorization: "bearer " + jwtToken
}
}, 1, "GET");
const duration = Date.now() - startTime;
const responseData = response;
if (!response.ok) {
const error = new Error(`HTTP ${response.status}`);
error.response = {
status: response.status,
statusText: response.statusText,
data: responseData
};
onResponse();
return;
}
Logger_default.logApiSuccess(url, "GET", {
messageCount: responseData?.length || 0,
hasData: responseData
}, duration);
const axiosResponse = {
data: responseData,
status: response.status,
statusText: response.statusText,
headers: {}
};
onResponse(axiosResponse);
} catch (e) {
const duration = Date.now() - startTime;
Logger_default.logApiError(url, "GET", e, duration);
onResponse();
}
}
async sendWebHookMessage(botConfig, isNewSession, msg, onResponse, payload, attachments) {
let url = this.baseUrl + "/chatbot/v2/webhook/" + botConfig.botId;
const startTime = Date.now();
const urlWithParams = new URL(url);
const customData = {
userName: "",
identity: "",
userAgent: Platform2.OS,
botToken: this.botClient.getJwtToken()
};
const requestPayload = {
session: { new: isNewSession },
message: {
type: isNewSession ? "event" : "text",
val: payload ? payload : msg
},
from: {
userInfo: {
firstName: "",
lastName: "",
email: ""
},
id: botConfig.identity
},
to: {
id: botConfig.botName,
groupInfo: {
id: "",
name: ""
}
},
attachments,
customData
};
console.log("Webhook payload " + JSON.stringify(requestPayload));
Logger_default.logApiRequest(url, "POST", { message: requestPayload });
try {
const response = await this.fetchWithRetries(urlWithParams.toString(), {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
Authorization: "bearer " + this.botClient.getJwtToken()
},
body: JSON.stringify(requestPayload)
}, 1, "POST");
const duration = Date.now() - startTime;
const responseData = await response.json();
console.log("Webhook response " + JSON.stringify(responseData));
if (!response.ok) {
const error = new Error(`HTTP ${response.status}`);
error.response = {
status: response.status,
statusText: response.statusText,
data: responseData
};
onResponse();
return;
}
Logger_default.logApiSuccess(url, "POST", {
messageCount: responseData?.length || 0,
hasData: !!responseData
}, duration);
const messages = this.processWebHookResponse(botConfig, responseData);
const axiosResponse = {
data: messages,
status: response.status,
statusText: response.statusText,
headers: {},
pollId: responseData.pollId
};
onResponse(axiosResponse);
if (responseData.pollId) {
setTimeout(async () => {
await this.getPollData(botConfig, responseData.pollId, onResponse);
}, 5e3);
}
} catch (e) {
const duration = Date.now() - startTime;
Logger_default.logApiError(url, "POST", e, duration);
onResponse();
}
}
processWebHookResponse(botConfig, response) {
const messages = response.data;
const processedMessages = [];
for (const message of messages) {
const isObject = typeof message.val === "object";
const payloadInner = { template_type: "text", text: "" };
if (!isObject) {
payloadInner.text = message.val;
}
let payloadOuter = isObject ? message.val : { text: message.val, type: "text", payload: payloadInner };
if (!isObject) {
try {
payloadOuter = JSON.parse(message.val);
} catch (e) {
}
}
const component = { type: isObject ? payloadOuter.type : "text", payload: payloadOuter };
const cInfo = { body: isObject ? payloadOuter : payloadInner };
const botResponseMsg = { type: isObject ? component.type : "text", component, cInfo };
const msgs = [botResponseMsg];
const botInfo = { chatBot: botConfig.botName, taskBotId: botConfig.botId, customData: null, channelClient: Platform2.OS };
const msg = {
type: "bot_response",
from: "bot",
message: msgs,
messageId: message.messageId,
createdOn: message.createdOn,
timeMillis: new Date(message.createdOn).getTime(),
botInfo
};
processedMessages.push(JSON.stringify(msg));
}
return processedMessages;
}
async getPollData(botConfig, pollId, onResponse) {
let url = this.baseUrl + "/chatbot/v2/webhook/" + botConfig.botId + "/poll/" + pollId;
const startTime = Date.now();
const urlWithParams = new URL(url);
Logger_default.logApiRequest(url, "GET", { pollId });
try {
const response = await this.fetchWithRetries(urlWithParams.toString(), {
method: "GET",
headers: {
"Accept": "application/json",
Authorization: "bearer " + this.botClient.getJwtToken()
}
}, 1, "GET");
const duration = Date.now() - startTime;
const responseData = await response.json();
console.log("PollData response " + JSON.stringify(responseData));
if (!response.ok) {
const error = new Error(`HTTP ${response.status}`);
error.response = {
status: response.status,
statusText: response.statusText,
data: responseData
};
onResponse();
return;
}
Logger_default.logApiSuccess(url, "GET", {
messageCount: responseData?.length || 0,
hasData: !!responseData
}, duration);
if (!responseData.data) {
return;
}
const messages = this.processWebHookResponse(botConfig, responseData);
const axiosResponse = {
data: messages,
status: response.status,
statusText: response.statusText,
headers: {}
};
onResponse(axiosResponse);
if (responseData.pollId) {
setTimeout(async () => {
await this.getPollData(botConfig, responseData.pollId, onResponse);
}, 5e3);
}
} catch (e) {
const duration = Date.now() - startTime;
Logger_default.logApiError(url, "GET", e, duration);
onResponse();
}
}
};
// bot-sdk/rtm/BotClient.tsx
var RECONNECT_ATTEMPT_LIMIT2 = 5;
var BotClient = class extends EventEmitter {
pingInterval;
pingTimer;
receivedLastPong;
timer;
isConnecting;
jwtToken;
resultViewSettings;
webSocket;
botUrl;
sessionActive;
appState;
isNetWorkAvailable;
botInfo;
customData;
userInfo;
authorization;
botCustomData;
isConnectAtleastOnce;
connectionState = ConnectionState.DISCONNECTED;
reconnectAttemptCount = 0;
isReconnectAttemptRequired = false;
DATA_IDENTITY = "identity";
DATA_USERNAME = "userName";
RECONNECT_PARAM = "&isReconnect=true";
reconnectTimer;
botConfig;
isChangeToken;
constructor() {
super();
this.pingInterval = 1e4;
this.receivedLastPong = false;
this.isConnecting = false;
this.jwtToken = "";
this.resultViewSettings = [];
this.webSocket = void 0;
this.botUrl = "";
this.sessionActive = false;
this.appState = APP_STATE.ACTIVE;
this.isNetWorkAvailable = true;
this.botCustomData = /* @__PURE__ */ new Map();
this.isChangeToken = true;
this.isConnectAtleastOnce = false;
}
initializeBotClient(config, isFirstTime) {
if (config == null || config == void 0) {
throw new Error("BotConfigModel object can not be null");
}
if (!config.botId || !config.clientId || !config.clientSecret || !config.botUrl || !config.identity || !config.value_aud) {
throw new Error("BotConfigModel object has some values are missing");
}
this.connectToBot(config, isFirstTime);
}
// async checkConnectivity() {
// try {
// const connectionInfo = await NetInfo.fetch();
// return connectionInfo.isConnected;
// } catch (error) {
// console.log('Error checking connectivity:', error);
// }
// return false;
// }
getJwtToken = () => {
return this.jwtToken;
};
getAccessToken() {
return this.authorization?.accessToken;
}
getUserId = () => {
return this.getBotUserId();
};
getBotName = () => {
return this.botConfig?.botName;
};
getBotUrl = () => {
return this.botConfig?.botUrl || "";
};
getJwtServerUrl = () => {
return this.botConfig?.jwtServerUrl || "";
};
getAuthorization = () => {
if (!this.authorization) {
return void 0;
}
return this.authorization?.token_type + " " + this.authorization?.accessToken;
};
async connectToBot(config, isFirstTime = true) {
const _this = this;
if (this.connectionState == ConnectionState.CONNECTED || this.isConnecting) {
console.log("this.connectionState :", this.connectionState);
return;
}
if (!config) {
this.emit(RTM_EVENT.ERROR, {
message: "BotConfigModel object has some values are missing",
isBack: true
});
return;
}
this.botConfig = config;
this.botCustomData.clear();
this.botCustomData.set(this.DATA_IDENTITY, "");
this.botCustomData.set(this.DATA_USERNAME, "");
this.isReconnectAttemptRequired = true;
await this.createJwtToken(this.botConfig, isFirstTime);
}
async createJwtToken(config, isFirstTime = true) {
if (!this.botConfig) return;
this.botInfo = new BotInfoModel(config.botName, config.botId, { identity: "", userName: "" });
this.initialize(this.botInfo, this.botCustomData);
if (this.botConfig.jwtToken) {
this.jwtToken = this.botConfig.jwtToken;
if (!this.botConfig?.isWebHook) {
await this.connectWithJwToken(this.jwtToken, !isFirstTime);
} else {
this.getWebhookMeta(this.botConfig, isFirstTime);
}
return;
}
const apiService = new ApiService(this.botConfig?.botName + "", this);
await apiService.getJwtToken(
this.botConfig,
isFirstTime,
async (jwtToken) => {
this.jwtToken = jwtToken;
if (!this.botConfig?.isWebHook) {
await this.connectWithJwToken(this.jwtToken, !isFirstTime);
} else {
this.getWebhookMeta(this.botConfig, isFirstTime);
}
},
(error) => {
this.emit(RTM_EVENT.ERROR, {
message: "Connection to the bot failed. Please ensure your configuration is valid and try again.",
isBack: false
});
}
);
}
async getWebhookMeta(botConfig, isFirstTime) {
const apiService = new ApiService(botConfig.botUrl, this);
await apiService.getWebHookBotMeta(this.jwtToken, botConfig.botId, (response) => {
if (response) {
apiService.sendWebHookMessage(
this.botConfig,
isFirstTime,
"ON_CONNECT",
(response2) => {
this.emit(RTM_EVENT.ON_OPEN);
if (isFirstTime) {
this.onWebhookMessages(response2.data);
}
}
);
}
});
}
initialize(botInfo, customData) {
this.botInfo = botInfo;
this.customData = customData;
}
setSessionActive(isActive) {
this.sessionActive = isActive;
}
setAppState(appState) {
this.appState = appState;
}
getAppState() {
return this.appState;
}
setIsNetworkAvailable(isNetWorkAvailable) {
this.isNetWorkAvailable = isNetWorkAvailable;
}
async connectWithJwToken(jwtToken, isReconnectionAttempt) {
if (this.isConnecting) {
Logger_default.warn("JWT Token Connection already in progress", {
isConnecting: this.isConnecting
});
return false;
}
this.jwtToken = jwtToken;
const apiService = new ApiService(this.botConfig?.botUrl + "", this);
await apiService.getJwtGrant(
jwtToken,
isReconnectionAttempt,
(status) => {
this.emit(RTM_EVENT.CONNECTING);
},
async (response) => {
this.userInfo = response.userInfo;
this.authorization = response.authorization;
Logger_default.logConnectionEvent("JWT Token Authorization Success", {
userId: this.userInfo?.userId,
tokenType: this.authorization?.token_type
});
this.emit(RTM_EVENT.ON_JWT_TOKEN_AUTHORIZED);
if (this.appState === APP_STATE.ACTIVE) {
await this.initSocketConnection(isReconnectionAttempt);
}
},
(error) => {
}
);
}
async getRtmUrl(isReconnectionAttempt) {
const apiService = new ApiService(this.botConfig?.botUrl + "", this);
await apiService.getRtmUrl(isReconnectionAttempt, (response) => {
this.connect(response, isReconnectionAttempt);
}, (error) => {
this.isChangeToken = false;
if (error?.response?.status === 401) {
Logger_default.logConnectionError("RTM Start - Unauthorized (401)", error);
this.refreshTokenAndReconnect(!isReconnectionAttempt);
} else if (isReconnectionAttempt) {
Logger_default.logConnectionError("RTM Start - Reconnection Failed", error);
this.reconnect(isReconnectionAttempt, !this.isConnectAtleastOnce);
} else {
Logger_default.logConnectionError("RTM Start - Connection Failed", error);
this.emit(RTM_EVENT.ERROR, {
message: "Error:" + error,
isBack: true
});
}
});
}
connect(data, isReconnectionAttempt) {
const _this = this;
let botServerUrl = this.botUrl?.replace("/https/g", "wss");
let url = data.url;
let wssUrl = url.replace("ws://dummy.com:80", botServerUrl);
this.connectionState = ConnectionState.CONNECTING;
wssUrl = isReconnectionAttempt ? wssUrl + this.RECONNECT_PARAM : wssUrl;
let isManualClose = false;
if (this.webSocket && (this.webSocket?.readyState == WebSocket.CONNECTING || this.webSocket?.readyState == WebSocket.OPEN)) {
isManualClose = true;
this.webSocket?.close();
}
const ws = new WebSocket(wssUrl);
ws.onopen = () => {
this.isConnectAtleastOnce = true;
Logger_default.logWebSocketEvent("Connected", {
url: wssUrl.substring(0, 100) + "...",
isReconnectionAttempt,
readyState: ws.readyState
});
_this.connectionState = ConnectionState.CONNECTED;
_this.emit(RTM_EVENT.ON_OPEN, {
message: "Bot socket connected",
isReconnectionAttempt
});
_this.startSendingPing();
_this.reconnectAttemptCount = 0;
};
ws.onclose = (e) => {
Logger_default.logWebSocketEvent("Closed", {
code: e?.code,
reason: e?.reason,
isManualClose,
wasCleanClose: e?.code === 1e3
});
_this.emit(RTM_EVENT.ON_CLOSE, "Bot socket closed:" + e);
if (isManualClose || e?.code === 1e3) {
Logger_default.info("WebSocket closed normally (manual or clean close)", {
code: e?.code,
isManualClose
});
return;
}
if (this.webSocket) {
this.webSocket.close();
}
_this.webSocket = void 0;
_this.isConnecting = false;
_this.reconnect(true);
_this.connectionState = ConnectionState.DISCONNECTED;
};
ws.onmessage = (e) => {
let data2 = JSON.parse(e.data);
switch (data2.type) {
case "pong":
_this.receivedLastPong = true;
Logger_default.debug("WebSocket Pong received", {
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
dataLength: e.data.length
});
break;
default:
Logger_default.logWebSocketEvent("Message Received", {
type: data2.type,
from: data2.from,
messageLength: e.data.length,
hasMessage: !!data2.message
});
_this.onMessage(e.data, false);
break;
}
};
ws.onerror = (e) => {
Logger_default.logWebSocketError("Error", e);
_this.emit(RTM_EVENT.ON_ERROR, e?.message);
if (_this.webSocket) {
_this.webSocket.close();
}
_this.webSocket = void 0;
_this.isConnecting = false;
let isReconnect = this.connectionState == ConnectionState.CONNECTED;
_this.connectionState = ConnectionState.DISCONNECTED;
_this.reconnect(isReconnect);
};
_this.webSocket = ws;
}
onMessage(messageData, isJsonObj = false) {
if (!messageData) {
return;
}
var data = null;
if (!isJsonObj) {
data = JSON.parse(messageData);
} else {
data = messageData;
}
switch (data.type) {
case "bot_response": {
if (data.from === "bot") {
if (data.type === "bot_response") {
data.timeMillis = new Date(data.createdOn).getTime();
}
this.emit(RTM_EVENT.ON_MESSAGE, data);
}
break;
}
case "user_message": {
if (data.from === "self") {
var message = data.message;
if (message) {
var messageData = {
type: "user_message",
message: [
{
type: "text",
component: {
type: "text",
payload: {
text: message.body,
createdOn: (/* @__PURE__ */ new Date()).getTime()
}
},
cInfo: {
body: message.body
},
clientMessageId: data.id
}
]
};
this.emit(RTM_EVENT.ON_MESSAGE, messageData);
}
}
break;
}
case "ack": {
this.emit(RTM_EVENT.ON_ACK, data);
break;
}
case "events": {
this.emit(RTM_EVENT.ON_EVENTS, data);
break;
}
case "pong": {
break;
}
default: {
break;
}
}
}
async fetchWithRetries(url, options, retries = 1, method = "POST") {
try {
return await fetch(url, options);
} catch (err) {
if (retries <= RECONNECT_ATTEMPT_LIMIT2) {
const delay = Math.min(Math.pow(2, retries) / 4 + Math.random(), RECONNECT_ATTEMPT_LIMIT2) * 1e3;
await new Promise((resolve) => setTimeout(() => resolve(void 0), delay));
Logger_default.logApiError(url, method, err, delay);
return this.fetchWithRetries(url, options, retries + 1, method);
} else {
throw new Error(`Max retries exceeded. error: ${err}`);
}
}
}
getConnectionState() {
return this.connectionState;
}
disconnect() {
Logger_default.logConnectionEvent("Bot Disconnect Called", {
connectionState: this.connectionState,
isConnecting: this.isConnecting,
hasWebSocket: !!this.webSocket,
reconnectAttemptCount: this.reconnectAttemptCount
});
if (this.reconnectTimer) {
this.reconnectAttemptCount = 0;
clearInterval(this.reconnectTimer);
}
if (this.pingTimer) {
clearInterval(this.pingTimer);
}
if (this.timer) {
clearInterval(this.timer);
}
this.connectionState = ConnectionState.DISCONNECTED;
this.isReconnectAttemptRequired = false;
this.userInfo = null;
this.authorization = null;
this.sessionActive = false;
this.isConnecting = false;
this.isConnectAtleastOnce = false;
if (this.webSocket) {
this.webSocket.close();
}
this.webSocket = void 0;
this.removeAllListeners();
Logger_default.logConnectionEvent("Bot Disconnected Successfully", {
connectionState: this.connectionState
});
}
async initSocketConnection(isReconnectionAttempt) {
if (this.isConnecting) {
return;
}
if (this.authorization) {
this.isConnecting = true;
await this.getRtmUrl(isReconnectionAttempt);
} else if (isReconnectionAttempt && this.botConfig) {
await this.connectToBot(this.botConfig, !this.isConnectAtleastOnce);
}
}
reconnect(isReconnectionAttempt, resetReconnectAttemptCount) {
if (this.isReconnectAttemptRequired && this.reconnectAttemptCount < RECONNECT_ATTEMPT_LIMIT2) {
Logger_default.logConnectionEvent("Reconnection Attempt", {
attemptCount: this.reconnectAttemptCount,
maxAttempts: RECONNECT_ATTEMPT_LIMIT2,
isReconnectionAttempt,
resetReconnectAttemptCount
});
if (this.reconnectTimer) {
clearInterval(this.reconnectTimer);
}
this.reconnectTimer = setTimeout(
async () => {
this.isConnecting = false;
await this.initSocketConnection(isReconnectionAttempt);
},
this.getReconnectDelay()
);
} else {
Logger_default.logConnectionError("Maximum Reconnection Limit Reached", {
attemptCount: this.reconnectAttemptCount,
maxAttempts: RECONNECT_ATTEMPT_LIMIT2,
isReconnectAttemptRequired: this.isReconnectAttemptRequired
});
}
}
async refreshTokenAndReconnect(isReconnectionAttempt) {
Logger_default.logConnectionEvent("Refresh Token and Reconnect Started", {
isReconnectionAttempt,
reconnectAttemptCount: this.reconnectAttemptCount,
connectionState: this.connectionState,
hasWebSocket: !!this.webSocket
});
if (this.reconnectTimer) {
this.reconnectAttemptCount = 0;
clearInterval(this.reconnectTimer);
}
this.isReconnectAttemptRequired = false;
this.userInfo = null;
this.authorization = null;
this.sessionActive = false;
this.isConnecting = false;
this.connectionState = ConnectionState.DISCONNECTED;
if (this.webSocket) {
this.webSocket.close();
}
if (this.webSocket?.readyState == WebSocket.CLOSED || this.webSocket?.readyState == WebSocket.CLOSING || this.receivedLastPong == false) {
clearInterval(this.pingTimer);
}
setTimeout(async () => {
this.reconnectAttemptCount = 0;
if (this.botConfig) {
Logger_default.logConnectionEvent("Initiating Fresh Connection After Token Refresh", {
hasBotConfig: !!this.botConfig
});
await this.connectToBot(this.botConfig, isReconnectionAttempt);
}
}, 500);
}
getReconnectDelay() {
this.reconnectAttemptCount++;
return 3e3;
}
checkSocketAndReconnect() {
if (!this.webSocket) {
this.reconnect(this.isReconnectAttemptRequired);
} else {
this.refreshTokenAndReconnect(false);
}
}
startSendingPing() {
let ws = this.webSocket;
if (this.pingTimer) {
clearInterval(this.pingTimer);
}
setTimeout(() => {
this.pingTimer = setInterval(() => {
if (ws?.readyState == WebSocket.OPEN) {
this.receivedLastPong = false;
this.send({ type: "ping" });
} else if (ws?.readyState == WebSocket.CLOSED || ws?.readyState == WebSocket.CLOSING || this.receivedLastPong == false) {
clearInterval(this.pingTimer);
}
}, this.pingInterval);
}, 1e3);
}
setTimer() {
let ws = this.webSocket;
if (this.timer) {
clearInterval(this.timer);
}
this.timer = setTimeout(() => {
if (ws?.readyState == WebSocket.OPEN) {
this.receivedLastPong = false;
this.send({ type: "ping" });
this.setTimer();
} else if (ws?.readyState == WebSocket.CLOSED || ws?.readyState == WebSocket.CLOSING || this.receivedLastPong == false) {
clearInterval(this.timer);
}
}, this.pingInterval);
}
send = (message) => {
switch (this.webSocket?.readyState) {
case WebSocket.OPEN:
try {
let jsonString = JSON.stringify(message);
this.webSocket.send(jsonString);
Logger_default.logWebSocketEvent("Message Sent", {
type: message.type,
clientMessageId: message.clientMessageId,
resourceid: message.resourceid,
messageLength: jsonString.length,
client: message.client
});
} catch (error) {
Logger_default.logWebSocketError("Send Failed", error);
}
break;
default:
Logger_default.warn("WebSocket Send Failed - Connection not ready", {
readyState: this.webSocket?.readyState,
connectionState: this.connectionState,
messageType: message.type
});
break;
}
};
getBotAccessToken() {
return this.authorization?.accessToken;
}
getResultViewSettings() {
return this.resultViewSettings;
}
//{"accountId": "60a4179424c895fef482f57c", "identity": "cs-1e38e7d9-20bd-579a-9a7c-9ec6777a39e2/42438ffd-b473-42d1-bd5f-66bd16715ad6", "managedBy": "60a4179424c895fef482f57c", "userId": "u-822d2104-c94e-5dc9-876b-b858b45d065d"}
getBotUserId() {
return this.userInfo?.userId;
}
getBotUserIdentity() {
return this.userInfo?.identity;
}
getBotInfo() {
return this.botInfo;
}
sendMessage(message, payload, attachments) {
var clientMessageId = (/* @__PURE__ */ new Date()).getTime();
Logger_default.info("Sending message to bot", {
clientMessageId,
messageLength: message?.length,
hasPayload: !!payload,
hasAttachments: !!attachments,
platform: Platform3.OS
});
var msgData = {
type: "user_message",
timeMillis: clientMessageId,
message: [
{
type: "text",
component: {
type: "text",
payload: {
text: message,
attachments,
createdOn: clientMessageId
}
},
clientMessageId
}
]
};
var messageToBot = {
clientMessageId,
message: {
body: payload || message,
renderMsg: payload != null ? message : null,
customData: {
botToken: this.getBotAccessToken(),
kmToken: this.getAccessToken(),
kmUId: this.getUserId()
}
},
resourceid: "/bot.message",
botInfo: this.getBotInfo(),
id: clientMessageId,
client: Platform3.OS
};
if (this.botConfig?.isWebHook) {
const apiService = new ApiService(this.botConfig.botUrl, this);
apiService.sendWebHookMessage(this.botConfig, false, message, (response) => {
this.onWebhookMessages(response.data);
}, payload, attachments);
} else {
this.send(messageToBot);
}
return msgData;
}
onWebhookMessages(messages) {
let index = 0;
const loop = () => {
if (index >= messages.length) return;
this.onMessage(messages[index]);
index++;
setTimeout(loop, index * 200);
};
loop();
}
sendEvent(eventName, isZenDeskEvent) {
var clientMessageId = (/* @__PURE__ */ new Date()).getTime();
Logger_default.info("Sending Event to bot", {
clientMessageId,
eventName,
isZenDeskEvent,
platform: Platform3.OS
});
var eventToBot = {
clientMessageId,
event: eventName,
message: {
body: isZenDeskEvent == true ? eventName : "",
customData: {
botToken: this.getBotAccessToken(),
kmToken: this.getAccessToken(),
kmUId: this.getUserId()
}
},
resourceid: isZenDeskEvent == true ? "/bot.clientEvent" : "/bot.message",
botInfo: this.getBotInfo(),
id: clientMessageId,
client: Platform3.OS
};
this.send(eventToBot);
}
};
// bot-sdk/rtm/KoreBotClient.tsx
var KoreBotClient = class _KoreBotClient extends BotClient {
static _instance;
constructor() {
super();
}
static getInstance() {
if (this._instance == null) {
this._instance = new _KoreBotClient();
}
return this._instance;
}
static disconnectClient() {
this._instance.disconnect();
this._instance = null;
}
setSessionActive(isActive) {
super.setSessionActive(isActive);
}
setAppState(_appState) {
super.setAppState(_appState);
}
setIsNetworkAvailable(isNetWorkAvailable) {
super.setIsNetworkAvailable(isNetWorkAvailable);
}
checkSocketAndReconnect() {
super.checkSocketAndReconnect();
}
};
// bot-sdk/branding/ActiveThemeAPI.tsx
var MAX_RETRIES = 5;
var ActiveThemeAPI = class {
isSocketACtive = false;
async fetchWithRetries(url, options, retries = 1, method = "GET")