import { Dict } from '@_unit/unit/lib/types/Dict' import { MenuOption } from './menu' import { labelToIcon, LiveMode, MusemeObjectMetadata, randomMenuOptions, } from './overlay' export const getCacheKey = (videoId: string, SceneId: string, Id: string) => { const id = `${videoId}-${SceneId}-${Id}` return id } export const buildEffectiveObjectId = ( sceneId: string, objectId: string, prevSceneId: number | undefined, prevObjectId: number | undefined ) => { const { sceneId: sceneId_, objectId: objectId_ } = getEffectiveIds( sceneId, objectId, prevSceneId, prevObjectId ) return `${sceneId_}-${objectId_}` } export const getEffectiveIds = ( sceneId: string, objectId: string, prevSceneId: number | undefined, prevObjectId: number | undefined ): { sceneId: string | number; objectId: string | number } => { if ( prevSceneId === -1 || prevSceneId === null || prevObjectId === -1 || prevObjectId === null ) { return { sceneId, objectId } } return { sceneId: prevSceneId, objectId: prevObjectId } } export const uppercaseFirstLetter = (str: string) => { if (!str) { return '' } return str[0].toUpperCase() + str.slice(1) } export const randomInArray = (array) => { return array[Math.floor(Math.random() * array.length)] } export const defaultGetObjectMenu = async ( hostname: string, videoId: string, metadata: MusemeObjectMetadata, live: boolean, liveMode: LiveMode, cache: Dict = {}, signal?: AbortSignal ): Promise => { const vote = () => { const { SceneId, Id, ActionList = [] } = metadata if (!ActionList.length) { return randomMenuOptions() } const { Metadata } = metadata if (Metadata) { if (Metadata.menu) { let menuArray: MenuOption[] try { menuArray = JSON.parse(Metadata.menu) } catch (err) { // } if (menuArray) { return menuArray } } } const options = ActionList.map((action) => { const iconNames = Object.values(labelToIcon) const icon = randomInArray(iconNames) return { value: action, label: uppercaseFirstLetter(action), icon, url: '', } }) return options } const link = async () => { const { SceneId, Id, PrevObjectId, PrevSceneId } = metadata const { sceneId: effectiveSceneId, objectId: effectiveObjectId } = getEffectiveIds(SceneId, Id, PrevObjectId, PrevSceneId) const url = `${hostname}/menu?video=${videoId}&scene_id=${effectiveSceneId}&object_id=${effectiveObjectId}` const id = getCacheKey(videoId, SceneId, Id) if (cache[id]) { return cache[id] } const response = await fetch(url, { signal, }) let data: any try { data = await response.json() } catch (err) { return [] } const { submenu } = data if (typeof submenu !== 'string') { return [] } const menu = JSON.parse(submenu) cache[id] = menu return menu } if (live) { if (liveMode === 'vote') { return vote() } else if (liveMode === 'link') { return link() } } else { return link() } } export const shouldLink = (option: MenuOption): boolean => { return !!option.url } export const defaultOnActionSelected = ( pollHostname: string, videoId: string, metadata: MusemeObjectMetadata, icon: string, options: MenuOption[], live: boolean, liveMode: LiveMode, debug: boolean ) => { if (live) { const { SceneId, PrevSceneId, Id, PrevObjectId } = metadata const effectiveId = buildEffectiveObjectId( SceneId, Id, PrevSceneId, PrevObjectId ) const option = options.find((option) => option.icon === icon) const { label: action } = option if (debug) { // eslint-disable-next-line no-console console.log('action', { SceneId, Id, PrevSceneId, PrevObjectId, effectiveId, }) } const link = shouldLink(option) if (link) { const option = options.find((o) => o.icon === icon) if (option.url) { window.open(option.url, '_blank', 'noopener,noreferrer') } } else { ;(async () => { const response = await fetch(`${pollHostname}`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ streamId: videoId, objectId: effectiveId, action, }), }) if (response.status === 200) { // } else { // } })() } return true } else { const option = options.find((o) => o.icon === icon) if (option.url) { window.open(option.url) } return false } } export const defaultGetLiveMetadataUrl = ( liveHostname: string, videoId: string ) => { const socketUrl = `${liveHostname}/${videoId}.json?meta=3` return socketUrl }