Skip to content

Commit

Permalink
Merge pull request #239 from team-winey/feature/#238
Browse files Browse the repository at this point in the history
[Feat]#238 feature: ์ „์ฒด ํ‘ธ์‹œ์•Œ๋ฆผ๋ฉ”์‹œ์ง€ ๋ฐœ์†ก
  • Loading branch information
sss4920 authored Mar 13, 2024
2 parents e8a16ce + a7af2f6 commit d143603
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 7 deletions.
35 changes: 35 additions & 0 deletions src/main/java/org/winey/server/controller/BroadCastController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.winey.server.controller;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.winey.server.common.dto.ApiResponse;
import org.winey.server.controller.request.broadcast.BroadCastAllUserDto;
import org.winey.server.exception.Success;
import org.winey.server.service.BroadCastService;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.firebase.messaging.FirebaseMessagingException;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
@RequestMapping("/broadcast")
@Tag(name = "BroadCast", description = "์œ„๋‹ˆ ์ „์ฒด ํ‘ธ์‹œ API Document")
public class BroadCastController {
private final BroadCastService broadCastService;

@PostMapping("/send-all")
@ResponseStatus(HttpStatus.OK)
@Operation(summary = "์ „์ฒด ์œ ์ €์—๊ฒŒ ๋ฉ”์‹œ์ง€ ๋ฐœ์†ก API", description = "์ „์ฒด ์œ ์ €์—๊ฒŒ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐœ์†กํ•ฉ๋‹ˆ๋‹ค.")
public ApiResponse sendMessageToEntireUser(@RequestBody BroadCastAllUserDto broadCastAllUserDto){
return ApiResponse.success(Success.SEND_ENTIRE_MESSAGE_SUCCESS, broadCastService.broadAllUser(broadCastAllUserDto));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.winey.server.controller.request.broadcast;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@AllArgsConstructor
public class BroadCastAllUserDto {
String title;

String message;
}
2 changes: 2 additions & 0 deletions src/main/java/org/winey/server/exception/Error.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ public enum Error {
* 422 UNPROCESSABLE ENTITY
*/
UNPROCESSABLE_ENTITY_DELETE_EXCEPTION(HttpStatus.UNPROCESSABLE_ENTITY, "ํด๋ผ์˜ ์š”์ฒญ์„ ์ดํ•ดํ–ˆ์ง€๋งŒ ์‚ญ์ œํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค."),
UNPROCESSABLE_FIND_USERS(HttpStatus.UNPROCESSABLE_ENTITY, "์š”์ฒญ์„ ์ดํ•ดํ–ˆ์ง€๋งŒ ์œ ์ €๋“ค์„ ์ฐพ์„ ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค."),
UNPROCESSABLE_SEND_TO_FIREBASE(HttpStatus.UNPROCESSABLE_ENTITY, "ํŒŒ์ด์–ด๋ฒ ์ด์Šค๋กœ ์ „์†กํ•˜๋Š” ๊ณผ์ •์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค."),

/**
* 500 INTERNAL SERVER ERROR
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/winey/server/exception/Success.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public enum Success {
BLOCK_USER_SUCCESS(HttpStatus.OK, "์œ ์ € ์ฐจ๋‹จ ์„ฑ๊ณต"),
GET_ACHIEVEMENT_STATUS_SUCCESS(HttpStatus.OK, "๋ ˆ๋ฒจ ๋‹ฌ์„ฑ ํ˜„ํ™ฉ ์กฐํšŒ ์„ฑ๊ณต"),

SEND_ENTIRE_MESSAGE_SUCCESS(HttpStatus.OK, "์ „์ฒด ๋ฉ”์‹œ์ง€ ์ „์†ก ์„ฑ๊ณต"),

/**
* 201 CREATED
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.Repository;
import org.springframework.lang.Nullable;
import org.winey.server.domain.feed.Feed;
import org.winey.server.domain.goal.Goal;
import org.winey.server.domain.recommend.Recommend;
Expand All @@ -18,6 +19,9 @@ public interface UserRepository extends Repository<User, Long> {
// READ
Optional<User> findByUserId(Long userId);

List<User> findByFcmTokenNotNull();


Boolean existsBySocialIdAndSocialType(String socialId, SocialType socialType);

Optional<User> findBySocialIdAndSocialType(String socialId, SocialType socialType);
Expand Down
54 changes: 54 additions & 0 deletions src/main/java/org/winey/server/service/BroadCastService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package org.winey.server.service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.winey.server.common.dto.ApiResponse;
import org.winey.server.controller.request.broadcast.BroadCastAllUserDto;
import org.winey.server.domain.user.User;
import org.winey.server.exception.Error;
import org.winey.server.exception.Success;
import org.winey.server.exception.model.CustomException;
import org.winey.server.infrastructure.UserRepository;
import org.winey.server.service.message.SendAllFcmDto;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.firebase.messaging.FirebaseMessagingException;
import com.sun.net.httpserver.Authenticator;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class BroadCastService {

private final FcmService fcmService;

private final UserRepository userRepository;

public ApiResponse broadAllUser(BroadCastAllUserDto broadCastAllUserDto){
List<User> allUser = userRepository.findByFcmTokenNotNull();
List<String> tokenList;
if (!allUser.isEmpty()){
try {
tokenList = allUser.stream().map(
User::getFcmToken).collect(Collectors.toList());
System.out.println(tokenList);
fcmService.sendAllByTokenList(
SendAllFcmDto.of(tokenList, broadCastAllUserDto.getTitle(), broadCastAllUserDto.getMessage()));
return ApiResponse.success(Success.SEND_ENTIRE_MESSAGE_SUCCESS,
Success.SEND_ENTIRE_MESSAGE_SUCCESS.getMessage());
}catch (FirebaseMessagingException | JsonProcessingException e){
return ApiResponse.error(Error.UNPROCESSABLE_SEND_TO_FIREBASE, Error.UNPROCESSABLE_SEND_TO_FIREBASE.getMessage());
}
}
return ApiResponse.error(Error.UNPROCESSABLE_FIND_USERS, Error.UNPROCESSABLE_FIND_USERS.getMessage());
}




}
70 changes: 63 additions & 7 deletions src/main/java/org/winey/server/service/FcmService.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,20 @@
import okhttp3.Response;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.winey.server.service.message.FcmMessage;
import org.winey.server.service.message.FcmRequestDto;
import org.winey.server.service.message.SendAllFcmDto;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -104,13 +108,6 @@ public void sendByTokenList(List<String> tokenList) {
@Async
public CompletableFuture<Response> sendByToken(FcmRequestDto wineyNotification) throws JsonProcessingException {
// ๋ฉ”์‹œ์ง€ ๋งŒ๋“ค๊ธฐ
// Message message = Message.builder()
// .putData("feedId", String.valueOf(wineyNotification.getFeedId()))
// .putData("notiType", String.valueOf(wineyNotification.getType()))
// .putData("title", "์œ„๋‹ˆ ์ œ๊ตญ์˜ ํŽธ์ง€๊ฐ€ ๋„์ฐฉํ–ˆ์–ด์š”.")
// .putData("message" ,wineyNotification.getMessage())
// .setToken(wineyNotification.getToken()) <- ๋งŒ์•ฝ ์—ฌ๊ธฐ destination ๋ถ€๋ถ„๋งŒ ์ˆ˜์ •ํ•ด๋„ ๋  ์ˆ˜๋„ ์žˆ์Œ. ๊ฐ€๋Šฅ์„ฑ ์ƒ๊ฐํ•˜๊ธฐ
// .build();
String jsonMessage = makeSingleMessage(wineyNotification);
// ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์„ ๋ฐ›์„ response
Response response;
Expand Down Expand Up @@ -182,5 +179,64 @@ private String makeSingleMessage(FcmRequestDto wineyNotification) throws JsonPro
}
}

// private List<FcmMessage> makeCustomMessages(SendAllFcmDto wineyNotification) throws JsonProcessingException {
// try {
// List<FcmMessage> messages = wineyNotification.getTokenList()
// .stream()
// .map(token -> FcmMessage.builder()
// .message(FcmMessage.Message.builder()
// .token(token) // 1:1 ์ „์†ก ์‹œ ๋ฐ˜๋“œ์‹œ ํ•„์š”ํ•œ ๋Œ€์ƒ ํ† ํฐ ์„ค์ •
// .data(FcmMessage.Data.builder()
// .title("์œ„๋‹ˆ ์ œ๊ตญ์˜ ํŽธ์ง€๊ฐ€ ๋„์ฐฉํ–ˆ์–ด์š”.")
// .message(wineyNotification.getMessage())
// .feedId(null)
// .notiType(null)
// .build())
// .notification(FcmMessage.Notification.builder()
// .title("์œ„๋‹ˆ ์ œ๊ตญ์˜ ํŽธ์ง€๊ฐ€ ๋„์ฐฉํ–ˆ์–ด์š”.")
// .body(wineyNotification.getMessage())
// .build())
// .build()
// ).validateOnly(false)
// .build()).collect(Collectors.toList());
// return messages;
// } catch (Exception e) {
// throw new IllegalArgumentException("JSON ์ฒ˜๋ฆฌ ๋„์ค‘์— ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.");
// }
// }

public CompletableFuture<BatchResponse> sendAllByTokenList(SendAllFcmDto wineyNotification) throws JsonProcessingException, FirebaseMessagingException {
// These registration tokens come from the client FCM SDKs.
List<String> registrationTokens = wineyNotification.getTokenList();
try {
MulticastMessage message = MulticastMessage.builder()
.putData("title", wineyNotification.getTitle())
.putData("message", wineyNotification.getMessage())
.setNotification(new Notification(wineyNotification.getTitle(), wineyNotification.getMessage()))
.addAllTokens(registrationTokens)
.build();
BatchResponse response = FirebaseMessaging.getInstance().sendMulticast(message);
if (response.getFailureCount() > 0) {
List<SendResponse> responses = response.getResponses();
List<String> failedTokens = new ArrayList<>();
for (int i = 0; i < responses.size(); i++) {
if (!responses.get(i).isSuccessful()) {
// The order of responses corresponds to the order of the registration tokens.
failedTokens.add(registrationTokens.get(i));
}
}

System.out.println("List of tokens that caused failures: " + failedTokens);
}
return CompletableFuture.completedFuture(response);
} catch (Exception e){
log.info(e.getMessage());
}
return null;
}
private Notification convertToFirebaseNotification(FcmMessage.Notification customNotification) {
return new Notification(customNotification.getTitle(), customNotification.getBody());
}

}

23 changes: 23 additions & 0 deletions src/main/java/org/winey/server/service/message/SendAllFcmDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.winey.server.service.message;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.winey.server.domain.notification.NotiType;

import java.io.Serializable;
import java.util.List;
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class SendAllFcmDto {
private List<String> tokenList;

private String title;

private String message;

public static SendAllFcmDto of(List<String> tokenList, String title, String message){
return new SendAllFcmDto(tokenList, title, message);
}
}

0 comments on commit d143603

Please sign in to comment.