Skip to content

Commit

Permalink
Merge pull request #238 from hufscheer/feat/#231-cheertalk
Browse files Browse the repository at this point in the history
[FEAT] 신고된 응원톡 가리기/가리기 해제 기능
  • Loading branch information
Zena0128 authored Sep 27, 2024
2 parents 23f1599 + e53bfc6 commit ed5ef23
Show file tree
Hide file tree
Showing 16 changed files with 355 additions and 30 deletions.
8 changes: 8 additions & 0 deletions src/docs/asciidoc/api.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ operation::cheer-talk-query-controller-test/응원톡을_조회한다[snippets='

operation::cheer-talk-query-controller-test/리그의_신고된_응원톡을_조회한다[snippets='http-request,query-parameters,path-parameters,http-response,response-fields']

=== 응원톡 가리기

operation::cheer-talk-controller-test/응원톡을_가린다[snippets='http-request,path-parameters,http-response']

=== 응원톡을 가리기 취소하기

operation::cheer-talk-controller-test/응원톡을_가리기_취소한다[snippets='http-request,path-parameters,http-response']

=== 응원톡 관리 화면에서의 응원톡 전체 조회

operation::cheer-talk-query-controller-test/리그의_차단되지_않은_응원톡을_조회한다[snippets='http-request,query-parameters,path-parameters,http-response,response-fields']
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ SecurityFilterChain filterChain(HttpSecurity http, MvcRequestMatcher.Builder mvc
mvc.pattern(HttpMethod.GET, "/leagues/{leagueId}/cheer-talks/**"),
mvc.pattern(HttpMethod.POST, "/leagues/{leagueId}/games"),
mvc.pattern(HttpMethod.POST, "/games/*/timelines/**"),
mvc.pattern(HttpMethod.POST, "/games/{gameId}/lineup-players/{lineupPlayerId}/**")
mvc.pattern(HttpMethod.POST, "/games/{gameId}/lineup-players/{lineupPlayerId}/**"),
mvc.pattern(HttpMethod.PATCH, "/cheer-talks/{leagueId}/{cheerTalkId}/**")
)
.authenticated()
.anyRequest().permitAll()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,39 @@

import static com.sports.server.command.cheertalk.exception.CheerTalkErrorMessages.CHEER_TALK_CONTAINS_BAD_WORD;

import com.sports.server.auth.exception.AuthorizationErrorMessages;
import com.sports.server.command.cheertalk.domain.CheerTalk;
import com.sports.server.command.cheertalk.domain.CheerTalkRepository;
import com.sports.server.command.cheertalk.domain.LanguageFilter;
import com.sports.server.command.cheertalk.dto.CheerTalkRequest;
import com.sports.server.command.cheertalk.exception.CheerTalkErrorMessages;
import com.sports.server.command.league.domain.League;
import com.sports.server.command.member.domain.Member;
import com.sports.server.command.report.domain.Report;
import com.sports.server.command.report.domain.ReportRepository;
import com.sports.server.command.report.domain.ReportState;
import com.sports.server.command.report.exception.ReportErrorMessage;
import com.sports.server.common.application.EntityUtils;
import com.sports.server.common.application.PermissionValidator;
import com.sports.server.common.exception.CustomException;
import com.sports.server.common.exception.UnauthorizedException;
import com.sports.server.query.repository.CheerTalkDynamicRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

@Service
@Transactional
@RequiredArgsConstructor
public class CheerTalkService {

private final CheerTalkRepository cheerTalkRepository;
private final ReportRepository reportRepository;
private final LanguageFilter languageFilter;
private final EntityUtils entityUtils;

public void register(final CheerTalkRequest cheerTalkRequest) {
validateContent(cheerTalkRequest.content());
Expand All @@ -31,4 +47,29 @@ private void validateContent(final String content) {
throw new CustomException(HttpStatus.BAD_REQUEST, CHEER_TALK_CONTAINS_BAD_WORD);
}
}

public void block(final Long leagueId, final Long cheerTalkId, final Member manager) {
League league = entityUtils.getEntity(leagueId, League.class);
PermissionValidator.checkPermission(league, manager);

CheerTalk cheerTalk = entityUtils.getEntity(cheerTalkId, CheerTalk.class);

Optional<Report> report = reportRepository.findByCheerTalk(cheerTalk);
if (report.isPresent()) {
report.get().accept();
} else {
cheerTalk.block();
}
}

public void unblock(final Long leagueId, final Long cheerTalkId, final Member manager) {
League league = entityUtils.getEntity(leagueId, League.class);
PermissionValidator.checkPermission(league, manager);

CheerTalk cheerTalk = entityUtils.getEntity(cheerTalkId, CheerTalk.class);

Optional<Report> report = reportRepository.findByCheerTalk(cheerTalk);
report.ifPresent(Report::cancel);
cheerTalk.unblock();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ public void block() {
this.isBlocked = true;
}

public void unblock() {
this.isBlocked = false;
}

public CheerTalk(final String content, final Long gameTeamId) {
this.createdAt = LocalDateTime.now();
this.content = content;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,38 @@

import com.sports.server.command.cheertalk.application.CheerTalkService;
import com.sports.server.command.cheertalk.dto.CheerTalkRequest;
import com.sports.server.command.member.domain.Member;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
@RequestMapping("/cheer-talks")
public class CheerTalkController {

private final CheerTalkService cheerTalkService;

@PostMapping("/cheer-talks")
@PostMapping
public ResponseEntity<Void> register(@RequestBody @Valid final CheerTalkRequest cheerTalkRequest) {
cheerTalkService.register(cheerTalkRequest);
return ResponseEntity.ok(null);
}

@PatchMapping("/{leagueId}/{cheerTalkId}/block")
public ResponseEntity<Void> block(@PathVariable Long leagueId,
@PathVariable Long cheerTalkId,
final Member manager) {
cheerTalkService.block(leagueId, cheerTalkId, manager);
return ResponseEntity.ok().build();
}

@PatchMapping("{leagueId}/{cheerTalkId}/unblock")
public ResponseEntity<Void> unblock(@PathVariable Long leagueId,
@PathVariable Long cheerTalkId,
final Member manager) {
cheerTalkService.unblock(leagueId, cheerTalkId, manager);
return ResponseEntity.ok().build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public void check(CheerTalk cheerTalk, Report report) {
}

if (cachedBadWords.contains(cheerTalk.getContent())) {
report.updateToValid();
report.accept();
return;
}
report.updateToPending();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,17 @@ public boolean isUnchecked() {
return this.state == ReportState.UNCHECKED;
}

public void updateToValid() {
public void accept() {
this.state = ReportState.VALID;
cheerTalk.block();
}

public void updateToPending() {
this.state = ReportState.PENDING;
}

public void cancel() {
this.state = ReportState.INVALID;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@ public class ReportErrorMessage {

public static final String INVALID_REPORT_BLOCKED_CHEER_TALK = "이미 블락된 응원톡은 신고할 수 없습니다.";
public static final String REPORT_CHECK_SERVER_ERROR = "신고 검사 서버에 문제가 발생했습니다";
public static final String REPORT_NOT_EXIST = "해당 응원톡에 대한 신고가 존재하지 않습니다.";
public static final String REPORT_NOT_PENDING = "대기 상태가 아닌 신고는 유효 처리할 수 없습니다.";
public static final String REPORT_NOT_VALID = "유효하지 않은 신고는 무효 처리할 수 없습니다.";
}
130 changes: 117 additions & 13 deletions src/main/resources/static/docs/api.html
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,8 @@ <h1>훕치치 서버 API 문서</h1>
<li><a href="#_응원톡_저장">응원톡 저장</a></li>
<li><a href="#_응원톡_조회">응원톡 조회</a></li>
<li><a href="#_신고된_리그의_응원톡_전체_조회">신고된 리그의 응원톡 전체 조회</a></li>
<li><a href="#_응원톡_가리기">응원톡 가리기</a></li>
<li><a href="#_응원톡을_가리기_취소하기">응원톡을 가리기 취소하기</a></li>
<li><a href="#_응원톡_관리_화면에서의_응원톡_전체_조회">응원톡 관리 화면에서의 응원톡 전체 조회</a></li>
</ul>
</li>
Expand Down Expand Up @@ -883,6 +885,104 @@ <h4 id="_신고된_리그의_응원톡_전체_조회_response_fields"><a class="
</div>
</div>
<div class="sect2">
<h3 id="_응원톡_가리기"><a class="link" href="#_응원톡_가리기">응원톡 가리기</a></h3>
<div class="sect3">
<h4 id="_응원톡_가리기_http_request"><a class="link" href="#_응원톡_가리기_http_request">HTTP request</a></h4>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight nowrap"><code class="language-http hljs" data-lang="http">PATCH /cheer-talks/1/1/block HTTP/1.1
Content-Type: application/json
Host: www.api.hufstreaming.site
Cookie: HCC_SES=temp-cookie</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_응원톡_가리기_path_parameters"><a class="link" href="#_응원톡_가리기_path_parameters">Path parameters</a></h4>
<table class="tableblock frame-all grid-all stretch">
<caption class="title">Table 1. /cheer-talks/{leagueId}/{cheerTalkId}/block</caption>
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Parameter</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>leagueId</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">리그의 ID</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cheerTalkId</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">응원톡의 ID</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect3">
<h4 id="_응원톡_가리기_http_response"><a class="link" href="#_응원톡_가리기_http_response">HTTP response</a></h4>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight nowrap"><code class="language-http hljs" data-lang="http">HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_응원톡을_가리기_취소하기"><a class="link" href="#_응원톡을_가리기_취소하기">응원톡을 가리기 취소하기</a></h3>
<div class="sect3">
<h4 id="_응원톡을_가리기_취소하기_http_request"><a class="link" href="#_응원톡을_가리기_취소하기_http_request">HTTP request</a></h4>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight nowrap"><code class="language-http hljs" data-lang="http">PATCH /cheer-talks/1/1/unblock HTTP/1.1
Content-Type: application/json
Host: www.api.hufstreaming.site
Cookie: HCC_SES=temp-cookie</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_응원톡을_가리기_취소하기_path_parameters"><a class="link" href="#_응원톡을_가리기_취소하기_path_parameters">Path parameters</a></h4>
<table class="tableblock frame-all grid-all stretch">
<caption class="title">Table 1. /cheer-talks/{leagueId}/{cheerTalkId}/unblock</caption>
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Parameter</th>
<th class="tableblock halign-left valign-top">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>leagueId</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">리그의 ID</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>cheerTalkId</code></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">응원톡의 ID</p></td>
</tr>
</tbody>
</table>
</div>
<div class="sect3">
<h4 id="_응원톡을_가리기_취소하기_http_response"><a class="link" href="#_응원톡을_가리기_취소하기_http_response">HTTP response</a></h4>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight nowrap"><code class="language-http hljs" data-lang="http">HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers</code></pre>
</div>
<h3 id="_응원톡_관리_화면에서의_응원톡_전체_조회"><a class="link" href="#_응원톡_관리_화면에서의_응원톡_전체_조회">응원톡 관리 화면에서의 응원톡 전체 조회</a></h3>
<div class="sect3">
<h4 id="_응원톡_관리_화면에서의_응원톡_전체_조회_http_request"><a class="link" href="#_응원톡_관리_화면에서의_응원톡_전체_조회_http_request">HTTP request</a></h4>
Expand Down Expand Up @@ -1800,7 +1900,7 @@ <h4 id="_게임_등록_http_request"><a class="link" href="#_게임_등록_http_
"round" : "16강",
"quarter" : "경기전",
"state" : "SCHEDULED",
"startTime" : "2024-09-26T14:37:45.37172",
"startTime" : "2024-09-11T12:00:00",
"idOfTeam1" : 1,
"idOfTeam2" : 2,
"videoId" : "videoId"
Expand Down Expand Up @@ -1851,7 +1951,7 @@ <h4 id="_게임_수정_http_request"><a class="link" href="#_게임_수정_http_
<div class="content">
<pre class="highlightjs highlight nowrap"><code class="language-http hljs" data-lang="http">PUT /leagues/1/1 HTTP/1.1
Content-Type: application/json
Content-Length: 172
Content-Length: 165
Host: www.api.hufstreaming.site
Cookie: HCC_SES=temp-cookie

Expand All @@ -1860,7 +1960,7 @@ <h4 id="_게임_수정_http_request"><a class="link" href="#_게임_수정_http_
"round" : "16강",
"quarter" : "전반전",
"state" : "PLAYING",
"startTime" : "2024-09-26T14:37:45.401267",
"startTime" : "2024-09-11T12:00:00",
"videoId" : "videoId"
}</code></pre>
</div>
Expand Down Expand Up @@ -2127,8 +2227,8 @@ <h4 id="_리그_생성_http_request"><a class="link" href="#_리그_생성_http_
{
"name" : "우물정 제기차기 대회",
"maxRound" : 4,
"startAt" : "2024-09-26T14:37:45.97513",
"endAt" : "2024-09-26T14:37:45.975134"
"startAt" : "2024-09-11T12:00:00",
"endAt" : "2024-09-11T12:00:00"
}</code></pre>
</div>
</div>
Expand Down Expand Up @@ -2198,8 +2298,8 @@ <h4 id="_리그_수정_http_request"><a class="link" href="#_리그_수정_http_

{
"name" : "훕치치배 망고 빨리먹기 대회",
"startAt" : "2024-09-26T14:37:46.00987",
"endAt" : "2024-09-26T14:37:46.009875",
"startAt" : "2024-09-11T12:00:00",
"endAt" : "2024-09-11T12:00:00",
"maxRound" : "16강"
}</code></pre>
</div>
Expand Down Expand Up @@ -3077,10 +3177,14 @@ <h4 id="_매니저가_생성한_리그_전체_조회홈_화면_http_response"><a
"id" : 1,
"name" : "삼건물 대회",
"state" : "진행 중",
"sizeOfLeagueTeams" : 2,
"maxRound" : "16강",
"startAt" : "2024-09-11T12:00:00",
"endAt" : "2024-09-11T12:00:00",
"inProgressGames" : [ {
"id" : 1,
"state" : "PLAYING",
"startTime" : "2024-09-26T14:37:52.423409",
"startTime" : "2024-09-11T12:00:00",
"gameTeams" : [ {
"gameTeamId" : 1,
"gameTeamName" : "경영 야생마",
Expand Down Expand Up @@ -3207,16 +3311,16 @@ <h4 id="_매니저가_생성한_리그_전체_조회대회_관리_화면_http_re
"leagueProgress" : "진행 중",
"sizeOfLeagueTeams" : 2,
"maxRound" : "16강",
"startAt" : "2024-09-26T14:37:52.514306",
"endAt" : "2024-09-26T14:37:52.51431"
"startAt" : "2024-09-11T12:00:00",
"endAt" : "2024-09-11T12:00:00"
}, {
"id" : 2,
"name" : "탁구 대회",
"leagueProgress" : "시작 전",
"sizeOfLeagueTeams" : 2,
"maxRound" : "16강",
"startAt" : "2024-09-26T14:37:52.514323",
"endAt" : "2024-09-26T14:37:52.514323"
"startAt" : "2024-09-11T12:00:00",
"endAt" : "2024-09-11T12:00:00"
} ]</code></pre>
</div>
</div>
Expand Down Expand Up @@ -4573,7 +4677,7 @@ <h4 id="_사용자_정보_조회_response_fields"><a class="link" href="#_사용
<div id="footer">
<div id="footer-text">
Version 0.0.1-SNAPSHOT<br>
Last updated 2024-09-25 10:46:55 +0900
Last updated 2024-09-25 22:08:26 +0900
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.18.3/highlight.min.js"></script>
Expand Down
Loading

0 comments on commit ed5ef23

Please sign in to comment.