Участник: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/По стопам Константина Устиновича относится к теме «Программирование» |