2021-07-11 00:00:22 +02:00
# File: GoogleSearch.pm
#
# Purpose: Google CustomSearch API. You'll need to configure an api-key and
# a custom-search context. URLs to instructions are provided by the command.
# SPDX-FileCopyrightText: 2021 Pragmatic Software <pragma78@gmail.com>
# SPDX-License-Identifier: MIT
2019-12-29 07:57:38 +01:00
2021-07-14 04:45:56 +02:00
package PBot::Plugin::GoogleSearch ;
use parent 'PBot::Plugin::Base' ;
2019-12-29 07:57:38 +01:00
2021-06-19 06:23:34 +02:00
use PBot::Imports ;
2019-12-31 04:32:58 +01:00
2019-12-29 07:57:38 +01:00
use WWW::Google::CustomSearch ;
use HTML::Entities ;
sub initialize {
2020-02-15 23:38:32 +01:00
my ( $ self , % conf ) = @ _ ;
$ self - > { pbot } - > { registry } - > add_default ( 'text' , 'googlesearch' , 'api_key' , '' ) ;
$ self - > { pbot } - > { registry } - > add_default ( 'text' , 'googlesearch' , 'context' , '' ) ;
2019-12-29 07:57:38 +01:00
2020-02-15 23:38:32 +01:00
$ self - > { pbot } - > { registry } - > set_default ( 'googlesearch' , 'api_key' , 'private' , 1 ) ;
$ self - > { pbot } - > { registry } - > set_default ( 'googlesearch' , 'context' , 'private' , 1 ) ;
2019-12-29 07:57:38 +01:00
2021-07-31 04:01:24 +02:00
$ self - > { pbot } - > { commands } - > add (
name = > 'google' ,
help = > 'Google search' ,
subref = > sub { $ self - > cmd_googlesearch ( @ _ ) } ,
) ;
2019-12-29 07:57:38 +01:00
}
sub unload {
2021-07-31 04:01:24 +02:00
my ( $ self ) = @ _ ;
$ self - > { pbot } - > { commands } - > remove ( 'google' ) ;
2019-12-29 07:57:38 +01:00
}
2020-05-04 22:21:35 +02:00
sub cmd_googlesearch {
my ( $ self , $ context ) = @ _ ;
2021-08-28 18:06:33 +02:00
return "Usage: google [-n <number of results>] query\n" if not length $ context - > { arguments } ;
2019-12-29 07:57:38 +01:00
2022-06-26 02:31:40 +02:00
my $ matches = 3 ;
2021-08-28 18:13:08 +02:00
$ matches = $ 1 if $ context - > { arguments } =~ s/-n\s+([0-9]+)\s*// ;
2021-08-28 18:06:33 +02:00
$ matches = 10 if $ matches > 10 ;
2020-02-15 23:38:32 +01:00
my $ api_key = $ self - > { pbot } - > { registry } - > get_value ( 'googlesearch' , 'api_key' ) ; # https://developers.google.com/custom-search/v1/overview
my $ cx = $ self - > { pbot } - > { registry } - > get_value ( 'googlesearch' , 'context' ) ; # https://cse.google.com/all
2019-12-29 07:57:38 +01:00
2020-02-15 23:38:32 +01:00
if ( not length $ api_key ) {
2020-05-04 22:21:35 +02:00
return "$context->{nick}: Registry item googlesearch.api_key is not set. See https://developers.google.com/custom-search/v1/overview to get an API key." ;
2020-02-15 23:38:32 +01:00
}
2019-12-29 07:57:38 +01:00
2020-05-04 22:21:35 +02:00
if ( not length $ cx ) { return "$context->{nick}: Registry item googlesearch.context is not set. See https://cse.google.com/all to set up a context." ; }
2019-12-29 07:57:38 +01:00
2020-05-04 22:21:35 +02:00
my $ engine = WWW::Google::CustomSearch - > new ( api_key = > $ api_key , cx = > $ cx , quotaUser = > $ context - > { hostmask } ) ;
2019-12-29 07:57:38 +01:00
2021-08-28 18:06:33 +02:00
# versus/fight mode: !google banana vs apple -- returns number of results for both terms.
2020-05-04 22:21:35 +02:00
if ( $ context - > { arguments } =~ m/(.*)\s+vs\s+(.*)/i ) {
2020-02-15 23:38:32 +01:00
my ( $ a , $ b ) = ( $ 1 , $ 2 ) ;
my $ result1 = $ engine - > search ( "\"$a\" -\"$b\"" ) ;
my $ result2 = $ engine - > search ( "\"$b\" -\"$a\"" ) ;
2019-12-29 07:57:38 +01:00
2020-05-04 22:21:35 +02:00
if ( not defined $ result1 or not defined $ result1 - > items or not @ { $ result1 - > items } ) { return "$context->{nick}: No results for $a" ; }
2019-12-29 07:57:38 +01:00
2020-05-04 22:21:35 +02:00
if ( not defined $ result2 or not defined $ result2 - > items or not @ { $ result2 - > items } ) { return "$context->{nick}: No results for $b" ; }
2019-12-29 07:57:38 +01:00
2020-02-15 23:38:32 +01:00
my $ title1 = $ result1 - > items - > [ 0 ] - > title ;
my $ title2 = $ result2 - > items - > [ 0 ] - > title ;
2019-12-31 04:32:58 +01:00
2020-02-15 23:38:32 +01:00
utf8:: decode $ title1 ;
utf8:: decode $ title2 ;
2019-12-31 04:32:58 +01:00
2021-08-28 18:06:33 +02:00
return "$context->{nick}: "
. "$a: (" . $ result1 - > formattedTotalResults . ') '
. decode_entities ( $ title1 ) . ' <' . $ result1 - > items - > [ 0 ] - > link . '> '
. 'VS '
. "$b: (" . $ result2 - > formattedTotalResults . ') '
. decode_entities ( $ title2 ) . ' <' . $ result2 - > items - > [ 0 ] - > link . '>' ;
2020-02-15 23:38:32 +01:00
}
2019-12-29 07:57:38 +01:00
2020-05-05 03:43:50 +02:00
my $ result = eval { $ engine - > search ( $ context - > { arguments } ) } ;
if ( $@ ) {
my $ error = $@ ;
$ error =~ s/^WWW::Google::CustomSearch::search\(\): /google: / ;
2020-05-05 22:52:59 +02:00
$ error =~ s/file .*?$// ;
$ error =~ s/Missing required arguments: totalResults.*/No results./ ;
2020-05-05 03:43:50 +02:00
return $ error ;
}
2019-12-29 07:57:38 +01:00
2020-05-04 22:21:35 +02:00
if ( not defined $ result or not defined $ result - > items or not @ { $ result - > items } ) { return "$context->{nick}: No results found" ; }
2019-12-29 07:57:38 +01:00
2020-05-04 22:21:35 +02:00
my $ output = "$context->{nick}: (" . $ result - > formattedTotalResults . " results) " ;
2019-12-29 07:57:38 +01:00
2021-08-28 18:06:33 +02:00
my @ results ;
2020-02-15 23:38:32 +01:00
foreach my $ item ( @ { $ result - > items } ) {
my $ title = $ item - > title ;
utf8:: decode $ title ;
2021-08-28 18:06:33 +02:00
push @ results , decode_entities ( $ title ) . ': <' . $ item - > link . '>' ;
2020-02-15 23:38:32 +01:00
last if - - $ matches <= 0 ;
}
2021-08-28 18:06:33 +02:00
2021-08-28 18:13:08 +02:00
$ output . = join "\n-- " , @ results ;
2021-08-28 18:06:33 +02:00
2020-02-15 23:38:32 +01:00
return $ output ;
2019-12-29 07:57:38 +01:00
}
1 ;