Skip to content
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
6 changes: 3 additions & 3 deletions src/ai-integration/services/summarization.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ export class AiSummarizationService {
const interestsText = response.choices[0]?.message?.content?.trim();

if (!interestsText || interestsText.length === 0) {
return '';
return '';
}

const normalizedResponse = interestsText.toUpperCase().replace(/[^A-Z]/g, '');
const normalizedResponse = interestsText.toUpperCase().replaceAll(/[^A-Z]/g, '');
const matchedInterest = ALL_INTERESTS.find(
interest => interest.toUpperCase().replace(/[^A-Z]/g, '') === normalizedResponse
interest => interest.toUpperCase().replaceAll(/[^A-Z]/g, '') === normalizedResponse
);

return matchedInterest || '';
Expand Down
6 changes: 4 additions & 2 deletions src/auth/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ import { ResetPasswordDto } from './dto/reset-password.dto';
import { UpdateEmailDto } from 'src/user/dto/update-email.dto';
import { UpdateUsernameDto } from 'src/user/dto/update-username.dto';
import { EmailDto, VerifyOtpDto } from './dto/email-verification.dto';
import { AuthJwtPayload } from 'src/types/jwtPayload';
import { AuthenticatedUser } from './interfaces/user.interface';
import { ChangePasswordDto } from './dto/change-password.dto';
import { VerifyPasswordDto } from './dto/verify-password.dto';
Expand Down Expand Up @@ -679,7 +678,10 @@ export class AuthController {
@Get('github/login')
@Public()
@UseGuards(GithubAuthGuard)
public githubLogin() {}
public githubLogin() {
// Passport guard redirect handles this - method intentionally empty
return;
}

@Get('github/redirect')
@Public()
Expand Down
1 change: 0 additions & 1 deletion src/auth/auth.module.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Module } from '@nestjs/common';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { PrismaService } from 'src/prisma/prisma.service';
import { UserModule } from 'src/user/user.module';
import { LocalStrategy } from './strategies/local.strategy';
import { JwtModule } from '@nestjs/jwt';
Expand Down
4 changes: 2 additions & 2 deletions src/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { RedisService } from 'src/redis/redis.service';
import { OAuth2Client } from 'google-auth-library';
import googleOauthConfig from './config/google-oauth.config';
import { ConfigType } from '@nestjs/config';
import { randomBytes } from 'crypto';
import { randomBytes } from 'node:crypto';
import { OAuthCodeData } from './interfaces/oauth-code-data.interface';

const ISVERIFIED_CACHE_PREFIX = 'verified:';
Expand All @@ -25,7 +25,7 @@ const CODE_EXPIRY = 300; // 5 minutes

@Injectable()
export class AuthService {
private googleClient: OAuth2Client;
private readonly googleClient: OAuth2Client;

constructor(
@Inject(Services.USER)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
ConflictException,
HttpException,
HttpStatus,
NotFoundException,
} from '@nestjs/common';
import { EmailService } from 'src/email/email.service';
import { UserService } from 'src/user/user.service';
Expand Down
2 changes: 1 addition & 1 deletion src/auth/services/jwt-token/jwt-token.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export class JwtTokenService {

public async generateAccessToken(userId: number, username: string): Promise<string> {
const payload: AuthJwtPayload = { sub: userId, username };
const [accessToken] = await Promise.all([this.jwtService.signAsync(payload)]);
const accessToken = await this.jwtService.signAsync(payload);
return accessToken;
}

Expand Down
6 changes: 3 additions & 3 deletions src/auth/services/password/password.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
BadRequestException,
} from '@nestjs/common';
import * as argon2 from 'argon2';
import * as crypto from 'crypto';
import * as crypto from 'node:crypto';
import { RequestPasswordResetDto } from 'src/auth/dto/request-password-reset.dto';
import { EmailService } from 'src/email/email.service';
import { UserService } from 'src/user/user.service';
Expand Down Expand Up @@ -149,15 +149,15 @@ export class PasswordService {
const key = `${MAX_RESET_ATTEMPTS_PREFIX}${email}`;
const attempts = await this.redisService.get(key);

if (attempts && parseInt(attempts) >= MAX_ATTEMPTS) {
if (attempts && Number.parseInt(attempts) >= MAX_ATTEMPTS) {
throw new BadRequestException('Too many password reset requests. Please try again later.');
}
}

private async incrementResetAttempts(email: string): Promise<void> {
const key = `${MAX_RESET_ATTEMPTS_PREFIX}${email}`;
const current = await this.redisService.get(key);
const count = current ? parseInt(current) + 1 : 1;
const count = current ? Number.parseInt(current) + 1 : 1;

await this.redisService.set(key, count.toString(), ATTEMPT_WINDOW_SECONDS);
}
Expand Down
2 changes: 1 addition & 1 deletion src/conversations/conversations.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export class ConversationsService {
});

const { Messages, ...conversationData } = oldConversation;
const reversedMessages = Messages.reverse(); // Reverse to show oldest first
const reversedMessages = Messages.toReversed(); // Reverse to show oldest first

return {
data: {
Expand Down
5 changes: 2 additions & 3 deletions src/email/email.controller.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Body, Controller, Inject, Post } from '@nestjs/common';
import { EmailService } from './email.service';
import { join } from 'path';
import { readFileSync } from 'fs';
import { join } from 'node:path';
import { readFileSync } from 'node:fs';
import { Routes, Services } from 'src/utils/constants';
import { Public } from 'src/auth/decorators/public.decorator';

Expand All @@ -21,7 +21,6 @@ export class EmailController {
'email-verification.html',
);
const template = readFileSync(templatePath, 'utf-8');
// console.log(template);
return this.emailService.sendEmail({
subject: 'Account Verification',
recipients: ['mohamedalbaz77@gmail.com'],
Expand Down
6 changes: 3 additions & 3 deletions src/email/email.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { Inject, Injectable, Logger, Optional } from '@nestjs/common';
import { ConfigType } from '@nestjs/config';
import mailerConfig from './../common/config/mailer.config';
import { SendEmailDto } from './dto/send-email.dto';
import { readFileSync } from 'fs';
import { join } from 'path';
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import { Resend } from 'resend';
import { EmailClient, EmailMessage, KnownEmailSendStatus } from '@azure/communication-email';
import * as nodemailer from 'nodemailer';
Expand Down Expand Up @@ -270,7 +270,7 @@ export class EmailService {
try {
let template = readFileSync(templatePath, 'utf-8');
for (const key of Object.keys(variables)) {
template = template.replace(new RegExp(`{{\\s*${key}\\s*}}`, 'g'), variables[key]);
template = template.replaceAll(new RegExp(`{{\\s*${key}\\s*}}`, 'g'), variables[key]);
}

return template;
Expand Down
4 changes: 2 additions & 2 deletions src/messages/messages.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ export class MessagesService {
}),
]);

const reversedMessages = messages.reverse(); // Return oldest first for chat display
const reversedMessages = messages.toReversed(); // Return oldest first for chat display

return {
data: reversedMessages,
Expand Down Expand Up @@ -281,7 +281,7 @@ export class MessagesService {
data: messages,
metadata: {
totalItems: messages.length,
firstMessageId: messages.length > 0 ? messages[messages.length - 1].id : null,
firstMessageId: messages.length > 0 ? messages.at(-1)!.id : null,
},
};
}
Expand Down
14 changes: 6 additions & 8 deletions src/notifications/notification.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,8 @@ export class NotificationService {
private async handleFailedTokens(responses: any[], tokens: string[]): Promise<void> {
const invalidTokens: string[] = [];

responses.forEach((response, index) => {
for (let index = 0; index < responses.length; index++) {
const response = responses[index];
if (!response.success) {
const errorCode = response.error?.code;
// Remove tokens that are invalid, not registered, or expired
Expand All @@ -299,7 +300,7 @@ export class NotificationService {
invalidTokens.push(tokens[index]);
}
}
});
}

if (invalidTokens.length > 0) {
await this.prismaService.deviceToken.deleteMany({
Expand Down Expand Up @@ -592,17 +593,14 @@ export class NotificationService {
where.type = { notIn: excludeTypes };
}

const [totalItems, notifications, unreadCount] = await Promise.all([
const [totalItems, notifications] = await Promise.all([
this.prismaService.notification.count({ where }),
this.prismaService.notification.findMany({
where,
orderBy: { createdAt: 'desc' },
skip: (page - 1) * limit,
take: limit,
}),
this.prismaService.notification.count({
where: { recipientId: userId, isRead: false },
}),
]);

// Fetch post data for REPLY, QUOTE, MENTION notifications
Expand Down Expand Up @@ -717,9 +715,9 @@ export class NotificationService {
const unreadNotifications = await notificationsRef.where('isRead', '==', false).get();

const batch = firestore.batch();
unreadNotifications.docs.forEach((doc) => {
for (const doc of unreadNotifications.docs) {
batch.update(doc.ref, { isRead: true });
});
}

await batch.commit();
} catch (error) {
Expand Down
90 changes: 1 addition & 89 deletions src/post/hashtag.controller.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
import {
Controller,
Get,
Post,
Query,
Param,
ParseIntPipe,
DefaultValuePipe,
HttpStatus,
HttpException,
UseGuards,
Inject,
Logger,
BadRequestException,
} from '@nestjs/common';
import { ApiOperation, ApiResponse, ApiQuery, ApiCookieAuth } from '@nestjs/swagger';
import { ApiOperation, ApiResponse, ApiQuery } from '@nestjs/swagger';
import { HashtagTrendService } from './services/hashtag-trends.service';
import { Services } from 'src/utils/constants';
import { TrendCategory, isValidTrendCategory } from './enums/trend-category.enum';
Expand Down Expand Up @@ -102,7 +97,6 @@ export class HashtagController {
user?.id,
);
}

return {
status: 'success',
data: { trending },
Expand All @@ -113,86 +107,4 @@ export class HashtagController {
},
};
}

// @Post('recalculate')
// @ApiCookieAuth()
// @ApiOperation({
// summary: 'Trigger hashtag trend recalculation',
// description:
// 'Manually triggers recalculation of trends for all active hashtags from the last 7 days, optionally filtered by category',
// })
// @ApiQuery({
// name: 'category',
// required: false,
// enum: TrendCategory,
// description:
// 'Category to recalculate trends for. Options: general, news, sports, entertainment, personalized. Defaults to "general" which processes all hashtags.',
// example: TrendCategory.GENERAL,
// })
// @ApiResponse({
// status: 200,
// description: 'Successfully queued recalculation',
// schema: {
// example: {
// status: 'success',
// message: 'Queued recalculation for 45 hashtags',
// data: {
// queuedHashtags: 45,
// category: 'sports',
// },
// },
// },
// })
// @ApiResponse({
// status: 400,
// description: 'Invalid category',
// })
// @ApiResponse({
// status: 500,
// description: 'Internal server error',
// })
// async recalculate(
// @Query('category', new DefaultValuePipe(TrendCategory.GENERAL)) category: string,
// ) {
// if (!isValidTrendCategory(category)) {
// throw new BadRequestException(
// `Invalid category. Must be one of: ${Object.values(TrendCategory).join(', ')}`,
// );
// }

// const count = await this.hashtagTrendService.recalculateTrends(category as TrendCategory);

// return {
// status: 'success',
// message: `Queued recalculation for ${count} hashtags in ${category} category`,
// data: {
// queuedHashtags: count,
// category,
// },
// };
// }

// @Post('reindex-hashtags')
// @ApiCookieAuth()
// @ApiOperation({
// summary: 'Reindex all post hashtags',
// description: 'Scans all posts and extracts hashtags, updating the hashtag relations.',
// })
// @ApiResponse({
// status: 200,
// description: 'Successfully completed reindexing',
// })
// @ApiResponse({
// status: 500,
// description: 'Internal server error',
// })
// async reindexHashtags() {
// const result = await this.hashtagTrendService.reindexAllPostHashtags();

// return {
// status: 'success',
// message: 'Hashtags reindexed',
// result,
// };
// }
}
4 changes: 2 additions & 2 deletions src/post/services/hashtag-trends.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,10 +206,10 @@ export class HashtagTrendService {
category,
);

redisMetadata.forEach((metadata, id) => {
for (const [id, metadata] of redisMetadata) {
metadataResults.set(id, metadata);
this.setMemoryCachedMetadata(id, metadata.tag, category);
});
}
}

const missingFromRedis = hashtagIds.filter((id) => !metadataResults.has(id));
Expand Down
2 changes: 1 addition & 1 deletion src/post/services/like.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Inject, Injectable, NotFoundException } from '@nestjs/common';
import { Inject, Injectable } from '@nestjs/common';
import { PrismaService } from 'src/prisma/prisma.service';
import { Services } from 'src/utils/constants';
import { EventEmitter2 } from '@nestjs/event-emitter';
Expand Down
2 changes: 1 addition & 1 deletion src/post/services/mention.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Inject, Injectable, NotFoundException } from '@nestjs/common';
import { Inject, Injectable } from '@nestjs/common';
import { PrismaService } from 'src/prisma/prisma.service';
import { Services } from 'src/utils/constants';
import { PostService } from './post.service';
Expand Down
Loading
Loading