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
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package dgu.newsee.domain.news.controller;

import dgu.newsee.domain.news.dto.NewsDetailDTO;
import dgu.newsee.domain.news.dto.NewsDTO;
import dgu.newsee.domain.news.dto.SavedNewsDTO;
import dgu.newsee.domain.news.service.NewsService;
import dgu.newsee.domain.user.entity.Level;
import dgu.newsee.domain.user.entity.User;
import dgu.newsee.domain.user.repository.UserRepository;
import dgu.newsee.global.exception.NewsException;
import dgu.newsee.global.payload.ApiResponse;
import dgu.newsee.global.payload.ResponseCode;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/news")
public class UserNewsController {

private final NewsService newsService;
private final UserRepository userRepository;

@GetMapping
@Operation(summary = "전체 뉴스 조회 (비회원은 중 레벨)")
public ApiResponse<List<NewsDTO>> getAllNews(Authentication authentication) {
Long userId = extractUserId(authentication);
return newsService.getAllNews(userId, null);
}

@GetMapping("/{newsId}")
@Operation(summary = "뉴스 상세 조회 (비회원은 중 레벨)")
public ApiResponse<NewsDetailDTO> getNewsDetail(@PathVariable Long newsId, Authentication authentication) {
Long userId = extractUserId(authentication);
return newsService.getNewsDetail(newsId, userId, null);
}

@GetMapping("/search")
@Operation(summary = "뉴스 검색 (비회원은 중 레벨)")
public ApiResponse<List<NewsDTO>> searchNews(@RequestParam String keyword, Authentication authentication) {
Long userId = extractUserId(authentication);
return newsService.searchNews(keyword, userId, null);
}

@GetMapping("/user/saved-news")
@Operation(summary = "북마크한 뉴스 목록 조회 (회원만 가능)")
public ApiResponse<List<SavedNewsDTO>> getSavedNews(Authentication authentication) {
Long userId = extractUserId(authentication);
if (userId == null) {
throw new NewsException(ResponseCode.USER_UNAUTHORIZED);
}
return newsService.getSavedNews(userId, null);
}

@PostMapping("/{newsId}")
@Operation(summary = "뉴스 북마크 저장 (회원만 가능)")
public ApiResponse<?> saveNews(@PathVariable Long newsId, Authentication authentication) {
Long userId = extractUserId(authentication);

if (userId == null) {
throw new NewsException(ResponseCode.USER_UNAUTHORIZED);
}

return newsService.saveNews(userId, newsId, null);
}

@DeleteMapping("/{savedNewsId}")
@Operation(summary = "뉴스 북마크 삭제 (회원만 가능)")
public ApiResponse<?> deleteNewsBookmark(
@PathVariable Long savedNewsId,
Authentication authentication
) {
Long userId = extractUserId(authentication);

if (userId == null) {
throw new NewsException(ResponseCode.USER_UNAUTHORIZED);
}

return newsService.deleteNewsBookmark(userId, savedNewsId);
}

private Long extractUserId(Authentication authentication) {
if (authentication == null || authentication.getName() == null) {
return null;
}
return Long.parseLong(authentication.getName());
}
}
68 changes: 68 additions & 0 deletions src/main/java/dgu/newsee/domain/news/converter/NewsConverter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package dgu.newsee.domain.news.converter;

import dgu.newsee.domain.crawlednews.entity.NewsOrigin;
import dgu.newsee.domain.news.dto.NewsDetailDTO;
import dgu.newsee.domain.news.dto.NewsDTO;
import dgu.newsee.domain.news.dto.SavedNewsDTO;
import dgu.newsee.domain.news.entity.SavedNews;
import dgu.newsee.domain.transformednews.entity.NewsTransformed;

import java.util.List;

public class NewsConverter {

public static NewsDTO toNewsDto(NewsOrigin origin, NewsTransformed transformed, boolean isBookmarked) {
return NewsDTO.builder()
.newsId(origin.getId())
.title(transformed.getNews().getTitle()) // transformed 제목
.category(origin.getCategory())
.transformedContent(transformed.getTransformedContent()) // transformed 내용
.source(origin.getSource())
.time(origin.getTime().toString())
.url(origin.getOriginalUrl())
.imageUrl(origin.getImageUrl())
.isBookmarked(isBookmarked)
.build();
}

public static SavedNewsDTO toSavedNewsDto(
SavedNews savedNews,
NewsTransformed transformed
) {
NewsOrigin origin = savedNews.getNewsOrigin();
return SavedNewsDTO.builder()
.savedNewsId(savedNews.getId())
.newsId(origin.getId())
.title(transformed != null ? transformed.getNews().getTitle() : origin.getTitle())
.category(origin.getCategory())
.source(origin.getSource())
.time(origin.getTime().toString())
.url(origin.getOriginalUrl())
.imageUrl(origin.getImageUrl())
.transformedContent(transformed != null ? transformed.getTransformedContent() : null)
.build();
}

public static NewsDetailDTO toNewsDetailDto(
NewsOrigin origin,
NewsTransformed transformed,
String userLevel,
boolean isBookmarked,
List<NewsDetailDTO.KeywordDto> keywords
) {
return NewsDetailDTO.builder()
.newsId(origin.getId())
.title(transformed.getNews().getTitle())
.category(origin.getCategory())
.source(origin.getSource())
.time(origin.getTime().toString())
.url(origin.getOriginalUrl())
.imageUrl(origin.getImageUrl())
.userLevel(userLevel)
.isBookmarked(isBookmarked)
.transformedContent(transformed.getTransformedContent())
.summary(transformed.getSummarized())
.keywords(keywords)
.build();
}
}
28 changes: 28 additions & 0 deletions src/main/java/dgu/newsee/domain/news/dto/NewsDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package dgu.newsee.domain.news.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

