faq engine for gemini with full text search
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

75 lines
2.1 KiB

#!/usr/bin/perl
# Copyright René Wagner 2020
# licenced under BSD 3-Clause licence
# https://src.clttr.info/rwa/gmnifaq
use strict;
use DBI;
use URI::Escape;
use lib 'lib/';
use gmnifaq;
config();
# enable UTF-8 mode for everything
use utf8;
binmode STDOUT, ':utf8';
binmode STDERR, ':utf8';
if (!defined($ENV{'SERVER_PROTOCOL'}) || $ENV{'SERVER_PROTOCOL'} ne 'GEMINI') {
write_response('CGI_ERROR', 'CGI execution error', undef);
}
my $query = lc(uri_unescape($ENV{'QUERY_STRING'}));
if ($query eq '' || $query !~ /^[0-9a-z\s]*$/i)
{
write_response('INPUT', 'Search faqs for the following terms (separate by blank, all terms must match)', undef);
}
my @body = ();
push @body, header();
push @body, search($query);
push @body, footer();
write_response('SUCCESS', 'text/gemini', @body);
exit;
sub search
{
my ($term) = @_;
my @result = ();
my $dbh = DBI->connect($CONF{'dsn'}, '', '', { RaiseError => 1 }) or die $DBI::errstr;
my $fts_search = join(' AND ', split(/ /, $term));
my @matchingtags = $dbh->selectall_array("SELECT DISTINCT t.*, count(tq.q_id) AS count FROM fts_data INNER JOIN tags t ON t.id = fts_data.t_id LEFT JOIN tags_questions tq ON tq.t_id = t.id WHERE fts_data MATCH '$fts_search' GROUP BY t.id ORDER BY rank");
my @matchingfaqs = $dbh->selectall_array("SELECT DISTINCT q_id, q.question FROM fts_data INNER JOIN questions q ON q.id = q_id WHERE fts_data MATCH '$fts_search' ORDER BY rank;");
$dbh->disconnect();
if ( !scalar @matchingtags && !scalar @matchingfaqs) {
push @result, ('Sorry, we can\'t find an entry that matches your search data.', '');
}
if ( scalar @matchingtags) {
push @result, ('## matching tags', '');
foreach (@matchingtags) {
push @result, sprintf("=> ./faqs.pl?tag=%d %s (%d entrys)", @$_[0], @$_[1], @$_[2]);
}
push @result, '';
}
if ( scalar @matchingfaqs) {
push @result, ('## matching FAQs', '');
foreach (@matchingfaqs) {
push @result, sprintf("=> ./faqs.pl?faq=%d %s", @$_[0], @$_[1]);
}
}
push @result, ('', '=> ./search.pl search again');
return @result;
}
sub header
{
return ('# '. $CONF{'name'}, '', "Matching results for your search term '$query':", '');
}