dumping ground for random patches and texts
 help / color / mirror / Atom feed
* [PATCH] www: add topics.html endpoint
@ 2023-11-09  1:46 Eric Wong
  0 siblings, 0 replies; only message in thread
From: Eric Wong @ 2023-11-09  1:46 UTC (permalink / raw)
  To: spew

---
 MANIFEST                     |  1 +
 lib/PublicInbox/View.pm      |  4 ++-
 lib/PublicInbox/WWW.pm       |  9 ++++++
 lib/PublicInbox/WwwStream.pm |  1 +
 lib/PublicInbox/WwwTopics.pm | 55 ++++++++++++++++++++++++++++++++++++
 t/extindex-psgi.t            |  6 ++++
 t/plack.t                    |  9 ++++--
 7 files changed, 81 insertions(+), 4 deletions(-)
 create mode 100644 lib/PublicInbox/WwwTopics.pm

diff --git a/MANIFEST b/MANIFEST
index 51dcffaf..e1c3dc97 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -371,6 +371,7 @@ lib/PublicInbox/WwwListing.pm
 lib/PublicInbox/WwwStatic.pm
 lib/PublicInbox/WwwStream.pm
 lib/PublicInbox/WwwText.pm
+lib/PublicInbox/WwwTopics.pm
 lib/PublicInbox/XapClient.pm
 lib/PublicInbox/XapHelper.pm
 lib/PublicInbox/XapHelperCxx.pm
diff --git a/lib/PublicInbox/View.pm b/lib/PublicInbox/View.pm
index e5f748f7..b4933b1b 100644
--- a/lib/PublicInbox/View.pm
+++ b/lib/PublicInbox/View.pm
@@ -1142,7 +1142,9 @@ sub pagination_footer ($$) {
 		$next = $next ? "$next | " : '             | ';
 		$prev .= qq[ | <a\nhref="$latest">latest</a>];
 	}
