Add rough, untested bounce parsing.
[p5sagit/Promulger.git] / lib / Promulger / List.pm
CommitLineData
514dce63 1package Promulger::List;
243baf4d 2use Moo;
2a007b5a 3use autodie;
514dce63 4
f5baca29 5use autodie ':all';
514dce63 6use Carp;
f5baca29 7use Path::Class;
8use Fcntl ':flock';
9bfd7b60 9use Tie::File;
0456162d 10use File::Slurp qw/read_file write_file/;
243baf4d 11use Data::Dumper;
0456162d 12use Try::Tiny;
1beca6d0 13use FindBin qw($Bin);
243baf4d 14$Data::Dumper::Purity = 1;
514dce63 15
21baaef0 16use Promulger::Config;
17
514dce63 18has listname => (
19 is => 'ro',
243baf4d 20 isa => sub { $_[0] =~ /^\w+$/ or die "listname must be a string" },
514dce63 21 required => 1,
22);
23
24has active => (
25 is => 'rw',
243baf4d 26 isa => sub { ($_[0] == 0 || $_[0] == 1) or die "active must be 0 or 1" },
514dce63 27 required => 1,
243baf4d 28 default => sub { 1 },
514dce63 29);
30
21baaef0 31has subscribers => (
32 is => 'rw',
243baf4d 33 isa => sub { ref $_[0] eq 'HASH' or die "subscribers must be a hashref" },
21baaef0 34 required => 1,
35 default => sub { {} },
36);
37
21baaef0 38sub resolve {
9bfd7b60 39 my ($self, $proto) = @_;
21baaef0 40 $proto =~ s/-request$//;
d16aba7a 41 $proto =~ s/^owner-//;
21baaef0 42 my $path = find_path_for($proto);
43 my $maybe_list;
0456162d 44 try {
21baaef0 45 $maybe_list = __PACKAGE__->load($path->stringify);
0456162d 46 } catch {
47 die "oh noes: $_";
21baaef0 48 };
49 return $maybe_list;
50}
f5baca29 51
21baaef0 52sub subscribe {
9bfd7b60 53 my ($self, $new) = @_;
8ad89cb2 54 return if $self->subscribers->{$new};
55 $self->subscribers->{$new} = 1;
56 $self->store(find_path_for($self->listname)->stringify);
57 return 1;
21baaef0 58}
f5baca29 59
21baaef0 60sub unsubscribe {
9bfd7b60 61 my ($self, $ex) = @_;
8ad89cb2 62 return unless exists $self->subscribers->{$ex};
63 delete $self->subscribers->{$ex};
64 $self->store(find_path_for($self->listname)->stringify);
65 return 1;
21baaef0 66}
f5baca29 67
21baaef0 68# XXX implement ACLs and other shinies -- apeiron, 2010-03-13
69sub accept_posts_from {
9bfd7b60 70 my ($self, $sender) = @_;
8ad89cb2 71 return grep { $sender eq $_ } keys %{$self->subscribers};
21baaef0 72}
f5baca29 73
74sub setup {
9bfd7b60 75 my ($self) = @_;
21baaef0 76 my $config = Promulger::Config->config;
514dce63 77 my $name = $self->listname;
9bfd7b60 78 croak "${name} already a known list" if $self->resolve($name);
21baaef0 79 my $path = find_path_for($name);
f5baca29 80
7636373d 81 my $tie = tie my @aliases, 'Tie::File', $config->{aliases}
82 or die "cannot tie " . $config->{aliases} . ": $!";
9bfd7b60 83 $tie->flock;
84 my @list_aliases = ($name, "${name}-request");
21baaef0 85
d16aba7a 86 # XXX add a flag to determine whether to write the aliases file or no
87 # -- apeiron, 2012-07-18
9bfd7b60 88 for my $list_alias (@list_aliases) {
89 if(grep { /^${list_alias}:/ } @aliases) {
90 croak "${list_alias} already in $config->{aliases}";
514dce63 91 }
9bfd7b60 92 push @aliases,
d16aba7a 93 qq(${list_alias}: "|$Bin msg -c $config->{config_file}"\n),
94 qq(${list_alias}-owner: "|$Bin msgbounce -c $config->{config_file}"\n);
514dce63 95 }
21baaef0 96
f5baca29 97 $self->store($path->stringify);
9bfd7b60 98}
99
100sub delete {
101 my ($self) = @_;
102 my $config = Promulger::Config->config;
103 my $name = $self->listname;
104
105 my $tie = tie my @aliases, 'Tie::File', $config->{aliases};
106 $tie->flock;
107
108 my @list_aliases = ($name, "${name}-request");
109 @aliases = grep {
110 $_ !~ /^$list_aliases[0]:/ &&
111 $_ !~ /^$list_aliases[1]:/
112 } @aliases;
113
8ad89cb2 114 unlink find_path_for($self->listname)->stringify;
514dce63 115}
116
21baaef0 117sub find_path_for {
118 my ($proto) = @_;
119 my $path = file(Promulger::Config->config->{list_home}, $proto . ".list");
9bfd7b60 120 return $path;
21baaef0 121}
122
243baf4d 123sub store {
124 my ($self, $path) = @_;
125 my $dumped = 'do { my '. Dumper($self) . '; $VAR1; }';
126 write_file($path, $dumped);
127}
128
129sub load {
130 my ($class, $path) = @_;
131 return do $path;
132}
133
0456162d 134sub get_lists {
135 my ($self) = @_;
136 my $config = Promulger::Config->config;
137 my @lists = map { $_->basename}
138 grep { -f } dir($config->{list_home})->children;
139 s/\.list//g for @lists;
140 return @lists;
141}
142
21baaef0 143'http://mitpress.mit.edu/sicp/';