import { Socket } from '@kira-dancer/nadal' import get from 'lodash/get' import has from 'lodash/has' import maxBy from 'lodash/maxBy' import { SocketChannels } from '#lib/enums/socket' import { useUserStore, useJackpotStore, useUserPromotionStore, } from '#lib/stores' import type { JackpotSocketResponse, MessageSocketResponse, PromotionUserSocketResponse, JackpotBanner } from '#lib/types/socket' import { RouterEnum } from '#lib/enums' import { DEFAULT_SOCKET_CONFIG } from '#lib/constants' import { useAuth } from '#lib/composables/auth' import { useResetStore, useGameToast } from '#lib/composables' import { useNuxtApp, useRouter, useRuntimeConfig } from 'nuxt/app' import { watch } from 'vue' import type { AppCookies } from '#lib/types' const GP_WALLET_KEY = 'gpWalletData[0].balance' const DATA_BALANCE_KEY = 'data[0].balance' const USER_BALANCE_KEY = 'currentUser.wallet.balance' export const useSocket = () => { const $appCookies = useNuxtApp().$appCookies as AppCookies const environment = useRuntimeConfig() const userStore = useUserStore() const jackpotStore = useJackpotStore() const promotionStore = useUserPromotionStore() const resetStore = useResetStore() const router = useRouter() const { openExpiredModal } = useAuth() const { resetToasts } = useGameToast() const onConnectTimeout = ref() const onMessageTimeout = ref() const onDisconnectTimeout = ref() const subscribeTimeout = ref() if (!$appCookies.token.value) { resetStore.resetAll() } const socketUrl = environment.public.SOCKET_URL let socket: Socket let lastUserId = userStore.data.id let lastToken = userStore.data.token const resetSocket = () => { socket?.disconnect() socket = new Socket(socketUrl, DEFAULT_SOCKET_CONFIG) } const subscribeInformation = () => { if (socket) { socket?.subscribeInformation() } } const subscribeJackpot = () => { socket?.subscribeJackpot() } const subscribeJackpotBanner = () => { // @ts-expect-error the nadal doesn't support new channel of socket socket?.emit('subscribeGameJackpot') } const unSubscribeWallet = () => { socket?.unsubscribeWallet({ userId: lastUserId, token: lastToken, }) } const unSubscribeUserPlan = () => { socket?.unsubscribeUserPlan({ userId: lastUserId, token: lastToken, }) } const subscribeWallet = () => { socket?.subscribeWallet({ userId: userStore.data.id, token: userStore.data.token, }) } const subscribeUserPlan = () => { socket?.subscribeUserPlan({ userId: userStore.data.id, token: userStore.data.token, }) } const initSocket = () => { socket = new Socket(socketUrl, DEFAULT_SOCKET_CONFIG) socket?.on(SocketChannels.Connect, () => { if (onConnectTimeout.value) { clearTimeout(onConnectTimeout.value) } onConnectTimeout.value = setTimeout(() => { if (!userStore.data.token) { socket?.authenticate({ token: '' }) } subscribeJackpot() subscribeJackpotBanner() subscribeInformation() }, 1000) }) socket?.on( SocketChannels.Message, async (message: MessageSocketResponse) => { const dataCode = (get(message, 'data.code', 0) ?? 0).toString() const data = message?.data const isUnauthorized = !data || parseInt(dataCode, 10) === 401 || dataCode === 'rest_forbidden' || message.error || !message.currentUser?.token if (isUnauthorized) { unSubscribeWallet() unSubscribeUserPlan() if (userStore.data.username) { onMessageTimeout.value = setTimeout(async () => { resetStore.resetAll() userStore.resetUser() resetToasts() $appCookies.token.value = null $appCookies.gpToken.value = null router.push(RouterEnum.Home) openExpiredModal() }) } return } if ( message.code === 200 && message.currentUser && message.currentUser.token ) { let newBalance: number = 0 if (has(message, USER_BALANCE_KEY)) { newBalance = get(message, USER_BALANCE_KEY, 0) as number } if (has(message, DATA_BALANCE_KEY)) { newBalance = get(message, DATA_BALANCE_KEY, 0) as number } if (has(message, GP_WALLET_KEY)) { newBalance = get(message, GP_WALLET_KEY, 0) as number } if (userStore.data.token) { const userStorage = localStorage.getItem('user') if (!userStorage || !JSON.parse(userStorage)?.data?.token || !useCookie('token').value) { setTimeout(async () => { resetStore.resetAll() userStore.resetUser() resetToasts() $appCookies.token.value = null $appCookies.gpToken.value = null router.push(RouterEnum.Home) openExpiredModal() }) } else { userStore.setUser({ ...userStore.data, ...message.currentUser, wallet: { ...message.currentUser.wallet, balance: newBalance, }, }) } } else { resetSocket() } } }, ) socket?.on( SocketChannels.Jackpot, (message: JackpotSocketResponse = { data: null }) => { if (message.data) { if (Object.keys(message.data).length != 0) { jackpotStore.setJackpot(message.data) } } }, ) socket?.on( SocketChannels.JackpotBanner, (message: JackpotBanner[] = []) => { if (message?.length) { const gameItem = maxBy( message.filter(item => item.on), 'currentValue' ) if (gameItem) { jackpotStore.setXocDiaJackpot({ gameId: gameItem.id, gameName: gameItem.name, value: gameItem.currentValue }) return } } jackpotStore.setXocDiaJackpot({ gameId: '', gameName: '', value: 0 }) }, ) socket?.on(SocketChannels.Maintenance, (message = { data: null }) => { if (message.data) { // todo } }) socket?.on( SocketChannels.Plan, (message: PromotionUserSocketResponse = { data: null }) => { if (message.data && Object.entries(message.data).length > 0) { const promotionUser = promotionStore.promotionUser const promotionData = message.data promotionStore.setPromotionUser({ ...promotionUser, ...promotionData, }) } }, ) socket?.on(SocketChannels.Disconnect, () => { if (onDisconnectTimeout.value) { clearTimeout(onDisconnectTimeout.value) } onDisconnectTimeout.value = setTimeout(() => { subscribeJackpot() subscribeInformation() subscribeJackpotBanner() if (userStore.data.token) { subscribeWallet() subscribeUserPlan() } }, 1000) }) socket?.on(SocketChannels.Connect, () => { if (userStore.data.token) { socket?.authenticate({ token: userStore.data.token }) } }) } watch( () => userStore.data.token, (data) => { if (data) { socket?.authenticate({ token: data }) if (subscribeTimeout.value) { clearTimeout(subscribeTimeout.value) } subscribeTimeout.value = setTimeout(() => { subscribeWallet() subscribeUserPlan() }, 1000) } else { unSubscribeWallet() unSubscribeUserPlan() } if (userStore.data.id || userStore.data.token) { lastUserId = userStore.data.id lastToken = userStore.data.token } }, { immediate: true, }, ) onBeforeUnmount(() => { if (onConnectTimeout.value) { clearTimeout(onConnectTimeout.value) } if (onMessageTimeout.value) { clearTimeout(onMessageTimeout.value) } if (onDisconnectTimeout.value) { clearTimeout(onDisconnectTimeout.value) } if (subscribeTimeout.value) { clearTimeout(subscribeTimeout.value) } }) return { initSocket, } }