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
4 changes: 4 additions & 0 deletions src/main/java/com/devpick/domain/content/entity/Content.java
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ public class Content extends BaseTimeEntity {
@Convert(converter = StackOverflowAnswerListConverter.class)
private List<StackOverflowAnswerDto> topAnswers;

// YouTube 전용 필드 저장 (JSON 문자열: videoId, channelName, duration, viewCount)
@Column(name = "extra", columnDefinition = "jsonb")
private String extra;

@OneToMany(mappedBy = "content", cascade = CascadeType.ALL, orphanRemoval = true)
@Builder.Default
private List<ContentTag> contentTags = new ArrayList<>();
Expand Down
5 changes: 5 additions & 0 deletions src/main/resources/data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,8 @@ WHERE NOT EXISTS (SELECT 1 FROM content_sources WHERE name = 'Medium_watcha');
INSERT INTO content_sources (id, name, url, collect_method, is_active, created_at)
SELECT gen_random_uuid(), 'Kakao_Tech', 'https://tech.kakao.com/feed/', 'rss_crawl', true, NOW()
WHERE NOT EXISTS (SELECT 1 FROM content_sources WHERE name = 'Kakao_Tech');

-- DP-413: YouTube 수집 소스 추가 (AI 레포가 YouTube Data API로 수집 후 POST /internal/contents 전달)
INSERT INTO content_sources (id, name, url, collect_method, is_active, created_at)
SELECT gen_random_uuid(), 'YouTube', 'https://www.youtube.com', 'api', true, NOW()
WHERE NOT EXISTS (SELECT 1 FROM content_sources WHERE name = 'YouTube');
34 changes: 34 additions & 0 deletions src/test/java/com/devpick/domain/content/entity/ContentTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,38 @@ void builder_withFields() {
assertThat(content.getIsOriginalVisible()).isTrue();
assertThat(content.getLicenseType()).isEqualTo("CC BY-SA 4.0");
}

@Test
@DisplayName("extra 필드 미설정 시 null — 기존 콘텐츠 조회에 영향 없음")
void builder_extraDefaultsToNull() {
ContentSource source = ContentSource.builder()
.name("Velog").url("https://v2.velog.io/graphql").collectMethod("graphql").build();

Content content = Content.builder()
.source(source)
.title("Kotlin 코루틴")
.canonicalUrl("https://velog.io/@user/kotlin")
.build();

assertThat(content.getExtra()).isNull();
}

@Test
@DisplayName("extra 필드에 YouTube JSON 문자열을 저장할 수 있다")
void builder_extraWithYouTubeJson() {
ContentSource source = ContentSource.builder()
.name("YouTube").url("https://www.youtube.com").collectMethod("api").build();
String youtubeExtra = "{\"videoId\":\"dQw4w9WgXcQ\",\"channelName\":\"우아한Tech\",\"duration\":312,\"viewCount\":15000}";

Content content = Content.builder()
.source(source)
.title("우아한Tech 스프링 강의")
.canonicalUrl("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
.extra(youtubeExtra)
.build();

assertThat(content.getExtra()).isEqualTo(youtubeExtra);
assertThat(content.getExtra()).contains("videoId");
assertThat(content.getExtra()).contains("channelName");
}
}
Loading