From: Andreas Scherbaum Date: Mon, 27 Feb 2012 13:54:08 +0000 (+0100) Subject: - add search functionality X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=aff771809dfe30c53915d5b98935aa214fa59c12;p=docbot.git - add search functionality --- diff --git a/docbot.conf b/docbot.conf index b33ea20..fe6487e 100644 --- a/docbot.conf +++ b/docbot.conf @@ -49,17 +49,18 @@ bot: commandchannel: '#pg_docbot' ircmaxchannels: 2 ircmaxsessions: 3 - queryprefix: '??' +search: urlpattern: '(http|ftp|news|bt|https)://' - maxwrap: 3 - likesearch: 0 - casesearch: 0 + maxresults: 4 + maxwrap: 2 + searchsite: 'http://pg-docbot.de/search/?q=' translations: de: learn: 'lerne|lernen' forget: 'vergesse|vergessen' config: 'konfiguriere' help: 'hilfe' + search: 'suche' successfully_added_1_keyword: 'Ein Schlüsselwort hinzugefügt' successfully_added_1_url: 'Eine URL hinzugefügt' successfully_added_x_keyword: '% Schlüsselwörter hinzugefügt' @@ -76,6 +77,11 @@ translations: additional_information_at: 'Weitere Informationen unter' you_are_not_authorized: 'Sie sind nicht authorisiert' access_denied: 'Zugriff verweigert' + invalid_search: 'Ungültige Suche' + database_error: 'Datenbankfehler' + more_results_at: 'Mehr Ergebnisse unter' + more_result: 'weiteres Ergebnis' + more_results: 'weitere Ergebnisse' fr: learn: 'apprendre' forget: 'oublier' diff --git a/docbot.pl b/docbot.pl index e3769c8..b5c4ed2 100755 --- a/docbot.pl +++ b/docbot.pl @@ -1621,6 +1621,7 @@ sub handle_command { switch ($command) { case('search') { $main::statistics{'command_counter_search'}++; + return handle_command_search($command, $string, $mode, $kernel, $heap, $who, $nick, $where, $msg, $sender, $irc, $channel); } case('help') { $main::statistics{'command_counter_help'}++; @@ -1721,10 +1722,149 @@ sub handle_command_status { } +# handle_command_search() +# +# command handler for the 'search' command +# +# parameter: +# - the command (lower case) +# - the parameter string (may be empty) +# - the command mode (admin/operator/user) +# - POE kernel +# - POE heap +# - the full who of the message sender, including the nick name +# - the nick name of the message sender +# - the full origin of the message +# - the message itself +# - POE sender +# - session irc handle +# - the channel name +# return: +# - text to send back to the sender +sub handle_command_search { + my $command = shift; + my $string = shift; + my $mode = shift; + my $kernel = shift; + my $heap = shift; + my $who = shift; + my $nick = shift; + my $where = shift; + my $msg = shift; + my $sender = shift; + my $irc = shift; + my $channel = shift; + + my $session = find_irc_session($irc); + + + if (lc($channel) eq lc($irc->nick_name())) { + print_msg("Search issued: '$string', by $nick", DEBUG2); + } else { + print_msg("Search issued: '$string', by $nick in $channel", DEBUG2); + } + # remove spaces at beginning and end + $string =~ s/^[\s\t]+//gs; + $string =~ s/[\s\t]+$//gs; + + if (length($string) < 1) { + if (lc($channel) eq lc($irc->nick_name())) { + # return error to sender in private message + return 'No search given'; + } + # don't flood a channel with the error message + return ''; + } + + + # find out where to reply the answer + my $replyto = $channel; + if (lc($channel) eq lc($irc->nick_name())) { + $replyto = $nick; + } elsif ($string =~ /^(.+)\s+>\s+(\w+)/i) { + if (grep(/^$channel$/i, find_nick($heap, $2, $session))) { + $string = $1; + $replyto = $2; + } else { + return ''; + } + } + + + if ($string !~ /^[a-zA-Z0-9 ]+$/) { + my $answer = "Invalid search"; + # translate error message + $answer = translate_text_for_channel($channel, 'invalid_search', $answer); + return $answer; + } + + + # compose the search + my @keys = split(/\s+/, $string); + + my $query_inner = "SELECT kurl FROM docbot_key WHERE LOWER(key) = ?"; + my $query = "SELECT url FROM docbot_url WHERE id IN ("; + $query .= join("\n INTERSECT\n" => map {"$query_inner\n"} @keys); + $query .= ")"; + # FIXME: sort order + my $st = $main::db->query($query, @keys); + if (!defined($st)) { + my $answer = "Database error"; + # translate error message + $answer = translate_text_for_channel($channel, 'database_error', $answer); + return $answer; + } + my $rows = $st->rows; + if ($rows == 0) { + my $answer = "Nothing found"; + # translate error message + $answer = translate_text_for_channel($channel, 'nothing_found', $answer); + return $answer; + } + # fetch the result + my @rows = (); + while (my @row = $st->fetchrow_array) { + push(@rows, $row[0]); + } + + my @lines = (); + my $maxresults = config_get_key2('search', 'maxresults'); + my $maxwrap = config_get_key2('search', 'maxwrap'); + for (my $a = 1; $a <= int($maxresults / $maxwrap); $a++) { + my @line = (); + for (my $b = 1; $b <= $maxwrap; $b++) { + if (defined($rows[0])) { + push(@line, shift(@rows)); + } + } + if (scalar(@line) > 0) { + push(@lines, join(" :: ", @line)); + } + } + if (scalar(@rows) > 0) { + my $line = ''; + if (scalar(@rows) == 1) { + $line = scalar(@rows) . " " . translate_text_for_channel($replyto, 'more_result', 'more result'); + } else { + $line = scalar(@rows) . " " . translate_text_for_channel($replyto, 'more_results', 'more results'); + } + $line .= ': ' . config_get_key2('search', 'searchsite') . uri_escape($string); + push(@lines, $line); + } + + if (scalar(@lines) > 0) { + foreach my $line (@lines) { + $irc->yield( privmsg => $replyto, $line ); + } + } + + + return ''; +} ######################################################################