forked from Archives/Athou_commafeed
import OPML
This commit is contained in:
12
pom.xml
12
pom.xml
@@ -118,6 +118,11 @@
|
|||||||
<artifactId>commons-lang</artifactId>
|
<artifactId>commons-lang</artifactId>
|
||||||
<version>2.6</version>
|
<version>2.6</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-fileupload</groupId>
|
||||||
|
<artifactId>commons-fileupload</artifactId>
|
||||||
|
<version>1.2.2</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.googlecode.lambdaj</groupId>
|
<groupId>com.googlecode.lambdaj</groupId>
|
||||||
<artifactId>lambdaj</artifactId>
|
<artifactId>lambdaj</artifactId>
|
||||||
@@ -134,6 +139,12 @@
|
|||||||
<artifactId>rome</artifactId>
|
<artifactId>rome</artifactId>
|
||||||
<version>1.0.0</version>
|
<version>1.0.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.rometools</groupId>
|
||||||
|
<artifactId>rome-opml</artifactId>
|
||||||
|
<version>1.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.httpcomponents</groupId>
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
<artifactId>httpclient</artifactId>
|
<artifactId>httpclient</artifactId>
|
||||||
@@ -171,7 +182,6 @@
|
|||||||
<artifactId>wicket-cdi</artifactId>
|
<artifactId>wicket-cdi</artifactId>
|
||||||
<version>6.6.0</version>
|
<version>6.6.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<profiles>
|
<profiles>
|
||||||
|
|||||||
@@ -3,15 +3,45 @@ package com.commafeed.backend.dao;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.ejb.Stateless;
|
import javax.ejb.Stateless;
|
||||||
|
import javax.persistence.NoResultException;
|
||||||
|
|
||||||
import com.commafeed.backend.model.FeedCategory;
|
import com.commafeed.backend.model.FeedCategory;
|
||||||
import com.commafeed.backend.model.User;
|
import com.commafeed.backend.model.User;
|
||||||
import com.commafeed.frontend.utils.ModelFactory.MF;
|
import com.commafeed.frontend.utils.ModelFactory.MF;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.uaihebert.model.EasyCriteria;
|
||||||
|
|
||||||
@Stateless
|
@Stateless
|
||||||
|
@SuppressWarnings("serial")
|
||||||
public class FeedCategoryService extends GenericDAO<FeedCategory, Long> {
|
public class FeedCategoryService extends GenericDAO<FeedCategory, Long> {
|
||||||
|
|
||||||
public List<FeedCategory> findAll(User user) {
|
public List<FeedCategory> findAll(User user) {
|
||||||
return findByField(MF.i(MF.p(FeedCategory.class).getUser()), user);
|
return findByField(MF.i(MF.p(FeedCategory.class).getUser()), user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FeedCategory findById(User user, Long id) {
|
||||||
|
EasyCriteria<FeedCategory> criteria = createCriteria();
|
||||||
|
criteria.andEquals(MF.i(proxy().getUser()), user);
|
||||||
|
criteria.andEquals(MF.i(proxy().getId()), id);
|
||||||
|
return Iterables.getFirst(criteria.getResultList(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FeedCategory findByName(User user, String name, FeedCategory parent) {
|
||||||
|
EasyCriteria<FeedCategory> criteria = createCriteria();
|
||||||
|
criteria.andEquals(MF.i(proxy().getUser()), user);
|
||||||
|
criteria.andEquals(MF.i(proxy().getName()), name);
|
||||||
|
if (parent == null) {
|
||||||
|
criteria.andIsNull(MF.i(proxy().getParent()));
|
||||||
|
} else {
|
||||||
|
criteria.andEquals(MF.i(proxy().getParent()), parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
FeedCategory category = null;
|
||||||
|
try {
|
||||||
|
category = criteria.getSingleResult();
|
||||||
|
} catch (NoResultException e) {
|
||||||
|
category = null;
|
||||||
|
}
|
||||||
|
return category;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import com.commafeed.frontend.utils.ModelFactory.MF;
|
|||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
@Stateless
|
@Stateless
|
||||||
|
@SuppressWarnings("serial")
|
||||||
public class FeedEntryService extends GenericDAO<FeedEntry, Long> {
|
public class FeedEntryService extends GenericDAO<FeedEntry, Long> {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -34,6 +35,7 @@ public class FeedEntryService extends GenericDAO<FeedEntry, Long> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
feed.setLastUpdated(Calendar.getInstance().getTime());
|
feed.setLastUpdated(Calendar.getInstance().getTime());
|
||||||
|
feed.setMessage(null);
|
||||||
em.merge(feed);
|
em.merge(feed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import com.uaihebert.factory.EasyCriteriaFactory;
|
|||||||
import com.uaihebert.model.EasyCriteria;
|
import com.uaihebert.model.EasyCriteria;
|
||||||
|
|
||||||
@Stateless
|
@Stateless
|
||||||
|
@SuppressWarnings("serial")
|
||||||
public class FeedEntryStatusService extends GenericDAO<FeedEntryStatus, Long> {
|
public class FeedEntryStatusService extends GenericDAO<FeedEntryStatus, Long> {
|
||||||
|
|
||||||
public FeedEntryStatus getStatus(User user, FeedEntry entry) {
|
public FeedEntryStatus getStatus(User user, FeedEntry entry) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.commafeed.frontend.utils.ModelFactory.MF;
|
|||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
@Stateless
|
@Stateless
|
||||||
|
@SuppressWarnings("serial")
|
||||||
public class FeedService extends GenericDAO<Feed, Long> {
|
public class FeedService extends GenericDAO<Feed, Long> {
|
||||||
|
|
||||||
public Feed findByUrl(String url) {
|
public Feed findByUrl(String url) {
|
||||||
|
|||||||
@@ -8,20 +8,37 @@ import javax.persistence.TypedQuery;
|
|||||||
|
|
||||||
import org.apache.commons.lang.ObjectUtils;
|
import org.apache.commons.lang.ObjectUtils;
|
||||||
|
|
||||||
|
import com.commafeed.backend.model.Feed;
|
||||||
import com.commafeed.backend.model.FeedCategory;
|
import com.commafeed.backend.model.FeedCategory;
|
||||||
import com.commafeed.backend.model.FeedSubscription;
|
import com.commafeed.backend.model.FeedSubscription;
|
||||||
import com.commafeed.backend.model.User;
|
import com.commafeed.backend.model.User;
|
||||||
import com.commafeed.frontend.utils.ModelFactory.MF;
|
import com.commafeed.frontend.utils.ModelFactory.MF;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.uaihebert.factory.EasyCriteriaFactory;
|
import com.uaihebert.factory.EasyCriteriaFactory;
|
||||||
import com.uaihebert.model.EasyCriteria;
|
import com.uaihebert.model.EasyCriteria;
|
||||||
|
|
||||||
@Stateless
|
@Stateless
|
||||||
|
@SuppressWarnings("serial")
|
||||||
public class FeedSubscriptionService extends GenericDAO<FeedSubscription, Long> {
|
public class FeedSubscriptionService extends GenericDAO<FeedSubscription, Long> {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
FeedCategoryService feedCategoryService;
|
FeedCategoryService feedCategoryService;
|
||||||
|
|
||||||
|
public FeedSubscription findById(User user, Long id) {
|
||||||
|
EasyCriteria<FeedSubscription> criteria = createCriteria();
|
||||||
|
criteria.andEquals(MF.i(proxy().getUser()), user);
|
||||||
|
criteria.andEquals(MF.i(proxy().getId()), id);
|
||||||
|
return Iterables.getFirst(criteria.getResultList(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FeedSubscription findByFeed(User user, Feed feed) {
|
||||||
|
EasyCriteria<FeedSubscription> criteria = createCriteria();
|
||||||
|
criteria.andEquals(MF.i(proxy().getUser()), user);
|
||||||
|
criteria.andEquals(MF.i(proxy().getFeed()), feed);
|
||||||
|
return Iterables.getFirst(criteria.getResultList(), null);
|
||||||
|
}
|
||||||
|
|
||||||
public List<FeedSubscription> findAll(User user) {
|
public List<FeedSubscription> findAll(User user) {
|
||||||
return findByField(MF.i(MF.p(FeedCategory.class).getUser()), user);
|
return findByField(MF.i(MF.p(FeedCategory.class).getUser()), user);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,6 +99,10 @@ public abstract class GenericDAO<T, K> implements
|
|||||||
return (Class<T>) type.getRawType();
|
return (Class<T>) type.getRawType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public EasyCriteria<T> createCriteria(){
|
||||||
|
return EasyCriteriaFactory.createQueryCriteria(em, getType());
|
||||||
|
}
|
||||||
|
|
||||||
protected T proxy() {
|
protected T proxy() {
|
||||||
return MF.p(getType());
|
return MF.p(getType());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import com.commafeed.frontend.utils.ModelFactory.MF;
|
|||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
@Stateless
|
@Stateless
|
||||||
|
@SuppressWarnings("serial")
|
||||||
public class UserService extends GenericDAO<User, Long> {
|
public class UserService extends GenericDAO<User, Long> {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import com.uaihebert.factory.EasyCriteriaFactory;
|
|||||||
import com.uaihebert.model.EasyCriteria;
|
import com.uaihebert.model.EasyCriteria;
|
||||||
|
|
||||||
@Stateless
|
@Stateless
|
||||||
|
@SuppressWarnings("serial")
|
||||||
public class UserSettingsService extends GenericDAO<UserSettings, Long> {
|
public class UserSettingsService extends GenericDAO<UserSettings, Long> {
|
||||||
|
|
||||||
public UserSettings findByUser(User user) {
|
public UserSettings findByUser(User user) {
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public class FeedFetcher {
|
|||||||
String content = EntityUtils.toString(entity, "UTF-8");
|
String content = EntityUtils.toString(entity, "UTF-8");
|
||||||
feed = parser.parse(feedUrl, content);
|
feed = parser.parse(feedUrl, content);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
throw new RuntimeException(e);
|
||||||
} finally {
|
} finally {
|
||||||
httpclient.getConnectionManager().shutdown();
|
httpclient.getConnectionManager().shutdown();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,8 +47,9 @@ public class FeedParser {
|
|||||||
feed.getEntries().add(entry);
|
feed.getEntries().add(entry);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new FeedException("Could not parse feed : " + e.getMessage(),
|
throw new FeedException(String.format(
|
||||||
e);
|
"Could not parse feed from %s : %s", feedUrl,
|
||||||
|
e.getMessage()), e);
|
||||||
}
|
}
|
||||||
return feed;
|
return feed;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,26 @@
|
|||||||
package com.commafeed.backend.feeds;
|
package com.commafeed.backend.feeds;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.Calendar;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
import javax.ejb.Schedule;
|
import javax.ejb.Schedule;
|
||||||
import javax.ejb.Singleton;
|
import javax.ejb.Singleton;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.commafeed.backend.dao.FeedEntryService;
|
import com.commafeed.backend.dao.FeedEntryService;
|
||||||
import com.commafeed.backend.dao.FeedService;
|
import com.commafeed.backend.dao.FeedService;
|
||||||
import com.commafeed.backend.model.Feed;
|
import com.commafeed.backend.model.Feed;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class FeedTimer {
|
public class FeedTimer {
|
||||||
|
|
||||||
|
private static Logger log = LoggerFactory.getLogger(FeedTimer.class);
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
FeedService feedService;
|
FeedService feedService;
|
||||||
|
|
||||||
@@ -26,21 +32,32 @@ public class FeedTimer {
|
|||||||
|
|
||||||
@Schedule(hour = "*", minute = "*", persistent = false)
|
@Schedule(hour = "*", minute = "*", persistent = false)
|
||||||
private void timeout() {
|
private void timeout() {
|
||||||
List<Feed> feeds = feedService.findAll();
|
Map<String, Feed> feeds = Maps.newHashMap();
|
||||||
|
for (Feed feed : feedService.findAll()) {
|
||||||
List<Future<Feed>> futures = Lists.newArrayList();
|
feeds.put(feed.getUrl(), feed);
|
||||||
for (Feed feed : feeds) {
|
|
||||||
Future<Feed> future = fetcher.fetch(feed.getUrl());
|
|
||||||
futures.add(future);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Future<Feed> future : futures) {
|
Map<String, Future<Feed>> futures = Maps.newHashMap();
|
||||||
|
for (Feed feed : feeds.values()) {
|
||||||
|
Future<Feed> future = fetcher.fetch(feed.getUrl());
|
||||||
|
futures.put(feed.getUrl(), future);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String key : futures.keySet()) {
|
||||||
|
Future<Feed> future = futures.get(key);
|
||||||
try {
|
try {
|
||||||
Feed feed = future.get();
|
Feed feed = future.get();
|
||||||
feedEntryService
|
feedEntryService
|
||||||
.updateEntries(feed.getUrl(), feed.getEntries());
|
.updateEntries(feed.getUrl(), feed.getEntries());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
log.info(
|
||||||
|
"Unable to refresh feed " + key + " : "
|
||||||
|
+ e.getMessage(), e);
|
||||||
|
|
||||||
|
Feed feed = feeds.get(key);
|
||||||
|
feed.setLastUpdated(Calendar.getInstance().getTime());
|
||||||
|
feed.setMessage("Unable to refresh feed: " + e.getMessage());
|
||||||
|
feedService.update(feed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
85
src/main/java/com/commafeed/backend/feeds/OPMLImporter.java
Normal file
85
src/main/java/com/commafeed/backend/feeds/OPMLImporter.java
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
package com.commafeed.backend.feeds;
|
||||||
|
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.ejb.Singleton;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
|
||||||
|
import com.commafeed.backend.dao.FeedCategoryService;
|
||||||
|
import com.commafeed.backend.dao.FeedService;
|
||||||
|
import com.commafeed.backend.dao.FeedSubscriptionService;
|
||||||
|
import com.commafeed.backend.model.Feed;
|
||||||
|
import com.commafeed.backend.model.FeedCategory;
|
||||||
|
import com.commafeed.backend.model.FeedSubscription;
|
||||||
|
import com.commafeed.backend.model.User;
|
||||||
|
import com.sun.syndication.feed.opml.Opml;
|
||||||
|
import com.sun.syndication.feed.opml.Outline;
|
||||||
|
import com.sun.syndication.io.FeedException;
|
||||||
|
import com.sun.syndication.io.WireFeedInput;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class OPMLImporter {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
FeedService feedService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
FeedSubscriptionService feedSubscriptionService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
FeedCategoryService feedCategoryService;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void importOpml(User user, String xml) throws FeedException {
|
||||||
|
|
||||||
|
WireFeedInput input = new WireFeedInput();
|
||||||
|
Opml feed = (Opml) input.build(new StringReader(xml));
|
||||||
|
List<Outline> outlines = (List<Outline>) feed.getOutlines();
|
||||||
|
for (Outline outline : outlines) {
|
||||||
|
handleOutline(user, outline, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private void handleOutline(User user, Outline outline, FeedCategory parent) {
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(outline.getType())) {
|
||||||
|
FeedCategory category = feedCategoryService.findByName(user,
|
||||||
|
outline.getText(), parent);
|
||||||
|
if (category == null) {
|
||||||
|
category = new FeedCategory();
|
||||||
|
category.setName(outline.getText());
|
||||||
|
category.setParent(parent);
|
||||||
|
category.setUser(user);
|
||||||
|
feedCategoryService.save(category);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Outline> children = outline.getChildren();
|
||||||
|
for (Outline child : children) {
|
||||||
|
handleOutline(user, child, category);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Feed feed = feedService.findByUrl(outline.getXmlUrl());
|
||||||
|
if (feed == null) {
|
||||||
|
feed = new Feed();
|
||||||
|
feed.setUrl(outline.getXmlUrl());
|
||||||
|
feedService.save(feed);
|
||||||
|
}
|
||||||
|
|
||||||
|
FeedSubscription sub = feedSubscriptionService.findByFeed(user,
|
||||||
|
feed);
|
||||||
|
if (sub == null) {
|
||||||
|
sub = new FeedSubscription();
|
||||||
|
sub.setFeed(feed);
|
||||||
|
sub.setUser(user);
|
||||||
|
feedSubscriptionService.save(sub);
|
||||||
|
}
|
||||||
|
sub.setCategory(parent);
|
||||||
|
sub.setTitle(outline.getText());
|
||||||
|
feedSubscriptionService.update(sub);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,6 +24,9 @@ public class Feed extends AbstractModel {
|
|||||||
@Temporal(TemporalType.TIMESTAMP)
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
private Date lastUpdated;
|
private Date lastUpdated;
|
||||||
|
|
||||||
|
@Column(length = 1024)
|
||||||
|
private String message;
|
||||||
|
|
||||||
@OneToMany(mappedBy = "feed", fetch = FetchType.EAGER)
|
@OneToMany(mappedBy = "feed", fetch = FetchType.EAGER)
|
||||||
private Set<FeedEntry> entries = Sets.newHashSet();
|
private Set<FeedEntry> entries = Sets.newHashSet();
|
||||||
|
|
||||||
@@ -59,4 +62,12 @@ public class Feed extends AbstractModel {
|
|||||||
this.entries = entries;
|
this.entries = entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class FeedEntry extends AbstractModel {
|
|||||||
@ManyToOne
|
@ManyToOne
|
||||||
private Feed feed;
|
private Feed feed;
|
||||||
|
|
||||||
@Column(length = 256)
|
@Column(length = 2048)
|
||||||
private String title;
|
private String title;
|
||||||
|
|
||||||
@Lob
|
@Lob
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
public class Category implements Serializable {
|
public class Category implements Serializable {
|
||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
public class Entries implements Serializable {
|
public class Entries implements Serializable {
|
||||||
private String name;
|
private String name;
|
||||||
private List<Entry> entries = Lists.newArrayList();
|
private List<Entry> entries = Lists.newArrayList();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.commafeed.frontend.model;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
public class Entry implements Serializable {
|
public class Entry implements Serializable {
|
||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.commafeed.frontend.model;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
public class Settings implements Serializable {
|
public class Settings implements Serializable {
|
||||||
|
|
||||||
private String readingMode;
|
private String readingMode;
|
||||||
|
|||||||
@@ -2,10 +2,12 @@ package com.commafeed.frontend.model;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
public class Subscription implements Serializable {
|
public class Subscription implements Serializable {
|
||||||
|
|
||||||
private Long id;
|
private Long id;
|
||||||
private String name;
|
private String name;
|
||||||
|
private String message;
|
||||||
private int unread;
|
private int unread;
|
||||||
|
|
||||||
public Long getId() {
|
public Long getId() {
|
||||||
@@ -32,4 +34,12 @@ public class Subscription implements Serializable {
|
|||||||
this.unread = unread;
|
this.unread = unread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ package com.commafeed.frontend.model;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
public class SubscriptionRequest implements Serializable {
|
public class SubscriptionRequest implements Serializable {
|
||||||
|
|
||||||
private String url;
|
private String url;
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
<script src="vendor/angular/angular.min.js"></script>
|
<script src="vendor/angular/angular.min.js"></script>
|
||||||
<script src="vendor/angular/angular-resource.min.js"></script>
|
<script src="vendor/angular/angular-resource.min.js"></script>
|
||||||
<script src="vendor/angular/angular-sanitize.min.js"></script>
|
<script src="vendor/angular/angular-sanitize.min.js"></script>
|
||||||
|
<script src="vendor/angular-upload/ng-upload.min.js"></script>
|
||||||
<script src="vendor/angular-ui/angular-ui.min.js"></script>
|
<script src="vendor/angular-ui/angular-ui.min.js"></script>
|
||||||
<script src="vendor/angular-ui-bootstrap/ui-bootstrap-tpls-0.2.0.min.js"></script>
|
<script src="vendor/angular-ui-bootstrap/ui-bootstrap-tpls-0.2.0.min.js"></script>
|
||||||
<script src="js/main.js"></script>
|
<script src="js/main.js"></script>
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import com.commafeed.backend.dao.FeedService;
|
|||||||
import com.commafeed.backend.dao.FeedSubscriptionService;
|
import com.commafeed.backend.dao.FeedSubscriptionService;
|
||||||
import com.commafeed.backend.dao.UserService;
|
import com.commafeed.backend.dao.UserService;
|
||||||
import com.commafeed.backend.dao.UserSettingsService;
|
import com.commafeed.backend.dao.UserSettingsService;
|
||||||
|
import com.commafeed.backend.feeds.OPMLImporter;
|
||||||
import com.commafeed.backend.model.User;
|
import com.commafeed.backend.model.User;
|
||||||
import com.commafeed.frontend.CommaFeedApplication;
|
import com.commafeed.frontend.CommaFeedApplication;
|
||||||
import com.commafeed.frontend.CommaFeedSession;
|
import com.commafeed.frontend.CommaFeedSession;
|
||||||
@@ -59,6 +60,9 @@ public abstract class AbstractREST {
|
|||||||
@Inject
|
@Inject
|
||||||
UserSettingsService userSettingsService;
|
UserSettingsService userSettingsService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
OPMLImporter opmlImporter;
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
CommaFeedApplication app = CommaFeedApplication.get();
|
CommaFeedApplication app = CommaFeedApplication.get();
|
||||||
|
|||||||
@@ -33,14 +33,14 @@ public class EntriesREST extends AbstractREST {
|
|||||||
boolean unreadOnly = "unread".equals(readType);
|
boolean unreadOnly = "unread".equals(readType);
|
||||||
|
|
||||||
if ("feed".equals(type)) {
|
if ("feed".equals(type)) {
|
||||||
FeedSubscription subscription = feedSubscriptionService
|
FeedSubscription subscription = feedSubscriptionService.findById(
|
||||||
.findById(Long.valueOf(id));
|
getUser(), Long.valueOf(id));
|
||||||
entries.setName(subscription.getTitle());
|
entries.setName(subscription.getTitle());
|
||||||
entries.getEntries().addAll(buildEntries(subscription, unreadOnly));
|
entries.getEntries().addAll(buildEntries(subscription, unreadOnly));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
FeedCategory feedCategory = "all".equals(id) ? null
|
FeedCategory feedCategory = "all".equals(id) ? null
|
||||||
: feedCategoryService.findById(Long.valueOf(id));
|
: feedCategoryService.findById(getUser(), Long.valueOf(id));
|
||||||
Collection<FeedSubscription> subscriptions = "all".equals(id) ? feedSubscriptionService
|
Collection<FeedSubscription> subscriptions = "all".equals(id) ? feedSubscriptionService
|
||||||
.findAll(getUser()) : feedSubscriptionService
|
.findAll(getUser()) : feedSubscriptionService
|
||||||
.findWithCategory(getUser(), feedCategory);
|
.findWithCategory(getUser(), feedCategory);
|
||||||
|
|||||||
@@ -2,11 +2,18 @@ package com.commafeed.frontend.rest.resources;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
import javax.ws.rs.POST;
|
import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.QueryParam;
|
import javax.ws.rs.QueryParam;
|
||||||
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
|
import org.apache.commons.fileupload.FileItem;
|
||||||
|
import org.apache.commons.fileupload.FileItemFactory;
|
||||||
|
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
|
||||||
|
import org.apache.commons.fileupload.servlet.ServletFileUpload;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.lang.ObjectUtils;
|
import org.apache.commons.lang.ObjectUtils;
|
||||||
|
|
||||||
import com.commafeed.backend.model.Feed;
|
import com.commafeed.backend.model.Feed;
|
||||||
@@ -50,6 +57,27 @@ public class SubscriptionsREST extends AbstractREST {
|
|||||||
feedSubscriptionService.deleteById(subscriptionId);
|
feedSubscriptionService.deleteById(subscriptionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("import")
|
||||||
|
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void importOpml() {
|
||||||
|
try {
|
||||||
|
FileItemFactory factory = new DiskFileItemFactory(1000000, null);
|
||||||
|
ServletFileUpload upload = new ServletFileUpload(factory);
|
||||||
|
List<FileItem> items = upload.parseRequest(request);
|
||||||
|
for (FileItem item : items) {
|
||||||
|
if ("file".equals(item.getFieldName())) {
|
||||||
|
opmlImporter.importOpml(getUser(),
|
||||||
|
IOUtils.toString(item.getInputStream(), "UTF-8"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
public Category getSubscriptions() {
|
public Category getSubscriptions() {
|
||||||
Category root = new Category();
|
Category root = new Category();
|
||||||
@@ -65,6 +93,7 @@ public class SubscriptionsREST extends AbstractREST {
|
|||||||
Subscription sub = new Subscription();
|
Subscription sub = new Subscription();
|
||||||
sub.setId(subscription.getId());
|
sub.setId(subscription.getId());
|
||||||
sub.setName(subscription.getTitle());
|
sub.setName(subscription.getTitle());
|
||||||
|
sub.setMessage(subscription.getFeed().getMessage());
|
||||||
int size = feedEntryService.getUnreadEntries(
|
int size = feedEntryService.getUnreadEntries(
|
||||||
subscription.getFeed(), getUser()).size();
|
subscription.getFeed(), getUser()).size();
|
||||||
sub.setUnread(size);
|
sub.setUnread(size);
|
||||||
@@ -88,6 +117,7 @@ public class SubscriptionsREST extends AbstractREST {
|
|||||||
Subscription sub = new Subscription();
|
Subscription sub = new Subscription();
|
||||||
sub.setId(subscription.getId());
|
sub.setId(subscription.getId());
|
||||||
sub.setName(subscription.getTitle());
|
sub.setName(subscription.getTitle());
|
||||||
|
sub.setMessage(subscription.getFeed().getMessage());
|
||||||
int size = feedEntryService.getUnreadEntries(
|
int size = feedEntryService.getUnreadEntries(
|
||||||
subscription.getFeed(), getUser()).size();
|
subscription.getFeed(), getUser()).size();
|
||||||
sub.setUnread(size);
|
sub.setUnread(size);
|
||||||
|
|||||||
@@ -1,5 +1,16 @@
|
|||||||
<div>
|
<div>
|
||||||
<button class="btn" ng-click="open()">Subscribe</button>
|
<div class="btn-group">
|
||||||
|
<button class="btn" ng-click="open()">Subscribe</button>
|
||||||
|
<button class="btn dropdown-toggle" data-toggle="dropdown">
|
||||||
|
<span class="caret"></span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li>
|
||||||
|
<a ng-click="open()">Subscribe</a>
|
||||||
|
</li>
|
||||||
|
<li><a ng-click="openImport()">Import</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
<div modal="isOpen" close="close()" options="opts">
|
<div modal="isOpen" close="close()" options="opts">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<button type="button" class="close" ng-click="close()">×</button>
|
<button type="button" class="close" ng-click="close()">×</button>
|
||||||
@@ -32,4 +43,27 @@
|
|||||||
<button class="btn btn-primary ok" ng-click="save()">Save</button>
|
<button class="btn btn-primary ok" ng-click="save()">Save</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div modal="isOpenImport" close="closeImport()" options="opts">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" ng-click="closeImport()">×</button>
|
||||||
|
<h4>Import</h4>
|
||||||
|
</div>
|
||||||
|
<form ng-upload class="form-horizontal" action="rest/subscriptions/import">
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="control-group">
|
||||||
|
<span>Select the subscriptions.xml file you got from the zip file on google.com/takeout</span>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label class="control-label">XML File</label>
|
||||||
|
<div class="controls">
|
||||||
|
<input type="file" name="file"></input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-warning cancel" ng-click="closeImport()">Cancel</button>
|
||||||
|
<button class="btn btn-primary ok" type="submit" upload-submit="uploadComplete(contents, completed)">Import</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -44,6 +44,9 @@ module.controller('CategoryTreeCtrl', function($scope, $routeParams, $location,
|
|||||||
|
|
||||||
$scope.formatFeedName = function(feed) {
|
$scope.formatFeedName = function(feed) {
|
||||||
var label = feed.name;
|
var label = feed.name;
|
||||||
|
if (feed.message) {
|
||||||
|
label = "!!! " + label;
|
||||||
|
}
|
||||||
if (feed.unread > 0) {
|
if (feed.unread > 0) {
|
||||||
label = label + " (" + feed.unread + ")";
|
label = label + " (" + feed.unread + ")";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
var module = angular.module('commafeed.directives', []);
|
var module = angular.module('commafeed.directives', []);
|
||||||
|
|
||||||
module.directive('subscribe', function() {
|
module.directive('subscribe', function(SubscriptionService) {
|
||||||
return {
|
return {
|
||||||
scope : {},
|
scope : {},
|
||||||
restrict : 'E',
|
restrict : 'E',
|
||||||
@@ -13,6 +13,7 @@ module.directive('subscribe', function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.isOpen = false;
|
$scope.isOpen = false;
|
||||||
|
$scope.isOpenImport = false;
|
||||||
$scope.sub = {};
|
$scope.sub = {};
|
||||||
|
|
||||||
$scope.SubscriptionService = SubscriptionService;
|
$scope.SubscriptionService = SubscriptionService;
|
||||||
@@ -31,6 +32,19 @@ module.directive('subscribe', function() {
|
|||||||
$scope.close();
|
$scope.close();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.openImport = function() {
|
||||||
|
$scope.isOpenImport = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.closeImport = function() {
|
||||||
|
$scope.isOpenImport = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.uploadComplete = function(contents, completed) {
|
||||||
|
SubscriptionService.init();
|
||||||
|
$scope.closeImport();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
var app = angular
|
var app = angular.module('commafeed', [ 'ui', 'ui.bootstrap',
|
||||||
.module('commafeed', [ 'ui', 'ui.bootstrap', 'commafeed.directives',
|
'commafeed.directives', 'commafeed.controllers', 'commafeed.services',
|
||||||
'commafeed.controllers', 'commafeed.services', 'ngSanitize' ]);
|
'ngSanitize', 'ngUpload' ]);
|
||||||
|
|
||||||
app.config([ '$routeProvider', function($routeProvider) {
|
app.config([ '$routeProvider', function($routeProvider) {
|
||||||
$routeProvider.when('/feeds/view/:_type/:_id', {
|
$routeProvider.when('/feeds/view/:_type/:_id', {
|
||||||
|
|||||||
1
src/main/webapp/vendor/angular-upload/ng-upload.min.js
vendored
Normal file
1
src/main/webapp/vendor/angular-upload/ng-upload.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
angular.module("ngUpload",[]).directive("uploadSubmit",["$parse",function(t){return{restrict:"AC",link:function(a,e,n){var o={};o.enableControls=n.uploadOptionsEnableControls;var i=e.parents("form[ng-upload]")||e.parents("form.ng-upload"),r=t(n.uploadSubmit);if(!angular.isFunction(r)){var l="The expression on the ngUpload directive does not point to a valid function.";throw l+"\n"}e.bind("click",function(t){t.preventDefault=!0;var n=angular.element("<iframe id='upload_iframe' name='upload_iframe' border='0' width='0' height='0' style='width: 0px; height: 0px; border: none; display: none' />");n.bind("load",function(){var t=n.contents().find("body").text();a.$apply(function(){r(a,{content:t,completed:!0})}),""!==t&&setTimeout(function(){n.remove()},250),e.attr("disabled",null),e.attr("title","Click to start upload.")}),i.parent().append(n),a.$apply(function(){r(a,{content:"Please wait...",completed:!1})});var l=!0;o.enableControls||(e.attr("disabled","disabled"),l=!1),e.attr("title",(l?"[ENABLED]: ":"[DISABLED]: ")+"Uploading, please wait..."),i.submit()}).attr("title","Click to start upload.")}}}]).directive("ngUpload",["$parse",function(){return{restrict:"AC",link:function(t,a){a.attr("target","upload_iframe"),a.attr("method","post"),a.attr("action",a.attr("action")+"?_t="+(new Date).getTime()),a.attr("enctype","multipart/form-data"),a.attr("encoding","multipart/form-data")}}}]);
|
||||||
Reference in New Issue
Block a user