#!/usr/bin/perl use strict; use lib "$ENV{LJHOME}/cgi-bin"; use Getopt::Long; require "ljlib.pl"; use LJ::ExtBlock; ## ## This script subscribes SUP users to e-mail notifications ## from 'ru_news' community ## my $verbose = 0; my @sub_methods = qw(Email Inbox); my @sub_events = qw(SupOfficialPost); my @flt_methods = qw(Email Inbox); my @flt_events = qw(OfficialPost); my @uns_methods = qw(Email Inbox); my @uns_events = qw(); my $our_user = ''; my $run = 0; my $chunk_size = 1000; my $continue = 0; my ($total, $subscribed, $unsubscribed, $already, $processed) = (0, 0, 0, 0, 0); parseOptions() && doit(); sub parseOptions { my $help = 0; my $sub_methods = join(',', @sub_methods); my $sub_events = join(',', @sub_events); my $flt_methods = join(',', @flt_methods); my $flt_events = join(',', @flt_events); my $uns_methods = join(',', @uns_methods); my $uns_events = join(',', @uns_events); unless (GetOptions( "smethods=s" => \$sub_methods, "sevents=s" => \$sub_events, "fmethods=s" => \$flt_methods, "fevents=s" => \$flt_events, "umethods=s" => \$uns_methods, "uevents=s" => \$uns_events, "user=s" => \$our_user, "help" => \$help, "verbose=n" => \$verbose, "chunk=i" => \$chunk_size, "continue" => \$continue, "run" => \$run, ) && !$help) { print < user); -chunk chunk size (now set to: $chunk_size); -continue continue from last processed userid; -run do real work, not just search and print statistics, without this option real database will not be updated. EOT return 0; } @sub_methods = split(',', $sub_methods); @sub_events = split(',', $sub_events); @flt_methods = split(',', $flt_methods); @flt_events = split(',', $flt_events); @uns_methods = split(',', $uns_methods); @uns_events = split(',', $uns_events); # TODO: Check events and methods. return 1; } sub doit { # Clean old error message. LJ::ExtBlock->delete('subscribe.error_msg') if $run; my $start_id = 0; if ($continue) { my $ext_block = LJ::ExtBlock->load_by_id('subscribe.start'); $start_id = ($ext_block->blocktext || 0) if $ext_block; } if ($verbose > 1) { print " id\tname\t\t\tstatus\n"; print "-----\t----------------\t------------\n"; } my $readed = 0; eval { while (my $uids = get_users($start_id, $chunk_size)) { last unless @$uids; $readed += scalar @$uids; print "Chunk of $readed user(s) readed in\n" if $verbose == 1; LJ::start_request(); # cleanup caches my $users = LJ::load_userids(@$uids); # hashref, id -> user-object foreach my $uid (@$uids) { process_user($uid, $users->{$uid}) if $users->{$uid}; print "\n" if $verbose > 1; $start_id = $uid if $uid > $start_id; LJ::ExtBlock->create_or_replace('subscribe.start', $start_id) if $run; } } }; if ($@) { LJ::ExtBlock->create_or_replace('subscribe.error_msg', $@) if $run; warn $@; } print "-----\t----------------\t------------\n" if $verbose > 1; if ($verbose) { print "--------- Statistics ---------\n"; print "Accounts:\n"; print "Total:\t\t\t$total\n"; print "Total subscribed:\t$subscribed\n"; print "Subscribed before:\t$already\n"; print "Unsubscribed now:\t$unsubscribed\n"; print "Processed now:\t\t$processed\n"; print "------------------------------\n"; } print "It was a dry run, without -run option.\n" unless $run; } sub process_user { my $userid = shift; my $u = shift; my $user = $u->user; my $f; $total++; printf "%5d\t%-16s\t", $userid, $user if $verbose > 1; # Check if this user is not subscribed yet foreach my $sub_event (@sub_events) { foreach my $sub_method (@sub_methods) { if ($u->has_subscription( method => $sub_method, event => $sub_event, )) { $already++; $subscribed++; print "already subscribed " if $verbose > 1; return; } } } # Check if this user is subscribed to filter events if (scalar @flt_events && scalar @flt_methods) { foreach my $flt_event (@flt_events) { foreach my $flt_method (@flt_methods) { unless ($u->has_subscription( method => $flt_method, event => $flt_event, )) { print "not subscribed ($flt_event,$flt_method) " if $verbose > 1; return; } } } } # Check if there is --user option and it is 'our' user if ($our_user && $our_user ne $u->user) { print "not our user" if $verbose > 1; return; } # Now subscribe. $f = 0; if (scalar @sub_events && scalar @sub_methods) { foreach my $sub_event (@sub_events) { foreach my $sub_method (@sub_methods) { $u->subscribe( method => $sub_method, event => $sub_event, ) if $run; $f = 1; } } if ($f) { $subscribed++; print "subscribed " if $verbose > 1; } } # Unsubscribe $f = 0; if (scalar @uns_events && scalar @uns_methods) { foreach my $uns_event (@uns_events) { foreach my $uns_method (@uns_methods) { my @subs = $u->has_subscription( method => $uns_method, event => $uns_event, ); if (@subs) { foreach my $sub (@subs) { $sub->delete if $run; $f = 1; } } } } if ($f) { $unsubscribed++; print "unsubscribed " if $verbose > 1; } } $processed++; } # TODO: It must be in API. sub get_users { my $start = shift; my $chunk_size = shift; my $db = LJ::get_dbh("slow") or die "Cannot get DB reader"; my $rows = $db->selectcol_arrayref( "SELECT userid ". "FROM user ". "WHERE (caps & 1024) = 1024 AND (caps & 2048) = 0 ". "AND journaltype = 'P' ". "AND userid > ? ORDER BY userid LIMIT $chunk_size", undef, $start); if (not $rows or $db->err) { die $db->errstr; } return $rows; }