Aion-Surf

 view release on metacpan or  search on metacpan

lib/Aion/Surf.pm  view on Meta::CPAN

use common::sense;

our $VERSION = "0.0.3";

use List::Util qw/pairmap/;
use LWP::UserAgent qw//;
use HTTP::Cookies qw//;
use Aion::Format::Json qw//;
use Aion::Format::Url qw//;

use Exporter qw/import/;
our @EXPORT = our @EXPORT_OK = grep {
	ref \$Aion::Surf::{$_} eq "GLOB"
		&& *{$Aion::Surf::{$_}}{CODE}
			&& !/^(_|(NaN|import)\z)/n
} keys %Aion::Surf::;


#@category surf

use config TIMEOUT => 10;
use config FROM_IP => undef;
use config AGENT => q{Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15};

our $ua = LWP::UserAgent->new;
$ua->agent(AGENT);
#$ua->env_proxy;
$ua->timeout(TIMEOUT);
$ua->local_address(FROM_IP) if FROM_IP;
$ua->cookie_jar(HTTP::Cookies->new);

# Между вызовами делаем случайный интервал (для граббинга - чтобы не быть заблокированным за автоматические обращения)
our $SLEEP = 0;
our $LAST_REQUEST = Time::HiRes::time();
sub _sleep(;$) {
	Time::HiRes::sleep(rand + .5) if Time::HiRes::time() - $LAST_REQUEST < 2;
	$LAST_REQUEST = Time::HiRes::time();
}

sub surf(@) {
	my $method = $_[0] =~ /^(\w+)\z/ ? shift: "GET";
	my $url = shift;
	my $headers;
	my $data = ref $_[0]? shift: undef;
	$headers = $data, undef $data if $method =~ /^(GET|HEAD)\z/n;

	my %set = @_;

	if(exists $set{sleep}) {
		my $sleep = delete $set{sleep};
	} else {
		_sleep if $SLEEP;
	}

	my $query = delete $set{query};
	if(defined $query) {
		$url = join "", $url, $url =~ /\?/ ? "&": "?",
			Aion::Format::Url::to_url_params $query;
	}

	my $request = HTTP::Request->new($method => $url);

	my $validate_data = sub {
		die "surf: data has already been provided!" if defined $data;
		die "surf: sended data in $method!" if $method =~ /^(HEAD|GET)\z/;
	};

	# Устанавливаем данные
	my $json = delete $set{json};
	$json = $data, undef $data if not defined $json and ref $data eq "HASH";
	if(defined $json) {
		$validate_data->();

		$request->header('Content-Type' => 'application/json; charset=utf-8');
		$data = Aion::Format::Json::to_json $json;
		utf8::encode($data) if utf8::is_utf8($data);
		$request->content($data);
	}

	my $form = delete $set{form};
	$form = $data, undef $data if not defined $form and ref $data eq "ARRAY";
	if(defined $form) {
		$validate_data->();
		$data = 1;

		$request->header('Content-Type' => 'application/x-www-form-urlencoded');
		$request->content(Aion::Format::Url::to_url_params $form);
	}

	if($headers = delete($set{headers}) // $headers) {
		if(ref $headers eq 'HASH') {
			$request->header($_, $headers->{$_}) for sort keys %$headers;
		} else {
			for my ($key, $val) (@$headers) {
				$request->header($key, $val);
			}
		}
	}

	if(my $cookie_href = delete $set{cookies}) {
		my $jar = $ua->cookie_jar;
		my $url_href = Aion::Format::Url::parse_url $url;
		my $domain = $url_href->{domain};
		$domain = "localhost.local" if $domain eq "localhost";

		$cookie_href = {@$cookie_href} if ref $cookie_href eq "ARRAY";

		for my $key (sort keys %$cookie_href) {

			my $av;
			my $val = $cookie_href->{$key};
			$av = $val, $val = shift @$av, $av = {@$av} if ref $val;

			$jar->set_cookie(
				delete($a->{version}),
				Aion::Format::Url::to_url_param $key
					=> Aion::Format::Url::to_url_param $val,
				delete($av->{path}) // "/",
				delete($av->{domain}) // $domain,
				delete($av->{port}),
				delete($av->{path_spec}),

lib/Aion/Surf.pm  view on Meta::CPAN

	chat_message "ABCD", "hi!"  # --> {ok => 1}

=head2 bot_message (;$message)

Sends a message to a telegram bot.

	bot_message "hi!" # --> {ok => 1}

=head2 tech_message (;$message)

Sends a message to a technical telegram channel.

	tech_message "hi!" # --> {ok => 1}

=head2 bot_update ()

Receives the latest messages sent to the bot.

	# mock
	*LWP::UserAgent::request = sub {
	    my ($ua, $request) = @_;
	
	    my $offset = from_json($request->content)->{offset};
	    if($offset) {
	        return HTTP::Response->new(200, "OK", undef, to_json {
	            ok => 1,
	            result => [],
	        });
	    }
	
	    HTTP::Response->new(200, "OK", undef, to_json {
	        ok => 1,
	        result => [{
	            message => "hi!",
	            update_id => 0,
	        }],
	    });
	};
	
	bot_update  # --> ["hi!"]
	
	
	# mock
	*LWP::UserAgent::request = sub {
	    HTTP::Response->new(200, "OK", undef, to_json {
	        ok => 0,
	        description => "nooo!"
	    })
	};
	
	eval { bot_update }; $@  # ~> nooo!

=head1 SEE ALSO

=over

=item * LWP::Simple

=item * LWP::Simple::Post

=item * HTTP::Request::Common

=item * WWW::Mechanize

=item * LLL<https://habr.com/ru/articles/63432/>

=back

=head1 AUTHOR

Yaroslav O. Kosmina LL<mailto:dart@cpan.org>

=head1 LICENSE

âš– B<GPLv3>

=head1 COPYRIGHT

The Aion::Surf module is copyright © 2023 Yaroslav O. Kosmina. Rusland. All rights reserved.



( run in 1.068 second using v1.01-cache-2.11-cpan-ceb78f64989 )