#!/usr/bin/perl -w # # Auto-magically closes MovableType entries to comments # using a simple sql query. # # Meant to be used from a cron-job, or a one time run, or, best, not at all. # #================================================== # Stuff to configure (See also args) #================================================== # Don't actually do anything, just pretend and report # what would have been done -- fake it. # my $fake = 0; # Close entries older than these many days (int) # my $days_back = 15; # disable trackbacks as well as comments # my $trackbacks = 0; # Database connection information # my $database_type = "mysql"; my $database_name = "blog"; my $database_user = "brunhilda"; my $database_pass = "password"; my $database_host = "localhost"; # These are the mt defaults, probably best if left alone. # my $mt_entry = "mt_entry"; my $entry_created_on = "entry_created_on"; my $entry_allow_comments = "entry_allow_comments"; my $entry_allow_pings = "entry_allow_pings"; my $close_comments_val = "2"; my $close_pings_val = "0"; #================================================== # Nothing to configure below #================================================== use Carp; use DBI; use strict; my $dbh = undef; # parse arguments and stuff # while(@ARGV) { my $arg = shift @ARGV; if ($arg =~ m/^-h$/) { &usage(); } if ($arg =~ m/^-f$/) { $fake = 1; } elsif ($arg =~ m/^-t$/) { $trackbacks = 1; } elsif ($arg =~ m/^--days=(.\d+)$/) { $days_back = $1; } elsif ($arg =~ m/^--db-type=(.+)$/) { $database_type = $1; } elsif ($arg =~ m/^--db-host=(.+)$/) { $database_host = $1; } elsif ($arg =~ m/^--db-user=(.+)$/) { $database_user = $1; } elsif ($arg =~ m/^--db-pass=(.+)$/) { $database_pass = $1; } elsif ($arg =~ m/^--db-name=(.+)$/) { $database_name = $1; } else { &usage("Invalid argument: $arg"); } } die &usage("$0: days back '$days_back' is not a number") unless ($days_back =~ /^\d+$/); &connect; my $time = time() - ($days_back * 24 * 60 * 60); my $year = (localtime($time))[5] + 1900; my $month = (localtime($time))[4] + 1; my $day = (localtime($time))[3]; # this works in mysql, dunno about other mt databases. # my $query_time = "$year$month$day"; my $count = &sqlSelect("count(*)", $mt_entry, "$entry_created_on < $query_time and $entry_allow_comments != $close_comments_val"); if($fake) { print STDERR "Would have updated $count entries to disallow comments.\n"; } else { &sqlUpdate($mt_entry, {$entry_allow_comments, $close_comments_val}, "$entry_created_on < $query_time"); } if($trackbacks) { $count = &sqlSelect("count(*)", $mt_entry, "$entry_created_on < $query_time and $entry_allow_pings != $close_pings_val"); if($fake) { print STDERR "Would have updated $count entries to disallow trackbacks.\n"; } else { &sqlUpdate($mt_entry, {$entry_allow_pings, $close_pings_val}, "$entry_created_on < $query_time"); } } $dbh->disconnect if $dbh; exit 0; sub connect { my $drh = DBI->install_driver($database_type); $dbh = &db_connect($database_name, $database_user, $database_pass, $database_host, $database_type); } sub db_connect { my $database = shift; my $user = shift; my $password = shift; my $host = shift; my $db_type = shift; my $h = DBI->connect("DBI:$db_type:database=$database;hostname=$host", $user, $password); if (!$h) { die("Unable to connect to $database", $DBI::errstr); return 0; } else { return $h; } } sub sqlSelect { my ($select, $from, $where, $other)=@_; my $sql="SELECT $select "; $sql.="FROM $from " if $from; $sql.="WHERE $where " if $where; $sql.="$other" if $other; my $c=$dbh->prepare($sql) or die "DB connection died\n"; if(not $c->execute()) { return undef; } my @r = $c->fetchrow(); $c->finish(); return wantarray ? @r : $r[0]; } sub sqlUpdate { my ($table, $data, $where) = @_; my $sql="UPDATE $table SET"; foreach (keys %$data) { if (/^-/) { s/^-//; $sql.="\n $_ = $$data{-$_} "; } else { $sql.="\n $_ = ".$dbh->quote($$data{$_}).","; } } chop($sql); $sql.="\nWHERE $where\n"; if(!$dbh->do($sql)) { $sql =~ s/\n/ /g; my $err = "FAILED:" . $sql . " " . $dbh->errstr; print STDERR $err; &do_exit(1); } } sub usage { warn "@_\n" if @_; die "usage: $0 [options]\n", "options are\n", " -f Fake mode - don't actually do anything, just\n", " provide feedback on what would have been done.\n", " -h Print usage and exit.\n", " -t Close trackbacks too.\n", " --days=num Close entries older than these many days (default $days_back).\n", " --db-type=type Type of database default is $database_type\n", " --db-host=host Database host default is $database_host\n", " --db-user=user Database user name\n", " --db-pass=pass Database password\n", "\n", "This script closes movable type entries to comments and trackbacks with a simple\n", "SQL query.\n", "\n", "This is meant to be used from a cron job, sample cron entry:\n", "# Close movable type entries that are older than 15 days to comments once a day at 4am.\n", "#\n", "0 4 * * * $0\n"; }