Ticket #2245: Link from /browse/* pages to the wiki key/value pages
[rails.git] / script / misc / update-key-and-tag-description-pages-from-wiki
1 #!/usr/bin/env perl
2 use strict;
3 use warnings;
4
5 use Pod::Usage ();
6 use Getopt::Long ();
7
8 BEGIN {
9     eval "require MediaWiki::API; require YAML::XS;" or do {
10         print "You have to install some modules via CPAN to run this:\n";
11         print "   sudo cpanp MediaWiki::API YAML::XS\n";
12         exit 1;
13     };
14 }
15
16 use MediaWiki::API;
17 use YAML::XS qw(Dump);
18 use Test::More 'no_plan';
19
20 =head1 NAME
21
22 update-key-and-tag-description-pages-from-wiki - Screen-scrape the wiki for key/value wiki description pages
23
24 =head1 SYNOPSIS
25
26     perl script/misc/update-key-and-tag-description-pages-from-wiki config/wiki-tag-and-key-description.yml 
27
28 =head1 BUGS
29
30 This will break if there are more than 500 key or value pages. Paging
31 needs to be implemenented.
32
33 That or using a proper API or something (if it's there) or making a
34 direct query to the wiki database.
35
36 =cut
37
38 # Get the command-line options
39 Getopt::Long::Parser->new(
40     config => [ qw< bundling no_ignore_case no_require_order pass_through > ],
41 )->getoptions(
42     'h|help' => \my $help,
43 ) or help();
44
45 # On --help
46 help() if $help;
47
48 help() unless $ARGV[0];
49
50 # Get a API interface
51 my $mw = MediaWiki::API->new();
52 ok($mw, "Got a MediaWiki API");
53 $mw->{config}->{api_url} = 'http://wiki.openstreetmap.org/w/api.php';
54
55 # All our goodies
56 my (%feature, %count);
57
58 # This is what you get on:
59 ## http://wiki.openstreetmap.org/w/index.php?search=Template:KeyDescription&fulltext=Search&fulltext=Search
60 for my $lang ('', map { "${_}:" } qw[ Pt Fi De It HU Cz Fr RU Pl ]) {
61     ok(1, "  Templates for language '$lang'");
62
63     # Key/value pages
64     for my $thing (qw(key value)) {
65         my $Thing = ucfirst $thing;
66         ok(1, "    Getting $thing pages");
67         my $cnt = stick_content_in_hash($thing, "Template:${lang}${Thing}Description", \%feature);
68         ok(1, "    Got $cnt $thing pages");
69         $count{$thing} += $cnt;
70     }
71 }
72
73 ok(1, "Got a total of $count{$_} ${_}s") for qw[ key value ];
74
75 # Dump to .yml file
76 open my $out, ">", $ARGV[0] or die "Can't open file '$ARGV[0]' supplied on the command line";
77 say $out "# THIS FILE IS AUTOGENERATED WITH THE script/misc/update-key-and-tag-description-pages-from-wiki";
78 say $out "# PROGRAM DO NOT MANUALLY EDIT IT";
79 say $out "";
80 say $out Dump(\%feature);
81 close $out;
82
83 exit 0;
84
85 sub stick_content_in_hash
86 {
87     my ($key, $title, $hash) = @_;
88     my $ukey = ucfirst $key;
89
90     my $space_to_underscore = sub {
91         my $txt = shift;
92         $txt =~ s/ /_/g;
93         $txt;
94     };
95
96     my $count = 0;
97     get_embeddedin(
98         $title,
99         sub {
100             my ($links) = @_;
101             my (@links) = @$links;
102             ok(1, "    ... got " . scalar(@links) . " more links");
103             for my $link (@links) {
104                 $count++;
105                 my $title = $link->{title};
106
107                 if ($title =~ /^$ukey:(?<key_name>.*?)$/) {
108                     # English by default
109                     $hash->{en}->{$key}->{ $space_to_underscore->($+{key_name}) } = $title;
110                 } elsif ($title =~ /^(?<lang>[^:]+):$ukey:(?<key_name>.*?)$/) {
111                     $hash->{lc $+{lang}}->{$key}->{ $space_to_underscore->($+{key_name}) } = $title;
112                 }
113             }
114         }
115     );
116
117     return $count;
118 }
119
120 sub get_embeddedin
121 {
122     my ($title, $callback) = @_;
123     my $articles = $mw->list(
124         {
125             action => 'query',
126             list => 'embeddedin',
127             eititle => $title,
128             eifilterredir => 'nonredirects',
129             # Doesn't work for De:* and anything non-en. Odd.
130             # einamespace => '0|8',
131             eilimit => '200',
132         },
133         {
134             max => '0',
135             hook => $callback,
136             skip_encoding => 1,
137         }
138     ) || die $mw->{error}->{code} . ': ' . $mw->{error}->{details};
139 }
140
141 sub help
142 {
143     my %arg = @_;
144
145     Pod::Usage::pod2usage(
146         -verbose => $arg{ verbose },
147         -exitval => $arg{ exitval } || 0,
148     );
149 }