2020-10-13 16:46:46 +02:00
import Axios from "axios" ;
2021-03-31 16:00:14 +02:00
import { PUSHER_URL } from "../Enum/EnvironmentVariable" ;
2021-06-03 13:07:52 +02:00
import type { CharacterTexture } from "./LocalUser" ;
export class MapDetail {
constructor ( public readonly mapUrl : string , public readonly textures : CharacterTexture [ ] | undefined ) {
}
}
2020-10-13 16:46:46 +02:00
2020-10-12 16:23:07 +02:00
export class Room {
2020-10-13 16:46:46 +02:00
public readonly id : string ;
public readonly isPublic : boolean ;
private mapUrl : string | undefined ;
2021-06-03 13:07:52 +02:00
private textures : CharacterTexture [ ] | undefined ;
2020-10-13 18:44:50 +02:00
private instance : string | undefined ;
2021-03-30 16:08:49 +02:00
private _search : URLSearchParams ;
2020-10-13 16:46:46 +02:00
2020-10-13 17:08:24 +02:00
constructor ( id : string ) {
2021-03-30 16:08:49 +02:00
const url = new URL ( id , 'https://example.com' ) ;
this . id = url . pathname ;
if ( this . id . startsWith ( '/' ) ) {
this . id = this . id . substr ( 1 ) ;
2020-10-13 16:46:46 +02:00
}
2021-03-30 16:08:49 +02:00
if ( this . id . startsWith ( '_/' ) ) {
2020-10-13 16:46:46 +02:00
this . isPublic = true ;
2021-03-30 16:08:49 +02:00
} else if ( this . id . startsWith ( '@/' ) ) {
2020-10-13 16:46:46 +02:00
this . isPublic = false ;
} else {
throw new Error ( 'Invalid room ID' ) ;
}
2020-10-15 15:50:51 +02:00
2021-03-30 16:08:49 +02:00
this . _search = new URLSearchParams ( url . search ) ;
2020-10-12 16:23:07 +02:00
}
2021-01-17 20:34:35 +01:00
2020-11-18 18:15:57 +01:00
public static getIdFromIdentifier ( identifier : string , baseUrl : string , currentInstance : string ) : { roomId : string , hash : string } {
let roomId = '' ;
let hash = '' ;
if ( ! identifier . startsWith ( '/_/' ) && ! identifier . startsWith ( '/@/' ) ) { //relative file link
2021-01-05 17:08:33 +01:00
//Relative identifier can be deep enough to rewrite the base domain, so we cannot use the variable 'baseUrl' as the actual base url for the URL objects.
//We instead use 'workadventure' as a dummy base value.
const baseUrlObject = new URL ( baseUrl ) ;
const absoluteExitSceneUrl = new URL ( identifier , 'http://workadventure/_/' + currentInstance + '/' + baseUrlObject . hostname + baseUrlObject . pathname ) ;
roomId = absoluteExitSceneUrl . pathname ; //in case of a relative url, we need to create a public roomId
roomId = roomId . substring ( 1 ) ; //remove the leading slash
2020-11-18 18:15:57 +01:00
hash = absoluteExitSceneUrl . hash ;
hash = hash . substring ( 1 ) ; //remove the leading diese
} else { //absolute room Id
const parts = identifier . split ( '#' ) ;
roomId = parts [ 0 ] ;
roomId = roomId . substring ( 1 ) ; //remove the leading slash
if ( parts . length > 1 ) {
hash = parts [ 1 ]
}
}
return { roomId , hash }
}
2020-10-13 16:46:46 +02:00
2021-06-03 13:07:52 +02:00
public async getMapDetail ( ) : Promise < MapDetail > {
return new Promise < MapDetail > ( ( resolve , reject ) = > {
if ( this . mapUrl !== undefined && this . textures != undefined ) {
resolve ( new MapDetail ( this . mapUrl , this . textures ) ) ;
2020-10-13 16:46:46 +02:00
return ;
}
if ( this . isPublic ) {
2020-10-13 17:30:53 +02:00
const match = /_\/[^/]+\/(.+)/ . exec ( this . id ) ;
2020-10-13 16:46:46 +02:00
if ( ! match ) throw new Error ( 'Could not extract url from "' + this . id + '"' ) ;
this . mapUrl = window . location . protocol + '//' + match [ 1 ] ;
2021-06-03 13:07:52 +02:00
resolve ( new MapDetail ( this . mapUrl , this . textures ) ) ;
2020-10-13 16:46:46 +02:00
return ;
} else {
// We have a private ID, we need to query the map URL from the server.
const urlParts = this . parsePrivateUrl ( this . id ) ;
2021-03-31 16:00:14 +02:00
Axios . get ( ` ${ PUSHER_URL } /map ` , {
2020-10-13 16:46:46 +02:00
params : urlParts
2020-10-13 17:30:53 +02:00
} ) . then ( ( { data } ) = > {
console . log ( 'Map ' , this . id , ' resolves to URL ' , data . mapUrl ) ;
2021-06-03 13:07:52 +02:00
resolve ( data ) ;
2020-10-13 17:30:53 +02:00
return ;
2021-01-17 20:34:35 +01:00
} ) . catch ( ( reason ) = > {
reject ( reason ) ;
2020-10-13 16:46:46 +02:00
} ) ;
}
} ) ;
}
2020-10-13 18:44:50 +02:00
/ * *
* Instance name is :
* - In a public URL : the second part of the URL ( _ / [ instance ] / map . json )
* - In a private URL : [ organizationId / worldId ]
* /
public getInstance ( ) : string {
if ( this . instance !== undefined ) {
return this . instance ;
}
if ( this . isPublic ) {
const match = /_\/([^/]+)\/.+/ . exec ( this . id ) ;
if ( ! match ) throw new Error ( 'Could not extract instance from "' + this . id + '"' ) ;
this . instance = match [ 1 ] ;
return this . instance ;
} else {
2020-10-14 10:37:00 +02:00
const match = /@\/([^/]+)\/([^/]+)\/.+/ . exec ( this . id ) ;
2020-10-13 18:44:50 +02:00
if ( ! match ) throw new Error ( 'Could not extract instance from "' + this . id + '"' ) ;
this . instance = match [ 1 ] + '/' + match [ 2 ] ;
return this . instance ;
}
}
2020-10-13 16:46:46 +02:00
private parsePrivateUrl ( url : string ) : { organizationSlug : string , worldSlug : string , roomSlug? : string } {
2020-10-13 17:30:53 +02:00
const regex = /@\/([^/]+)\/([^/]+)(?:\/([^/]*))?/gm ;
2020-10-13 16:46:46 +02:00
const match = regex . exec ( url ) ;
if ( ! match ) {
throw new Error ( 'Invalid URL ' + url ) ;
}
2020-10-13 17:30:53 +02:00
const results : { organizationSlug : string , worldSlug : string , roomSlug? : string } = {
2020-10-13 16:46:46 +02:00
organizationSlug : match [ 1 ] ,
worldSlug : match [ 2 ] ,
}
if ( match [ 3 ] !== undefined ) {
results . roomSlug = match [ 3 ] ;
}
return results ;
}
2021-03-30 16:08:49 +02:00
public isDisconnected ( ) : boolean
{
const alone = this . _search . get ( 'alone' ) ;
if ( alone && alone !== '0' && alone . toLowerCase ( ) !== 'false' ) {
return true ;
}
return false ;
}
public get search ( ) : URLSearchParams {
return this . _search ;
}
2020-10-13 16:46:46 +02:00
}