@typexim/agent-js-sdk 1.0.19 → 1.0.21
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/dist/types/index.d.ts +25 -2
- 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 _(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"}(u||(u={})),function(e){e[e.up=0]="up",e[e.down=1]="down"}(l||(l={}));const m="[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(`${m}[DEBUG]`,...e)}info(...e){this.shouldPrint(0)&&console.info(`${m}[INFO]`,...e)}warn(...e){this.shouldPrint(1)&&console.warn(`${m}[WARN]`,...e)}error(...e){this.shouldPrint(2)&&console.error(`${m}[ERROR]`,...e)}}function R(e){return(new TextEncoder).encode(e).buffer}async function p(t,s){return window.crypto&&window.crypto.subtle?await async function(e,t){const s=R(t),i=R(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 C=e=>{if(null==e)return"";if("object"!=typeof e||Array.isArray(e)){if(Array.isArray(e)){let t="";for(const s of e)t+=C(s);return t}return"string"==typeof e?e:String(e)}{const t=Object.keys(e).sort();let s="";for(const i of t)s+=C(e[i]);return s}};class I{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,console.log("[HttpClient] sessionId",this.store.sessionId),e.headers["X-Sid"]=this.store.sessionId,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:E.SDK_ERROR,msg:e})}try{const i=await(async(e,t)=>{const s=C(e);return await p(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),_({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 A{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 D extends A{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 O{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 f{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)}}var N,P;!function(e){e.OPEN="OPEN",e.ERROR="ERROR",e.CLOSE="CLOSE",e.MESSAGE="MESSAGE",e.STATUS_CHANGE="STATUS_CHANGE",e.KICK_OFF="KICK_OFF"}(N||(N={}));class U extends A{connection;reconnector;heartbeat;pongTimeoutCount=0;offlineReconnectTimer;constructor(e,t){super(t),this.connection=new D({url:e.wsUrl,token:e.token},t),this.reconnector=new f(this.connection,t),this.heartbeat=new O(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(N.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(N.KICK_OFF),void this.disconnect();this.emit(N.CLOSE)}),this.connection.on(a.MESSAGE,e=>{this.handleRawMessage(e)}),this.connection.on(a.STATUS_CHANGE,e=>{this.emit(N.STATUS_CHANGE,e)}),this.connection.on(a.ERROR,e=>{this.emit(N.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(N.MESSAGE,e);else this.emit(N.MESSAGE,t)}catch(e){this.logger.error("[IMClient][handleRawMessage]","Message raw data json.parse error",e),this.emit(N.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"}(P||(P={}));class b extends A{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 y{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 M{config;logger;http;imClient=null;store;events;version;loadFeedAbortController=null;promises=new Map;constructor(e,t){this.logger=new T,this.store=new b(this.logger),this.events=new A(this.logger),this.store.set(P.APP_ID,e),this.config=t,this.version=new y,this.http=new I({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: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),_({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)}}innerLogin(e,t){return this.http.post("/user/token/login",{token:t.authToken,userId:t.userId,deviceId:e,avatar:t.avatar,name:t.name,email:t.email})}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);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}).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 S(null);const e=await this.http.get("/user/logout");return 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:E.SDK_ERROR,msg:"not found chat id"});if(!t?.length)return S(null);const s=this.store.currentFeed;if(!s)return _({code:E.SDK_ERROR,msg:"not found current feed"});const i=await this.getChatMembers(s.chat_id,s.chat_member);if(!i.ok)return _({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):_({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||[]);return t.ok&&t.data?(this.store.set(P.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: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(e.ok&&e.data?.[s]){return S({hasMore:a,list: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 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),_({code:E.SDK_ERROR,msg:`Unsupported message type: ${t}`})}}catch(e){return this.handleException(e)}}async sendTextMessage(e){return this.http.post("/message/send_text",{chat_id:e.chatId,client_msg_id:e.clientMsgId,text:e.text.trim()},{needSign:!0})}async sendImageMessage(e){return 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})}async sendVideoMessage(e){return 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})}async sendFileMessage(e){return 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})}async uploadFile(e){const{chatId:t,fileContent:s,fileFormat:i,fileName:n,fileType:r,onUploadProgress:o}=e;if(s.size>209715200)return _({code:E.SDK_ERROR,msg:"File size exceeds 200MB, upload failed"});const a=new FormData;return 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),this.http.post("/chat/upload",a,{needSign:!1,ignoreDeveloper:!0,onUploadProgress:o,headers:{"Content-Type":"multipart/form-data"}})}async sendMessageReadReceipt(e){try{return this.assertReady(),e.messageIds?.length?this.http.post("/message/read",{chat_id:e.chatId,message_ids:e.messageIds},{needSign:!0}):S(null)}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{return this.assertReady(),e.messageIds.length?this.http.post("/message/remove",{chat_id:e.chatId,message_ids:e.messageIds,two_way:1},{needSign:!0}):S(null)}catch(e){return this.handleException(e)}}async createFeed(e){const t=this.store.currentUser?.id;if(!t)return _({code:E.SDK_ERROR,msg:"User not logged in"});if(this.promises.has(t))return this.promises.get(t);const s=this.http.post("/chat/group",{receiver_ids:e,group_type:0,name:`User ${this.store.currentUser?.name||this.store.currentUser?.id}`},{needSign:!0}).catch(e=>{throw e}).finally(()=>{this.promises.delete(t)});return this.promises.set(t,s),s}async getChatMembers(e,t){return this.http.post("/chat/chatter_info",JSON.stringify({chatters:{[e]:t}}))}async addMember(e,t){return t?e.length?this.http.post("/chat/group/add_member",{user_ids:e,chat_id:t},{needSign:!0}):S(null):_({code:E.SDK_ERROR,msg:"not found chat id"})}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_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()}}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(w).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(w).close()}notifyOtherTabsLogin(){new BroadcastChannel(w).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 U({token:e,wsUrl:`${this.config.websocketHost}/ws`},this.logger),this.imClient.on(N.STATUS_CHANGE,e=>{this.store.set(P.CONNECTION_STATUS,e),this.events.emit(u.CONNECTION_STATUS_CHANGE,e)}),this.imClient.on(N.OPEN,()=>{this.store.set(P.IS_CONNECTED,!0)}),this.imClient.on(N.KICK_OFF,()=>{this.store.set(P.IS_CONNECTED,!1)}),this.imClient.on(N.CLOSE,()=>{this.store.set(P.IS_CONNECTED,!1)}),this.imClient.on(N.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 G=new Map;function v(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 v(G.get(e));const s=new M(e,t);return G.set(e,s),v(s)}};export{E as ChatSdkErrorCode,u as ChatSdkEvent,c as ChatType,o as ConnectionStatus,h as MessageKind,g as MessageOperation,d as MessageType,l as RequestDirection,F 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 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}};class A{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.headers["X-Sid"]=this.store.sessionId,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 D{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 O extends D{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 f{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 N{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)}}var U,P;!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 b extends D{connection;reconnector;heartbeat;pongTimeoutCount=0;offlineReconnectTimer;constructor(e,t){super(t),this.connection=new O({url:e.wsUrl,token:e.token},t),this.reconnector=new N(this.connection,t),this.heartbeat=new f(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"}(P||(P={}));class M extends D{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 w{version;constructor(){this.version=0}increment(){this.version++}get currentVersion(){return this.version}check(e){return e===this.version}}const y="@typexim/agent-js-sdk_broadcast_channel";class G{config;logger;http;imClient=null;store;events;version;loadFeedAbortController=null;promises=new Map;constructor(e,t){this.logger=new T,this.store=new M(this.logger),this.events=new D(this.logger),this.store.set(P.APP_ID,e),this.config=t,this.version=new w,this.http=new A({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(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}).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 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||[]);return this.triggerUnauthorized(t),t.ok&&t.data?(this.store.set(P.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){const t=this.store.currentUser?.id;if(!t)return m({code:E.SDK_ERROR,msg:"User not logged in"});if(this.promises.has(t))return this.promises.get(t);const s=this.http.post("/chat/group",{receiver_ids:e,group_type:0,name:`User ${this.store.currentUser?.name||this.store.currentUser?.id}`},{needSign:!0}).catch(e=>{throw e}).finally(()=>{this.promises.delete(t)});return this.promises.set(t,s),s}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(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(y).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(y).close()}notifyOtherTabsLogin(){new BroadcastChannel(y).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 b({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 v=new Map;function F(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 L={create:function(e,t){if(v.has(e))return F(v.get(e));const s=new G(e,t);return v.set(e,s),F(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,L as default};
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e,t,s,r,n,i,o,a,c,h,d,E,g=require("crypto-js"),u=require("axios"),l=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",exports.RequestDirection=void 0,(E=exports.RequestDirection||(exports.RequestDirection={}))[E.up=0]="up",E[E.down=1]="down";const p="[TYPEX_AGENT_JS_SDK]";class C{level=0;setLogLevel(e){this.level=e}getLogLevel(){return this.level}shouldPrint(e){return e>=this.level}debug(...e){this.shouldPrint(0)&&console.debug(`${p}[DEBUG]`,...e)}info(...e){this.shouldPrint(0)&&console.info(`${p}[INFO]`,...e)}warn(...e){this.shouldPrint(1)&&console.warn(`${p}[WARN]`,...e)}error(...e){this.shouldPrint(2)&&console.error(`${p}[ERROR]`,...e)}}function m(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=m(t),r=m(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=g.HmacSHA256(e,t);return g.enc.Hex.stringify(s)}(e,t)}const R=e=>{if(null==e)return"";if("object"!=typeof e||Array.isArray(e)){if(Array.isArray(e)){let t="";for(const s of e)t+=R(s);return t}return"string"==typeof e?e:String(e)}{const t=Object.keys(e).sort();let s="";for(const r of t)s+=R(e[r]);return s}};class I{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=u.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,console.log("[HttpClient] sessionId",this.store.sessionId),e.headers["X-Sid"]=this.store.sessionId,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=R(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 A{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 D extends A{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 O{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 N{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)}}var f,P;!function(e){e.OPEN="OPEN",e.ERROR="ERROR",e.CLOSE="CLOSE",e.MESSAGE="MESSAGE",e.STATUS_CHANGE="STATUS_CHANGE",e.KICK_OFF="KICK_OFF"}(f||(f={}));class b extends A{connection;reconnector;heartbeat;pongTimeoutCount=0;offlineReconnectTimer;constructor(e,t){super(t),this.connection=new D({url:e.wsUrl,token:e.token},t),this.reconnector=new N(this.connection,t),this.heartbeat=new O(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(f.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(f.KICK_OFF),void this.disconnect();this.emit(f.CLOSE)}),this.connection.on(n.MESSAGE,e=>{this.handleRawMessage(e)}),this.connection.on(n.STATUS_CHANGE,e=>{this.emit(f.STATUS_CHANGE,e)}),this.connection.on(n.ERROR,e=>{this.emit(f.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(f.MESSAGE,e);else this.emit(f.MESSAGE,s)}catch(e){this.logger.error("[IMClient][handleRawMessage]","Message raw data json.parse error",e),this.emit(f.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"}(P||(P={}));class U extends A{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||exports.ConnectionStatus.INIT),this.state.connectionStatus||exports.ConnectionStatus.INIT}}class y{version;constructor(){this.version=0}increment(){this.version++}get currentVersion(){return this.version}check(e){return e===this.version}}const v="@typexim/agent-js-sdk_broadcast_channel";class M{config;logger;http;imClient=null;store;events;version;loadFeedAbortController=null;promises=new Map;constructor(e,t){this.logger=new C,this.store=new U(this.logger),this.events=new A(this.logger),this.store.set(P.APP_ID,e),this.config=t,this.version=new y,this.http=new I({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)}}innerLogin(e,t){return this.http.post("/user/token/login",{token:t.authToken,userId:t.userId,deviceId:e,avatar:t.avatar,name:t.name,email:t.email})}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 l.load(),s=await t.get();return this.logger.debug("[ChatSdk] generateBrowserFingerprint success",s.visitorId),this.store.setWithSession(P.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(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 r=t.data?.feed_list?.find(e=>e.chat_type===exports.ChatType.groupChat);t.ok&&(this.logger.debug("[ChatSdk][FEED_UPDATED] loadFeed success",r),this.store.set(P.CURRENT_FEED,r),this.events.emit(exports.ChatSdkEvent.FEED_UPDATED,r))}async syncLoginState(e){this.store.set(P.CURRENT_USER,e),this.store.set(P.SDK_READY,!0),await this.loadFeed(),this.events.emit(exports.ChatSdkEvent.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(exports.ChatSdkEvent.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}).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 S(null);const e=await this.http.get("/user/logout");return 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||[]);return t.ok&&t.data?(this.store.set(P.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(e.ok&&e.data?.[s]){return S({hasMore:a,list: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 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){return this.http.post("/message/send_text",{chat_id:e.chatId,client_msg_id:e.clientMsgId,text:e.text.trim()},{needSign:!0})}async sendImageMessage(e){return 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})}async sendVideoMessage(e){return 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})}async sendFileMessage(e){return 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})}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;return 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),this.http.post("/chat/upload",a,{needSign:!1,ignoreDeveloper:!0,onUploadProgress:o,headers:{"Content-Type":"multipart/form-data"}})}async sendMessageReadReceipt(e){try{return this.assertReady(),e.messageIds?.length?this.http.post("/message/read",{chat_id:e.chatId,message_ids:e.messageIds},{needSign:!0}):S(null)}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{return this.assertReady(),e.messageIds.length?this.http.post("/message/remove",{chat_id:e.chatId,message_ids:e.messageIds,two_way:1},{needSign:!0}):S(null)}catch(e){return this.handleException(e)}}async createFeed(e){const t=this.store.currentUser?.id;if(!t)return _({code:exports.ChatSdkErrorCode.SDK_ERROR,msg:"User not logged in"});if(this.promises.has(t))return this.promises.get(t);const s=this.http.post("/chat/group",{receiver_ids:e,group_type:0,name:`User ${this.store.currentUser?.name||this.store.currentUser?.id}`},{needSign:!0}).catch(e=>{throw e}).finally(()=>{this.promises.delete(t)});return this.promises.set(t,s),s}async getChatMembers(e,t){return this.http.post("/chat/chatter_info",JSON.stringify({chatters:{[e]:t}}))}async addMember(e,t){return t?e.length?this.http.post("/chat/group/add_member",{user_ids:e,chat_id:t},{needSign:!0}):S(null):_({code:exports.ChatSdkErrorCode.SDK_ERROR,msg:"not found chat id"})}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_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()}}handleFeedUpdate(e){this.store.set(P.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(v).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(v).close()}notifyOtherTabsLogin(){new BroadcastChannel(v).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 b({token:e,wsUrl:`${this.config.websocketHost}/ws`},this.logger),this.imClient.on(f.STATUS_CHANGE,e=>{this.store.set(P.CONNECTION_STATUS,e),this.events.emit(exports.ChatSdkEvent.CONNECTION_STATUS_CHANGE,e)}),this.imClient.on(f.OPEN,()=>{this.store.set(P.IS_CONNECTED,!0)}),this.imClient.on(f.KICK_OFF,()=>{this.store.set(P.IS_CONNECTED,!1)}),this.imClient.on(f.CLOSE,()=>{this.store.set(P.IS_CONNECTED,!1)}),this.imClient.on(f.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 w=new Map;function k(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 x={create:function(e,t){if(w.has(e))return k(w.get(e));const s=new M(e,t);return w.set(e,s),k(s)}};exports.default=x;
|
|
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}};class D{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.headers["X-Sid"]=this.store.sessionId,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 A{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 O extends A{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 N{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 U{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)}}var f,P;!function(e){e.OPEN="OPEN",e.ERROR="ERROR",e.CLOSE="CLOSE",e.MESSAGE="MESSAGE",e.STATUS_CHANGE="STATUS_CHANGE",e.KICK_OFF="KICK_OFF"}(f||(f={}));class M extends A{connection;reconnector;heartbeat;pongTimeoutCount=0;offlineReconnectTimer;constructor(e,t){super(t),this.connection=new O({url:e.wsUrl,token:e.token},t),this.reconnector=new U(this.connection,t),this.heartbeat=new N(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(f.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(f.KICK_OFF),void this.disconnect();this.emit(f.CLOSE)}),this.connection.on(i.MESSAGE,e=>{this.handleRawMessage(e)}),this.connection.on(i.STATUS_CHANGE,e=>{this.emit(f.STATUS_CHANGE,e)}),this.connection.on(i.ERROR,e=>{this.emit(f.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(f.MESSAGE,e);else this.emit(f.MESSAGE,s)}catch(e){this.logger.error("[IMClient][handleRawMessage]","Message raw data json.parse error",e),this.emit(f.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"}(P||(P={}));class b extends A{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||exports.ConnectionStatus.INIT),this.state.connectionStatus||exports.ConnectionStatus.INIT}}class y{version;constructor(){this.version=0}increment(){this.version++}get currentVersion(){return this.version}check(e){return e===this.version}}const v="@typexim/agent-js-sdk_broadcast_channel";class w{config;logger;http;imClient=null;store;events;version;loadFeedAbortController=null;promises=new Map;constructor(e,t){this.logger=new m,this.store=new b(this.logger),this.events=new A(this.logger),this.store.set(P.APP_ID,e),this.config=t,this.version=new y,this.http=new D({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(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 _.load(),s=await t.get();return this.logger.debug("[ChatSdk] generateBrowserFingerprint success",s.visitorId),this.store.setWithSession(P.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(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 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(P.CURRENT_FEED,r),this.events.emit(exports.ChatSdkEvent.FEED_UPDATED,r))}async syncLoginState(e){this.store.set(P.CURRENT_USER,e),this.store.set(P.SDK_READY,!0),await this.loadFeed(),this.events.emit(exports.ChatSdkEvent.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(exports.ChatSdkEvent.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}).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 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||[]);return this.triggerUnauthorized(t),t.ok&&t.data?(this.store.set(P.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){const t=this.store.currentUser?.id;if(!t)return p({code:exports.ChatSdkErrorCode.SDK_ERROR,msg:"User not logged in"});if(this.promises.has(t))return this.promises.get(t);const s=this.http.post("/chat/group",{receiver_ids:e,group_type:0,name:`User ${this.store.currentUser?.name||this.store.currentUser?.id}`},{needSign:!0}).catch(e=>{throw e}).finally(()=>{this.promises.delete(t)});return this.promises.set(t,s),s}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(P.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(v).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(v).close()}notifyOtherTabsLogin(){new BroadcastChannel(v).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(f.STATUS_CHANGE,e=>{this.store.set(P.CONNECTION_STATUS,e),this.events.emit(exports.ChatSdkEvent.CONNECTION_STATUS_CHANGE,e)}),this.imClient.on(f.OPEN,()=>{this.store.set(P.IS_CONNECTED,!0)}),this.imClient.on(f.KICK_OFF,()=>{this.store.set(P.IS_CONNECTED,!1)}),this.imClient.on(f.CLOSE,()=>{this.store.set(P.IS_CONNECTED,!1)}),this.imClient.on(f.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 k=new Map;function G(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 x={create:function(e,t){if(k.has(e))return G(k.get(e));const s=new w(e,t);return k.set(e,s),G(s)}};exports.default=x;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -105,7 +105,11 @@ declare enum ChatSdkEvent {
|
|
|
105
105
|
/** 消息已读回执,哪些消息被对方已读了 */
|
|
106
106
|
MESSAGE_RECEIPT_RECEIVED = "MESSAGE_RECEIPT_RECEIVED",
|
|
107
107
|
/** websocket 连接状态改变 */
|
|
108
|
-
CONNECTION_STATUS_CHANGE = "CONNECTION_STATUS_CHANGE"
|
|
108
|
+
CONNECTION_STATUS_CHANGE = "CONNECTION_STATUS_CHANGE",
|
|
109
|
+
/** 授信过期 */
|
|
110
|
+
UNAUTHORIZED = "UNAUTHORIZED",
|
|
111
|
+
/** 群成员变动 */
|
|
112
|
+
GROUP_MEMBER_UPDATED = "GROUP_MEMBER_UPDATED"
|
|
109
113
|
}
|
|
110
114
|
declare enum RequestDirection {
|
|
111
115
|
/**
|
|
@@ -117,6 +121,12 @@ declare enum RequestDirection {
|
|
|
117
121
|
*/
|
|
118
122
|
down = 1
|
|
119
123
|
}
|
|
124
|
+
declare enum GroupMemberUpdateType {
|
|
125
|
+
/** 新增群成员 */
|
|
126
|
+
ADD_GROUP_MEMBER = 21,
|
|
127
|
+
/** 移除群成员 */
|
|
128
|
+
DEL_GROUP_MEMBER = 22
|
|
129
|
+
}
|
|
120
130
|
|
|
121
131
|
interface Message {
|
|
122
132
|
/**
|
|
@@ -414,6 +424,12 @@ interface ChatSdkEventData {
|
|
|
414
424
|
readerUserIds: string[];
|
|
415
425
|
};
|
|
416
426
|
[ChatSdkEvent.CONNECTION_STATUS_CHANGE]: ConnectionStatus;
|
|
427
|
+
[ChatSdkEvent.UNAUTHORIZED]: undefined;
|
|
428
|
+
[ChatSdkEvent.GROUP_MEMBER_UPDATED]: {
|
|
429
|
+
type: GroupMemberUpdateType;
|
|
430
|
+
chatId: string;
|
|
431
|
+
members: ChatMember[];
|
|
432
|
+
};
|
|
417
433
|
}
|
|
418
434
|
interface AddGroupMemberResp {
|
|
419
435
|
user_id: string;
|
|
@@ -425,6 +441,13 @@ interface AddGroupMemberResp {
|
|
|
425
441
|
|
|
426
442
|
type ChatSdkResponse<T> = HttpResponse<T>;
|
|
427
443
|
|
|
444
|
+
type ChatMember = {
|
|
445
|
+
avatar: string;
|
|
446
|
+
chat_id: string;
|
|
447
|
+
name: string;
|
|
448
|
+
user_id: string;
|
|
449
|
+
};
|
|
450
|
+
|
|
428
451
|
/**
|
|
429
452
|
* 0-打印所有日志
|
|
430
453
|
* 1-只打印warning和error
|
|
@@ -474,5 +497,5 @@ declare const _default: {
|
|
|
474
497
|
create: typeof createChatSdk;
|
|
475
498
|
};
|
|
476
499
|
|
|
477
|
-
export { ChatSdkErrorCode, ChatSdkEvent, ChatType, ConnectionStatus, MessageKind, MessageOperation, MessageType, RequestDirection, _default as default };
|
|
500
|
+
export { ChatSdkErrorCode, ChatSdkEvent, ChatType, ConnectionStatus, GroupMemberUpdateType, MessageKind, MessageOperation, MessageType, RequestDirection, _default as default };
|
|
478
501
|
export type { AddGroupMemberResp, ChatSDKConfig, ChatSdk, ChatSdkEventData, ChatSdkResponse, Feed, GetMessageListData, GetMessageListResp, InitialChatData, LoginData, Message, RecallMessageData, SendFileMsgData, SendImageMsgData, SendMessageCommonData, SendMessageData, SendMessageReadReceiptData, SendTextMsgData, SendVideoMsgData, UploadFileData, UploadFileType, User };
|