Участник:FedyaBot/По стопам Константина Устиновича
Материал из Викиреальностя
«По стопам Константина Устиновича» — моя основная работа. Я был так вдохновлён, как он показывает свои фокусы с хранилищем даты в Малом Цирке, исправляя сразу много карточек с датами, что решил повторить его успех своею собственною работаю. К сожалению, я не возжелал возехаться с отвратной вещью жабий язык, разобраться в которой можно только, будучи не совсем в себе… Я решил написать своё сочинение на классическом языке, и мои методы действовали — помешала только лень с карточками. Я надеюсь, кто-то повторит мой путь, полный лишений, постов и самобичеваний.
Я хочу верить — найдётся хороший приемник.
Содержание |
[править] Глава 1. Бутовская птицеферма в г. Томске
#! /usr/bin/perl
# {{autoupdated infobox}}
use utf8;
use MediaWiki::API;
use Encode;
use Switch;
use lib qw(./lib);
use wiki_functions;
use web_functions;
require "lib/wiki_variables.pl";
require "confa/bot_config.pl";
write_log("$ \nНачато исполнение скрипта");
my $home_api = 'http://wikireality.ru/w/api.php';
my $username = $bot_config::usernames{'wr'}; my $password = $bot_config::passwords{'wr'};
my $home = MediaWiki::API->new({ api_url => $home_api });
$home->{ua}->agent($bot_config::home_agent{'updater'});
$home->login({ lgname => $username, lgpassword => $password }) || die "Вали откуда пришёл, Царь гневается: $home->{error}->{details}.\n";
my %languages = %wiki_variables::languages;
my %months = %wiki_variables::months;
my $tasks;
my ($i, $a, $string, $api);
my $ret = $home->api({ action => 'query', list => 'categorymembers', cmtitle => 'Категория:Статьи_для_автоматического_обновления', cmnamespace => '0',
cmtype => 'page', cmlimit => '5000', cmsort => 'sortkey', cmprop => 'title|sortkeyprefix' })
|| die "Ошибка получения содержимого категории со статьями для обновления: $home->{error}->{details}.\n";
foreach $i(@{$ret->{query}->{categorymembers}}) # to-do - fuck off api query limit.
{
my $sortkey = $i->{sortkeyprefix};
if(length(encode_utf8($sortkey)) > 200 )
{
my $result = $home->api({ action => 'parse', page => $i->{title}, prop => 'categories' })
|| write_log(sprintf("Ошибка получения содержимого для страницы %s - %s",$i->{title},$home->{error}->{details}));
$sortkey = $result->{parse}->{categories}[0]->{sortkey};
}
my @parts = split(/:/, $sortkey);
my $prefix = $parts[0];
$tasks->{$prefix}->{$i->{title}} = $parts[1];
}
# Обновление статей про участников вики-проектов
foreach my $user(keys %{$tasks->{user}})
{
my (@editcount, @userpages, @groups, @registration, $sign, @babel,
@city, $birth, $usertools, $wikitext, $category, @proj, @nickname);
my @splitted = split(/,/, $tasks->{user}->{$user});
for($i = 0; $i < scalar @splitted; $i++)
{
$string = $splitted[$i];
if($string =~ m/(.*?)\[(.*?)\]/)
{
$proj[$i] = $1;
$nickname[$i] = $2;
}
else
{
$proj[$i] = $string;
$nickname[$i] = $user;
}
}
for($i = 0; $i < scalar @proj; $i++)
{
my $url = api_url($proj[$i]);
unless($url)
{
write_log(sprintf("Не удалось получить адрес API для проекта %s (участник %s)",$proj[$i],$nickname[$i]));
next;
}
my $pname = project_name($proj[$i]);
my $domain = $url;
$domain =~ s/http:\/\/(.*?)\/(.*)/$1/i;
$api = security_api($domain, $url);
unless($api)
{
write_log(sprintf("Не удалось получить объект API для домена %s (участник %s)",$domain,$nickname[$i]");
next;
}
my $username = $nickname[$i];
my $res = $api->api({ action => 'query', list => 'users', usprop => 'groups|editcount|registration', ususers => $username })
|| write_log("Ошибка получения данных об участнике $nickname[$i]: $api->{error}->{details}");
if($res && $res->{query} && $res->{query}->{users}[0])
{
my $info = $res->{query}->{users}[0];
if(!$info->{missing} && $info->{editcount})
{
push(@editcount, sprintf("%s (%s)",round($info->{editcount}),$pname));
my $groups_arr = $info->{groups};
my @g = ();
foreach my $gr(@$groups_arr)
{
next if $gr =~ m/^(\*|filemover|user|autoconfirmed|uploader)$/i;
push(@g, flag_name($gr,$proj[$i]));
}
push(@groups, join(', ', @g) . " (" . $pname . ")") if(@g);
$res = $api->api({
action => 'query', list => 'usercontribs', uclimit => 1, ucuser => $username, ucdir => 'newer', ucprop => 'timestamp'
}) || write_log("Ошибка запроса вклада участника " . $info->{name} . " в " . $proj[$i] . " " . $api->{error}->{details});
my $first = convert_time($res->{query}->{usercontribs}[0]->{timestamp});
if($info->{registration} && $first eq convert_time($info->{registration}))
{
push(@registration, convert_time($info->{registration}) . " (" . $pname . ")");
}
elsif($info->{registration} && $first ne convert_time($info->{registration}))
{
push(@registration, convert_time($info->{registration}) . ", первая правка " . $first . " (" . $pname . ")");
}
else
{
push(@registration, "неизвестно, первая правка " . $first . " (" . $pname . ")");
write_log("Не удалось получить дату регистрации для " . $info->{name} . " в " . $proj[$i] . ": возможно, зарегистрирован ранее создания журналов");
}
}
}
$res = $api->api({ action => 'query', prop => 'info', titles => 'User:' . $username })
|| write_log("Ошибка получения информации о странице User:" . $username . ": " . $api->{error}->{details});
my $missing = exists((values %{$res->{query}->{pages}})[0]->{missing});
push(@userpages, external_page($proj[$i], $missing ? 'Special' : 'User', $missing ? 'Contributions/' . $username : $username, $i == 0 ? ucfirst($pname) : $pname));
if($i == 0)
{
$res = $api->api({ action => 'query', list => 'usercontribs', uclimit => '1', ucuser => $username, ucnamespace => '3', ucprop => 'ids|title' })
|| write_log("Ошибка получения вклада участника $nickname[$i] в $proj[$i]: " . $api->{error}->{details});
if($res->{query}->{usercontribs}[0])
{
my $lastpage = $res->{query}->{usercontribs}[0]->{title};
$res = $api->api({ action => 'query', prop => 'revisions', titles => $lastpage, rvlimit => '1', rvuser => $username, rvprop => 'content' })
|| write_log("Ошибка получения последней правки участника $nickname[$i] в $proj[$i]: " . $api->{error}->{details});
if($res && $res->{query})
{
my $diff = (values %{$res->{query}->{pages}})[0]->{revisions}[0]->{'*'};
$sign = $2 if($diff =~ m/\[\[(User|Участник):$username\|(.*?)\]\]/i && $2 ne $username);
}
}
}
if($proj[$i] eq 'ruwiki')
{
my $userpage = "Участник:$username";
$res = $api->api({ action => 'parse', prop => 'categories', page => $userpage })
|| write_log("Ошибка получения категорий для $nickname[$i] в ruwiki: " . $api->{error}->{details});
if($res->{parse}->{categories})
{
my $categories = $res->{parse}->{categories};
for($a = 0; $a < scalar @$categories; $a++)
{
$category = $categories->[$a]->{'*'};
if($category =~ m/Участники_из_.*/i)
{
$res = $api->api({ action => 'parse', prop => 'wikitext', page => 'Категория:' . $category })
|| write_log("Ошибка получения викитекста для $catpage: " . $api->{error}->{details});
if($res->{parse}->{wikitext}->{'*'})
{
$wikitext = $res->{parse}->{wikitext}->{'*'};
push(@city, $1) if ($wikitext =~ m/\[\[Категория\:Википедия\:Участники по.*?\|(.*?)\]\]/i);
}
}
elsif($category =~ m/User_([a-z][a-z][a-z]?-N?[0-5]?)/i)
{
push(@babel, $1);
}
}
$res = $api->api({ action => 'parse', prop => 'wikitext', page => $userpage })
|| write_log("Ошибка получения викитекста для $userpage: " . $api->{error}->{details});
if($res->{parse}->{wikitext}->{'*'})
{
$wikitext = $res->{parse}->{wikitext}->{'*'};
my $m;
if($wikitext =~ m/(Участник|User)\:Box\/Родился\|(день=)?(.*?)\|(месяц=)?(.*?)\|(год=)?(.*?)}}/i)
{
$m = length($5) == 1 ? '0' . $5 : $5;
$birth = $3 . ' ' . $months{$m} . ' ' . $7;
}
elsif(!$m && $wikitext =~ m/(Участник|User)\:Box\/Родился\|(день=)?(.*?)\|(месяц=)?(.*?)}}/i)
{
$m = length($5) == 1 ? '0' . $5 : $5;
$birth = $3 . ' ' . $months{$m};
}
}
}
$usertools .= '{{usertools|ruwiki|' . $username . '}}';
}
}
if(@userpages)
{
my $out = '{{#switch: {{{1|}}}' . "\n";
$out .= '|Число правок=' . join(' + ', @editcount) . "\n" if(@editcount);
$out .= '|Личные страницы=' . join('<br />', @userpages) . "\n" if(@userpages);
$out .= '|Права участника=' . join('<br />', @groups) . "\n" if(@groups);
$out .= '|Начало участия=' . join('<br />', @registration) . "\n" if(@registration);
$out .= '|Подпись=' . $sign . "\n" if($sign);
$out .= '|Знание языков=' . join(', ', @babel) . "\n" if(@babel);
$out .= '|Город=' . join(', ', @city) . "\n" if(@city);
$out .= '|День рождения=' . $birth . "\n" if($birth);
$out .= '|Инструменты=' . join(' · ', $usertools) . "\n" if($usertools);
$out .= '}}';
$home->edit({
action => 'edit', title => 'Data:User:' . $user, text => $out, minor => 1, bot => 1,
summary => '[[Project:Updater|Updater]]: Обновление информации для шаблона-карточки участника'
}) || write_log("Ошибка записи страницы информации для user - $user: " . $home->{error}->{details});
write_log("Элемент {user}->" . $user . " обработан");
}
}
# Обновление статей про вики-проекты на движке MediaWiki
foreach my $site(keys %{$tasks->{wiki}}) {
my ($engine, $founded, $articles, $pages,
$users, $activity,
$logo, $license, $tcy, $pr,
$api, $api_url, $res, $status);
my @data = split(/,/, $tasks->{wiki}->{$site});
my $domain = $data[0]; my $code = $data[1];
my $fullurl = 'http://' . $domain . '/';
$api_url = api_url($code) if($code);
$api_url = 'http://' .url . '/w/api.php' if(!$api_url);
$api = security_api($domain, $api_url);
$res = $api->api({ action => 'query', meta => 'siteinfo' }) if($api);
if($res->{query}) {
$status = 'ok';
} else {
$api_url = 'http://' .url . '/api.php';
$api = security_api($domain, $api_url);
$res = $api->api({ action => 'query', meta => 'siteinfo' }) if($api);
$status = 'ok' if($res && $res->{query});
}
if($status eq 'ok') {
$engine = 'MediaWiki';
# Не работает из-за проблем с HTTP::Message.
# my $file_url = logo_url($fullurl);
# my $file_name = 'Лого_' . $site . '.' . ext($file_url);
# $status = mw_upload($home, $file_name, $file_url, 'Логотип для вики-проекта ' . $site, undef);
# $status eq 'done' ? $logo = '[[File:' . $file_name . '|135px|center]]' : write_log($status);
$res = $api->api({ action => 'query', meta => 'siteinfo', siprop => 'statistics' });
if($res->{query}) {
my $stats = $res->{query}->{statistics};
$articles = round($stats->{articles});
$pages = round($stats->{pages});
$users = round($stats->{users}) . ' (' . round($stats->{activeusers}) . ' активных)';
my $c = 0; undef $status;
while($status ne 'ok') {
$c++;
if($c > 50) {
write_log("Не удалось получить первые " . $c-1 . " правок для " . $domain);
last;
}
$res = $api->api({ action => 'query', prop => 'revisions', revids => $c, rvprop => 'timestamp|ids' });
if($res->{query}->{pages}) {
my $rev = (values %{$res->{query}->{pages}})[0]->{revisions}->[0]->{timestamp};
if($rev) {
$founded = convert_time($rev);
$status = 'ok';
}
}
}
$founded .= ' (' . $c . ' правка)' if($founded && $c != 1);
}
# Тестировать:
my $info = element_by_id($fullurl . 'wiki/Special:Random', 'copyright');
switch($info) {
case /GNU FDL/ { $license = 'GFDL'; }
case /CC-BY-SA 3.0/ { $license = 'CC-BY-SA 3.0'; }
}
} else {
write_log("Не удалось получить объект API для вики-проекта " . $domain);
}
$tcy = site_tcy($fullurl);
$pr = site_pr($domain);
my $out = '{{#switch: {{{1|}}}' . "\n";
$out .= '|URL=[' . $fullurl . ' ' . $domain . ']';
$out .= '|Логотип=' . $logo . "\n" if($logo);
$out .= '|Дата основания=' . $founded . "\n" if($founded);
$out .= '|Название движка=' . $engine . "\n" if($engine);
if($articles) {
$out .= '|Число статей=' . $articles . "\n";
$out .= '|Число страниц=' . $pages . "\n";
$out .= '|Число участников=' . $users . "\n";
}
$out .= '|Лицензия=' . $license . "\n" if($license);
$out .= '|тИЦ=' . $tcy . "\n" if($tcy);
$out .= '|PR=' . $pr . "\n" if($pr);
$out .= '}}';
$home->edit({
action => 'edit', title => 'Data:Wiki:' . $site, text => $out, minor => 1, bot => 1,
summary => '[[Project:Updater|Updater]]: Обновление информации для шаблона-карточки вики-проекта'
}) || write_log("Ошибка записи страницы информации для wiki - $site: " . $home->{error}->{details});
write_log("Элемент {wiki}->" . $site . " обработан");
}
write_log("Исполнение скрипта завершено");
sub write_log {
my $line = shift;
my $time = timestamp(time());
$line = $time . ": " . $line . ".\n";
open(LOG, ">>update_data.log");
binmode LOG, ':utf8';
print LOG "$line";
close(LOG;
}
[править] Глава 2. Пароли и явки
Мои пароли и явки были записаны на отдельной бумажке.
#! /usr/bin/perl
package bot_config;
use utf8;
our %usernames = ('wr' => 'FedyaBot','cw' => 'FedyaBot');
our %passwords = ('wr' => 'daposhlivsenahuisindeikoy','cw' => 'pizdecgolovavcirkeveshaet');
our %home_agent = ('updater' => 'MediaWikiBot/0.37 Wiki-infobox updater/1.0');
our %fake_agent = ('updater' => 'Mozilla/5.0 (Windows; U; Windows NT 6.1; fr; rv:1.9.2.22) Gecko/20110902 Firefox/3.6.22');
our $open_proxy = 'http://64.90.37.42:16522/';
1;
[править] Глава 3. Обработка паутины
#! /usr/bin/perl
package web_functions;
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(element_by_id site_security secure_www site_tcy site_pr ext round);
use utf8;
use Switch;
use LWP::UserAgent;
use HTML::TreeBuilder;
use wiki_functions;
use lib qw(/home/script/perl/conf);
require "bot_config.pl";
1;
sub element_by_id
{
my ($url, $id) = @_;
return undef unless($url || $id);
my $ua = secure_www($url);
return undef unless($ua);
my $res = $ua->get($url);
if($res->is_success())
{
my $content = $res->content();
my $parser = HTML::TreeBuilder->new_from_content($content);
my $node = $parser->look_down("id" => $id);
if($node)
{
$node = $node->as_XML();
chomp($node);
$node =~ s/^<.*?id=["']$id["'].*?>(.*)<\/.*?>$/$1/;
return $node;
}
}
return undef;
}
sub site_security
{
my $url = shift;
return undef unless($url);
unless(is_secure($url))
{
switch($url)
{
case /^([a-z0-9_-]+)?\.livejournal\.com$/ { return 'secure'; }
else { return undef; }
}
}
return $level;
}
sub secure_www
{
my $url = shift;
return undef unless($url);
$url =~ s/^http:\/\/([a-z]+\.)?([a-z]+\.)?([a-z0-9\-]+\.[a-z]+)\/.*$/$3/i;
my $ua;
my $agent = 'Robot (+http://wikireality.ru/wiki/Project:Updater)';
my $fake_agent = 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.17) Gecko/20110420 Firefox/3.6.17';
my $timeout = 50;
switch(site_security($url))
{
case 'secure'
{
$ua = LWP::UserAgent->new( agent => $agent, timeout => $timeout );
return $ua;
}
case 'medium'
{
$ua = LWP::UserAgent->new( agent => $agent, timeout => $timeout );
return $ua;
}
case 'insecure'
{
$ua = LWP::UserAgent->new( agent => $fake_agent, timeout => $timeout );
$ua->proxy('http', $bot_config::open_proxy);
return $ua;
}
else { return undef; }
}
}
# Похоже устарело, тр***ть восемь пианисток, яндексовые м**илы.
sub site_tcy
{
my $url = shift;
return undef if(!$url);
my $ua = LWP::UserAgent->new( agent => 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.17) Gecko/20110420 Firefox/3.6.17', timeout => 35 );
my $res = $ua->get('http://bar-navig.yandex.ru/u?ver=2&show=32&url=' . $url);
if($res->is_success())
{
$res = $res->content;
$res =~ s/\n//g;
$res =~ s/^.*value=["'](.*?)["'].*$/$1/;
return $res;
}
return undef;
}
sub site_pr
{
my $domain = shift;
return undef unless($domain);
my $res = element_by_id("http://pr-cy.ru/analysis/$domain", 'indicators-tbl');
return undef unless($res);
$res =~ s/\n//g;
$res =~ s/^.*PageRank <\/td><td valign="top"><b>(.*?)\/10.*$/$1/;
return $res;
}
sub ext
{
my $string = shift;
return undef unless($string);
$string =~ m/^.*\.([a-z]+)$/;
return $1;
}
sub round
{
my $int = shift;
return undef unless($int);
$int = sprintf("%.0f", $int);
if($int > 1100)
{
$int =~ m/^(.*?)([0-9])([0-9])([0-9])$/;
my($r3, $r4) = ($3, $4);
$r3 = $r4 > 4 ? $r3+1 : $r3;
$r3 = $r3 > 4 ? '5' : '0';
return sprintf("~ %s%S%s0",$1,$2,$r3);
}
elsif($int > 200)
{
$int =~ m/^(.*?)([0-9])([0-9])$/;
my($n2, $n3) = ($2, $3);
$n2 = $n3 > 4 ? $n2+1 : $n2;
return sprintf("~ %s%s0",$1,$n2);
}
else
{
return $int;
}
}
[править] Глава 4. Методы работы с вики
#! /usr/bin/perl
package wiki_functions;
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(is_secure security_api iwiki_link format_time project_name api_url flag_name convert_time timestamp external_page logo_url mw_upload);
use utf8;
use MediaWiki::API;
use Switch;
use web_functions;
use lib qw("C:\DmitryMedvedev\bot");
require "wiki_variables.pl";
require "bot_config.pl";
1;
sub is_secure
{
my $url = shift;
switch($url)
{
case /^([w]+\.)?[a-z]+\.wik(imedia|ipedia|tionary|isource|iquote|ibooks|iversity|inews)\.org/ { return 'secure'; }
case /^([w]+\.)?(wikireality\.ru|cyclowiki\.org|provizorii\.ru|mediawiki\.org|[a-z]+?\.[a-z0-9]+\.wikia\.com|wikilogia\.ru)/ { return 'secure'; }
case /^([w]+\.)?(traditio\.ru|wikifocus\.org|anticopyright\.ru|ejwiki\.org|lurkmore\.ru)/ { return 'medium'; }
case /^([w]+\.)?(absurdopedia\.net|[a-z]+\.pifia\.ru|miningwiki\.ru|starcraft-wiki\.ru|novopedia\.net)/ { return 'insecure'; }
else { return undef; }
}
}
sub security_api
{
my ($domain, $url) = @_;
switch(is_secure($domain))
{
case 'secure'
{
$api = MediaWiki::API->new({ api_url => $url });
$api->{ua}->agent($bot_config::home_agent{'updater'});
return $api;
}
case 'medium'
{
$api = MediaWiki::API->new({ api_url => $url });
$api->{ua}->agent($bot_config::home_agent{'updater'});
return $api;
}
case 'insecure'
{
$api = MediaWiki::API->new({ api_url => $url });
$api->{ua}->agent($bot_config::fake_agent{'updater'});
$api->{ua}->proxy('http', $bot_config::open_proxy);
return $api;
}
else { return undef; }
}
}
sub iwiki_link
{
my $code = shift;
switch($code)
{
case /^(lurk|lm)$/ { return 'lurk'; }
case /^(ac|kp|provizorii|absurd|commons|meta|mw)$/ { return $code; }
case /^(c|cw|cyclo|cp)$/ { return 'cw'; }
else
{
$code =~ m/([a-z_]+)wik([a-z_]+)/;
return undef unless($1 || $2);
my $i;
switch($2)
{
case 'i' { $i = 'w'; }
case /^(t|tionary)$/ { $i = 'wikt'; }
case 'iquote' { $i = 'q'; }
case 'ibooks' { $i = 'b'; }
case 'iversity' { $i = 'v'; }
case 'inews' { $i = 'n'; }
case 'isource' { $i = 's'; }
else { undef $i; }
}
return undef unless($i);
my $lang = $1;
return $i if($lang eq 'en');
return sprintf("%s:%s",$i,$lang);
}
}
}
# @_: 'ruwiki', 'User', 'Drbug', 'Русская Википедия' -> [[:w-ru:User:Drbug|Русская Википедия]]
sub external_page
{
my ($code, $ns, $page, $title) = @_;
my $prefix = defined($ns) ? "$ns:" : '';
my $text = defined($title) ? $title : $page;
if(iwiki_link($code))
{
return sprintf("[[%s:%s%s|%s]]",$iwiki,$prefix,$page,$text);
}
my $path;
switch($code)
{
case 'wr' { $path = 'http://wikireality.ru/wiki/'; }
case /^(wf|wikifocus)$/ { $path = 'http://wikifocus.org/wiki/'; }
case 'ejwiki' { $path = 'http://ejwiki.org/wiki/'; }
else { undef $path; }
}
if($path)
{
$path .= $prefix . $page;
$path =~ s/ /_/;
return sprintf("[%s %s]",$path,$text);
}
return undef;
}
sub project_name
{
my $code = shift;
switch($code)
{
case 'wr' { return 'Викиреальность'; }
case /^(c|cw|cp|cyclo)$/ { return 'Циклопедия'; }
case /^(lurk|lm)$/ { return 'Луркоморье'; }
case 'provizorii' { return 'Провизории'; }
case 'absurd' { return 'Абсурдопедия'; }
case 'ejwiki' { return 'Ежевика'; }
case 'commons' { return 'Викисклад'; }
case /^(m|meta)$/ { return 'Мета Фонда Викимедиа'; }
case /^(mw|mediawiki)$/ { return 'MediaWiki.org'; }
case /^(wf|wikifocus)$/ { return 'ВикиФокус'; }
case undef { return undef; }
else
{
$code =~ m/([a-z_]+)wik([a-z_]+)/;
return undef unless($1 || $2);
my ($name, $gender);
switch($2)
{
case 'i' { $name = 'Википедия'; $gender = 'f'; }
case /^(t|tionary)$/ { $name = 'Викисловарь'; $gender = 'm'; }
case 'iquote' { $name = 'Викицитатник'; $gender = 'm'; }
case 'ibooks' { $name = 'Викиучебник'; $gender = 'm'; }
case 'iversity' { $name = 'Викиверситет'; $gender = 'm'; }
case 'inews' { $name = 'Викиновости'; $gender = 'p'; }
case 'isource' { $name = 'Викитека'; $gender = 'f'; }
}
return undef unless($name);
my $lang = $wiki_variables::languages{$1};
return $code unless($lang);
$lang = lcfirst($lang);
if($lang =~ m/т$/) {
return sprintf("%s на %sе",$name,$lang);
} elsif ($lang !~ m/ий$/) {
return sprintf("%s на языке %s",$name,$lang);
}
if($gender ne 'm') {
my $result = $gender eq 'f' ? 'ая' : 'ие';
$lang =~ s/ий$/$result/;
}
return sprintf("%s %s",$lang,$name);
}
}
}
sub api_url
{
my $code = shift;
switch($code)
{
case 'wr' { return 'http://www.wikireality.ru/w/api.php'; }
case /^(c|cw|cp|cyclo)$/ { return 'http://cyclowiki.org/w/api.php'; }
case /^(lurk|lm)$/ { return 'http://lurkmore.ru/api.php'; }
case 'provizorii' { return 'http://provizorii.ru/api.php'; }
case 'absurd' { return 'http://absurdopedia.net/api.php'; }
case 'ejwiki' { return 'http://ejwiki.org/w/api.php'; }
case 'commons' { return 'http://commons.wikimedia.org/w/api.php'; }
case /^(m|meta)$/ { return 'http://meta.wikimedia.org/w/api.php'; }
case /^(mw|mediawiki)$/ { return 'http://www.mediawiki.org/w/api.php'; }
case /^(wf|wikifocus)$/ { return 'http://wikifocus.org/w/api.php'; }
case undef { return undef; }
else
{
$code =~ m/([a-z_]+)wik([a-z_]+)/;
return undef unless($1 || $2);
my $domain;
switch($2) {
case 'i' { $domain = 'wikipedia.org'; }
case /^(t|tionary)$/ { $domain = 'wiktionary.org'; }
case 'iquote' { $domain = 'wikiquote.org'; }
case 'ibooks' { $domain = 'wikibooks.org'; }
case 'iversity' { $domain = 'wikiversity.org'; }
case 'inews' { $domain = 'wikinews.org'; }
case 'isource' { $domain = 'wikisource.org'; }
}
return undef unless($domain);
return sprintf("http://%s.%s/w/api.php",$1,$domain);
}
}
}
sub flag_name
{
my ($code, $site) = @_;
switch($code)
{
case 'autoeditor' { return 'автопатрулируемый'; }
case /^(editor|patroller)$/ { return ($site eq 'wr') ? 'редактор' : 'патрулирующий'; }
case 'citizen' { return 'редактор'; }
case 'guard' { return 'смотритель'; }
case 'referee' { return 'эксперт'; }
case 'wizard' { return 'мастер'; }
case 'olsysop' { return 'распорядитель'; }
case 'reviewer' { return 'выверяющий'; }
case /^rollback(er)?$/ { return ($site eq 'absurd') ? 'рыцарь' : 'откатывающий'; }
case 'ipblock-exempt' { return 'исключение из IP-блокировок'; }
case 'closer' { return 'подводящий итоги'; }
case 'sysop' { return 'администратор'; }
case 'bureaucrat' { return 'бюрократ'; }
case 'checkuser' { return 'проверяющий участников'; }
case 'oversight' { return 'ревизор'; }
case 'steward' { return 'стюард'; }
case 'magician' { return 'фокусник'; }
else { return $code; }
}
}
sub logo_url
{
my $url = shift;
return undef unless($url);
my $string = element_by_id($url . 'wiki/Special:Random', 'p-logo');
chomp($string);
$string =~ m/.*?url\((.*?)\).*?/;
return $1;
}
# Метод отказывается работать, да пошёл он на сибирский п***с
#sub mw_upload
#{
# my ($api, $name, $url, $sum, $reupload) = @_;
#
# my $res = $api->api({ action => 'query', prop => 'info', titles => $name }) || return $api->{error}->{details};
# my $missing = exists((values %{$res->{query}->{pages}})[0]->{missing});
#
# my $ua = secure_www($url);
# return sprintf("Не удалось получить объект LWP::UserAgent для %s (загрузка %s )",$url,$name) unless($ua);
## my $response = $ua->get($url);
# $response = $response->content if($response->is_success());
# open(FILE, ">>$name");
# print FILE "$response";
# binmode FILE;
# my ($buffer, $data);
# while ( read(FILE, $buffer, 65536) ) { $data .= $buffer; }
# close(FILE);
#
# if((!$missing && $reupload) || $missing) {
# $api->edit({ action => 'upload', filename => $name, comment => $sum, text => $sum, file => $response,
# ignorewarnings => 1 }) || return 'Ошибка при загрузке файла ' . $name . ': ' . $api->{error}->{details};
# unlink $name;
# return 'done';
# }
# return sprintf("Файл %s уже существует, опция $reupload отключена",$name);
#}
sub convert_time
{
my $time = shift;
return undef if(!$time);
$time =~ m/(20[0-9][0-9])\-([01][0-9])\-([0-3])([0-9])T.*Z/;
my $m = $3 == '0' ? $4 : $3 . $4;
return sprintf("%s %s %s",$m,$wiki_variables::months{$2},$1);
}
[править] Глава 5. Учебник иностранных языков
#! /usr/bin/perl package wiki_variables; use utf8; our %languages = ( "ab" => "Абхазский", "av" => "Аварский", "ae" => "Авестийский", "az" => "Азербайджанский", "ay" => "Аймара", "ak" => "Акан", "sq" => "Албанский", "am" => "Амхарский", "en" => "Английский", "ar" => "Арабский", "hy" => "Армянский", "as" => "Ассамский", "aa" => "Афарский", "af" => "Африкаанс", "eu" => "Баскский", "ba" => "Башкирский", "be" => "Белорусский", "bn" => "Бенгальский", "my" => "Бирманский", "bi" => "Бислама", "bg" => "Болгарский", "bs" => "Боснийский", "br" => "Бретонский", "cy" => "Валлийский", "hu" => "Венгерский", "ve" => "Венда", "vo" => "Волапюк", "wo" => "Волоф", "vi" => "Вьетнамский", "gl" => "Галисийский", "lg" => "Ганда", "hz" => "Гереро", "nl" => "Голландский", "kl" => "Гренландский", "el" => "Греческий", "ka" => "Грузинский", "gu" => "Гуджарати", "gd" => "Гаэльский", "da" => "Датский", "dz" => "Дзонг-кэ", "dv" => "Мальдивский", "zu" => "Зулу", "he" => "Иврит", "ig" =>"Игбо", "yi" => "Идиш", "id" => "Индонезийский", "ia" => "Интерлингва", "ie" => "Интерлингве", "iu" => "Инуктитут", "ik" => "Инупиак", "ga" => "Ирландский", "is" => "Исландский", "es" => "Испанский", "it" => "Итальянский", "yo" => "Йоруба", "kk" => "Казахский", "kn" => "Каннада", "kr" => "Канури", "ca" => "Каталанский", "ks" => "Кашмири", "qu" => "Кечуа", "ki" => "Кикуйю", "kj" => "Киньяма", "zh" => "Китайский", "kv" => "Коми", "kg" => "Конго", "ko" => "Корейский", "kw" => "Корнский", "co" => "Корсиканский", "xh" => "Коса", "ku" => "Курдский", "km" => "Кхмерский", "lo" => "Лаосский", "la" => "Латинский", "lv" => "Латышский", "ln" => "Лингала", "lt" => "Литовский", "lu" => "Луба-катанга", "lb" => "Люксембургский", "mk" => "Македонский", "mg" => "Малагасийский", "ms" => "Малайский", "mt" => "Мальтийский", "mi" => "Маори", "mr" => "Маратхи", "mh" => "Маршалльский", "me" => "Мерянский", "mo" => "Молдавский", "mn" => "Монгольский", "nv" => "Навахо", "na" => "Науру", "nd" => "Ндебеле северный", "nr" => "Ндебеле южный", "ng" => "Ндунга", "de" => "Немецкий", "ne" => "Непальский", "no" => "Норвежский", "ny" => "Ньянджа", "nn" => "Нюнорск", "oj" => "Оджибве", "oc" => "Окситанский", "om" => "Оромо", "os" => "Осетинский", "pi" => "Пали", "pa" => "Пенджабский", "fa" => "Персидский язык", "pl" => "Польский", "pt" => "Португальский", "ps" => "Пушту", "rm" => "Ретороманский", "rw" => "Руанда", "ro" => "Румынский", "rn" => "Рунди", "ru" => "Русский", "sm" => "Самоанский", "sg" => "Санго", "sa" => "Санскрит", "sc" => "Сардинский", "ss" => "Свази", "sr" => "Сербский", "si" => "Сингальский", "sd" => "Синдхи", "sk" => "Словацкий", "sl" => "Словенский", "so" => "Сомали", "st" => "Сото южный", "sw" => "Суахили", "su" => "Сунданский", "tl" => "Тагальский", "tg" => "Таджикский", "th" => "Тайский", "ty" => "Таитянский", "ta" => "Тамильский", "tt" => "Татарский", "tw" => "Тви", "te" => "Телугу", "bo" => "Тибетский", "ti" => "Тигринья", "to" => "Тонга", "tn" => "Тсвана", "ts" => "Тсонга", "tr" => "Турецкий", "tk" => "Туркменский", "uz" => "Узбекский", "ug" => "Уйгурский", "uk" => "Украинский", "ur" => "Урду", "fo" => "Фарерский", "fj" => "Фиджи", "fi" => "Финский", "fr" => "Французский", "fy" => "Фризский", "ff" => "Фулах", "ha" => "Хауса", "hi" => "Хинди", "ho" => "Хиримоту", "cu" => "Старославянский", "ch" => "Чаморро", "ce" => "Чеченский", "cs" => "Чешский", "za" => "Чжуанский", "cv" => "Чувашский", "sv" => "Шведский", "sn" => "Шона", "ee" => "Эве", "eo" => "Эсперанто", "et" => "Эстонский", "jv" => "Яванский", "ja" => "Японский" ); our %months = ( "01" => "января", "02" => "февраля", "03" => "марта", "04" => "апреля", "05" => "мая", "06" => "июня", "07" => "июля", "08" => "августа", "09" => "сентября", "10" => "октября", "11" => "ноября", "12" => "декабря" );
[править] Глава 6. Генератор карты
Эта часть почти полностью использует труды Константина Устиновича.
print '<includeonly>{{#switch: {{NAMESPACE}}|=[[Категория:Статьи для автоматического обновления|{{{prefix}}}:{{{preload_data|}}}]]|}}<div class="p-summary" style="border-color: #{{{border-color|D8BFD8}}}">{{summary/title|{{PAGENAME}}||#{{{border-color|D8BFD8}}}}}';
sub wide { my($x, $pname, @else) = @_;
return "{{#if: {{{$pname|}}}|" .
"{{#if: {{{x$x|}}}" .
'|' . "{{summary/line|{{{$pname}}}}}" .
'|' . "{{summary/field|$pname|{{{$pname}}}}}" .
"}}" .
(@else ? '|' . join("", @else) : '') .
"}}";
}
foreach my $i(1..25) {
print "{{#if:{{{m$i|}}}|";
print '{{', "#switch:{{{m$i}}}",
'|*=', "{{summary/section|{{{t$i}}}}}",
'|+=', wide($i, "{{{t$i}}}",
'{{#ifexist:data:{{{prefix}}}:{{PAGENAME}}',
'|', "{{#if: {{{x$i|}}}",
'|', "{{summary/line|{{data:{{{prefix}}}:{{PAGENAME}}|1={{{t$i}}}}}}}" ,
'|', "{{summary/field|{{{t$i}}}|{{data:{{{prefix}}}:{{PAGENAME}}|1={{{t$i}}}}}}}" ,
'}}',
'|',
'}}'
),
'|~=', wide($i, "{{{t$i}}}"),
'}}|}}';
}
print "</div></includeonly><noinclude>{{doc}}</noinclude>";
[править] Пояснение для глухонемных
Форматированный код шаблона {{autoupdated infobox}}.
----
Шапка: выводится один раз в начале.
<includeonly>
{{#switch: {{NAMESPACE}}
|=[[Категория:Статьи для автоматического обновления|{{{prefix}}}:{{{preload_data|}}}]]
|
}}
<div class="p-summary" style="border-color: #{{{border-color|D8BFD8}}}">
{{summary/title|{{PAGENAME}}||#{{{border-color|D8BFD8}}}}}
----
Основная часть: Повторяется 25 раз, <N> = <N>+1, в начале 1
{{#if:{{{m<N>|}}} # Если определен тип параметра <N>
|{{#switch:{{{m<N>}}} # В зависимости от его значения
|*={{summary/section|{{{t<N>}}}}} # * → выдать секцию, содержащую текст параметра <N>
|+={{#if: {{{ {{{t<N>}}} |}}} # Если параметр с названием <N> может обновляться ботом
|{{#if: {{{x<N>}}} # Если для параметра <N> определено значение x
|{{summary/line|{{{ {{{t<N>}}} }}}}} # Выдать строку, содержащую текст параметра <N>
|{{summary/field| {{{t<N>}}} |{{{ {{{t<N>}}} }}}}} # Иначе выдать поле с названием и текстом параметра <N>
}}
|{{#ifexist:data:{{{prefix}}}:{{PAGENAME}} # Иначе, если существует страница Data:Prefix:Pagename
|{{#if: {{{x<N>}}} # Если для параметра <N> определено значение x
|{{summary/line|{{data:{{{prefix}}}:{{PAGENAME}}|<N>={{{t<N>}}}}}}} # Выдать строку, содержащую значение со страницы данных
|{{summary/field|{{{t<N>}}}|{{data:{{{prefix}}}:{{PAGENAME}}|<N>={{{t<N>}}}}}}} # Иначе выдать поле с названием параметра <N> и строку, содержащую значение со страницы данных
}}
| # Если нет источников данных, ничего не выдать
}}
}}
|~={{#if: {{{{{{t<N>}}}|}}} # Если параметр с названием <N> должен определяться человеком
|{{#if: {{{x<N>}}} # Если для параметра <N> определено значение x
|{{summary/line|{{{{{{t<N>}}}}}}}} # Выдать строку, содержащую текст параметра <N>
|{{summary/field|{{{t<N>}}}|{{{{{{t<N>}}}}}}}} # Иначе выдать поле с названием и текстом параметра <N>
}}
}}
}}
| # Если параметр <N> не определен, ничего не выдать
}}
----
Подвал: выводится один раз в конце
</div>
</includeonly>
<noinclude>{{doc}}</noinclude>
| FedyaBot/По стопам Константина Устиновича относится к теме «Программирование» |