[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

updated module



Dunno where we're gonna store these, so everyone gets a copy...

I think I have all the bugs ironned out.  Here's a show of some of the new
improvements:

-- added spelling, using 'ispell' wasn't yielding beneficial results.
> spell apropoo
apropoo doesn't seem right, how about apropos
> spell apropos
"apropos" is a correct spelling. But other close matches are atropos or
aprosos

-- you can also check out what dictionaries are on the dictionary server
the infobot is using:
> dictionaries
Dictionaries I have:  hitchcock, jargon, easton, gazetteer, web1913,
elements, wn or foldoc
# and then query the dictionary:
> dictionary jargon
jargon: "Jargon File (4.0.0/24 July 1996)"

-- also gave support for quoting multi-worded queries:
> define "bit bucket"             
"bit bucket": No match, try using jargon or foldoc.
> define "bit bucket" using jargon
bit bucket /n./ 1. The universal data sink (originally, the mythical
receptacle used to catch bits when they fall off end of a register during
a shift instruction).  .....

Enjoy,
Jay
a.k.a teckle.
# 
#  Dict -- infobot module for Dictionary lookups.
# 	   requires the Net::Dict module.
#  By Jay Jacobs (teckle)
#

package Infobot::Module::Dict;


use strict;
use Infobot::Module;

$Infobot::Module::Dict::VERSION = "0.90_00";
$Infobot::Module{"Dict"} = $Infobot::Module::Dict::VERSION;
@Infobot::Module::Dict::ISA = qw(Infobot::Module);

my $anybad;

BEGIN {
    $anybad = '';
    eval { require Net::Dict};
    eval { require Data::Dumper};
    if ($@) {
      $anybad = "Net::Dict"; 
      warn "Infobot::Module::Dict requires $anybad to work"
          . "You can get it from htt://www.perl.com/CPAN/ or use "
          . "the CPAN installer:  "
          . "perl -MCPAN -e 'install $anybad'";
    }
}

sub new {
  return undef if $anybad;
  my $class = shift ;
  my $self  = $class->SUPER::new(@_);

  $self->weight(1); 

  $self->name('Dict');
  $self->regex(qr/^(?:(define|spell|dictionary)\s+(\"[-\w ]+\"|[-\w]+)|dictionaries)(?:\s+using\s+)?(\S+)?/i);
  $self->usage("define <word> [using DICT], where DICT is an accepted dictionary defaults to wordnet 'wn', plus a lot more");
  $self->descrip("Lookups up a word (or a close match) using the default 'wordnet' dictionary, or one specified, plus a lot more");
  ($anybad)?$self->enabled(1):$self->enabled(0);
  $self->dictserv('server1.shopthenet.net');
  $self->timeout('5');
  my $tserv = Net::Dict->new($self->dictserv, Timeout => $self->timeout);
  if (defined $tserv) {
    $self->{_serverInfo} = $tserv->serverInfo;
    %{$self->{_dictdb}} = $tserv->dbs;
  } else {
    print "Could not set up dictionary stuff\n";
    print "Server is ".$self->dictserv."; timeout is ".$self->timeout."\n";
  }
  bless $self, $class;
}

sub action {
  my $self = shift ;
  print Dumper $self;
  return undef unless defined $self and $self->enabled;

  my $message = shift; 
  return undef unless $message;
  my ($action, $word, $dict) = @{$message->get('args')};
  $dict = "wn" if (! defined $dict);
  my $Ret;
  if (lc($action) eq "define") {
    $self->status(3, "Defining \"$word\" in dictionary: \"$dict\"");
    $Ret = $self->givefull($word, $dict);
  } elsif (lc($action) eq "spell") {
    $self->status(3, "Checking the spelling of \"$word\" in dictionary: \"$dict\"");
    $Ret = $self->givespell($word, $dict);
  } elsif (lc($action) eq "dictionary") {
    $self->status(3, "Checking dictionary \"$word\"");
    $Ret = $self->lookatdict($word);
  } else {
    $Ret = "Dictionaries I have: ".$self->dictionaries;
  }
  return $Ret;
}

sub givefull {
  my $self = shift;
  my $server = Net::Dict->new($self->dictserv, Timeout => $self->timeout);
  return ("I can't reach my dictioncary right now") if (! defined $server);
  my ($word, $dict) = @_;
  my $h = $server->define($word);
  my ($i, $Ret, $dct, $def);
  my $found = 0;
  my @other_matches;
  if (! defined @{$h}) {
    $self->status(3, "No match Found at all, looking up alternatives");
    $Ret = findmatch($server, $dict, $word);
  } else {
    foreach $i (@{$h}) {
      ($dct, $def) = @{$i};
      if ($dct eq $dict) {
        foreach (split(/\n/, $def)) {
	  $_=~s/\s{3,}//g;
	  # $_=~s/\s+$//g;
	  $Ret.=$_." ";
        }
      } else {
        push(@other_matches, $dct);
      }
    }
    if (! $Ret) {
      $self->status(3, "match found in other dict, looking up alternatives");
      $Ret = findmatch($server, $dict, $word, @other_matches);
    }
  }
  return($Ret);
}

sub findmatch {
  my $server = shift;
  my $dict = shift;
  my $word = shift;
  my @other_matches = @_;
  my @others;
  my ($h, $i, $dct, $def);
  $h = $server->match($word, "lev");
  foreach $i (@{$h}) {
    ($dct, $def) = @{$i};
    push (@others, $def) if ($dct eq $dict);
  }
  if (@others) {
    my $str = gimmePretty(@others);
    if (@other_matches) {
      $str.="; or try using:".(gimmePretty(@other_matches));
    }
    return("$word: No Match. Perhaps you mean:$str");
  } elsif (@other_matches) {
    return("$word: No match, try using".(gimmePretty(@other_matches)).".");
  } else {
    return "$word: No matches found";
  }
}

sub givespell {
  my $self = shift;
  my $server = Net::Dict->new($self->dictserv, Timeout => $self->timeout);
  return ("I can't reach my dictioncary right now") if (! defined $server);
  my $word = shift;
  my $i;
  my %found;
  my $Ret;
  foreach $i (@{$server->match($word, "lev", (keys %{$self->{_dictdb}}))}) {
    $$i[1]=~s/\"//g;
    $found{lc($$i[1])} = undef;
  }
  if (exists $found{lc($word)}) {
    $Ret = "\"$word\" is a correct spelling. But other close matches are";
    delete $found{lc($word)};
  } else {
    $Ret = "$word doesn't seem right, how about";
  }
  if (keys %found) {
    $Ret .= gimmePretty(keys %found);
  } else {
    return "I can't find any word close to \"$word\"";
  }
}
  
sub lookatdict {
  my $self = shift;
  return "$_[0]: ".$self->{_dictdb}{$_[0]} if (defined $self->{_dictdb}{$_[0]});
  return "No such dictionary, I do have: ".($self->dictionaries);
}

sub dictionaries {
  my $self = shift;
  return gimmePretty(keys %{$self->{_dictdb}});
}

sub dictserv {
  my $self = shift;
  $self->{dictserv} = shift if (@_);
  return $self->{dictserv};
}

sub timeout {
  my $self = shift;
  $self->{timeout} = shift if (@_);
  return $self->{timeout};
}

sub gimmePretty {
  my @words = @_;
  my $str = "";
  if ($#words>=1) {
    for (0..($#words-1)) {
      $words[$_]=~s/"//g;
      $str .= " $words[$_],";
    }
    chop($str);
    $str .= " or";
  }
  $words[$#words]=~s/"//g;
  $str .= " ".$words[$#words];
  return($str);
}
1;

=pod

=head1 NAME

Infobot::Module::Dict - Word definition module for infobot

=head1 SYNOPSIS

define <word> [using <dictionary>]

=head1 DESCRIPTION

Uses the Net::Dict module to lookup a word for a specific 
dictionary.  If the dictionary isn't specified, it will 
default to use the "wordnet" (wn) dictionary.  It will try
to return a definition from the dictionary, if it doesn't
find one, it will try to find close matches using the 
Levensetein distance one matching strategy.  If it found
the word in other dictionaries, it will also mention those
as a possible place to look.

=head1 AUTHORS

Jay Jacobs (teckle)
jjacobs@securetty.org