Skip to content

Commit 581d29e

Browse files
committed
feat: apps-engine presence bridge
1 parent d98cab1 commit 581d29e

5 files changed

Lines changed: 65 additions & 1 deletion

File tree

apps/meteor/app/apps/server/bridges/users.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { IAppServerOrchestrator } from '@rocket.chat/apps';
22
import { UserBridge } from '@rocket.chat/apps/dist/server/bridges/UserBridge';
33
import type { IUserCreationOptions, IUser, UserType } from '@rocket.chat/apps-engine/definition/users';
44
import { Presence } from '@rocket.chat/core-services';
5-
import type { UserStatus } from '@rocket.chat/core-typings';
5+
import type { PresenceSource, UserStatus } from '@rocket.chat/core-typings';
66
import { Subscriptions, Users } from '@rocket.chat/models';
77
import { Random } from '@rocket.chat/random';
88

@@ -173,6 +173,27 @@ export class AppUserBridge extends UserBridge {
173173
return true;
174174
}
175175

176+
protected async setActiveState(
177+
userId: IUser['id'],
178+
state: Pick<IUser, 'statusDefault' | 'statusSource' | 'statusText' | 'statusExpiresAt'>,
179+
appId: string,
180+
): Promise<void> {
181+
this.orch.debugLog(`The App ${appId} is setting active state for user ${userId}`);
182+
183+
await Presence.setActiveState(userId, {
184+
statusDefault: state.statusDefault as UserStatus,
185+
statusText: state.statusText,
186+
statusSource: state.statusSource as PresenceSource,
187+
statusExpiresAt: state.statusExpiresAt,
188+
});
189+
}
190+
191+
protected async endActiveState(userId: IUser['id'], appId: string): Promise<void> {
192+
this.orch.debugLog(`The App ${appId} is ending active state for user ${userId}`);
193+
194+
await Presence.endActiveState(userId);
195+
}
196+
176197
protected async getActiveUserCount(): Promise<number> {
177198
return Users.getActiveLocalUserCount();
178199
}

packages/apps-engine/src/definition/accessors/IUserUpdater.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,9 @@ export interface IUserUpdater {
1515
updateBio(user: IUser, bio: IUser['bio']): Promise<boolean>;
1616
updateCustomFields(user: IUser, customFields: IUser['customFields']): Promise<boolean>;
1717
deactivate(userId: IUser['id'], confirmRelinquish: boolean): Promise<boolean>;
18+
setActiveState(
19+
userId: IUser['id'],
20+
state: Pick<IUser, 'statusDefault' | 'statusSource' | 'statusText' | 'statusExpiresAt'>,
21+
): Promise<void>;
22+
endActiveState(userId: IUser['id']): Promise<void>;
1823
}

packages/apps-engine/src/definition/users/IUser.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ export interface IUser {
1515
status: string;
1616
statusConnection: UserStatusConnection;
1717
statusText?: string;
18+
statusDefault?: string;
19+
statusSource?: 'internal' | 'external' | 'manual';
20+
statusExpiresAt?: Date;
1821
utcOffset: number;
1922
createdAt: Date;
2023
updatedAt: Date;

packages/apps/src/server/accessors/UserUpdater.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,15 @@ export class UserUpdater implements IUserUpdater {
2929
public async deactivate(userId: IUser['id'], confirmRelinquish: boolean) {
3030
return this.bridges.getUserBridge().doDeactivate(userId, confirmRelinquish, this.appId);
3131
}
32+
33+
public async setActiveState(
34+
userId: IUser['id'],
35+
state: Pick<IUser, 'statusDefault' | 'statusSource' | 'statusText' | 'statusExpiresAt'>,
36+
) {
37+
return this.bridges.getUserBridge().doSetActiveState(userId, state, this.appId);
38+
}
39+
40+
public async endActiveState(userId: IUser['id']) {
41+
return this.bridges.getUserBridge().doEndActiveState(userId, this.appId);
42+
}
3243
}

packages/apps/src/server/bridges/UserBridge.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,22 @@ export abstract class UserBridge extends BaseBridge {
6464
}
6565
}
6666

67+
public async doSetActiveState(
68+
userId: IUser['id'],
69+
state: Pick<IUser, 'statusDefault' | 'statusSource' | 'statusText' | 'statusExpiresAt'>,
70+
appId: string,
71+
): Promise<void> {
72+
if (this.hasWritePermission(appId)) {
73+
await this.setActiveState(userId, state, appId);
74+
}
75+
}
76+
77+
public async doEndActiveState(userId: IUser['id'], appId: string): Promise<void> {
78+
if (this.hasWritePermission(appId)) {
79+
await this.endActiveState(userId, appId);
80+
}
81+
}
82+
6783
protected abstract getById(id: string, appId: string): Promise<IUser>;
6884

6985
protected abstract getByUsername(username: string, appId: string): Promise<IUser>;
@@ -126,6 +142,14 @@ export abstract class UserBridge extends BaseBridge {
126142
*/
127143
protected abstract deactivate(userId: IUser['id'], confirmRelinquish: boolean, appId: string): Promise<boolean>;
128144

145+
protected abstract setActiveState(
146+
userId: IUser['id'],
147+
state: Pick<IUser, 'statusDefault' | 'statusSource' | 'statusText' | 'statusExpiresAt'>,
148+
appId: string,
149+
): Promise<void>;
150+
151+
protected abstract endActiveState(userId: IUser['id'], appId: string): Promise<void>;
152+
129153
private hasReadPermission(appId: string): boolean {
130154
if (AppPermissionManager.hasPermission(appId, AppPermissions.user.read)) {
131155
return true;

0 commit comments

Comments
 (0)