From 35b75a73004985c9ba829356aa25a55dc89894cb Mon Sep 17 00:00:00 2001 From: jrandom <jrandom> Date: Sat, 3 Dec 2005 19:03:44 +0000 Subject: [PATCH] 2005-12-03 jrandom * Added support for a 'most recent posts' view that CofE requested, which includes the ability to filter by age (e.g. posts by your favorite authors in the last 5 days). --- .../src/net/i2p/syndie/data/ArchiveIndex.java | 9 +++- .../java/src/net/i2p/syndie/data/BlogURI.java | 18 ++++++++ .../i2p/syndie/sml/ThreadedHTMLRenderer.java | 16 +++++-- .../src/net/i2p/syndie/web/BaseServlet.java | 21 ++++++++- .../i2p/syndie/web/ViewThreadedServlet.java | 43 ++++++++++++++++++- history.txt | 7 ++- 6 files changed, 105 insertions(+), 9 deletions(-) diff --git a/apps/syndie/java/src/net/i2p/syndie/data/ArchiveIndex.java b/apps/syndie/java/src/net/i2p/syndie/data/ArchiveIndex.java index 61126821ae..ca64105523 100644 --- a/apps/syndie/java/src/net/i2p/syndie/data/ArchiveIndex.java +++ b/apps/syndie/java/src/net/i2p/syndie/data/ArchiveIndex.java @@ -281,6 +281,9 @@ public class ArchiveIndex { * */ public void selectMatchesOrderByEntryId(List out, Hash blog, String tag) { + selectMatchesOrderByEntryId(out, blog, tag, 0); + } + public void selectMatchesOrderByEntryId(List out, Hash blog, String tag, long lowestEntryId) { TreeMap ordered = new TreeMap(); for (int i = 0; i < _blogs.size(); i++) { BlogSummary summary = (BlogSummary)_blogs.get(i); @@ -288,7 +291,7 @@ public class ArchiveIndex { if (!blog.equals(summary.blog)) continue; } - if (tag != null) { + if ( (tag != null) && (tag.trim().length() > 0) ) { if (!tag.equals(summary.tag)) { if (_log.shouldLog(Log.DEBUG)) _log.debug("Tag [" + summary.tag + "] does not match the requested [" + tag + "] in " + summary.blog.toBase64()); @@ -312,6 +315,8 @@ public class ArchiveIndex { for (int j = 0; j < summary.entries.size(); j++) { EntrySummary entry = (EntrySummary)summary.entries.get(j); + if (entry.entry.getEntryId() < lowestEntryId) + continue; String k = (Long.MAX_VALUE-entry.entry.getEntryId()) + "-" + entry.entry.getKeyHash().toBase64(); ordered.put(k, entry.entry); //System.err.println("Including match: " + k); @@ -319,6 +324,8 @@ public class ArchiveIndex { } for (Iterator iter = ordered.values().iterator(); iter.hasNext(); ) { BlogURI entry = (BlogURI)iter.next(); + if (entry.getEntryId() < lowestEntryId) + continue; if (!out.contains(entry)) out.add(entry); } diff --git a/apps/syndie/java/src/net/i2p/syndie/data/BlogURI.java b/apps/syndie/java/src/net/i2p/syndie/data/BlogURI.java index 5b38a55af9..b2b7a814f5 100644 --- a/apps/syndie/java/src/net/i2p/syndie/data/BlogURI.java +++ b/apps/syndie/java/src/net/i2p/syndie/data/BlogURI.java @@ -10,6 +10,8 @@ public class BlogURI { private Hash _blogHash; private long _entryId; + public static final Comparator COMPARATOR = new NewestFirstComparator(); + public BlogURI() { this(null, -1); } @@ -95,4 +97,20 @@ public class BlogURI { if (!u.toString().equals(uri)) System.err.println("Not a match: [" + uri + "] != [" + u.toString() + "]"); } + + /** + * Order the BlogURIs by entryId, with the highest entryId first + */ + private static class NewestFirstComparator implements Comparator { + public int compare(Object lhs, Object rhs) { + BlogURI l = (BlogURI)lhs; + BlogURI r = (BlogURI)rhs; + if (l.getEntryId() > r.getEntryId()) + return -1; + else if (l.getEntryId() < r.getEntryId()) + return 1; + else // same date, compare by blog hash (aka randomly) + return DataHelper.compareTo(l.getKeyHash().getData(), r.getKeyHash().getData()); + } + } } diff --git a/apps/syndie/java/src/net/i2p/syndie/sml/ThreadedHTMLRenderer.java b/apps/syndie/java/src/net/i2p/syndie/sml/ThreadedHTMLRenderer.java index 8441d99d8d..37b4ac2442 100644 --- a/apps/syndie/java/src/net/i2p/syndie/sml/ThreadedHTMLRenderer.java +++ b/apps/syndie/java/src/net/i2p/syndie/sml/ThreadedHTMLRenderer.java @@ -40,6 +40,8 @@ public class ThreadedHTMLRenderer extends HTMLRenderer { public static final String PARAM_OFFSET = "offset"; public static final String PARAM_TAGS = "tags"; public static final String PARAM_AUTHOR = "author"; + /** search back through the blog for entries this many days */ + public static final String PARAM_DAYS_BACK = "daysBack"; // parameters for editing one's profile public static final String PARAM_PROFILE_NAME = "profileName"; public static final String PARAM_PROFILE_DESC = "profileDesc"; @@ -446,8 +448,12 @@ public class ThreadedHTMLRenderer extends HTMLRenderer { String inReplyTo = (String)_headers.get(HEADER_IN_REPLY_TO); if ( (inReplyTo != null) && (inReplyTo.trim().length() > 0) ) { BlogURI replyURI = new BlogURI(inReplyTo); - if (replyURI.getEntryId() > 0) - _postBodyBuffer.append(" <a ").append(getClass("summDetailParent")).append(" href=\"").append(getPageURL(replyURI.getKeyHash(), null, replyURI.getEntryId(), 0, 0, true, true)).append("\">(view parent)</a><br />\n"); + if (replyURI.getEntryId() > 0) { + _postBodyBuffer.append(" <a ").append(getClass("summDetailParent")); + _postBodyBuffer.append(" href=\""); + _postBodyBuffer.append(getPageURL(replyURI.getKeyHash(), null, replyURI.getEntryId(), 0, 0, true, true)); + _postBodyBuffer.append("\">(view parent)</a><br />\n"); + } } _postBodyBuffer.append(" </td>\n"); @@ -487,14 +493,18 @@ public class ThreadedHTMLRenderer extends HTMLRenderer { public String getPageURL(Hash blog, String tag, long entryId, String group, int numPerPage, int pageNum, boolean expandEntries, boolean showImages) { StringBuffer buf = new StringBuffer(128); buf.append(_baseURI).append('?'); + String entry = null; if ( (blog != null) && (entryId > 0) ) { - buf.append(PARAM_VIEW_POST).append('=').append(Base64.encode(blog.getData())).append('/').append(entryId).append('&'); + entry = blog.toBase64() + '/' + entryId; + buf.append(PARAM_VIEW_THREAD).append('=').append(entry).append('&'); buf.append(PARAM_VISIBLE).append('=').append(Base64.encode(blog.getData())).append('/').append(entryId).append('&'); } else if (blog != null) { buf.append(PARAM_AUTHOR).append('=').append(blog.toBase64()).append('&'); } if (tag != null) buf.append(PARAM_TAGS).append('=').append(sanitizeTagParam(tag)).append('&'); + if ( (blog != null) && (entryId > 0) ) + buf.append("#blog://").append(entry); return buf.toString(); } } diff --git a/apps/syndie/java/src/net/i2p/syndie/web/BaseServlet.java b/apps/syndie/java/src/net/i2p/syndie/web/BaseServlet.java index c662bc0cd2..8c32847c51 100644 --- a/apps/syndie/java/src/net/i2p/syndie/web/BaseServlet.java +++ b/apps/syndie/java/src/net/i2p/syndie/web/BaseServlet.java @@ -77,6 +77,8 @@ public abstract class BaseServlet extends HttpServlet { req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); resp.setContentType("text/html;charset=UTF-8"); + resp.setHeader("cache-control", "no-cache"); + resp.setHeader("pragma", "no-cache"); User user = (User)req.getSession().getAttribute("user"); String login = req.getParameter("login"); @@ -490,6 +492,8 @@ public abstract class BaseServlet extends HttpServlet { protected void renderBegin(User user, HttpServletRequest req, PrintWriter out, ThreadIndex index) throws IOException { out.write("<html>\n<head><title>" + getTitle() + "</title>\n"); + out.write("<meta http-equiv=\"cache-control\" content=\"no-cache\" />"); + out.write("<meta http-equiv=\"pragma\" content=\"no-cache\" />"); out.write("<style>"); out.write(STYLE_HTML); Reader css = null; @@ -553,10 +557,11 @@ public abstract class BaseServlet extends HttpServlet { SKIP_TAGS.add("filter"); // post and visible are skipped since we aren't good at filtering by tag when the offset will // skip around randomly. at least, not yet. - SKIP_TAGS.add("visible"); + SKIP_TAGS.add(ThreadedHTMLRenderer.PARAM_VISIBLE); //SKIP_TAGS.add("post"); //SKIP_TAGS.add("thread"); - SKIP_TAGS.add("offset"); // if we are adjusting the filter, ignore the previous offset + SKIP_TAGS.add(ThreadedHTMLRenderer.PARAM_OFFSET); // if we are adjusting the filter, ignore the previous offset + SKIP_TAGS.add(ThreadedHTMLRenderer.PARAM_DAYS_BACK); SKIP_TAGS.add("addLocation"); SKIP_TAGS.add("addGroup"); SKIP_TAGS.add("login"); @@ -597,6 +602,12 @@ public abstract class BaseServlet extends HttpServlet { PetNameDB db = user.getPetNameDB(); TreeSet names = new TreeSet(db.getNames()); out.write("<option value=\"\">Any authors</option>\n"); + if (user.getAuthenticated()) { + if ("favorites".equals(author)) + out.write("<option selected=\"true\" value=\"favorites\">All recent posts by favorite authors</option>\n"); + else + out.write("<option value=\"favorites\">All recent posts by favorite authors</option>\n"); + } if (user.getBlog() != null) { if ( (author != null) && (author.equals(user.getBlog().toBase64())) ) out.write("<option value=\"" + user.getBlog().toBase64() + "\" selected=\"true\">Threads you posted in</option>\n"); @@ -619,6 +630,12 @@ public abstract class BaseServlet extends HttpServlet { out.write("Tags: <input type=\"text\" name=\"" + ThreadedHTMLRenderer.PARAM_TAGS + "\" size=\"10\" value=\"" + tags + "\" title=\"Threads are filtered to include only ones with posts containing these tags\" />\n"); + String days = req.getParameter(ThreadedHTMLRenderer.PARAM_DAYS_BACK); + if (days == null) + days = ""; + out.write("Age: <input type=\"text\" name=\"" + ThreadedHTMLRenderer.PARAM_DAYS_BACK + "\" size=\"2\" value=\"" + days + + "\" title=\"Posts are filtered to include only ones which were made within this many days ago\" /> days\n"); + out.write("<input type=\"submit\" name=\"action\" value=\"Go\" />\n"); out.write("</td><td class=\"controlBarRight\" width=\"1%\">"); diff --git a/apps/syndie/java/src/net/i2p/syndie/web/ViewThreadedServlet.java b/apps/syndie/java/src/net/i2p/syndie/web/ViewThreadedServlet.java index ec0bb3a902..8e7519abcf 100644 --- a/apps/syndie/java/src/net/i2p/syndie/web/ViewThreadedServlet.java +++ b/apps/syndie/java/src/net/i2p/syndie/web/ViewThreadedServlet.java @@ -21,7 +21,7 @@ import net.i2p.syndie.sml.*; public class ViewThreadedServlet extends BaseServlet { protected void renderServletDetails(User user, HttpServletRequest req, PrintWriter out, ThreadIndex index, int threadOffset, BlogURI visibleEntry, Archive archive) throws IOException { - List posts = getPosts(archive, req, index); + List posts = getPosts(user, archive, req, index); renderBody(user, req, out, index, archive, posts); renderThreadNav(user, req, out, threadOffset, index); @@ -46,8 +46,47 @@ public class ViewThreadedServlet extends BaseServlet { } } - private List getPosts(Archive archive, HttpServletRequest req, ThreadIndex index) { + private List getPosts(User user, Archive archive, HttpServletRequest req, ThreadIndex index) { List rv = new ArrayList(1); + String author = req.getParameter(ThreadedHTMLRenderer.PARAM_AUTHOR); + String tags = req.getParameter(ThreadedHTMLRenderer.PARAM_TAGS); + if (author != null) { + long dayBegin = BlogManager.instance().getDayBegin(); + String daysStr = req.getParameter(ThreadedHTMLRenderer.PARAM_DAYS_BACK); + int days = 1; + try { + if (daysStr != null) + days = Integer.parseInt(daysStr); + } catch (NumberFormatException nfe) { + days = 1; + } + dayBegin -= (days-1) * 24*60*60*1000; + + ArchiveIndex aindex = archive.getIndex(); + PetNameDB db = user.getPetNameDB(); + if ("favorites".equals(author)) { + for (Iterator nameIter = db.getNames().iterator(); nameIter.hasNext(); ) { + PetName pn = db.getByName((String)nameIter.next()); + if (pn.isMember(FilteredThreadIndex.GROUP_FAVORITE) && AddressesServlet.PROTO_BLOG.equals(pn.getProtocol()) ) { + Hash loc = new Hash(); + byte key[] = Base64.decode(pn.getLocation()); + if ( (key != null) && (key.length == Hash.HASH_LENGTH) ) { + loc.setData(key); + aindex.selectMatchesOrderByEntryId(rv, loc, tags, dayBegin); + } + } + } + Collections.sort(rv, BlogURI.COMPARATOR); + } else { + Hash loc = new Hash(); + byte key[] = Base64.decode(author); + if ( (key != null) && (key.length == Hash.HASH_LENGTH) ) { + loc.setData(key); + aindex.selectMatchesOrderByEntryId(rv, loc, tags, dayBegin); + } + } + } + String post = req.getParameter(ThreadedHTMLRenderer.PARAM_VIEW_POST); BlogURI uri = getAsBlogURI(post); if ( (uri != null) && (uri.getEntryId() > 0) ) { diff --git a/history.txt b/history.txt index 004008bf3a..6dbcd4af3e 100644 --- a/history.txt +++ b/history.txt @@ -1,4 +1,9 @@ -$Id: history.txt,v 1.342 2005/12/03 00:41:25 jrandom Exp $ +$Id: history.txt,v 1.343 2005/12/03 12:33:35 jrandom Exp $ + +2005-12-03 jrandom + * Added support for a 'most recent posts' view that CofE requested, which + includes the ability to filter by age (e.g. posts by your favorite + authors in the last 5 days). 2005-12-03 jrandom * Adjusted Syndie to use the threaded view that cervantes suggested, which -- GitLab