120 lines
3.3 KiB
Perl
120 lines
3.3 KiB
Perl
package DDG::Goodie::CallingCodes;
|
|
# ABSTRACT: Matches country names to international calling codes
|
|
|
|
use strict;
|
|
use DDG::Goodie;
|
|
use Locale::Country qw/country2code code2country/;
|
|
use Telephony::CountryDialingCodes;
|
|
|
|
zci answer_type => "calling_codes";
|
|
zci is_cached => 1;
|
|
|
|
my @codewords = qw(code codes);
|
|
my @descriptors = ('calling', 'dialing', 'dial-in', 'dial in');
|
|
my @extras = qw(international country);
|
|
|
|
my @triggers;
|
|
foreach my $cw (@codewords) {
|
|
foreach my $desc (@descriptors) {
|
|
push @triggers, $desc . ' ' . $cw;
|
|
foreach my $extra (@extras) {
|
|
push @triggers, join(' ', $extra, $desc, $cw);
|
|
}
|
|
}
|
|
}
|
|
|
|
triggers any => @triggers;
|
|
|
|
handle remainder => sub {
|
|
my $query = shift;
|
|
|
|
my ($dialing_code, @countries);
|
|
|
|
my $in_number;
|
|
if ($query =~ /^\+?(\d+)/) {
|
|
$in_number = $1;
|
|
# $query looks like a phone number. eg +65
|
|
($dialing_code, @countries) = number_to_country($in_number);
|
|
} elsif ($query =~ /^\w+/) {
|
|
# $query looks like a country name or country code. eg Brazil or Br
|
|
($dialing_code, @countries) = country_to_calling_code($query);
|
|
}
|
|
|
|
return unless $dialing_code && @countries && (defined $countries[0]);
|
|
|
|
$dialing_code = '+' . $dialing_code;
|
|
my $country_list = list2string(@countries);
|
|
|
|
return $dialing_code . ' is the international calling code for ' . $country_list . '.',
|
|
structured_answer => {
|
|
data => {
|
|
title => $in_number ? $country_list : $dialing_code,
|
|
subtitle => 'International calling code: ' . ($in_number ? $dialing_code : $country_list)
|
|
},
|
|
templates => {
|
|
group => 'text'
|
|
}
|
|
};
|
|
};
|
|
|
|
# Convert a list of country names to a single human readable English string.
|
|
sub list2string {
|
|
my @countries = @_;
|
|
my $string;
|
|
|
|
$_ =~ s/^The /the / for @countries;
|
|
|
|
if (scalar @countries == 1) {
|
|
$string = $countries[0];
|
|
}
|
|
elsif (scalar @countries == 2) {
|
|
$string = $countries[0] . " and " . $countries[1];
|
|
}
|
|
else {
|
|
my $last = pop @countries;
|
|
$string = join ', ', @countries;
|
|
$string .= ", and " . $last;
|
|
}
|
|
|
|
return $string;
|
|
}
|
|
|
|
# Deduce the country from a number.
|
|
sub number_to_country {
|
|
my $number = shift;
|
|
|
|
my $telephony = Telephony::CountryDialingCodes->new;
|
|
my @country_codes = $telephony->country_codes($number);
|
|
my $dialing_code = $telephony->extract_dialing_code($number);
|
|
my @countries = map { code2country($_) } @country_codes;
|
|
|
|
return ($dialing_code, @countries);
|
|
}
|
|
|
|
# Deduce the calling code from a country name or country code.
|
|
sub country_to_calling_code {
|
|
my $country = shift;
|
|
|
|
# clean up
|
|
$country =~ s/^to\s+//;
|
|
$country =~ s/^for\s+//;
|
|
$country =~ s/^in\s+//;
|
|
$country =~ s/^the\s+//;
|
|
$country =~ s/\s+\+?\d+$//; # remove trailing phone code. for queries
|
|
# like 'calling code for brazil +55'
|
|
|
|
my $country_code = country2code($country);
|
|
|
|
# if we didn't find a country code, maybe $country is a country_code
|
|
$country_code = $country unless $country_code;
|
|
|
|
$country = code2country($country_code);
|
|
|
|
my $telephony = Telephony::CountryDialingCodes->new;
|
|
my $dialing_code = $telephony->dialing_code($country_code);
|
|
|
|
return ($dialing_code, $country);
|
|
}
|
|
|
|
1;
|