Боремся со спамом в MediaWiki. Часть 2
Jun. 26th, 2013 10:59 amСм. также ч.1
Какая бы крутая у нас не стояла бы каптча, боты все равно круче, сколько-то из них прорвуться.
При этом есть один нюанс... Для того чтобы сделать спамовый пост, нужно сквозь каптчу прораваться дважды: сначала зарегистрировать пользователя, а потом уже от его имени создать статью...
Через такую двойную линию обороны пробираются не многие, но от частичного преодаления получается неприятный эффект: куча спамовый пользователей, который по своей сути безвредны, к ним боты редко когда возвращаются, но пространство захламляют...
Для больбы с этим эффектом я написал специальный скрипт, который в автоматическом режиме удаляет всехпользователей не сделавших ни одной правки, а о всех прчих правках сделанных за последние сутки сообщает администратору прямой ссылкой на удаление :-)
Предполагается, что скрипт этот прописан в cron'е на запуск раз в сутки, и что там же в corn'е правильно выставленна переменная MAILTO= заворачивающая весь STDOUT и STDERR вам на почту
Какая бы крутая у нас не стояла бы каптча, боты все равно круче, сколько-то из них прорвуться.
При этом есть один нюанс... Для того чтобы сделать спамовый пост, нужно сквозь каптчу прораваться дважды: сначала зарегистрировать пользователя, а потом уже от его имени создать статью...
Через такую двойную линию обороны пробираются не многие, но от частичного преодаления получается неприятный эффект: куча спамовый пользователей, который по своей сути безвредны, к ним боты редко когда возвращаются, но пространство захламляют...
Для больбы с этим эффектом я написал специальный скрипт, который в автоматическом режиме удаляет всехпользователей не сделавших ни одной правки, а о всех прчих правках сделанных за последние сутки сообщает администратору прямой ссылкой на удаление :-)
Предполагается, что скрипт этот прописан в cron'е на запуск раз в сутки, и что там же в corn'е правильно выставленна переменная MAILTO= заворачивающая весь STDOUT и STDERR вам на почту
#!/usr/bin/perl
use strict;
my $db_host = 'localhost';
my $db_name = '########';
my $db_user = '##########';
my $db_password = '#####################';
my $cache_dir = '/.bots/cache'; # Директория для храняния всякой нужной фигни
my $prefix = 'mw_'; # префикс имен таблиц MediaWiki. Часто 'mv_' или пустой
my $www_host = "http://wiki.##########.ru"; # www host по которому доступна wiki из интернета (для формирования ссылок на удаление)
my $timestamp_file = "$cache_dir/$db_name.db_timestamp";
my $name_spaces = {
0 => "",
2 => "User:",
3 => "User_Talk:",
};
# удаляем всех пользователей у которых не было ни одной правки
do_query("delete from ${prefix}user where user_name not in (select distinct rev_user_text from ${prefix}revision );");
# удаляем все упоминания об удаленных пользователях из recent changes
do_query("delete from ${prefix}recentchanges where rc_log_type = \"newusers\" and rc_log_action=\"create\" and rc_user not in (select user_id from ${prefix}user)");
my $present_timestamp = do_query("select max(rc_timestamp) from ${prefix}recentchanges;");
$present_timestamp =~ s/^.*?\n//s;
chomp $present_timestamp;
my $last_timestamp = undef;
if (-e $timestamp_file)
{
$last_timestamp = `cat $timestamp_file`;
chomp $last_timestamp;
$last_timestamp = undef unless $last_timestamp =~ /^\d*$/;
}
$last_timestamp = $present_timestamp - 60*60*24+300 unless $last_timestamp;
# Собираем данные о правках сулчившихся за последние сутки
my $changes = do_query("select rc_user_text, rc_title, rc_namespace, rc_log_type, rc_log_action from ${prefix}recentchanges where rc_timestamp > $last_timestamp and (rc_log_type not in (\"delete\", \"block\", \"newusers\") or rc_log_type is null) ");
if ($changes)
{
print "New changes at $www_host were made this day:\n\n";
$changes=~s/^rc_user_text\trc_title\trc_namespace\trc_log_type\trc_log_action\n//s;
foreach (split "\n",$changes)
{
my($rc_user_text,$rc_title,$rc_namespace,$rc_log_type,$rc_log_action) = split("\t",$_);
my $namespace = $name_spaces->{$rc_namespace} // "??????:";
print "$rc_user_text\tdid\t$rc_log_type\t $rc_log_action on page\t$namespace$rc_title:\t$www_host/index.php?action=delete&title=$namespace$rc_title\n";
}
`echo $present_timestamp > $timestamp_file `;
}
sub do_query
{
my $query = shift;
return `mysql $db_name -h $db_host -u $db_user -p$db_password -e '$query';`
}
# 41001103370866 - не забудте кинуть монетку на яндекс деньги :-))