@typexim/agent-js-sdk 1.0.24 → 1.0.25
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.
- package/dist/index.es.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/index.es.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"crypto-js";import t from"axios";import s from"@fingerprintjs/fingerprintjs";var i,n,r,o,a,c,h,d,g,E,u,l,_;function m(e){return{ok:!1,code:e.code||E.SDK_ERROR,status:e.status,msg:e.msg||"sdk error",msg_i18n:e.msg_i18n}}function S(e){return{ok:!0,data:e}}!function(e){e[e.KICK_OFF=4001]="KICK_OFF"}(i||(i={})),function(e){e[e.CREATE_FEED=0]="CREATE_FEED",e[e.UPDATE_FEED=1]="UPDATE_FEED",e[e.ADD_MESSAGE=2]="ADD_MESSAGE",e[e.UPDATE_MESSAGE=3]="UPDATE_MESSAGE",e[e.UPDATE_USER_DATA=4]="UPDATE_USER_DATA",e[e.USER_LOGIN=5]="USER_LOGIN",e[e.READ_MESSAGE=6]="READ_MESSAGE",e[e.PONG_MESSAGE=8]="PONG_MESSAGE",e[e.DELETE_MESSAGE=9]="DELETE_MESSAGE",e[e.UPDATE_GROUP=12]="UPDATE_GROUP",e[e.DELETE_GROUP=13]="DELETE_GROUP",e[e.UPDATE_LOGIN_USER=17]="UPDATE_LOGIN_USER",e[e.UPDATE_MESSAGE_REACTION=19]="UPDATE_MESSAGE_REACTION",e[e.ADD_GROUP_MEMBER=21]="ADD_GROUP_MEMBER",e[e.DEL_GROUP_MEMBER=22]="DEL_GROUP_MEMBER",e[e.ADD_CONTACTS=23]="ADD_CONTACTS",e[e.UPDATE_CONTACTS=24]="UPDATE_CONTACTS",e[e.DEL_CONTACTS=25]="DEL_CONTACTS",e[e.BLOCK_USER=26]="BLOCK_USER",e[e.DEVICE_CODE=27]="DEVICE_CODE",e[e.MSG_OPEN_CLOCK=28]="MSG_OPEN_CLOCK",e[e.DELETE_SECRET_CHAT=29]="DELETE_SECRET_CHAT",e[e.DELETE_FEED=30]="DELETE_FEED",e[e.FAVORITE_UPDATE=31]="FAVORITE_UPDATE",e[e.STICKERS_UPDATE=32]="STICKERS_UPDATE",e[e.CUSTOM_STICKERS_UPDATE=33]="CUSTOM_STICKERS_UPDATE",e[e.MANAGE_DEVICE_UPDATE=34]="MANAGE_DEVICE_UPDATE",e[e.MASS_MESSAGE_UPDATE=35]="MASS_MESSAGE_UPDATE",e[e.CHAT_WALLPAPER_DELETE=36]="CHAT_WALLPAPER_DELETE",e[e.CHAT_WALLPAPER_ADD=37]="CHAT_WALLPAPER_ADD",e[e.CONTACT_REQUEST=40]="CONTACT_REQUEST",e[e.USER_PREFERENCE_CHANGE=38]="USER_PREFERENCE_CHANGE",e[e.UPDATE_GROUP_PIN=41]="UPDATE_GROUP_PIN",e[e.RTC_CANCEL=46]="RTC_CANCEL",e[e.ADD_FEED_FOLDER=43]="ADD_FEED_FOLDER",e[e.UPDATE_FEED_FOLDER=44]="UPDATE_FEED_FOLDER",e[e.UPDATE_FOLDER_FEED_LIST=47]="UPDATE_FOLDER_FEED_LIST",e[e.DELETE_FEED_FOLDER=45]="DELETE_FEED_FOLDER",e[e.UPDATE_CHATTER=42]="UPDATE_CHATTER",e[e.PAPER_KEY=48]="PAPER_KEY",e[e.PAPER_KEY_LOG=49]="PAPER_KEY_LOG",e[e.USER_LOGIN_SCAN=50]="USER_LOGIN_SCAN",e[e.RTC_RINGING=51]="RTC_RINGING",e[e.ON_UPDATE_PRIVATE_SETTING=52]="ON_UPDATE_PRIVATE_SETTING",e[e.ON_DELETE_PRIVATE_SETTING=53]="ON_DELETE_PRIVATE_SETTING",e[e.ON_UPDATE_LOGIN_PRIVATE_SETTING=54]="ON_UPDATE_LOGIN_PRIVATE_SETTING",e[e.PUSH_LIVE_MESSAGE=56]="PUSH_LIVE_MESSAGE",e[e.BIG_PACKAGE_PUSH=126]="BIG_PACKAGE_PUSH",e[e.KICK_OUT_DEVICE=127]="KICK_OUT_DEVICE",e[e.CLEAR_HISTORY=128]="CLEAR_HISTORY",e[e.CLEAR_DATA=255]="CLEAR_DATA"}(n||(n={})),function(e){e[e.KICK_OUT=0]="KICK_OUT"}(r||(r={})),function(e){e.INIT="INIT",e.CONNECTING="CONNECTING",e.CONNECTED="CONNECTED",e.DISCONNECTED="DISCONNECTED",e.CLOSED="CLOSED"}(o||(o={})),function(e){e.OPEN="OPEN",e.ERROR="ERROR",e.CLOSE="CLOSE",e.MESSAGE="MESSAGE",e.STATUS_CHANGE="STATUS_CHANGE"}(a||(a={})),function(e){e[e.singleChat=1]="singleChat",e[e.groupChat=2]="groupChat"}(c||(c={})),function(e){e[e.normal=0]="normal",e[e.system=1]="system"}(h||(h={})),function(e){e[e.text=0]="text",e[e.image=1]="image",e[e.audio=3]="audio",e[e.video=4]="video",e[e.file=5]="file",e[e.mergeForward=6]="mergeForward",e[e.sticker=7]="sticker",e[e.richText=8]="richText",e[e.contact=9]="contact",e[e.communication=10]="communication",e[e.mixedImageText=11]="mixedImageText",e[e.custom=13]="custom",e[e.luckyGift=14]="luckyGift",e[e.fileGroup=15]="fileGroup",e[e.cardMsg=16]="cardMsg"}(d||(d={})),function(e){e[e.normal=0]="normal",e[e.recall=1]="recall"}(g||(g={})),function(e){e[e.NETWORK_ERROR=-1e4]="NETWORK_ERROR",e[e.SDK_ERROR=-10001]="SDK_ERROR",e[e.SERVER_ERROR=-10002]="SERVER_ERROR"}(E||(E={})),function(e){e.SDK_READY="SDK_READY",e.SDK_NOT_READY="SDK_NOT_READY",e.SDK_KICKOUT="SDK_KICKOUT",e.FEED_UPDATED="FEED_UPDATED",e.MESSAGE_RECEIVED="MESSAGE_RECEIVED",e.MESSAGE_UPDATED="MESSAGE_UPDATED",e.MESSAGE_RECEIPT_RECEIVED="MESSAGE_RECEIPT_RECEIVED",e.CONNECTION_STATUS_CHANGE="CONNECTION_STATUS_CHANGE",e.UNAUTHORIZED="UNAUTHORIZED",e.GROUP_MEMBER_UPDATED="GROUP_MEMBER_UPDATED"}(u||(u={})),function(e){e[e.up=0]="up",e[e.down=1]="down"}(l||(l={})),function(e){e[e.ADD_GROUP_MEMBER=21]="ADD_GROUP_MEMBER",e[e.DEL_GROUP_MEMBER=22]="DEL_GROUP_MEMBER"}(_||(_={}));const R="[TYPEX_AGENT_JS_SDK]";class T{level=0;setLogLevel(e){this.level=e}getLogLevel(){return this.level}shouldPrint(e){return e>=this.level}debug(...e){this.shouldPrint(0)&&console.debug(`${R}[DEBUG]`,...e)}info(...e){this.shouldPrint(0)&&console.info(`${R}[INFO]`,...e)}warn(...e){this.shouldPrint(1)&&console.warn(`${R}[WARN]`,...e)}error(...e){this.shouldPrint(2)&&console.error(`${R}[ERROR]`,...e)}}function p(e){return(new TextEncoder).encode(e).buffer}async function C(t,s){return window.crypto&&window.crypto.subtle?await async function(e,t){const s=p(t),i=p(e),n=await crypto.subtle.importKey("raw",s,{name:"HMAC",hash:{name:"SHA-256"}},!1,["sign"]),r=await crypto.subtle.sign("HMAC",n,i);return Array.from(new Uint8Array(r)).map(e=>e.toString(16).padStart(2,"0")).join("")}(t,s):function(t,s){const i=e.HmacSHA256(t,s);return e.enc.Hex.stringify(i)}(t,s)}const I=e=>{if(null==e)return"";if("object"!=typeof e||Array.isArray(e)){if(Array.isArray(e)){let t="";for(const s of e)t+=I(s);return t}return"string"==typeof e?e:String(e)}{const t=Object.keys(e).sort();let s="";for(const i of t)s+=I(e[i]);return s}};var A,D,O="1.0.24";class f{instance;developer;logger;store;constructor(e,s){this.logger=s.logger,this.store=s.store,this.developer=e.developer;const i=e.baseURL.replace(/\/$/,"");this.instance=t.create({baseURL:i,headers:{...e.defaultHeaders??{}},timeout:e.timeout??3e4,withCredentials:!0}),this.setupInterceptors()}setupInterceptors(){this.instance.interceptors.request.use(e=>(e.headers=e.headers||{},e.headers["Content-Type"]||(e.headers["Content-Type"]="application/json"),e.headers.Platform="web",e.headers.AppID=this.store.appId,e.withCredentials&&(e.headers["X-Sid"]=this.store.sessionId),e.ignoreWebsdkVersion||(e.headers["X-Websdk-Version"]=O),this.developer&&!e.ignoreDeveloper&&(e.headers["x-developer"]=this.developer),e)),this.instance.interceptors.response.use(e=>{const t=e.headers["x-sid"];return t&&(e.data.sessionId=t),e},e=>Promise.reject(e))}async get(e,t={},s={}){return this.request({url:e,method:"GET",params:t,...s})}async post(e,t,s={}){return this.request({url:e,method:"POST",data:t,...s})}async request(e){try{const{needSign:t,...s}=e;if(t&&"POST"===s.method?.toUpperCase()&&s.data){const t=this.store.currentUser;if(!t){const e="[HttpClient] HttpClient needs make sign but not found login user";return this.logger.error(e),m({code:E.SDK_ERROR,msg:e})}try{const i=await(async(e,t)=>{const s=I(e);return await C(s,t)})(s.data,t.secretKey);e.headers||(e.headers={}),e.headers.sign=i}catch(e){const t=`[HttpClient] HttpClient make sign error: ${e.message}`;return this.logger.error(t),m({code:E.SDK_ERROR,msg:t})}}const i=await this.instance.request({...s,headers:{...e.headers||{}}}),n=i.data;return 0!==n.code?(this.logger.error("[HttpClient]","Business server response error:",i),{ok:!1,code:n.code,msg:n.msg,msg_i18n:n.msg_i18n}):n.sessionId?{ok:!0,sessionId:n.sessionId,data:n.data}:{ok:!0,data:n.data}}catch(e){return this.handleError(e)}}handleError(e){return 200!==e.response?.status?{ok:!1,code:E.SERVER_ERROR,status:e.response?.status,msg:e.message||"server error"}:"ECONNABORTED"===e.code?{ok:!1,code:E.NETWORK_ERROR,msg:e.message||"request timeout"}:{ok:!1,code:E.NETWORK_ERROR,msg:e.message||"network error"}}}class N{listeners=new Map;logger;constructor(e){this.logger=e}on(e,t){this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t)}once(e,t){const s=i=>{t(i),this.off(e,s)};this.on(e,s)}off(e,t){this.listeners.has(e)&&(t?this.listeners.get(e).delete(t):this.listeners.delete(e))}emit(e,t){if(this.listeners.has(e))for(const s of this.listeners.get(e))try{s(t)}catch(t){this.logger.error(`[EventCore] handler error on "${String(e)}":`,t)}}clear(){this.listeners.clear()}}class U extends N{ws;options;status=o.INIT;constructor(e,t){super(t),this.options=e}connect(){if(this.status===o.CONNECTING||this.status===o.CONNECTED)return void this.logger.debug("[CONNECTION]","WebSocket is connecting or connected,current connect status is",`[${this.status}]`);this.logger.debug("[CONNECTION][connect]","WebSocket is connecting"),this.setStatus(o.CONNECTING);const e=new WebSocket(`${this.options.url}?token=${this.options.token}&platform=web`);this.ws=e,e.onopen=()=>{this.logger.debug("[CONNECTION][ws.onopen]","WebSocket is connected"),this.setStatus(o.CONNECTED),this.emit(a.OPEN)},e.onmessage=e=>{this.logger.debug("[CONNECTION][ws.onmessage]","WebSocket received a message",e.data),this.emit(a.MESSAGE,e.data)},e.onerror=e=>{this.logger.error("[CONNECTION][ws.onerror]","WebSocket connect error",e),this.emit(a.ERROR,e)},e.onclose=e=>{this.logger.debug("[CONNECTION][ws.onclose]","WebSocket connect be closed",e),this.setStatus(o.DISCONNECTED),this.emit(a.CLOSE,e)}}close(){this.ws?.close(),this.ws=void 0,this.setStatus(o.CLOSED)}send(e){if(this.status!==o.CONNECTED)throw new Error("WebSocket is not connected");this.ws.send(e)}getStatus(){return this.status}setStatus(e){this.status!==e&&(this.logger.debug("[CONNECTION][setStatus]","WebSocket status changed",this.status,"->",e),this.status=e,this.emit(a.STATUS_CHANGE,e))}}class P{connection;pingTimeout;pongTimeout;pingTimer;pongTimer;logger;constructor(e,t,s={}){this.connection=e,this.pingTimeout=s.pingTimeout??3e4,this.pongTimeout=s.pongTimeout??2e4,this.logger=t}ping(e){this.logger.debug("[Heartbeat]","Heartbeat ping"),this.stop(),this.pingTimer=window.setTimeout(()=>{try{this.connection.send(JSON.stringify({type:0})),this.logger.debug("[Heartbeat]","Heartbeat send PING"),this.pong(e)}catch{}},this.pingTimeout)}pong(e){clearTimeout(this.pongTimer),this.pongTimer=window.setTimeout(()=>{e?.(),this.logger.debug("[Heartbeat]","PING timeout, called PING/PONG callback")},this.pongTimeout)}stop(){this.logger.debug("[Heartbeat]","Heartbeat stop"),clearTimeout(this.pingTimer),clearTimeout(this.pongTimer),this.pingTimer=void 0,this.pongTimer=void 0}}class b{connection;baseInterval=1e3;maxAttempts=1/0;attempts=0;timer;enabled=!1;logger;constructor(e,t,s={}){this.logger=t,this.connection=e,s.baseInterval&&(this.baseInterval=s.baseInterval),s.maxAttempts&&(this.maxAttempts=s.maxAttempts),this.bindEvents()}bindEvents(){this.connection.on(a.CLOSE,()=>{this.enabled&&this.scheduleReconnect()}),this.connection.on(a.OPEN,()=>{this.reset()})}start(){this.logger.debug("[Reconnector]","Reconnector start"),this.enabled=!0}stop(){this.logger.debug("[Reconnector]","Reconnector stop"),this.enabled=!1,this.clearTimer()}scheduleReconnect(){if(this.logger.debug("[Reconnector]",`Reconnector scheduleReconnect, attempts: ${this.attempts}, maxAttempts: ${this.maxAttempts}`),this.attempts>=this.maxAttempts)return;this.attempts++;const e=this.baseInterval*Math.min(this.attempts,10);this.clearTimer(),this.timer=window.setTimeout(()=>{this.connection.connect()},e)}reset(){this.logger.debug("[Reconnector]","Reconnector reset"),this.attempts=0,this.clearTimer()}clearTimer(){this.timer&&(clearTimeout(this.timer),this.timer=void 0)}}!function(e){e.OPEN="OPEN",e.ERROR="ERROR",e.CLOSE="CLOSE",e.MESSAGE="MESSAGE",e.STATUS_CHANGE="STATUS_CHANGE",e.KICK_OFF="KICK_OFF"}(A||(A={}));class M extends N{connection;reconnector;heartbeat;pongTimeoutCount=0;offlineReconnectTimer;constructor(e,t){super(t),this.connection=new U({url:e.wsUrl,token:e.token},t),this.reconnector=new b(this.connection,t),this.heartbeat=new P(this.connection,t),this.bindEvents()}connect(){this.reconnector.start(),this.connection.connect()}disconnect(){this.reconnector.stop(),this.heartbeat.stop(),this.connection.close()}startPing(){this.heartbeat.ping(()=>{if(this.logger.warn("[IMClient][Heartbeat]","PONG timeout, current pong timeout count: ",this.pongTimeoutCount),this.pongTimeoutCount++,this.pongTimeoutCount>=2){this.disconnect();const e=setTimeout(()=>{this.connect(),clearTimeout(e)},1e4);return}this.startPing()})}bindEvents(){this.connection.on(a.OPEN,()=>{this.emit(A.OPEN),this.offlineReconnectTimer&&(clearTimeout(this.offlineReconnectTimer),this.offlineReconnectTimer=void 0),this.startPing()}),this.connection.on(a.CLOSE,e=>{if(e.code===i.KICK_OFF)return this.logger.warn("[IMClient][CLOSE][KICK_OFF]","You has been kicked off"),this.emit(A.KICK_OFF),void this.disconnect();this.emit(A.CLOSE)}),this.connection.on(a.MESSAGE,e=>{this.handleRawMessage(e)}),this.connection.on(a.STATUS_CHANGE,e=>{this.emit(A.STATUS_CHANGE,e)}),this.connection.on(a.ERROR,e=>{this.emit(A.ERROR,e)}),"undefined"!=typeof window&&(window.addEventListener("offline",()=>{if(this.offlineReconnectTimer)return;this.connection.close();const e=()=>{if(this.connection.getStatus()===o.CONNECTED)return this.offlineReconnectTimer&&clearTimeout(this.offlineReconnectTimer),void(this.offlineReconnectTimer=void 0);this.connection.connect(),this.offlineReconnectTimer=window.setTimeout(e,1e3)};e()}),window.addEventListener("online",()=>{this.offlineReconnectTimer&&(clearTimeout(this.offlineReconnectTimer),this.offlineReconnectTimer=void 0),this.connection.connect()}))}handleRawMessage(e){try{const t=JSON.parse(e);if(t.type===n.PONG_MESSAGE?this.startPing():this.sendAck(t.id),t.type===n.BIG_PACKAGE_PUSH)for(const e of t.content.big_push)this.emit(A.MESSAGE,e);else this.emit(A.MESSAGE,t)}catch(e){this.logger.error("[IMClient][handleRawMessage]","Message raw data json.parse error",e),this.emit(A.ERROR,e)}}sendAck(e){this.connection.send(JSON.stringify({type:1,ids:[e]}))}}!function(e){e.APP_ID="appId",e.CURRENT_USER="currentUser",e.CURRENT_FEED="currentFeed",e.SDK_READY="sdkReady",e.IS_CONNECTED="isConnected",e.CONNECTION_STATUS="connectionStatus",e.DEVICE_ID="typeximDeviceId",e.BROWSER_FINGERPRINT="typeximBrowserFingerprint",e.TAB_ID="typeximTabId"}(D||(D={}));class w extends N{state={};constructor(e){super(e)}set(e,t){this.logger.debug("[Store] set:",e,t),this.state[e]=t,this.emit("change",{key:e,value:t})}get(e){return this.logger.debug("[Store] get:",e,this.state[e]),this.state[e]}remove(e){this.logger.debug("[Store] remove:",e,this.state[e]),delete this.state[e],this.emit("change",{key:e,value:void 0})}clear(){this.logger.debug("[Store] clear",this.state),this.state={appId:this.state.appId,typeximBrowserFingerprint:this.state.typeximBrowserFingerprint},this.emit("clear",void 0)}setWithSession(e,t){this.logger.debug("[Store] setWithSession:",e,t),this.set(e,t),sessionStorage.setItem(e,JSON.stringify(t))}getWithSession(e){if(this.logger.debug("[Store] getWithSession:",e,this.state[e]),this.state[e])return this.state[e];const t=sessionStorage.getItem(e);return t?JSON.parse(t):void 0}removeWithSession(e){this.logger.debug("[Store] removeWithSession:",e,this.state[e]),sessionStorage.removeItem(e),this.remove(e)}onChange(e){this.on("change",e)}offChange(e){this.off("change",e)}onClear(e){this.on("clear",e)}get appId(){return this.logger.debug("[Store] get appId",this.state.appId),this.state.appId}get ready(){return this.logger.debug("[Store] get ready",this.state.sdkReady),!!this.state.sdkReady}get deviceId(){const e=this.getWithSession(D.DEVICE_ID);return this.logger.debug("[Store] get deviceId",e),e}get currentUser(){return this.logger.debug("[Store] get currentUser",this.state.currentUser),this.state.currentUser}get currentChatId(){return this.logger.debug("[Store] get currentChatId",this.state.currentFeed?.chat_id),this.state.currentFeed?.chat_id}get currentFeed(){return this.logger.debug("[Store] get currentFeed",this.state.currentFeed),this.state.currentFeed}get sessionId(){return this.logger.debug("[Store] get sessionId",this.state.currentUser?.sessionId),this.state.currentUser?.sessionId}get browserFingerprint(){const e=this.getWithSession(D.BROWSER_FINGERPRINT);return this.logger.debug("[Store] get browserFingerprint",e),e}get tabId(){const e=this.getWithSession(D.TAB_ID);return this.logger.debug("[Store] get tabId",e),e}get connectionStatus(){return this.logger.debug("[Store] get connectionStatus",this.state.connectionStatus||o.INIT),this.state.connectionStatus||o.INIT}}class y{version;constructor(){this.version=0}increment(){this.version++}get currentVersion(){return this.version}check(e){return e===this.version}}const G="@typexim/agent-js-sdk_broadcast_channel";class v{config;logger;http;imClient=null;store;events;version;loadFeedAbortController=null;promises=new Map;constructor(e,t){this.logger=new T,this.store=new w(this.logger),this.events=new N(this.logger),this.store.set(D.APP_ID,e),this.config=t,this.version=new y,this.http=new f({baseURL:t.httpHost,developer:t.developer},{logger:this.logger,store:this.store}),this.generateTabId(),this.generateBrowserFingerprint(),this.listenBroadcastChannel()}setLogLevel(e){this.logger.setLogLevel(e)}async login(e){try{const t={...e||{}};if(!t.authToken)return m({code:E.SDK_ERROR,msg:"Invalid param: authToken must be provided"});if(!t.userId){const e=await this.generateBrowserFingerprint();t.userId=e}const s=await this.requestDeviceId(),i=await this.innerLogin(s,t);if(!i.ok||!i.data)return this.logger.error("[InternalChatSdk] Login failed",i),m({code:i.code,msg:i.msg,msg_i18n:i.msg_i18n,status:i.status});const n={...i.data||{},sessionId:i.sessionId};if(!i.sessionId)throw this.logger.error("[InternalChatSdk] Login failed, not found sessionid"),new Error("Login failed, not found sessionid");return n.secretKey=i.data.key,await Promise.all([this.syncLoginState(n),this.connectWebSocket(i.sessionId)]),this.notifyOtherTabsLogin(),S({id:n.id,userId:t.userId,name:n.name,avatar:n.avatar,email:n.email})}catch(e){return this.handleException(e)}}async innerLogin(e,t){const s=await this.http.post("/user/token/login",{token:t.authToken,userId:t.userId,deviceId:e,avatar:t.avatar,name:t.name,email:t.email});return this.triggerUnauthorized(s),s}generateTabId(){const e=this.store.getWithSession(D.TAB_ID);if(e)return e;const t=`${this.store.appId}_${Date.now()}_${Math.random().toString(36).substring(2,15)}`;return this.store.setWithSession(D.TAB_ID,t),t}async generateBrowserFingerprint(){try{const e=this.store.getWithSession(D.BROWSER_FINGERPRINT);if(e)return this.logger.debug("[ChatSdk] generateBrowserFingerprint success from local session",e),e;const t=await s.load(),i=await t.get();return this.logger.debug("[ChatSdk] generateBrowserFingerprint success",i.visitorId),this.store.setWithSession(D.BROWSER_FINGERPRINT,i.visitorId),i.visitorId}catch(e){this.logger.info("[ChatSdk] FingerprintJS generateBrowserFingerprint Error",e);const t=`${Date.now()}_${Math.random().toString(36).substring(2,15)}`;return this.logger.debug("[ChatSdk] random generateBrowserFingerprint success",t),this.store.setWithSession(D.BROWSER_FINGERPRINT,t),t}}async loadFeed(){const e=this.version.currentVersion;this.loadFeedAbortController&&this.loadFeedAbortController.abort(),this.loadFeedAbortController=new AbortController;const t=await this.http.get("/feed",{limit:10},{signal:this.loadFeedAbortController.signal}).catch(e=>{this.logger.error("[ChatSdk] loadFeed Error",e)});this.loadFeedAbortController=null;const s=this.version.check(e);if(!t||!s)return;const i=t.data?.feed_list?.find(e=>e.chat_type===c.groupChat);this.triggerUnauthorized(t),t.ok&&(this.logger.debug("[ChatSdk][FEED_UPDATED] loadFeed success",i),this.store.set(D.CURRENT_FEED,i),this.events.emit(u.FEED_UPDATED,i))}async syncLoginState(e){this.store.set(D.CURRENT_USER,e),this.store.set(D.SDK_READY,!0),await this.loadFeed(),this.events.emit(u.SDK_READY)}syncLogoutState(){this.unlistenBroadcastChannel(),this.store.set(D.CURRENT_USER,void 0),this.store.set(D.SDK_READY,!1),this.store.set(D.CURRENT_FEED,void 0),this.events.emit(u.SDK_NOT_READY)}async requestDeviceId(){const e=this.store.getWithSession(D.DEVICE_ID);if(e)return this.logger.debug("[ChatSdk] requestDeviceId success from local session",e),e;const t=await this.http.post("/device_api/device_id",{platform:"web",hash_str:this.store.browserFingerprint||""},{withCredentials:!1,ignoreWebsdkVersion:!0}).catch(e=>{this.logger.error("[ChatSdk] requestDeviceId Error",e)});if(!t?.ok||!t?.data)throw this.logger.error("[ChatSdk] requestDeviceId Error",t),new Error("requestDeviceId failed");return this.logger.debug("[ChatSdk] requestDeviceId success",t.data),this.store.setWithSession(D.DEVICE_ID,t.data),t.data}async logout(){try{if(!this.store.currentUser)return S(null);const e=await this.http.get("/user/logout");return this.triggerUnauthorized(e),e.ok?(this.syncLogoutState(),this.disconnectWebSocket(),S(null)):m({code:e.code,msg:e.msg,msg_i18n:e.msg_i18n,status:e.status})}catch(e){return this.handleException(e)}}async addGroupMember(e,t){try{if(this.assertReady(),!e)return m({code:E.SDK_ERROR,msg:"not found chat id"});if(!t?.length)return S(null);const s=this.store.currentFeed;if(!s)return m({code:E.SDK_ERROR,msg:"not found current feed"});const i=await this.getChatMembers(s.chat_id,s.chat_member);if(!i.ok)return m({code:i.code,msg:i.msg,msg_i18n:i.msg_i18n,status:i.status});const n=(i.data||[]).map(e=>e.user_id),r=t.filter(e=>!n.includes(e)),o=await this.addMember(r,s.chat_id);return o.ok?S(o.data):m({code:o.code,msg:o.msg,msg_i18n:o.msg_i18n,status:o.status})}catch(e){return this.handleException(e)}}async initialChat(e){try{this.assertReady();const t=this.store.currentFeed;if(!t){const t=await this.createFeed(e?.receiverIds||[],e?.name);return this.triggerUnauthorized(t),t.ok&&t.data?(this.store.set(D.CURRENT_FEED,t.data),S(t.data.chat_id)):m({code:t.code,msg:t.msg,msg_i18n:t.msg_i18n,status:t.status})}if(!e?.receiverIds?.length)return S(t.chat_id);const s=await this.addGroupMember(t.chat_id,e.receiverIds);return s.ok?S(t.chat_id):s}catch(e){return this.handleException(e)}}async getCurrentFeed(){try{return this.assertReady(),{ok:!0,data:this.store.currentFeed}}catch(e){return this.handleException(e)}}async getMessageList(e){try{this.assertReady();const t=this.store.currentFeed;if(!t)return m({code:E.SDK_ERROR,msg:"No feed found"});const{chat_id:s,first_position:i,last_message_position:n}=t,{positions:r,nextPosition:o,hasMore:a}=(e=>{const t=[];if(e.direction===l.up){let s=e.startPosition??e.maxPosition;for(;t.length<e.limit&&s>=e.minPosition;)t.push(s),s--;const i=s>=e.minPosition;let n;return i&&(n=s),{positions:t,nextPosition:n,hasMore:i}}{let s=e.startPosition??e.minPosition;for(;t.length<e.limit&&s<=e.maxPosition;)t.push(s),s++;const i=s<=e.maxPosition;let n;return i&&(n=s),{positions:t,nextPosition:n,hasMore:i}}})({maxPosition:n,minPosition:i,startPosition:e.messagePosition,limit:e.limit,direction:e.direction??l.up});if(r.length>0){const e=await this.http.post("/message/get_by_position",{chat_position:{[s]:r}});if(this.triggerUnauthorized(e),e.ok&&e.data?.[s]){return S({hasMore:a,list:e.data[s].reverse(),nextMessagePosition:o})}return m({code:e.code,msg:e.msg,msg_i18n:e.msg_i18n,status:e.status})}return S({hasMore:!1,list:[]})}catch(e){return this.handleException(e)}}async sendMessage(e){try{this.assertReady();const t=e.messageType;switch(t){case d.text:return this.sendTextMessage(e);case d.image:return this.sendImageMessage(e);case d.video:return this.sendVideoMessage(e);case d.file:return this.sendFileMessage(e);default:return this.logger.warn("Unsupported message type: ",t),m({code:E.SDK_ERROR,msg:`Unsupported message type: ${t}`})}}catch(e){return this.handleException(e)}}async sendTextMessage(e){const t=await this.http.post("/message/send_text",{chat_id:e.chatId,client_msg_id:e.clientMsgId,text:e.text.trim()},{needSign:!0});return this.triggerUnauthorized(t),t}async sendImageMessage(e){const t=await this.http.post("/message/send_image",{chat_id:e.chatId,client_msg_id:e.clientMsgId,object_url:e.objectUrl,width:e.width,height:e.height},{needSign:!0});return this.triggerUnauthorized(t),t}async sendVideoMessage(e){const t=await this.http.post("/message/send_video",{chat_id:e.chatId,client_msg_id:e.clientMsgId,video_url:e.objectUrl,duration_second:e.duration,image_url:e.coverUrl,width:e.width,height:e.height},{needSign:!0});return this.triggerUnauthorized(t),t}async sendFileMessage(e){const t=await this.http.post("/message/send_file",{chat_id:e.chatId,client_msg_id:e.clientMsgId,object_url:e.objectUrl,file_name:e.fileName,file_size:e.fileSize},{needSign:!0});return this.triggerUnauthorized(t),t}async uploadFile(e){const{chatId:t,fileContent:s,fileFormat:i,fileName:n,fileType:r,onUploadProgress:o}=e;if(s.size>209715200)return m({code:E.SDK_ERROR,msg:"File size exceeds 200MB, upload failed"});const a=new FormData;a.append("file_content",s),a.append("file_type",r),a.append("file_name",n),a.append("file_format",i),a.append("chat_id",t);const c=await this.http.post("/chat/upload",a,{needSign:!1,ignoreDeveloper:!0,onUploadProgress:o,headers:{"Content-Type":"multipart/form-data"}});return this.triggerUnauthorized(c),c}async sendMessageReadReceipt(e){try{if(this.assertReady(),!e.messageIds?.length)return S(null);const t=await this.http.post("/message/read",{chat_id:e.chatId,message_ids:e.messageIds},{needSign:!0});return this.triggerUnauthorized(t),t}catch(e){return this.handleException(e)}}async markAllMessagesAsRead(e){const t=this.store.currentFeed?.unread_message_ids||[];return this.sendMessageReadReceipt({chatId:e,messageIds:t})}async recallMessage(e){try{if(this.assertReady(),!e.messageIds.length)return S(null);const t=await this.http.post("/message/remove",{chat_id:e.chatId,message_ids:e.messageIds,two_way:1},{needSign:!0});return this.triggerUnauthorized(t),t}catch(e){return this.handleException(e)}}triggerUnauthorized(e){e.ok||401!==e.status||this.events.emit(u.UNAUTHORIZED)}async createFeed(e,t){const s=this.store.currentUser?.id;if(!s)return m({code:E.SDK_ERROR,msg:"User not logged in"});if(this.promises.has(s))return this.promises.get(s);const i=this.http.post("/chat/group",{receiver_ids:e,group_type:0,name:t||`User ${this.store.currentUser?.name||this.store.currentUser?.id}`},{needSign:!0}).catch(e=>{throw e}).finally(()=>{this.promises.delete(s)});return this.promises.set(s,i),i}async getChatMembers(e,t){const s=await this.http.post("/chat/chatter_info",JSON.stringify({chatters:{[e]:t}}));return this.triggerUnauthorized(s),s}async addMember(e,t){if(!t)return m({code:E.SDK_ERROR,msg:"not found chat id"});if(!e.length)return S(null);const s=await this.http.post("/chat/group/add_member",{user_ids:e,chat_id:t},{needSign:!0});return this.triggerUnauthorized(s),s}handlePushMessage(e){switch(this.logger.debug("handlePushMessage",e),e.type){case n.CREATE_FEED:case n.UPDATE_FEED:this.handleFeedUpdate(e);break;case n.ADD_GROUP_MEMBER:case n.DEL_GROUP_MEMBER:this.handleGroupMemberUpdate(e);break;case n.ADD_MESSAGE:this.handleAddMessage(e);break;case n.UPDATE_MESSAGE:this.handleUpdateMessage(e);break;case n.READ_MESSAGE:this.handleReadMessage(e);break;case n.KICK_OUT_DEVICE:this.handleKickOut()}}handleGroupMemberUpdate(e){e.content.chat_id===this.store.currentChatId&&this.events.emit(u.GROUP_MEMBER_UPDATED,{type:e.type,chatId:e.content.chat_id,members:(e?.content?.chat_member||[]).map(e=>({avatar:e.avatar,chatId:e.chat_id,name:e.name,userId:e.user_id}))})}handleFeedUpdate(e){this.store.set(D.CURRENT_FEED,e.content),this.events.emit(u.FEED_UPDATED,e.content)}async handleAddMessage(e){e.content.chat_id===this.store.currentChatId&&(await this.loadFeed(),this.events.emit(u.MESSAGE_RECEIVED,e.content))}async handleUpdateMessage(e){e.content.chat_id===this.store.currentChatId&&(await this.loadFeed(),this.events.emit(u.MESSAGE_UPDATED,e.content))}async handleReadMessage(e){e.content.chat_id===this.store.currentChatId&&(await this.loadFeed(),this.events.emit(u.MESSAGE_RECEIPT_RECEIVED,{chatId:e.content.chat_id,messageIds:e.content.message_ids,readerUserIds:e.content.reader_ids}))}handleKickOut(){this.syncLogoutState(),this.disconnectWebSocket(),this.events.emit(u.SDK_KICKOUT)}on(e,t){return this.events.on(e,t)}once(e,t){return this.events.once(e,t)}off(e,t){return this.events.off(e,t)}get currentUserId(){return this.logger.debug("[InternalChatSdk] get currentUserId==>",this.store.currentUser),this.store.currentUser?.id}get currentChatId(){return this.logger.debug("[InternalChatSdk] get currentChatId==>",this.store.currentChatId),this.store.currentChatId}get isReady(){return this.logger.debug("[InternalChatSdk] get isReady==>",this.store.ready),this.store.ready}listenBroadcastChannel(){new BroadcastChannel(G).onmessage=e=>{const t=this.store.appId,s=this.store.tabId;e.data.type===r.KICK_OUT&&e.data.appId===t&&e.data.tabId!==s&&(this.logger.debug("[BroadcastChannel] message: kick out",{appId:t,sourceTabId:e.data.tabId,currentTabId:s}),this.handleKickOut())}}unlistenBroadcastChannel(){new BroadcastChannel(G).close()}notifyOtherTabsLogin(){new BroadcastChannel(G).postMessage({type:r.KICK_OUT,appId:this.store.appId,tabId:this.store.tabId})}async connectWebSocket(e){if(!e)throw Error("connect websocket error, not found login user token");this.imClient=new M({token:e,wsUrl:`${this.config.websocketHost}/ws`},this.logger),this.imClient.on(A.STATUS_CHANGE,e=>{this.store.set(D.CONNECTION_STATUS,e),this.events.emit(u.CONNECTION_STATUS_CHANGE,e)}),this.imClient.on(A.OPEN,()=>{this.store.set(D.IS_CONNECTED,!0)}),this.imClient.on(A.KICK_OFF,()=>{this.store.set(D.IS_CONNECTED,!1)}),this.imClient.on(A.CLOSE,()=>{this.store.set(D.IS_CONNECTED,!1)}),this.imClient.on(A.MESSAGE,e=>{this.handlePushMessage(e)}),this.imClient.connect()}disconnectWebSocket(){this.imClient&&(this.imClient.disconnect(),this.imClient=null)}assertReady(){if(!this.store.ready)throw{code:E.SDK_ERROR,msg:"sdk not ready"}}handleException(e){return this.logger.error("[ChatSDK Error]",e),{ok:!1,code:e.code||E.SDK_ERROR,msg:e.msg||e.message||"sdk error"}}}const F=new Map;function L(e){return{setLogLevel(t){e.setLogLevel(t)},login:t=>e.login(t),logout:()=>e.logout(),initialChat:t=>e.initialChat(t),addGroupMember:(t,s)=>e.addGroupMember(t,s),getCurrentFeed:()=>e.getCurrentFeed(),getMessageList:t=>e.getMessageList(t),uploadFile:t=>e.uploadFile(t),sendMessage:t=>e.sendMessage(t),sendMessageReadReceipt:t=>e.sendMessageReadReceipt(t),markAllMessagesAsRead:t=>e.markAllMessagesAsRead(t),recallMessage:t=>e.recallMessage(t),get currentUserId(){return e.currentUserId},get currentChatId(){return e.currentChatId},get isReady(){return e.isReady},on:(t,s)=>e.on(t,s),once:(t,s)=>e.once(t,s),off:(t,s)=>e.off(t,s)}}var k={create:function(e,t){if(F.has(e))return L(F.get(e));const s=new v(e,t);return F.set(e,s),L(s)}};export{E as ChatSdkErrorCode,u as ChatSdkEvent,c as ChatType,o as ConnectionStatus,_ as GroupMemberUpdateType,h as MessageKind,g as MessageOperation,d as MessageType,l as RequestDirection,k as default};
|
|
1
|
+
import e from"crypto-js";import t from"axios";import s from"@fingerprintjs/fingerprintjs";var i,n,r,o,a,c,h,d,g,E,u,l,_;function S(e){return{ok:!1,code:e.code||E.SDK_ERROR,status:e.status,msg:e.msg||"sdk error",msg_i18n:e.msg_i18n}}function m(e){return{ok:!0,data:e}}!function(e){e[e.KICK_OFF=4001]="KICK_OFF"}(i||(i={})),function(e){e[e.CREATE_FEED=0]="CREATE_FEED",e[e.UPDATE_FEED=1]="UPDATE_FEED",e[e.ADD_MESSAGE=2]="ADD_MESSAGE",e[e.UPDATE_MESSAGE=3]="UPDATE_MESSAGE",e[e.UPDATE_USER_DATA=4]="UPDATE_USER_DATA",e[e.USER_LOGIN=5]="USER_LOGIN",e[e.READ_MESSAGE=6]="READ_MESSAGE",e[e.PONG_MESSAGE=8]="PONG_MESSAGE",e[e.DELETE_MESSAGE=9]="DELETE_MESSAGE",e[e.UPDATE_GROUP=12]="UPDATE_GROUP",e[e.DELETE_GROUP=13]="DELETE_GROUP",e[e.UPDATE_LOGIN_USER=17]="UPDATE_LOGIN_USER",e[e.UPDATE_MESSAGE_REACTION=19]="UPDATE_MESSAGE_REACTION",e[e.ADD_GROUP_MEMBER=21]="ADD_GROUP_MEMBER",e[e.DEL_GROUP_MEMBER=22]="DEL_GROUP_MEMBER",e[e.ADD_CONTACTS=23]="ADD_CONTACTS",e[e.UPDATE_CONTACTS=24]="UPDATE_CONTACTS",e[e.DEL_CONTACTS=25]="DEL_CONTACTS",e[e.BLOCK_USER=26]="BLOCK_USER",e[e.DEVICE_CODE=27]="DEVICE_CODE",e[e.MSG_OPEN_CLOCK=28]="MSG_OPEN_CLOCK",e[e.DELETE_SECRET_CHAT=29]="DELETE_SECRET_CHAT",e[e.DELETE_FEED=30]="DELETE_FEED",e[e.FAVORITE_UPDATE=31]="FAVORITE_UPDATE",e[e.STICKERS_UPDATE=32]="STICKERS_UPDATE",e[e.CUSTOM_STICKERS_UPDATE=33]="CUSTOM_STICKERS_UPDATE",e[e.MANAGE_DEVICE_UPDATE=34]="MANAGE_DEVICE_UPDATE",e[e.MASS_MESSAGE_UPDATE=35]="MASS_MESSAGE_UPDATE",e[e.CHAT_WALLPAPER_DELETE=36]="CHAT_WALLPAPER_DELETE",e[e.CHAT_WALLPAPER_ADD=37]="CHAT_WALLPAPER_ADD",e[e.CONTACT_REQUEST=40]="CONTACT_REQUEST",e[e.USER_PREFERENCE_CHANGE=38]="USER_PREFERENCE_CHANGE",e[e.UPDATE_GROUP_PIN=41]="UPDATE_GROUP_PIN",e[e.RTC_CANCEL=46]="RTC_CANCEL",e[e.ADD_FEED_FOLDER=43]="ADD_FEED_FOLDER",e[e.UPDATE_FEED_FOLDER=44]="UPDATE_FEED_FOLDER",e[e.UPDATE_FOLDER_FEED_LIST=47]="UPDATE_FOLDER_FEED_LIST",e[e.DELETE_FEED_FOLDER=45]="DELETE_FEED_FOLDER",e[e.UPDATE_CHATTER=42]="UPDATE_CHATTER",e[e.PAPER_KEY=48]="PAPER_KEY",e[e.PAPER_KEY_LOG=49]="PAPER_KEY_LOG",e[e.USER_LOGIN_SCAN=50]="USER_LOGIN_SCAN",e[e.RTC_RINGING=51]="RTC_RINGING",e[e.ON_UPDATE_PRIVATE_SETTING=52]="ON_UPDATE_PRIVATE_SETTING",e[e.ON_DELETE_PRIVATE_SETTING=53]="ON_DELETE_PRIVATE_SETTING",e[e.ON_UPDATE_LOGIN_PRIVATE_SETTING=54]="ON_UPDATE_LOGIN_PRIVATE_SETTING",e[e.PUSH_LIVE_MESSAGE=56]="PUSH_LIVE_MESSAGE",e[e.BIG_PACKAGE_PUSH=126]="BIG_PACKAGE_PUSH",e[e.KICK_OUT_DEVICE=127]="KICK_OUT_DEVICE",e[e.CLEAR_HISTORY=128]="CLEAR_HISTORY",e[e.CLEAR_DATA=255]="CLEAR_DATA"}(n||(n={})),function(e){e[e.KICK_OUT=0]="KICK_OUT"}(r||(r={})),function(e){e.INIT="INIT",e.CONNECTING="CONNECTING",e.CONNECTED="CONNECTED",e.DISCONNECTED="DISCONNECTED",e.CLOSED="CLOSED"}(o||(o={})),function(e){e.OPEN="OPEN",e.ERROR="ERROR",e.CLOSE="CLOSE",e.MESSAGE="MESSAGE",e.STATUS_CHANGE="STATUS_CHANGE"}(a||(a={})),function(e){e[e.singleChat=1]="singleChat",e[e.groupChat=2]="groupChat"}(c||(c={})),function(e){e[e.normal=0]="normal",e[e.system=1]="system"}(h||(h={})),function(e){e[e.text=0]="text",e[e.image=1]="image",e[e.audio=3]="audio",e[e.video=4]="video",e[e.file=5]="file",e[e.mergeForward=6]="mergeForward",e[e.sticker=7]="sticker",e[e.richText=8]="richText",e[e.contact=9]="contact",e[e.communication=10]="communication",e[e.mixedImageText=11]="mixedImageText",e[e.custom=13]="custom",e[e.luckyGift=14]="luckyGift",e[e.fileGroup=15]="fileGroup",e[e.cardMsg=16]="cardMsg"}(d||(d={})),function(e){e[e.normal=0]="normal",e[e.recall=1]="recall"}(g||(g={})),function(e){e[e.NETWORK_ERROR=-1e4]="NETWORK_ERROR",e[e.SDK_ERROR=-10001]="SDK_ERROR",e[e.SERVER_ERROR=-10002]="SERVER_ERROR"}(E||(E={})),function(e){e.SDK_READY="SDK_READY",e.SDK_NOT_READY="SDK_NOT_READY",e.SDK_KICKOUT="SDK_KICKOUT",e.FEED_UPDATED="FEED_UPDATED",e.MESSAGE_RECEIVED="MESSAGE_RECEIVED",e.MESSAGE_UPDATED="MESSAGE_UPDATED",e.MESSAGE_RECEIPT_RECEIVED="MESSAGE_RECEIPT_RECEIVED",e.CONNECTION_STATUS_CHANGE="CONNECTION_STATUS_CHANGE",e.UNAUTHORIZED="UNAUTHORIZED",e.GROUP_MEMBER_UPDATED="GROUP_MEMBER_UPDATED"}(u||(u={})),function(e){e[e.up=0]="up",e[e.down=1]="down"}(l||(l={})),function(e){e[e.ADD_GROUP_MEMBER=21]="ADD_GROUP_MEMBER",e[e.DEL_GROUP_MEMBER=22]="DEL_GROUP_MEMBER"}(_||(_={}));const R="[TYPEX_AGENT_JS_SDK]";class p{level=0;setLogLevel(e){this.level=e}getLogLevel(){return this.level}shouldPrint(e){return e>=this.level}debug(...e){this.shouldPrint(0)&&console.debug(`${R}[DEBUG]`,...e)}info(...e){this.shouldPrint(0)&&console.info(`${R}[INFO]`,...e)}warn(...e){this.shouldPrint(1)&&console.warn(`${R}[WARN]`,...e)}error(...e){this.shouldPrint(2)&&console.error(`${R}[ERROR]`,...e)}}function T(e){return(new TextEncoder).encode(e).buffer}async function C(t,s){return window.crypto&&window.crypto.subtle?await async function(e,t){const s=T(t),i=T(e),n=await crypto.subtle.importKey("raw",s,{name:"HMAC",hash:{name:"SHA-256"}},!1,["sign"]),r=await crypto.subtle.sign("HMAC",n,i);return Array.from(new Uint8Array(r)).map(e=>e.toString(16).padStart(2,"0")).join("")}(t,s):function(t,s){const i=e.HmacSHA256(t,s);return e.enc.Hex.stringify(i)}(t,s)}const I=e=>{if(null==e)return"";if("object"!=typeof e||Array.isArray(e)){if(Array.isArray(e)){let t="";for(const s of e)t+=I(s);return t}return"string"==typeof e?e:String(e)}{const t=Object.keys(e).sort();let s="";for(const i of t)s+=I(e[i]);return s}},D="api-coco.typex.im",A=e=>e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),O=e=>new RegExp(`https?:\\\\?/\\\\?/${A(e)}(?:\\\\.|[^"\\\\\\s])*`,"g"),f=(e,t,s)=>{if(!e||"string"!=typeof e)return e;const i=O(t);return e.replace(i,e=>{const t=(e=>{try{return JSON.parse(`"${e}"`)}catch{return e}})(e),i=s(t);return"string"!=typeof i||i===t?e:(n=i,JSON.stringify(n).slice(1,-1));var n})},N=(e,t,s=D)=>f(e,s,e=>((e,t,s)=>{const i=encodeURIComponent(t),n=encodeURIComponent(s),r=e.indexOf("#"),o=r>=0?e.slice(0,r):e,a=r>=0?e.slice(r):"",c=new RegExp(`([?&])${A(i)}=[^&#]*`);if(c.test(o))return o.replace(c,`$1${i}=${n}`)+a;const h=o.includes("?")?"&":"?";return`${o}${h}${i}=${n}${a}`})(e,"xsid",t));var U,P,b="1.0.25";class w{instance;developer;logger;store;constructor(e,s){this.logger=s.logger,this.store=s.store,this.developer=e.developer;const i=e.baseURL.replace(/\/$/,"");this.instance=t.create({baseURL:i,headers:{...e.defaultHeaders??{}},timeout:e.timeout??3e4,withCredentials:!0}),this.setupInterceptors()}setupInterceptors(){this.instance.interceptors.request.use(e=>(e.headers=e.headers||{},e.headers["Content-Type"]||(e.headers["Content-Type"]="application/json"),e.headers.Platform="web",e.headers.AppID=this.store.appId,e.withCredentials&&(e.headers["X-Sid"]=this.store.sessionId),e.ignoreWebsdkVersion||(e.headers["X-Websdk-Version"]=b),this.developer&&!e.ignoreDeveloper&&(e.headers["x-developer"]=this.developer),e)),this.instance.interceptors.response.use(e=>{const t=e.headers["x-sid"];return t&&(e.data.sessionId=t),e},e=>Promise.reject(e))}async get(e,t={},s={}){return this.request({url:e,method:"GET",params:t,...s})}async post(e,t,s={}){return this.request({url:e,method:"POST",data:t,...s})}async request(e){try{const{needSign:t,...s}=e;if(t&&"POST"===s.method?.toUpperCase()&&s.data){const t=this.store.currentUser;if(!t){const e="[HttpClient] HttpClient needs make sign but not found login user";return this.logger.error(e),S({code:E.SDK_ERROR,msg:e})}try{const i=await(async(e,t)=>{const s=I(e);return await C(s,t)})(s.data,t.secretKey);e.headers||(e.headers={}),e.headers.sign=i}catch(e){const t=`[HttpClient] HttpClient make sign error: ${e.message}`;return this.logger.error(t),S({code:E.SDK_ERROR,msg:t})}}const i=await this.instance.request({...s,headers:{...e.headers||{}}}),n=i.data;return 0!==n.code?(this.logger.error("[HttpClient]","Business server response error:",i),{ok:!1,code:n.code,msg:n.msg,msg_i18n:n.msg_i18n}):n.sessionId?{ok:!0,sessionId:n.sessionId,data:n.data}:{ok:!0,data:n.data}}catch(e){return this.handleError(e)}}handleError(e){return 200!==e.response?.status?{ok:!1,code:E.SERVER_ERROR,status:e.response?.status,msg:e.message||"server error"}:"ECONNABORTED"===e.code?{ok:!1,code:E.NETWORK_ERROR,msg:e.message||"request timeout"}:{ok:!1,code:E.NETWORK_ERROR,msg:e.message||"network error"}}}class y{listeners=new Map;logger;constructor(e){this.logger=e}on(e,t){this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t)}once(e,t){const s=i=>{t(i),this.off(e,s)};this.on(e,s)}off(e,t){this.listeners.has(e)&&(t?this.listeners.get(e).delete(t):this.listeners.delete(e))}emit(e,t){if(this.listeners.has(e))for(const s of this.listeners.get(e))try{s(t)}catch(t){this.logger.error(`[EventCore] handler error on "${String(e)}":`,t)}}clear(){this.listeners.clear()}}class M extends y{ws;options;status=o.INIT;constructor(e,t){super(t),this.options=e}connect(){if(this.status===o.CONNECTING||this.status===o.CONNECTED)return void this.logger.debug("[CONNECTION]","WebSocket is connecting or connected,current connect status is",`[${this.status}]`);this.logger.debug("[CONNECTION][connect]","WebSocket is connecting"),this.setStatus(o.CONNECTING);const e=new WebSocket(`${this.options.url}?token=${this.options.token}&platform=web`);this.ws=e,e.onopen=()=>{this.logger.debug("[CONNECTION][ws.onopen]","WebSocket is connected"),this.setStatus(o.CONNECTED),this.emit(a.OPEN)},e.onmessage=e=>{this.logger.debug("[CONNECTION][ws.onmessage]","WebSocket received a message",e.data),this.emit(a.MESSAGE,e.data)},e.onerror=e=>{this.logger.error("[CONNECTION][ws.onerror]","WebSocket connect error",e),this.emit(a.ERROR,e)},e.onclose=e=>{this.logger.debug("[CONNECTION][ws.onclose]","WebSocket connect be closed",e),this.setStatus(o.DISCONNECTED),this.emit(a.CLOSE,e)}}close(){this.ws?.close(),this.ws=void 0,this.setStatus(o.CLOSED)}send(e){if(this.status!==o.CONNECTED)throw new Error("WebSocket is not connected");this.ws.send(e)}getStatus(){return this.status}setStatus(e){this.status!==e&&(this.logger.debug("[CONNECTION][setStatus]","WebSocket status changed",this.status,"->",e),this.status=e,this.emit(a.STATUS_CHANGE,e))}}class G{connection;pingTimeout;pongTimeout;pingTimer;pongTimer;logger;constructor(e,t,s={}){this.connection=e,this.pingTimeout=s.pingTimeout??3e4,this.pongTimeout=s.pongTimeout??2e4,this.logger=t}ping(e){this.logger.debug("[Heartbeat]","Heartbeat ping"),this.stop(),this.pingTimer=window.setTimeout(()=>{try{this.connection.send(JSON.stringify({type:0})),this.logger.debug("[Heartbeat]","Heartbeat send PING"),this.pong(e)}catch{}},this.pingTimeout)}pong(e){clearTimeout(this.pongTimer),this.pongTimer=window.setTimeout(()=>{e?.(),this.logger.debug("[Heartbeat]","PING timeout, called PING/PONG callback")},this.pongTimeout)}stop(){this.logger.debug("[Heartbeat]","Heartbeat stop"),clearTimeout(this.pingTimer),clearTimeout(this.pongTimer),this.pingTimer=void 0,this.pongTimer=void 0}}class v{connection;baseInterval=1e3;maxAttempts=1/0;attempts=0;timer;enabled=!1;logger;constructor(e,t,s={}){this.logger=t,this.connection=e,s.baseInterval&&(this.baseInterval=s.baseInterval),s.maxAttempts&&(this.maxAttempts=s.maxAttempts),this.bindEvents()}bindEvents(){this.connection.on(a.CLOSE,()=>{this.enabled&&this.scheduleReconnect()}),this.connection.on(a.OPEN,()=>{this.reset()})}start(){this.logger.debug("[Reconnector]","Reconnector start"),this.enabled=!0}stop(){this.logger.debug("[Reconnector]","Reconnector stop"),this.enabled=!1,this.clearTimer()}scheduleReconnect(){if(this.logger.debug("[Reconnector]",`Reconnector scheduleReconnect, attempts: ${this.attempts}, maxAttempts: ${this.maxAttempts}`),this.attempts>=this.maxAttempts)return;this.attempts++;const e=this.baseInterval*Math.min(this.attempts,10);this.clearTimer(),this.timer=window.setTimeout(()=>{this.connection.connect()},e)}reset(){this.logger.debug("[Reconnector]","Reconnector reset"),this.attempts=0,this.clearTimer()}clearTimer(){this.timer&&(clearTimeout(this.timer),this.timer=void 0)}}!function(e){e.OPEN="OPEN",e.ERROR="ERROR",e.CLOSE="CLOSE",e.MESSAGE="MESSAGE",e.STATUS_CHANGE="STATUS_CHANGE",e.KICK_OFF="KICK_OFF"}(U||(U={}));class F extends y{connection;reconnector;heartbeat;pongTimeoutCount=0;offlineReconnectTimer;constructor(e,t){super(t),this.connection=new M({url:e.wsUrl,token:e.token},t),this.reconnector=new v(this.connection,t),this.heartbeat=new G(this.connection,t),this.bindEvents()}connect(){this.reconnector.start(),this.connection.connect()}disconnect(){this.reconnector.stop(),this.heartbeat.stop(),this.connection.close()}startPing(){this.heartbeat.ping(()=>{if(this.logger.warn("[IMClient][Heartbeat]","PONG timeout, current pong timeout count: ",this.pongTimeoutCount),this.pongTimeoutCount++,this.pongTimeoutCount>=2){this.disconnect();const e=setTimeout(()=>{this.connect(),clearTimeout(e)},1e4);return}this.startPing()})}bindEvents(){this.connection.on(a.OPEN,()=>{this.emit(U.OPEN),this.offlineReconnectTimer&&(clearTimeout(this.offlineReconnectTimer),this.offlineReconnectTimer=void 0),this.startPing()}),this.connection.on(a.CLOSE,e=>{if(e.code===i.KICK_OFF)return this.logger.warn("[IMClient][CLOSE][KICK_OFF]","You has been kicked off"),this.emit(U.KICK_OFF),void this.disconnect();this.emit(U.CLOSE)}),this.connection.on(a.MESSAGE,e=>{this.handleRawMessage(e)}),this.connection.on(a.STATUS_CHANGE,e=>{this.emit(U.STATUS_CHANGE,e)}),this.connection.on(a.ERROR,e=>{this.emit(U.ERROR,e)}),"undefined"!=typeof window&&(window.addEventListener("offline",()=>{if(this.offlineReconnectTimer)return;this.connection.close();const e=()=>{if(this.connection.getStatus()===o.CONNECTED)return this.offlineReconnectTimer&&clearTimeout(this.offlineReconnectTimer),void(this.offlineReconnectTimer=void 0);this.connection.connect(),this.offlineReconnectTimer=window.setTimeout(e,1e3)};e()}),window.addEventListener("online",()=>{this.offlineReconnectTimer&&(clearTimeout(this.offlineReconnectTimer),this.offlineReconnectTimer=void 0),this.connection.connect()}))}handleRawMessage(e){try{const t=JSON.parse(e);if(t.type===n.PONG_MESSAGE?this.startPing():this.sendAck(t.id),t.type===n.BIG_PACKAGE_PUSH)for(const e of t.content.big_push)this.emit(U.MESSAGE,e);else this.emit(U.MESSAGE,t)}catch(e){this.logger.error("[IMClient][handleRawMessage]","Message raw data json.parse error",e),this.emit(U.ERROR,e)}}sendAck(e){this.connection.send(JSON.stringify({type:1,ids:[e]}))}}!function(e){e.APP_ID="appId",e.CURRENT_USER="currentUser",e.CURRENT_FEED="currentFeed",e.SDK_READY="sdkReady",e.IS_CONNECTED="isConnected",e.CONNECTION_STATUS="connectionStatus",e.DEVICE_ID="typeximDeviceId",e.BROWSER_FINGERPRINT="typeximBrowserFingerprint",e.TAB_ID="typeximTabId",e.CROSS_SITE_COOKIE_BLOCKED="typeximCrossSiteCookieBlocked"}(P||(P={}));class k extends y{state={};constructor(e){super(e)}set(e,t){this.logger.debug("[Store] set:",e,t),this.state[e]=t,this.emit("change",{key:e,value:t})}get(e){return this.logger.debug("[Store] get:",e,this.state[e]),this.state[e]}remove(e){this.logger.debug("[Store] remove:",e,this.state[e]),delete this.state[e],this.emit("change",{key:e,value:void 0})}clear(){this.logger.debug("[Store] clear",this.state),this.state={appId:this.state.appId,typeximBrowserFingerprint:this.state.typeximBrowserFingerprint},this.emit("clear",void 0)}setWithSession(e,t){this.logger.debug("[Store] setWithSession:",e,t),this.set(e,t),sessionStorage.setItem(e,JSON.stringify(t))}getWithSession(e){if(this.logger.debug("[Store] getWithSession:",e,this.state[e]),this.state[e])return this.state[e];const t=sessionStorage.getItem(e);return t?JSON.parse(t):void 0}removeWithSession(e){this.logger.debug("[Store] removeWithSession:",e,this.state[e]),sessionStorage.removeItem(e),this.remove(e)}onChange(e){this.on("change",e)}offChange(e){this.off("change",e)}onClear(e){this.on("clear",e)}get appId(){return this.logger.debug("[Store] get appId",this.state.appId),this.state.appId}get ready(){return this.logger.debug("[Store] get ready",this.state.sdkReady),!!this.state.sdkReady}get deviceId(){const e=this.getWithSession(P.DEVICE_ID);return this.logger.debug("[Store] get deviceId",e),e}get currentUser(){return this.logger.debug("[Store] get currentUser",this.state.currentUser),this.state.currentUser}get currentChatId(){return this.logger.debug("[Store] get currentChatId",this.state.currentFeed?.chat_id),this.state.currentFeed?.chat_id}get currentFeed(){return this.logger.debug("[Store] get currentFeed",this.state.currentFeed),this.state.currentFeed}get sessionId(){return this.logger.debug("[Store] get sessionId",this.state.currentUser?.sessionId),this.state.currentUser?.sessionId}get browserFingerprint(){const e=this.getWithSession(P.BROWSER_FINGERPRINT);return this.logger.debug("[Store] get browserFingerprint",e),e}get tabId(){const e=this.getWithSession(P.TAB_ID);return this.logger.debug("[Store] get tabId",e),e}get connectionStatus(){return this.logger.debug("[Store] get connectionStatus",this.state.connectionStatus||o.INIT),this.state.connectionStatus||o.INIT}}class L{version;constructor(){this.version=0}increment(){this.version++}get currentVersion(){return this.version}check(e){return e===this.version}}const K="@typexim/agent-js-sdk_broadcast_channel";class x{config;logger;http;imClient=null;store;events;version;loadFeedAbortController=null;promises=new Map;constructor(e,t){this.logger=new p,this.store=new k(this.logger),this.events=new y(this.logger),this.store.set(P.APP_ID,e),this.config=t,this.version=new L,this.http=new w({baseURL:t.httpHost,developer:t.developer},{logger:this.logger,store:this.store}),this.generateTabId(),this.generateBrowserFingerprint(),this.listenBroadcastChannel()}setLogLevel(e){this.logger.setLogLevel(e)}async login(e){try{const t={...e||{}};if(!t.authToken)return S({code:E.SDK_ERROR,msg:"Invalid param: authToken must be provided"});if(!t.userId){const e=await this.generateBrowserFingerprint();t.userId=e}const s=await this.requestDeviceId(),i=await this.innerLogin(s,t);if(!i.ok||!i.data)return this.logger.error("[InternalChatSdk] Login failed",i),S({code:i.code,msg:i.msg,msg_i18n:i.msg_i18n,status:i.status});const n={...i.data||{},sessionId:i.sessionId};if(!i.sessionId)throw this.logger.error("[InternalChatSdk] Login failed, not found sessionid"),new Error("Login failed, not found sessionid");return n.secretKey=i.data.key,await Promise.all([this.syncLoginState(n),this.connectWebSocket(i.sessionId)]),this.notifyOtherTabsLogin(),m({id:n.id,userId:t.userId,name:n.name,avatar:n.avatar,email:n.email})}catch(e){return this.handleException(e)}}async innerLogin(e,t){const s=await this.http.post("/user/token/login",{token:t.authToken,userId:t.userId,deviceId:e,avatar:t.avatar,name:t.name,email:t.email});return this.triggerUnauthorized(s),s}generateTabId(){const e=this.store.getWithSession(P.TAB_ID);if(e)return e;const t=`${this.store.appId}_${Date.now()}_${Math.random().toString(36).substring(2,15)}`;return this.store.setWithSession(P.TAB_ID,t),t}async generateBrowserFingerprint(){try{const e=this.store.getWithSession(P.BROWSER_FINGERPRINT);if(e)return this.logger.debug("[ChatSdk] generateBrowserFingerprint success from local session",e),e;const t=await s.load(),i=await t.get();return this.logger.debug("[ChatSdk] generateBrowserFingerprint success",i.visitorId),this.store.setWithSession(P.BROWSER_FINGERPRINT,i.visitorId),i.visitorId}catch(e){this.logger.info("[ChatSdk] FingerprintJS generateBrowserFingerprint Error",e);const t=`${Date.now()}_${Math.random().toString(36).substring(2,15)}`;return this.logger.debug("[ChatSdk] random generateBrowserFingerprint success",t),this.store.setWithSession(P.BROWSER_FINGERPRINT,t),t}}async loadFeed(){const e=this.version.currentVersion;this.loadFeedAbortController&&this.loadFeedAbortController.abort(),this.loadFeedAbortController=new AbortController;const t=await this.http.get("/feed",{limit:10},{signal:this.loadFeedAbortController.signal}).catch(e=>{this.logger.error("[ChatSdk] loadFeed Error",e)});this.loadFeedAbortController=null;const s=this.version.check(e);if(!t||!s)return;const i=t.data?.feed_list?.find(e=>e.chat_type===c.groupChat);this.triggerUnauthorized(t),t.ok&&(this.logger.debug("[ChatSdk][FEED_UPDATED] loadFeed success",i),this.store.set(P.CURRENT_FEED,i),this.events.emit(u.FEED_UPDATED,i))}async syncLoginState(e){this.store.set(P.CURRENT_USER,e),this.store.set(P.SDK_READY,!0),await this.loadFeed(),this.events.emit(u.SDK_READY)}syncLogoutState(){this.unlistenBroadcastChannel(),this.store.set(P.CURRENT_USER,void 0),this.store.set(P.SDK_READY,!1),this.store.set(P.CURRENT_FEED,void 0),this.events.emit(u.SDK_NOT_READY)}async requestDeviceId(){const e=this.store.getWithSession(P.DEVICE_ID);if(e)return this.logger.debug("[ChatSdk] requestDeviceId success from local session",e),e;const t=await this.http.post("/device_api/device_id",{platform:"web",hash_str:this.store.browserFingerprint||""},{withCredentials:!1,ignoreWebsdkVersion:!0}).catch(e=>{this.logger.error("[ChatSdk] requestDeviceId Error",e)});if(!t?.ok||!t?.data)throw this.logger.error("[ChatSdk] requestDeviceId Error",t),new Error("requestDeviceId failed");return this.logger.debug("[ChatSdk] requestDeviceId success",t.data),this.store.setWithSession(P.DEVICE_ID,t.data),t.data}async logout(){try{if(!this.store.currentUser)return m(null);const e=await this.http.get("/user/logout");return this.triggerUnauthorized(e),e.ok?(this.syncLogoutState(),this.disconnectWebSocket(),m(null)):S({code:e.code,msg:e.msg,msg_i18n:e.msg_i18n,status:e.status})}catch(e){return this.handleException(e)}}async addGroupMember(e,t){try{if(this.assertReady(),!e)return S({code:E.SDK_ERROR,msg:"not found chat id"});if(!t?.length)return m(null);const s=this.store.currentFeed;if(!s)return S({code:E.SDK_ERROR,msg:"not found current feed"});const i=await this.getChatMembers(s.chat_id,s.chat_member);if(!i.ok)return S({code:i.code,msg:i.msg,msg_i18n:i.msg_i18n,status:i.status});const n=(i.data||[]).map(e=>e.user_id),r=t.filter(e=>!n.includes(e)),o=await this.addMember(r,s.chat_id);return o.ok?m(o.data):S({code:o.code,msg:o.msg,msg_i18n:o.msg_i18n,status:o.status})}catch(e){return this.handleException(e)}}async initialChat(e){try{this.assertReady();const t=this.store.currentFeed;if(!t){const t=await this.createFeed(e?.receiverIds||[],e?.name);return this.triggerUnauthorized(t),t.ok&&t.data?(this.store.set(P.CURRENT_FEED,t.data),m(t.data.chat_id)):S({code:t.code,msg:t.msg,msg_i18n:t.msg_i18n,status:t.status})}if(!e?.receiverIds?.length)return m(t.chat_id);const s=await this.addGroupMember(t.chat_id,e.receiverIds);return s.ok?m(t.chat_id):s}catch(e){return this.handleException(e)}}async getCurrentFeed(){try{return this.assertReady(),{ok:!0,data:this.store.currentFeed}}catch(e){return this.handleException(e)}}async getMessageList(e){try{this.assertReady();const t=this.store.currentFeed;if(!t)return S({code:E.SDK_ERROR,msg:"No feed found"});const{chat_id:s,first_position:i,last_message_position:n}=t,{positions:r,nextPosition:o,hasMore:a}=(e=>{const t=[];if(e.direction===l.up){let s=e.startPosition??e.maxPosition;for(;t.length<e.limit&&s>=e.minPosition;)t.push(s),s--;const i=s>=e.minPosition;let n;return i&&(n=s),{positions:t,nextPosition:n,hasMore:i}}{let s=e.startPosition??e.minPosition;for(;t.length<e.limit&&s<=e.maxPosition;)t.push(s),s++;const i=s<=e.maxPosition;let n;return i&&(n=s),{positions:t,nextPosition:n,hasMore:i}}})({maxPosition:n,minPosition:i,startPosition:e.messagePosition,limit:e.limit,direction:e.direction??l.up});if(r.length>0){const e=await this.http.post("/message/get_by_position",{chat_position:{[s]:r}});if(this.triggerUnauthorized(e),e.ok&&e.data?.[s]){return m({hasMore:a,list:await this.processMessageListResourceAuth(e.data[s].reverse()),nextMessagePosition:o})}return S({code:e.code,msg:e.msg,msg_i18n:e.msg_i18n,status:e.status})}return m({hasMore:!1,list:[]})}catch(e){return this.handleException(e)}}async processMessageListResourceAuth(e){if(!e.length)return e;if(!await this.detectNeedAppendXsidBySessionCache(e))return e;const t=this.store.sessionId;return t?e.map(e=>{if(!e.content||"string"!=typeof e.content)return e;const s=N(e.content,t,D);return s===e.content?e:{...e,content:s}}):e}async detectNeedAppendXsidBySessionCache(e){const t=this.store.getWithSession(P.CROSS_SITE_COOKIE_BLOCKED);if("boolean"==typeof t)return t;const s=this.extractFirstDomainResourceUrl(e,D);if(this.logger.debug("[ChatSdk] detectNeedAppendXsidBySessionCache probeUrl",s),!s)return!1;if(!this.isCrossSiteUrl(s))return this.store.setWithSession(P.CROSS_SITE_COOKIE_BLOCKED,!1),!1;const i=await this.probeCrossSiteCookieBlocked(s);return i&&this.logger.warn("[ChatSdk] Cross site cookie blocked, will change auth method"),this.store.setWithSession(P.CROSS_SITE_COOKIE_BLOCKED,i),i}extractFirstDomainResourceUrl(e,t){const s=O(t);for(const t of e){if(!t.content||"string"!=typeof t.content)continue;s.lastIndex=0;const e=t.content.match(s)?.[0];if(e)try{return JSON.parse(`"${e}"`)}catch{return e}}}async probeCrossSiteCookieBlocked(e){try{const t=await fetch(e,{method:"GET",credentials:"include",cache:"no-store",headers:{Range:"bytes=0-0"}});return 401===t.status||403===t.status}catch{return!1}}isCrossSiteUrl(e){try{return new URL(e,window.location.href).origin!==window.location.origin}catch{return!0}}async sendMessage(e){try{this.assertReady();const t=e.messageType;switch(t){case d.text:return this.sendTextMessage(e);case d.image:return this.sendImageMessage(e);case d.video:return this.sendVideoMessage(e);case d.file:return this.sendFileMessage(e);default:return this.logger.warn("Unsupported message type: ",t),S({code:E.SDK_ERROR,msg:`Unsupported message type: ${t}`})}}catch(e){return this.handleException(e)}}async sendTextMessage(e){const t=await this.http.post("/message/send_text",{chat_id:e.chatId,client_msg_id:e.clientMsgId,text:e.text.trim()},{needSign:!0});return this.triggerUnauthorized(t),t}async sendImageMessage(e){const t=await this.http.post("/message/send_image",{chat_id:e.chatId,client_msg_id:e.clientMsgId,object_url:e.objectUrl,width:e.width,height:e.height},{needSign:!0});return this.triggerUnauthorized(t),t}async sendVideoMessage(e){const t=await this.http.post("/message/send_video",{chat_id:e.chatId,client_msg_id:e.clientMsgId,video_url:e.objectUrl,duration_second:e.duration,image_url:e.coverUrl,width:e.width,height:e.height},{needSign:!0});return this.triggerUnauthorized(t),t}async sendFileMessage(e){const t=await this.http.post("/message/send_file",{chat_id:e.chatId,client_msg_id:e.clientMsgId,object_url:e.objectUrl,file_name:e.fileName,file_size:e.fileSize},{needSign:!0});return this.triggerUnauthorized(t),t}async uploadFile(e){const{chatId:t,fileContent:s,fileFormat:i,fileName:n,fileType:r,onUploadProgress:o}=e;if(s.size>209715200)return S({code:E.SDK_ERROR,msg:"File size exceeds 200MB, upload failed"});const a=new FormData;a.append("file_content",s),a.append("file_type",r),a.append("file_name",n),a.append("file_format",i),a.append("chat_id",t);const c=await this.http.post("/chat/upload",a,{needSign:!1,ignoreDeveloper:!0,onUploadProgress:o,headers:{"Content-Type":"multipart/form-data"}});return this.triggerUnauthorized(c),c}async sendMessageReadReceipt(e){try{if(this.assertReady(),!e.messageIds?.length)return m(null);const t=await this.http.post("/message/read",{chat_id:e.chatId,message_ids:e.messageIds},{needSign:!0});return this.triggerUnauthorized(t),t}catch(e){return this.handleException(e)}}async markAllMessagesAsRead(e){const t=this.store.currentFeed?.unread_message_ids||[];return this.sendMessageReadReceipt({chatId:e,messageIds:t})}async recallMessage(e){try{if(this.assertReady(),!e.messageIds.length)return m(null);const t=await this.http.post("/message/remove",{chat_id:e.chatId,message_ids:e.messageIds,two_way:1},{needSign:!0});return this.triggerUnauthorized(t),t}catch(e){return this.handleException(e)}}triggerUnauthorized(e){e.ok||401!==e.status||this.events.emit(u.UNAUTHORIZED)}async createFeed(e,t){const s=this.store.currentUser?.id;if(!s)return S({code:E.SDK_ERROR,msg:"User not logged in"});if(this.promises.has(s))return this.promises.get(s);const i=this.http.post("/chat/group",{receiver_ids:e,group_type:0,name:t||`User ${this.store.currentUser?.name||this.store.currentUser?.id}`},{needSign:!0}).catch(e=>{throw e}).finally(()=>{this.promises.delete(s)});return this.promises.set(s,i),i}async getChatMembers(e,t){const s=await this.http.post("/chat/chatter_info",JSON.stringify({chatters:{[e]:t}}));return this.triggerUnauthorized(s),s}async addMember(e,t){if(!t)return S({code:E.SDK_ERROR,msg:"not found chat id"});if(!e.length)return m(null);const s=await this.http.post("/chat/group/add_member",{user_ids:e,chat_id:t},{needSign:!0});return this.triggerUnauthorized(s),s}handlePushMessage(e){switch(this.logger.debug("handlePushMessage",e),e.type){case n.CREATE_FEED:case n.UPDATE_FEED:this.handleFeedUpdate(e);break;case n.ADD_GROUP_MEMBER:case n.DEL_GROUP_MEMBER:this.handleGroupMemberUpdate(e);break;case n.ADD_MESSAGE:this.handleAddMessage(e);break;case n.UPDATE_MESSAGE:this.handleUpdateMessage(e);break;case n.READ_MESSAGE:this.handleReadMessage(e);break;case n.KICK_OUT_DEVICE:this.handleKickOut()}}handleGroupMemberUpdate(e){e.content.chat_id===this.store.currentChatId&&this.events.emit(u.GROUP_MEMBER_UPDATED,{type:e.type,chatId:e.content.chat_id,members:(e?.content?.chat_member||[]).map(e=>({avatar:e.avatar,chatId:e.chat_id,name:e.name,userId:e.user_id}))})}handleFeedUpdate(e){this.store.set(P.CURRENT_FEED,e.content),this.events.emit(u.FEED_UPDATED,e.content)}async handleAddMessage(e){e.content.chat_id===this.store.currentChatId&&(await this.loadFeed(),this.events.emit(u.MESSAGE_RECEIVED,e.content))}async handleUpdateMessage(e){e.content.chat_id===this.store.currentChatId&&(await this.loadFeed(),this.events.emit(u.MESSAGE_UPDATED,e.content))}async handleReadMessage(e){e.content.chat_id===this.store.currentChatId&&(await this.loadFeed(),this.events.emit(u.MESSAGE_RECEIPT_RECEIVED,{chatId:e.content.chat_id,messageIds:e.content.message_ids,readerUserIds:e.content.reader_ids}))}handleKickOut(){this.syncLogoutState(),this.disconnectWebSocket(),this.events.emit(u.SDK_KICKOUT)}on(e,t){return this.events.on(e,t)}once(e,t){return this.events.once(e,t)}off(e,t){return this.events.off(e,t)}get currentUserId(){return this.logger.debug("[InternalChatSdk] get currentUserId==>",this.store.currentUser),this.store.currentUser?.id}get currentChatId(){return this.logger.debug("[InternalChatSdk] get currentChatId==>",this.store.currentChatId),this.store.currentChatId}get isReady(){return this.logger.debug("[InternalChatSdk] get isReady==>",this.store.ready),this.store.ready}listenBroadcastChannel(){new BroadcastChannel(K).onmessage=e=>{const t=this.store.appId,s=this.store.tabId;e.data.type===r.KICK_OUT&&e.data.appId===t&&e.data.tabId!==s&&(this.logger.debug("[BroadcastChannel] message: kick out",{appId:t,sourceTabId:e.data.tabId,currentTabId:s}),this.handleKickOut())}}unlistenBroadcastChannel(){new BroadcastChannel(K).close()}notifyOtherTabsLogin(){new BroadcastChannel(K).postMessage({type:r.KICK_OUT,appId:this.store.appId,tabId:this.store.tabId})}async connectWebSocket(e){if(!e)throw Error("connect websocket error, not found login user token");this.imClient=new F({token:e,wsUrl:`${this.config.websocketHost}/ws`},this.logger),this.imClient.on(U.STATUS_CHANGE,e=>{this.store.set(P.CONNECTION_STATUS,e),this.events.emit(u.CONNECTION_STATUS_CHANGE,e)}),this.imClient.on(U.OPEN,()=>{this.store.set(P.IS_CONNECTED,!0)}),this.imClient.on(U.KICK_OFF,()=>{this.store.set(P.IS_CONNECTED,!1)}),this.imClient.on(U.CLOSE,()=>{this.store.set(P.IS_CONNECTED,!1)}),this.imClient.on(U.MESSAGE,e=>{this.handlePushMessage(e)}),this.imClient.connect()}disconnectWebSocket(){this.imClient&&(this.imClient.disconnect(),this.imClient=null)}assertReady(){if(!this.store.ready)throw{code:E.SDK_ERROR,msg:"sdk not ready"}}handleException(e){return this.logger.error("[ChatSDK Error]",e),{ok:!1,code:e.code||E.SDK_ERROR,msg:e.msg||e.message||"sdk error"}}}const B=new Map;function H(e){return{setLogLevel(t){e.setLogLevel(t)},login:t=>e.login(t),logout:()=>e.logout(),initialChat:t=>e.initialChat(t),addGroupMember:(t,s)=>e.addGroupMember(t,s),getCurrentFeed:()=>e.getCurrentFeed(),getMessageList:t=>e.getMessageList(t),uploadFile:t=>e.uploadFile(t),sendMessage:t=>e.sendMessage(t),sendMessageReadReceipt:t=>e.sendMessageReadReceipt(t),markAllMessagesAsRead:t=>e.markAllMessagesAsRead(t),recallMessage:t=>e.recallMessage(t),get currentUserId(){return e.currentUserId},get currentChatId(){return e.currentChatId},get isReady(){return e.isReady},on:(t,s)=>e.on(t,s),once:(t,s)=>e.once(t,s),off:(t,s)=>e.off(t,s)}}var W={create:function(e,t){if(B.has(e))return H(B.get(e));const s=new x(e,t);return B.set(e,s),H(s)}};export{E as ChatSdkErrorCode,u as ChatSdkEvent,c as ChatType,o as ConnectionStatus,_ as GroupMemberUpdateType,h as MessageKind,g as MessageOperation,d as MessageType,l as RequestDirection,W as default};
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e,t,s,r,i,n,o,a,h,c,d,E,g,u=require("crypto-js"),l=require("axios"),_=require("@fingerprintjs/fingerprintjs");function p(e){return{ok:!1,code:e.code||exports.ChatSdkErrorCode.SDK_ERROR,status:e.status,msg:e.msg||"sdk error",msg_i18n:e.msg_i18n}}function S(e){return{ok:!0,data:e}}!function(e){e[e.KICK_OFF=4001]="KICK_OFF"}(e||(e={})),function(e){e[e.CREATE_FEED=0]="CREATE_FEED",e[e.UPDATE_FEED=1]="UPDATE_FEED",e[e.ADD_MESSAGE=2]="ADD_MESSAGE",e[e.UPDATE_MESSAGE=3]="UPDATE_MESSAGE",e[e.UPDATE_USER_DATA=4]="UPDATE_USER_DATA",e[e.USER_LOGIN=5]="USER_LOGIN",e[e.READ_MESSAGE=6]="READ_MESSAGE",e[e.PONG_MESSAGE=8]="PONG_MESSAGE",e[e.DELETE_MESSAGE=9]="DELETE_MESSAGE",e[e.UPDATE_GROUP=12]="UPDATE_GROUP",e[e.DELETE_GROUP=13]="DELETE_GROUP",e[e.UPDATE_LOGIN_USER=17]="UPDATE_LOGIN_USER",e[e.UPDATE_MESSAGE_REACTION=19]="UPDATE_MESSAGE_REACTION",e[e.ADD_GROUP_MEMBER=21]="ADD_GROUP_MEMBER",e[e.DEL_GROUP_MEMBER=22]="DEL_GROUP_MEMBER",e[e.ADD_CONTACTS=23]="ADD_CONTACTS",e[e.UPDATE_CONTACTS=24]="UPDATE_CONTACTS",e[e.DEL_CONTACTS=25]="DEL_CONTACTS",e[e.BLOCK_USER=26]="BLOCK_USER",e[e.DEVICE_CODE=27]="DEVICE_CODE",e[e.MSG_OPEN_CLOCK=28]="MSG_OPEN_CLOCK",e[e.DELETE_SECRET_CHAT=29]="DELETE_SECRET_CHAT",e[e.DELETE_FEED=30]="DELETE_FEED",e[e.FAVORITE_UPDATE=31]="FAVORITE_UPDATE",e[e.STICKERS_UPDATE=32]="STICKERS_UPDATE",e[e.CUSTOM_STICKERS_UPDATE=33]="CUSTOM_STICKERS_UPDATE",e[e.MANAGE_DEVICE_UPDATE=34]="MANAGE_DEVICE_UPDATE",e[e.MASS_MESSAGE_UPDATE=35]="MASS_MESSAGE_UPDATE",e[e.CHAT_WALLPAPER_DELETE=36]="CHAT_WALLPAPER_DELETE",e[e.CHAT_WALLPAPER_ADD=37]="CHAT_WALLPAPER_ADD",e[e.CONTACT_REQUEST=40]="CONTACT_REQUEST",e[e.USER_PREFERENCE_CHANGE=38]="USER_PREFERENCE_CHANGE",e[e.UPDATE_GROUP_PIN=41]="UPDATE_GROUP_PIN",e[e.RTC_CANCEL=46]="RTC_CANCEL",e[e.ADD_FEED_FOLDER=43]="ADD_FEED_FOLDER",e[e.UPDATE_FEED_FOLDER=44]="UPDATE_FEED_FOLDER",e[e.UPDATE_FOLDER_FEED_LIST=47]="UPDATE_FOLDER_FEED_LIST",e[e.DELETE_FEED_FOLDER=45]="DELETE_FEED_FOLDER",e[e.UPDATE_CHATTER=42]="UPDATE_CHATTER",e[e.PAPER_KEY=48]="PAPER_KEY",e[e.PAPER_KEY_LOG=49]="PAPER_KEY_LOG",e[e.USER_LOGIN_SCAN=50]="USER_LOGIN_SCAN",e[e.RTC_RINGING=51]="RTC_RINGING",e[e.ON_UPDATE_PRIVATE_SETTING=52]="ON_UPDATE_PRIVATE_SETTING",e[e.ON_DELETE_PRIVATE_SETTING=53]="ON_DELETE_PRIVATE_SETTING",e[e.ON_UPDATE_LOGIN_PRIVATE_SETTING=54]="ON_UPDATE_LOGIN_PRIVATE_SETTING",e[e.PUSH_LIVE_MESSAGE=56]="PUSH_LIVE_MESSAGE",e[e.BIG_PACKAGE_PUSH=126]="BIG_PACKAGE_PUSH",e[e.KICK_OUT_DEVICE=127]="KICK_OUT_DEVICE",e[e.CLEAR_HISTORY=128]="CLEAR_HISTORY",e[e.CLEAR_DATA=255]="CLEAR_DATA"}(t||(t={})),function(e){e[e.KICK_OUT=0]="KICK_OUT"}(s||(s={})),exports.ConnectionStatus=void 0,(r=exports.ConnectionStatus||(exports.ConnectionStatus={})).INIT="INIT",r.CONNECTING="CONNECTING",r.CONNECTED="CONNECTED",r.DISCONNECTED="DISCONNECTED",r.CLOSED="CLOSED",function(e){e.OPEN="OPEN",e.ERROR="ERROR",e.CLOSE="CLOSE",e.MESSAGE="MESSAGE",e.STATUS_CHANGE="STATUS_CHANGE"}(i||(i={})),exports.ChatType=void 0,(n=exports.ChatType||(exports.ChatType={}))[n.singleChat=1]="singleChat",n[n.groupChat=2]="groupChat",exports.MessageKind=void 0,(o=exports.MessageKind||(exports.MessageKind={}))[o.normal=0]="normal",o[o.system=1]="system",exports.MessageType=void 0,(a=exports.MessageType||(exports.MessageType={}))[a.text=0]="text",a[a.image=1]="image",a[a.audio=3]="audio",a[a.video=4]="video",a[a.file=5]="file",a[a.mergeForward=6]="mergeForward",a[a.sticker=7]="sticker",a[a.richText=8]="richText",a[a.contact=9]="contact",a[a.communication=10]="communication",a[a.mixedImageText=11]="mixedImageText",a[a.custom=13]="custom",a[a.luckyGift=14]="luckyGift",a[a.fileGroup=15]="fileGroup",a[a.cardMsg=16]="cardMsg",exports.MessageOperation=void 0,(h=exports.MessageOperation||(exports.MessageOperation={}))[h.normal=0]="normal",h[h.recall=1]="recall",exports.ChatSdkErrorCode=void 0,(c=exports.ChatSdkErrorCode||(exports.ChatSdkErrorCode={}))[c.NETWORK_ERROR=-1e4]="NETWORK_ERROR",c[c.SDK_ERROR=-10001]="SDK_ERROR",c[c.SERVER_ERROR=-10002]="SERVER_ERROR",exports.ChatSdkEvent=void 0,(d=exports.ChatSdkEvent||(exports.ChatSdkEvent={})).SDK_READY="SDK_READY",d.SDK_NOT_READY="SDK_NOT_READY",d.SDK_KICKOUT="SDK_KICKOUT",d.FEED_UPDATED="FEED_UPDATED",d.MESSAGE_RECEIVED="MESSAGE_RECEIVED",d.MESSAGE_UPDATED="MESSAGE_UPDATED",d.MESSAGE_RECEIPT_RECEIVED="MESSAGE_RECEIPT_RECEIVED",d.CONNECTION_STATUS_CHANGE="CONNECTION_STATUS_CHANGE",d.UNAUTHORIZED="UNAUTHORIZED",d.GROUP_MEMBER_UPDATED="GROUP_MEMBER_UPDATED",exports.RequestDirection=void 0,(E=exports.RequestDirection||(exports.RequestDirection={}))[E.up=0]="up",E[E.down=1]="down",exports.GroupMemberUpdateType=void 0,(g=exports.GroupMemberUpdateType||(exports.GroupMemberUpdateType={}))[g.ADD_GROUP_MEMBER=21]="ADD_GROUP_MEMBER",g[g.DEL_GROUP_MEMBER=22]="DEL_GROUP_MEMBER";const C="[TYPEX_AGENT_JS_SDK]";class m{level=0;setLogLevel(e){this.level=e}getLogLevel(){return this.level}shouldPrint(e){return e>=this.level}debug(...e){this.shouldPrint(0)&&console.debug(`${C}[DEBUG]`,...e)}info(...e){this.shouldPrint(0)&&console.info(`${C}[INFO]`,...e)}warn(...e){this.shouldPrint(1)&&console.warn(`${C}[WARN]`,...e)}error(...e){this.shouldPrint(2)&&console.error(`${C}[ERROR]`,...e)}}function R(e){return(new TextEncoder).encode(e).buffer}async function T(e,t){return window.crypto&&window.crypto.subtle?await async function(e,t){const s=R(t),r=R(e),i=await crypto.subtle.importKey("raw",s,{name:"HMAC",hash:{name:"SHA-256"}},!1,["sign"]),n=await crypto.subtle.sign("HMAC",i,r);return Array.from(new Uint8Array(n)).map(e=>e.toString(16).padStart(2,"0")).join("")}(e,t):function(e,t){const s=u.HmacSHA256(e,t);return u.enc.Hex.stringify(s)}(e,t)}const I=e=>{if(null==e)return"";if("object"!=typeof e||Array.isArray(e)){if(Array.isArray(e)){let t="";for(const s of e)t+=I(s);return t}return"string"==typeof e?e:String(e)}{const t=Object.keys(e).sort();let s="";for(const r of t)s+=I(e[r]);return s}};var D,A,O="1.0.24";class N{instance;developer;logger;store;constructor(e,t){this.logger=t.logger,this.store=t.store,this.developer=e.developer;const s=e.baseURL.replace(/\/$/,"");this.instance=l.create({baseURL:s,headers:{...e.defaultHeaders??{}},timeout:e.timeout??3e4,withCredentials:!0}),this.setupInterceptors()}setupInterceptors(){this.instance.interceptors.request.use(e=>(e.headers=e.headers||{},e.headers["Content-Type"]||(e.headers["Content-Type"]="application/json"),e.headers.Platform="web",e.headers.AppID=this.store.appId,e.withCredentials&&(e.headers["X-Sid"]=this.store.sessionId),e.ignoreWebsdkVersion||(e.headers["X-Websdk-Version"]=O),this.developer&&!e.ignoreDeveloper&&(e.headers["x-developer"]=this.developer),e)),this.instance.interceptors.response.use(e=>{const t=e.headers["x-sid"];return t&&(e.data.sessionId=t),e},e=>Promise.reject(e))}async get(e,t={},s={}){return this.request({url:e,method:"GET",params:t,...s})}async post(e,t,s={}){return this.request({url:e,method:"POST",data:t,...s})}async request(e){try{const{needSign:t,...s}=e;if(t&&"POST"===s.method?.toUpperCase()&&s.data){const t=this.store.currentUser;if(!t){const e="[HttpClient] HttpClient needs make sign but not found login user";return this.logger.error(e),p({code:exports.ChatSdkErrorCode.SDK_ERROR,msg:e})}try{const r=await(async(e,t)=>{const s=I(e);return await T(s,t)})(s.data,t.secretKey);e.headers||(e.headers={}),e.headers.sign=r}catch(e){const t=`[HttpClient] HttpClient make sign error: ${e.message}`;return this.logger.error(t),p({code:exports.ChatSdkErrorCode.SDK_ERROR,msg:t})}}const r=await this.instance.request({...s,headers:{...e.headers||{}}}),i=r.data;return 0!==i.code?(this.logger.error("[HttpClient]","Business server response error:",r),{ok:!1,code:i.code,msg:i.msg,msg_i18n:i.msg_i18n}):i.sessionId?{ok:!0,sessionId:i.sessionId,data:i.data}:{ok:!0,data:i.data}}catch(e){return this.handleError(e)}}handleError(e){return 200!==e.response?.status?{ok:!1,code:exports.ChatSdkErrorCode.SERVER_ERROR,status:e.response?.status,msg:e.message||"server error"}:"ECONNABORTED"===e.code?{ok:!1,code:exports.ChatSdkErrorCode.NETWORK_ERROR,msg:e.message||"request timeout"}:{ok:!1,code:exports.ChatSdkErrorCode.NETWORK_ERROR,msg:e.message||"network error"}}}class U{listeners=new Map;logger;constructor(e){this.logger=e}on(e,t){this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t)}once(e,t){const s=r=>{t(r),this.off(e,s)};this.on(e,s)}off(e,t){this.listeners.has(e)&&(t?this.listeners.get(e).delete(t):this.listeners.delete(e))}emit(e,t){if(this.listeners.has(e))for(const s of this.listeners.get(e))try{s(t)}catch(t){this.logger.error(`[EventCore] handler error on "${String(e)}":`,t)}}clear(){this.listeners.clear()}}class f extends U{ws;options;status=exports.ConnectionStatus.INIT;constructor(e,t){super(t),this.options=e}connect(){if(this.status===exports.ConnectionStatus.CONNECTING||this.status===exports.ConnectionStatus.CONNECTED)return void this.logger.debug("[CONNECTION]","WebSocket is connecting or connected,current connect status is",`[${this.status}]`);this.logger.debug("[CONNECTION][connect]","WebSocket is connecting"),this.setStatus(exports.ConnectionStatus.CONNECTING);const e=new WebSocket(`${this.options.url}?token=${this.options.token}&platform=web`);this.ws=e,e.onopen=()=>{this.logger.debug("[CONNECTION][ws.onopen]","WebSocket is connected"),this.setStatus(exports.ConnectionStatus.CONNECTED),this.emit(i.OPEN)},e.onmessage=e=>{this.logger.debug("[CONNECTION][ws.onmessage]","WebSocket received a message",e.data),this.emit(i.MESSAGE,e.data)},e.onerror=e=>{this.logger.error("[CONNECTION][ws.onerror]","WebSocket connect error",e),this.emit(i.ERROR,e)},e.onclose=e=>{this.logger.debug("[CONNECTION][ws.onclose]","WebSocket connect be closed",e),this.setStatus(exports.ConnectionStatus.DISCONNECTED),this.emit(i.CLOSE,e)}}close(){this.ws?.close(),this.ws=void 0,this.setStatus(exports.ConnectionStatus.CLOSED)}send(e){if(this.status!==exports.ConnectionStatus.CONNECTED)throw new Error("WebSocket is not connected");this.ws.send(e)}getStatus(){return this.status}setStatus(e){this.status!==e&&(this.logger.debug("[CONNECTION][setStatus]","WebSocket status changed",this.status,"->",e),this.status=e,this.emit(i.STATUS_CHANGE,e))}}class P{connection;pingTimeout;pongTimeout;pingTimer;pongTimer;logger;constructor(e,t,s={}){this.connection=e,this.pingTimeout=s.pingTimeout??3e4,this.pongTimeout=s.pongTimeout??2e4,this.logger=t}ping(e){this.logger.debug("[Heartbeat]","Heartbeat ping"),this.stop(),this.pingTimer=window.setTimeout(()=>{try{this.connection.send(JSON.stringify({type:0})),this.logger.debug("[Heartbeat]","Heartbeat send PING"),this.pong(e)}catch{}},this.pingTimeout)}pong(e){clearTimeout(this.pongTimer),this.pongTimer=window.setTimeout(()=>{e?.(),this.logger.debug("[Heartbeat]","PING timeout, called PING/PONG callback")},this.pongTimeout)}stop(){this.logger.debug("[Heartbeat]","Heartbeat stop"),clearTimeout(this.pingTimer),clearTimeout(this.pongTimer),this.pingTimer=void 0,this.pongTimer=void 0}}class b{connection;baseInterval=1e3;maxAttempts=1/0;attempts=0;timer;enabled=!1;logger;constructor(e,t,s={}){this.logger=t,this.connection=e,s.baseInterval&&(this.baseInterval=s.baseInterval),s.maxAttempts&&(this.maxAttempts=s.maxAttempts),this.bindEvents()}bindEvents(){this.connection.on(i.CLOSE,()=>{this.enabled&&this.scheduleReconnect()}),this.connection.on(i.OPEN,()=>{this.reset()})}start(){this.logger.debug("[Reconnector]","Reconnector start"),this.enabled=!0}stop(){this.logger.debug("[Reconnector]","Reconnector stop"),this.enabled=!1,this.clearTimer()}scheduleReconnect(){if(this.logger.debug("[Reconnector]",`Reconnector scheduleReconnect, attempts: ${this.attempts}, maxAttempts: ${this.maxAttempts}`),this.attempts>=this.maxAttempts)return;this.attempts++;const e=this.baseInterval*Math.min(this.attempts,10);this.clearTimer(),this.timer=window.setTimeout(()=>{this.connection.connect()},e)}reset(){this.logger.debug("[Reconnector]","Reconnector reset"),this.attempts=0,this.clearTimer()}clearTimer(){this.timer&&(clearTimeout(this.timer),this.timer=void 0)}}!function(e){e.OPEN="OPEN",e.ERROR="ERROR",e.CLOSE="CLOSE",e.MESSAGE="MESSAGE",e.STATUS_CHANGE="STATUS_CHANGE",e.KICK_OFF="KICK_OFF"}(D||(D={}));class M extends U{connection;reconnector;heartbeat;pongTimeoutCount=0;offlineReconnectTimer;constructor(e,t){super(t),this.connection=new f({url:e.wsUrl,token:e.token},t),this.reconnector=new b(this.connection,t),this.heartbeat=new P(this.connection,t),this.bindEvents()}connect(){this.reconnector.start(),this.connection.connect()}disconnect(){this.reconnector.stop(),this.heartbeat.stop(),this.connection.close()}startPing(){this.heartbeat.ping(()=>{if(this.logger.warn("[IMClient][Heartbeat]","PONG timeout, current pong timeout count: ",this.pongTimeoutCount),this.pongTimeoutCount++,this.pongTimeoutCount>=2){this.disconnect();const e=setTimeout(()=>{this.connect(),clearTimeout(e)},1e4);return}this.startPing()})}bindEvents(){this.connection.on(i.OPEN,()=>{this.emit(D.OPEN),this.offlineReconnectTimer&&(clearTimeout(this.offlineReconnectTimer),this.offlineReconnectTimer=void 0),this.startPing()}),this.connection.on(i.CLOSE,t=>{if(t.code===e.KICK_OFF)return this.logger.warn("[IMClient][CLOSE][KICK_OFF]","You has been kicked off"),this.emit(D.KICK_OFF),void this.disconnect();this.emit(D.CLOSE)}),this.connection.on(i.MESSAGE,e=>{this.handleRawMessage(e)}),this.connection.on(i.STATUS_CHANGE,e=>{this.emit(D.STATUS_CHANGE,e)}),this.connection.on(i.ERROR,e=>{this.emit(D.ERROR,e)}),"undefined"!=typeof window&&(window.addEventListener("offline",()=>{if(this.offlineReconnectTimer)return;this.connection.close();const e=()=>{if(this.connection.getStatus()===exports.ConnectionStatus.CONNECTED)return this.offlineReconnectTimer&&clearTimeout(this.offlineReconnectTimer),void(this.offlineReconnectTimer=void 0);this.connection.connect(),this.offlineReconnectTimer=window.setTimeout(e,1e3)};e()}),window.addEventListener("online",()=>{this.offlineReconnectTimer&&(clearTimeout(this.offlineReconnectTimer),this.offlineReconnectTimer=void 0),this.connection.connect()}))}handleRawMessage(e){try{const s=JSON.parse(e);if(s.type===t.PONG_MESSAGE?this.startPing():this.sendAck(s.id),s.type===t.BIG_PACKAGE_PUSH)for(const e of s.content.big_push)this.emit(D.MESSAGE,e);else this.emit(D.MESSAGE,s)}catch(e){this.logger.error("[IMClient][handleRawMessage]","Message raw data json.parse error",e),this.emit(D.ERROR,e)}}sendAck(e){this.connection.send(JSON.stringify({type:1,ids:[e]}))}}!function(e){e.APP_ID="appId",e.CURRENT_USER="currentUser",e.CURRENT_FEED="currentFeed",e.SDK_READY="sdkReady",e.IS_CONNECTED="isConnected",e.CONNECTION_STATUS="connectionStatus",e.DEVICE_ID="typeximDeviceId",e.BROWSER_FINGERPRINT="typeximBrowserFingerprint",e.TAB_ID="typeximTabId"}(A||(A={}));class y extends U{state={};constructor(e){super(e)}set(e,t){this.logger.debug("[Store] set:",e,t),this.state[e]=t,this.emit("change",{key:e,value:t})}get(e){return this.logger.debug("[Store] get:",e,this.state[e]),this.state[e]}remove(e){this.logger.debug("[Store] remove:",e,this.state[e]),delete this.state[e],this.emit("change",{key:e,value:void 0})}clear(){this.logger.debug("[Store] clear",this.state),this.state={appId:this.state.appId,typeximBrowserFingerprint:this.state.typeximBrowserFingerprint},this.emit("clear",void 0)}setWithSession(e,t){this.logger.debug("[Store] setWithSession:",e,t),this.set(e,t),sessionStorage.setItem(e,JSON.stringify(t))}getWithSession(e){if(this.logger.debug("[Store] getWithSession:",e,this.state[e]),this.state[e])return this.state[e];const t=sessionStorage.getItem(e);return t?JSON.parse(t):void 0}removeWithSession(e){this.logger.debug("[Store] removeWithSession:",e,this.state[e]),sessionStorage.removeItem(e),this.remove(e)}onChange(e){this.on("change",e)}offChange(e){this.off("change",e)}onClear(e){this.on("clear",e)}get appId(){return this.logger.debug("[Store] get appId",this.state.appId),this.state.appId}get ready(){return this.logger.debug("[Store] get ready",this.state.sdkReady),!!this.state.sdkReady}get deviceId(){const e=this.getWithSession(A.DEVICE_ID);return this.logger.debug("[Store] get deviceId",e),e}get currentUser(){return this.logger.debug("[Store] get currentUser",this.state.currentUser),this.state.currentUser}get currentChatId(){return this.logger.debug("[Store] get currentChatId",this.state.currentFeed?.chat_id),this.state.currentFeed?.chat_id}get currentFeed(){return this.logger.debug("[Store] get currentFeed",this.state.currentFeed),this.state.currentFeed}get sessionId(){return this.logger.debug("[Store] get sessionId",this.state.currentUser?.sessionId),this.state.currentUser?.sessionId}get browserFingerprint(){const e=this.getWithSession(A.BROWSER_FINGERPRINT);return this.logger.debug("[Store] get browserFingerprint",e),e}get tabId(){const e=this.getWithSession(A.TAB_ID);return this.logger.debug("[Store] get tabId",e),e}get connectionStatus(){return this.logger.debug("[Store] get connectionStatus",this.state.connectionStatus||exports.ConnectionStatus.INIT),this.state.connectionStatus||exports.ConnectionStatus.INIT}}class v{version;constructor(){this.version=0}increment(){this.version++}get currentVersion(){return this.version}check(e){return e===this.version}}const w="@typexim/agent-js-sdk_broadcast_channel";class k{config;logger;http;imClient=null;store;events;version;loadFeedAbortController=null;promises=new Map;constructor(e,t){this.logger=new m,this.store=new y(this.logger),this.events=new U(this.logger),this.store.set(A.APP_ID,e),this.config=t,this.version=new v,this.http=new N({baseURL:t.httpHost,developer:t.developer},{logger:this.logger,store:this.store}),this.generateTabId(),this.generateBrowserFingerprint(),this.listenBroadcastChannel()}setLogLevel(e){this.logger.setLogLevel(e)}async login(e){try{const t={...e||{}};if(!t.authToken)return p({code:exports.ChatSdkErrorCode.SDK_ERROR,msg:"Invalid param: authToken must be provided"});if(!t.userId){const e=await this.generateBrowserFingerprint();t.userId=e}const s=await this.requestDeviceId(),r=await this.innerLogin(s,t);if(!r.ok||!r.data)return this.logger.error("[InternalChatSdk] Login failed",r),p({code:r.code,msg:r.msg,msg_i18n:r.msg_i18n,status:r.status});const i={...r.data||{},sessionId:r.sessionId};if(!r.sessionId)throw this.logger.error("[InternalChatSdk] Login failed, not found sessionid"),new Error("Login failed, not found sessionid");return i.secretKey=r.data.key,await Promise.all([this.syncLoginState(i),this.connectWebSocket(r.sessionId)]),this.notifyOtherTabsLogin(),S({id:i.id,userId:t.userId,name:i.name,avatar:i.avatar,email:i.email})}catch(e){return this.handleException(e)}}async innerLogin(e,t){const s=await this.http.post("/user/token/login",{token:t.authToken,userId:t.userId,deviceId:e,avatar:t.avatar,name:t.name,email:t.email});return this.triggerUnauthorized(s),s}generateTabId(){const e=this.store.getWithSession(A.TAB_ID);if(e)return e;const t=`${this.store.appId}_${Date.now()}_${Math.random().toString(36).substring(2,15)}`;return this.store.setWithSession(A.TAB_ID,t),t}async generateBrowserFingerprint(){try{const e=this.store.getWithSession(A.BROWSER_FINGERPRINT);if(e)return this.logger.debug("[ChatSdk] generateBrowserFingerprint success from local session",e),e;const t=await _.load(),s=await t.get();return this.logger.debug("[ChatSdk] generateBrowserFingerprint success",s.visitorId),this.store.setWithSession(A.BROWSER_FINGERPRINT,s.visitorId),s.visitorId}catch(e){this.logger.info("[ChatSdk] FingerprintJS generateBrowserFingerprint Error",e);const t=`${Date.now()}_${Math.random().toString(36).substring(2,15)}`;return this.logger.debug("[ChatSdk] random generateBrowserFingerprint success",t),this.store.setWithSession(A.BROWSER_FINGERPRINT,t),t}}async loadFeed(){const e=this.version.currentVersion;this.loadFeedAbortController&&this.loadFeedAbortController.abort(),this.loadFeedAbortController=new AbortController;const t=await this.http.get("/feed",{limit:10},{signal:this.loadFeedAbortController.signal}).catch(e=>{this.logger.error("[ChatSdk] loadFeed Error",e)});this.loadFeedAbortController=null;const s=this.version.check(e);if(!t||!s)return;const r=t.data?.feed_list?.find(e=>e.chat_type===exports.ChatType.groupChat);this.triggerUnauthorized(t),t.ok&&(this.logger.debug("[ChatSdk][FEED_UPDATED] loadFeed success",r),this.store.set(A.CURRENT_FEED,r),this.events.emit(exports.ChatSdkEvent.FEED_UPDATED,r))}async syncLoginState(e){this.store.set(A.CURRENT_USER,e),this.store.set(A.SDK_READY,!0),await this.loadFeed(),this.events.emit(exports.ChatSdkEvent.SDK_READY)}syncLogoutState(){this.unlistenBroadcastChannel(),this.store.set(A.CURRENT_USER,void 0),this.store.set(A.SDK_READY,!1),this.store.set(A.CURRENT_FEED,void 0),this.events.emit(exports.ChatSdkEvent.SDK_NOT_READY)}async requestDeviceId(){const e=this.store.getWithSession(A.DEVICE_ID);if(e)return this.logger.debug("[ChatSdk] requestDeviceId success from local session",e),e;const t=await this.http.post("/device_api/device_id",{platform:"web",hash_str:this.store.browserFingerprint||""},{withCredentials:!1,ignoreWebsdkVersion:!0}).catch(e=>{this.logger.error("[ChatSdk] requestDeviceId Error",e)});if(!t?.ok||!t?.data)throw this.logger.error("[ChatSdk] requestDeviceId Error",t),new Error("requestDeviceId failed");return this.logger.debug("[ChatSdk] requestDeviceId success",t.data),this.store.setWithSession(A.DEVICE_ID,t.data),t.data}async logout(){try{if(!this.store.currentUser)return S(null);const e=await this.http.get("/user/logout");return this.triggerUnauthorized(e),e.ok?(this.syncLogoutState(),this.disconnectWebSocket(),S(null)):p({code:e.code,msg:e.msg,msg_i18n:e.msg_i18n,status:e.status})}catch(e){return this.handleException(e)}}async addGroupMember(e,t){try{if(this.assertReady(),!e)return p({code:exports.ChatSdkErrorCode.SDK_ERROR,msg:"not found chat id"});if(!t?.length)return S(null);const s=this.store.currentFeed;if(!s)return p({code:exports.ChatSdkErrorCode.SDK_ERROR,msg:"not found current feed"});const r=await this.getChatMembers(s.chat_id,s.chat_member);if(!r.ok)return p({code:r.code,msg:r.msg,msg_i18n:r.msg_i18n,status:r.status});const i=(r.data||[]).map(e=>e.user_id),n=t.filter(e=>!i.includes(e)),o=await this.addMember(n,s.chat_id);return o.ok?S(o.data):p({code:o.code,msg:o.msg,msg_i18n:o.msg_i18n,status:o.status})}catch(e){return this.handleException(e)}}async initialChat(e){try{this.assertReady();const t=this.store.currentFeed;if(!t){const t=await this.createFeed(e?.receiverIds||[],e?.name);return this.triggerUnauthorized(t),t.ok&&t.data?(this.store.set(A.CURRENT_FEED,t.data),S(t.data.chat_id)):p({code:t.code,msg:t.msg,msg_i18n:t.msg_i18n,status:t.status})}if(!e?.receiverIds?.length)return S(t.chat_id);const s=await this.addGroupMember(t.chat_id,e.receiverIds);return s.ok?S(t.chat_id):s}catch(e){return this.handleException(e)}}async getCurrentFeed(){try{return this.assertReady(),{ok:!0,data:this.store.currentFeed}}catch(e){return this.handleException(e)}}async getMessageList(e){try{this.assertReady();const t=this.store.currentFeed;if(!t)return p({code:exports.ChatSdkErrorCode.SDK_ERROR,msg:"No feed found"});const{chat_id:s,first_position:r,last_message_position:i}=t,{positions:n,nextPosition:o,hasMore:a}=(e=>{const t=[];if(e.direction===exports.RequestDirection.up){let s=e.startPosition??e.maxPosition;for(;t.length<e.limit&&s>=e.minPosition;)t.push(s),s--;const r=s>=e.minPosition;let i;return r&&(i=s),{positions:t,nextPosition:i,hasMore:r}}{let s=e.startPosition??e.minPosition;for(;t.length<e.limit&&s<=e.maxPosition;)t.push(s),s++;const r=s<=e.maxPosition;let i;return r&&(i=s),{positions:t,nextPosition:i,hasMore:r}}})({maxPosition:i,minPosition:r,startPosition:e.messagePosition,limit:e.limit,direction:e.direction??exports.RequestDirection.up});if(n.length>0){const e=await this.http.post("/message/get_by_position",{chat_position:{[s]:n}});if(this.triggerUnauthorized(e),e.ok&&e.data?.[s]){return S({hasMore:a,list:e.data[s].reverse(),nextMessagePosition:o})}return p({code:e.code,msg:e.msg,msg_i18n:e.msg_i18n,status:e.status})}return S({hasMore:!1,list:[]})}catch(e){return this.handleException(e)}}async sendMessage(e){try{this.assertReady();const t=e.messageType;switch(t){case exports.MessageType.text:return this.sendTextMessage(e);case exports.MessageType.image:return this.sendImageMessage(e);case exports.MessageType.video:return this.sendVideoMessage(e);case exports.MessageType.file:return this.sendFileMessage(e);default:return this.logger.warn("Unsupported message type: ",t),p({code:exports.ChatSdkErrorCode.SDK_ERROR,msg:`Unsupported message type: ${t}`})}}catch(e){return this.handleException(e)}}async sendTextMessage(e){const t=await this.http.post("/message/send_text",{chat_id:e.chatId,client_msg_id:e.clientMsgId,text:e.text.trim()},{needSign:!0});return this.triggerUnauthorized(t),t}async sendImageMessage(e){const t=await this.http.post("/message/send_image",{chat_id:e.chatId,client_msg_id:e.clientMsgId,object_url:e.objectUrl,width:e.width,height:e.height},{needSign:!0});return this.triggerUnauthorized(t),t}async sendVideoMessage(e){const t=await this.http.post("/message/send_video",{chat_id:e.chatId,client_msg_id:e.clientMsgId,video_url:e.objectUrl,duration_second:e.duration,image_url:e.coverUrl,width:e.width,height:e.height},{needSign:!0});return this.triggerUnauthorized(t),t}async sendFileMessage(e){const t=await this.http.post("/message/send_file",{chat_id:e.chatId,client_msg_id:e.clientMsgId,object_url:e.objectUrl,file_name:e.fileName,file_size:e.fileSize},{needSign:!0});return this.triggerUnauthorized(t),t}async uploadFile(e){const{chatId:t,fileContent:s,fileFormat:r,fileName:i,fileType:n,onUploadProgress:o}=e;if(s.size>209715200)return p({code:exports.ChatSdkErrorCode.SDK_ERROR,msg:"File size exceeds 200MB, upload failed"});const a=new FormData;a.append("file_content",s),a.append("file_type",n),a.append("file_name",i),a.append("file_format",r),a.append("chat_id",t);const h=await this.http.post("/chat/upload",a,{needSign:!1,ignoreDeveloper:!0,onUploadProgress:o,headers:{"Content-Type":"multipart/form-data"}});return this.triggerUnauthorized(h),h}async sendMessageReadReceipt(e){try{if(this.assertReady(),!e.messageIds?.length)return S(null);const t=await this.http.post("/message/read",{chat_id:e.chatId,message_ids:e.messageIds},{needSign:!0});return this.triggerUnauthorized(t),t}catch(e){return this.handleException(e)}}async markAllMessagesAsRead(e){const t=this.store.currentFeed?.unread_message_ids||[];return this.sendMessageReadReceipt({chatId:e,messageIds:t})}async recallMessage(e){try{if(this.assertReady(),!e.messageIds.length)return S(null);const t=await this.http.post("/message/remove",{chat_id:e.chatId,message_ids:e.messageIds,two_way:1},{needSign:!0});return this.triggerUnauthorized(t),t}catch(e){return this.handleException(e)}}triggerUnauthorized(e){e.ok||401!==e.status||this.events.emit(exports.ChatSdkEvent.UNAUTHORIZED)}async createFeed(e,t){const s=this.store.currentUser?.id;if(!s)return p({code:exports.ChatSdkErrorCode.SDK_ERROR,msg:"User not logged in"});if(this.promises.has(s))return this.promises.get(s);const r=this.http.post("/chat/group",{receiver_ids:e,group_type:0,name:t||`User ${this.store.currentUser?.name||this.store.currentUser?.id}`},{needSign:!0}).catch(e=>{throw e}).finally(()=>{this.promises.delete(s)});return this.promises.set(s,r),r}async getChatMembers(e,t){const s=await this.http.post("/chat/chatter_info",JSON.stringify({chatters:{[e]:t}}));return this.triggerUnauthorized(s),s}async addMember(e,t){if(!t)return p({code:exports.ChatSdkErrorCode.SDK_ERROR,msg:"not found chat id"});if(!e.length)return S(null);const s=await this.http.post("/chat/group/add_member",{user_ids:e,chat_id:t},{needSign:!0});return this.triggerUnauthorized(s),s}handlePushMessage(e){switch(this.logger.debug("handlePushMessage",e),e.type){case t.CREATE_FEED:case t.UPDATE_FEED:this.handleFeedUpdate(e);break;case t.ADD_GROUP_MEMBER:case t.DEL_GROUP_MEMBER:this.handleGroupMemberUpdate(e);break;case t.ADD_MESSAGE:this.handleAddMessage(e);break;case t.UPDATE_MESSAGE:this.handleUpdateMessage(e);break;case t.READ_MESSAGE:this.handleReadMessage(e);break;case t.KICK_OUT_DEVICE:this.handleKickOut()}}handleGroupMemberUpdate(e){e.content.chat_id===this.store.currentChatId&&this.events.emit(exports.ChatSdkEvent.GROUP_MEMBER_UPDATED,{type:e.type,chatId:e.content.chat_id,members:(e?.content?.chat_member||[]).map(e=>({avatar:e.avatar,chatId:e.chat_id,name:e.name,userId:e.user_id}))})}handleFeedUpdate(e){this.store.set(A.CURRENT_FEED,e.content),this.events.emit(exports.ChatSdkEvent.FEED_UPDATED,e.content)}async handleAddMessage(e){e.content.chat_id===this.store.currentChatId&&(await this.loadFeed(),this.events.emit(exports.ChatSdkEvent.MESSAGE_RECEIVED,e.content))}async handleUpdateMessage(e){e.content.chat_id===this.store.currentChatId&&(await this.loadFeed(),this.events.emit(exports.ChatSdkEvent.MESSAGE_UPDATED,e.content))}async handleReadMessage(e){e.content.chat_id===this.store.currentChatId&&(await this.loadFeed(),this.events.emit(exports.ChatSdkEvent.MESSAGE_RECEIPT_RECEIVED,{chatId:e.content.chat_id,messageIds:e.content.message_ids,readerUserIds:e.content.reader_ids}))}handleKickOut(){this.syncLogoutState(),this.disconnectWebSocket(),this.events.emit(exports.ChatSdkEvent.SDK_KICKOUT)}on(e,t){return this.events.on(e,t)}once(e,t){return this.events.once(e,t)}off(e,t){return this.events.off(e,t)}get currentUserId(){return this.logger.debug("[InternalChatSdk] get currentUserId==>",this.store.currentUser),this.store.currentUser?.id}get currentChatId(){return this.logger.debug("[InternalChatSdk] get currentChatId==>",this.store.currentChatId),this.store.currentChatId}get isReady(){return this.logger.debug("[InternalChatSdk] get isReady==>",this.store.ready),this.store.ready}listenBroadcastChannel(){new BroadcastChannel(w).onmessage=e=>{const t=this.store.appId,r=this.store.tabId;e.data.type===s.KICK_OUT&&e.data.appId===t&&e.data.tabId!==r&&(this.logger.debug("[BroadcastChannel] message: kick out",{appId:t,sourceTabId:e.data.tabId,currentTabId:r}),this.handleKickOut())}}unlistenBroadcastChannel(){new BroadcastChannel(w).close()}notifyOtherTabsLogin(){new BroadcastChannel(w).postMessage({type:s.KICK_OUT,appId:this.store.appId,tabId:this.store.tabId})}async connectWebSocket(e){if(!e)throw Error("connect websocket error, not found login user token");this.imClient=new M({token:e,wsUrl:`${this.config.websocketHost}/ws`},this.logger),this.imClient.on(D.STATUS_CHANGE,e=>{this.store.set(A.CONNECTION_STATUS,e),this.events.emit(exports.ChatSdkEvent.CONNECTION_STATUS_CHANGE,e)}),this.imClient.on(D.OPEN,()=>{this.store.set(A.IS_CONNECTED,!0)}),this.imClient.on(D.KICK_OFF,()=>{this.store.set(A.IS_CONNECTED,!1)}),this.imClient.on(D.CLOSE,()=>{this.store.set(A.IS_CONNECTED,!1)}),this.imClient.on(D.MESSAGE,e=>{this.handlePushMessage(e)}),this.imClient.connect()}disconnectWebSocket(){this.imClient&&(this.imClient.disconnect(),this.imClient=null)}assertReady(){if(!this.store.ready)throw{code:exports.ChatSdkErrorCode.SDK_ERROR,msg:"sdk not ready"}}handleException(e){return this.logger.error("[ChatSDK Error]",e),{ok:!1,code:e.code||exports.ChatSdkErrorCode.SDK_ERROR,msg:e.msg||e.message||"sdk error"}}}const G=new Map;function x(e){return{setLogLevel(t){e.setLogLevel(t)},login:t=>e.login(t),logout:()=>e.logout(),initialChat:t=>e.initialChat(t),addGroupMember:(t,s)=>e.addGroupMember(t,s),getCurrentFeed:()=>e.getCurrentFeed(),getMessageList:t=>e.getMessageList(t),uploadFile:t=>e.uploadFile(t),sendMessage:t=>e.sendMessage(t),sendMessageReadReceipt:t=>e.sendMessageReadReceipt(t),markAllMessagesAsRead:t=>e.markAllMessagesAsRead(t),recallMessage:t=>e.recallMessage(t),get currentUserId(){return e.currentUserId},get currentChatId(){return e.currentChatId},get isReady(){return e.isReady},on:(t,s)=>e.on(t,s),once:(t,s)=>e.once(t,s),off:(t,s)=>e.off(t,s)}}var F={create:function(e,t){if(G.has(e))return x(G.get(e));const s=new k(e,t);return G.set(e,s),x(s)}};exports.default=F;
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e,t,s,r,n,i,o,a,c,h,d,E,g,u=require("crypto-js"),l=require("axios"),p=require("@fingerprintjs/fingerprintjs");function _(e){return{ok:!1,code:e.code||exports.ChatSdkErrorCode.SDK_ERROR,status:e.status,msg:e.msg||"sdk error",msg_i18n:e.msg_i18n}}function S(e){return{ok:!0,data:e}}!function(e){e[e.KICK_OFF=4001]="KICK_OFF"}(e||(e={})),function(e){e[e.CREATE_FEED=0]="CREATE_FEED",e[e.UPDATE_FEED=1]="UPDATE_FEED",e[e.ADD_MESSAGE=2]="ADD_MESSAGE",e[e.UPDATE_MESSAGE=3]="UPDATE_MESSAGE",e[e.UPDATE_USER_DATA=4]="UPDATE_USER_DATA",e[e.USER_LOGIN=5]="USER_LOGIN",e[e.READ_MESSAGE=6]="READ_MESSAGE",e[e.PONG_MESSAGE=8]="PONG_MESSAGE",e[e.DELETE_MESSAGE=9]="DELETE_MESSAGE",e[e.UPDATE_GROUP=12]="UPDATE_GROUP",e[e.DELETE_GROUP=13]="DELETE_GROUP",e[e.UPDATE_LOGIN_USER=17]="UPDATE_LOGIN_USER",e[e.UPDATE_MESSAGE_REACTION=19]="UPDATE_MESSAGE_REACTION",e[e.ADD_GROUP_MEMBER=21]="ADD_GROUP_MEMBER",e[e.DEL_GROUP_MEMBER=22]="DEL_GROUP_MEMBER",e[e.ADD_CONTACTS=23]="ADD_CONTACTS",e[e.UPDATE_CONTACTS=24]="UPDATE_CONTACTS",e[e.DEL_CONTACTS=25]="DEL_CONTACTS",e[e.BLOCK_USER=26]="BLOCK_USER",e[e.DEVICE_CODE=27]="DEVICE_CODE",e[e.MSG_OPEN_CLOCK=28]="MSG_OPEN_CLOCK",e[e.DELETE_SECRET_CHAT=29]="DELETE_SECRET_CHAT",e[e.DELETE_FEED=30]="DELETE_FEED",e[e.FAVORITE_UPDATE=31]="FAVORITE_UPDATE",e[e.STICKERS_UPDATE=32]="STICKERS_UPDATE",e[e.CUSTOM_STICKERS_UPDATE=33]="CUSTOM_STICKERS_UPDATE",e[e.MANAGE_DEVICE_UPDATE=34]="MANAGE_DEVICE_UPDATE",e[e.MASS_MESSAGE_UPDATE=35]="MASS_MESSAGE_UPDATE",e[e.CHAT_WALLPAPER_DELETE=36]="CHAT_WALLPAPER_DELETE",e[e.CHAT_WALLPAPER_ADD=37]="CHAT_WALLPAPER_ADD",e[e.CONTACT_REQUEST=40]="CONTACT_REQUEST",e[e.USER_PREFERENCE_CHANGE=38]="USER_PREFERENCE_CHANGE",e[e.UPDATE_GROUP_PIN=41]="UPDATE_GROUP_PIN",e[e.RTC_CANCEL=46]="RTC_CANCEL",e[e.ADD_FEED_FOLDER=43]="ADD_FEED_FOLDER",e[e.UPDATE_FEED_FOLDER=44]="UPDATE_FEED_FOLDER",e[e.UPDATE_FOLDER_FEED_LIST=47]="UPDATE_FOLDER_FEED_LIST",e[e.DELETE_FEED_FOLDER=45]="DELETE_FEED_FOLDER",e[e.UPDATE_CHATTER=42]="UPDATE_CHATTER",e[e.PAPER_KEY=48]="PAPER_KEY",e[e.PAPER_KEY_LOG=49]="PAPER_KEY_LOG",e[e.USER_LOGIN_SCAN=50]="USER_LOGIN_SCAN",e[e.RTC_RINGING=51]="RTC_RINGING",e[e.ON_UPDATE_PRIVATE_SETTING=52]="ON_UPDATE_PRIVATE_SETTING",e[e.ON_DELETE_PRIVATE_SETTING=53]="ON_DELETE_PRIVATE_SETTING",e[e.ON_UPDATE_LOGIN_PRIVATE_SETTING=54]="ON_UPDATE_LOGIN_PRIVATE_SETTING",e[e.PUSH_LIVE_MESSAGE=56]="PUSH_LIVE_MESSAGE",e[e.BIG_PACKAGE_PUSH=126]="BIG_PACKAGE_PUSH",e[e.KICK_OUT_DEVICE=127]="KICK_OUT_DEVICE",e[e.CLEAR_HISTORY=128]="CLEAR_HISTORY",e[e.CLEAR_DATA=255]="CLEAR_DATA"}(t||(t={})),function(e){e[e.KICK_OUT=0]="KICK_OUT"}(s||(s={})),exports.ConnectionStatus=void 0,(r=exports.ConnectionStatus||(exports.ConnectionStatus={})).INIT="INIT",r.CONNECTING="CONNECTING",r.CONNECTED="CONNECTED",r.DISCONNECTED="DISCONNECTED",r.CLOSED="CLOSED",function(e){e.OPEN="OPEN",e.ERROR="ERROR",e.CLOSE="CLOSE",e.MESSAGE="MESSAGE",e.STATUS_CHANGE="STATUS_CHANGE"}(n||(n={})),exports.ChatType=void 0,(i=exports.ChatType||(exports.ChatType={}))[i.singleChat=1]="singleChat",i[i.groupChat=2]="groupChat",exports.MessageKind=void 0,(o=exports.MessageKind||(exports.MessageKind={}))[o.normal=0]="normal",o[o.system=1]="system",exports.MessageType=void 0,(a=exports.MessageType||(exports.MessageType={}))[a.text=0]="text",a[a.image=1]="image",a[a.audio=3]="audio",a[a.video=4]="video",a[a.file=5]="file",a[a.mergeForward=6]="mergeForward",a[a.sticker=7]="sticker",a[a.richText=8]="richText",a[a.contact=9]="contact",a[a.communication=10]="communication",a[a.mixedImageText=11]="mixedImageText",a[a.custom=13]="custom",a[a.luckyGift=14]="luckyGift",a[a.fileGroup=15]="fileGroup",a[a.cardMsg=16]="cardMsg",exports.MessageOperation=void 0,(c=exports.MessageOperation||(exports.MessageOperation={}))[c.normal=0]="normal",c[c.recall=1]="recall",exports.ChatSdkErrorCode=void 0,(h=exports.ChatSdkErrorCode||(exports.ChatSdkErrorCode={}))[h.NETWORK_ERROR=-1e4]="NETWORK_ERROR",h[h.SDK_ERROR=-10001]="SDK_ERROR",h[h.SERVER_ERROR=-10002]="SERVER_ERROR",exports.ChatSdkEvent=void 0,(d=exports.ChatSdkEvent||(exports.ChatSdkEvent={})).SDK_READY="SDK_READY",d.SDK_NOT_READY="SDK_NOT_READY",d.SDK_KICKOUT="SDK_KICKOUT",d.FEED_UPDATED="FEED_UPDATED",d.MESSAGE_RECEIVED="MESSAGE_RECEIVED",d.MESSAGE_UPDATED="MESSAGE_UPDATED",d.MESSAGE_RECEIPT_RECEIVED="MESSAGE_RECEIPT_RECEIVED",d.CONNECTION_STATUS_CHANGE="CONNECTION_STATUS_CHANGE",d.UNAUTHORIZED="UNAUTHORIZED",d.GROUP_MEMBER_UPDATED="GROUP_MEMBER_UPDATED",exports.RequestDirection=void 0,(E=exports.RequestDirection||(exports.RequestDirection={}))[E.up=0]="up",E[E.down=1]="down",exports.GroupMemberUpdateType=void 0,(g=exports.GroupMemberUpdateType||(exports.GroupMemberUpdateType={}))[g.ADD_GROUP_MEMBER=21]="ADD_GROUP_MEMBER",g[g.DEL_GROUP_MEMBER=22]="DEL_GROUP_MEMBER";const C="[TYPEX_AGENT_JS_SDK]";class m{level=0;setLogLevel(e){this.level=e}getLogLevel(){return this.level}shouldPrint(e){return e>=this.level}debug(...e){this.shouldPrint(0)&&console.debug(`${C}[DEBUG]`,...e)}info(...e){this.shouldPrint(0)&&console.info(`${C}[INFO]`,...e)}warn(...e){this.shouldPrint(1)&&console.warn(`${C}[WARN]`,...e)}error(...e){this.shouldPrint(2)&&console.error(`${C}[ERROR]`,...e)}}function R(e){return(new TextEncoder).encode(e).buffer}async function T(e,t){return window.crypto&&window.crypto.subtle?await async function(e,t){const s=R(t),r=R(e),n=await crypto.subtle.importKey("raw",s,{name:"HMAC",hash:{name:"SHA-256"}},!1,["sign"]),i=await crypto.subtle.sign("HMAC",n,r);return Array.from(new Uint8Array(i)).map(e=>e.toString(16).padStart(2,"0")).join("")}(e,t):function(e,t){const s=u.HmacSHA256(e,t);return u.enc.Hex.stringify(s)}(e,t)}const I=e=>{if(null==e)return"";if("object"!=typeof e||Array.isArray(e)){if(Array.isArray(e)){let t="";for(const s of e)t+=I(s);return t}return"string"==typeof e?e:String(e)}{const t=Object.keys(e).sort();let s="";for(const r of t)s+=I(e[r]);return s}},D="api-coco.typex.im",A=e=>e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),O=e=>new RegExp(`https?:\\\\?/\\\\?/${A(e)}(?:\\\\.|[^"\\\\\\s])*`,"g"),f=(e,t,s)=>{if(!e||"string"!=typeof e)return e;const r=O(t);return e.replace(r,e=>{const t=(e=>{try{return JSON.parse(`"${e}"`)}catch{return e}})(e),r=s(t);return"string"!=typeof r||r===t?e:(n=r,JSON.stringify(n).slice(1,-1));var n})},N=(e,t,s=D)=>f(e,s,e=>((e,t,s)=>{const r=encodeURIComponent(t),n=encodeURIComponent(s),i=e.indexOf("#"),o=i>=0?e.slice(0,i):e,a=i>=0?e.slice(i):"",c=new RegExp(`([?&])${A(r)}=[^&#]*`);if(c.test(o))return o.replace(c,`$1${r}=${n}`)+a;const h=o.includes("?")?"&":"?";return`${o}${h}${r}=${n}${a}`})(e,"xsid",t));var U,b,P="1.0.25";class y{instance;developer;logger;store;constructor(e,t){this.logger=t.logger,this.store=t.store,this.developer=e.developer;const s=e.baseURL.replace(/\/$/,"");this.instance=l.create({baseURL:s,headers:{...e.defaultHeaders??{}},timeout:e.timeout??3e4,withCredentials:!0}),this.setupInterceptors()}setupInterceptors(){this.instance.interceptors.request.use(e=>(e.headers=e.headers||{},e.headers["Content-Type"]||(e.headers["Content-Type"]="application/json"),e.headers.Platform="web",e.headers.AppID=this.store.appId,e.withCredentials&&(e.headers["X-Sid"]=this.store.sessionId),e.ignoreWebsdkVersion||(e.headers["X-Websdk-Version"]=P),this.developer&&!e.ignoreDeveloper&&(e.headers["x-developer"]=this.developer),e)),this.instance.interceptors.response.use(e=>{const t=e.headers["x-sid"];return t&&(e.data.sessionId=t),e},e=>Promise.reject(e))}async get(e,t={},s={}){return this.request({url:e,method:"GET",params:t,...s})}async post(e,t,s={}){return this.request({url:e,method:"POST",data:t,...s})}async request(e){try{const{needSign:t,...s}=e;if(t&&"POST"===s.method?.toUpperCase()&&s.data){const t=this.store.currentUser;if(!t){const e="[HttpClient] HttpClient needs make sign but not found login user";return this.logger.error(e),_({code:exports.ChatSdkErrorCode.SDK_ERROR,msg:e})}try{const r=await(async(e,t)=>{const s=I(e);return await T(s,t)})(s.data,t.secretKey);e.headers||(e.headers={}),e.headers.sign=r}catch(e){const t=`[HttpClient] HttpClient make sign error: ${e.message}`;return this.logger.error(t),_({code:exports.ChatSdkErrorCode.SDK_ERROR,msg:t})}}const r=await this.instance.request({...s,headers:{...e.headers||{}}}),n=r.data;return 0!==n.code?(this.logger.error("[HttpClient]","Business server response error:",r),{ok:!1,code:n.code,msg:n.msg,msg_i18n:n.msg_i18n}):n.sessionId?{ok:!0,sessionId:n.sessionId,data:n.data}:{ok:!0,data:n.data}}catch(e){return this.handleError(e)}}handleError(e){return 200!==e.response?.status?{ok:!1,code:exports.ChatSdkErrorCode.SERVER_ERROR,status:e.response?.status,msg:e.message||"server error"}:"ECONNABORTED"===e.code?{ok:!1,code:exports.ChatSdkErrorCode.NETWORK_ERROR,msg:e.message||"request timeout"}:{ok:!1,code:exports.ChatSdkErrorCode.NETWORK_ERROR,msg:e.message||"network error"}}}class M{listeners=new Map;logger;constructor(e){this.logger=e}on(e,t){this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t)}once(e,t){const s=r=>{t(r),this.off(e,s)};this.on(e,s)}off(e,t){this.listeners.has(e)&&(t?this.listeners.get(e).delete(t):this.listeners.delete(e))}emit(e,t){if(this.listeners.has(e))for(const s of this.listeners.get(e))try{s(t)}catch(t){this.logger.error(`[EventCore] handler error on "${String(e)}":`,t)}}clear(){this.listeners.clear()}}class w extends M{ws;options;status=exports.ConnectionStatus.INIT;constructor(e,t){super(t),this.options=e}connect(){if(this.status===exports.ConnectionStatus.CONNECTING||this.status===exports.ConnectionStatus.CONNECTED)return void this.logger.debug("[CONNECTION]","WebSocket is connecting or connected,current connect status is",`[${this.status}]`);this.logger.debug("[CONNECTION][connect]","WebSocket is connecting"),this.setStatus(exports.ConnectionStatus.CONNECTING);const e=new WebSocket(`${this.options.url}?token=${this.options.token}&platform=web`);this.ws=e,e.onopen=()=>{this.logger.debug("[CONNECTION][ws.onopen]","WebSocket is connected"),this.setStatus(exports.ConnectionStatus.CONNECTED),this.emit(n.OPEN)},e.onmessage=e=>{this.logger.debug("[CONNECTION][ws.onmessage]","WebSocket received a message",e.data),this.emit(n.MESSAGE,e.data)},e.onerror=e=>{this.logger.error("[CONNECTION][ws.onerror]","WebSocket connect error",e),this.emit(n.ERROR,e)},e.onclose=e=>{this.logger.debug("[CONNECTION][ws.onclose]","WebSocket connect be closed",e),this.setStatus(exports.ConnectionStatus.DISCONNECTED),this.emit(n.CLOSE,e)}}close(){this.ws?.close(),this.ws=void 0,this.setStatus(exports.ConnectionStatus.CLOSED)}send(e){if(this.status!==exports.ConnectionStatus.CONNECTED)throw new Error("WebSocket is not connected");this.ws.send(e)}getStatus(){return this.status}setStatus(e){this.status!==e&&(this.logger.debug("[CONNECTION][setStatus]","WebSocket status changed",this.status,"->",e),this.status=e,this.emit(n.STATUS_CHANGE,e))}}class v{connection;pingTimeout;pongTimeout;pingTimer;pongTimer;logger;constructor(e,t,s={}){this.connection=e,this.pingTimeout=s.pingTimeout??3e4,this.pongTimeout=s.pongTimeout??2e4,this.logger=t}ping(e){this.logger.debug("[Heartbeat]","Heartbeat ping"),this.stop(),this.pingTimer=window.setTimeout(()=>{try{this.connection.send(JSON.stringify({type:0})),this.logger.debug("[Heartbeat]","Heartbeat send PING"),this.pong(e)}catch{}},this.pingTimeout)}pong(e){clearTimeout(this.pongTimer),this.pongTimer=window.setTimeout(()=>{e?.(),this.logger.debug("[Heartbeat]","PING timeout, called PING/PONG callback")},this.pongTimeout)}stop(){this.logger.debug("[Heartbeat]","Heartbeat stop"),clearTimeout(this.pingTimer),clearTimeout(this.pongTimer),this.pingTimer=void 0,this.pongTimer=void 0}}class k{connection;baseInterval=1e3;maxAttempts=1/0;attempts=0;timer;enabled=!1;logger;constructor(e,t,s={}){this.logger=t,this.connection=e,s.baseInterval&&(this.baseInterval=s.baseInterval),s.maxAttempts&&(this.maxAttempts=s.maxAttempts),this.bindEvents()}bindEvents(){this.connection.on(n.CLOSE,()=>{this.enabled&&this.scheduleReconnect()}),this.connection.on(n.OPEN,()=>{this.reset()})}start(){this.logger.debug("[Reconnector]","Reconnector start"),this.enabled=!0}stop(){this.logger.debug("[Reconnector]","Reconnector stop"),this.enabled=!1,this.clearTimer()}scheduleReconnect(){if(this.logger.debug("[Reconnector]",`Reconnector scheduleReconnect, attempts: ${this.attempts}, maxAttempts: ${this.maxAttempts}`),this.attempts>=this.maxAttempts)return;this.attempts++;const e=this.baseInterval*Math.min(this.attempts,10);this.clearTimer(),this.timer=window.setTimeout(()=>{this.connection.connect()},e)}reset(){this.logger.debug("[Reconnector]","Reconnector reset"),this.attempts=0,this.clearTimer()}clearTimer(){this.timer&&(clearTimeout(this.timer),this.timer=void 0)}}!function(e){e.OPEN="OPEN",e.ERROR="ERROR",e.CLOSE="CLOSE",e.MESSAGE="MESSAGE",e.STATUS_CHANGE="STATUS_CHANGE",e.KICK_OFF="KICK_OFF"}(U||(U={}));class x extends M{connection;reconnector;heartbeat;pongTimeoutCount=0;offlineReconnectTimer;constructor(e,t){super(t),this.connection=new w({url:e.wsUrl,token:e.token},t),this.reconnector=new k(this.connection,t),this.heartbeat=new v(this.connection,t),this.bindEvents()}connect(){this.reconnector.start(),this.connection.connect()}disconnect(){this.reconnector.stop(),this.heartbeat.stop(),this.connection.close()}startPing(){this.heartbeat.ping(()=>{if(this.logger.warn("[IMClient][Heartbeat]","PONG timeout, current pong timeout count: ",this.pongTimeoutCount),this.pongTimeoutCount++,this.pongTimeoutCount>=2){this.disconnect();const e=setTimeout(()=>{this.connect(),clearTimeout(e)},1e4);return}this.startPing()})}bindEvents(){this.connection.on(n.OPEN,()=>{this.emit(U.OPEN),this.offlineReconnectTimer&&(clearTimeout(this.offlineReconnectTimer),this.offlineReconnectTimer=void 0),this.startPing()}),this.connection.on(n.CLOSE,t=>{if(t.code===e.KICK_OFF)return this.logger.warn("[IMClient][CLOSE][KICK_OFF]","You has been kicked off"),this.emit(U.KICK_OFF),void this.disconnect();this.emit(U.CLOSE)}),this.connection.on(n.MESSAGE,e=>{this.handleRawMessage(e)}),this.connection.on(n.STATUS_CHANGE,e=>{this.emit(U.STATUS_CHANGE,e)}),this.connection.on(n.ERROR,e=>{this.emit(U.ERROR,e)}),"undefined"!=typeof window&&(window.addEventListener("offline",()=>{if(this.offlineReconnectTimer)return;this.connection.close();const e=()=>{if(this.connection.getStatus()===exports.ConnectionStatus.CONNECTED)return this.offlineReconnectTimer&&clearTimeout(this.offlineReconnectTimer),void(this.offlineReconnectTimer=void 0);this.connection.connect(),this.offlineReconnectTimer=window.setTimeout(e,1e3)};e()}),window.addEventListener("online",()=>{this.offlineReconnectTimer&&(clearTimeout(this.offlineReconnectTimer),this.offlineReconnectTimer=void 0),this.connection.connect()}))}handleRawMessage(e){try{const s=JSON.parse(e);if(s.type===t.PONG_MESSAGE?this.startPing():this.sendAck(s.id),s.type===t.BIG_PACKAGE_PUSH)for(const e of s.content.big_push)this.emit(U.MESSAGE,e);else this.emit(U.MESSAGE,s)}catch(e){this.logger.error("[IMClient][handleRawMessage]","Message raw data json.parse error",e),this.emit(U.ERROR,e)}}sendAck(e){this.connection.send(JSON.stringify({type:1,ids:[e]}))}}!function(e){e.APP_ID="appId",e.CURRENT_USER="currentUser",e.CURRENT_FEED="currentFeed",e.SDK_READY="sdkReady",e.IS_CONNECTED="isConnected",e.CONNECTION_STATUS="connectionStatus",e.DEVICE_ID="typeximDeviceId",e.BROWSER_FINGERPRINT="typeximBrowserFingerprint",e.TAB_ID="typeximTabId",e.CROSS_SITE_COOKIE_BLOCKED="typeximCrossSiteCookieBlocked"}(b||(b={}));class G extends M{state={};constructor(e){super(e)}set(e,t){this.logger.debug("[Store] set:",e,t),this.state[e]=t,this.emit("change",{key:e,value:t})}get(e){return this.logger.debug("[Store] get:",e,this.state[e]),this.state[e]}remove(e){this.logger.debug("[Store] remove:",e,this.state[e]),delete this.state[e],this.emit("change",{key:e,value:void 0})}clear(){this.logger.debug("[Store] clear",this.state),this.state={appId:this.state.appId,typeximBrowserFingerprint:this.state.typeximBrowserFingerprint},this.emit("clear",void 0)}setWithSession(e,t){this.logger.debug("[Store] setWithSession:",e,t),this.set(e,t),sessionStorage.setItem(e,JSON.stringify(t))}getWithSession(e){if(this.logger.debug("[Store] getWithSession:",e,this.state[e]),this.state[e])return this.state[e];const t=sessionStorage.getItem(e);return t?JSON.parse(t):void 0}removeWithSession(e){this.logger.debug("[Store] removeWithSession:",e,this.state[e]),sessionStorage.removeItem(e),this.remove(e)}onChange(e){this.on("change",e)}offChange(e){this.off("change",e)}onClear(e){this.on("clear",e)}get appId(){return this.logger.debug("[Store] get appId",this.state.appId),this.state.appId}get ready(){return this.logger.debug("[Store] get ready",this.state.sdkReady),!!this.state.sdkReady}get deviceId(){const e=this.getWithSession(b.DEVICE_ID);return this.logger.debug("[Store] get deviceId",e),e}get currentUser(){return this.logger.debug("[Store] get currentUser",this.state.currentUser),this.state.currentUser}get currentChatId(){return this.logger.debug("[Store] get currentChatId",this.state.currentFeed?.chat_id),this.state.currentFeed?.chat_id}get currentFeed(){return this.logger.debug("[Store] get currentFeed",this.state.currentFeed),this.state.currentFeed}get sessionId(){return this.logger.debug("[Store] get sessionId",this.state.currentUser?.sessionId),this.state.currentUser?.sessionId}get browserFingerprint(){const e=this.getWithSession(b.BROWSER_FINGERPRINT);return this.logger.debug("[Store] get browserFingerprint",e),e}get tabId(){const e=this.getWithSession(b.TAB_ID);return this.logger.debug("[Store] get tabId",e),e}get connectionStatus(){return this.logger.debug("[Store] get connectionStatus",this.state.connectionStatus||exports.ConnectionStatus.INIT),this.state.connectionStatus||exports.ConnectionStatus.INIT}}class F{version;constructor(){this.version=0}increment(){this.version++}get currentVersion(){return this.version}check(e){return e===this.version}}const L="@typexim/agent-js-sdk_broadcast_channel";class K{config;logger;http;imClient=null;store;events;version;loadFeedAbortController=null;promises=new Map;constructor(e,t){this.logger=new m,this.store=new G(this.logger),this.events=new M(this.logger),this.store.set(b.APP_ID,e),this.config=t,this.version=new F,this.http=new y({baseURL:t.httpHost,developer:t.developer},{logger:this.logger,store:this.store}),this.generateTabId(),this.generateBrowserFingerprint(),this.listenBroadcastChannel()}setLogLevel(e){this.logger.setLogLevel(e)}async login(e){try{const t={...e||{}};if(!t.authToken)return _({code:exports.ChatSdkErrorCode.SDK_ERROR,msg:"Invalid param: authToken must be provided"});if(!t.userId){const e=await this.generateBrowserFingerprint();t.userId=e}const s=await this.requestDeviceId(),r=await this.innerLogin(s,t);if(!r.ok||!r.data)return this.logger.error("[InternalChatSdk] Login failed",r),_({code:r.code,msg:r.msg,msg_i18n:r.msg_i18n,status:r.status});const n={...r.data||{},sessionId:r.sessionId};if(!r.sessionId)throw this.logger.error("[InternalChatSdk] Login failed, not found sessionid"),new Error("Login failed, not found sessionid");return n.secretKey=r.data.key,await Promise.all([this.syncLoginState(n),this.connectWebSocket(r.sessionId)]),this.notifyOtherTabsLogin(),S({id:n.id,userId:t.userId,name:n.name,avatar:n.avatar,email:n.email})}catch(e){return this.handleException(e)}}async innerLogin(e,t){const s=await this.http.post("/user/token/login",{token:t.authToken,userId:t.userId,deviceId:e,avatar:t.avatar,name:t.name,email:t.email});return this.triggerUnauthorized(s),s}generateTabId(){const e=this.store.getWithSession(b.TAB_ID);if(e)return e;const t=`${this.store.appId}_${Date.now()}_${Math.random().toString(36).substring(2,15)}`;return this.store.setWithSession(b.TAB_ID,t),t}async generateBrowserFingerprint(){try{const e=this.store.getWithSession(b.BROWSER_FINGERPRINT);if(e)return this.logger.debug("[ChatSdk] generateBrowserFingerprint success from local session",e),e;const t=await p.load(),s=await t.get();return this.logger.debug("[ChatSdk] generateBrowserFingerprint success",s.visitorId),this.store.setWithSession(b.BROWSER_FINGERPRINT,s.visitorId),s.visitorId}catch(e){this.logger.info("[ChatSdk] FingerprintJS generateBrowserFingerprint Error",e);const t=`${Date.now()}_${Math.random().toString(36).substring(2,15)}`;return this.logger.debug("[ChatSdk] random generateBrowserFingerprint success",t),this.store.setWithSession(b.BROWSER_FINGERPRINT,t),t}}async loadFeed(){const e=this.version.currentVersion;this.loadFeedAbortController&&this.loadFeedAbortController.abort(),this.loadFeedAbortController=new AbortController;const t=await this.http.get("/feed",{limit:10},{signal:this.loadFeedAbortController.signal}).catch(e=>{this.logger.error("[ChatSdk] loadFeed Error",e)});this.loadFeedAbortController=null;const s=this.version.check(e);if(!t||!s)return;const r=t.data?.feed_list?.find(e=>e.chat_type===exports.ChatType.groupChat);this.triggerUnauthorized(t),t.ok&&(this.logger.debug("[ChatSdk][FEED_UPDATED] loadFeed success",r),this.store.set(b.CURRENT_FEED,r),this.events.emit(exports.ChatSdkEvent.FEED_UPDATED,r))}async syncLoginState(e){this.store.set(b.CURRENT_USER,e),this.store.set(b.SDK_READY,!0),await this.loadFeed(),this.events.emit(exports.ChatSdkEvent.SDK_READY)}syncLogoutState(){this.unlistenBroadcastChannel(),this.store.set(b.CURRENT_USER,void 0),this.store.set(b.SDK_READY,!1),this.store.set(b.CURRENT_FEED,void 0),this.events.emit(exports.ChatSdkEvent.SDK_NOT_READY)}async requestDeviceId(){const e=this.store.getWithSession(b.DEVICE_ID);if(e)return this.logger.debug("[ChatSdk] requestDeviceId success from local session",e),e;const t=await this.http.post("/device_api/device_id",{platform:"web",hash_str:this.store.browserFingerprint||""},{withCredentials:!1,ignoreWebsdkVersion:!0}).catch(e=>{this.logger.error("[ChatSdk] requestDeviceId Error",e)});if(!t?.ok||!t?.data)throw this.logger.error("[ChatSdk] requestDeviceId Error",t),new Error("requestDeviceId failed");return this.logger.debug("[ChatSdk] requestDeviceId success",t.data),this.store.setWithSession(b.DEVICE_ID,t.data),t.data}async logout(){try{if(!this.store.currentUser)return S(null);const e=await this.http.get("/user/logout");return this.triggerUnauthorized(e),e.ok?(this.syncLogoutState(),this.disconnectWebSocket(),S(null)):_({code:e.code,msg:e.msg,msg_i18n:e.msg_i18n,status:e.status})}catch(e){return this.handleException(e)}}async addGroupMember(e,t){try{if(this.assertReady(),!e)return _({code:exports.ChatSdkErrorCode.SDK_ERROR,msg:"not found chat id"});if(!t?.length)return S(null);const s=this.store.currentFeed;if(!s)return _({code:exports.ChatSdkErrorCode.SDK_ERROR,msg:"not found current feed"});const r=await this.getChatMembers(s.chat_id,s.chat_member);if(!r.ok)return _({code:r.code,msg:r.msg,msg_i18n:r.msg_i18n,status:r.status});const n=(r.data||[]).map(e=>e.user_id),i=t.filter(e=>!n.includes(e)),o=await this.addMember(i,s.chat_id);return o.ok?S(o.data):_({code:o.code,msg:o.msg,msg_i18n:o.msg_i18n,status:o.status})}catch(e){return this.handleException(e)}}async initialChat(e){try{this.assertReady();const t=this.store.currentFeed;if(!t){const t=await this.createFeed(e?.receiverIds||[],e?.name);return this.triggerUnauthorized(t),t.ok&&t.data?(this.store.set(b.CURRENT_FEED,t.data),S(t.data.chat_id)):_({code:t.code,msg:t.msg,msg_i18n:t.msg_i18n,status:t.status})}if(!e?.receiverIds?.length)return S(t.chat_id);const s=await this.addGroupMember(t.chat_id,e.receiverIds);return s.ok?S(t.chat_id):s}catch(e){return this.handleException(e)}}async getCurrentFeed(){try{return this.assertReady(),{ok:!0,data:this.store.currentFeed}}catch(e){return this.handleException(e)}}async getMessageList(e){try{this.assertReady();const t=this.store.currentFeed;if(!t)return _({code:exports.ChatSdkErrorCode.SDK_ERROR,msg:"No feed found"});const{chat_id:s,first_position:r,last_message_position:n}=t,{positions:i,nextPosition:o,hasMore:a}=(e=>{const t=[];if(e.direction===exports.RequestDirection.up){let s=e.startPosition??e.maxPosition;for(;t.length<e.limit&&s>=e.minPosition;)t.push(s),s--;const r=s>=e.minPosition;let n;return r&&(n=s),{positions:t,nextPosition:n,hasMore:r}}{let s=e.startPosition??e.minPosition;for(;t.length<e.limit&&s<=e.maxPosition;)t.push(s),s++;const r=s<=e.maxPosition;let n;return r&&(n=s),{positions:t,nextPosition:n,hasMore:r}}})({maxPosition:n,minPosition:r,startPosition:e.messagePosition,limit:e.limit,direction:e.direction??exports.RequestDirection.up});if(i.length>0){const e=await this.http.post("/message/get_by_position",{chat_position:{[s]:i}});if(this.triggerUnauthorized(e),e.ok&&e.data?.[s]){return S({hasMore:a,list:await this.processMessageListResourceAuth(e.data[s].reverse()),nextMessagePosition:o})}return _({code:e.code,msg:e.msg,msg_i18n:e.msg_i18n,status:e.status})}return S({hasMore:!1,list:[]})}catch(e){return this.handleException(e)}}async processMessageListResourceAuth(e){if(!e.length)return e;if(!await this.detectNeedAppendXsidBySessionCache(e))return e;const t=this.store.sessionId;return t?e.map(e=>{if(!e.content||"string"!=typeof e.content)return e;const s=N(e.content,t,D);return s===e.content?e:{...e,content:s}}):e}async detectNeedAppendXsidBySessionCache(e){const t=this.store.getWithSession(b.CROSS_SITE_COOKIE_BLOCKED);if("boolean"==typeof t)return t;const s=this.extractFirstDomainResourceUrl(e,D);if(this.logger.debug("[ChatSdk] detectNeedAppendXsidBySessionCache probeUrl",s),!s)return!1;if(!this.isCrossSiteUrl(s))return this.store.setWithSession(b.CROSS_SITE_COOKIE_BLOCKED,!1),!1;const r=await this.probeCrossSiteCookieBlocked(s);return r&&this.logger.warn("[ChatSdk] Cross site cookie blocked, will change auth method"),this.store.setWithSession(b.CROSS_SITE_COOKIE_BLOCKED,r),r}extractFirstDomainResourceUrl(e,t){const s=O(t);for(const t of e){if(!t.content||"string"!=typeof t.content)continue;s.lastIndex=0;const e=t.content.match(s)?.[0];if(e)try{return JSON.parse(`"${e}"`)}catch{return e}}}async probeCrossSiteCookieBlocked(e){try{const t=await fetch(e,{method:"GET",credentials:"include",cache:"no-store",headers:{Range:"bytes=0-0"}});return 401===t.status||403===t.status}catch{return!1}}isCrossSiteUrl(e){try{return new URL(e,window.location.href).origin!==window.location.origin}catch{return!0}}async sendMessage(e){try{this.assertReady();const t=e.messageType;switch(t){case exports.MessageType.text:return this.sendTextMessage(e);case exports.MessageType.image:return this.sendImageMessage(e);case exports.MessageType.video:return this.sendVideoMessage(e);case exports.MessageType.file:return this.sendFileMessage(e);default:return this.logger.warn("Unsupported message type: ",t),_({code:exports.ChatSdkErrorCode.SDK_ERROR,msg:`Unsupported message type: ${t}`})}}catch(e){return this.handleException(e)}}async sendTextMessage(e){const t=await this.http.post("/message/send_text",{chat_id:e.chatId,client_msg_id:e.clientMsgId,text:e.text.trim()},{needSign:!0});return this.triggerUnauthorized(t),t}async sendImageMessage(e){const t=await this.http.post("/message/send_image",{chat_id:e.chatId,client_msg_id:e.clientMsgId,object_url:e.objectUrl,width:e.width,height:e.height},{needSign:!0});return this.triggerUnauthorized(t),t}async sendVideoMessage(e){const t=await this.http.post("/message/send_video",{chat_id:e.chatId,client_msg_id:e.clientMsgId,video_url:e.objectUrl,duration_second:e.duration,image_url:e.coverUrl,width:e.width,height:e.height},{needSign:!0});return this.triggerUnauthorized(t),t}async sendFileMessage(e){const t=await this.http.post("/message/send_file",{chat_id:e.chatId,client_msg_id:e.clientMsgId,object_url:e.objectUrl,file_name:e.fileName,file_size:e.fileSize},{needSign:!0});return this.triggerUnauthorized(t),t}async uploadFile(e){const{chatId:t,fileContent:s,fileFormat:r,fileName:n,fileType:i,onUploadProgress:o}=e;if(s.size>209715200)return _({code:exports.ChatSdkErrorCode.SDK_ERROR,msg:"File size exceeds 200MB, upload failed"});const a=new FormData;a.append("file_content",s),a.append("file_type",i),a.append("file_name",n),a.append("file_format",r),a.append("chat_id",t);const c=await this.http.post("/chat/upload",a,{needSign:!1,ignoreDeveloper:!0,onUploadProgress:o,headers:{"Content-Type":"multipart/form-data"}});return this.triggerUnauthorized(c),c}async sendMessageReadReceipt(e){try{if(this.assertReady(),!e.messageIds?.length)return S(null);const t=await this.http.post("/message/read",{chat_id:e.chatId,message_ids:e.messageIds},{needSign:!0});return this.triggerUnauthorized(t),t}catch(e){return this.handleException(e)}}async markAllMessagesAsRead(e){const t=this.store.currentFeed?.unread_message_ids||[];return this.sendMessageReadReceipt({chatId:e,messageIds:t})}async recallMessage(e){try{if(this.assertReady(),!e.messageIds.length)return S(null);const t=await this.http.post("/message/remove",{chat_id:e.chatId,message_ids:e.messageIds,two_way:1},{needSign:!0});return this.triggerUnauthorized(t),t}catch(e){return this.handleException(e)}}triggerUnauthorized(e){e.ok||401!==e.status||this.events.emit(exports.ChatSdkEvent.UNAUTHORIZED)}async createFeed(e,t){const s=this.store.currentUser?.id;if(!s)return _({code:exports.ChatSdkErrorCode.SDK_ERROR,msg:"User not logged in"});if(this.promises.has(s))return this.promises.get(s);const r=this.http.post("/chat/group",{receiver_ids:e,group_type:0,name:t||`User ${this.store.currentUser?.name||this.store.currentUser?.id}`},{needSign:!0}).catch(e=>{throw e}).finally(()=>{this.promises.delete(s)});return this.promises.set(s,r),r}async getChatMembers(e,t){const s=await this.http.post("/chat/chatter_info",JSON.stringify({chatters:{[e]:t}}));return this.triggerUnauthorized(s),s}async addMember(e,t){if(!t)return _({code:exports.ChatSdkErrorCode.SDK_ERROR,msg:"not found chat id"});if(!e.length)return S(null);const s=await this.http.post("/chat/group/add_member",{user_ids:e,chat_id:t},{needSign:!0});return this.triggerUnauthorized(s),s}handlePushMessage(e){switch(this.logger.debug("handlePushMessage",e),e.type){case t.CREATE_FEED:case t.UPDATE_FEED:this.handleFeedUpdate(e);break;case t.ADD_GROUP_MEMBER:case t.DEL_GROUP_MEMBER:this.handleGroupMemberUpdate(e);break;case t.ADD_MESSAGE:this.handleAddMessage(e);break;case t.UPDATE_MESSAGE:this.handleUpdateMessage(e);break;case t.READ_MESSAGE:this.handleReadMessage(e);break;case t.KICK_OUT_DEVICE:this.handleKickOut()}}handleGroupMemberUpdate(e){e.content.chat_id===this.store.currentChatId&&this.events.emit(exports.ChatSdkEvent.GROUP_MEMBER_UPDATED,{type:e.type,chatId:e.content.chat_id,members:(e?.content?.chat_member||[]).map(e=>({avatar:e.avatar,chatId:e.chat_id,name:e.name,userId:e.user_id}))})}handleFeedUpdate(e){this.store.set(b.CURRENT_FEED,e.content),this.events.emit(exports.ChatSdkEvent.FEED_UPDATED,e.content)}async handleAddMessage(e){e.content.chat_id===this.store.currentChatId&&(await this.loadFeed(),this.events.emit(exports.ChatSdkEvent.MESSAGE_RECEIVED,e.content))}async handleUpdateMessage(e){e.content.chat_id===this.store.currentChatId&&(await this.loadFeed(),this.events.emit(exports.ChatSdkEvent.MESSAGE_UPDATED,e.content))}async handleReadMessage(e){e.content.chat_id===this.store.currentChatId&&(await this.loadFeed(),this.events.emit(exports.ChatSdkEvent.MESSAGE_RECEIPT_RECEIVED,{chatId:e.content.chat_id,messageIds:e.content.message_ids,readerUserIds:e.content.reader_ids}))}handleKickOut(){this.syncLogoutState(),this.disconnectWebSocket(),this.events.emit(exports.ChatSdkEvent.SDK_KICKOUT)}on(e,t){return this.events.on(e,t)}once(e,t){return this.events.once(e,t)}off(e,t){return this.events.off(e,t)}get currentUserId(){return this.logger.debug("[InternalChatSdk] get currentUserId==>",this.store.currentUser),this.store.currentUser?.id}get currentChatId(){return this.logger.debug("[InternalChatSdk] get currentChatId==>",this.store.currentChatId),this.store.currentChatId}get isReady(){return this.logger.debug("[InternalChatSdk] get isReady==>",this.store.ready),this.store.ready}listenBroadcastChannel(){new BroadcastChannel(L).onmessage=e=>{const t=this.store.appId,r=this.store.tabId;e.data.type===s.KICK_OUT&&e.data.appId===t&&e.data.tabId!==r&&(this.logger.debug("[BroadcastChannel] message: kick out",{appId:t,sourceTabId:e.data.tabId,currentTabId:r}),this.handleKickOut())}}unlistenBroadcastChannel(){new BroadcastChannel(L).close()}notifyOtherTabsLogin(){new BroadcastChannel(L).postMessage({type:s.KICK_OUT,appId:this.store.appId,tabId:this.store.tabId})}async connectWebSocket(e){if(!e)throw Error("connect websocket error, not found login user token");this.imClient=new x({token:e,wsUrl:`${this.config.websocketHost}/ws`},this.logger),this.imClient.on(U.STATUS_CHANGE,e=>{this.store.set(b.CONNECTION_STATUS,e),this.events.emit(exports.ChatSdkEvent.CONNECTION_STATUS_CHANGE,e)}),this.imClient.on(U.OPEN,()=>{this.store.set(b.IS_CONNECTED,!0)}),this.imClient.on(U.KICK_OFF,()=>{this.store.set(b.IS_CONNECTED,!1)}),this.imClient.on(U.CLOSE,()=>{this.store.set(b.IS_CONNECTED,!1)}),this.imClient.on(U.MESSAGE,e=>{this.handlePushMessage(e)}),this.imClient.connect()}disconnectWebSocket(){this.imClient&&(this.imClient.disconnect(),this.imClient=null)}assertReady(){if(!this.store.ready)throw{code:exports.ChatSdkErrorCode.SDK_ERROR,msg:"sdk not ready"}}handleException(e){return this.logger.error("[ChatSDK Error]",e),{ok:!1,code:e.code||exports.ChatSdkErrorCode.SDK_ERROR,msg:e.msg||e.message||"sdk error"}}}const B=new Map;function H(e){return{setLogLevel(t){e.setLogLevel(t)},login:t=>e.login(t),logout:()=>e.logout(),initialChat:t=>e.initialChat(t),addGroupMember:(t,s)=>e.addGroupMember(t,s),getCurrentFeed:()=>e.getCurrentFeed(),getMessageList:t=>e.getMessageList(t),uploadFile:t=>e.uploadFile(t),sendMessage:t=>e.sendMessage(t),sendMessageReadReceipt:t=>e.sendMessageReadReceipt(t),markAllMessagesAsRead:t=>e.markAllMessagesAsRead(t),recallMessage:t=>e.recallMessage(t),get currentUserId(){return e.currentUserId},get currentChatId(){return e.currentChatId},get isReady(){return e.isReady},on:(t,s)=>e.on(t,s),once:(t,s)=>e.once(t,s),off:(t,s)=>e.off(t,s)}}var W={create:function(e,t){if(B.has(e))return H(B.get(e));const s=new K(e,t);return B.set(e,s),H(s)}};exports.default=W;
|