192e8d7a30d7ad837525f716edd03284c31cec58
[ikiwiki.git] / IkiWiki / Plugin / notifyemail.pm
1 #!/usr/bin/perl
2 package IkiWiki::Plugin::notifyemail;
3
4 use warnings;
5 use strict;
6 use IkiWiki 3.00;
7
8 sub import {
9         hook(type => "formbuilder_setup", id => "notifyemail", call => \&formbuilder_setup);
10         hook(type => "formbuilder", id => "notifyemail", call => \&formbuilder);
11         hook(type => "getsetup", id => "notifyemail",  call => \&getsetup);
12         hook(type => "changes", id => "notifyemail", call => \&notify);
13 }
14
15 sub getsetup () {
16         return
17                 plugin => {
18                         safe => 1,
19                         rebuild => 0,
20                         section => "misc",
21                 },
22 }
23
24 sub formbuilder_setup (@) {
25         my %params=@_;
26
27         my $form=$params{form};
28         return unless $form->title eq "preferences";
29         my $session=$params{session};
30         $form->field(name => "subscriptions", size => 50,
31                 fieldset => "preferences",
32                 comment => "(".htmllink("", "", "ikiwiki/PageSpec", noimageinline => 1).")",
33                 value => getsubscriptions($session->param("name")));
34 }
35
36 sub formbuilder (@) {
37         my %params=@_;
38         my $form=$params{form};
39         return unless $form->title eq "preferences" &&
40                 $form->submitted eq "Save Preferences" && $form->validate &&
41                 defined $form->field("subscriptions");
42         setsubscriptions($form->field('name'), $form->field('subscriptions'));
43 }
44
45 sub getsubscriptions ($) {
46         my $user=shift;
47         eval q{use IkiWiki::UserInfo};
48         error $@ if $@;
49         IkiWiki::userinfo_get($user, "subscriptions");
50 }
51
52 sub setsubscriptions ($$) {
53         my $user=shift;
54         my $subscriptions=shift;
55         eval q{use IkiWiki::UserInfo};
56         error $@ if $@;
57         IkiWiki::userinfo_set($user, "subscriptions", $subscriptions);
58 }
59
60 # Called by other plugins to subscribe the user to a pagespec.
61 sub subscribe ($$) {
62         my $user=shift;
63         my $addpagespec=shift;
64         my $pagespec=getsubscriptions($user);
65         setsubscriptions($user, $pagespec." or ".$addpagespec);
66 }
67
68 sub notify (@) {
69         my @files=@_;
70         return unless @files;
71
72         eval q{use Mail::Sendmail};
73         error $@ if $@;
74         eval q{use IkiWiki::UserInfo};
75         error $@ if $@;
76
77         # Daemonize, in case the mail sending takes a while.
78         #defined(my $pid = fork) or error("Can't fork: $!");
79         #return if $pid; # parent
80         #chdir '/';
81         #open STDIN, '/dev/null';
82         #open STDOUT, '>/dev/null';
83         #POSIX::setsid() or error("Can't start a new session: $!");
84         #open STDERR, '>&STDOUT' or error("Can't dup stdout: $!");
85
86         # Don't need to keep a lock on the wiki as a daemon.
87         IkiWiki::unlockwiki();
88
89         my $userinfo=IkiWiki::userinfo_retrieve();
90         #exit 0 unless defined $userinfo;
91
92         foreach my $user (keys %$userinfo) {
93                 my $pagespec=$userinfo->{$user}->{"subscriptions"};
94                 next unless defined $pagespec && length $pagespec;
95                 my $email=$userinfo->{$user}->{email};
96                 next unless defined $email && length $email;
97                 print "!!$user\n";
98
99                 foreach my $file (@files) {
100                         my $page=pagename($file);
101                         print "file: $file ($page)\n";
102                         next unless pagespec_match($page, $pagespec);
103                         my $content="";
104                         my $showcontent=defined pagetype($file);
105                         if ($showcontent) {
106                                 $content=eval { readfile(srcfile($file)) };
107                                 $showcontent=0 if $@;
108                         }
109                         my $url;
110                         if (! IkiWiki::isinternal($page)) {
111                                 $url=urlto($page, undef, 1);
112                         }
113                         elsif (defined $pagestate{$page}{meta}{permalink}) {
114                                 # need to use permalink for an internal page
115                                 $url=$pagestate{$page}{meta}{permalink};
116                         }
117                         else {
118                                 $url=$config{wikiurl}; # crummy fallback url
119                         }
120                         my $template=template("notifyemail.tmpl");
121                         $template->param(
122                                 wikiname => $config{wikiname},
123                                 url => $url,
124                                 prefsurl => IkiWiki::cgiurl(do => "prefs"),
125                                 showcontent => $showcontent,
126                                 content => $content,
127                         );
128                         #translators: The two variables are the name of the wiki,
129                         #translators: and a page that was changed.
130                         #translators: This is used as the subject of an email.
131                         my $subject=sprintf(gettext("%s: change notification for %s"),
132                                 $config{wikiname}, $page);
133                         sendmail(
134                                 To => $email,
135                                 From => "$config{wikiname} <$config{adminemail}>",
136                                 Subject => $subject,
137                                 Message => $template->output,
138                         );
139                 }
140         }
141
142         #exit 0; # daemon child
143 }
144
145 1