diff --git a/__tests__/fixtures/guildMember.fixture.ts b/__tests__/fixtures/guildMember.fixture.ts index a49851d3..1c56e048 100644 --- a/__tests__/fixtures/guildMember.fixture.ts +++ b/__tests__/fixtures/guildMember.fixture.ts @@ -2,42 +2,46 @@ import { Connection } from 'mongoose'; export const guildMemberOne = { discordId: "123456789", - username: "Behzad", + username: "behzad_rabiei", avatar: null, roles: ["987654321123456789", "123456789987654321"], joinedAt: new Date("2023-03-07"), isBot: false, - discriminator: "0" + discriminator: "0", + nickname: null, + globalName: "Behzad" }; export const guildMemberTwo = { discordId: "987654321", - username: "Bi", + username: "mrjackalop", avatar: "AvatarLink", roles: ["652345789987654321", "123456789987654321"], joinedAt: new Date("2023-03-31"), isBot: false, - discriminator: "1234" + discriminator: "0", + nickname: "Daniel", + globalName: "Danielo" }; export const guildMemberThree = { discordId: "555555555", - username: "Audi", + username: "amin_torabi", avatar: "AvatarLink", roles: ["987654321123456789"], joinedAt: new Date("2022-06-01"), isBot: false, - discriminator: "0" + discriminator: "0", }; export const guildMemberFour = { discordId: "444444444", - username: "User4", + username: "zc_behzad", avatar: "AvatarLink", roles: ["652345789987654321"], joinedAt: new Date("2023-04-01"), isBot: false, - discriminator: "4321" + discriminator: "4321", }; export const guildMemberFive = { diff --git a/__tests__/integration/memberActivity.test.ts b/__tests__/integration/memberActivity.test.ts index 48750bce..29a9a2f9 100644 --- a/__tests__/integration/memberActivity.test.ts +++ b/__tests__/integration/memberActivity.test.ts @@ -365,14 +365,14 @@ describe('member-activity routes', () => { expect(Array.isArray(res.body)).toBe(true); expect(res.body).toHaveLength(2) expect(res.body).toEqual(expect.arrayContaining([({ - from: { id: '123456789', radius: 3, username: 'Behzad', stats: "SENDER" }, - to: { id: '987654321', radius: 3, username: 'Bi#1234', stats: "RECEIVER" }, + from: { id: '123456789', radius: 3, username: 'behzad_rabiei', stats: "SENDER" }, + to: { id: '987654321', radius: 3, username: 'mrjackalop', stats: "RECEIVER" }, width: 1 }) ])) expect(res.body).toEqual(expect.arrayContaining([({ - from: { id: '987654321', radius: 3, username: 'Bi#1234', stats: "RECEIVER" }, - to: { id: '123456789', radius: 3, username: 'Behzad', stats: "SENDER" }, + from: { id: '987654321', radius: 3, username: 'mrjackalop', stats: "RECEIVER" }, + to: { id: '123456789', radius: 3, username: 'behzad_rabiei', stats: "SENDER" }, width: 2 }) ])) @@ -757,6 +757,7 @@ describe('member-activity routes', () => { expect(res.body.results[0]).toEqual({ discordId: guildMemberThree.discordId, username: guildMemberThree.username, + ngu: guildMemberThree.username, avatar: guildMemberThree.avatar, roles: [ { roleId: role2.roleId, name: role2.name, color: role2.color } @@ -769,6 +770,7 @@ describe('member-activity routes', () => { expect(res.body.results[1]).toEqual({ discordId: guildMemberOne.discordId, username: guildMemberOne.username, + ngu: guildMemberOne.globalName, avatar: guildMemberOne.avatar, roles: [ { roleId: role2.roleId, name: role2.name, color: role2.color }, @@ -782,7 +784,8 @@ describe('member-activity routes', () => { expect(res.body.results[2]).toEqual({ discordId: guildMemberTwo.discordId, - username: guildMemberTwo.username + "#" + guildMemberTwo.discriminator, + username: guildMemberTwo.username, + ngu: guildMemberTwo.nickname, avatar: guildMemberTwo.avatar, roles: [ { roleId: role1.roleId, name: role1.name, color: role1.color }, @@ -796,6 +799,7 @@ describe('member-activity routes', () => { expect(res.body.results[3]).toEqual({ discordId: guildMemberFour.discordId, username: guildMemberFour.username + "#" + guildMemberFour.discriminator, + ngu: guildMemberFour.username + "#" + guildMemberFour.discriminator, avatar: guildMemberFour.avatar, roles: [ { roleId: role1.roleId, name: role1.name, color: role1.color }], @@ -944,7 +948,7 @@ describe('member-activity routes', () => { const res = await request(app) .get(`/api/v1/member-activity/${guildOne.guildId}/active-members-composition-table`) .set('Authorization', `Bearer ${userOneAccessToken}`) - .query({ username: "B" }) + .query({ ngu: "behzad" }) .send() .expect(httpStatus.OK); @@ -957,7 +961,7 @@ describe('member-activity routes', () => { }); expect(res.body.results).toHaveLength(2); expect(res.body.results[0].discordId).toBe(guildMemberOne.discordId); - expect(res.body.results[1].discordId).toBe(guildMemberTwo.discordId); + expect(res.body.results[1].discordId).toBe(guildMemberFour.discordId); }) test('should correctly sort the returned array if descending sort param is specified', async () => { @@ -1136,6 +1140,7 @@ describe('member-activity routes', () => { expect(res.body.results[0]).toEqual({ discordId: guildMemberThree.discordId, username: guildMemberThree.username, + ngu: guildMemberThree.username, avatar: guildMemberThree.avatar, roles: [ { roleId: role2.roleId, name: role2.name, color: role2.color } @@ -1148,6 +1153,7 @@ describe('member-activity routes', () => { expect(res.body.results[1]).toEqual({ discordId: guildMemberOne.discordId, username: guildMemberOne.username, + ngu: guildMemberOne.globalName, avatar: guildMemberOne.avatar, roles: [ { roleId: role2.roleId, name: role2.name, color: role2.color }, @@ -1161,7 +1167,8 @@ describe('member-activity routes', () => { expect(res.body.results[2]).toEqual({ discordId: guildMemberTwo.discordId, - username: guildMemberTwo.username + "#" + guildMemberTwo.discriminator, + username: guildMemberTwo.username, + ngu: guildMemberTwo.nickname, avatar: guildMemberTwo.avatar, roles: [ { roleId: role1.roleId, name: role1.name, color: role1.color }, @@ -1175,6 +1182,7 @@ describe('member-activity routes', () => { expect(res.body.results[3]).toEqual({ discordId: guildMemberFour.discordId, username: guildMemberFour.username + "#" + guildMemberFour.discriminator, + ngu: guildMemberFour.username + "#" + guildMemberFour.discriminator, avatar: guildMemberFour.avatar, roles: [ { roleId: role1.roleId, name: role1.name, color: role1.color }, @@ -1324,7 +1332,7 @@ describe('member-activity routes', () => { const res = await request(app) .get(`/api/v1/member-activity/${guildOne.guildId}/active-members-onboarding-table`) .set('Authorization', `Bearer ${userOneAccessToken}`) - .query({ username: "B" }) + .query({ ngu: "behzad" }) .send() .expect(httpStatus.OK); @@ -1337,7 +1345,7 @@ describe('member-activity routes', () => { }); expect(res.body.results).toHaveLength(2); expect(res.body.results[0].discordId).toBe(guildMemberOne.discordId); - expect(res.body.results[1].discordId).toBe(guildMemberTwo.discordId); + expect(res.body.results[1].discordId).toBe(guildMemberFour.discordId); }) test('should correctly sort the returned array if descending sort param is specified', async () => { @@ -1516,6 +1524,7 @@ describe('member-activity routes', () => { expect(res.body.results[0]).toEqual({ discordId: guildMemberThree.discordId, username: guildMemberThree.username, + ngu: guildMemberThree.username, avatar: guildMemberThree.avatar, roles: [ { roleId: role2.roleId, name: role2.name, color: role2.color } @@ -1528,6 +1537,7 @@ describe('member-activity routes', () => { expect(res.body.results[1]).toEqual({ discordId: guildMemberOne.discordId, username: guildMemberOne.username, + ngu: guildMemberOne.globalName, avatar: guildMemberOne.avatar, roles: [ { roleId: role2.roleId, name: role2.name, color: role2.color }, @@ -1541,7 +1551,8 @@ describe('member-activity routes', () => { expect(res.body.results[2]).toEqual({ discordId: guildMemberTwo.discordId, - username: guildMemberTwo.username + "#" + guildMemberTwo.discriminator, + username: guildMemberTwo.username, + ngu: guildMemberTwo.nickname, avatar: guildMemberTwo.avatar, roles: [ { roleId: role1.roleId, name: role1.name, color: role1.color }, @@ -1555,6 +1566,7 @@ describe('member-activity routes', () => { expect(res.body.results[3]).toEqual({ discordId: guildMemberFour.discordId, username: guildMemberFour.username + "#" + guildMemberFour.discriminator, + ngu: guildMemberFour.username + "#" + guildMemberFour.discriminator, avatar: guildMemberFour.avatar, roles: [ { roleId: role1.roleId, name: role1.name, color: role1.color }, @@ -1702,7 +1714,7 @@ describe('member-activity routes', () => { const res = await request(app) .get(`/api/v1/member-activity/${guildOne.guildId}/disengaged-members-composition-table`) .set('Authorization', `Bearer ${userOneAccessToken}`) - .query({ username: "B" }) + .query({ ngu: "behzad" }) .send() .expect(httpStatus.OK); @@ -1715,7 +1727,7 @@ describe('member-activity routes', () => { }); expect(res.body.results).toHaveLength(2); expect(res.body.results[0].discordId).toBe(guildMemberOne.discordId); - expect(res.body.results[1].discordId).toBe(guildMemberTwo.discordId); + expect(res.body.results[1].discordId).toBe(guildMemberFour.discordId); }) test('should correctly sort the returned array if descending sort param is specified', async () => { diff --git a/package-lock.json b/package-lock.json index 02d84bcd..79561621 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@discordjs/rest": "^1.7.0", "@notionhq/client": "^2.2.3", "@sentry/node": "^7.50.0", - "@togethercrew.dev/db": "^2.4.93", + "@togethercrew.dev/db": "^2.4.95", "@togethercrew.dev/tc-messagebroker": "^0.0.40", "babel-jest": "^29.3.1", "compression": "^1.7.4", @@ -2878,9 +2878,9 @@ } }, "node_modules/@togethercrew.dev/db": { - "version": "2.4.93", - "resolved": "https://registry.npmjs.org/@togethercrew.dev/db/-/db-2.4.93.tgz", - "integrity": "sha512-rFtByGDsfFJzflVol80osMPNY3wPMEUz9LRZd0Y6TBYrGlFa7aHXzkaQq286Wrr7Ff1eZtVxlo920VeXy0e7qg==", + "version": "2.4.95", + "resolved": "https://registry.npmjs.org/@togethercrew.dev/db/-/db-2.4.95.tgz", + "integrity": "sha512-aMOFGnL0dK3YZU/Ha5FfyJvp25yexqWlUmS4v8CB+IzAq8V1RdtZK5vdVx+lDz9XUL40hlMLQzNRfDoJiqMv8w==", "dependencies": { "discord.js": "^14.7.1", "joi": "^17.7.0", diff --git a/package.json b/package.json index f4e08de2..e937d84f 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "@discordjs/rest": "^1.7.0", "@notionhq/client": "^2.2.3", "@sentry/node": "^7.50.0", - "@togethercrew.dev/db": "^2.4.93", + "@togethercrew.dev/db": "^2.4.95", "@togethercrew.dev/tc-messagebroker": "^0.0.40", "babel-jest": "^29.3.1", "compression": "^1.7.4", diff --git a/src/controllers/memberActivity.controller.ts b/src/controllers/memberActivity.controller.ts index 403444fb..b2d4e664 100644 --- a/src/controllers/memberActivity.controller.ts +++ b/src/controllers/memberActivity.controller.ts @@ -92,7 +92,7 @@ const activeMembersCompositionTable = catchAsync(async function (req: IAuthReque if (!await guildService.getGuild({ guildId: req.params.guildId, user: req.user.discordId })) { throw new ApiError(httpStatus.NOT_FOUND, 'Guild not found'); } - const filter = pick(req.query, ['activityComposition', 'roles', 'username']); + const filter = pick(req.query, ['activityComposition', 'roles', 'ngu']); const options = pick(req.query, ['sortBy', 'limit', 'page']); const connection = databaseService.connectionFactory(req.params.guildId, config.mongoose.botURL); const activityCompostionFields = memberActivityService.getActivityCompositionOfActiveMembersComposition() @@ -110,7 +110,7 @@ const activeMembersOnboardingTable = catchAsync(async function (req: IAuthReques if (!await guildService.getGuild({ guildId: req.params.guildId, user: req.user.discordId })) { throw new ApiError(httpStatus.NOT_FOUND, 'Guild not found'); } - const filter = pick(req.query, ['activityComposition', 'roles', 'username']); + const filter = pick(req.query, ['activityComposition', 'roles', 'ngu']); const options = pick(req.query, ['sortBy', 'limit', 'page']); const connection = databaseService.connectionFactory(req.params.guildId, config.mongoose.botURL); const activityCompostionFields = memberActivityService.getActivityCompositionOfActiveMembersOnboarding(); @@ -128,7 +128,7 @@ const disengagedMembersCompositionTable = catchAsync(async function (req: IAuthR if (!await guildService.getGuild({ guildId: req.params.guildId, user: req.user.discordId })) { throw new ApiError(httpStatus.NOT_FOUND, 'Guild not found'); } - const filter = pick(req.query, ['activityComposition', 'roles', 'username']); + const filter = pick(req.query, ['activityComposition', 'roles', 'ngu']); const options = pick(req.query, ['sortBy', 'limit', 'page']); const connection = databaseService.connectionFactory(req.params.guildId, config.mongoose.botURL); const activityCompostionFields = memberActivityService.getActivityCompositionOfDisengagedComposition(); diff --git a/src/docs/memberActivity.doc.yml b/src/docs/memberActivity.doc.yml index 47d7de9f..0f7c0933 100644 --- a/src/docs/memberActivity.doc.yml +++ b/src/docs/memberActivity.doc.yml @@ -377,8 +377,6 @@ paths: "404": description: NotFound $ref: "#/components/responses/NotFound" - - /api/v1/member-activity/{guildId}/active-members-onboarding-line-graph: post: tags: @@ -465,7 +463,7 @@ paths: summary: Get data for active members composition table security: - bearerAuth: [] - description: for now sortBy just can apply for username and joinedAt(DaoMemberSince in UI) + description: for now sortBy just can apply for ngu and joinedAt(DaoMemberSince in UI) parameters: - in: path name: guildId @@ -493,7 +491,7 @@ paths: style: form explode: true - in: query - name: username + name: ngu required: false schema: type: string @@ -503,7 +501,7 @@ paths: required: false schema: type: string - example: "joinedAt:desc,username:asc" + example: "joinedAt:desc,ngu:asc" - in: query name: limit required: false @@ -533,7 +531,10 @@ paths: items: type: object properties: - name: + username: + type: string + example: "Behzad_Rabiei" + ngu: type: string example: "Behzad" avatar: @@ -590,7 +591,7 @@ paths: summary: Get data for active members onboarding table security: - bearerAuth: [] - description: for now sortBy just can apply for username and joinedAt(DaoMemberSince in UI) + description: for now sortBy just can apply for ngu and joinedAt(DaoMemberSince in UI) parameters: - in: path name: guildId @@ -618,7 +619,7 @@ paths: style: form explode: true - in: query - name: username + name: ngu required: false schema: type: string @@ -628,7 +629,7 @@ paths: required: false schema: type: string - example: "joinedAt:desc,username:asc" + example: "joinedAt:desc,ngu:asc" - in: query name: limit required: false @@ -658,7 +659,10 @@ paths: items: type: object properties: - name: + username: + type: string + example: "Behzad_Rabiei" + ngu: type: string example: "Behzad" avatar: @@ -715,7 +719,7 @@ paths: summary: Get data for disengaged members composition table security: - bearerAuth: [] - description: for now sortBy just can apply for username and joinedAt(DaoMemberSince in UI) + description: for now sortBy just can apply for ngu and joinedAt(DaoMemberSince in UI) parameters: - in: path name: guildId @@ -743,7 +747,7 @@ paths: style: form explode: true - in: query - name: username + name: ngu required: false schema: type: string @@ -753,7 +757,7 @@ paths: required: false schema: type: string - example: "joinedAt:desc,username:asc" + example: "joinedAt:desc,ngu:asc" - in: query name: limit required: false @@ -783,7 +787,10 @@ paths: items: type: object properties: - name: + username: + type: string + example: "Behzad_Rabiei" + ngu: type: string example: "Behzad" avatar: diff --git a/src/services/guildMember.service.ts b/src/services/guildMember.service.ts index 0344bf01..f6c062c4 100644 --- a/src/services/guildMember.service.ts +++ b/src/services/guildMember.service.ts @@ -6,7 +6,7 @@ import { IRole, IGuildMember } from '@togethercrew.dev/db'; type Filter = { activityComposition?: Array; roles?: Array; - username?: string; + ngu?: string; }; type Options = { @@ -25,7 +25,7 @@ type Options = { */ async function queryGuildMembers(connection: Connection, filter: Filter, options: Options, memberActivity: any, activityCompostionsTypes: Array) { try { - const { roles, username, activityComposition } = filter; + const { roles, ngu, activityComposition } = 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; @@ -59,8 +59,12 @@ async function queryGuildMembers(connection: Connection, filter: Filter, options } } } - if (username) { - matchStage.username = { $regex: username, $options: 'i' }; + if (ngu) { + matchStage.$or = [ + { "username": { $regex: ngu, $options: 'i' } }, + { "globalName": { $regex: ngu, $options: 'i' } }, + { "nickname": { $regex: ngu, $options: 'i' } } + ]; } if (roles && roles.length > 0) { @@ -94,7 +98,9 @@ async function queryGuildMembers(connection: Connection, filter: Filter, options roles: 1, avatar: 1, joinedAt: 1, - _id: 0 + nickname: 1, + globalName: 1, + _id: 0, } } ]); @@ -120,7 +126,7 @@ async function queryGuildMembers(connection: Connection, filter: Filter, options } } /** - * handel guild member roles, ngu, and username + * handel guild member roles and displayName * @param {Array} guildMembers - guild members array. * @param {Array} roles - roles array. * @param {Any} memberActivity - The document containing the last member activity. @@ -129,6 +135,7 @@ async function queryGuildMembers(connection: Connection, filter: Filter, options */ // eslint-disable-next-line @typescript-eslint/no-explicit-any async function addNeededDataForTable(guildMembers: Array, roles: Array, memberActivity: any, activityComposition: Array) { + guildMembers.forEach((guildMember) => { guildMember.roles = guildMember.roles.map((roleId: string) => { const role = roles.find((role: IRole) => role.roleId === roleId); @@ -137,7 +144,18 @@ async function addNeededDataForTable(guildMembers: Array, roles: Array