diff --git a/src/main/java/com/commafeed/backend/feeds/FeedUtils.java b/src/main/java/com/commafeed/backend/feeds/FeedUtils.java index fa0e543f..25dede29 100644 --- a/src/main/java/com/commafeed/backend/feeds/FeedUtils.java +++ b/src/main/java/com/commafeed/backend/feeds/FeedUtils.java @@ -1,5 +1,7 @@ package com.commafeed.backend.feeds; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; import java.util.Calendar; import java.util.Collections; import java.util.Date; @@ -14,12 +16,16 @@ import org.jsoup.nodes.Document.OutputSettings; import org.jsoup.nodes.Entities.EscapeMode; import org.jsoup.safety.Whitelist; import org.mozilla.universalchardet.UniversalDetector; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.commafeed.backend.model.FeedEntry; import com.google.api.client.util.Lists; public class FeedUtils { + protected static Logger log = LoggerFactory.getLogger(FeedUtils.class); + public static String truncate(String string, int length) { if (string != null) { string = string.substring(0, Math.min(length, string.length())); @@ -204,4 +210,26 @@ public class FeedUtils { return baseUrl + url; } + + public static String getFaviconUrl(String url, String publicUrl) { + + String defaultIcon = removeTrailingSlash(publicUrl) + + "/images/default_favicon.gif"; + if (StringUtils.isBlank(url)) { + return defaultIcon; + } + + int index = Math.max(url.length(), url.lastIndexOf('?')); + + StringBuilder iconUrl = new StringBuilder( + "https://getfavicon.appspot.com/"); + try { + iconUrl.append(URLEncoder.encode(url.substring(0, index), "UTF-8")); + } catch (UnsupportedEncodingException e) { + // never happens + log.error(e.getMessage(), e); + } + iconUrl.append("?defaulticon=none"); + return iconUrl.toString(); + } } diff --git a/src/main/java/com/commafeed/frontend/model/Entry.java b/src/main/java/com/commafeed/frontend/model/Entry.java index 397cb7d8..2f2ca2d1 100644 --- a/src/main/java/com/commafeed/frontend/model/Entry.java +++ b/src/main/java/com/commafeed/frontend/model/Entry.java @@ -8,6 +8,7 @@ import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; +import com.commafeed.backend.feeds.FeedUtils; import com.commafeed.backend.model.FeedEntry; import com.commafeed.backend.model.FeedEntryStatus; import com.sun.syndication.feed.synd.SyndContentImpl; @@ -22,7 +23,7 @@ import com.wordnik.swagger.annotations.ApiProperty; @ApiClass("Entry details") public class Entry implements Serializable { - public static Entry build(FeedEntryStatus status) { + public static Entry build(FeedEntryStatus status, String publicUrl) { Entry entry = new Entry(); FeedEntry feedEntry = status.getEntry(); @@ -44,6 +45,8 @@ public class Entry implements Serializable { entry.setFeedId(String.valueOf(status.getSubscription().getId())); entry.setFeedUrl(status.getSubscription().getFeed().getUrl()); entry.setFeedLink(status.getSubscription().getFeed().getLink()); + entry.setIconUrl(FeedUtils.getFaviconUrl(status.getSubscription() + .getFeed().getLink(), publicUrl)); return entry; } @@ -98,6 +101,9 @@ public class Entry implements Serializable { @ApiProperty("this entry's website url") private String feedLink; + @ApiProperty(value = "The favicon url to use for this feed") + private String iconUrl; + @ApiProperty("entry url") private String url; @@ -227,4 +233,12 @@ public class Entry implements Serializable { this.author = author; } + public String getIconUrl() { + return iconUrl; + } + + public void setIconUrl(String iconUrl) { + this.iconUrl = iconUrl; + } + } diff --git a/src/main/java/com/commafeed/frontend/model/Subscription.java b/src/main/java/com/commafeed/frontend/model/Subscription.java index 2382d002..d4dbfac2 100644 --- a/src/main/java/com/commafeed/frontend/model/Subscription.java +++ b/src/main/java/com/commafeed/frontend/model/Subscription.java @@ -8,6 +8,7 @@ import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; +import com.commafeed.backend.feeds.FeedUtils; import com.commafeed.backend.model.Feed; import com.commafeed.backend.model.FeedCategory; import com.commafeed.backend.model.FeedSubscription; @@ -21,7 +22,7 @@ import com.wordnik.swagger.annotations.ApiProperty; public class Subscription implements Serializable { public static Subscription build(FeedSubscription subscription, - long unreadCount) { + String publicUrl, long unreadCount) { Date now = Calendar.getInstance().getTime(); FeedCategory category = subscription.getCategory(); Feed feed = subscription.getFeed(); @@ -32,6 +33,7 @@ public class Subscription implements Serializable { sub.setErrorCount(feed.getErrorCount()); sub.setFeedUrl(feed.getUrl()); sub.setFeedLink(feed.getLink()); + sub.setIconUrl(FeedUtils.getFaviconUrl(feed.getLink(), publicUrl)); sub.setLastRefresh(feed.getLastUpdated()); sub.setNextRefresh((feed.getDisabledUntil() != null && feed .getDisabledUntil().before(now)) ? null : feed @@ -66,6 +68,9 @@ public class Subscription implements Serializable { @ApiProperty(value = "this subscription's website url", required = true) private String feedLink; + @ApiProperty(value = "The favicon url to use for this feed") + private String iconUrl; + @ApiProperty(value = "unread count", required = true) private long unread; @@ -152,4 +157,12 @@ public class Subscription implements Serializable { this.nextRefresh = nextRefresh; } + public String getIconUrl() { + return iconUrl; + } + + public void setIconUrl(String iconUrl) { + this.iconUrl = iconUrl; + } + } \ No newline at end of file diff --git a/src/main/java/com/commafeed/frontend/rest/resources/CategoryREST.java b/src/main/java/com/commafeed/frontend/rest/resources/CategoryREST.java index 0bf24f05..3e46881d 100644 --- a/src/main/java/com/commafeed/frontend/rest/resources/CategoryREST.java +++ b/src/main/java/com/commafeed/frontend/rest/resources/CategoryREST.java @@ -70,6 +70,7 @@ public class CategoryREST extends AbstractResourceREST { @ApiParam(value = "date ordering", allowableValues = "asc,desc") @QueryParam("order") @DefaultValue("desc") ReadingOrder order) { Preconditions.checkNotNull(readType); + limit = Math.min(limit, 50); Entries entries = new Entries(); boolean unreadOnly = readType == ReadType.unread; @@ -82,7 +83,9 @@ public class CategoryREST extends AbstractResourceREST { List unreadEntries = feedEntryStatusDAO.findAll( getUser(), unreadOnly, offset, limit, order, true); for (FeedEntryStatus status : unreadEntries) { - entries.getEntries().add(Entry.build(status)); + entries.getEntries().add( + Entry.build(status, applicationSettingsService.get() + .getPublicUrl())); } } else if (STARRED.equals(id)) { @@ -90,7 +93,9 @@ public class CategoryREST extends AbstractResourceREST { List starred = feedEntryStatusDAO.findStarred( getUser(), offset, limit, order, true); for (FeedEntryStatus status : starred) { - entries.getEntries().add(Entry.build(status)); + entries.getEntries().add( + Entry.build(status, applicationSettingsService.get() + .getPublicUrl())); } } else { FeedCategory feedCategory = feedCategoryDAO.findById(getUser(), @@ -102,7 +107,9 @@ public class CategoryREST extends AbstractResourceREST { .findByCategories(childrenCategories, getUser(), unreadOnly, offset, limit, order, true); for (FeedEntryStatus status : unreadEntries) { - entries.getEntries().add(Entry.build(status)); + entries.getEntries().add( + Entry.build(status, applicationSettingsService + .get().getPublicUrl())); } entries.setName(feedCategory.getName()); } @@ -347,7 +354,9 @@ public class CategoryREST extends AbstractResourceREST { .equals(subscription.getCategory().getId(), id))) { Long size = unreadCount.get(subscription.getId()); long unread = size == null ? 0 : size; - Subscription sub = Subscription.build(subscription, unread); + Subscription sub = Subscription + .build(subscription, applicationSettingsService.get() + .getPublicUrl(), unread); category.getFeeds().add(sub); } } diff --git a/src/main/java/com/commafeed/frontend/rest/resources/EntryREST.java b/src/main/java/com/commafeed/frontend/rest/resources/EntryREST.java index a559ab87..adaaace9 100644 --- a/src/main/java/com/commafeed/frontend/rest/resources/EntryREST.java +++ b/src/main/java/com/commafeed/frontend/rest/resources/EntryREST.java @@ -63,6 +63,7 @@ public class EntryREST extends AbstractResourceREST { @ApiParam(value = "offset for paging") @DefaultValue("0") @QueryParam("offset") int offset, @ApiParam(value = "limit for paging") @DefaultValue("-1") @QueryParam("limit") int limit) { keywords = StringUtils.trimToEmpty(keywords); + limit = Math.min(limit, 50); Preconditions.checkArgument(StringUtils.length(keywords) >= 3); Entries entries = new Entries(); @@ -71,7 +72,8 @@ public class EntryREST extends AbstractResourceREST { List entriesStatus = feedEntryStatusDAO .findByKeywords(getUser(), keywords, offset, limit); for (FeedEntryStatus status : entriesStatus) { - list.add(Entry.build(status)); + list.add(Entry.build(status, applicationSettingsService.get() + .getPublicUrl())); } entries.setName("Search for : " + keywords); diff --git a/src/main/java/com/commafeed/frontend/rest/resources/FeedREST.java b/src/main/java/com/commafeed/frontend/rest/resources/FeedREST.java index 20afdf74..22f163f2 100644 --- a/src/main/java/com/commafeed/frontend/rest/resources/FeedREST.java +++ b/src/main/java/com/commafeed/frontend/rest/resources/FeedREST.java @@ -75,6 +75,8 @@ public class FeedREST extends AbstractResourceREST { Preconditions.checkNotNull(id); Preconditions.checkNotNull(readType); + + limit = Math.min(limit, 50); Entries entries = new Entries(); boolean unreadOnly = readType == ReadType.unread; @@ -90,7 +92,9 @@ public class FeedREST extends AbstractResourceREST { .findByFeed(subscription.getFeed(), getUser(), unreadOnly, offset, limit, order, true); for (FeedEntryStatus status : unreadEntries) { - entries.getEntries().add(Entry.build(status)); + entries.getEntries().add( + Entry.build(status, applicationSettingsService.get() + .getPublicUrl())); } } @@ -221,7 +225,9 @@ public class FeedREST extends AbstractResourceREST { if (sub == null) { return Response.status(Status.NOT_FOUND).build(); } - return Response.ok(Subscription.build(sub, 0)).build(); + return Response.ok( + Subscription.build(sub, applicationSettingsService.get() + .getPublicUrl(), 0)).build(); } @POST diff --git a/src/main/webapp/js/directives.js b/src/main/webapp/js/directives.js index 20fef789..639f1a68 100644 --- a/src/main/webapp/js/directives.js +++ b/src/main/webapp/js/directives.js @@ -40,29 +40,7 @@ module.directive('favicon', function() { url : '=' }, replace : true, - template : '', - controller : ['$scope', function($scope) { - - $scope.iconUrl = function() { - var url = $scope.url; - - var current = window.location.href; - var baseUrl = current.substring(0, current.lastIndexOf('#')); - var defaultIcon = baseUrl + 'images/default_favicon.gif'; - if (!url) { - return defaultIcon; - } - - var index = Math.max(url.length, url.lastIndexOf('?')); - - var iconUrl = '//getfavicon.appspot.com/'; - iconUrl += encodeURIComponent(url.substring(0, index)); - iconUrl += '?defaulticon=none'; - return iconUrl; - }; - - - }] + template : '' }; }); diff --git a/src/main/webapp/templates/_category.html b/src/main/webapp/templates/_category.html index d0a18cc0..051a02fe 100644 --- a/src/main/webapp/templates/_category.html +++ b/src/main/webapp/templates/_category.html @@ -30,7 +30,7 @@ - + {{feed.name}} {{feedCountLabel(feed)}} diff --git a/src/main/webapp/templates/feeds.view.html b/src/main/webapp/templates/feeds.view.html index 8416ed8b..c41938c8 100644 --- a/src/main/webapp/templates/feeds.view.html +++ b/src/main/webapp/templates/feeds.view.html @@ -15,7 +15,7 @@ - + {{entry.feedName}}