File Coverage

blib/lib/OurNet/Query.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package OurNet::Query;
2             require 5.005;
3              
4             $OurNet::Query::VERSION = '1.22';
5              
6 1     1   24039 use strict;
  1         3  
  1         1392  
7              
8 1     1   12537 use OurNet::Site;
  1         4  
  1         46  
9 1     1   1259 use HTTP::Request::Common;
  1         42603  
  1         401  
10 1     1   2073 use LWP::Parallel::UserAgent;
  0            
  0            
11              
12             =head1 NAME
13              
14             OurNet::Query - Perform scriptable queries via LWP
15              
16             =head1 SYNOPSIS
17              
18             use OurNet::Query;
19              
20             # Set query parameters
21             my ($query, $hits) = ('autrijus', 10);
22             my @sites = ('Altavista', 'InfoSeek', 'Yahoo', 'Excite');
23             my %found;
24              
25             # Generate a new Query object
26             my $bot = OurNet::Query->new($query, $hits, @sites);
27              
28             # Perform a query
29             my $found = $bot->begin(\&callback, 30); # Timeout after 30 seconds
30              
31             print '*** ' . ($found ? $found : 'No') . ' match(es) found.';
32              
33             sub callback {
34             my %entry = @_;
35             my $entry = \%entry;
36              
37             unless ($found{$entry{'url'}}) {
38             print "*** [$entry->{'title'}]" .
39             " ($entry->{'score'})" .
40             " - [$entry->{'id'}]\n" .
41             " URL: [$entry->{'url'}]\n";
42             }
43              
44             $found{$entry{'url'}}++;
45             }
46              
47             =head1 DESCRIPTION
48              
49             OurNet::Query provides an easy interface to perform multiple queries
50             to internet services, and "wrap" them into your own format at once.
51             The results are processed on-the-fly and are returned via callback
52             functions.
53              
54             =cut
55              
56             # ---------------
57             # Variable Fields
58             # ---------------
59             use fields qw/callback pua timeout query sites bots hits found/;
60              
61             # -----------------
62             # Package Constants
63             # -----------------
64             use constant ERROR_QUERY_NEEDED => __PACKAGE__ . ' needs a query';
65             use constant ERROR_HITS_NEEDED => __PACKAGE__ . ' needs sufficient hits';
66             use constant ERROR_SITES_NEEDED => __PACKAGE__ . ' needs one or more sites';
67             use constant ERROR_CALLBACK_NEEDED => __PACKAGE__ . ' needs a callback function';
68             use constant ERROR_PROTOCOL_UNDEF => __PACKAGE__ . ' cannot use the protocol';
69              
70             # -------------------------------------
71             # Subroutine new($query, $hits, @sites)
72             # -------------------------------------
73             sub new {
74             my $class = shift;
75             my $self = ($] > 5.00562) ? fields::new($class)
76             : do { no strict 'refs';
77             bless [\%{"$class\::FIELDS"}], $class };
78              
79             $self->{'query'} = shift or (warn(ERROR_QUERY_NEEDED), return);
80             $self->{'hits'} = shift or (warn(ERROR_HITS_NEEDED), return);
81             $self->{'sites'} = [ @_ ] or (warn(ERROR_SITES_NEEDED), return);
82             $self->{'pua'} = LWP::Parallel::UserAgent->new();
83              
84             return $self;
85             }
86              
87             # ---------------------------------------------
88             # Subroutine begin($self, \&callback, $timeout)
89             # ---------------------------------------------
90             sub begin {
91             my $self = shift;
92              
93             $self->{'callback'} = ($_[0] ? $_[0] : $self->{'callback'})
94             or (warn(ERROR_CALLBACK_NEEDED), return);
95             $self->{'timeout'} = ($_[1] ? $_[1] : $self->{'timeout'});
96             $self->{'pua'}->initialize();
97              
98             foreach my $count (0 .. $#{$self->{'sites'}}) {
99             $self->{'bots'}[$count] = OurNet::Site->new($self->{'sites'}[$count]);
100              
101             my $siteurl = $self->{'bots'}[$count]->geturl($self->{'query'}, $self->{'hits'});
102              
103             my $request = ($siteurl =~ m|^post:(.+?)\?(.+)|)
104             ? POST("http:$1", [split('[&;=]', $2)])
105             : GET($siteurl)
106             or (warn(ERROR_PROTOCOL_UNDEF), return);
107              
108             # Closure is not something that most Perl programmers need
109             # trouble themselves about to begin with. (perlref.pod)
110             $self->{'pua'}->register($request, sub {
111             $self->{'bots'}[$count]->callme($self, $count,
112             $_[0], \&callmeback);
113             return;
114             });
115             }
116              
117             $self->{'found'} = 0;
118             $self->{'pua'}->wait($self->{'timeout'});
119              
120             return $self->{'found'};
121             }
122              
123             # --------------------------------------
124             # Subroutine callmeback($self, $himself)
125             # --------------------------------------
126             sub callmeback {
127             my ($self, $himself) = @_;
128              
129             foreach my $entry (@{$himself->{'response'}}) {
130             if (exists($entry->{'url'})) {
131             &{$self->{'callback'}}(%{$entry});
132             delete($entry->{'url'});
133              
134             $self->{'found'}++;
135             }
136             }
137             }
138              
139             1;
140              
141             =head1 SEE ALSO
142              
143             L
144              
145             =head1 AUTHORS
146              
147             Autrijus Tang Eautrijus@autrijus.org>
148              
149             =head1 COPYRIGHT
150              
151             Copyright 2001 by Autrijus Tang Eautrijus@autrijus.org>.
152              
153             All rights reserved. You can redistribute and/or modify
154             this module under the same terms as Perl itself.
155              
156             =cut