Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
umi0410 committed Nov 17, 2021
2 parents bde443b + 96ce203 commit 7d21669
Show file tree
Hide file tree
Showing 20 changed files with 302 additions and 164 deletions.
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ build/
# resources์—๋Š” credential์ด ์œ„์น˜ํ•  ์ˆ˜๋„ ์žˆ์Œ.
/src/main/resources
!/src/main/resources/application.properties
testdata.sh
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ build/
# resources์—๋Š” credential์ด ์œ„์น˜ํ•  ์ˆ˜๋„ ์žˆ์Œ.
**/src/main/resources
!**/src/main/resources/application.properties
testdata.sh
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ dependencies {
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.springframework.boot:spring-boot-starter-security'

implementation("com.slack.api:slack-api-client:1.12.1")

// gson
implementation('com.google.code.gson:gson:2.8.0')

// jpa mysql driver
// ์ฐธ๊ณ  https://victorydntmd.tistory.com/321
runtimeOnly 'mysql:mysql-connector-java'
implementation 'mysql:mysql-connector-java:8.0.25'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

// logger
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,28 @@

import com.fasterxml.jackson.annotation.JsonProperty;
import com.khumu.alimi.data.ResourceKind;
import com.khumu.alimi.data.dto.AnnouncementDto;
import com.khumu.alimi.data.dto.NotificationDto;
import com.khumu.alimi.data.dto.ResourceNotificationSubscriptionDto;
import com.khumu.alimi.data.dto.SimpleKhumuUserDto;
import com.khumu.alimi.data.entity.Notification;
import com.khumu.alimi.data.dto.*;
import com.khumu.alimi.data.entity.ResourceNotificationSubscription;
import com.khumu.alimi.service.KhumuException;
import com.khumu.alimi.service.NotifyAnnouncementCrawledService;
import com.khumu.alimi.service.notification.NotificationService;
import com.khumu.alimi.service.notification.NotifyNewAnnouncementService;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.method.P;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

import static com.khumu.alimi.service.KhumuException.*;

@RequiredArgsConstructor
@Slf4j
@RestController
public class NotificationController {
final NotificationService notificationService;
private final NotifyNewAnnouncementService notifyNewAnnouncementService;
private final NotificationService notificationService;
private final NotifyAnnouncementCrawledService announcementEventService;

@RequestMapping(value="/ping", method=RequestMethod.GET)
public String ping() {
Expand Down Expand Up @@ -98,8 +88,8 @@ public DefaultResponse<Object> delete(@AuthenticationPrincipal SimpleKhumuUserDt
@ResponseStatus(code = HttpStatus.OK)
// TODO: ์ง€๊ธˆ์€ ํŽธ์˜์ƒ ๊ทธ๋ƒฅ Notification์„ return
// ๊ทผ๋ฐ ์–˜๋Š” ์˜์†ํ™”๋œ Notification์ด ์•„๋‹ˆ๋ผ ํ‘ธ์‹œ์•Œ๋ฆผ๋งŒ ๋ณด๋ƒ„.
public List<Notification> notifyNewAnnouncement(@RequestBody AnnouncementDto body) throws Exception {
return notifyNewAnnouncementService.notify(body);
public void notifyNewAnnouncement(@RequestBody NewAnnouncementCrawledDto body) {
announcementEventService.notifyNewAnnouncementCrawled(body);
}

@PostMapping(value = "/api/subscriptions")
Expand Down

This file was deleted.

31 changes: 24 additions & 7 deletions src/main/java/com/khumu/alimi/data/dto/AnnouncementDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,20 @@
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.List;

/**
* notice crawler๊ฐ€ ์ƒˆ๋กœ์šด ๊ณต์ง€์‚ฌํ•ญ์„ crawlํ•œ ๊ฒฝ์šฐ ๋งค์‹œ์ง€๋ฅผ publish
{
"id": 184,
"title": "์ˆ˜๊ฐ•์‹ ์ฒญ ์•ˆ๋‚ด",
"author_name": "์ปดํ“จํ„ฐ๊ณตํ•™๊ณผ"
"id": 1,
"title": "์†Œ๋ฐฉ์‹œ์„ค ๋ณด์™„๊ณต์‚ฌ ์‹œํ–‰ ์•ˆ๋‚ด ",
"sub_link": "http://ce.khu.ac.kr/index.php?hCode=BOARD&page=view&idx=2330&bo_idx=1",
"date": "2021-08-06 11:15:38",
"author": {
"id": 1,
"author_name": "์ปดํ“จํ„ฐ๊ณตํ•™๊ณผ",
"followed": false
}
*/
@AllArgsConstructor
Expand All @@ -21,10 +28,20 @@
public class AnnouncementDto {
Long id;
String title;
String authorName;
String link;
// follower๋“ค์˜ ID
List<String> followers;
String subLink;
// LocalDateTime date;
AuthorDto author;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public static class AuthorDto {
Long id;
String authorName;
Boolean followed;
}

}


Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.khumu.alimi.data.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

/**
* notice crawler๊ฐ€ ์ƒˆ๋กœ์šด ๊ณต์ง€์‚ฌํ•ญ์„ crawlํ•œ ๊ฒฝ์šฐ ๋งค์‹œ์ง€๋ฅผ publish
{
"announcement": {
"id": 1,
"title": "์†Œ๋ฐฉ์‹œ์„ค ๋ณด์™„๊ณต์‚ฌ ์‹œํ–‰ ์•ˆ๋‚ด ",
"sub_link": "http://ce.khu.ac.kr/index.php?hCode=BOARD&page=view&idx=2330&bo_idx=1",
"date": "2021-08-06 11:15:38",
"author": {
"id": 1,
"author_name": "์ปดํ“จํ„ฐ๊ณตํ•™๊ณผ",
"followed": false
},
"followers": [
"jinsu", "bo314"
]
}
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class NewAnnouncementCrawledDto {
AnnouncementDto announcement;
// ์•Œ๋ฆผ์„ ๋ฐ›์„ ํ›„๋ณด์ธ user๋“ค. ํ•ด๋‹น author์„ follow ์ค‘์ด๋‹ค
List<String> followers;
}


3 changes: 2 additions & 1 deletion src/main/java/com/khumu/alimi/data/dto/NotificationDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ public class NotificationDto {
String content;
String kind;
String recipient;
String reference; // ์ฐธ์กฐ ๋งํฌ
String reference; // ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ๋กœ
String link; // ์‹ค์ œ ๋งํฌ

// @JsonProperty("is_read")// Jackson์ด is๋ผ๋Š” prefix๋ฅผ ์‚ญ์ œํ•ด๋ฒ„๋ฆผ.
// boolean์ธ ๊ฒฝ์šฐ ๋ฐœ์ƒํ•˜๋˜ ๋ฌธ์  ๋ฐ Boolean์œผ๋กœ ๋ณ€๊ฒฝํ•จ์œผ๋กœ์จ ํ•ด๊ฒฐ
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/khumu/alimi/data/entity/PushOptionKind.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ public enum PushOptionKind {
NEW_HOT_ARTICLE,

// ์ž์‹ ์ด ํŒ”๋กœ์šฐ ์ค‘์ธ ์ž‘์„ฑ์ž์˜ ์ƒˆ ๊ณต์ง€์‚ฌํ•ญ์ด ์ž‘์„ฑ๋์„ ๋•Œ
@JsonProperty("new_announcement_of_following_author")
NEW_ANNOUNCEMENT_OF_FOLLOWING_AUTHOR,
@JsonProperty("announcement_crawled")
ANNOUNCEMENT_CRAWLED,

// ํ•™์‚ฌ์ผ์ • ๊ด€๋ จ ์•Œ๋ฆผ
@JsonProperty("haksa_schedule")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import com.khumu.alimi.data.ResourceKind;
import com.khumu.alimi.data.dto.*;
import com.khumu.alimi.data.resource.ArticleResource;
import com.khumu.alimi.external.slack.SlackNotifier;
import com.khumu.alimi.service.NotifyAnnouncementCrawledService;
import com.khumu.alimi.service.notification.ArticleEventService;
import com.khumu.alimi.service.notification.CommentEventService;
import com.khumu.alimi.service.notification.HaksaScheduleEventService;
Expand All @@ -17,10 +19,12 @@
@Slf4j
@RequiredArgsConstructor
public class SqsMessageListener {
final CommentEventService commentEventMessageService;
final NotifyAnnouncementCrawledService announcementEventService;
final ArticleEventService articleEventMessageService;
final CommentEventService commentEventMessageService;
final HaksaScheduleEventService haksaScheduleEventService;
final ObjectMapper objectMapper;
final SlackNotifier slackNotifier;

@SqsListener(value = "${sqs.notificationQueue.name}")
public void receiveMessage(SqsMessageBodyDto body) {
Expand Down Expand Up @@ -56,17 +60,22 @@ public void receiveMessage(SqsMessageBodyDto body) {
}
} break;
case announcement:{
AnnouncementDto announcementDto = objectMapper.readValue(body.getMessage(), AnnouncementDto.class);
NewAnnouncementCrawledDto event = objectMapper.readValue(body.getMessage(), NewAnnouncementCrawledDto.class);
switch (eventKind) {
case create:{
slackNotifier.sendSlack("์ƒˆ๋กœ์šด ๊ณต์ง€์‚ฌํ•ญ์— ๋Œ€ํ•œ ์•Œ๋ฆผ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.", event.getAnnouncement().getTitle());
announcementEventService.notifyNewAnnouncementCrawled(event);
} break;
}
} break;
case haksa_schedule:{
System.out.println("์ƒˆ๋กœ์šด ํ•™์‚ฌ์ผ์ • ์ „๋‹ฌ๋จ!");
HaksaScheduleDto haksaScheduleDto = objectMapper.readValue(body.getMessage(), HaksaScheduleDto.class);
System.out.println(1);
haksaScheduleEventService.createNotificationForHaksaScheduleStarts(haksaScheduleDto);
switch (eventKind) {
case start:{
System.out.println("์ƒˆ๋กœ์šด ํ•™์‚ฌ์ผ์ • ์ „๋‹ฌ๋จ!");
HaksaScheduleDto haksaScheduleDto = objectMapper.readValue(body.getMessage(), HaksaScheduleDto.class);
haksaScheduleEventService.createNotificationForHaksaScheduleStarts(haksaScheduleDto);
} break;
}
} break;
default:
System.out.println("default");
Expand All @@ -75,13 +84,7 @@ public void receiveMessage(SqsMessageBodyDto body) {
} catch (Exception e) {
e.printStackTrace();
log.error("SQS ๋ฉ”์‹œ์ง€ ์ฒ˜๋ฆฌ ๋„์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ!");
slackNotifier.sendSlack("SQS ๋ฉ”์‹œ์ง€ ์ฒ˜๋ฆฌ ๋„์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ!", e.getMessage());
}
// System.out.println("SQS ๋น„์šฉ์„ ์ค„์ด๊ธฐ ์œ„ํ•œ Dummy wait ์‹œ์ž‘");
// try {
// Thread.sleep(1500);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// System.out.println("SQS ๋น„์šฉ์„ ์ค„์ด๊ธฐ ์œ„ํ•œ Dummy wait ๋งˆ๋ฌด๋ฆฌ");
}
}
97 changes: 97 additions & 0 deletions src/main/java/com/khumu/alimi/external/slack/SlackNotifier.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package com.khumu.alimi.external.slack;

import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;

import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Nullable;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.List;

@Component
@RequiredArgsConstructor
@Slf4j
public class SlackNotifier {
@Value("${notification.slack.enabled}")
private boolean slackEnabled;
@Value("${notification.slack.webhook.url}")
private String webhookUrl;
@Value("${notification.slack.channel}")
private String channel;
@Value("${notification.slack.botName}") private String botName;
@Value("${notification.slack.icon.emoji}") private String iconEmoji;
@Value("${notification.slack.icon.url}") private String iconUrl;

@Autowired
Environment env;
@PostConstruct
public void postConstructor(){
// slack = Slack.getInstance();
}
public void sendSlack(String title, String content) {
if (slackEnabled) {
try { // create slack
SlackMessage slackMessage = SlackMessage.builder().attachments(List.of(SlackMessage.Attachment.builder()
.title(title)
.text(content)
.footer("from " + env.getActiveProfiles()[0])
.build()
)).channel(channel).build();
String payload = new Gson().toJson(slackMessage);
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", MediaType.APPLICATION_JSON_VALUE); // send the post request
HttpEntity<String> entity = new HttpEntity<>(payload, headers);
restTemplate.postForEntity(webhookUrl, entity, String.class);
} catch (Exception e) {
log.error("Unhandled Exception occurred while send slack. [Reason] : ", e);
}
}
}

@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class SlackMessage {
@SerializedName("text")
private String text;
@SerializedName("channel")
private String channel;
@SerializedName("username")
private String botName;
@SerializedName("icon_emoji")
private String iconEmoji;
@SerializedName("icon_url")
private String iconUrl;
@SerializedName("attachments")
private List<Attachment> attachments;

@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Attachment {
@SerializedName("title")
private String title;
@SerializedName("text")
private String text;
@SerializedName("color")
@Builder.Default
private String color = "#2222BB";
@SerializedName("footer")
private String footer;
}
}
}
Loading

0 comments on commit 7d21669

Please sign in to comment.