#!/usr/local/bin/perl # WANT_JSON # yamd - client Yandex.Mail for Domain API # Run as stand-alone application or as Ansible module # # Copyright 2018 Sergey Kiselev # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # 3. Neither the name of the copyright holder nor the names of its # contributors may be used to endorse or promote products derived from this # software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. use strict; use warnings; our $VERSION = '0.1'; use File::Basename; use Encode qw/encode/; use YAML::XS qw/Load LoadFile/; use JSON::XS; use Types::Serialiser; use LWP::UserAgent; use HTTP::Request; our $api_url = "https://pddimp.yandex.ru/api2/admin"; our $api_requests = Load(<); close $fh; } else { # Stand-alone running with args in the YAML-file $task = %{LoadFile($task_file)}{yamd} or die "Unable to open file '" . $task_file ."'\n"; } } # Checking general mandatory parameters of the request foreach my $check ("query", "service", "token") { if (!defined $task->{$check}) { die "'" . $check . "' is undefined in '" . $task_file . "'\n"; } else { if (!ref($task->{$check})) { if ($task->{$check} =~ /^-?\d+\.?\d*/) { die "Incorrect value of '" . $check . "' in '" . $task_file . "'\n"; } } else { die "Incorrect value of '" . $check . "' in '" . $task_file . "'\n"; } } } my $request_url = ""; my $request_type = ""; my $request_content_type = ""; my $service = $task->{service}; my $sub_service = $task->{sub_service}; my $query = $task->{query}; my $options = $task->{options}; my $api_request = undef; my @check_list; # Checking mandatory parameters of the request if (defined $sub_service) { $api_request = $api_requests->{$service}->{$sub_service}->{$query}; } else { $api_request = $api_requests->{$service}->{$query}; } if (defined $api_request->{parameters}->{required}) { @check_list = @{$api_request->{parameters}->{required}}; } foreach my $check (@check_list) { if (defined $task->{$check}) { if (!ref($task->{$check})) { if ($task->{$check} =~ /^-?\d+\.?\d*/) { die "Incorrect value of '" . $check . "' in '" . $task_file . "'\n"; } } else { die "Incorrect value of '" . $check . "' in '" . $task_file . "'\n"; } } elsif (defined $options->{$check}) { if (!ref($options->{$check})) { if ($options->{$check} =~ /^-?\d+\.?\d*/) { die "Incorrect value of '" . $check . "' in '" . $task_file . "'\n"; } } else { die "Incorrect value of '" . $check . "' in '" . $task_file . "'\n"; } } else { die "'" . $check . "' is undefined in '" . $task_file . "'\n"; } } $request_url = $api_url . "/" . $service; $request_url .= (defined $sub_service) ? "/" . $sub_service : ""; $request_url .= "/" . $query; if ( $service eq "import" && $query eq "start_import_file" ) { $request_url .= "?domain=" . $task->{domain}; foreach my $k (keys %{$task->{options}}) { $request_url .= "&" . $k . "=" . $task->{options}->{$k}; } } if (defined $sub_service) { $request_type = $api_request->{query_type}; $request_content_type = $api_request->{content_type}; } else { $request_type = $api_request->{query_type}; $request_content_type = $api_request->{content_type}; } if (!defined $request_content_type) { $request_content_type = $api_requests->{default_content_type}; } if (!defined $sub_service) { $sub_service = ""; } my $ua = new LWP::UserAgent; my $request = new HTTP::Request($request_type => $request_url); if ( $service eq "domain" && $sub_service eq "logo" && $query eq "set" ) { { my $boundary = 'X'; my @rand = ('a'..'z', 'A'..'Z'); for (0..14) { $boundary .= $rand[rand(@rand)]; } $request->header( 'PddToken' => $task->{token}, 'Content-type' => $request_content_type . "; boundary=" . $boundary ); my $field = new HTTP::Message([ 'Content-Disposition' => 'form-data; name="domain"', 'Content-Type' => 'text/plain; charset=utf-8' ]); $field->add_content_utf8($task->{domain}); $request->add_part($field); open(my $fh, '<', $task->{options}->{file}); my $file_content = new HTTP::Message([ 'Content-Disposition' => 'form-data; name="file"; filename="logo"', 'Content-Type' => 'application/octet-stream' ]); $file_content->add_content($_) while <$fh>; $request->add_part($file_content); close $fh; } } elsif ( $task->{service} eq "import" && $task->{query} eq "start_import_file" ) { { my $boundary = 'X'; my @rand = ('a'..'z', 'A'..'Z'); for (0..14) { $boundary .= $rand[rand(@rand)]; } $request->header( 'PddToken' => $task->{token}, 'Content-type' => $request_content_type . "; boundary=" . $boundary ); open(my $fh, '<', $task->{options}->{file}); my $file_content = new HTTP::Message([ 'Content-Disposition' => 'form-data; name="import_list_file"; filename="import_list_file"', 'Content-Type' => 'text/plain', ]); $file_content->add_content($_) while <$fh>; $request->add_part($file_content); close $fh; } } else { { $request->header( 'PddToken' => $task->{token}, 'Content-type' => $request_content_type ); my $request_content = ""; if (defined $task->{domain}) { $request_content = "domain=" . $task->{domain}; } foreach my $k (keys %{$task->{options}}) { $request_content .= "&" . $k . "="; $request_content .= encode("utf8",$task->{options}->{$k}); } $request->content($request_content); } } my $response = $ua->request($request); if ($response->is_success) { print $response->content . "\n\n"; } else { print $response->status_line . "\n\n"; }