-	($next || $prev) ? "<hr><pre id=nav>page: $next$prev</pre>" : '';
+	my $x = '<hr><pre id=nav>';
+	$x .= "page: $next$prev " if $next || $prev;
+	$x .= q{- recent:[<a href="./topics.html">topics</a>]</pre>};
 }
 
 sub paginate_recent ($$) {
diff --git a/lib/PublicInbox/WWW.pm b/lib/PublicInbox/WWW.pm
index d2bd68ea..dcaf93cb 100644
--- a/lib/PublicInbox/WWW.pm
+++ b/lib/PublicInbox/WWW.pm
@@ -101,6 +101,8 @@ sub call {
 		invalid_inbox($ctx, $1) || get_atom($ctx);
 	} elsif ($path_info =~ m!$INBOX_RE/new\.html\z!o) {
 		invalid_inbox($ctx, $1) || get_new($ctx);
+	} elsif ($path_info =~ m!$INBOX_RE/topics\.html\z!o) {
+		invalid_inbox($ctx, $1) || get_topics($ctx);
 	} elsif ($path_info =~ m!$INBOX_RE/description\z!o) {
 		get_description($ctx, $1);
 	} elsif ($path_info =~ m!$INBOX_RE/(?:(?:git/)?([0-9]+)(?:\.git)?/)?
@@ -270,6 +272,13 @@ sub get_new {
 	PublicInbox::Feed::new_html($ctx);
 }
 
+# /$INBOX/topics.html			-> HTML only
+sub get_topics {
+	my ($ctx) = @_;
+	require PublicInbox::WwwTopics;
+	PublicInbox::WwwTopics::topics_html($ctx) || r404($ctx);
+}
+
 # /$INBOX/?r=$GIT_COMMIT                 -> HTML only
 sub get_index {
 	my ($ctx) = @_;
diff --git a/lib/PublicInbox/WwwStream.pm b/lib/PublicInbox/WwwStream.pm
index 4cbdda99..3a1d6edf 100644
--- a/lib/PublicInbox/WwwStream.pm
+++ b/lib/PublicInbox/WwwStream.pm
@@ -113,6 +113,7 @@ sub html_top ($) {
 			qq(<a\nid=mirror) .
 			qq(\nhref="${upfx}_/text/mirror/">mirror</a>$code / ).
 			qq(<a\nhref="$atom">Atom feed</a>);
+	$links .= delete($ctx->{-html_more_links}) if $ctx->{-html_more_links};
 	if ($ibx->isrch) {
 		my $q_val = delete($ctx->{-q_value_html}) // '';
 		$q_val = qq(\nvalue="$q_val") if $q_val ne '';
diff --git a/lib/PublicInbox/WwwTopics.pm b/lib/PublicInbox/WwwTopics.pm
new file mode 100644
index 00000000..5605cfbe
--- /dev/null
+++ b/lib/PublicInbox/WwwTopics.pm
@@ -0,0 +1,55 @@
+# Copyright (C) all contributors <meta@public-inbox.org>
+# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
+
+package PublicInbox::WwwTopics;
+use v5.12;
+use autodie qw(open);
+use PublicInbox::Hval qw(ascii_html mid_href fmt_ts);
+use PublicInbox::WwwStream;
+
+sub add_topic_line ($$$) {
+	my (undef, $prev, $nr) = @_;
+	my $s = ascii_html($prev->{subject});
+	$s = '(no subject)' if $s eq '';
+	$_[0] .= "\n".fmt_ts($prev->{ds}).
+		qq{ <a\nhref="}.mid_href($prev->{mid}).qq{/#r">$s</a>};
+	$_[0] .= " $nr+ messages" if $nr > 1;
+}
+
+sub topics_html { # GET /$INBOX_NAME/topics.html
+	my ($ctx) = @_;
+	my $over = $ctx->{ibx}->over or
+			return $ctx->{www}->can('need')->($ctx,'Overview');
+
+	# XXX there is likely faster ways to do this.
+	# OTOH SQLite tends to be faster with multiple simple queries
+	# rather than more complex ones
+	my $msgs = $over->do_get(<<EOS, { limit => 10000 });
+SELECT num,ts,ds,tid,ddd FROM over WHERE tid IN
+(SELECT DISTINCT(tid) FROM over WHERE tid > 0 ORDER BY tid DESC LIMIT 200)
+AND +num > 0
+ORDER BY tid,ts ASC
+EOS
+	# can't use SQL to filter references since our schema wasn't designed
+	# for it, but our SQL sorts by ascending time to favor top-level
+	# messages while our final result (post-references filter) favors
+	# recent messages
+	chomp($ctx->{-html_more_links} = <<EOM);
+\n- recent:[<a href="./">subjects (threaded)</a>|topics] (all times UTC)
+EOM
+	my $buf = '<pre>';
+	my ($nr, $prev);
+	while (my $smsg = pop @$msgs) {
+		if ($prev && $smsg->{tid} != $prev->{tid}) {
+			add_topic_line($buf, $prev, $nr);
+			$nr = 0;
+		}
+		++$nr;
+		$prev = $smsg;
+	}
+	add_topic_line($buf, $prev, $nr) if $prev;
+	$buf .= '</pre>';
+	PublicInbox::WwwStream::html_oneshot($ctx, 200, $buf);
+}
+
+1;
diff --git a/t/extindex-psgi.t b/t/extindex-psgi.t
index f71210a5..9e0c7dc3 100644
--- a/t/extindex-psgi.t
+++ b/t/extindex-psgi.t
@@ -118,6 +118,12 @@ my $client = sub {
 	is($res->code, 404, '404 on out-of-range mid2tid query');
 	$res = $cb->(POST("/m2t/t\@1/?q=s:unrelated&x=m"));
 	is($res->code, 404, '404 on cross-thread search');
+
+
+	$res = $cb->(GET('/m2t/topics.html'));
+	is($res->code, 200, 'topics.html on basic v2');
+	$res = $cb->(GET('/all/topics.html'));
+	is($res->code, 200, 'topics.html on extindex');
 };
 test_psgi(sub { $www->call(@_) }, $client);
 %$env = (%$env, TMPDIR => $tmpdir, PI_CONFIG => $pi_config);
diff --git a/t/plack.t b/t/plack.t
index 7f80f488..7ec35e7a 100644
--- a/t/plack.t
+++ b/t/plack.t
@@ -204,9 +204,12 @@ my $c1 = sub {
 	my $raw = PublicInbox::Eml->new(\$body);
 	is($raw->body_raw, $eml->body_raw, 'ISO-2022-JP body unmodified');
 
-	$res = $cb->(GET($pfx . '/blah@example.com/t.mbox.gz'));
-	is(501, $res->code, '501 when overview missing');
-	like($res->content, qr!\bOverview\b!, 'overview omission noted');
+	for my $u (qw(blah@example.com/t.mbox.gz topics.html)) {
+		$res = $cb->(GET("$pfx/$u"));
+		is(501, $res->code, "501 on /$u when overview missing");
+		like($res->content, qr!\bOverview\b!,
+			"overview omission noted for /$u");
+	}
 
 	# legacy redirects
 	for my $t (qw(m f)) {

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2023-11-09  1:46 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-09  1:46 [PATCH] www: add topics.html endpoint Eric Wong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).