package WebService::WordsAPI;
$WebService::WordsAPI::VERSION = '0.01';
use 5.006;
use Moo;
use JSON::MaybeXS;

has key => (
    is       => 'ro',
    required => 1,

has ua => (
    is      => 'ro',
    default => sub {
                   require HTTP::Tiny;
                   require IO::Socket::SSL;
                   return HTTP::Tiny->new;

has base_url => (
    is      => 'ro',
    default => sub { '' },

has return_type => (
    is      => 'ro',
    default => sub { 'perl' },

sub _request
    my ($self, $relurl) = @_;
    my $url             = $self->base_url.'/'.$relurl;
    my $headers         = {
                             "X-Mashape-Key" => $self->key,
                             "Accept"        => "application/json",
    my $response        = $self->ua->get($url, { headers => $headers });

    if (not $response->{success}) {
        die "failed $response->{status} $response->{reason}\n";

    return $self->return_type eq 'json'
           ? $response->{content}
           : decode_json($response->{content})

sub get_word_details
    my ($self, $word) = @_;

    return $self->_request($word);

sub rhymes_with
    my ($self, $word) = @_;

    return $self->_request($word.'/rhymes');

sub definitions
    my ($self, $word) = @_;

    return $self->_request($word.'/definitions');


=head1 NAME

WebService::WordsAPI - a draft Perl 5 interface to the WordsAPI service


 use WebService::WordsAPI;
 my $api = WebService::WordsAPI->new(key => '...');
 my $details = $api->get_word_details('plan');
 print $details->{results}[0]{definition}, "\n";


This module is an interface to the WordsAPI service,
which provides an API for getting information about words,
including definitions, pronunciations, number of syllables, and more.

This is very much a first cut at an interface,
so (a) the interface may well change, and
(b) contributions are welcome.

To use this module you need an API I<key> from L<>,
which is where WordsAPI is hosted.
They have a free level, which gets you 2500 lookups per day.

All of the instance methods take a word and by default
return a Perl data structure.
You can request to get back the underlying JSON response instead,
by setting the C<return_type> attribute.

=head1 METHODS

=head2 new

You must provide the B<key> that you got from rapidapi,
and can optionally specify the B<return_type>,
which should be C<'perl'> or C<'json'>.

 my $api = WebService::WordsAPI->new(
               key         => '...',
               return_type => 'json',

I figured people wouldn't want to vary the return type
on a method-by-method basis,
which is why it's not something you can specify on individual methods.

=head2 get_word_details

This is the main function of the API.
It takes a word and returns a structure with various bits of information.
You may get multiple entries in the result.
For example when looking up "wind", it can be a verb,
as in I<to wind a clock>,
and a noun,
as in I<the wind blew from the East>.

 my $details = $api->get_word_details('wind');
 foreach my $result (@{ $details->{results} }) {
   printf "%s: %s\n",

Look at the L<API documentation|>
to see exactly what is returned.

=head2 definitions

This returns just the definitions for the word.
As noted above, this may return multiple definitions:

 my $result = $api->definitions('wind');
 foreach my $entry (@{ $result->{definitions} }) {
   printf "%s: %s\n",

=head2 rhymes_with

This takes a word and returns one or more lists of words
that rhyme with the given word:

 my $results = $api->rhymes_with('wind');
 my $rhymes  = $results->{rhymes};

 foreach my $pos (keys %$rhymes) {
   my $words = @{ $rhymes->{ $pos } };
   print "\n$pos: @words\n";

=head1 SEE ALSO

L<> is the home page for the service;
documentation for the API can be found at L<>.



=head1 AUTHOR

Neil Bowers E<lt>neilb@cpan.orgE<gt>


This software is copyright (c) 2019 by Neil Bowers <>.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.