FeedEntryImportService.java
package net.sasasin.sreader.service;
import com.rometools.rome.feed.synd.SyndEntry;
import com.rometools.rome.feed.synd.SyndFeed;
import com.rometools.rome.io.FeedException;
import com.rometools.rome.io.SyndFeedInput;
import com.rometools.rome.io.XmlReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.Date;
import java.util.Optional;
import net.sasasin.sreader.domain.ContentHeader;
import net.sasasin.sreader.domain.FeedUrl;
import net.sasasin.sreader.domain.FullTextMethod;
import net.sasasin.sreader.repository.ContentHeaderRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service
public class FeedEntryImportService {
private static final Logger logger = LoggerFactory.getLogger(FeedEntryImportService.class);
private final HttpFetchService httpFetchService;
private final ContentHeaderRepository contentHeaderRepository;
private final FeedEntryFullTextExtractor feedEntryFullTextExtractor;
private final ContentFullTextWriter contentFullTextWriter;
public FeedEntryImportService(
HttpFetchService httpFetchService,
ContentHeaderRepository contentHeaderRepository,
FeedEntryFullTextExtractor feedEntryFullTextExtractor,
ContentFullTextWriter contentFullTextWriter) {
this.httpFetchService = httpFetchService;
this.contentHeaderRepository = contentHeaderRepository;
this.feedEntryFullTextExtractor = feedEntryFullTextExtractor;
this.contentFullTextWriter = contentFullTextWriter;
}
public int importEntries(FeedUrl feedUrl) {
try {
HttpFetchService.FetchedResource feed = httpFetchService.get(URI.create(feedUrl.url()));
SyndFeed syndFeed =
new SyndFeedInput()
.build(
new XmlReader(
new ByteArrayInputStream(feed.body().getBytes(StandardCharsets.UTF_8))));
int inserted = 0;
for (SyndEntry entry : syndFeed.getEntries()) {
if (entry.getLink() == null || entry.getLink().isBlank()) {
continue;
}
URI articleUri = httpFetchService.resolveRedirect(URI.create(entry.getLink()));
Optional<String> feedText =
feedUrl.fullTextMethod() == FullTextMethod.FEED
? feedEntryFullTextExtractor.extract(entry)
: Optional.empty();
ContentHeader header =
new ContentHeader(
HashIds.md5(articleUri.toString()),
feedUrl.id(),
articleUri.toString(),
entry.getTitle(),
toOffsetDateTime(entry.getPublishedDate()),
feedText.orElse(null));
if (contentHeaderRepository.insertIfAbsent(header)) {
inserted++;
}
if (feedUrl.fullTextMethod() == FullTextMethod.FEED) {
feedText.ifPresent(fullText -> contentFullTextWriter.saveIfAbsent(header, fullText));
}
}
return inserted;
} catch (IllegalArgumentException | IOException | InterruptedException | FeedException e) {
if (e instanceof InterruptedException) {
Thread.currentThread().interrupt();
}
logger.warn("Failed to import feed {}", feedUrl.url(), e);
return 0;
}
}
private OffsetDateTime toOffsetDateTime(Date date) {
if (date == null) {
return null;
}
return date.toInstant().atOffset(ZoneOffset.UTC);
}
}