diff --git a/src/main/java/com/commafeed/backend/feed/FeedParser.java b/src/main/java/com/commafeed/backend/feed/FeedParser.java
index 4b483af4..e34ec66d 100644
--- a/src/main/java/com/commafeed/backend/feed/FeedParser.java
+++ b/src/main/java/com/commafeed/backend/feed/FeedParser.java
@@ -10,9 +10,7 @@ import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.inject.Singleton;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-
+import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.jdom2.Element;
import org.jdom2.Namespace;
@@ -22,6 +20,13 @@ import com.commafeed.backend.model.Feed;
import com.commafeed.backend.model.FeedEntry;
import com.commafeed.backend.model.FeedEntryContent;
import com.google.common.collect.Iterables;
+import com.rometools.modules.mediarss.MediaEntryModule;
+import com.rometools.modules.mediarss.MediaModule;
+import com.rometools.modules.mediarss.types.MediaGroup;
+import com.rometools.modules.mediarss.types.Metadata;
+import com.rometools.modules.mediarss.types.Thumbnail;
+import com.rometools.rome.feed.synd.SyndCategory;
+import com.rometools.rome.feed.synd.SyndContent;
import com.rometools.rome.feed.synd.SyndEnclosure;
import com.rometools.rome.feed.synd.SyndEntry;
import com.rometools.rome.feed.synd.SyndFeed;
@@ -30,6 +35,10 @@ import com.rometools.rome.feed.synd.SyndLinkImpl;
import com.rometools.rome.io.FeedException;
import com.rometools.rome.io.SyndFeedInput;
+import lombok.Data;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
@Slf4j
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
@Singleton
@@ -86,15 +95,28 @@ public class FeedParser {
FeedEntryContent content = new FeedEntryContent();
content.setContent(getContent(item));
- content.setCategories(FeedUtils.truncate(
- item.getCategories().stream().map(c -> c.getName()).collect(Collectors.joining(", ")), 4096));
+ content.setCategories(FeedUtils
+ .truncate(item.getCategories().stream().map(SyndCategory::getName).collect(Collectors.joining(", ")), 4096));
content.setTitle(getTitle(item));
content.setAuthor(StringUtils.trimToNull(item.getAuthor()));
+
SyndEnclosure enclosure = Iterables.getFirst(item.getEnclosures(), null);
if (enclosure != null) {
content.setEnclosureUrl(FeedUtils.truncate(enclosure.getUrl(), 2048));
content.setEnclosureType(enclosure.getType());
}
+
+ MediaEntryModule module = (MediaEntryModule) item.getModule(MediaModule.URI);
+ if (module != null) {
+ Media media = getMedia(module);
+ if (media != null) {
+ content.setMediaDescription(media.getDescription());
+ content.setMediaThumbnailUrl(FeedUtils.truncate(media.getThumbnailUrl(), 2048));
+ content.setMediaThumbnailWidth(media.getThumbnailWidth());
+ content.setMediaThumbnailHeight(media.getThumbnailHeight());
+ }
+ }
+
entry.setContent(content);
entries.add(entry);
@@ -166,7 +188,7 @@ public class FeedParser {
if (item.getContents().isEmpty()) {
content = item.getDescription() == null ? null : item.getDescription().getValue();
} else {
- content = item.getContents().stream().map(c -> c.getValue()).collect(Collectors.joining(System.lineSeparator()));
+ content = item.getContents().stream().map(SyndContent::getValue).collect(Collectors.joining(System.lineSeparator()));
}
return StringUtils.trimToNull(content);
}
@@ -184,6 +206,41 @@ public class FeedParser {
return StringUtils.trimToNull(title);
}
+ private Media getMedia(MediaEntryModule module) {
+ Media media = getMedia(module.getMetadata());
+ if (media == null && ArrayUtils.isNotEmpty(module.getMediaGroups())) {
+ MediaGroup group = module.getMediaGroups()[0];
+ media = getMedia(group.getMetadata());
+ }
+
+ return media;
+ }
+
+ private Media getMedia(Metadata metadata) {
+ if (metadata == null) {
+ return null;
+ }
+
+ Media media = new Media();
+ media.setDescription(metadata.getDescription());
+
+ if (ArrayUtils.isNotEmpty(metadata.getThumbnail())) {
+ Thumbnail thumbnail = metadata.getThumbnail()[0];
+ media.setThumbnailWidth(thumbnail.getWidth());
+ media.setThumbnailHeight(thumbnail.getHeight());
+
+ if (thumbnail.getUrl() != null) {
+ media.setThumbnailUrl(thumbnail.getUrl().toString());
+ }
+ }
+
+ if (media.isEmpty()) {
+ return null;
+ }
+
+ return media;
+ }
+
private String findHub(SyndFeed feed) {
for (SyndLink l : feed.getLinks()) {
if ("hub".equalsIgnoreCase(l.getRel())) {
@@ -204,4 +261,16 @@ public class FeedParser {
return null;
}
+ @Data
+ private static class Media {
+ private String description;
+ private String thumbnailUrl;
+ private Integer thumbnailWidth;
+ private Integer thumbnailHeight;
+
+ public boolean isEmpty() {
+ return description == null && thumbnailUrl == null;
+ }
+ }
+
}
diff --git a/src/main/java/com/commafeed/backend/model/FeedEntryContent.java b/src/main/java/com/commafeed/backend/model/FeedEntryContent.java
index 34ae0c69..3f005c4d 100644
--- a/src/main/java/com/commafeed/backend/model/FeedEntryContent.java
+++ b/src/main/java/com/commafeed/backend/model/FeedEntryContent.java
@@ -43,6 +43,17 @@ public class FeedEntryContent extends AbstractModel {
@Column(length = 255)
private String enclosureType;
+ @Lob
+ @Column(length = Integer.MAX_VALUE)
+ @Type(type = "org.hibernate.type.TextType")
+ private String mediaDescription;
+
+ @Column(length = 2048)
+ private String mediaThumbnailUrl;
+
+ private Integer mediaThumbnailWidth;
+ private Integer mediaThumbnailHeight;
+
@Column(length = 4096)
private String categories;
diff --git a/src/main/java/com/commafeed/backend/service/FeedEntryContentService.java b/src/main/java/com/commafeed/backend/service/FeedEntryContentService.java
index d7bc7fdf..738c8134 100644
--- a/src/main/java/com/commafeed/backend/service/FeedEntryContentService.java
+++ b/src/main/java/com/commafeed/backend/service/FeedEntryContentService.java
@@ -3,8 +3,6 @@ package com.commafeed.backend.service;
import javax.inject.Inject;
import javax.inject.Singleton;
-import lombok.RequiredArgsConstructor;
-
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
@@ -12,6 +10,8 @@ import com.commafeed.backend.dao.FeedEntryContentDAO;
import com.commafeed.backend.feed.FeedUtils;
import com.commafeed.backend.model.FeedEntryContent;
+import lombok.RequiredArgsConstructor;
+
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
@Singleton
public class FeedEntryContentService {
@@ -35,6 +35,7 @@ public class FeedEntryContentService {
content.setAuthor(FeedUtils.truncate(FeedUtils.handleContent(content.getAuthor(), baseUrl, true), 128));
content.setTitle(FeedUtils.truncate(FeedUtils.handleContent(content.getTitle(), baseUrl, true), 2048));
content.setContent(FeedUtils.handleContent(content.getContent(), baseUrl, false));
+ content.setMediaDescription(FeedUtils.handleContent(content.getMediaDescription(), baseUrl, false));
result = content;
feedEntryContentDAO.saveOrUpdate(result);
} else {
diff --git a/src/main/java/com/commafeed/frontend/model/Entry.java b/src/main/java/com/commafeed/frontend/model/Entry.java
index 91e87325..2c631d8d 100644
--- a/src/main/java/com/commafeed/frontend/model/Entry.java
+++ b/src/main/java/com/commafeed/frontend/model/Entry.java
@@ -12,6 +12,7 @@ import com.commafeed.backend.feed.FeedUtils;
import com.commafeed.backend.model.FeedEntry;
import com.commafeed.backend.model.FeedEntryContent;
import com.commafeed.backend.model.FeedEntryStatus;
+import com.commafeed.backend.model.FeedEntryTag;
import com.commafeed.backend.model.FeedSubscription;
import com.rometools.rome.feed.synd.SyndContent;
import com.rometools.rome.feed.synd.SyndContentImpl;
@@ -49,17 +50,25 @@ public class Entry implements Serializable {
entry.setFeedUrl(sub.getFeed().getUrl());
entry.setFeedLink(sub.getFeed().getLink());
entry.setIconUrl(FeedUtils.getFaviconUrl(sub, publicUrl));
- entry.setTags(status.getTags().stream().map(t -> t.getName()).collect(Collectors.toList()));
+ entry.setTags(status.getTags().stream().map(FeedEntryTag::getName).collect(Collectors.toList()));
if (content != null) {
entry.setRtl(FeedUtils.isRTL(feedEntry));
entry.setTitle(content.getTitle());
entry.setContent(proxyImages ? FeedUtils.proxyImages(content.getContent(), publicUrl) : content.getContent());
entry.setAuthor(content.getAuthor());
+
entry.setEnclosureType(content.getEnclosureType());
entry.setEnclosureUrl(proxyImages && StringUtils.contains(content.getEnclosureType(), "image")
? FeedUtils.proxyImage(content.getEnclosureUrl(), publicUrl)
: content.getEnclosureUrl());
+
+ entry.setMediaDescription(content.getMediaDescription());
+ entry.setMediaThumbnailUrl(
+ proxyImages ? FeedUtils.proxyImage(content.getMediaThumbnailUrl(), publicUrl) : content.getMediaThumbnailUrl());
+ entry.setMediaThumbnailWidth(content.getMediaThumbnailWidth());
+ entry.setMediaThumbnailHeight(content.getMediaThumbnailHeight());
+
entry.setCategories(content.getCategories());
}
@@ -116,6 +125,18 @@ public class Entry implements Serializable {
@ApiModelProperty(value = "entry enclosure mime type, if any")
private String enclosureType;
+ @ApiModelProperty(value = "entry media description, if any")
+ private String mediaDescription;
+
+ @ApiModelProperty(value = "entry media thumbnail url, if any")
+ private String mediaThumbnailUrl;
+
+ @ApiModelProperty(value = "entry media thumbnail width, if any")
+ private Integer mediaThumbnailWidth;
+
+ @ApiModelProperty(value = "entry media thumbnail height, if any")
+ private Integer mediaThumbnailHeight;
+
@ApiModelProperty(value = "entry publication date", dataType = "number", required = true)
private Date date;
diff --git a/src/main/resources/changelogs/db.changelog-2.6.xml b/src/main/resources/changelogs/db.changelog-2.6.xml
index 62149c04..23a0a002 100644
--- a/src/main/resources/changelogs/db.changelog-2.6.xml
+++ b/src/main/resources/changelogs/db.changelog-2.6.xml
@@ -8,4 +8,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+