UNPKG

@botonic/react

Version:

Build Chatbots using React

192 lines 7.75 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.WebviewApp = void 0; const tslib_1 = require("tslib"); const jsx_runtime_1 = require("react/jsx-runtime"); /* eslint-disable @typescript-eslint/no-empty-function */ // @ts-nocheck const core_1 = require("@botonic/core"); const axios_1 = tslib_1.__importDefault(require("axios")); const react_1 = tslib_1.__importDefault(require("react")); const client_1 = require("react-dom/client"); const react_router_dom_1 = require("react-router-dom"); const contexts_1 = require("./contexts"); var WebviewUrlParams; (function (WebviewUrlParams) { WebviewUrlParams["Context"] = "context"; WebviewUrlParams["BotId"] = "bot_id"; WebviewUrlParams["UserId"] = "user_id"; WebviewUrlParams["HubtypeApiUrl"] = "hubtype_api_url"; })(WebviewUrlParams || (WebviewUrlParams = {})); const DEFAULT_HUBTYPE_API_URL = 'https://api.hubtype.com'; class App extends react_1.default.Component { constructor(props) { super(props); this.hubtypeApiUrl = DEFAULT_HUBTYPE_API_URL; this.url = new URL(window.location.href); this.state = { session: null, params: {}, }; } async componentDidMount() { await this.initializeApp(); } async initializeApp() { try { const botId = this.url.searchParams.get(WebviewUrlParams.BotId); const chatId = this.url.searchParams.get(WebviewUrlParams.UserId); const hubtypeApiUrl = this.url.searchParams.get(WebviewUrlParams.HubtypeApiUrl); if (botId && chatId && hubtypeApiUrl) { const session = await this.getBotSessionContextFromExternalApi(hubtypeApiUrl, botId, chatId); this.hubtypeApiUrl = hubtypeApiUrl; this.setState({ session, params: this.getParamsFromUrl(), }); } else { const session = this.getBotSessionContextFromUrl(); this.hubtypeApiUrl = session._hubtype_api || DEFAULT_HUBTYPE_API_URL; this.setState({ session, params: this.getParamsFromUrl(), }); } } catch (error) { console.error('Failed to initialize app:', error); const session = this.getBotSessionContextFromUrl(); this.hubtypeApiUrl = session._hubtype_api || DEFAULT_HUBTYPE_API_URL; this.setState({ session, params: this.getParamsFromUrl(), }); } } async getBotSessionContextFromExternalApi(hubtypeApiUrl, botId, userId) { const url = `${hubtypeApiUrl}/external/v2/conversational_apps/${botId}/users/${userId}/context/`; const response = await axios_1.default.get(url); return response.data; } getBotSessionContextFromUrl() { const urlContext = this.url.searchParams.get(WebviewUrlParams.Context); try { return JSON.parse(urlContext || '{}'); } catch (error) { console.error('Failed to parse session context from URL:', error); return {}; } } getParamsFromUrl() { const keysToExclude = [ WebviewUrlParams.Context, WebviewUrlParams.BotId, WebviewUrlParams.UserId, WebviewUrlParams.HubtypeApiUrl, ]; return Array.from(this.url.searchParams.entries()) .filter(([key]) => !keysToExclude.includes(key)) .reduce((params, [key, value]) => { params[key] = value; return params; }, {}); } async closeWebviewForProvider(provider, session, _payload) { const { user } = session; switch (provider) { case core_1.PROVIDER.WHATSAPP: location.href = `https://wa.me/${user.unformatted_phone_number}`; break; case core_1.PROVIDER.TELEGRAM: location.href = `https://t.me/${user.imp_id}`; break; case core_1.PROVIDER.APPLE: location.href = `https://bcrw.apple.com/urn:biz:${user.imp_id}`; break; case core_1.PROVIDER.TWITTER: location.href = `https://twitter.com/messages/compose?recipient_id=${user.imp_id}`; break; case core_1.PROVIDER.INSTAGRAM: window.close(); break; case core_1.PROVIDER.FACEBOOK: try { window.MessengerExtensions.requestCloseBrowser( // biome-ignore lint/suspicious/noEmptyBlockStatements: success callback is empty () => { }, // success callback () => window.close() // error callback ); } catch (_error) { window.close(); } break; case core_1.PROVIDER.WEBCHAT: try { await parent.postMessage('botonicCloseWebview', '*'); } catch (error) { console.error('Failed to send close message to parent:', error); } break; default: console.warn(`Unknown provider: ${provider}`); } } async close(options) { if (!this.state.session) { console.error('No session available for closing webview'); return; } let payload = options?.payload || null; if (options?.path) { payload = `__PATH_PAYLOAD__${options.path}`; } if (payload) { if (options?.params) { payload = `${payload}?${(0, core_1.params2queryString)(options.params)}`; } try { const url = `${this.hubtypeApiUrl}/v1/bots/${this.state.session.bot.id}/send_postback/`; const data = { payload, chat_id: this.state.session.user.id, }; await axios_1.default.post(url, data); } catch (error) { console.error('Failed to send postback:', error); } } await this.closeWebviewForProvider(this.state.session.user.provider, this.state.session, payload); } render() { if (!this.state.session) { return null; } const webviewRequestContext = { params: this.state.params, session: this.state.session, getUserCountry: () => this.state.session.user.country, getUserLocale: () => this.state.session.user.locale, getSystemLocale: () => this.state.session.user.system_locale, closeWebview: this.close.bind(this), }; return ((0, jsx_runtime_1.jsx)(contexts_1.WebviewRequestContext.Provider, { value: webviewRequestContext, children: this.props.webviews.map((Webview, i) => ((0, jsx_runtime_1.jsx)(react_router_dom_1.Route, { path: `/${Webview.name}`, component: Webview }, `route-${i}-${Webview.name}`))) })); } } class WebviewApp { constructor({ webviews, locales }) { this.webviews = webviews; this.locales = locales; } render(dest) { const component = ((0, jsx_runtime_1.jsx)(react_router_dom_1.BrowserRouter, { children: (0, jsx_runtime_1.jsx)(App, { webviews: this.webviews, locales: this.locales }) })); const reactRoot = (0, client_1.createRoot)(dest); reactRoot.render(component); } } exports.WebviewApp = WebviewApp; //# sourceMappingURL=webview-app.js.map