- add search functionality
authorAndreas Scherbaum <[email protected]>
Mon, 27 Feb 2012 13:54:08 +0000 (14:54 +0100)
committerAndreas Scherbaum <[email protected]>
Mon, 27 Feb 2012 13:54:08 +0000 (14:54 +0100)
docbot.conf
docbot.pl

index b33ea208c1f82b5b9ffeef69956e99306733952f..fe6487e57860c93b74321737287ec53de8d8277e 100644 (file)
@@ -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'
index e3769c8a61361fac8f8fc527fa2b86cb0cb2cc8c..b5c4ed27860d693096c8eb373b527c822dddc2a8 100755 (executable)
--- 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 '';
+}
 
 
 ######################################################################