Files
oddmuse/scripts/unsubscribe.pl

121 lines
3.2 KiB
Perl
Raw Permalink Normal View History

#! /usr/bin/perl
# Copyright (C) 20102021 Alex Schroeder <alex@gnu.org>
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
=head1 NAME
unsubscribe.pl - mass unsubscribe from Oddmuse
=head2 SYNOPSIS
B<perl unsubscribe.pl> F<MAILDB> [B<--regexp=>I<REGEXP>]
B<perl unsubscribe.pl> F<MAILDB> [B<--dump>]
=head2 DESCRIPTION
If you use the Mail Extension to Oddmuse, you end up with subscriptions to very
old pages. This script helps you unsubsribe people from old pages.
C<--regexp> indicates a regular expression matching pages names
The mandatory F<MAILDB> argument is the file containing all the mail
subscriptions.
=head2 EXAMPLES
Make a copy, unsubscribe people, check a dump of the remaining subscriptions,
and move the file back to the wiki data directory.
cp ~/alexschroeder/mail.db copy.db
perl ~/src/oddmuse/scripts/unsubscribe.pl copy.db --regexp='20[01][0-9]'
perl ~/src/oddmuse/scripts/unsubscribe.pl copy.db --dump
mv copy.db ~/alexschroeder/mail.db
=cut;
use Modern::Perl;
use Getopt::Long;
use Encode qw(encode_utf8 decode_utf8);
use DB_File;
binmode(STDOUT, ":utf8");
my $re = "";
my $confirm;
my $dump;
GetOptions ("regexp=s" => \$re,
"dump" => \$dump,
"confirm" => \$confirm, );
my $file = shift;
die "Not a file: $file" unless -f $file;
die "Unknown arguments: @ARGV" if @ARGV;
sub UrlEncode {
my $str = shift;
return '' unless $str;
my @letters = split(//, encode_utf8($str));
my %safe = map {$_ => 1} ('a' .. 'z', 'A' .. 'Z', '0' .. '9', '-', '_', '.', '!', '~', '*', "'", '(', ')', '#');
foreach my $letter (@letters) {
$letter = sprintf("%%%02x", ord($letter)) unless $safe{$letter};
}
return join('', @letters);
}
sub UrlDecode {
my $str = shift;
return '' unless $str;
$str =~ s/%([0-9a-f][0-9a-f])/chr(hex($1))/eig;
return decode_utf8($str);
}
tie my %h, "DB_File", $file;
my $FS = "\x1e";
if ($dump) {
for my $key (keys %h) {
my @value = split /$FS/, UrlDecode($h{$key});
say UrlDecode($key), ": @value";
}
exit;
}
for my $raw (keys %h) {
if ($raw =~ /@/) {
# email address
my $mail = UrlDecode($raw);
my $value = $h{$raw};
my @subscriptions = grep !/$re/, map { UrlDecode($_) } split /$FS/, $value;
if (@subscriptions) {
$h{$raw} = join $FS, map { UrlEncode($_) } @subscriptions if $confirm;
say "> $mail: remains subscribed to @subscriptions";
} else {
delete $h{$raw} if $confirm;
say "> $mail: unsubscribe from all pages";
}
} else {
my $id = UrlDecode($raw);
next unless $id =~ /$re/;
delete $h{$raw} if $confirm;
say "Delete $id";
}
}
untie %h;
say "Use --confirm to actually do it" unless $confirm;