File Coverage

blib/lib/WoW/Wiki.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             package WoW::Wiki;
2              
3 1     1   23743 use 5.008006;
  1         3  
  1         37  
4 1     1   5 use strict;
  1         3  
  1         33  
5 1     1   5 use warnings;
  1         7  
  1         42  
6              
7             #
8             # Module dependencies
9             #
10 1     1   6 use Carp;
  1         1  
  1         107  
11 1     1   445 use XML::Parser;
  0            
  0            
12             use XML::SimpleObject;
13             use LWP::UserAgent;
14             use URI::Escape;
15             use HTTP::Response;
16             use Storable qw(store retrieve freeze thaw dclone);
17              
18             require Exporter;
19              
20             our @ISA = qw(Exporter);
21              
22             # This allows declaration use WoW::Wiki ':all';
23             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
24             # will save memory.
25             our %EXPORT_TAGS = ( 'all' => [ qw(parse) ] );
26              
27             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
28              
29             our @EXPORT = qw(parse);
30              
31             our $VERSION = '0.01';
32              
33              
34             # OO Methods
35             sub new
36             {
37             my $this = shift;
38             my $class = ref($this) || $this;
39             my $self = {};
40             bless($self, $class);
41             $self->{AGENT} = new LWP::UserAgent;
42             $self->{AGENT}->agent("Wiki Scraper/0.1");
43             return $self;
44             }
45              
46             =cut
47             This public method takes 1 parameter
48             the title page to parse, it returns a list of hashes representing
49             each part of the API
50             =cut
51             sub parse
52             {
53             my $self = shift;
54             my $title = shift;
55             my $results = $self->_get_wikidata($title);
56             my $titleType = $self->_get_markup_type($results);
57             if($titleType eq 'HANDLER')
58             {
59             return [_handler_parse($title,$results)];
60             }
61             elsif($titleType eq 'EVENT')
62             {
63             return _event_parse($results);
64             }
65             elsif($titleType eq 'METHOD')
66             {
67             return _method_parse($title,$results);
68             }
69             elsif($titleType eq 'API')
70             {
71             return _api_parse($title,$results);
72             }
73             elsif($titleType eq 'UI')
74             {
75             return _ui_parse($title,$results);
76             }
77            
78             }
79              
80              
81             =head3 PRIVATE METHODS
82             =cut
83              
84             =cut
85             Get the wiki markup for a given title
86             =cut
87             sub _get_wikidata
88             {
89             my $self = shift;
90             my $page = shift;
91             my $req = new HTTP::Request POST => 'http://www.wowwiki.com/Special:Export';
92             $req->content_type('application/x-www-form-urlencoded');
93             $req->content('action=submit&curonly=1&pages='.uri_escape($page));
94             my $res = $self->{AGENT}->request($req);
95             # Check the outcome of the response
96             if ($res->is_success)
97             {
98             my $wikiMarkup = "";
99             eval{
100             my $xmlobj = new XML::SimpleObject(XML => $res->content, ErrorContext => 2);
101             my $markup = $xmlobj->child("mediawiki")->child("page")->child("revision")->child("text");
102             $wikiMarkup = $markup->value;
103             };
104             if($@)
105             {
106             croak "Bad Title Page!";
107             }
108             return $wikiMarkup;
109             }
110             else
111             {
112             croak "Unable to pull data from wow wiki! "..$res->content;
113             }
114             }
115              
116             =cut
117             Determine the type of markup this is
118             =cut
119             sub _get_markup_type
120             {
121             # Markup tags
122             # Handler: {{widgethandler}}
123             # Events : {{evt|EVENT|Categories}} comma seperator for cats
124             # Methods: {{widgetmethod}}
125             # API Raw: {{wowapi}}
126             # UIXML : {{framexmlfunc|XML_FILE_LOCATION}}
127             my $self = shift;
128             my $input = shift;
129             if($input =~ /\{\{widgethandler/)
130             {
131             return "HANDLER";
132             }
133             elsif($input =~ /\{\{evt/)
134             {
135             return "EVENT";
136             }
137             elsif($input =~ /\{\{widgetmethod/)
138             {
139             return "METHOD";
140             }
141             elsif($input =~ /\{\{wowapi/)
142             {
143             return "API";
144             }
145             elsif($input =~ /\{\{framexmlfunc/)
146             {
147             return "UI";
148             }
149             return "UNKNOWN";
150             }
151             =cut
152             trim whitespace
153             =cut
154             sub _trim
155             {
156             my $string = shift;
157             $string =~ s/^\s+//;
158             $string =~ s/\s+$//;
159             return $string;
160             }
161             sub _fix_hrefs
162             {
163             my $string = shift;
164             $string =~ s/\[\[(.+\s?.+)\|+?(.*)\]\]/$2/;
165             $string =~ s/\[\[(\w+)\]\]/$1/;
166             return $string;
167             }
168             sub _fix_quotes
169             {
170             my $string = shift;
171             $string =~ s/(["])/\\$1/g;
172             return $string;
173             }
174             sub _fix_case
175             {
176             my $line = shift;
177             my $nline = lc($line);
178             $nline =~ s/\b(\w)/\U$1/g;
179             return $nline;
180             }
181             =cut
182             Handle an Event Page
183             =cut
184             sub _event_parse
185             {
186             my $input = shift;
187             my @lines = split(/\n/,$input);
188             my $lastEvent = "";
189             my @events = [];
190             my %event;
191             foreach my $line (@lines)
192             {
193             # Skip blank lines
194             if(length($line) <= 1)
195             {
196             next;
197             }
198             # look for the starting "Event" Line
199             if($line =~ /evt\|/)
200             {
201             if(keys(%event))
202             {
203             my $d = dclone(\%event);
204             push(@events,$d);
205             undef %event;
206             }
207             # remove the braces
208             $line =~ s/{|}//g;
209             # split the line up
210             my($evtL,$event,$cat) = split(/\|/,$line);
211             $lastEvent = $event;
212             $event =~ s/_/ /g;
213             $event{'NAME'} = _fix_case($event);
214             $event{'TYPE'} = 'EVENT';
215             $event{'CATEGORIES'} = $cat;
216             }
217             elsif($line =~ /^\w/ && length($lastEvent) > 1)
218             {
219             chomp($line);
220             $event{'DESC'} .= _fix_quotes(_fix_hrefs(_trim($line))) . "\\n";
221             }
222             elsif($line =~ /^:/ && length($lastEvent) > 1)
223             {
224             chomp($line);
225             $line =~ s/://;
226             $event{'DESC'} .= _fix_quotes(_fix_hrefs(_trim($line))) . "\\n";
227             }
228             elsif($line =~ /^\;/ && length($lastEvent) > 1)
229             {
230             chomp($line);
231             $line =~ s/\;//;
232             $event{'ARGS'} .= _fix_quotes(_fix_hrefs(_trim($line))) . "\\n";
233             }
234             }
235             return \@events;
236             }
237              
238             =cut
239             parser for Widget Handlers
240             =cut
241             sub _handler_parse
242             {
243             my $title = shift;
244             my $input = shift;
245             $title =~ s/UIHANDLER_//;
246             my %handler;
247             $handler{'NAME'} = $title;
248             $handler{'TYPE'} = 'HANDLER';
249             my @lines = split(/\n/,$input);
250             my $state = "";
251             foreach my $sitem (@lines)
252             {
253             if($sitem =~ /^== Description/)
254             {
255             $state = "DESC";
256             next;
257             }
258             if($sitem =~ /^== Arguments/)
259             {
260             $state = "ARGS";
261             next;
262             }
263             if($sitem =~ /^== \w+/)
264             {
265             $state = "";
266             next;
267             }
268             unless(length($sitem) > 1 || length($state) < 1)
269             {
270             next;
271             }
272             if(length($state) > 1)
273             {
274             if($state eq 'ARGS')
275             {
276             if($sitem =~ /^; ar/)
277             {
278             $sitem =~ s/\;//;
279             }
280             $handler{$state} .= _trim($sitem);
281             }
282             else
283             {
284             $handler{$state} .= _trim($sitem);
285             }
286             }
287             }
288             return \%handler;
289             }
290              
291             sub _method_parse
292             {
293             croak "Method parsing not implemented yet!";
294             }
295             sub _api_parse
296             {
297             croak "API type parsing not implemented yet!";
298             }
299             sub _ui_parse
300             {
301             croak "UI frameXML parsing not implemented yet!";
302             }
303              
304              
305             1;
306             __END__