diff --git a/src/main/java/com/hlab/yanalyst/service/YoutubeVideoIdParser.java b/src/main/java/com/hlab/yanalyst/service/YoutubeVideoIdParser.java new file mode 100644 index 0000000..d6819cc --- /dev/null +++ b/src/main/java/com/hlab/yanalyst/service/YoutubeVideoIdParser.java @@ -0,0 +1,30 @@ +package com.hlab.yanalyst.service; + +import java.util.regex.Pattern; +import java.util.regex.Matcher; + +/** 유튜브 URL 또는 11자리 영상 ID에서 videoId를 추출한다. 실패 시 null. */ +public final class YoutubeVideoIdParser { + + private static final Pattern BARE = Pattern.compile("^[A-Za-z0-9_-]{11}$"); + private static final Pattern[] PATTERNS = { + Pattern.compile("[?&]v=([A-Za-z0-9_-]{11})"), + Pattern.compile("youtu\\.be/([A-Za-z0-9_-]{11})"), + Pattern.compile("/shorts/([A-Za-z0-9_-]{11})"), + Pattern.compile("/embed/([A-Za-z0-9_-]{11})"), + }; + + private YoutubeVideoIdParser() {} + + public static String parse(String input) { + if (input == null) return null; + String s = input.trim(); + if (s.isEmpty()) return null; + if (BARE.matcher(s).matches()) return s; + for (Pattern p : PATTERNS) { + Matcher m = p.matcher(s); + if (m.find()) return m.group(1); + } + return null; + } +} diff --git a/src/test/java/com/hlab/yanalyst/service/YoutubeVideoIdParserTest.java b/src/test/java/com/hlab/yanalyst/service/YoutubeVideoIdParserTest.java new file mode 100644 index 0000000..cbaf2c7 --- /dev/null +++ b/src/test/java/com/hlab/yanalyst/service/YoutubeVideoIdParserTest.java @@ -0,0 +1,43 @@ +package com.hlab.yanalyst.service; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +class YoutubeVideoIdParserTest { + + @Test + void parsesWatchUrl() { + assertEquals("dQw4w9WgXcQ", + YoutubeVideoIdParser.parse("https://www.youtube.com/watch?v=dQw4w9WgXcQ")); + } + + @Test + void parsesWatchUrlWithExtraParams() { + assertEquals("dQw4w9WgXcQ", + YoutubeVideoIdParser.parse("https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=42s&list=ABC")); + } + + @Test + void parsesShortLink() { + assertEquals("dQw4w9WgXcQ", + YoutubeVideoIdParser.parse("https://youtu.be/dQw4w9WgXcQ?si=xyz")); + } + + @Test + void parsesShortsLink() { + assertEquals("abc12345678", + YoutubeVideoIdParser.parse("https://www.youtube.com/shorts/abc12345678")); + } + + @Test + void parsesBareId() { + assertEquals("dQw4w9WgXcQ", YoutubeVideoIdParser.parse("dQw4w9WgXcQ")); + } + + @Test + void returnsNullForGarbage() { + assertNull(YoutubeVideoIdParser.parse("not a youtube link")); + assertNull(YoutubeVideoIdParser.parse("")); + assertNull(YoutubeVideoIdParser.parse(null)); + } +}