Store RSS feeds in a separate dedicated blog

A fake LocalAuthor is created for this new blog and stored in the feed's metadata.
This commit is contained in:
Torsten Grote
2017-04-10 12:15:48 -03:00
parent 9755cd9ab4
commit c7ff1ba974
10 changed files with 245 additions and 116 deletions

View File

@@ -179,7 +179,6 @@ public class FeedFragment extends BaseFragment implements
case R.id.action_rss_feeds_import: case R.id.action_rss_feeds_import:
Intent i2 = Intent i2 =
new Intent(getActivity(), RssFeedImportActivity.class); new Intent(getActivity(), RssFeedImportActivity.class);
i2.putExtra(GROUP_ID, personalBlog.getId().getBytes());
startActivity(i2); startActivity(i2);
return true; return true;
case R.id.action_rss_feeds_manage: case R.id.action_rss_feeds_manage:

View File

@@ -1,7 +1,6 @@
package org.briarproject.briar.android.blog; package org.briarproject.briar.android.blog;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.text.Editable; import android.text.Editable;
@@ -15,7 +14,6 @@ import android.widget.ProgressBar;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent; import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity; import org.briarproject.briar.android.activity.BriarActivity;
@@ -44,9 +42,6 @@ public class RssFeedImportActivity extends BriarActivity {
@IoExecutor @IoExecutor
Executor ioExecutor; Executor ioExecutor;
// Fields that are accessed from background threads must be volatile
private volatile GroupId groupId = null;
@Inject @Inject
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
volatile FeedManager feedManager; volatile FeedManager feedManager;
@@ -55,12 +50,6 @@ public class RssFeedImportActivity extends BriarActivity {
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
// GroupId from Intent
Intent i = getIntent();
byte[] b = i.getByteArrayExtra(GROUP_ID);
if (b == null) throw new IllegalStateException("No Group in intent.");
groupId = new GroupId(b);
setContentView(R.layout.activity_rss_feed_import); setContentView(R.layout.activity_rss_feed_import);
urlInput = (EditText) findViewById(R.id.urlInput); urlInput = (EditText) findViewById(R.id.urlInput);
@@ -128,7 +117,7 @@ public class RssFeedImportActivity extends BriarActivity {
@Override @Override
public void run() { public void run() {
try { try {
feedManager.addFeed(url, groupId); feedManager.addFeed(url);
feedImported(); feedImported();
} catch (DbException | IOException e) { } catch (DbException | IOException e) {
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))

View File

@@ -87,7 +87,6 @@ public class RssFeedManageActivity extends BriarActivity
return true; return true;
case R.id.action_rss_feeds_import: case R.id.action_rss_feeds_import:
Intent i = new Intent(this, RssFeedImportActivity.class); Intent i = new Intent(this, RssFeedImportActivity.class);
i.putExtra(GROUP_ID, groupId.getBytes());
startActivity(i); startActivity(i);
return true; return true;
default: default:

View File

@@ -1,39 +1,32 @@
package org.briarproject.briar.api.feed; package org.briarproject.briar.api.feed;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfEntry;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.briar.api.blog.Blog;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_BLOG_GROUP_ID;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_ADDED;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_AUTHOR;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_DESC;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_LAST_ENTRY;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_TITLE;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_UPDATED;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_URL;
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
public class Feed { public class Feed {
private final String url; private final String url;
private final GroupId blogId; private final Blog blog;
private final LocalAuthor localAuthor;
@Nullable @Nullable
private final String title, description, author; private final String title, description, author;
private final long added, updated, lastEntryTime; private final long added, updated, lastEntryTime;
public Feed(String url, GroupId blogId, @Nullable String title, public Feed(String url, Blog blog, LocalAuthor localAuthor,
@Nullable String description, @Nullable String author, @Nullable String title, @Nullable String description,
long added, long updated, long lastEntryTime) { @Nullable String author, long added, long updated,
long lastEntryTime) {
this.url = url; this.url = url;
this.blogId = blogId; this.blog = blog;
this.localAuthor = localAuthor;
this.title = title; this.title = title;
this.description = description; this.description = description;
this.author = author; this.author = author;
@@ -42,13 +35,14 @@ public class Feed {
this.lastEntryTime = lastEntryTime; this.lastEntryTime = lastEntryTime;
} }
public Feed(String url, GroupId blogId, @Nullable String title, public Feed(String url, Blog blog, LocalAuthor localAuthor,
@Nullable String description, @Nullable String author, long added) { @Nullable String title, @Nullable String description,
this(url, blogId, title, description, author, added, 0L, 0L); @Nullable String author, long added) {
this(url, blog, localAuthor, title, description, author, added, 0L, 0L);
} }
public Feed(String url, GroupId blogId, long added) { public Feed(String url, Blog blog, LocalAuthor localAuthor, long added) {
this(url, blogId, null, null, null, added, 0L, 0L); this(url, blog, localAuthor, null, null, null, added, 0L, 0L);
} }
public String getUrl() { public String getUrl() {
@@ -56,34 +50,15 @@ public class Feed {
} }
public GroupId getBlogId() { public GroupId getBlogId() {
return blogId; return blog.getId();
} }
public BdfDictionary toBdfDictionary() { public Blog getBlog() {
BdfDictionary d = BdfDictionary.of( return blog;
new BdfEntry(KEY_FEED_URL, url),
new BdfEntry(KEY_BLOG_GROUP_ID, blogId.getBytes()),
new BdfEntry(KEY_FEED_ADDED, added),
new BdfEntry(KEY_FEED_UPDATED, updated),
new BdfEntry(KEY_FEED_LAST_ENTRY, lastEntryTime)
);
if (title != null) d.put(KEY_FEED_TITLE, title);
if (description != null) d.put(KEY_FEED_DESC, description);
if (author != null) d.put(KEY_FEED_AUTHOR, author);
return d;
} }
public static Feed from(BdfDictionary d) throws FormatException { public LocalAuthor getLocalAuthor() {
String url = d.getString(KEY_FEED_URL); return localAuthor;
GroupId blogId = new GroupId(d.getRaw(KEY_BLOG_GROUP_ID));
String title = d.getOptionalString(KEY_FEED_TITLE);
String desc = d.getOptionalString(KEY_FEED_DESC);
String author = d.getOptionalString(KEY_FEED_AUTHOR);
long added = d.getLong(KEY_FEED_ADDED, 0L);
long updated = d.getLong(KEY_FEED_UPDATED, 0L);
long lastEntryTime = d.getLong(KEY_FEED_LAST_ENTRY, 0L);
return new Feed(url, blogId, title, desc, author, added, updated,
lastEntryTime);
} }
@Nullable @Nullable
@@ -118,13 +93,13 @@ public class Feed {
if (this == o) return true; if (this == o) return true;
if (o instanceof Feed) { if (o instanceof Feed) {
Feed f = (Feed) o; Feed f = (Feed) o;
return url.equals(f.url) && blogId.equals(f.getBlogId()) && return url.equals(f.url) && blog.equals(f.blog) &&
equalsWithNull(title, f.getTitle()) && equalsWithNull(title, f.title) &&
equalsWithNull(description, f.getDescription()) && equalsWithNull(description, f.description) &&
equalsWithNull(author, f.getAuthor()) && equalsWithNull(author, f.author) &&
added == f.getAdded() && added == f.added &&
updated == f.getUpdated() && updated == f.updated &&
lastEntryTime == f.getLastEntryTime(); lastEntryTime == f.lastEntryTime;
} }
return false; return false;
} }
@@ -134,4 +109,5 @@ public class Feed {
if (a == null || b == null) return false; if (a == null || b == null) return false;
return a.equals(b); return a.equals(b);
} }
} }

View File

@@ -18,7 +18,9 @@ public interface FeedConstants {
// group metadata keys // group metadata keys
String KEY_FEEDS = "feeds"; String KEY_FEEDS = "feeds";
String KEY_FEED_URL = "feedURL"; String KEY_FEED_URL = "feedURL";
String KEY_BLOG_GROUP_ID = "blogGroupId"; String KEY_BLOG_TITLE = "blogTitle";
String KEY_PUBLIC_KEY = "publicKey";
String KEY_PRIVATE_KEY = "privateKey";
String KEY_FEED_TITLE = "feedTitle"; String KEY_FEED_TITLE = "feedTitle";
String KEY_FEED_DESC = "feedDesc"; String KEY_FEED_DESC = "feedDesc";
String KEY_FEED_AUTHOR = "feedAuthor"; String KEY_FEED_AUTHOR = "feedAuthor";

View File

@@ -3,7 +3,6 @@ package org.briarproject.briar.api.feed;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.ClientId; import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.bramble.api.sync.GroupId;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
@@ -17,9 +16,9 @@ public interface FeedManager {
ClientId CLIENT_ID = new ClientId("org.briarproject.briar.feed"); ClientId CLIENT_ID = new ClientId("org.briarproject.briar.feed");
/** /**
* Adds an RSS feed. * Adds an RSS feed as a new dedicated blog.
*/ */
void addFeed(String url, GroupId g) throws DbException, IOException; void addFeed(String url) throws DbException, IOException;
/** /**
* Removes an RSS feed. * Removes an RSS feed.

View File

@@ -0,0 +1,34 @@
package org.briarproject.briar.feed;
import com.rometools.rome.feed.synd.SyndFeed;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.briar.api.feed.Feed;
interface FeedFactory {
/**
* Create a new feed based on the feed url
* and the metadata of an existing {@link SyndFeed}.
*/
Feed createFeed(String url, SyndFeed feed);
/**
* Creates a new updated feed, based on the given existing feed,
* new metadata from the given {@link SyndFeed}
* and the time of the last feed entry.
*/
Feed createFeed(Feed feed, SyndFeed f, long lastEntryTime);
/**
* De-serializes a {@link BdfDictionary} into a {@link Feed}.
*/
Feed createFeed(BdfDictionary d) throws FormatException;
/**
* Serializes a {@link Feed} into a {@link BdfDictionary}.
*/
BdfDictionary feedToBdfDictionary(Feed feed);
}

View File

@@ -0,0 +1,111 @@
package org.briarproject.briar.feed;
import com.rometools.rome.feed.synd.SyndFeed;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfEntry;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.briar.api.blog.Blog;
import org.briarproject.briar.api.blog.BlogFactory;
import org.briarproject.briar.api.feed.Feed;
import javax.inject.Inject;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_BLOG_TITLE;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_ADDED;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_AUTHOR;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_DESC;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_LAST_ENTRY;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_TITLE;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_UPDATED;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEED_URL;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_PRIVATE_KEY;
import static org.briarproject.briar.api.feed.FeedConstants.KEY_PUBLIC_KEY;
class FeedFactoryImpl implements FeedFactory {
private final CryptoComponent cryptoComponent;
private final AuthorFactory authorFactory;
private final BlogFactory blogFactory;
private final Clock clock;
@Inject
FeedFactoryImpl(CryptoComponent cryptoComponent,
AuthorFactory authorFactory, BlogFactory blogFactory, Clock clock) {
this.cryptoComponent = cryptoComponent;
this.authorFactory = authorFactory;
this.blogFactory = blogFactory;
this.clock = clock;
}
@Override
public Feed createFeed(String url, SyndFeed syndFeed) {
if (syndFeed.getTitle() == null) syndFeed.setTitle("RSS feed");
KeyPair keyPair = cryptoComponent.generateSignatureKeyPair();
LocalAuthor localAuthor = authorFactory
.createLocalAuthor(syndFeed.getTitle(),
keyPair.getPublic().getEncoded(),
keyPair.getPrivate().getEncoded());
Blog blog = blogFactory.createBlog(localAuthor);
long added = clock.currentTimeMillis();
return new Feed(url, blog, localAuthor, added);
}
@Override
public Feed createFeed(Feed feed, SyndFeed f, long lastEntryTime) {
long updated = clock.currentTimeMillis();
return new Feed(feed.getUrl(), feed.getBlog(), feed.getLocalAuthor(),
f.getTitle(), f.getDescription(), f.getAuthor(),
feed.getAdded(), updated, lastEntryTime);
}
@Override
public Feed createFeed(BdfDictionary d) throws FormatException {
String url = d.getString(KEY_FEED_URL);
String blogTitle = d.getString(KEY_BLOG_TITLE);
byte[] publicKey = d.getRaw(KEY_PUBLIC_KEY);
byte[] privateKey = d.getRaw(KEY_PRIVATE_KEY);
LocalAuthor localAuthor = authorFactory
.createLocalAuthor(blogTitle, publicKey, privateKey);
Blog blog = blogFactory.createBlog(localAuthor);
String title = d.getOptionalString(KEY_FEED_TITLE);
String desc = d.getOptionalString(KEY_FEED_DESC);
String author = d.getOptionalString(KEY_FEED_AUTHOR);
long added = d.getLong(KEY_FEED_ADDED, 0L);
long updated = d.getLong(KEY_FEED_UPDATED, 0L);
long lastEntryTime = d.getLong(KEY_FEED_LAST_ENTRY, 0L);
return new Feed(url, blog, localAuthor, title, desc, author, added,
updated, lastEntryTime);
}
@Override
public BdfDictionary feedToBdfDictionary(Feed feed) {
BdfDictionary d = BdfDictionary.of(
new BdfEntry(KEY_FEED_URL, feed.getUrl()),
new BdfEntry(KEY_BLOG_TITLE, feed.getLocalAuthor().getName()),
new BdfEntry(KEY_PUBLIC_KEY,
feed.getLocalAuthor().getPublicKey()),
new BdfEntry(KEY_PRIVATE_KEY,
feed.getLocalAuthor().getPrivateKey()),
new BdfEntry(KEY_FEED_ADDED, feed.getAdded()),
new BdfEntry(KEY_FEED_UPDATED, feed.getUpdated()),
new BdfEntry(KEY_FEED_LAST_ENTRY, feed.getLastEntryTime())
);
if (feed.getTitle() != null) d.put(KEY_FEED_TITLE, feed.getTitle());
if (feed.getDescription() != null)
d.put(KEY_FEED_DESC, feed.getDescription());
if (feed.getAuthor() != null) d.put(KEY_FEED_AUTHOR, feed.getAuthor());
return d;
}
}

View File

@@ -18,7 +18,6 @@ import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener; import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@@ -88,9 +87,9 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
private final DatabaseComponent db; private final DatabaseComponent db;
private final ContactGroupFactory contactGroupFactory; private final ContactGroupFactory contactGroupFactory;
private final ClientHelper clientHelper; private final ClientHelper clientHelper;
private final IdentityManager identityManager;
private final BlogManager blogManager; private final BlogManager blogManager;
private final BlogPostFactory blogPostFactory; private final BlogPostFactory blogPostFactory;
private final FeedFactory feedFactory;
private final SocketFactory torSocketFactory; private final SocketFactory torSocketFactory;
private final Clock clock; private final Clock clock;
private final AtomicBoolean fetcherStarted = new AtomicBoolean(false); private final AtomicBoolean fetcherStarted = new AtomicBoolean(false);
@@ -99,8 +98,8 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
FeedManagerImpl(@Scheduler ScheduledExecutorService scheduler, FeedManagerImpl(@Scheduler ScheduledExecutorService scheduler,
@IoExecutor Executor ioExecutor, DatabaseComponent db, @IoExecutor Executor ioExecutor, DatabaseComponent db,
ContactGroupFactory contactGroupFactory, ClientHelper clientHelper, ContactGroupFactory contactGroupFactory, ClientHelper clientHelper,
IdentityManager identityManager, BlogManager blogManager, BlogManager blogManager, BlogPostFactory blogPostFactory,
BlogPostFactory blogPostFactory, SocketFactory torSocketFactory, FeedFactory feedFactory, SocketFactory torSocketFactory,
Clock clock) { Clock clock) {
this.scheduler = scheduler; this.scheduler = scheduler;
@@ -108,9 +107,9 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
this.db = db; this.db = db;
this.contactGroupFactory = contactGroupFactory; this.contactGroupFactory = contactGroupFactory;
this.clientHelper = clientHelper; this.clientHelper = clientHelper;
this.identityManager = identityManager;
this.blogManager = blogManager; this.blogManager = blogManager;
this.blogPostFactory = blogPostFactory; this.blogPostFactory = blogPostFactory;
this.feedFactory = feedFactory;
this.torSocketFactory = torSocketFactory; this.torSocketFactory = torSocketFactory;
this.clock = clock; this.clock = clock;
} }
@@ -158,21 +157,22 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
} }
@Override @Override
public void addFeed(String url, GroupId g) throws DbException, IOException { public void addFeed(String url) throws DbException, IOException {
LOG.info("Adding new RSS feed...");
// TODO check for existing feed? // TODO check for existing feed?
// fetch feed to get its metadata // fetch syndication feed to get its metadata
Feed feed = new Feed(url, g, clock.currentTimeMillis()); SyndFeed f;
try { try {
feed = fetchFeed(feed, false); f = fetchSyndFeed(url);
} catch (FeedException e) { } catch (FeedException e) {
throw new IOException(e); throw new IOException(e);
} }
// store feed Feed feed = feedFactory.createFeed(url, f);
// store feed and new blog
Transaction txn = db.startTransaction(false); Transaction txn = db.startTransaction(false);
try { try {
blogManager.addBlog(txn, feed.getBlog());
List<Feed> feeds = getFeeds(txn); List<Feed> feeds = getFeeds(txn);
feeds.add(feed); feeds.add(feed);
storeFeeds(txn, feeds); storeFeeds(txn, feeds);
@@ -181,10 +181,10 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
db.endTransaction(txn); db.endTransaction(txn);
} }
// fetch feed again, post entries this time // fetch feed again and post entries
Feed updatedFeed; Feed updatedFeed;
try { try {
updatedFeed = fetchFeed(feed, true); updatedFeed = fetchFeed(feed);
} catch (FeedException e) { } catch (FeedException e) {
throw new IOException(e); throw new IOException(e);
} }
@@ -208,16 +208,17 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
Transaction txn = db.startTransaction(false); Transaction txn = db.startTransaction(false);
try { try {
List<Feed> feeds = getFeeds(txn); List<Feed> feeds = getFeeds(txn);
boolean found = false; Feed feed = null;
for (Feed feed : feeds) { for (Feed f : feeds) {
if (feed.getUrl().equals(url)) { if (f.getUrl().equals(url)) {
found = true; feed = f;
feeds.remove(feed); feeds.remove(f);
break; break;
} }
} }
if (!found) throw new DbException(); if (feed == null) throw new DbException();
storeFeeds(txn, feeds); storeFeeds(txn, feeds);
// TODO blogManager.removeBlog(txn, feed.getBlog());
db.commitTransaction(txn); db.commitTransaction(txn);
} finally { } finally {
db.endTransaction(txn); db.endTransaction(txn);
@@ -246,7 +247,7 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
for (Object object : d.getList(KEY_FEEDS)) { for (Object object : d.getList(KEY_FEEDS)) {
if (!(object instanceof BdfDictionary)) if (!(object instanceof BdfDictionary))
throw new FormatException(); throw new FormatException();
feeds.add(Feed.from((BdfDictionary) object)); feeds.add(feedFactory.createFeed((BdfDictionary) object));
} }
} catch (FormatException e) { } catch (FormatException e) {
throw new DbException(e); throw new DbException(e);
@@ -259,7 +260,7 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
BdfList feedList = new BdfList(); BdfList feedList = new BdfList();
for (Feed feed : feeds) { for (Feed feed : feeds) {
feedList.add(feed.toBdfDictionary()); feedList.add(feedFactory.feedToBdfDictionary(feed));
} }
BdfDictionary gm = BdfDictionary.of(new BdfEntry(KEY_FEEDS, feedList)); BdfDictionary gm = BdfDictionary.of(new BdfEntry(KEY_FEEDS, feedList));
try { try {
@@ -300,7 +301,7 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
List<Feed> newFeeds = new ArrayList<Feed>(feeds.size()); List<Feed> newFeeds = new ArrayList<Feed>(feeds.size());
for (Feed feed : feeds) { for (Feed feed : feeds) {
try { try {
newFeeds.add(fetchFeed(feed, true)); newFeeds.add(fetchFeed(feed));
} catch (FeedException e) { } catch (FeedException e) {
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))
LOG.log(WARNING, e.toString(), e); LOG.log(WARNING, e.toString(), e);
@@ -323,31 +324,45 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
LOG.info("Done updating RSS feeds"); LOG.info("Done updating RSS feeds");
} }
private Feed fetchFeed(Feed feed, boolean post) private SyndFeed fetchSyndFeed(String url)
throws FeedException, IOException, DbException { throws FeedException, IOException {
String title, description, author; // fetch feed
long updated = clock.currentTimeMillis(); SyndFeed f = getSyndFeed(getFeedInputStream(url));
long lastEntryTime = feed.getLastEntryTime();
SyndFeed f = getSyndFeed(getFeedInputStream(feed.getUrl()));
title = StringUtils.isNullOrEmpty(f.getTitle()) ? null : f.getTitle();
if (title != null) title = clean(title, STRIP_ALL);
description = StringUtils.isNullOrEmpty(f.getDescription()) ? null :
f.getDescription();
if (description != null) description = clean(description, STRIP_ALL);
author =
StringUtils.isNullOrEmpty(f.getAuthor()) ? null : f.getAuthor();
if (author != null) author = clean(author, STRIP_ALL);
if (f.getEntries().size() == 0) if (f.getEntries().size() == 0)
throw new FeedException("Feed has no entries"); throw new FeedException("Feed has no entries");
// clean title
String title =
StringUtils.isNullOrEmpty(f.getTitle()) ? null : f.getTitle();
if (title != null) title = clean(title, STRIP_ALL);
f.setTitle(title);
// clean description
String description =
StringUtils.isNullOrEmpty(f.getDescription()) ? null :
f.getDescription();
if (description != null) description = clean(description, STRIP_ALL);
f.setDescription(description);
// clean author
String author =
StringUtils.isNullOrEmpty(f.getAuthor()) ? null : f.getAuthor();
if (author != null) author = clean(author, STRIP_ALL);
f.setAuthor(author);
return f;
}
private Feed fetchFeed(Feed feed)
throws FeedException, IOException, DbException {
// fetch and clean feed
SyndFeed f = fetchSyndFeed(feed.getUrl());
// sort and add new entries // sort and add new entries
if (post) { long lastEntryTime = postFeedEntries(feed, f.getEntries());
lastEntryTime = postFeedEntries(feed, f.getEntries());
} return feedFactory.createFeed(feed, f, lastEntryTime);
return new Feed(feed.getUrl(), feed.getBlogId(), title, description,
author, feed.getAdded(), updated, lastEntryTime);
} }
private InputStream getFeedInputStream(String url) throws IOException { private InputStream getFeedInputStream(String url) throws IOException {
@@ -461,9 +476,9 @@ class FeedManagerImpl implements FeedManager, Client, EventListener {
String body = getPostBody(b.toString()); String body = getPostBody(b.toString());
try { try {
// create and store post // create and store post
LocalAuthor author = identityManager.getLocalAuthor(txn); LocalAuthor localAuthor = feed.getLocalAuthor();
BlogPost post = blogPostFactory BlogPost post = blogPostFactory
.createBlogPost(groupId, time, null, author, body); .createBlogPost(groupId, time, null, localAuthor, body);
blogManager.addLocalPost(txn, post); blogManager.addLocalPost(txn, post);
} catch (DbException e) { } catch (DbException e) {
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))

View File

@@ -28,4 +28,9 @@ public class FeedModule {
return feedManager; return feedManager;
} }
@Provides
FeedFactory provideFeedFactory(FeedFactoryImpl feedFactory) {
return feedFactory;
}
} }