Skip to content
This repository was archived by the owner on Nov 5, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/definition/accessors/IConfigurationExtend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { ISchedulerExtend } from './ISchedulerExtend';
import { ISettingsExtend } from './ISettingsExtend';
import { ISlashCommandsExtend } from './ISlashCommandsExtend';
import { IUIExtend } from './IUIExtend';
import { IVideoConfProvidersExtend } from './IVideoConfProvidersExtend';

/**
* This accessor provides methods for declaring the configuration
Expand All @@ -29,4 +30,7 @@ export interface IConfigurationExtend {
readonly scheduler: ISchedulerExtend;
/** Accessor for registering different elements in the host UI */
readonly ui: IUIExtend;

/** Accessor for declaring the videoconf providers which your App provides. */
readonly videoConfProviders: IVideoConfProvidersExtend;
}
15 changes: 15 additions & 0 deletions src/definition/accessors/IVideoConfProvidersExtend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { IVideoConfProvider } from '../videoConfProviders';

/**
* This accessor provides methods for adding videoconf providers.
* It is provided during the initialization of your App
*/

export interface IVideoConfProvidersExtend {
/**
* Adds a videoconf provider
*
* @param provider the provider information
*/
provideVideoConfProvider(provider: IVideoConfProvider): Promise<void>;
}
1 change: 1 addition & 0 deletions src/definition/accessors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,4 @@ export * from './IUploadCreator';
export * from './IUploadRead';
export * from './IUserBuilder';
export * from './IUserRead';
export * from './IVideoConfProvidersExtend';
2 changes: 2 additions & 0 deletions src/definition/metadata/AppMethod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export enum AppMethod {
_COMMAND_PREVIEWER = 'previewer',
_COMMAND_PREVIEW_EXECUTOR = 'executePreviewItem',
_JOB_PROCESSOR = 'jobProcessor',
_VIDEOCONF_GENERATE_URL = 'generateUrl',
_VIDEOCONF_CUSTOMIZE_URL = 'customizeUrl',
INITIALIZE = 'initialize',
ONENABLE = 'onEnable',
ONDISABLE = 'onDisable',
Expand Down
17 changes: 17 additions & 0 deletions src/definition/videoConfProviders/IVideoConfProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { INewVideoConference, IVideoConference } from './IVideoConference';
import { IVideoConferenceOptions } from './IVideoConferenceOptions';
import { IVideoConferenceUser } from './IVideoConferenceUser';

/**
* Represents a video conference provider
*/
export interface IVideoConfProvider {
/**
* The function which gets called when a new video conference url is requested
*/
generateUrl(call: INewVideoConference): Promise<string>;
/**
* The function which gets called whenever a user join url is requested
*/
customizeUrl(call: IVideoConference, user?: IVideoConferenceUser, options?: IVideoConferenceOptions): Promise<string>;
}
13 changes: 13 additions & 0 deletions src/definition/videoConfProviders/IVideoConference.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { IVideoConferenceUser } from './IVideoConferenceUser';

export interface INewVideoConference {
_id: string;
type: 'direct' | 'videoconference';
rid: string;
createdBy: IVideoConferenceUser;
title?: string;
}

export interface IVideoConference extends INewVideoConference {
url: string;
}
4 changes: 4 additions & 0 deletions src/definition/videoConfProviders/IVideoConferenceOptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface IVideoConferenceOptions {
mic?: boolean;
cam?: boolean;
}
5 changes: 5 additions & 0 deletions src/definition/videoConfProviders/IVideoConferenceUser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface IVideoConferenceUser {
_id: string;
username: string;
name: string;
}
12 changes: 12 additions & 0 deletions src/definition/videoConfProviders/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { INewVideoConference, IVideoConference } from './IVideoConference';
import { IVideoConferenceOptions } from './IVideoConferenceOptions';
import { IVideoConferenceUser } from './IVideoConferenceUser';
import { IVideoConfProvider } from './IVideoConfProvider';

export {
INewVideoConference,
IVideoConference,
IVideoConferenceOptions,
IVideoConferenceUser,
IVideoConfProvider,
};
10 changes: 9 additions & 1 deletion src/server/AppManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { InvalidLicenseError } from './errors';
import { IGetAppsFilter } from './IGetAppsFilter';
import {
AppAccessorManager, AppApiManager, AppExternalComponentManager, AppLicenseManager, AppListenerManager, AppSchedulerManager, AppSettingsManager,
AppSlashCommandManager,
AppSlashCommandManager, AppVideoConfProviderManager,
} from './managers';
import { UIActionButtonManager } from './managers/UIActionButtonManager';
import { IMarketplaceInfo } from './marketplace';
Expand Down Expand Up @@ -60,6 +60,7 @@ export class AppManager {
private readonly licenseManager: AppLicenseManager;
private readonly schedulerManager: AppSchedulerManager;
private readonly uiActionButtonManager: UIActionButtonManager;
private readonly videoConfProviderManager: AppVideoConfProviderManager;

private isLoaded: boolean;

Expand Down Expand Up @@ -106,6 +107,7 @@ export class AppManager {
this.licenseManager = new AppLicenseManager(this);
this.schedulerManager = new AppSchedulerManager(this);
this.uiActionButtonManager = new UIActionButtonManager(this);
this.videoConfProviderManager = new AppVideoConfProviderManager(this);

this.isLoaded = false;
AppManager.Instance = this;
Expand Down Expand Up @@ -151,6 +153,10 @@ export class AppManager {
return this.commandManager;
}

public getVideoConfProviderManager(): AppVideoConfProviderManager {
return this.videoConfProviderManager;
}

public getLicenseManager(): AppLicenseManager {
return this.licenseManager;
}
Expand Down Expand Up @@ -870,6 +876,7 @@ export class AppManager {
this.accessorManager.purifyApp(app.getID());
await this.schedulerManager.cleanUp(app.getID());
this.uiActionButtonManager.clearAppActionButtons(app.getID());
this.videoConfProviderManager.unregisterProviders(app.getID());
}

/**
Expand Down Expand Up @@ -936,6 +943,7 @@ export class AppManager {
this.apiManager.registerApis(app.getID());
this.listenerManager.registerListeners(app);
this.listenerManager.releaseEssentialEvents(app);
this.videoConfProviderManager.registerProviders(app.getID());
} else {
await this.purgeAppConfig(app);
}
Expand Down
2 changes: 2 additions & 0 deletions src/server/accessors/ConfigurationExtend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
ISettingsExtend,
ISlashCommandsExtend,
IUIExtend,
IVideoConfProvidersExtend,
} from '../../definition/accessors';

export class ConfigurationExtend implements IConfigurationExtend {
Expand All @@ -18,5 +19,6 @@ export class ConfigurationExtend implements IConfigurationExtend {
public readonly externalComponents: IExternalComponentsExtend,
public readonly scheduler: ISchedulerExtend,
public readonly ui: IUIExtend,
public readonly videoConfProviders: IVideoConfProvidersExtend,
) { }
}
12 changes: 12 additions & 0 deletions src/server/accessors/VideoConfProviderExtend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { AppVideoConfProviderManager } from '../managers/AppVideoConfProviderManager';

import { IVideoConfProvidersExtend } from '../../definition/accessors';
import { IVideoConfProvider } from '../../definition/videoConfProviders';

export class VideoConfProviderExtend implements IVideoConfProvidersExtend {
constructor(private readonly manager: AppVideoConfProviderManager, private readonly appId: string) { }

public provideVideoConfProvider(provider: IVideoConfProvider): Promise<void> {
return Promise.resolve(this.manager.addProvider(this.appId, provider));
}
}
2 changes: 2 additions & 0 deletions src/server/accessors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { SlashCommandsModify } from './SlashCommandsModify';
import { UploadRead } from './UploadRead';
import { UserBuilder } from './UserBuilder';
import { UserRead } from './UserRead';
import { VideoConfProviderExtend } from './VideoConfProviderExtend';

export {
ApiExtend,
Expand Down Expand Up @@ -70,4 +71,5 @@ export {
UserRead,
SchedulerExtend,
SchedulerModify,
VideoConfProviderExtend,
};
4 changes: 4 additions & 0 deletions src/server/errors/AVideoConfProviderAlreadyExistsError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export class AVideoConfProviderAlreadyExistsError implements Error {
public name = 'AVideoConfProviderAlreadyExists';
public message = 'A video conference provider is already registered in the system.';
}
4 changes: 4 additions & 0 deletions src/server/errors/NoVideoConfProviderRegisteredError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export class NoVideoConfProviderRegisteredError implements Error {
public name = 'NoVideoConfProviderRegistered';
public message = 'There are no video conference providers registered in the system.';
}
4 changes: 4 additions & 0 deletions src/server/errors/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { AVideoConfProviderAlreadyExistsError } from './AVideoConfProviderAlreadyExistsError';
import { CommandAlreadyExistsError } from './CommandAlreadyExistsError';
import { CommandHasAlreadyBeenTouchedError } from './CommandHasAlreadyBeenTouchedError';
import { CompilerError } from './CompilerError';
import { InvalidLicenseError } from './InvalidLicenseError';
import { MustContainFunctionError } from './MustContainFunctionError';
import { MustExtendAppError } from './MustExtendAppError';
import { NotEnoughMethodArgumentsError } from './NotEnoughMethodArgumentsError';
import { NoVideoConfProviderRegisteredError } from './NoVideoConfProviderRegisteredError';
import { PathAlreadyExistsError } from './PathAlreadyExistsError';
import { RequiredApiVersionError } from './RequiredApiVersionError';

Expand All @@ -18,4 +20,6 @@ export {
NotEnoughMethodArgumentsError,
RequiredApiVersionError,
InvalidLicenseError,
NoVideoConfProviderRegisteredError,
AVideoConfProviderAlreadyExistsError,
};
4 changes: 3 additions & 1 deletion src/server/managers/AppAccessorManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
SlashCommandsModify,
UploadRead,
UserRead,
VideoConfProviderExtend,
} from '../accessors';
import { CloudWorkspaceRead } from '../accessors/CloudWorkspaceRead';
import { UIExtend } from '../accessors/UIExtend';
Expand Down Expand Up @@ -87,13 +88,14 @@ export class AppAccessorManager {

const htt = new HttpExtend();
const cmds = new SlashCommandsExtend(this.manager.getCommandManager(), appId);
const videoConf = new VideoConfProviderExtend(this.manager.getVideoConfProviderManager(), appId);
const apis = new ApiExtend(this.manager.getApiManager(), appId);
const sets = new SettingsExtend(rl);
const excs = new ExternalComponentsExtend(this.manager.getExternalComponentManager(), appId);
const scheduler = new SchedulerExtend(this.manager.getSchedulerManager(), appId);
const ui = new UIExtend(this.manager.getUIActionButtonManager(), appId);

this.configExtenders.set(appId, new ConfigurationExtend(htt, sets, cmds, apis, excs, scheduler, ui));
this.configExtenders.set(appId, new ConfigurationExtend(htt, sets, cmds, apis, excs, scheduler, ui, videoConf));
}

return this.configExtenders.get(appId);
Expand Down
88 changes: 88 additions & 0 deletions src/server/managers/AppVideoConfProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { AppMethod } from '../../definition/metadata';
import type { INewVideoConference, IVideoConference, IVideoConferenceOptions, IVideoConferenceUser, IVideoConfProvider } from '../../definition/videoConfProviders';

import { ProxiedApp } from '../ProxiedApp';
import { AppLogStorage } from '../storage';
import { AppAccessorManager } from './AppAccessorManager';

export class AppVideoConfProvider {
/**
* States whether this provider has been registered into the Rocket.Chat system or not.
*/
public isRegistered: boolean;

constructor(public app: ProxiedApp, public provider: IVideoConfProvider) {
this.isRegistered = false;
}

public hasBeenRegistered(): void {
this.isRegistered = true;
}

public canBeRan(method: AppMethod): boolean {
return this.app.hasMethod(method);
}

public async runGenerateUrl(
call: INewVideoConference,
logStorage: AppLogStorage,
accessors: AppAccessorManager,
): Promise<string> {
return await this.runTheCode(AppMethod._VIDEOCONF_GENERATE_URL, logStorage, accessors, [call]);
}

public async runCustomizeUrl(
call: IVideoConference,
user: IVideoConferenceUser | undefined,
options: IVideoConferenceOptions = {},
logStorage: AppLogStorage,
accessors: AppAccessorManager,
): Promise<string> {
return await this.runTheCode(AppMethod._VIDEOCONF_CUSTOMIZE_URL, logStorage, accessors, [call, user, options]);
}

private async runTheCode(
method: AppMethod._VIDEOCONF_GENERATE_URL | AppMethod._VIDEOCONF_CUSTOMIZE_URL,
logStorage: AppLogStorage,
accessors: AppAccessorManager,
runContextArgs: Array<any>,
): Promise<string | undefined> {
// Ensure the provider has the property before going on
if (typeof this.provider[method] !== 'function') {
return;
}

const runContext = this.app.makeContext({
provider: this.provider,
args: [
...runContextArgs,
accessors.getReader(this.app.getID()),
accessors.getModifier(this.app.getID()),
accessors.getHttp(this.app.getID()),
accessors.getPersistence(this.app.getID()),
],
});

const logger = this.app.setupLogger(method);
logger.debug(`Executing ${ method } on video conference provider...`);

let result: string | undefined;
try {
const runCode = `provider.${ method }.apply(provider, args)`;
result = await this.app.runInContext(runCode, runContext);
logger.debug(`Video Conference Provider's ${ method } was successfully executed.`);
} catch (e) {
logger.error(e);
logger.debug(`Video Conference Provider's ${ method } was unsuccessful.`);
}

try {
await logStorage.storeEntries(this.app.getID(), logger);
} catch (e) {
// Don't care, at the moment.
// TODO: Evaluate to determine if we do care
}

return result;
}
}
Loading