From 8f7c69148a7d05e9becdc0a56c5f4f2d8e0c4b66 Mon Sep 17 00:00:00 2001
From: Alexandre Morignot <erdnaxeli@cervoi.se>
Date: Sat, 18 Apr 2020 15:08:08 +0200
Subject: [PATCH] Add full text search with !fts

---
 PlayBot/commands/get.pm       |  7 +++---
 PlayBot/commands/get/query.pm |  6 +++++
 PlayBot/commands/parser.pm    |  6 +++--
 PlayBot/utils/db/get.pm       | 42 +++++++++++++++++++++++++----------
 4 files changed, 44 insertions(+), 17 deletions(-)

diff --git a/PlayBot/commands/get.pm b/PlayBot/commands/get.pm
index 53c920d..568610b 100644
--- a/PlayBot/commands/get.pm
+++ b/PlayBot/commands/get.pm
@@ -14,11 +14,12 @@ our $irc;
 our $log;
 
 sub exec {
-	my ($chan, $msg, $chan_src) = @_;
+	my ($fts, $chan, $msg, $chan_src) = @_;
 
     my $query = PlayBot::commands::get::query->new(
-        chan => $chan,
-        query  => ($msg) ? $msg : ''
+        chan    => $chan,
+        query   => ($msg) ? $msg : '',
+        fts     => $fts,
     );
 
     my $db_query = PlayBot::utils::db::get->new();
diff --git a/PlayBot/commands/get/query.pm b/PlayBot/commands/get/query.pm
index 91549ce..55458ee 100644
--- a/PlayBot/commands/get/query.pm
+++ b/PlayBot/commands/get/query.pm
@@ -20,6 +20,12 @@ has 'chan' => (
     required    => 1
 );
 
+has 'fts' => (
+    is          => 'ro',
+    isa         => 'Bool',
+    required    => 1,
+);
+
 has 'is_global' => (
     is          => 'ro',
     isa         => 'Bool',
diff --git a/PlayBot/commands/parser.pm b/PlayBot/commands/parser.pm
index 4cb9ddb..1d0c917 100644
--- a/PlayBot/commands/parser.pm
+++ b/PlayBot/commands/parser.pm
@@ -94,9 +94,11 @@ sub exec {
             $irc->yield(privmsg => $chan => $insultes[rand @insultes]);
         };
     }
-    elsif ($msg =~ /^( *!get)( +.*)?$/) {
+    elsif ($msg =~ /^ *!(get|fts)( +.*)?$/) {
         my $query = $2;
-        my @args = ($chan, $query);
+        my $fts = $1 eq 'fts';
+        my @args = ($fts, $chan, $query);
+
         my $id = PlayBot::commands::get::exec(@args);
 
         if ($id) {
diff --git a/PlayBot/utils/db/get.pm b/PlayBot/utils/db/get.pm
index 6fd1a68..3da527d 100644
--- a/PlayBot/utils/db/get.pm
+++ b/PlayBot/utils/db/get.pm
@@ -149,18 +149,24 @@ sub _init {
 sub _prepare_request {
     my ($self, $query) = @_;
     
-    my @words_param;
     my $req;
     my @args;
+    my $words_sql;
+    my @words_param;
 
-    foreach (@{$query->words}) {
-        unshift @words_param, '%'.$_.'%';
+    if ($query->fts) {
+        @words_param = (join(' ', @{$query->words}));
+        $words_sql = 'match (sender, title) against (?)';
     }
+    else {
+        foreach (@{$query->words}) {
+            unshift @words_param, '%'.$_.'%';
+        }
 
-    my $words_sql;
-    foreach (@{$query->words}) {
-        $words_sql .= ' and ' if ($words_sql);
-        $words_sql .= "concat(p.sender, ' ', p.title) like ?";
+        foreach (@{$query->words}) {
+            $words_sql .= ' and ' if ($words_sql);
+            $words_sql .= "concat(p.sender, ' ', p.title) like ?";
+        }
     }
 
     if ($query->id >= 0) {
@@ -168,8 +174,10 @@ sub _prepare_request {
         $req .= ' from playbot p where id = ?';
 
         @args = ($query->id);
+        return ($req, @args);
     }
-    elsif (@{$query->tags}) {
+
+    if (@{$query->tags}) {
         my @where;
 
         foreach my $tag (@{$query->tags}) {
@@ -183,7 +191,7 @@ sub _prepare_request {
             $req .= ' from playbot p where '.$where;
             $req .= ' and '.$words_sql if ($words_sql);
             $req .= ' and p.playlist is false';
-            $req .= ' group by p.id order by rand()';
+            $req .= ' group by p.id';
 
             @args = (@{$query->tags}, @words_param);
         }
@@ -193,7 +201,7 @@ sub _prepare_request {
             $req .= ' where '.$where;
             $req .= ' and '.$words_sql if ($words_sql);
             $req .= ' and p.playlist is false';
-            $req .= ' and pc.chan = ? group by p.id order by rand()';
+            $req .= ' and pc.chan = ? group by p.id';
 
             @args = (@{$query->tags}, @words_param, $query->chan);
         }
@@ -204,7 +212,7 @@ sub _prepare_request {
             $req .= ' from playbot p where';
             $req .= ' '.$words_sql.' and' if ($words_sql);
             $req .= ' p.playlist is false';
-            $req .= ' group by p.id order by rand()';
+            $req .= ' group by p.id';
 
             @args = (@words_param);
         }
@@ -214,10 +222,20 @@ sub _prepare_request {
             $req .= ' where pc.chan = ?';
             $req .= ' and '.$words_sql if ($words_sql);
             $req .= ' and p.playlist is false';
-            $req .= ' group by p.id order by rand()';
+            $req .= ' group by p.id';
 
             @args = ($query->chan, @words_param);
         }
+
+    }
+
+
+    if ($query->fts and $words_sql) {
+        $req .= ' order by '.$words_sql.' desc';
+	push @args, @words_param;
+    }
+    else {
+        $req .= ' order by rand()';
     }
 
     return ($req, @args);
-- 
GitLab