@Getter
@AllArgsConstructor
@Builder
public class NewsDTO {
private Long newsId;
private String title;
private String category;
private String source;
private String time;
private String url;
private String imageUrl;
private boolean isBookmarked;
private String transformedContent;

@JsonProperty("isBookmarked")
public boolean getIsBookmarked() {
return isBookmarked;
}

// private String level;
}
42 changes: 42 additions & 0 deletions src/main/java/dgu/newsee/domain/news/dto/NewsDetailDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package dgu.newsee.domain.news.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

import java.util.List;

@Getter
@AllArgsConstructor
@Builder
public class NewsDetailDTO {
private Long newsId;
private String title;
private String category;
private String source;
private String time;
private String url;
private String imageUrl;
private String userLevel;
private boolean isBookmarked;

@JsonProperty("isBookmarked")
public boolean getIsBookmarked() {
return isBookmarked;
}

private String transformedContent;
private String summary;
private List<KeywordDto> keywords;

@Getter
@AllArgsConstructor
@Builder
public static class KeywordDto {
private Long wordId;
private String term;
private String description;
private String source;
}
}
11 changes: 11 additions & 0 deletions src/main/java/dgu/newsee/domain/news/dto/SaveNewsResponseDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package dgu.newsee.domain.news.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class SaveNewsResponseDTO {
private Long userId;
private Long newsId;
}
21 changes: 21 additions & 0 deletions src/main/java/dgu/newsee/domain/news/dto/SavedNewsDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package dgu.newsee.domain.news.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

@Getter
@AllArgsConstructor
@Builder
public class SavedNewsDTO {
private Long savedNewsId;
private Long newsId;
private String title;
private String category;
private String source;
private String time;
private String url;
private String imageUrl;
private String transformedContent;
}
27 changes: 27 additions & 0 deletions src/main/java/dgu/newsee/domain/news/entity/SavedNews.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package dgu.newsee.domain.news.entity;

import dgu.newsee.domain.crawlednews.entity.NewsOrigin;
import dgu.newsee.domain.transformednews.entity.TransformLevel;
import jakarta.persistence.*;
import lombok.*;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
public class SavedNews {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private Long userId;

@Enumerated(EnumType.STRING)
private TransformLevel savedLevel; // 북마크 당시 level로 저장

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "news_origin_id")
private NewsOrigin newsOrigin;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package dgu.newsee.domain.news.repository;

import dgu.newsee.domain.crawlednews.entity.NewsOrigin;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface NewsQueryRepository extends JpaRepository<NewsOrigin, Long> {

// 자동 크롤링만 가져오기
List<NewsOrigin> findByStatus(dgu.newsee.domain.crawlednews.entity.NewsStatus status);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package dgu.newsee.domain.news.repository;

import dgu.newsee.domain.news.entity.SavedNews;
import org.springframework.data.jpa.repository.JpaRepository;
import dgu.newsee.domain.transformednews.entity.TransformLevel;

import java.util.List;
import java.util.Optional;

public interface SavedNewsRepository extends JpaRepository<SavedNews, Long> {
List<SavedNews> findByUserId(Long userId);

boolean existsByUserIdAndNewsOriginIdAndSavedLevel(Long userId, Long newsOriginId, TransformLevel savedLevel);
}
24 changes: 24 additions & 0 deletions src/main/java/dgu/newsee/domain/news/service/NewsService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package dgu.newsee.domain.news.service;

import dgu.newsee.domain.news.dto.NewsDetailDTO;
import dgu.newsee.domain.news.dto.NewsDTO;
import dgu.newsee.domain.news.dto.SavedNewsDTO;
import dgu.newsee.global.payload.ApiResponse;

import java.util.List;

public interface NewsService {

ApiResponse<List<NewsDTO>> getAllNews(Long userId, String levelKor);

ApiResponse<NewsDetailDTO> getNewsDetail(Long newsId, Long userId, String levelKor);

ApiResponse<List<NewsDTO>> searchNews(String keyword, Long userId, String levelKor);

ApiResponse<List<SavedNewsDTO>> getSavedNews(Long userId, String levelKor);

ApiResponse<?> saveNews(Long userId, Long newsId, String levelKor);

ApiResponse<?> deleteNewsBookmark(Long userId, Long savedNewsId);

}
Loading