Skip to content

Commit

Permalink
Merge pull request #336 from TogetherCrew/populate-roles-for-communit…
Browse files Browse the repository at this point in the history
…y-api

Populate roles for community api
  • Loading branch information
cyri113 authored Apr 8, 2024
2 parents 696dee8 + 77f71aa commit 582b2c1
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 38 deletions.
32 changes: 28 additions & 4 deletions __tests__/integration/community.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,11 @@
// await insertCommunities([communityOne, communityTwo, communityThree]);
// await insertUsers([userOne, userTwo]);
// await insertPlatforms([platformOne, platformTwo, platformThree]);
// await insertGuildMembers(
// [discordGuildMember1, discordGuildMember2, discordGuildMember3, discordGuildMember4],
// connection,
// );
// await insertRoles([discordRole1, discordRole2, discordRole3, discordRole4], connection);

// const res = await request(app)
// .get(`/api/v1/communities/${communityOne._id}`)
Expand All @@ -364,16 +369,31 @@
// source: {
// platform: 'discord',
// identifierType: 'member',
// identifierValues: ['987654321'],
// // platformId: new Types.ObjectId(),
// identifierValues: [{
// discordId: discordGuildMember2.discordId,
// username: discordGuildMember2.username,
// ngu: discordGuildMember2.nickname,
// discriminator: discordGuildMember2.discriminator,
// nickname: discordGuildMember2.nickname,
// globalName: discordGuildMember2.globalName,
// avatar: discordGuildMember2.avatar,
// }],
// },
// });
// expect(res.body.roles[1]).toMatchObject({
// roleType: 'view',
// source: {
// platform: 'discord',
// identifierType: 'member',
// identifierValues: ['987654321'],
// identifierValues: [{
// discordId: discordGuildMember2.discordId,
// username: discordGuildMember2.username,
// ngu: discordGuildMember2.nickname,
// discriminator: discordGuildMember2.discriminator,
// nickname: discordGuildMember2.nickname,
// globalName: discordGuildMember2.globalName,
// avatar: discordGuildMember2.avatar,
// }],
// // platformId: new Types.ObjectId(),
// },
// });
Expand All @@ -382,7 +402,11 @@
// source: {
// platform: 'discord',
// identifierType: 'role',
// identifierValues: ['652345789987654321'],
// identifierValues: [{
// roleId: discordRole1.roleId,
// name: discordRole1.name,
// color: discordRole1.color,
// }],
// // platformId: new Types.ObjectId(),
// },
// });
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"@discordjs/rest": "^1.7.0",
"@notionhq/client": "^2.2.3",
"@sentry/node": "^7.50.0",
"@togethercrew.dev/db": "^3.0.34",
"@togethercrew.dev/db": "^3.0.42",
"@togethercrew.dev/tc-messagebroker": "^0.0.45",
"@types/express-session": "^1.17.7",
"@types/morgan": "^1.9.5",
Expand Down
13 changes: 8 additions & 5 deletions src/controllers/community.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,14 @@ const getCommunities = catchAsync(async function (req: IAuthRequest, res: Respon
res.send(result);
});
const getCommunity = catchAsync(async function (req: IAuthRequest, res: Response) {
const community = req.community;
await community?.populate({
path: 'platforms',
select: '_id name metadata disconnectedAt',
});
let community = req.community;
if (community) {
await community?.populate({
path: 'platforms',
select: '_id name metadata disconnectedAt',
});
community = await communityService.populateRoles(community);
}
res.send(community);
});
const updateCommunity = catchAsync(async function (req: IAuthRequest, res: Response) {
Expand Down
45 changes: 43 additions & 2 deletions src/services/community.service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { HydratedDocument, Types } from 'mongoose';
import httpStatus from 'http-status';
import { Community, ICommunity } from '@togethercrew.dev/db';
import { Community, ICommunity, DatabaseManager, GuildMember, IRole } from '@togethercrew.dev/db';
import ApiError from '../utils/ApiError';

import guildMemberService from './discord/guildMember.service';
import roleService from './discord/role.service';
import platformService from './platform.service';
/**
* Create a community
* @param {ICommunity} communityBody
Expand Down Expand Up @@ -107,6 +109,44 @@ const addPlatformToCommunityById = async (
return community;
};

/**
* Populate roles
* @param {HydratedDocument<ICommunity>} community
* @returns {Promise<HydratedDocument<ICommunity>>}
*/
const populateRoles = async (community: HydratedDocument<ICommunity>): Promise<HydratedDocument<ICommunity>> => {
if (community.roles) {
for (const role of community.roles) {
const platformId = role.source.platformId;
const platform = await platformService.getPlatformById(platformId);
if (platform) {
const connection = await DatabaseManager.getInstance().getTenantDb(platform?.metadata?.id);
if (role.source.identifierType === 'member') {
const guildMembers = await guildMemberService.getGuildMembers(
connection,
{ discordId: { $in: role.source.identifierValues } },
{ avatar: 1, discordId: 1, username: 1, discriminator: 1, nickname: 1, globalName: 1 },
);
guildMembers.forEach((guildMember: any) => {
guildMember.ngu = guildMemberService.getNgu(guildMember);
guildMember.username = guildMemberService.getUsername(guildMember);
});
role.source.identifierValues = guildMembers;
} else if (role.source.identifierType === 'role') {
const roles: IRole[] = await roleService.getRoles(
connection,
{ roleId: { $in: role.source.identifierValues } },
{ roleId: 1, color: 1, name: 1 },
);
role.source.identifierValues = roles;
}
}
}
}

return community;
};

export default {
createCommunity,
queryCommunities,
Expand All @@ -116,4 +156,5 @@ export default {
updateCommunityByFilter,
deleteCommunityByFilter,
addPlatformToCommunityById,
populateRoles,
};
25 changes: 19 additions & 6 deletions src/services/discord/guildMember.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Connection } from 'mongoose';
import { Connection, HydratedDocument } from 'mongoose';
import { sort } from '../../utils';
import { IGuildMember } from '@togethercrew.dev/db';
import parentLogger from '../../config/logger';
Expand All @@ -12,6 +12,7 @@ type Filter = {
allRoles: boolean;
include?: Array<string>;
exclude?: Array<string>;
discordId?: any;
};

type Options = {
Expand All @@ -28,7 +29,6 @@ type Options = {
* @param {Array<string>} activityCompostionsTypes - An array containing types of activity compositions.
* @returns {Promise<QueryResult>} - An object with the query results and other information like 'limit', 'page', 'totalPages', 'totalResults'.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async function queryGuildMembersForTables(
connection: Connection,
filter: Filter,
Expand All @@ -43,7 +43,6 @@ async function queryGuildMembersForTables(
const page = options.page && parseInt(options.page, 10) > 0 ? parseInt(options.page, 10) : 1;
const sortParams: Record<string, 1 | -1> = sortBy ? sort.sortByHandler(sortBy) : { username: 1 };

// eslint-disable-next-line @typescript-eslint/no-explicit-any
let matchStage: any = {};
let allActivityIds: string[] = [];

Expand Down Expand Up @@ -224,16 +223,14 @@ async function getGuildMember(connection: Connection, filter: object): Promise<I
* @param {number} [options.limit] - Maximum number of results per page (default = 10)
* @param {number} [options.page] - Current page (default = 1)
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const queryGuildMembers = async (connection: any, filter: Filter, options: Options) => {
const queryGuildMembers = async (connection: any, filter: any, options: Options) => {
try {
const { ngu } = filter;
const { sortBy } = options;
const limit = options.limit && parseInt(options.limit, 10) > 0 ? parseInt(options.limit, 10) : 10;
const page = options.page && parseInt(options.page, 10) > 0 ? parseInt(options.page, 10) : 1;
const sortParams: Record<string, 1 | -1> = sortBy ? sort.sortByHandler(sortBy) : { username: 1 };

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const matchStage: any = {};

if (ngu) {
Expand Down Expand Up @@ -304,6 +301,21 @@ const getAllDiscordIdsInLastedMemberActivity = async (connection: Connection, me
return allDiscordIds;
};

/**
* Get guildMembers by filter
* @param {Connection} connection - Mongoose connection object for the database.
* @param {Object} filter - Mongo filter
* @param {Object} select - Selete fields
* @returns {Promise<HydratedDocument<IGuildMember>[] | []>}
*/
const getGuildMembers = async (
connection: Connection,
filter: object,
select?: object,
): Promise<HydratedDocument<IGuildMember>[] | []> => {
return connection.models.GuildMember.find(filter).select(select);
};

export default {
getGuildMemberInfoFromDiscordIds,
getAllDiscordIdsInLastedMemberActivity,
Expand All @@ -313,4 +325,5 @@ export default {
getNgu,
getUsername,
queryGuildMembers,
getGuildMembers,
};
23 changes: 11 additions & 12 deletions src/services/discord/role.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Connection } from 'mongoose';
import { Connection, HydratedDocument } from 'mongoose';
import { IRole, IGuildMember } from '@togethercrew.dev/db';

/**
Expand All @@ -12,18 +12,18 @@ async function getRole(connection: Connection, filter: object): Promise<IRole |
}

/**
* Get roles from the database based on the filter criteria.
* @param {Connection} connection - Mongoose connection object for the database.
* @param {object} filter - An object specifying the filter criteria to match the desired role entries.
* @returns {Promise<IRole[] | []>} - A promise that resolves to an array of the matching role objects.
* @param {Object} filter - Mongo filter
* @param {Object} select - Selete fields
* @returns {Promise<HydratedDocument<IRole>[] | []>}
*/
async function getRoles(connection: Connection, filter: object): Promise<IRole[] | []> {
try {
return await connection.models.Role.find(filter);
} catch (error) {
return [];
}
}
const getRoles = async (
connection: Connection,
filter: object,
select?: object,
): Promise<HydratedDocument<IRole>[] | []> => {
return connection.models.Role.find(filter).select(select);
};

/**
* Get an array of Discord IDs based on the role IDs present in the guild member's data.
Expand Down Expand Up @@ -71,7 +71,6 @@ function getRolesForGuildMember(guildMember: IGuildMember, roles: Array<IRole>)
* @param {number} [options.limit] - Maximum number of results per page (default = 10)
* @param {number} [options.page] - Current page (default = 1)
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const queryRoles = async (connection: any, filter: object, options: object) => {
return await connection.models.Role.paginate(filter, options);
};
Expand Down
4 changes: 0 additions & 4 deletions src/services/memberActivity.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -871,7 +871,6 @@ async function getLastDocumentForTablesUsage(connection: Connection, activityCom
return lastDocument[0];
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function getActivityComposition(guildMember: IGuildMember, memberActivity: any, activityComposition: Array<string>) {
const activityTypes = [
{ key: 'all_new_active', message: 'Newly active' },
Expand Down Expand Up @@ -949,7 +948,6 @@ async function getMembersInteractionsNetworkGraph(
const neo4jUsersInteractionsData = await Neo4j.read(usersInteractionsQuery);
const { records: neo4jUsersInteractions } = neo4jUsersInteractionsData;
const usersInteractions = neo4jUsersInteractions.map((usersInteraction) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const { _fieldLookup, _fields } = usersInteraction;
const a = _fields[_fieldLookup['a']];
Expand Down Expand Up @@ -981,7 +979,6 @@ async function getMembersInteractionsNetworkGraph(
const neo4jUserRadiusData = await Neo4j.read(userRadiusQuery);
const { records: neo4jUserRadius } = neo4jUserRadiusData;
const userRadius = neo4jUserRadius.map((userRadius) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const { _fieldLookup, _fields } = userRadius;
const userId = _fields[_fieldLookup['userId']] as string;
Expand All @@ -999,7 +996,6 @@ async function getMembersInteractionsNetworkGraph(
const neo4jUserStatusData = await Neo4j.read(userStatusQuery);
const { records: neo4jUserStatus } = neo4jUserStatusData;
const userStatus = neo4jUserStatus.map((userStatus) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const { _fieldLookup, _fields } = userStatus;
const userId = _fields[_fieldLookup['userId']] as string;
Expand Down

0 comments on commit 582b2c1

Please sign in to comment.