File Coverage

blib/lib/Finance/Currency/Convert/GMC.pm
Criterion Covered Total %
statement 44 52 84.6
branch 8 16 50.0
condition 2 2 100.0
subroutine 8 8 100.0
pod 2 2 100.0
total 64 80 80.0


line stmt bran cond sub pod time code
1             package Finance::Currency::Convert::GMC;
2              
3             our $DATE = '2017-07-10'; # DATE
4             our $VERSION = '0.003'; # VERSION
5              
6 2     2   34540 use 5.010001;
  2         9  
7 2     2   11 use strict;
  2         6  
  2         42  
8 2     2   11 use warnings;
  2         5  
  2         61  
9 2     2   7445 use Log::ger;
  2         228  
  2         13  
10              
11 2     2   2679 use Exporter 'import';
  2         6  
  2         1544  
12             our @EXPORT_OK = qw(get_currencies convert_currency);
13              
14             our %SPEC;
15              
16             my $url = "https://www.gmc.co.id/";
17              
18             $SPEC{':package'} = {
19             v => 1.1,
20             summary => 'Convert currency using GMC (Golden Money Changer) website',
21             description => <<"_",
22              
23             This module can extract currency rates from the Golden Money Changer website:
24              
25             $url
26              
27             Currently only conversions from a few currencies to Indonesian Rupiah (IDR) are
28             available.
29              
30             _
31             };
32              
33             $SPEC{get_currencies} = {
34             v => 1.1,
35             summary => 'Extract data from GMC page',
36             result => {
37             description => <<'_',
38             Will return a hash containing key `currencies`.
39              
40             The currencies is a hash with currency symbols as keys and prices as values.
41              
42             Tha values is a hash with these keys: `buy` and `sell`.
43              
44             _
45             },
46             };
47             sub get_currencies {
48 2     2 1 1516 require Mojo::DOM;
49             #require Parse::Number::ID;
50 2         220876 require Parse::Number::EN;
51              
52 2         785 my %args = @_;
53              
54             #return [543, "Test parse failure response"];
55              
56 2         6 my $page;
57 2 100       13 if ($args{_page_content}) {
58 1         5 $page = $args{_page_content};
59             } else {
60 1         621 require Mojo::UserAgent;
61 1         196848 my $ua = Mojo::UserAgent->new;
62 1         11 my $tx = $ua->get($url);
63 1 50       475310 unless ($tx->success) {
64 0         0 my $err = $tx->error;
65 0         0 return [500, "Can't retrieve GMC page ($url): ".
66             "$err->{code} - $err->{message}"];
67             }
68 1         26 $page = $tx->res->body;
69             }
70              
71 2         902 my $dom = Mojo::DOM->new($page);
72              
73 2         41645 my %currencies;
74 2         12 my $tbody = $dom->find("table#rate-table tbody")->[0];
75             $tbody->find("tr")->each(
76             sub {
77 20     20   4040 my $row0 = shift;
78             my $row = $row0->find("td")->map(
79 20         59 sub { $_->text })->to_array;
  60         7042  
80             #use DD; dd $row;
81 20 50       817 next unless $row->[0] =~ /\A[A-Z]{3}\z/;
82 20         62 $currencies{$row->[0]} = {
83             buy => Parse::Number::EN::parse_number_en(text=>$row->[1]),
84             sell => Parse::Number::EN::parse_number_en(text=>$row->[2]),
85             };
86             }
87 2         8296 );
88              
89 2 50       93 if (keys %currencies < 3) {
90 0         0 return [543, "Check: no/too few currencies found"];
91             }
92              
93             # XXX parse update dates (mtime_er, mtime_ttc, mtime_bn)
94 2         355 [200, "OK", {currencies=>\%currencies}];
95             }
96              
97             # used for testing only
98             our $_get_res;
99              
100             $SPEC{convert_currency} = {
101             v => 1.1,
102             summary => 'Convert currency using GMC',
103             description => <<'_',
104              
105             Currently can only handle conversion `to` IDR. Dies if given other currency.
106              
107             Will warn if failed getting currencies from the webpage.
108              
109             Currency rate is not cached (retrieved from the website every time). Employ your
110             own caching.
111              
112             Will return undef if no conversion rate is available for the requested currency.
113              
114             Use `get_currencies()`, which actually retrieves and scrapes the source web
115             page, if you need the more complete result.
116              
117             _
118             args => {
119             n => {
120             schema=>'float*',
121             req => 1,
122             pos => 0,
123             },
124             from => {
125             schema=>'str*',
126             req => 1,
127             pos => 1,
128             },
129             to => {
130             schema=>'str*',
131             req => 1,
132             pos => 2,
133             },
134             which => {
135             summary => 'Select which rate to use (default is `sell`)',
136             schema => ['str*', in=>['buy', 'sell']],
137             default => 'sell',
138             pos => 3,
139             },
140             },
141             args_as => 'array',
142             result_naked => 1,
143             };
144             sub convert_currency {
145 2     2 1 1056 my ($n, $from, $to, $which) = @_;
146              
147 2   100     10 $which //= 'sell';
148              
149 2 50       8 if (uc($to) ne 'IDR') {
150 0         0 die "Currently only conversion to IDR is supported".
151             " (you asked for conversion to '$to')\n";
152             }
153              
154 2 50       10 unless ($_get_res) {
155 0         0 $_get_res = get_currencies();
156 0 0       0 unless ($_get_res->[0] == 200) {
157 0         0 warn "Can't get currencies: $_get_res->[0] - $_get_res->[1]\n";
158 0         0 return undef;
159             }
160             }
161              
162 2 50       8 my $c = $_get_res->[2]{currencies}{uc $from} or return undef;
163              
164 2         4 my $rate;
165             #if ($which =~ /\Aavg_(.+)/) {
166             # $rate = ($c->{"buy_$1"} + $c->{"sell_$1"}) / 2;
167             #} else {
168 2         4 $rate = $c->{$which};
169             #}
170              
171 2         9 $n * $rate;
172             }
173              
174             1;
175             # ABSTRACT: Convert currency using GMC (Golden Money Changer) website
176              
177             __END__
178              
179             =pod
180              
181             =encoding UTF-8
182              
183             =head1 NAME
184              
185             Finance::Currency::Convert::GMC - Convert currency using GMC (Golden Money Changer) website
186              
187             =head1 VERSION
188              
189             This document describes version 0.003 of Finance::Currency::Convert::GMC (from Perl distribution Finance-Currency-Convert-GMC), released on 2017-07-10.
190              
191             =head1 SYNOPSIS
192              
193             use Finance::Currency::Convert::GMC qw(convert_currency);
194              
195             printf "1 USD = Rp %.0f\n", convert_currency(1, 'USD', 'IDR');
196              
197             =head1 DESCRIPTION
198              
199              
200             This module can extract currency rates from the Golden Money Changer website:
201              
202             https://www.gmc.co.id/
203              
204             Currently only conversions from a few currencies to Indonesian Rupiah (IDR) are
205             available.
206              
207             =head1 FUNCTIONS
208              
209              
210             =head2 convert_currency
211              
212             Usage:
213              
214             convert_currency($n, $from, $to, $which) -> any
215              
216             Convert currency using GMC.
217              
218             Currently can only handle conversion C<to> IDR. Dies if given other currency.
219              
220             Will warn if failed getting currencies from the webpage.
221              
222             Currency rate is not cached (retrieved from the website every time). Employ your
223             own caching.
224              
225             Will return undef if no conversion rate is available for the requested currency.
226              
227             Use C<get_currencies()>, which actually retrieves and scrapes the source web
228             page, if you need the more complete result.
229              
230             This function is not exported by default, but exportable.
231              
232             Arguments ('*' denotes required arguments):
233              
234             =over 4
235              
236             =item * B<$from>* => I<str>
237              
238             =item * B<$n>* => I<float>
239              
240             =item * B<$to>* => I<str>
241              
242             =item * B<$which> => I<str> (default: "sell")
243              
244             Select which rate to use (default is `sell`).
245              
246             =back
247              
248             Return value: (any)
249              
250              
251             =head2 get_currencies
252              
253             Usage:
254              
255             get_currencies() -> [status, msg, result, meta]
256              
257             Extract data from GMC page.
258              
259             This function is not exported by default, but exportable.
260              
261             No arguments.
262              
263             Returns an enveloped result (an array).
264              
265             First element (status) is an integer containing HTTP status code
266             (200 means OK, 4xx caller error, 5xx function error). Second element
267             (msg) is a string containing error message, or 'OK' if status is
268             200. Third element (result) is optional, the actual result. Fourth
269             element (meta) is called result metadata and is optional, a hash
270             that contains extra information.
271              
272             Return value: (any)
273              
274              
275             Will return a hash containing key C<currencies>.
276              
277             The currencies is a hash with currency symbols as keys and prices as values.
278              
279             Tha values is a hash with these keys: C<buy> and C<sell>.
280              
281             =head1 HOMEPAGE
282              
283             Please visit the project's homepage at L<https://metacpan.org/release/Finance-Currency-Convert-GMC>.
284              
285             =head1 SOURCE
286              
287             Source repository is at L<https://github.com/perlancar/perl-Finance-Currency-Convert-GMC>.
288              
289             =head1 BUGS
290              
291             Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Finance-Currency-Convert-GMC>
292              
293             When submitting a bug or request, please include a test-file or a
294             patch to an existing test-file that illustrates the bug or desired
295             feature.
296              
297             =head1 AUTHOR
298              
299             perlancar <perlancar@cpan.org>
300              
301             =head1 COPYRIGHT AND LICENSE
302              
303             This software is copyright (c) 2017, 2016 by perlancar@cpan.org.
304              
305             This is free software; you can redistribute it and/or modify it under
306             the same terms as the Perl 5 programming language system itself.
307              
308             =cut