# # 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 [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 [using ] =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