partey_workadventure/front/src/Connexion/Room.ts

144 lines
5.3 KiB
TypeScript
Raw Normal View History

import Axios from "axios";
2021-06-23 12:42:24 +02:00
import { PUSHER_URL } from "../Enum/EnvironmentVariable";
import type { CharacterTexture } from "./LocalUser";
2021-06-23 12:42:24 +02:00
export class MapDetail {
constructor(public readonly mapUrl: string, public readonly textures: CharacterTexture[] | undefined) {
}
}
export class Room {
public readonly id: string;
public readonly isPublic: boolean;
2021-06-23 12:42:24 +02:00
private mapUrl: string | undefined;
private textures: CharacterTexture[] | undefined;
private instance: string | undefined;
private _search: URLSearchParams;
2020-10-13 17:08:24 +02:00
constructor(id: string) {
const url = new URL(id, 'https://example.com');
this.id = url.pathname;
if (this.id.startsWith('/')) {
this.id = this.id.substr(1);
}
if (this.id.startsWith('_/')) {
this.isPublic = true;
} else if (this.id.startsWith('@/')) {
this.isPublic = false;
} else {
throw new Error('Invalid room ID');
}
this._search = new URLSearchParams(url.search);
}
2021-06-23 12:42:24 +02:00
public static getIdFromIdentifier(identifier: string, baseUrl: string, currentInstance: string): { roomId: string, hash: string | null } {
let roomId = '';
2021-06-23 12:42:24 +02:00
let hash = null;
if (!identifier.startsWith('/_/') && !identifier.startsWith('/@/')) { //relative file link
//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);
2021-06-23 12:42:24 +02:00
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
hash = absoluteExitSceneUrl.hash;
hash = hash.substring(1); //remove the leading diese
if (!hash.length) {
hash = null
}
} 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]
}
}
2021-06-23 12:42:24 +02:00
return { roomId, hash }
}
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));
return;
}
if (this.isPublic) {
2020-10-13 17:30:53 +02:00
const match = /_\/[^/]+\/(.+)/.exec(this.id);
2021-06-23 12:42:24 +02:00
if (!match) throw new Error('Could not extract url from "' + this.id + '"');
this.mapUrl = window.location.protocol + '//' + match[1];
resolve(new MapDetail(this.mapUrl, this.textures));
return;
} else {
// We have a private ID, we need to query the map URL from the server.
const urlParts = this.parsePrivateUrl(this.id);
Axios.get(`${PUSHER_URL}/map`, {
params: urlParts
2021-06-23 12:42:24 +02:00
}).then(({ data }) => {
2020-10-13 17:30:53 +02:00
console.log('Map ', this.id, ' resolves to URL ', data.mapUrl);
resolve(data);
2020-10-13 17:30:53 +02:00
return;
}).catch((reason) => {
reject(reason);
});
}
});
}
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);
2021-06-23 12:42:24 +02:00
if (!match) throw new Error('Could not extract instance from "' + this.id + '"');
2020-10-13 18:44:50 +02:00
this.instance = match[1];
return this.instance;
} else {
const match = /@\/([^/]+)\/([^/]+)\/.+/.exec(this.id);
2021-06-23 12:42:24 +02:00
if (!match) throw new Error('Could not extract instance from "' + this.id + '"');
this.instance = match[1] + '/' + match[2];
2020-10-13 18:44:50 +02:00
return this.instance;
}
}
private parsePrivateUrl(url: string): { organizationSlug: string, worldSlug: string, roomSlug?: string } {
2020-10-13 17:30:53 +02:00
const regex = /@\/([^/]+)\/([^/]+)(?:\/([^/]*))?/gm;
const match = regex.exec(url);
if (!match) {
2021-06-23 12:42:24 +02:00
throw new Error('Invalid URL ' + url);
}
2020-10-13 17:30:53 +02:00
const results: { organizationSlug: string, worldSlug: string, roomSlug?: string } = {
organizationSlug: match[1],
worldSlug: match[2],
}
if (match[3] !== undefined) {
results.roomSlug = match[3];
}
return results;
}
2021-06-23 12:42:24 +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;
}
}