PageRenderTime 69ms CodeModel.GetById 51ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/WWW/DuckDuckGo.pm

https://github.com/duckduckgo/p5-www-duckduckgo
Perl | 194 lines | 175 code | 17 blank | 2 comment | 7 complexity | f18f35ebcc498d9e948773317421c396 MD5 | raw file
  1package WWW::DuckDuckGo;
  2# ABSTRACT: Access to the DuckDuckGo APIs
  3
  4use Moo;
  5
  6use LWP::UserAgent;
  7use HTTP::Request;
  8use WWW::DuckDuckGo::ZeroClickInfo;
  9use JSON;
 10use URI;
 11use URI::QueryParam;
 12
 13our $VERSION ||= '0.0development';
 14
 15has _duckduckgo_api_url => (
 16	is => 'ro',
 17	lazy => 1,
 18	default => sub { 'http://api.duckduckgo.com/' },
 19);
 20
 21has _duckduckgo_api_url_secure => (
 22	is => 'ro',
 23	lazy => 1,
 24	default => sub { 'https://api.duckduckgo.com/' },
 25);
 26
 27has _zeroclickinfo_class => (
 28	is => 'ro',
 29	lazy => 1,
 30	default => sub { 'WWW::DuckDuckGo::ZeroClickInfo' },
 31);
 32
 33has _http_agent => (
 34	is => 'ro',
 35	lazy => 1,
 36	default => sub {
 37		my $self = shift;
 38		my $ua = LWP::UserAgent->new;
 39		$ua->agent($self->http_agent_name);
 40		return $ua;
 41	},
 42);
 43
 44has http_agent_name => (
 45	is => 'ro',
 46	lazy => 1,
 47	default => sub { __PACKAGE__.'/'.$VERSION },
 48);
 49
 50has forcesecure => (
 51	is => 'ro',
 52	default => sub { 0 },
 53);
 54
 55has safeoff => (
 56	is => 'ro',
 57	default => sub { 0 },
 58);
 59
 60has html => (
 61	is => 'ro',
 62	default => sub { 0 },
 63);
 64
 65# HashRef of extra params
 66has params => (
 67    is => 'ro',
 68    default => sub { {} },
 69);
 70
 71sub zci { shift->zeroclickinfo(@_) }
 72
 73sub _zeroclickinfo_request_base {
 74	my ( $self, $for_uri, @query_fields ) = @_;
 75	my $query = join(' ',@query_fields);
 76	my $uri = URI->new($for_uri);
 77    my %params = %{$self->params};
 78	$uri->query_param( q => $query );
 79	$uri->query_param( o => 'json' );
 80	$uri->query_param( kp => -1 ) if $self->safeoff;
 81    $uri->query_param( no_redirect => 1 );
 82    $self->html ? 
 83        $uri->query_param( no_html => 0 ) : 
 84        $uri->query_param( no_html => 1 );
 85    $uri->query_param($_ => $params{$_}) for keys %params;
 86	return HTTP::Request->new(GET => $uri->as_string);
 87}
 88
 89sub zeroclickinfo_request_secure {
 90	my ( $self, @query_fields ) = @_;
 91	return if !@query_fields;
 92	return $self->_zeroclickinfo_request_base($self->_duckduckgo_api_url_secure,@query_fields);
 93}
 94
 95sub zeroclickinfo_request {
 96	my ( $self, @query_fields ) = @_;
 97	return if !@query_fields;
 98	return $self->_zeroclickinfo_request_base($self->_duckduckgo_api_url,@query_fields);
 99}
100
101sub zeroclickinfo {
102	my ( $self, @query_fields ) = @_;
103	return if !@query_fields;
104	my $query = join(' ',@query_fields);
105	my $res;
106	eval {
107		$res = $self->_http_agent->request($self->zeroclickinfo_request_secure(@query_fields));
108	};
109	if (!$self->forcesecure and ( $@ or !$res or !$res->is_success ) ) {
110		warn __PACKAGE__." HTTP request failed: ".$res->status_line if ($res and !$res->is_success);
111		warn __PACKAGE__." Can't access ".$self->_duckduckgo_api_url_secure." falling back to: ".$self->_duckduckgo_api_url;
112		$res = $self->_http_agent->request($self->zeroclickinfo_request(@query_fields));
113	}
114	return $self->zeroclickinfo_by_response($res);
115}
116
117sub zeroclickinfo_by_response {
118	my ( $self, $response ) = @_;
119	if ($response->is_success) {
120		my $result = decode_json($response->content);
121		return $self->_zeroclickinfo_class->by($result);
122	} else {
123		die __PACKAGE__.' HTTP request failed: '.$response->status_line, "\n";
124	}	
125}
126
1271;
128
129=encoding utf8
130
131=head1 SYNOPSIS
132
133  use WWW::DuckDuckGo;
134
135  my $duck = WWW::DuckDuckGo->new;
136  
137  # request the Zero Click Info, you can also use ..->zci('duck duck go')
138  my $zeroclickinfo = $duck->zeroclickinfo('duck duck go');
139
140  # request the Zero Click Info of "duck duck go more stuff"
141  my $other_zeroclickinfo = $duck->zeroclickinfo('duck duck go','more stuff');
142
143=head1 DESCRIPTION
144
145This distribution gives you an easy access to the DuckDuckGo Zero Click Info API. It tries to connect via https first and falls back to http if there is a failure.
146
147=head1 ATTRIBUTES
148
149=attr forcesecure
150
151Set to true will force the client to use https, so it will not fallback to http on failure.
152
153=attr http_agent_name
154
155Set the http agent name which the webserver gets. Defaults to WWW::DuckDuckGo
156
157=attr safeoff
158
159Set to true to disable safesearch.
160
161=attr html
162
163Allow HTML in output. This is the default in DuckDuckGo, but not default here to maintain backwards compatibility.
164
165=attr params
166
167A HashRef of extra GET params to pass with the query (documented on https://api.duckduckgo.com/)
168
169=head1 METHODS
170
171=method $obj->zeroclickinfo
172
173Arguments: @query_fields
174
175Return value: L<WWW::DuckDuckGo::ZeroClickInfo>
176
177Returns the L<WWW::DuckDuckGo::ZeroClickInfo> of the query specified by the parameters. If you give several parameters they will get joined with an empty space.
178
179=head1 SUPPORT
180
181IRC
182
183  Join #duckduckgo on irc.freenode.net.
184
185Repository
186
187  http://github.com/duckduckgo/p5-www-duckduckgo
188  Pull request and additional contributors are welcome
189 
190Issue Tracker
191
192  http://github.com/duckduckgo/p5-www-duckduckgo/issues
193
194