package Net::Cloudflare::DNS;

use 5.006;
use strict;
use warnings;
use JSON;
use URI;
use LWP::UserAgent;
use LWP::Protocol::https;
 
 
sub new {
    my $class = shift;
    my %args = @_;
    bless \%args, $class;
}
 
sub get_records {
    my $self = shift;
    my %args = @_;

    my $email = $self->{email};
    my $api_key = $self->{api_key};
    my $zone_id = $self->{zone_id};
    
    my $uri = URI->new("https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records");
    $uri->query_form(%args);

    my $ua = LWP::UserAgent->new;
    my %headers = (
        'Content-Type' => 'application/json',
        'X-Auth-Key'   => $api_key,
        'X-Auth-Email' => $email,
    );
 
    my $res = $ua->get($uri,
        %headers,
    );

    if ($res->is_success ) {
        return decode_json($res->decoded_content);
    } else {
        die $res->status_line, $res->decoded_content;
    }
}


sub create_record {
    my $self = shift;
    my %args = @_;

    my $data = encode_json(\%args);
    my $email = $self->{email};
    my $api_key = $self->{api_key};
    my $zone_id = $self->{zone_id};
    

    my $uri = "https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records";
    my $ua = LWP::UserAgent->new;
    my %headers = (
        'Content-Type' => 'application/json',
        'X-Auth-Key'   => $api_key,
        'X-Auth-Email' => $email,
    );
 
    my $res = $ua->post($uri,
        %headers,
        Content => $data,
    );

    if ($res->is_success ) {
        return decode_json($res->decoded_content);
    } else {
        die $res->status_line, $res->decoded_content;
    }
}

sub update_record {
    my $self = shift;
    my $record_id = shift;
    my %args = @_;

    my $data = encode_json(\%args);
    my $email = $self->{email};
    my $api_key = $self->{api_key};
    my $zone_id = $self->{zone_id};

    my $uri = "https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records/$record_id";
    my $ua = LWP::UserAgent->new;
    my %headers = (
        'Content-Type' => 'application/json',
        'X-Auth-Key'   => $api_key,
        'X-Auth-Email' => $email,
    );
 
    my $res = $ua->put($uri,
        %headers,
        Content => $data,
    );

    if ($res->is_success ) {
        return decode_json($res->decoded_content);
    } else {
        die $res->status_line, $res->decoded_content;
    }
}

sub delete_record {
    my $self = shift;
    my $record_id = shift;

    my $email = $self->{email};
    my $api_key = $self->{api_key};
    my $zone_id = $self->{zone_id};

    my $uri = "https://api.cloudflare.com/client/v4/zones/$zone_id/dns_records/$record_id";
    my $ua = LWP::UserAgent->new;
    my %headers = (
        'Content-Type' => 'application/json',
        'X-Auth-Key'   => $api_key,
        'X-Auth-Email' => $email,
    );
 
    my $res = $ua->delete($uri,
        %headers,
    );

    if ($res->is_success ) {
        return decode_json($res->decoded_content);
    } else {
        die $res->status_line, $res->decoded_content;
    }
}

=head1 NAME

Net::Cloudflare::DNS - DNS API for Cloudflare API v4 

=head1 VERSION

Version 0.15

=cut

our $VERSION = '0.15';


=head1 SYNOPSIS

This perl module is working for Cloudflare DNS API v4.

If you find any issues in using the module, please don't hesitate to email me: opensoft [at] posthub.me

My system is Ubuntu, to use the module, I have the following perl modules pre-installed in the system.

    sudo apt install libio-socket-ssl-perl
    sudo cpanm LWP::Protocol::https

After then, you can run "cpanm Net::Cloudflare::DNS" to install this module.

    use strict;
    use Net::Cloudflare::DNS;
    use Data::Dumper;

    my $api_key = " ";
    my $zone_id = " ";
    my $email = " ";

    # new the object
    my $dns = Net::Cloudflare::DNS->new(email=>$email, api_key=>$api_key, zone_id=>$zone_id);
    my $res;

    # create record
    $res = $dns->create_record(type=>"A", name=>"www.simplemail.co.in", content=>"74.81.81.81", proxied=>\1, ttl=>60);

    # get records
    $res = $dns->get_records(name=>"www.simplemail.co.in");

    # parse record id
    my $rid = $res->{result}->[0]->{id};

    # update record
    $res = $dns->update_record($rid, type=>"A", name=>"www.simplemail.co.in",content=>"52.1.14.22", proxied=>\0, ttl=>60);

    # delete record
    $res = $dns->delete_record($rid);

    # If it success, cloudflare's response is just resturned as a reference to you.
    # Otherwise the method just dies, you should catch the error in the code.
    print Dumper $res;


=head1 SUBROUTINES/METHODS

=head2 new

    my $dns = Net::Cloudflare::DNS->new(email=>$email, api_key=>$api_key, zone_id=>$zone_id);

You have to provide 3 arguments to new() method. The first is your registration email on Cloudflare. The second is your API Key, which can be 
found on Cloudflare's management panel ("Global API Key"). The last is Zone ID, each zone has the unique ID, which can be found
on zone's page.

Please notice: You must enable zone edit permissions for this API. In management panel, when you click "Create Token", you have the
chance to setup permissions for the zone, with which you can edit zone's DNS records. 
 

=head2 create_record

    my $res = $dns->create_record(type=>"A", name=>"www.simplemail.co.in",content=>"1.2.3.4",proxied=>\1,ttl=>1);

Create record in the zone.

You have to provide the following parameters.

type: includes "A", "TXT", "MX", "CNAME" ... They are standard DNS record types.

name: the hostname you want to create, such as www.

content: record value, for "A" record, it's an IP address.

ttl: time to live. You can set it to 1, which means to be automated by Cloudflare.

Optional parameters:

priority: MX priority, default 0.

proxied: whether proxied by cloudflare, it's either \1 (true) or \0 (false).

Please read their official documentation below.

    https://developers.cloudflare.com/api/#dns-records-for-a-zone-properties


=head2 update_record

    $res = $dns->update_record($record_id, type=>"TXT", name=>"www.simplemail.co.in",content=>"bala bala",ttl=>1);

Update record in the zone.

Please provide $record_id as the first argument, the rest are almost the same as create_record.

You can get $record_id from get_records method.


=head2 delete_record

    $res = $dns->delete_record($record_id);

Delete record from the zone.

Provide $record_id as the unique argument.


=head2 get_records

    $res = $dns->get_records(conditions...);

List records by conditions. For details please read the following documentation.

    https://developers.cloudflare.com/api/#dns-records-for-a-zone-properties



=head1 AUTHOR

Wesley Peng, C<< <wesley at cpan.org> >>

=head1 BUGS

Please report any bugs or feature requests to C<bug-net-cloudflare-dns at rt.cpan.org>, or through
the web interface at L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Net-Cloudflare-DNS>.  I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.




=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Net::Cloudflare::DNS


You can also look for information at:

=over 4

=item * RT: CPAN's request tracker (report bugs here)

L<https://rt.cpan.org/NoAuth/Bugs.html?Dist=Net-Cloudflare-DNS>

=item * CPAN Ratings

L<https://cpanratings.perl.org/d/Net-Cloudflare-DNS>

=item * Search CPAN

L<https://metacpan.org/release/Net-Cloudflare-DNS>

=back


=head1 ACKNOWLEDGEMENTS


=head1 LICENSE AND COPYRIGHT

This software is Copyright (c) 2020 by Wesley Peng.

This is free software, licensed under:

  The Artistic License 2.0 (GPL Compatible)


=cut

1; # End of Net::Cloudflare::DNS
