mirror of
https://github.com/jlengrand/OpenGraphKt.git
synced 2026-03-10 08:31:23 +00:00
Adding unsupported types
This commit is contained in:
@@ -36,7 +36,17 @@ data class OpenGraphData(
|
||||
// Optional type-specific metadata
|
||||
val article: OpenGraphArticle?,
|
||||
val profile: OpenGraphProfile?,
|
||||
val book: OpenGraphBook?
|
||||
val book: OpenGraphBook?,
|
||||
|
||||
// Music types
|
||||
val musicSong: OpenGraphMusicSong?,
|
||||
val musicAlbum: OpenGraphMusicAlbum?,
|
||||
val musicPlaylist: OpenGraphMusicPlaylist?,
|
||||
val musicRadioStation: OpenGraphMusicRadioStation?,
|
||||
|
||||
// Video types
|
||||
val videoMovie: OpenGraphVideoMovie?,
|
||||
val videoEpisode: OpenGraphVideoEpisode?
|
||||
) {
|
||||
/**
|
||||
* Checks if this Open Graph data contains the minimum required properties.
|
||||
@@ -63,9 +73,6 @@ data class OpenGraphData(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an Open Graph image.
|
||||
*/
|
||||
data class OpenGraphImage(
|
||||
val url: String?,
|
||||
val secureUrl: String?,
|
||||
@@ -75,9 +82,6 @@ data class OpenGraphImage(
|
||||
val alt: String?
|
||||
)
|
||||
|
||||
/**
|
||||
* Represents an Open Graph video.
|
||||
*/
|
||||
data class OpenGraphVideo(
|
||||
val url: String?,
|
||||
val secureUrl: String?,
|
||||
@@ -87,9 +91,6 @@ data class OpenGraphVideo(
|
||||
val duration: Int?
|
||||
)
|
||||
|
||||
/**
|
||||
* Represents an Open Graph audio.
|
||||
*/
|
||||
data class OpenGraphAudio(
|
||||
val url: String?,
|
||||
val secureUrl: String?,
|
||||
@@ -97,7 +98,8 @@ data class OpenGraphAudio(
|
||||
)
|
||||
|
||||
/**
|
||||
* Represents Open Graph article metadata.
|
||||
* * video.tv_show - same as video.movie
|
||||
* * video.other - same as video.movie
|
||||
*/
|
||||
data class OpenGraphArticle(
|
||||
val publishedTime: String?,
|
||||
@@ -108,9 +110,6 @@ data class OpenGraphArticle(
|
||||
val tags: List<String>
|
||||
)
|
||||
|
||||
/**
|
||||
* Represents Open Graph profile metadata.
|
||||
*/
|
||||
data class OpenGraphProfile(
|
||||
val firstName: String?,
|
||||
val lastName: String?,
|
||||
@@ -118,9 +117,6 @@ data class OpenGraphProfile(
|
||||
val gender: String?
|
||||
)
|
||||
|
||||
/**
|
||||
* Represents Open Graph book metadata.
|
||||
*/
|
||||
data class OpenGraphBook(
|
||||
val authors: List<String>,
|
||||
val isbn: String?,
|
||||
@@ -128,6 +124,48 @@ data class OpenGraphBook(
|
||||
val tags: List<String>
|
||||
)
|
||||
|
||||
data class OpenGraphMusicSong(
|
||||
val duration: Int?,
|
||||
val album: String?,
|
||||
val albumDisc: Int?,
|
||||
val albumTrack: Int?,
|
||||
val musician: List<String>
|
||||
)
|
||||
|
||||
data class OpenGraphMusicAlbum(
|
||||
val songs: List<String>,
|
||||
val musician: List<String>,
|
||||
val releaseDate: String?
|
||||
)
|
||||
|
||||
data class OpenGraphMusicPlaylist(
|
||||
val songs: List<String>,
|
||||
val creator: String?
|
||||
)
|
||||
|
||||
data class OpenGraphMusicRadioStation(
|
||||
val creator: String?
|
||||
)
|
||||
|
||||
data class OpenGraphVideoMovie(
|
||||
val actors: List<String>,
|
||||
val director: List<String>,
|
||||
val writer: List<String>,
|
||||
val duration: Int?,
|
||||
val releaseDate: String?,
|
||||
val tags: List<String>
|
||||
)
|
||||
|
||||
data class OpenGraphVideoEpisode(
|
||||
val actors: List<String>,
|
||||
val director: List<String>,
|
||||
val writer: List<String>,
|
||||
val duration: Int?,
|
||||
val releaseDate: String?,
|
||||
val tags: List<String>,
|
||||
val series: String?
|
||||
)
|
||||
|
||||
/**
|
||||
* A comprehensive parser for Open Graph protocol tags.
|
||||
*
|
||||
@@ -243,6 +281,16 @@ class OpenGraphParser {
|
||||
// Build book-specific properties if the type is "book"
|
||||
val book = if (type == "book") buildBook(groupedTags) else null
|
||||
|
||||
// Build music-specific properties based on type
|
||||
val musicSong = if (type == "music.song") buildMusicSong(groupedTags) else null
|
||||
val musicAlbum = if (type == "music.album") buildMusicAlbum(groupedTags) else null
|
||||
val musicPlaylist = if (type == "music.playlist") buildMusicPlaylist(groupedTags) else null
|
||||
val musicRadioStation = if (type == "music.radio_station") buildMusicRadioStation(groupedTags) else null
|
||||
|
||||
// Build video-specific properties based on type
|
||||
val videoMovie = if (type == "video.movie" || type == "video.tv_show" || type == "video.other") buildVideoMovie(groupedTags) else null
|
||||
val videoEpisode = if (type == "video.episode") buildVideoEpisode(groupedTags) else null
|
||||
|
||||
return OpenGraphData(
|
||||
tags = tags,
|
||||
title = title,
|
||||
@@ -258,7 +306,13 @@ class OpenGraphParser {
|
||||
audios = audios,
|
||||
article = article,
|
||||
profile = profile,
|
||||
book = book
|
||||
book = book,
|
||||
musicSong = musicSong,
|
||||
musicAlbum = musicAlbum,
|
||||
musicPlaylist = musicPlaylist,
|
||||
musicRadioStation = musicRadioStation,
|
||||
videoMovie = videoMovie,
|
||||
videoEpisode = videoEpisode
|
||||
)
|
||||
}
|
||||
|
||||
@@ -503,4 +557,160 @@ class OpenGraphParser {
|
||||
tags = tags
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an OpenGraphMusicSong object from music.song-related tags.
|
||||
*
|
||||
* @param groupedTags The map of grouped OpenGraphTag objects
|
||||
* @return An OpenGraphMusicSong object, or null if no music.song tags are found
|
||||
*/
|
||||
private fun buildMusicSong(groupedTags: Map<String, List<OpenGraphTag>>): OpenGraphMusicSong? {
|
||||
val musicTags = groupedTags.getOrDefault("music", emptyList())
|
||||
|
||||
if (musicTags.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
|
||||
val duration = musicTags.firstOrNull { it.property == "music:duration" }?.content?.toIntOrNull()
|
||||
val album = musicTags.firstOrNull { it.property == "music:album" }?.content
|
||||
val albumDisc = musicTags.firstOrNull { it.property == "music:album:disc" }?.content?.toIntOrNull()
|
||||
val albumTrack = musicTags.firstOrNull { it.property == "music:album:track" }?.content?.toIntOrNull()
|
||||
val musicians = musicTags.filter { it.property == "music:musician" }.map { it.content }
|
||||
|
||||
return OpenGraphMusicSong(
|
||||
duration = duration,
|
||||
album = album,
|
||||
albumDisc = albumDisc,
|
||||
albumTrack = albumTrack,
|
||||
musician = musicians
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an OpenGraphMusicAlbum object from music.album-related tags.
|
||||
*
|
||||
* @param groupedTags The map of grouped OpenGraphTag objects
|
||||
* @return An OpenGraphMusicAlbum object, or null if no music.album tags are found
|
||||
*/
|
||||
private fun buildMusicAlbum(groupedTags: Map<String, List<OpenGraphTag>>): OpenGraphMusicAlbum? {
|
||||
val musicTags = groupedTags.getOrDefault("music", emptyList())
|
||||
|
||||
if (musicTags.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
|
||||
val songs = musicTags.filter { it.property == "music:song" }.map { it.content }
|
||||
val musicians = musicTags.filter { it.property == "music:musician" }.map { it.content }
|
||||
val releaseDate = musicTags.firstOrNull { it.property == "music:release_date" }?.content
|
||||
|
||||
return OpenGraphMusicAlbum(
|
||||
songs = songs,
|
||||
musician = musicians,
|
||||
releaseDate = releaseDate
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an OpenGraphMusicPlaylist object from music.playlist-related tags.
|
||||
*
|
||||
* @param groupedTags The map of grouped OpenGraphTag objects
|
||||
* @return An OpenGraphMusicPlaylist object, or null if no music.playlist tags are found
|
||||
*/
|
||||
private fun buildMusicPlaylist(groupedTags: Map<String, List<OpenGraphTag>>): OpenGraphMusicPlaylist? {
|
||||
val musicTags = groupedTags.getOrDefault("music", emptyList())
|
||||
|
||||
if (musicTags.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
|
||||
val songs = musicTags.filter { it.property == "music:song" }.map { it.content }
|
||||
val creator = musicTags.firstOrNull { it.property == "music:creator" }?.content
|
||||
|
||||
return OpenGraphMusicPlaylist(
|
||||
songs = songs,
|
||||
creator = creator
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an OpenGraphMusicRadioStation object from music.radio_station-related tags.
|
||||
*
|
||||
* @param groupedTags The map of grouped OpenGraphTag objects
|
||||
* @return An OpenGraphMusicRadioStation object, or null if no music.radio_station tags are found
|
||||
*/
|
||||
private fun buildMusicRadioStation(groupedTags: Map<String, List<OpenGraphTag>>): OpenGraphMusicRadioStation? {
|
||||
val musicTags = groupedTags.getOrDefault("music", emptyList())
|
||||
|
||||
if (musicTags.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
|
||||
val creator = musicTags.firstOrNull { it.property == "music:creator" }?.content
|
||||
|
||||
return OpenGraphMusicRadioStation(
|
||||
creator = creator
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an OpenGraphVideoMovie object from video.movie-related tags.
|
||||
*
|
||||
* @param groupedTags The map of grouped OpenGraphTag objects
|
||||
* @return An OpenGraphVideoMovie object, or null if no video.movie tags are found
|
||||
*/
|
||||
private fun buildVideoMovie(groupedTags: Map<String, List<OpenGraphTag>>): OpenGraphVideoMovie? {
|
||||
val videoTags = groupedTags.getOrDefault("video", emptyList())
|
||||
|
||||
if (videoTags.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
|
||||
val actors = videoTags.filter { it.property == "video:actor" }.map { it.content }
|
||||
val directors = videoTags.filter { it.property == "video:director" }.map { it.content }
|
||||
val writers = videoTags.filter { it.property == "video:writer" }.map { it.content }
|
||||
val duration = videoTags.firstOrNull { it.property == "video:duration" }?.content?.toIntOrNull()
|
||||
val releaseDate = videoTags.firstOrNull { it.property == "video:release_date" }?.content
|
||||
val tags = videoTags.filter { it.property == "video:tag" }.map { it.content }
|
||||
|
||||
return OpenGraphVideoMovie(
|
||||
actors = actors,
|
||||
director = directors,
|
||||
writer = writers,
|
||||
duration = duration,
|
||||
releaseDate = releaseDate,
|
||||
tags = tags
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an OpenGraphVideoEpisode object from video.episode-related tags.
|
||||
*
|
||||
* @param groupedTags The map of grouped OpenGraphTag objects
|
||||
* @return An OpenGraphVideoEpisode object, or null if no video.episode tags are found
|
||||
*/
|
||||
private fun buildVideoEpisode(groupedTags: Map<String, List<OpenGraphTag>>): OpenGraphVideoEpisode? {
|
||||
val videoTags = groupedTags.getOrDefault("video", emptyList())
|
||||
|
||||
if (videoTags.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
|
||||
val actors = videoTags.filter { it.property == "video:actor" }.map { it.content }
|
||||
val directors = videoTags.filter { it.property == "video:director" }.map { it.content }
|
||||
val writers = videoTags.filter { it.property == "video:writer" }.map { it.content }
|
||||
val duration = videoTags.firstOrNull { it.property == "video:duration" }?.content?.toIntOrNull()
|
||||
val releaseDate = videoTags.firstOrNull { it.property == "video:release_date" }?.content
|
||||
val tags = videoTags.filter { it.property == "video:tag" }.map { it.content }
|
||||
val series = videoTags.firstOrNull { it.property == "video:series" }?.content
|
||||
|
||||
return OpenGraphVideoEpisode(
|
||||
actors = actors,
|
||||
director = directors,
|
||||
writer = writers,
|
||||
duration = duration,
|
||||
releaseDate = releaseDate,
|
||||
tags = tags,
|
||||
series = series
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,6 +180,15 @@ class OpenGraphParserTest {
|
||||
assertEquals(2, openGraphData.localeAlternate.size)
|
||||
assertTrue(openGraphData.localeAlternate.contains("fr_FR"))
|
||||
assertTrue(openGraphData.localeAlternate.contains("es_ES"))
|
||||
|
||||
// Verify video.movie properties
|
||||
assertNotNull(openGraphData.videoMovie)
|
||||
assertEquals(0, openGraphData.videoMovie.actors.size)
|
||||
assertEquals(0, openGraphData.videoMovie.director.size)
|
||||
assertEquals(0, openGraphData.videoMovie.writer.size)
|
||||
assertEquals(null, openGraphData.videoMovie.duration)
|
||||
assertEquals(null, openGraphData.videoMovie.releaseDate)
|
||||
assertEquals(0, openGraphData.videoMovie.tags.size)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -296,4 +305,60 @@ class OpenGraphParserTest {
|
||||
assertTrue(openGraphData.article.authors.contains("John Doe"))
|
||||
assertTrue(openGraphData.article.authors.contains("Jane Smith"))
|
||||
}
|
||||
|
||||
// Sample HTML with video.movie-specific tags
|
||||
private val videoMovieHtml = """
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Video Movie Example</title>
|
||||
<meta property="og:title" content="The Matrix" />
|
||||
<meta property="og:type" content="video.movie" />
|
||||
<meta property="og:url" content="https://example.com/movies/the-matrix" />
|
||||
<meta property="og:image" content="https://example.com/matrix-poster.jpg" />
|
||||
<meta property="og:description" content="A sci-fi action movie" />
|
||||
<meta property="og:video:actor" content="Keanu Reeves" />
|
||||
<meta property="og:video:actor" content="Laurence Fishburne" />
|
||||
<meta property="og:video:director" content="Lana Wachowski" />
|
||||
<meta property="og:video:director" content="Lilly Wachowski" />
|
||||
<meta property="og:video:writer" content="Lana Wachowski" />
|
||||
<meta property="og:video:writer" content="Lilly Wachowski" />
|
||||
<meta property="og:video:duration" content="136" />
|
||||
<meta property="og:video:release_date" content="1999-03-31" />
|
||||
<meta property="og:video:tag" content="sci-fi" />
|
||||
<meta property="og:video:tag" content="action" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>The Matrix</h1>
|
||||
</body>
|
||||
</html>
|
||||
""".trimIndent()
|
||||
|
||||
@Test
|
||||
fun `test parse with video movie-specific tags`() {
|
||||
val openGraphData = parser.parse(videoMovieHtml)
|
||||
|
||||
// Verify basic properties
|
||||
assertEquals("The Matrix", openGraphData.title)
|
||||
assertEquals("video.movie", openGraphData.type)
|
||||
assertEquals("https://example.com/movies/the-matrix", openGraphData.url)
|
||||
assertEquals("A sci-fi action movie", openGraphData.description)
|
||||
|
||||
// Verify video.movie-specific properties
|
||||
assertNotNull(openGraphData.videoMovie)
|
||||
assertEquals(2, openGraphData.videoMovie.actors.size)
|
||||
assertTrue(openGraphData.videoMovie.actors.contains("Keanu Reeves"))
|
||||
assertTrue(openGraphData.videoMovie.actors.contains("Laurence Fishburne"))
|
||||
assertEquals(2, openGraphData.videoMovie.director.size)
|
||||
assertTrue(openGraphData.videoMovie.director.contains("Lana Wachowski"))
|
||||
assertTrue(openGraphData.videoMovie.director.contains("Lilly Wachowski"))
|
||||
assertEquals(2, openGraphData.videoMovie.writer.size)
|
||||
assertTrue(openGraphData.videoMovie.writer.contains("Lana Wachowski"))
|
||||
assertTrue(openGraphData.videoMovie.writer.contains("Lilly Wachowski"))
|
||||
assertEquals(136, openGraphData.videoMovie.duration)
|
||||
assertEquals("1999-03-31", openGraphData.videoMovie.releaseDate)
|
||||
assertEquals(2, openGraphData.videoMovie.tags.size)
|
||||
assertTrue(openGraphData.videoMovie.tags.contains("sci-fi"))
|
||||
assertTrue(openGraphData.videoMovie.tags.contains("action"))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user