package addon.rss; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.jsoup.Jsoup; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import utils.WebPage; import static utils.Constants.*; public class Feed { protected String address; protected String name; protected String lastKnownTitle; protected List<String> lastFiveTitles; protected List<String> titlePatterns; protected boolean displayLinks; protected enum Type { Atom, RSS, Undefined } protected Type type; public Feed(String name, String address) { this.address = address; this.name = name; this.lastKnownTitle = ""; this.lastFiveTitles = new ArrayList<>(); this.titlePatterns = new ArrayList<>(); this.displayLinks = false; this.type = Type.Undefined; } public String getName() { return name; } public List<String> check(byte maxMsgsCount) throws IOException { WebPage entry = WebPage.loadWebPage(address, "UTF-8"); String content = replaceLinks( entry.getContent() ); defineFeedTypeIfNecessary(content); Elements items = Jsoup.parse(content).getElementsByTag( getItemTag() ); int itemsCount = items.size(); String newestTitle = null; List<String> newTitles = new ArrayList<>(); for (byte i = 0; i < maxMsgsCount && i < itemsCount; ++i) { String title = removeCDATA( items.get(i).getElementsByTag("title").text() ); String link = getLink( items.get(i) ); if( title.equals(lastKnownTitle) ) break; if ( titleMatched(title) ) { String output = title; if (displayLinks) output += " | " + link; newTitles.add(output); if (newestTitle == null) newestTitle = title; } } if (newestTitle != null) { lastKnownTitle = newestTitle; addToCache(newTitles); } return newTitles; } protected void addToCache(List<String> newTitles) { lastFiveTitles.addAll(0, newTitles); int endIndex = Math.min(5, lastFiveTitles.size() ); lastFiveTitles = lastFiveTitles.subList(0, endIndex); } protected void defineFeedTypeIfNecessary(String content) { if (type == Type.Undefined) { int maxSearchLen = Math.min(300, content.length() ); boolean isRSS = content.substring(0, maxSearchLen).indexOf("<rss") != NOT_FOUND; type = isRSS ? Type.RSS : Type.Atom; } } protected String getItemTag() { switch (type) { case Atom: return "entry"; default: return "item"; } } protected String getLink(Element item) { switch (type) { case Atom: return item.getElementsByTag("link").attr("href"); default: return item.getElementsByTag("span").text(); } } protected String replaceLinks(String content) { return content.replaceAll("<link>", "<span>").replaceAll("</link>", "</span>"); } public List<String> getLastMessages(int count) { return lastFiveTitles; } protected boolean titleMatched(String title) { if ( titlePatterns.isEmpty() ) return true; for(String pattern : titlePatterns) if( title.indexOf(pattern) != NOT_FOUND ) return true; return false; } protected String removeCDATA(String title) { return ( title.indexOf("<![CDATA[") != NOT_FOUND ) ? title.substring(9, title.length() - 3) : title; } };