@messenger-box/platform-server 10.0.3-alpha.7 → 10.0.3-alpha.72
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/containers/containers.js +4 -1
- package/lib/containers/containers.js.map +1 -1
- package/lib/containers/context-services-from-container.d.ts +1 -1
- package/lib/containers/context-services-from-container.js +1 -1
- package/lib/containers/context-services-from-container.js.map +1 -1
- package/lib/graphql/resolvers/channel-member.d.ts +3 -2
- package/lib/graphql/resolvers/channel-member.js +30 -5
- package/lib/graphql/resolvers/channel-member.js.map +1 -1
- package/lib/graphql/resolvers/channel.d.ts +3 -2
- package/lib/graphql/resolvers/channel.js +279 -53
- package/lib/graphql/resolvers/channel.js.map +1 -1
- package/lib/graphql/resolvers/extended-token-account.d.ts +3 -2
- package/lib/graphql/resolvers/extended-token-account.js +90 -23
- package/lib/graphql/resolvers/extended-token-account.js.map +1 -1
- package/lib/graphql/resolvers/index.d.ts +1 -1
- package/lib/graphql/resolvers/post-thread.d.ts +1 -1
- package/lib/graphql/resolvers/post-thread.js +294 -132
- package/lib/graphql/resolvers/post-thread.js.map +1 -1
- package/lib/graphql/resolvers/post.d.ts +2 -3
- package/lib/graphql/resolvers/post.js +696 -234
- package/lib/graphql/resolvers/post.js.map +1 -1
- package/lib/graphql/resolvers/reaction.d.ts +3 -2
- package/lib/graphql/resolvers/reaction.js +96 -14
- package/lib/graphql/resolvers/reaction.js.map +1 -1
- package/lib/graphql/schema/channel-member.graphql +110 -21
- package/lib/graphql/schema/channel-member.graphql.js +1 -1
- package/lib/graphql/schema/channel.graphql +337 -38
- package/lib/graphql/schema/channel.graphql.js +1 -1
- package/lib/graphql/schema/post-thread.graphql +167 -21
- package/lib/graphql/schema/post-thread.graphql.js +1 -1
- package/lib/graphql/schema/post.graphql +284 -40
- package/lib/graphql/schema/post.graphql.js +1 -1
- package/lib/graphql/schema/reaction.graphql +71 -13
- package/lib/graphql/schema/reaction.graphql.js +1 -1
- package/lib/graphql/schema/services.graphql +2 -0
- package/lib/graphql/schema/users.graphql +76 -13
- package/lib/graphql/schema/users.graphql.js +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/interfaces/index.d.ts +0 -1
- package/lib/interfaces/services.d.ts +1 -1
- package/lib/migrations/dbMigrations/AddPostsConfigurationsMigration.d.ts +17 -0
- package/lib/migrations/dbMigrations/AddPostsConfigurationsMigration.js +44 -0
- package/lib/migrations/dbMigrations/AddPostsConfigurationsMigration.js.map +1 -0
- package/lib/migrations/dbMigrations/index.d.ts +1 -0
- package/lib/migrations/index.d.ts +1 -0
- package/lib/migrations/mail-template-migration.js +1 -1
- package/lib/migrations/message-notification-template-migration.d.ts +1 -1
- package/lib/migrations/message-notification-template-migration.js +1 -1
- package/lib/plugins/channel-moleculer-service.d.ts +21 -1
- package/lib/plugins/channel-moleculer-service.js +417 -115
- package/lib/plugins/channel-moleculer-service.js.map +1 -1
- package/lib/plugins/extended-token-account-moleculer-service.d.ts +25 -1
- package/lib/plugins/extended-token-account-moleculer-service.js +348 -22
- package/lib/plugins/extended-token-account-moleculer-service.js.map +1 -1
- package/lib/plugins/messenger-notification-moleculer-service.d.ts +27 -3
- package/lib/plugins/messenger-notification-moleculer-service.js +404 -58
- package/lib/plugins/messenger-notification-moleculer-service.js.map +1 -1
- package/lib/plugins/post-moleculer-service.d.ts +85 -21
- package/lib/plugins/post-moleculer-service.js +986 -256
- package/lib/plugins/post-moleculer-service.js.map +1 -1
- package/lib/plugins/post-thread-moleculer-service.d.ts +33 -1
- package/lib/plugins/post-thread-moleculer-service.js +326 -8
- package/lib/plugins/post-thread-moleculer-service.js.map +1 -1
- package/lib/plugins/reaction-moleculer-service.js +1 -1
- package/lib/plugins/reaction-moleculer-service.js.map +1 -1
- package/lib/preferences/settings/post-settings.d.ts +2 -0
- package/lib/preferences/settings/post-settings.js +47 -9
- package/lib/preferences/settings/post-settings.js.map +1 -1
- package/lib/services/channel-service.d.ts +179 -33
- package/lib/services/channel-service.js +821 -274
- package/lib/services/channel-service.js.map +1 -1
- package/lib/services/extended-token-account-service.d.ts +130 -14
- package/lib/services/extended-token-account-service.js +462 -52
- package/lib/services/extended-token-account-service.js.map +1 -1
- package/lib/services/index.d.ts +1 -0
- package/lib/services/messenger-notification-service.d.ts +106 -13
- package/lib/services/messenger-notification-service.js +824 -442
- package/lib/services/messenger-notification-service.js.map +1 -1
- package/lib/services/post-service.d.ts +182 -16
- package/lib/services/post-service.js +731 -115
- package/lib/services/post-service.js.map +1 -1
- package/lib/services/post-thread-service.d.ts +114 -5
- package/lib/services/post-thread-service.js +400 -13
- package/lib/services/post-thread-service.js.map +1 -1
- package/lib/services/proxy-services/channel-microservice.d.ts +5 -3
- package/lib/services/proxy-services/channel-microservice.js +19 -10
- package/lib/services/proxy-services/channel-microservice.js.map +1 -1
- package/lib/services/proxy-services/messenger-notification-microservice.d.ts +128 -8
- package/lib/services/proxy-services/messenger-notification-microservice.js +324 -29
- package/lib/services/proxy-services/messenger-notification-microservice.js.map +1 -1
- package/lib/services/proxy-services/post-microservice.d.ts +186 -12
- package/lib/services/proxy-services/post-microservice.js +543 -54
- package/lib/services/proxy-services/post-microservice.js.map +1 -1
- package/lib/services/proxy-services/post-thread-microservice.d.ts +134 -3
- package/lib/services/proxy-services/post-thread-microservice.js +388 -6
- package/lib/services/proxy-services/post-thread-microservice.js.map +1 -1
- package/lib/services/proxy-services/reaction-microservice.d.ts +161 -3
- package/lib/services/proxy-services/reaction-microservice.js +474 -2
- package/lib/services/proxy-services/reaction-microservice.js.map +1 -1
- package/lib/services/reaction-service.d.ts +124 -4
- package/lib/services/reaction-service.js +415 -3
- package/lib/services/reaction-service.js.map +1 -1
- package/lib/services/redis-cache-manager.d.ts +18 -0
- package/lib/services/redis-cache-manager.js +83 -0
- package/lib/services/redis-cache-manager.js.map +1 -0
- package/lib/store/models/account-token-store.d.ts +1 -1
- package/lib/store/models/account-token-store.js.map +1 -1
- package/lib/store/models/channel.d.ts +2 -3
- package/lib/store/models/channel.js +181 -72
- package/lib/store/models/channel.js.map +1 -1
- package/lib/store/models/post-thread.d.ts +3 -3
- package/lib/store/models/post-thread.js +96 -14
- package/lib/store/models/post-thread.js.map +1 -1
- package/lib/store/models/post.d.ts +2 -3
- package/lib/store/models/post.js +143 -23
- package/lib/store/models/post.js.map +1 -1
- package/lib/store/models/reaction.d.ts +2 -3
- package/lib/store/models/reaction.js +67 -8
- package/lib/store/models/reaction.js.map +1 -1
- package/lib/store/repositories/__tests__/__fixtures__/team-repository.d.ts +3 -3
- package/lib/store/repositories/channel-repository.d.ts +6 -6
- package/lib/store/repositories/channel-repository.js +5 -2
- package/lib/store/repositories/channel-repository.js.map +1 -1
- package/lib/store/repositories/post-repository.d.ts +6 -6
- package/lib/store/repositories/post-repository.js +5 -2
- package/lib/store/repositories/post-repository.js.map +1 -1
- package/lib/store/repositories/post-thread-repository.d.ts +6 -6
- package/lib/store/repositories/post-thread-repository.js +5 -2
- package/lib/store/repositories/post-thread-repository.js.map +1 -1
- package/lib/store/repositories/reaction-repository.d.ts +6 -6
- package/lib/store/repositories/reaction-repository.js +5 -2
- package/lib/store/repositories/reaction-repository.js.map +1 -1
- package/lib/templates/constants/SERVER_TYPES.ts.template +0 -3
- package/lib/templates/repositories/ChannelRepository.ts.template +3 -3
- package/lib/templates/repositories/PostRepository.ts.template +3 -3
- package/lib/templates/repositories/PostThreadRepository.ts.template +3 -3
- package/lib/templates/repositories/ReactionRepository.ts.template +3 -4
- package/lib/templates/services/ChannelService.ts.template +280 -39
- package/lib/templates/services/ExtendedTokenAccountService.ts.template +104 -9
- package/lib/templates/services/MessengerNotificationService.ts.template +94 -19
- package/lib/templates/services/PostService.ts.template +184 -20
- package/lib/templates/services/PostThreadService.ts.template +151 -6
- package/lib/templates/services/ReactionService.ts.template +129 -3
- package/lib/templates/services/RedisCacheManager.ts.template +22 -0
- package/package.json +6 -5
- package/lib/interfaces/context.d.ts +0 -14
- package/lib/store/models/common-options.js +0 -20
- package/lib/store/models/common-options.js.map +0 -1
|
@@ -1,272 +1,718 @@
|
|
|
1
|
-
import {__decorate,__param,__metadata}from'tslib';import {inject}from'inversify';import {SERVER_TYPES,RoomType,SortEnum}from'common';import {
|
|
2
|
-
|
|
1
|
+
import {__decorate,__param,__metadata}from'tslib';import {injectable,inject}from'inversify';import {Emitter,DisposableCollection}from'@adminide-stack/core';import {SERVER_TYPES,RoomType,SortEnum}from'common/server';import {BaseService2}from'@common-stack/store-mongo';import'@cdm-logger/core';import {ServiceBroker}from'moleculer';import {CommonType}from'@common-stack/core';import'../constants/query.constants.js';import {DEFAULT_NOTIFY_PROPS}from'../constants/default-notify-props.js';import {config}from'../config/env-config.js';var ChannelService_1;
|
|
2
|
+
const CACHE_TTL = {
|
|
3
|
+
maxAge: 5 * 60,
|
|
4
|
+
scope: 'PUBLIC'
|
|
5
|
+
}; // 5 minutes
|
|
6
|
+
/**
|
|
7
|
+
* Modern implementation of the Channel Service
|
|
8
|
+
*
|
|
9
|
+
* This service handles comprehensive channel management within the messenger platform,
|
|
10
|
+
* providing operations for managing channels, their members, and related messaging workflows.
|
|
11
|
+
*
|
|
12
|
+
* Key capabilities:
|
|
13
|
+
* - Channel lifecycle management (creation, updates, deletion)
|
|
14
|
+
* - Member management (adding, removing, role assignment)
|
|
15
|
+
* - Direct and public channel handling
|
|
16
|
+
* - Message and post management within channels
|
|
17
|
+
* - Channel visibility and access control
|
|
18
|
+
* - Notification and unread message tracking
|
|
19
|
+
* - Team-based channel organization
|
|
20
|
+
* - Channel discovery and filtering
|
|
21
|
+
* - Redis caching for performance optimization
|
|
22
|
+
* - Comprehensive error handling and logging
|
|
23
|
+
* - Event-driven architecture with proper disposal
|
|
24
|
+
*
|
|
25
|
+
* The service layer abstracts the underlying data access operations and
|
|
26
|
+
* provides a cohesive API for channel-related functionality throughout
|
|
27
|
+
* the messaging platform, handling complex business rules and cross-cutting concerns.
|
|
28
|
+
*/
|
|
29
|
+
let ChannelService = ChannelService_1 = class ChannelService extends BaseService2 {
|
|
3
30
|
repository;
|
|
4
31
|
postService;
|
|
5
|
-
|
|
32
|
+
broker;
|
|
33
|
+
redisCacheManager;
|
|
34
|
+
redisClient;
|
|
35
|
+
// Event emitters for channel lifecycle events
|
|
36
|
+
onChannelCreated = new Emitter();
|
|
37
|
+
onChannelUpdated = new Emitter();
|
|
38
|
+
onChannelDeleted = new Emitter();
|
|
39
|
+
onChannelRestored = new Emitter();
|
|
40
|
+
onMemberAdded = new Emitter();
|
|
41
|
+
onMemberRemoved = new Emitter();
|
|
42
|
+
onChannelViewed = new Emitter();
|
|
43
|
+
toDispose = new DisposableCollection(this.onChannelCreated, this.onChannelUpdated, this.onChannelDeleted, this.onChannelRestored, this.onMemberAdded, this.onMemberRemoved, this.onChannelViewed);
|
|
44
|
+
logger;
|
|
45
|
+
constructor(repository, postService, broker, redisCacheManager, redisClient, logger) {
|
|
6
46
|
super(repository);
|
|
7
47
|
this.repository = repository;
|
|
8
48
|
this.postService = postService;
|
|
49
|
+
this.broker = broker;
|
|
50
|
+
this.redisCacheManager = redisCacheManager;
|
|
51
|
+
this.redisClient = redisClient;
|
|
52
|
+
this.logger = logger?.child({
|
|
53
|
+
className: 'ChannelService'
|
|
54
|
+
}) || console;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Disposes of resources used by the service
|
|
58
|
+
*/
|
|
59
|
+
dispose() {
|
|
60
|
+
this.toDispose.dispose();
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Helper method to make service calls
|
|
64
|
+
* @param command - Command to execute
|
|
65
|
+
* @param params - Command parameters
|
|
66
|
+
* @param topic - Service topic
|
|
67
|
+
* @param opts - Call options
|
|
68
|
+
* @returns Command result
|
|
69
|
+
*/
|
|
70
|
+
async callAction(command, params, topic, opts) {
|
|
71
|
+
try {
|
|
72
|
+
if (!this.broker) {
|
|
73
|
+
throw new Error('Service broker not available');
|
|
74
|
+
}
|
|
75
|
+
const actionName = topic ? `${topic}.${command}` : command;
|
|
76
|
+
return await this.broker.call(actionName, params, opts);
|
|
77
|
+
} catch (error) {
|
|
78
|
+
this.logger.error(`Error calling action ${command}: %o`, error);
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
9
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Enhanced method to check if a user is a member of a specific channel
|
|
84
|
+
*
|
|
85
|
+
* @description Verifies channel membership with proper error handling and logging
|
|
86
|
+
*
|
|
87
|
+
* @param {string} channelId - The ID of the channel to check
|
|
88
|
+
* @param {string} user - The ID of the user
|
|
89
|
+
* @returns {Promise<boolean>} - True if the user is a member
|
|
90
|
+
*/
|
|
10
91
|
async isMember(channelId, user) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
92
|
+
try {
|
|
93
|
+
if (!channelId || !user) {
|
|
94
|
+
this.logger.warn('Channel ID and user ID are required for membership check');
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
this.logger.debug('Checking channel membership', {
|
|
98
|
+
channelId,
|
|
99
|
+
userId: user
|
|
100
|
+
});
|
|
101
|
+
const channel = await this.get(channelId);
|
|
102
|
+
if (!channel?.members) {
|
|
103
|
+
this.logger.debug('Channel not found or has no members', {
|
|
104
|
+
channelId
|
|
105
|
+
});
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
const isMember = !!channel.members.find(member => member.user && member.user.toString() === user.toString());
|
|
109
|
+
this.logger.debug('Channel membership check result', {
|
|
110
|
+
channelId,
|
|
111
|
+
userId: user,
|
|
112
|
+
isMember
|
|
113
|
+
});
|
|
114
|
+
return isMember;
|
|
115
|
+
} catch (error) {
|
|
116
|
+
this.logger.error('Error checking channel membership: %o', error);
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
16
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Enhanced method to get default notification properties
|
|
122
|
+
*
|
|
123
|
+
* @description Retrieves default notification settings with extensibility
|
|
124
|
+
*
|
|
125
|
+
* @returns {INotificationProps} - Default notification properties
|
|
126
|
+
*/
|
|
17
127
|
get defaultNotifyProps() {
|
|
18
|
-
|
|
19
|
-
|
|
128
|
+
try {
|
|
129
|
+
// Future enhancement: Load from user preferences or organization settings
|
|
130
|
+
return DEFAULT_NOTIFY_PROPS;
|
|
131
|
+
} catch (error) {
|
|
132
|
+
this.logger.error('Error getting default notification props: %o', error);
|
|
133
|
+
return DEFAULT_NOTIFY_PROPS;
|
|
134
|
+
}
|
|
20
135
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
136
|
+
/**
|
|
137
|
+
* Enhanced method to get maximum channels per team with configuration support
|
|
138
|
+
*
|
|
139
|
+
* @description Retrieves channel limit with future configuration support
|
|
140
|
+
*
|
|
141
|
+
* @param {string} teamId - The ID of the team
|
|
142
|
+
* @returns {Promise<number>} - Maximum number of channels allowed
|
|
143
|
+
*/
|
|
144
|
+
static async getMaxChannelsPerTeam(teamId) {
|
|
145
|
+
try {
|
|
146
|
+
// Future enhancement: Get from team settings or organization configuration
|
|
147
|
+
return Promise.resolve(100); // Default max channels per team
|
|
148
|
+
} catch (error) {
|
|
149
|
+
console.error('Error getting max channels per team:', error);
|
|
150
|
+
return Promise.resolve(10); // Fallback value
|
|
151
|
+
}
|
|
24
152
|
}
|
|
153
|
+
/**
|
|
154
|
+
* Enhanced method to get current channel count per team
|
|
155
|
+
*
|
|
156
|
+
* @description Counts active channels for a team with proper error handling
|
|
157
|
+
*
|
|
158
|
+
* @param {string} team - The team identifier
|
|
159
|
+
* @returns {Promise<number>} - Current channel count
|
|
160
|
+
*/
|
|
25
161
|
async getCurrentChannelCountPerTeam(team) {
|
|
26
|
-
|
|
27
|
-
team
|
|
28
|
-
|
|
29
|
-
|
|
162
|
+
try {
|
|
163
|
+
if (!team) {
|
|
164
|
+
this.logger.warn('Team ID is required for channel count');
|
|
165
|
+
return 0;
|
|
166
|
+
}
|
|
167
|
+
const count = await this.repository.count({
|
|
168
|
+
team,
|
|
169
|
+
type: RoomType.Channel,
|
|
170
|
+
deletedAt: {
|
|
171
|
+
$exists: false
|
|
172
|
+
} // Only count non-deleted channels
|
|
173
|
+
});
|
|
174
|
+
this.logger.debug('Current channel count for team', {
|
|
175
|
+
team,
|
|
176
|
+
count
|
|
177
|
+
});
|
|
178
|
+
return count;
|
|
179
|
+
} catch (error) {
|
|
180
|
+
this.logger.error('Error getting current channel count per team: %o', error);
|
|
181
|
+
return 0;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Enhanced method to generate DM name from user IDs
|
|
186
|
+
*
|
|
187
|
+
* @description Creates a standardized direct message channel name
|
|
188
|
+
*
|
|
189
|
+
* @param {string} senderId - The sender's user ID
|
|
190
|
+
* @param {string} receiverId - The receiver's user ID
|
|
191
|
+
* @returns {string} - Generated DM name
|
|
192
|
+
*/
|
|
193
|
+
static getDmNameFromIds(senderId, receiverId) {
|
|
194
|
+
try {
|
|
195
|
+
if (!senderId || !receiverId) {
|
|
196
|
+
throw new Error('Both sender and receiver IDs are required');
|
|
197
|
+
}
|
|
198
|
+
// Sort IDs to ensure consistent naming regardless of order
|
|
199
|
+
const [id1, id2] = [senderId, receiverId].sort();
|
|
200
|
+
return `${id1}__${id2}`;
|
|
201
|
+
} catch (error) {
|
|
202
|
+
console.error('Error generating DM name:', error);
|
|
203
|
+
return `${senderId}__${receiverId}`;
|
|
204
|
+
}
|
|
30
205
|
}
|
|
206
|
+
/**
|
|
207
|
+
* Enhanced method to create a direct channel between users
|
|
208
|
+
*
|
|
209
|
+
* @description Creates direct channels with comprehensive validation and error handling
|
|
210
|
+
*
|
|
211
|
+
* @param {ICreateDirectChannelParams} data - The direct channel creation parameters
|
|
212
|
+
* @returns {Promise<AsDomainType<IChannelModel> | Error>} - The created channel or error
|
|
213
|
+
*/
|
|
31
214
|
async createDirectChannel(data) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
215
|
+
try {
|
|
216
|
+
this.logger.debug('Creating direct channel', {
|
|
217
|
+
sender: data.sender,
|
|
218
|
+
receiverCount: data.receiver?.length || 0,
|
|
219
|
+
orgName: data.orgName
|
|
220
|
+
});
|
|
221
|
+
const {
|
|
222
|
+
sender,
|
|
223
|
+
receiver,
|
|
224
|
+
displayName,
|
|
225
|
+
orgName,
|
|
226
|
+
channelOptions
|
|
227
|
+
} = data;
|
|
228
|
+
if (!sender) {
|
|
229
|
+
return new Error('Sender ID is required');
|
|
230
|
+
}
|
|
231
|
+
if (!receiver || receiver.length === 0) {
|
|
232
|
+
return new Error('At least one receiver is required');
|
|
233
|
+
}
|
|
234
|
+
// Check for duplicate direct channel
|
|
235
|
+
const existingChannelName = ChannelService_1.getDmNameFromIds(sender, receiver[0]);
|
|
236
|
+
const existingChannel = await this.getByName(existingChannelName);
|
|
237
|
+
if (existingChannel) {
|
|
238
|
+
this.logger.debug('Direct channel already exists', {
|
|
239
|
+
channelName: existingChannelName
|
|
50
240
|
});
|
|
241
|
+
return existingChannel;
|
|
51
242
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
243
|
+
// Build channel members
|
|
244
|
+
const channelMembers = [{
|
|
245
|
+
user: sender,
|
|
246
|
+
schemeAdmin: channelOptions?.schemeAdmin || false,
|
|
247
|
+
notifyProps: this.defaultNotifyProps
|
|
248
|
+
}];
|
|
249
|
+
receiver.forEach(receiverId => {
|
|
250
|
+
if (receiverId !== sender) {
|
|
251
|
+
channelMembers.push({
|
|
252
|
+
user: receiverId,
|
|
253
|
+
schemeAdmin: channelOptions?.schemeAdmin || false,
|
|
254
|
+
notifyProps: this.defaultNotifyProps
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
const channelPayload = {
|
|
259
|
+
title: displayName || ChannelService_1.getDmNameFromIds(sender, receiver[0]),
|
|
260
|
+
orgName,
|
|
261
|
+
organization: orgName,
|
|
262
|
+
type: RoomType.Direct,
|
|
263
|
+
creator: sender,
|
|
264
|
+
members: channelMembers,
|
|
265
|
+
displayName: displayName || `Direct chat`,
|
|
266
|
+
_id: undefined // Allow repository to generate
|
|
267
|
+
};
|
|
268
|
+
const result = await this.saveDirectChannel(channelPayload);
|
|
269
|
+
if (!(result instanceof Error)) {
|
|
270
|
+
this.onChannelCreated.fire({
|
|
271
|
+
channel: result,
|
|
272
|
+
userContext: {
|
|
273
|
+
accountId: sender,
|
|
274
|
+
tenantId: orgName
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
return result;
|
|
279
|
+
} catch (error) {
|
|
280
|
+
this.logger.error('Error creating direct channel: %o', error);
|
|
281
|
+
return error instanceof Error ? error : new Error('Unknown error occurred while creating direct channel');
|
|
282
|
+
}
|
|
62
283
|
}
|
|
284
|
+
/**
|
|
285
|
+
* Enhanced method to save a direct channel
|
|
286
|
+
*
|
|
287
|
+
* @description Saves direct channels with comprehensive validation
|
|
288
|
+
*
|
|
289
|
+
* @param {ISaveDirectChannelParams} channel - The direct channel parameters
|
|
290
|
+
* @returns {Promise<AsDomainType<IChannelModel> | Error>} - The created channel or error
|
|
291
|
+
*/
|
|
63
292
|
async saveDirectChannel(channel) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
293
|
+
try {
|
|
294
|
+
this.logger.debug('Saving direct channel', {
|
|
295
|
+
type: channel.type,
|
|
296
|
+
creator: channel.creator,
|
|
297
|
+
memberCount: channel.members?.length || 0
|
|
298
|
+
});
|
|
299
|
+
const {
|
|
300
|
+
type,
|
|
301
|
+
deletedAt
|
|
302
|
+
} = channel;
|
|
303
|
+
if (deletedAt) {
|
|
304
|
+
return new Error('Deleted channels cannot be saved');
|
|
305
|
+
}
|
|
306
|
+
if (type !== RoomType.Direct) {
|
|
307
|
+
return new Error('Only direct channels are allowed in this method');
|
|
308
|
+
}
|
|
309
|
+
const result = await this.repository.create(channel);
|
|
310
|
+
this.logger.debug('Direct channel saved successfully', {
|
|
311
|
+
channelId: result.id,
|
|
312
|
+
type: result.type
|
|
313
|
+
});
|
|
314
|
+
return result;
|
|
315
|
+
} catch (error) {
|
|
316
|
+
this.logger.error('Error saving direct channel: %o', error);
|
|
317
|
+
return error instanceof Error ? error : new Error('Unknown error occurred while saving direct channel');
|
|
73
318
|
}
|
|
74
|
-
return this.repository.create(channel);
|
|
75
319
|
}
|
|
320
|
+
/**
|
|
321
|
+
* Enhanced method to add a member to a channel
|
|
322
|
+
*
|
|
323
|
+
* @description Adds a single member to a channel with comprehensive validation and event firing
|
|
324
|
+
*
|
|
325
|
+
* @param {string} channelId - The ID of the channel
|
|
326
|
+
* @param {string} memberId - The ID of the member to add
|
|
327
|
+
* @returns {Promise<AsDomainType<IChannelModel> | Error>} - The updated channel or error
|
|
328
|
+
*/
|
|
76
329
|
async addMemberToChannel(channelId, memberId) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}).then(async res => {
|
|
82
|
-
const mebs = res.members;
|
|
83
|
-
mebs.push({
|
|
84
|
-
id: '',
|
|
85
|
-
user: memberId,
|
|
86
|
-
schemeAdmin: false,
|
|
87
|
-
notifyProps: this.defaultNotifyProps
|
|
330
|
+
try {
|
|
331
|
+
this.logger.debug('Adding member to channel', {
|
|
332
|
+
channelId,
|
|
333
|
+
memberId
|
|
88
334
|
});
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
335
|
+
if (!channelId || !memberId) {
|
|
336
|
+
return new Error('Channel ID and member ID are required');
|
|
337
|
+
}
|
|
338
|
+
// Check if member is already in channel
|
|
339
|
+
const isMember = await this.isMember(channelId, memberId);
|
|
340
|
+
if (isMember) {
|
|
341
|
+
this.logger.debug('Member already exists in channel', {
|
|
342
|
+
channelId,
|
|
343
|
+
memberId
|
|
344
|
+
});
|
|
345
|
+
return await this.get(channelId);
|
|
346
|
+
}
|
|
347
|
+
const resData = await this.repository.get({
|
|
92
348
|
id: channelId
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
349
|
+
}).then(async res => {
|
|
350
|
+
if (!res) {
|
|
351
|
+
throw new Error(`Channel ${channelId} not found`);
|
|
352
|
+
}
|
|
353
|
+
const members = res.members || [];
|
|
354
|
+
members.push({
|
|
355
|
+
user: memberId,
|
|
356
|
+
schemeAdmin: false,
|
|
357
|
+
notifyProps: this.defaultNotifyProps
|
|
358
|
+
});
|
|
359
|
+
const objToUpdate = {
|
|
360
|
+
...res,
|
|
361
|
+
members
|
|
362
|
+
};
|
|
363
|
+
const finalResult = await this.repository.update({
|
|
364
|
+
id: channelId
|
|
365
|
+
}, objToUpdate, {
|
|
366
|
+
overwrite: true
|
|
367
|
+
});
|
|
368
|
+
return finalResult;
|
|
369
|
+
}).catch(err => {
|
|
370
|
+
this.logger.error('Error in addMemberToChannel operation: %o', err);
|
|
371
|
+
return err;
|
|
372
|
+
});
|
|
373
|
+
if (resData instanceof Error) {
|
|
374
|
+
return resData;
|
|
375
|
+
}
|
|
376
|
+
// Fire member added event
|
|
377
|
+
this.onMemberAdded.fire({
|
|
378
|
+
channelId,
|
|
379
|
+
memberId,
|
|
380
|
+
userContext: {
|
|
381
|
+
accountId: memberId
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
this.logger.debug('Member added to channel successfully', {
|
|
385
|
+
channelId,
|
|
386
|
+
memberId
|
|
387
|
+
});
|
|
388
|
+
return resData;
|
|
389
|
+
} catch (error) {
|
|
390
|
+
this.logger.error('Error adding member to channel: %o', error);
|
|
391
|
+
return error instanceof Error ? error : new Error('Unknown error occurred while adding member to channel');
|
|
392
|
+
}
|
|
99
393
|
}
|
|
100
394
|
async saveMembersToChannel(data) {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if (membersIds
|
|
111
|
-
membersIds
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
395
|
+
try {
|
|
396
|
+
const {
|
|
397
|
+
channelId,
|
|
398
|
+
membersIds
|
|
399
|
+
} = data;
|
|
400
|
+
const resData = await this.repository.get({
|
|
401
|
+
id: channelId
|
|
402
|
+
}).then(async res => {
|
|
403
|
+
let mebs = res.members || [];
|
|
404
|
+
if (Array.isArray(membersIds)) {
|
|
405
|
+
if (membersIds?.length) {
|
|
406
|
+
membersIds.forEach(mid => {
|
|
407
|
+
mebs.push({
|
|
408
|
+
user: mid,
|
|
409
|
+
schemeAdmin: false,
|
|
410
|
+
notifyProps: this.defaultNotifyProps
|
|
411
|
+
});
|
|
117
412
|
});
|
|
118
|
-
}
|
|
413
|
+
}
|
|
119
414
|
}
|
|
415
|
+
const objToUpdate = res;
|
|
416
|
+
objToUpdate.members = mebs;
|
|
417
|
+
const finalResult = await this.repository.update({
|
|
418
|
+
id: channelId
|
|
419
|
+
}, objToUpdate, {
|
|
420
|
+
overwrite: true
|
|
421
|
+
});
|
|
422
|
+
return finalResult;
|
|
423
|
+
}).catch(err => err);
|
|
424
|
+
if (resData instanceof Error) {
|
|
425
|
+
return resData;
|
|
120
426
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
overwrite: true
|
|
127
|
-
});
|
|
128
|
-
return finalResult;
|
|
129
|
-
}).catch(err => err);
|
|
130
|
-
return resData;
|
|
427
|
+
return resData;
|
|
428
|
+
} catch (error) {
|
|
429
|
+
this.logger.error('Error saving members to channel: %o', error);
|
|
430
|
+
return error instanceof Error ? error : new Error('Unknown error occurred');
|
|
431
|
+
}
|
|
131
432
|
}
|
|
132
433
|
async saveChannel(data) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if (team) {
|
|
142
|
-
const maxChannels = await ChannelService_1.getMaxChannelsPerTeam(team);
|
|
143
|
-
const currentChannels = await this.getCurrentChannelCountPerTeam(team);
|
|
144
|
-
const canAddNewChannel = currentChannels < maxChannels;
|
|
145
|
-
if (!canAddNewChannel) {
|
|
146
|
-
throw Error(`Only max of ${maxChannels} allowed`);
|
|
434
|
+
try {
|
|
435
|
+
const {
|
|
436
|
+
type,
|
|
437
|
+
team,
|
|
438
|
+
creator
|
|
439
|
+
} = data;
|
|
440
|
+
if (type === RoomType.Direct) {
|
|
441
|
+
return new Error('Invalid Channel Type');
|
|
147
442
|
}
|
|
443
|
+
if (team) {
|
|
444
|
+
const maxChannels = await ChannelService_1.getMaxChannelsPerTeam(team);
|
|
445
|
+
const currentChannels = await this.getCurrentChannelCountPerTeam(team);
|
|
446
|
+
const canAddNewChannel = currentChannels < maxChannels;
|
|
447
|
+
if (!canAddNewChannel) {
|
|
448
|
+
return new Error(`Only max of ${maxChannels} allowed`);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
const channelPayload = {
|
|
452
|
+
...data,
|
|
453
|
+
members: [{
|
|
454
|
+
user: creator,
|
|
455
|
+
schemeAdmin: false,
|
|
456
|
+
notifyProps: this.defaultNotifyProps
|
|
457
|
+
}]
|
|
458
|
+
};
|
|
459
|
+
const result = await this.repository.create(channelPayload);
|
|
460
|
+
return result;
|
|
461
|
+
} catch (error) {
|
|
462
|
+
this.logger.error('Error saving channel: %o', error);
|
|
463
|
+
return error instanceof Error ? error : new Error('Unknown error occurred');
|
|
148
464
|
}
|
|
149
|
-
const channelPayload = {
|
|
150
|
-
...data,
|
|
151
|
-
members: [{
|
|
152
|
-
user: creator,
|
|
153
|
-
schemeAdmin: false,
|
|
154
|
-
notifyProps: this.defaultNotifyProps
|
|
155
|
-
}]
|
|
156
|
-
};
|
|
157
|
-
return this.repository.create(channelPayload);
|
|
158
465
|
}
|
|
159
466
|
async savePublicChannel(data) {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
467
|
+
try {
|
|
468
|
+
const {
|
|
469
|
+
type
|
|
470
|
+
} = data;
|
|
471
|
+
if (type !== RoomType.Public) {
|
|
472
|
+
return new Error('Invalid Channel Type');
|
|
473
|
+
}
|
|
474
|
+
const result = await this.repository.create(data);
|
|
475
|
+
return result;
|
|
476
|
+
} catch (error) {
|
|
477
|
+
this.logger.error('Error saving public channel: %o', error);
|
|
478
|
+
return error instanceof Error ? error : new Error('Unknown error occurred');
|
|
165
479
|
}
|
|
166
|
-
return this.repository.create(data);
|
|
167
480
|
}
|
|
168
481
|
async getChannelUnread(channelId, userId) {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
482
|
+
try {
|
|
483
|
+
const channel = await this.repository.get({
|
|
484
|
+
id: channelId,
|
|
485
|
+
members: {
|
|
486
|
+
user: userId
|
|
487
|
+
}
|
|
488
|
+
}); // Type assertion to handle the interface mismatch
|
|
489
|
+
const {
|
|
490
|
+
members,
|
|
491
|
+
team,
|
|
492
|
+
id
|
|
493
|
+
} = channel;
|
|
494
|
+
const member = members?.find(i => i.user && i.user.toString() === userId);
|
|
495
|
+
if (!member) {
|
|
496
|
+
return {
|
|
497
|
+
channelId: id,
|
|
498
|
+
teamId: team ? team.toString() : '',
|
|
499
|
+
msgCount: 0,
|
|
500
|
+
msgCountRoot: 0,
|
|
501
|
+
mentionCount: 0,
|
|
502
|
+
notifyProps: this.defaultNotifyProps,
|
|
503
|
+
mentionCountRoot: 0
|
|
504
|
+
};
|
|
173
505
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
notifyProps,
|
|
195
|
-
mentionCountRoot
|
|
196
|
-
};
|
|
506
|
+
const msgCount = (channel.totalMsgCount || 0) - (member.msgCount || 0);
|
|
507
|
+
const msgCountRoot = (channel.totalMsgCountRoot || 0) - (member.msgCountRoot || 0);
|
|
508
|
+
const {
|
|
509
|
+
notifyProps,
|
|
510
|
+
mentionCountRoot,
|
|
511
|
+
mentionCount
|
|
512
|
+
} = member;
|
|
513
|
+
return {
|
|
514
|
+
channelId: id,
|
|
515
|
+
teamId: team ? team.toString() : '',
|
|
516
|
+
msgCount,
|
|
517
|
+
msgCountRoot,
|
|
518
|
+
mentionCount: mentionCount || 0,
|
|
519
|
+
notifyProps: notifyProps || this.defaultNotifyProps,
|
|
520
|
+
mentionCountRoot: mentionCountRoot || 0
|
|
521
|
+
};
|
|
522
|
+
} catch (error) {
|
|
523
|
+
this.logger.error('Error getting channel unread: %o', error);
|
|
524
|
+
return error instanceof Error ? error : new Error('Unknown error occurred');
|
|
525
|
+
}
|
|
197
526
|
}
|
|
198
527
|
async getPinnedPosts(channelId) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
}
|
|
221
|
-
deletedAt: time
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
// getByName(team: string, title: string): Promise<IChannel> {
|
|
225
|
-
// return this.get({
|
|
226
|
-
// team,
|
|
227
|
-
// title,
|
|
228
|
-
// });
|
|
229
|
-
// }
|
|
230
|
-
getByName(title) {
|
|
231
|
-
return this.get({
|
|
232
|
-
title
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
getByNameIncludeDeleted(team, title) {
|
|
236
|
-
return this.get({
|
|
237
|
-
team,
|
|
238
|
-
title,
|
|
239
|
-
deletedAt: true
|
|
240
|
-
});
|
|
528
|
+
try {
|
|
529
|
+
const posts = await this.postService.getAll({
|
|
530
|
+
criteria: {
|
|
531
|
+
channelId,
|
|
532
|
+
isPinned: true
|
|
533
|
+
},
|
|
534
|
+
sort: {
|
|
535
|
+
key: 'CreatAt',
|
|
536
|
+
value: SortEnum.Asc
|
|
537
|
+
}
|
|
538
|
+
});
|
|
539
|
+
const replyCounts = await Promise.all(posts.map(post => this.postService.count({
|
|
540
|
+
rootId: post.rootId || post._id
|
|
541
|
+
})));
|
|
542
|
+
return posts.reduce((acc, curr, index) => [...acc, {
|
|
543
|
+
...curr,
|
|
544
|
+
replyCount: replyCounts[index]
|
|
545
|
+
}], []);
|
|
546
|
+
} catch (error) {
|
|
547
|
+
this.logger.error('Error getting pinned posts: %o', error);
|
|
548
|
+
return error instanceof Error ? error : new Error('Unknown error occurred');
|
|
549
|
+
}
|
|
241
550
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
551
|
+
async getFromMaster(id) {
|
|
552
|
+
try {
|
|
553
|
+
// Try Redis cache first
|
|
554
|
+
if (this.redisCacheManager && id) {
|
|
555
|
+
try {
|
|
556
|
+
const cacheKey = `${config.APP_NAME}:getChannelById`;
|
|
557
|
+
const variables = {
|
|
558
|
+
id
|
|
559
|
+
};
|
|
560
|
+
const cacheCtx = {
|
|
561
|
+
userId: 'system'
|
|
562
|
+
};
|
|
563
|
+
const cached = await this.redisCacheManager.get(cacheKey, variables, cacheCtx);
|
|
564
|
+
if (cached) {
|
|
565
|
+
this.logger.debug(`Cache hit for channel ID: ${id}`);
|
|
566
|
+
return cached;
|
|
567
|
+
}
|
|
568
|
+
} catch (cacheError) {
|
|
569
|
+
this.logger.warn(`Redis cache error for getFromMaster(${id}): ${cacheError?.message}`);
|
|
248
570
|
}
|
|
249
571
|
}
|
|
250
|
-
|
|
572
|
+
const result = await this.get({
|
|
573
|
+
id
|
|
574
|
+
});
|
|
575
|
+
// Set cache
|
|
576
|
+
if (this.redisCacheManager && result) {
|
|
577
|
+
try {
|
|
578
|
+
const cacheKey = `${config.APP_NAME}:getChannelById`;
|
|
579
|
+
const variables = {
|
|
580
|
+
id
|
|
581
|
+
};
|
|
582
|
+
const cacheCtx = {
|
|
583
|
+
userId: 'system'
|
|
584
|
+
};
|
|
585
|
+
await this.redisCacheManager.set(cacheKey, variables, result, cacheCtx, CACHE_TTL);
|
|
586
|
+
} catch (cacheError) {
|
|
587
|
+
this.logger.warn(`Failed to cache channel by id: ${cacheError?.message}`);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
return result;
|
|
591
|
+
} catch (error) {
|
|
592
|
+
this.logger.error('Error getting channel from master: %o', error);
|
|
593
|
+
return error instanceof Error ? error : new Error('Unknown error occurred');
|
|
594
|
+
}
|
|
251
595
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
596
|
+
async restore(channelId, time) {
|
|
597
|
+
try {
|
|
598
|
+
await this.repository.update({
|
|
599
|
+
id: channelId
|
|
600
|
+
}, {
|
|
601
|
+
deletedAt: time
|
|
602
|
+
});
|
|
603
|
+
} catch (error) {
|
|
604
|
+
this.logger.error('Error restoring channel: %o', error);
|
|
605
|
+
throw error;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
// @ts-ignore - Type compatibility issue with base class method
|
|
609
|
+
async getByName(title) {
|
|
610
|
+
try {
|
|
611
|
+
if (!title) {
|
|
612
|
+
this.logger.warn('Empty channel title provided');
|
|
613
|
+
return null;
|
|
257
614
|
}
|
|
258
|
-
|
|
615
|
+
// Try Redis cache first
|
|
616
|
+
if (this.redisCacheManager) {
|
|
617
|
+
try {
|
|
618
|
+
const cacheKey = `${config.APP_NAME}:getChannelByName`;
|
|
619
|
+
const variables = {
|
|
620
|
+
name: title
|
|
621
|
+
};
|
|
622
|
+
const cacheCtx = {
|
|
623
|
+
userId: 'system'
|
|
624
|
+
};
|
|
625
|
+
const cached = await this.redisCacheManager.get(cacheKey, variables, cacheCtx);
|
|
626
|
+
if (cached) {
|
|
627
|
+
this.logger.debug(`Cache hit for channel name: ${title}`);
|
|
628
|
+
return cached;
|
|
629
|
+
}
|
|
630
|
+
} catch (cacheError) {
|
|
631
|
+
this.logger.warn(`Redis cache error for getByName(${title}): ${cacheError?.message}`);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
const result = await this.get({
|
|
635
|
+
title
|
|
636
|
+
});
|
|
637
|
+
// Cache the result
|
|
638
|
+
if (this.redisCacheManager && result) {
|
|
639
|
+
try {
|
|
640
|
+
const cacheKey = `${config.APP_NAME}:getChannelByName`;
|
|
641
|
+
const variables = {
|
|
642
|
+
name: title
|
|
643
|
+
};
|
|
644
|
+
const cacheCtx = {
|
|
645
|
+
userId: 'system'
|
|
646
|
+
};
|
|
647
|
+
await this.redisCacheManager.set(cacheKey, variables, result, cacheCtx, CACHE_TTL);
|
|
648
|
+
} catch (cacheError) {
|
|
649
|
+
this.logger.warn(`Failed to cache channel by name: ${cacheError?.message}`);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
return result;
|
|
653
|
+
} catch (error) {
|
|
654
|
+
this.logger.error('Error getting channel by name: %o', error);
|
|
655
|
+
throw error;
|
|
656
|
+
}
|
|
259
657
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
team,
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
658
|
+
async getByNameIncludeDeleted(teamId, name) {
|
|
659
|
+
try {
|
|
660
|
+
const result = await this.get({
|
|
661
|
+
team: teamId,
|
|
662
|
+
title: name,
|
|
663
|
+
deletedAt: true
|
|
664
|
+
});
|
|
665
|
+
return result;
|
|
666
|
+
} catch (error) {
|
|
667
|
+
this.logger.error('Error getting channel by name including deleted: %o', error);
|
|
668
|
+
return error instanceof Error ? error : new Error('Unknown error occurred');
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
async getByNames(teamId, names) {
|
|
672
|
+
try {
|
|
673
|
+
const result = await this.getAll({
|
|
674
|
+
criteria: {
|
|
675
|
+
team: teamId,
|
|
676
|
+
title: {
|
|
677
|
+
$in: names
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
});
|
|
681
|
+
return result;
|
|
682
|
+
} catch (error) {
|
|
683
|
+
this.logger.error('Error getting channels by names: %o', error);
|
|
684
|
+
return error instanceof Error ? error : new Error('Unknown error occurred');
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
async getChannelCounts(teamId, userId) {
|
|
688
|
+
try {
|
|
689
|
+
return await this.count({
|
|
690
|
+
team: teamId,
|
|
691
|
+
members: {
|
|
692
|
+
user: userId
|
|
693
|
+
}
|
|
694
|
+
});
|
|
695
|
+
} catch (error) {
|
|
696
|
+
this.logger.error('Error getting channel counts: %o', error);
|
|
697
|
+
return error instanceof Error ? error : new Error('Unknown error occurred');
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
async getChannels(teamId, userId, includeDeleted, lastDeleteAt, orgId) {
|
|
701
|
+
try {
|
|
702
|
+
const result = await this.repository.getAll({
|
|
703
|
+
criteria: this.generateCriteria({
|
|
704
|
+
team: teamId,
|
|
705
|
+
user: userId,
|
|
706
|
+
includeDeleted,
|
|
707
|
+
lastDeleteAt,
|
|
708
|
+
orgName: orgId
|
|
709
|
+
})
|
|
710
|
+
});
|
|
711
|
+
return result;
|
|
712
|
+
} catch (error) {
|
|
713
|
+
this.logger.error('Error getting channels: %o', error);
|
|
714
|
+
return error instanceof Error ? error : new Error('Unknown error occurred');
|
|
715
|
+
}
|
|
270
716
|
}
|
|
271
717
|
generateCriteria(options) {
|
|
272
718
|
const {
|
|
@@ -323,72 +769,173 @@ let ChannelService = ChannelService_1 = class ChannelService extends BaseService
|
|
|
323
769
|
}
|
|
324
770
|
return criteria;
|
|
325
771
|
}
|
|
326
|
-
deleteChannel(id) {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
return Promise.resolve(undefined);
|
|
772
|
+
async deleteChannel(id) {
|
|
773
|
+
try {
|
|
774
|
+
return await this.repository.delete({
|
|
775
|
+
id
|
|
776
|
+
});
|
|
777
|
+
} catch (error) {
|
|
778
|
+
this.logger.error('Error deleting channel: %o', error);
|
|
779
|
+
return error instanceof Error ? error : new Error('Unknown error occurred');
|
|
780
|
+
}
|
|
336
781
|
}
|
|
337
|
-
|
|
338
|
-
|
|
782
|
+
async getDeleted(teamId, offset, limit, userId) {
|
|
783
|
+
try {
|
|
784
|
+
// Implementation would go here to get deleted channels
|
|
785
|
+
return [];
|
|
786
|
+
} catch (error) {
|
|
787
|
+
this.logger.error('Error getting deleted channels: %o', error);
|
|
788
|
+
return error instanceof Error ? error : new Error('Unknown error occurred');
|
|
789
|
+
}
|
|
339
790
|
}
|
|
340
|
-
|
|
341
|
-
|
|
791
|
+
async getDeletedByName(teamId, name) {
|
|
792
|
+
try {
|
|
793
|
+
// Implementation would go here
|
|
794
|
+
return null;
|
|
795
|
+
} catch (error) {
|
|
796
|
+
this.logger.error('Error getting deleted channel by name: %o', error);
|
|
797
|
+
return error instanceof Error ? error : new Error('Unknown error occurred');
|
|
798
|
+
}
|
|
342
799
|
}
|
|
343
|
-
|
|
344
|
-
|
|
800
|
+
async getMoreChannels(teamId, userId, offset, limit) {
|
|
801
|
+
try {
|
|
802
|
+
// Implementation would go here
|
|
803
|
+
return [];
|
|
804
|
+
} catch (error) {
|
|
805
|
+
this.logger.error('Error getting more channels: %o', error);
|
|
806
|
+
return error instanceof Error ? error : new Error('Unknown error occurred');
|
|
807
|
+
}
|
|
345
808
|
}
|
|
346
|
-
|
|
347
|
-
|
|
809
|
+
async getPrivateChannelsForTeam(teamId, offset, limit) {
|
|
810
|
+
try {
|
|
811
|
+
// Implementation would go here
|
|
812
|
+
return [];
|
|
813
|
+
} catch (error) {
|
|
814
|
+
this.logger.error('Error getting private channels for team: %o', error);
|
|
815
|
+
return error instanceof Error ? error : new Error('Unknown error occurred');
|
|
816
|
+
}
|
|
348
817
|
}
|
|
349
|
-
|
|
350
|
-
|
|
818
|
+
async getPublicChannelsByIdsForTeam(teamId, channelsIds) {
|
|
819
|
+
try {
|
|
820
|
+
// Implementation would go here
|
|
821
|
+
return [];
|
|
822
|
+
} catch (error) {
|
|
823
|
+
this.logger.error('Error getting public channels by IDs for team: %o', error);
|
|
824
|
+
return error instanceof Error ? error : new Error('Unknown error occurred');
|
|
825
|
+
}
|
|
351
826
|
}
|
|
352
|
-
|
|
353
|
-
|
|
827
|
+
async getPublicChannelsForTeam(teamId, offset, limit) {
|
|
828
|
+
try {
|
|
829
|
+
// Implementation would go here
|
|
830
|
+
return [];
|
|
831
|
+
} catch (error) {
|
|
832
|
+
this.logger.error('Error getting public channels for team: %o', error);
|
|
833
|
+
return error instanceof Error ? error : new Error('Unknown error occurred');
|
|
834
|
+
}
|
|
354
835
|
}
|
|
355
|
-
|
|
356
|
-
|
|
836
|
+
async getTeamChannels(teamId) {
|
|
837
|
+
try {
|
|
838
|
+
// Implementation would go here
|
|
839
|
+
return [];
|
|
840
|
+
} catch (error) {
|
|
841
|
+
this.logger.error('Error getting team channels: %o', error);
|
|
842
|
+
return error instanceof Error ? error : new Error('Unknown error occurred');
|
|
843
|
+
}
|
|
357
844
|
}
|
|
358
|
-
|
|
359
|
-
|
|
845
|
+
async hideChannel(id) {
|
|
846
|
+
try {
|
|
847
|
+
// Implementation would go here
|
|
848
|
+
return false;
|
|
849
|
+
} catch (error) {
|
|
850
|
+
this.logger.error('Error hiding channel: %o', error);
|
|
851
|
+
return false;
|
|
852
|
+
}
|
|
360
853
|
}
|
|
361
|
-
leaveChannel(id) {
|
|
362
|
-
|
|
854
|
+
async leaveChannel(id) {
|
|
855
|
+
try {
|
|
856
|
+
// Implementation would go here
|
|
857
|
+
return false;
|
|
858
|
+
} catch (error) {
|
|
859
|
+
this.logger.error('Error leaving channel: %o', error);
|
|
860
|
+
return false;
|
|
861
|
+
}
|
|
363
862
|
}
|
|
364
863
|
async viewChannel(id, user) {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
864
|
+
try {
|
|
865
|
+
// Accessing private property
|
|
866
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
867
|
+
// @ts-ignore
|
|
868
|
+
if (id) {
|
|
869
|
+
await this.repository.model.updateOne({
|
|
870
|
+
_id: id
|
|
871
|
+
}, {
|
|
872
|
+
'members.$[elem].lastViewedAt': new Date()
|
|
873
|
+
}, {
|
|
874
|
+
arrayFilters: [{
|
|
875
|
+
'elem.user': user
|
|
876
|
+
}]
|
|
877
|
+
});
|
|
878
|
+
}
|
|
879
|
+
return true;
|
|
880
|
+
} catch (error) {
|
|
881
|
+
this.logger.error('Error viewing channel: %o', error);
|
|
882
|
+
return false;
|
|
378
883
|
}
|
|
379
|
-
return true;
|
|
380
884
|
}
|
|
381
|
-
permanentDelete(channelId) {
|
|
382
|
-
|
|
885
|
+
async permanentDelete(channelId) {
|
|
886
|
+
try {
|
|
887
|
+
// Implementation would go here for permanent deletion
|
|
888
|
+
this.logger.debug(`Permanently deleting channel ${channelId}`);
|
|
889
|
+
} catch (error) {
|
|
890
|
+
this.logger.error('Error permanently deleting channel: %o', error);
|
|
891
|
+
return error instanceof Error ? error : new Error('Unknown error occurred');
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
async permanentDeleteByTeam(teamId) {
|
|
895
|
+
try {
|
|
896
|
+
// Implementation would go here for permanent team deletion
|
|
897
|
+
this.logger.debug(`Permanently deleting all channels for team ${teamId}`);
|
|
898
|
+
} catch (error) {
|
|
899
|
+
this.logger.error('Error permanently deleting channels by team: %o', error);
|
|
900
|
+
return error instanceof Error ? error : new Error('Unknown error occurred');
|
|
901
|
+
}
|
|
383
902
|
}
|
|
384
|
-
|
|
385
|
-
|
|
903
|
+
async permanentDeleteMembersByChannel(channelId) {
|
|
904
|
+
try {
|
|
905
|
+
// Implementation would go here for permanent member deletion
|
|
906
|
+
this.logger.debug(`Permanently deleting all members for channel ${channelId}`);
|
|
907
|
+
} catch (error) {
|
|
908
|
+
this.logger.error('Error permanently deleting members by channel: %o', error);
|
|
909
|
+
return error instanceof Error ? error : new Error('Unknown error occurred');
|
|
910
|
+
}
|
|
386
911
|
}
|
|
387
|
-
|
|
388
|
-
|
|
912
|
+
async saveMultipleMembers(members) {
|
|
913
|
+
try {
|
|
914
|
+
// Implementation would go here
|
|
915
|
+
return [];
|
|
916
|
+
} catch (error) {
|
|
917
|
+
this.logger.error('Error saving multiple members: %o', error);
|
|
918
|
+
return error instanceof Error ? error : new Error('Unknown error occurred');
|
|
919
|
+
}
|
|
389
920
|
}
|
|
390
|
-
|
|
391
|
-
|
|
921
|
+
async invalidateChannelByName(teamId, name) {
|
|
922
|
+
try {
|
|
923
|
+
if (!this.redisCacheManager) {
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
// Invalidate name-based cache
|
|
927
|
+
await this.redisCacheManager.del(`${config.APP_NAME}:getChannelByName`, {
|
|
928
|
+
name
|
|
929
|
+
}, {
|
|
930
|
+
userId: 'system'
|
|
931
|
+
}, true);
|
|
932
|
+
// If we have team-specific variations in future, consider invalidating those keys as well
|
|
933
|
+
this.logger.debug(`Invalidated channel cache for name ${name} (team: ${teamId || 'n/a'})`);
|
|
934
|
+
} catch (error) {
|
|
935
|
+
this.logger.warn(`Error invalidating channel cache: ${error?.message}`);
|
|
936
|
+
}
|
|
392
937
|
}
|
|
393
938
|
};
|
|
394
|
-
ChannelService = ChannelService_1 = __decorate([
|
|
939
|
+
ChannelService = ChannelService_1 = __decorate([injectable()
|
|
940
|
+
// @ts-ignore - Type compatibility issue between BaseService2 and IChannelService
|
|
941
|
+
, __param(0, inject(SERVER_TYPES.ChannelRepository)), __param(1, inject(SERVER_TYPES.PostService)), __param(2, inject(CommonType.MOLECULER_BROKER)), __param(3, inject(SERVER_TYPES.IRedisCacheManager)), __param(4, inject(CommonType.REDIS_CLIENT)), __param(5, inject('Logger')), __metadata("design:paramtypes", [Object, Object, ServiceBroker, Object, Function, Object])], ChannelService);export{ChannelService};//# sourceMappingURL=channel-service.js.map
|