public-inbox.git  about / heads / tags
an "archives first" approach to mailing lists
blob 9d2707323729da17f906b0870d2843fbcefb88b4 2672 bytes (raw)
$ git show HEAD:lib/PublicInbox/WwwTopics.pm	# shows this blob on the CLI

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
 
# 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 PublicInbox::Hval qw(ascii_html mid_href fmt_ts);

sub add_topic_html ($$) {
	my (undef, $smsg) = @_;
	my $s = ascii_html($smsg->{subject});
	$s = '(no subject)' if $s eq '';
	$_[0] .= "\n".fmt_ts($smsg->{ds}) .
		qq{ <a\nhref="}.mid_href($smsg->{mid}).qq{/#r">$s</a>};
	my $nr = $smsg->{'COUNT(num)'};
	$_[0] .= " $nr+ messages" if $nr > 1;
}

# n.b. the `SELECT DISTINCT(tid)' subquery is critical for performance
# with giant inboxes and extindices
sub topics_new ($) {
        $_[0]->do_get(<<EOS);
SELECT ds,ddd,COUNT(num) FROM over WHERE tid IN
(SELECT DISTINCT(tid) FROM over WHERE tid > 0 ORDER BY ts DESC LIMIT 200)
AND +num > 0
GROUP BY tid
ORDER BY ds ASC
EOS
}

sub topics_active ($) {
        $_[0]->do_get(<<EOS);
SELECT ddd,MAX(ds) as ds,COUNT(num) FROM over WHERE tid IN
(SELECT DISTINCT(tid) FROM over WHERE tid > 0 ORDER BY ts DESC LIMIT 200)
AND +num > 0
GROUP BY tid
ORDER BY ds ASC
EOS
}

sub topics_i { pop @{$_[0]->{msgs}} }

sub topics_atom { # GET /$INBOX_NAME/topics_(new|active).atom
	my ($ctx) = @_;
	require PublicInbox::WwwAtomStream;
	my ($hdr, $smsg, $val);
	PublicInbox::WwwAtomStream->response($ctx, \&topics_i);
}

sub topics_html { # GET /$INBOX_NAME/topics_(new|active).html
	my ($ctx) = @_;
	require PublicInbox::WwwStream;
	my $buf = '<pre>';
	$ctx->{-html_more_links} = qq{\n- recent:[<a
href="./">subjects (threaded)</a>|};

	if ($ctx->{topic_category} eq 'new') {
		$ctx->{-html_more_links} .= qq{<b>topics (new)</b>|<a
href="./topics_active.html">topics (active)</a>]};
	} else { # topic_category eq "active" - topics with recent replies
		$ctx->{-html_more_links} .= qq{<a
href="./topics_new.html">topics (new)</a>|<b>topics (active)</b>]};
	}
	# 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
	my $msgs = delete $ctx->{msgs};
	add_topic_html($buf, pop @$msgs) while scalar(@$msgs);
	$buf .= '</pre>';
	PublicInbox::WwwStream::html_oneshot($ctx, 200, $buf);
}

sub response {
	my ($ctx, $ibx_name, $category, $type) = @_;
	my ($ret, $over);
	$ret = PublicInbox::WWW::invalid_inbox($ctx, $ibx_name) and return $ret;
	$over = $ctx->{ibx}->over or
		return PublicInbox::WWW::need($ctx, 'Overview', './');
	$ctx->{msgs} = $category eq 'new' ? topics_new($over) :
			topics_active($over);
	$ctx->{topic_category} = $category;
	$type eq 'atom' ? topics_atom($ctx) : topics_html($ctx);
}

1;

git clone https://public-inbox.org/public-inbox.git
git clone http://7fh6tueqddpjyxjmgtdiueylzoqt6pt7hec3pukyptlmohoowvhde4yd.onion/public-inbox.git