Skip to content

Commit

Permalink
Fix/v0.0.1 버그픽스 (#12)
Browse files Browse the repository at this point in the history
* fix: 탯글 생성시 조회 조건에 feedId 사용되도록 수정

* feat: SlackConfig 필드 신규 추가

* feat: feed 신고 API 비즈니스 로직 변경

- 피드 신고 최소 글자 10 => 5로 변경
- 피드 신고횟수 5회시 피드 만료처리
- 피드 신고 횟수 5회시 슬랙 알림 전송 로직 추가
  • Loading branch information
dbwogus94 authored Oct 13, 2023
1 parent 0e431b7 commit 0b750d1
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 12 deletions.
49 changes: 43 additions & 6 deletions src/common/util/slack/slack-template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,14 @@ type Viewer = {
viewerText: string;
};
type MessageOptions = {
/**
* 서버 이름
*/
appType: string;
/**
* 메시지 헤더
*/
header: string;
/**
* 메시지 타입
*/
type: 'Alert' | 'Error';
type: 'Alert' | 'Error' | 'Report';
/**
* 메세지 발행 주체 ex)className
*/
Expand All @@ -45,6 +41,11 @@ type ErrorMessageOptions = MessageOptions & {
error: Error;
request?: Request;
};
type ReportAlertMessageOptions = MessageOptions & {
type: 'Report';
feed: { id: number; content: string; reportCount: number };
reason: string;
};

export class SlackTemplate {
public static alertTemplate(
Expand Down Expand Up @@ -88,8 +89,44 @@ export class SlackTemplate {
};
}

public static reportAlertTemplate(
options: ReportAlertMessageOptions,
): IncomingWebhookSendArguments {
const { viewer, feed, reason } = options;
const defaultAttachment = this.makeDefaultAttachment(options);
const viewerAttachment = this.makeViewerAttachment({
...viewer,
viewerUrl: `${viewer.viewerUrl}/${feed.id}`,
});
return {
attachments: [
defaultAttachment,
{
color: 'good',
fields: [
{
title: `*피드 정보*:`,
value:
'```' +
`- 피드 id: ${feed.id}\n- 피드 내용: ${feed.content}\n- 누적 신고 횟수: ${feed.reportCount}` +
'```',
short: false,
},
{
title: `*신고 내용*:`,
value: '```' + reason + '```',
short: false,
},
],
},
,
viewerAttachment,
],
};
}

private static makeDefaultAttachment(
options: AlertMessageOptions | ErrorMessageOptions,
options: MessageOptions,
): MessageAttachment {
return {
blocks: [
Expand Down
6 changes: 6 additions & 0 deletions src/config/app/environment/local.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,5 +78,11 @@ export const LocalConfig: AppConfig = {
description: process.env.SLACK_DESCRIPTION_BY_SERVER_ERROR_ALERT,
viewerUrl: process.env.SLACK_VIEWER_URL_BY_SERVER_ERROR_ALERT,
},
feedReportAlert: {
webHooklUrl: process.env.SLACK_WEB_HOOK_URI_BY_FEED_REPORT_ALERT,
channelName: process.env.SLACK_CHANNEL_NAME_BY_FEED_REPORT_ALERT,
description: process.env.SLACK_DESCRIPTION_BY_FEED_REPORT_ALERT,
viewerUrl: process.env.SLACK_VIEWER_URL_BY_FEED_REPORT_ALERT,
},
},
};
6 changes: 6 additions & 0 deletions src/config/app/environment/production.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,5 +78,11 @@ export const ProdConfig: AppConfig = {
description: process.env.SLACK_DESCRIPTION_BY_SERVER_ERROR_ALERT,
viewerUrl: process.env.SLACK_VIEWER_URL_BY_SERVER_ERROR_ALERT,
},
feedReportAlert: {
webHooklUrl: process.env.SLACK_WEB_HOOK_URI_BY_FEED_REPORT_ALERT,
channelName: process.env.SLACK_CHANNEL_NAME_BY_FEED_REPORT_ALERT,
description: process.env.SLACK_DESCRIPTION_BY_FEED_REPORT_ALERT,
viewerUrl: process.env.SLACK_VIEWER_URL_BY_FEED_REPORT_ALERT,
},
},
};
3 changes: 3 additions & 0 deletions src/config/monitor/slack.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,7 @@ export class SlackAlertOptions {
export class SlackConfig {
@InstanceValidator(SlackAlertOptions)
readonly serverErrorAlert: SlackAlertOptions;

@InstanceValidator(SlackAlertOptions)
readonly feedReportAlert: SlackAlertOptions;
}
1 change: 0 additions & 1 deletion src/custom/nest/interceptor/slack-sender.interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ export class SlackSenderInterceptor implements NestInterceptor {
const message = SlackTemplate.errorTemplate({
error,
request,
appType: this.config.get('appType'),
header: `${appName}-API-Server 버그 발생`,
type: 'Error',
trigger: 'SlackInterceptor',
Expand Down
4 changes: 4 additions & 0 deletions src/domain/feed/domain/feed.domain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ export class Feed extends BaseDomain<FeedProps> {
return this.props.activationAt >= new Date();
}

get isLockFeed(): boolean {
return this.props.reportCount >= 5;
}

/* ========== method ========== */
addViewCount(): this {
this.props.viewCount++;
Expand Down
1 change: 1 addition & 0 deletions src/domain/feed/feed.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ export class FeedRepositoryImpl
qb.select();
qb.innerJoin('comment.user', 'user') //
.addSelect(['user.id', 'user.nickname', 'user.mbtiType']);
qb.where('comment.feedId = :feedId', { feedId });
if (!Util.isNil(nextCursor)) {
sort === 'ASC' && qb.andWhere('comment.id >= :id', { id: nextCursor });
sort !== 'ASC' && qb.andWhere('comment.id <= :id', { id: nextCursor });
Expand Down
36 changes: 33 additions & 3 deletions src/domain/feed/feed.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
NotFoundException,
} from '@nestjs/common';

import { Util, errorMessage } from '@app/common';
import { SlackTemplate, Util, errorMessage } from '@app/common';
import { InjectDataSource } from '@nestjs/typeorm';
import { DataSource } from 'typeorm';
import { UserRepository, UserRepositoryToken } from '../user/user.repository';
Expand All @@ -25,6 +25,10 @@ import {
import { FeedRepository, FeedRepositoryToken } from './feed.repository';
import { RecommendType } from '@app/entity';
import { UploadService, UploadServiceToken } from './upload/upload.service';
import { ConfigService } from '@nestjs/config';
import { SlackAlertOptions, SlackConfig } from '@app/config';
import { IncomingWebhook } from '@slack/client';
import { Feed } from './domain';

export const FeedServiceToken = Symbol('FeedServiceToken');
export interface FeedService {
Expand Down Expand Up @@ -72,12 +76,19 @@ export interface FeedService {

@Injectable()
export class FeedServiceImpl implements FeedService {
private readonly reportAlartConfig: SlackAlertOptions;
private readonly webhook: IncomingWebhook;

constructor(
@InjectDataSource() private readonly dataSource: DataSource,
@Inject(FeedRepositoryToken) private readonly feedRepo: FeedRepository,
@Inject(UserRepositoryToken) private readonly userRepo: UserRepository,
@Inject(UploadServiceToken) private readonly uploadService: UploadService,
) {}
config: ConfigService,
) {
this.reportAlartConfig = config.get<SlackConfig>('slack').feedReportAlert;
this.webhook = new IncomingWebhook(this.reportAlartConfig.webHooklUrl);
}

async getFeeds(getDto: GetFeedsRequestDTO): Promise<GetFeedsResponseDTO[]> {
const feeds =
Expand Down Expand Up @@ -247,10 +258,13 @@ export class FeedServiceImpl implements FeedService {
if (isExist) throw new ConflictException(errorMessage.E409_FEED_003);

await txFeedRepo.createReportHistory(userId, feedId, postDto);
// TODO: report 로직 향후 변경 예정
await txFeedRepo.updateProperty(feedId, {
reportCount: feed.addReportCount().reportCount,
activationAt: feed.isLockFeed ? new Date() : feed.activationAt,
});
// TODO: 신고 횟수가 5회 이상이면 슬랙에 알림을 보내는 로직을 추가한다.

feed.isLockFeed && (await this.feedReportAlert(feed, postDto.reason));
await queryRunner.commitTransaction();
} catch (error) {
await queryRunner.rollbackTransaction();
Expand Down Expand Up @@ -306,4 +320,20 @@ export class FeedServiceImpl implements FeedService {
await queryRunner.release();
}
}

private async feedReportAlert(feed: Feed, reason: string) {
const { viewerUrl } = this.reportAlartConfig;
const message = SlackTemplate.reportAlertTemplate({
header: '피드 신고 알림',
type: 'Report',
trigger: 'FeedService',
viewer: {
viewerUrl,
viewerText: '피드 신고 내역 확인',
},
feed,
reason,
});
await this.webhook.send(message);
}
}
4 changes: 2 additions & 2 deletions src/entity/feed/report-history.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ export class ReportHistoryEntity extends BaseEntity {
@ApiProperty({
description: '신고 사유',
type: String,
minLength: 10,
minLength: 5,
maxLength: 200,
})
@Expose()
@StringValidator({ minLength: 10, maxLength: 200 })
@StringValidator({ minLength: 5, maxLength: 200 })
@Column('varchar', { comment: '신고 사유', length: 200 })
reason: string;

Expand Down

0 comments on commit 0b750d1

Please sign in to comment.