package Pcore::API::Proxy::airsocks; use Pcore -class, -res, -const; use Pcore::API::Proxy; our $EXPORT = { AIRSOCKS_FP => [qw[$AIRSOCKS_FP_WIN $AIRSOCKS_FP_WIN_FUZZY $AIRSOCKS_FP_WINXP $AIRSOCKS_FP_ANDROID $AIRSOCKS_FP_MACOS $AIRSOCKS_FP_IOS $AIRSOCKS_FP_NT $AIRSOCKS_FP_NT_FUZZY $AIRSOCKS_FP_UNKNOWN]], }; has proxy => ( required => 1 ); has session_key => ( required => 1 ); has channel_id => ( required => 1 ); has changed => ( init_arg => undef ); has ip => ( init_arg => undef ); has fp => ( init_arg => undef ); has _change_ip_url => ( init_arg => undef ); has _status_url => ( init_arg => undef ); const our $AIRSOCKS_FP_WIN => 'win'; # Windows 7 or 8 (and Windows 8.1) const our $AIRSOCKS_FP_WIN_FUZZY => 'win fuzzy'; # Windows 7 or 8 [fuzzy] is common on Windows Server 2012 const our $AIRSOCKS_FP_WINXP => 'winxp'; # Windows XP: const our $AIRSOCKS_FP_ANDROID => 'android'; # Android (Linux 2.2.x-3.x): const our $AIRSOCKS_FP_MACOS => 'isfuzzy'; # 'Mac OS X [generic][fuzzy]' (MacBook / OS X / iPhone) const our $AIRSOCKS_FP_IOS => 'ios'; # 'MacOS X [generic]' less popular option for MacBook / OS X / iPhone const our $AIRSOCKS_FP_NT => 'net generic'; # 'Windows NT [generic]' which is the most common OS currently Windows 10 / Windows 2016 Server. const our $AIRSOCKS_FP_NT_FUZZY => 'ntfuzzy'; # 'Windows NT [generic][fuzzy]' is an option for Windows 10 / Windows 2016 Server. const our $AIRSOCKS_FP_UNKNOWN => 'unknown'; # '???'in the system definition. In other words, Passive OS Fingerprint (TCP/IP) will be hidden. around new => sub ( $orig, $self, $url, $key ) { $url = P->uri($url); my $args = { proxy => Pcore::API::Proxy->new($url), session_key => $key, channel_id => substr( $url->{port}, -1, 1 ), }; return $self->$orig($args); }; sub change_ip ( $self, $nowait = undef ) { my $url = $self->{_change_ip_url} //= P->uri("http://$self->{proxy}->{uri}->{host}/api/v3/changer_channels/channel_$self->{channel_id}?session=$self->{session_key}"); REDO: my $res = P->http->get($url); if ($res) { if ( $res->{data}->$* =~ /wait\s+(\d+)s/sm ) { return res 400 if $nowait; Coro::sleep( $1 + 1 ); goto REDO; } my $headers; for my $line ( split /\n/sm, $res->{data}->$* ) { my ( $k, $v ) = split /:\s*/sm, $line, 2; $headers->{ lc $k } = $v; } $self->{ip} = $headers->{newip}; $self->{fp} = $headers->{osfingeprint}; $self->{changed} = $headers->{at}; } return res $res; } # TODO # &fp= sub change_fp ( $self, $fp ) { my $url = P->uri( "http://$self->{proxy}->{uri}->{host}/api/v3/changer_channels/channel_$self->{channel_id}?session=$self->{session_key}&fp=" . P->data->to_uri($fp) ); my $res = P->http->get($url); return $res; } # TODO sub get_status ($self) { my $url = $self->{_status_url} //= P->uri("http://$self->{proxy}->{uri}->{host}/api/v3/changer_channels/channel_$self->{channel_id}/status?session=$self->{session_key}"); my $res = P->http->get($url); return $res; } 1; __END__ =pod =encoding utf8 =head1 NAME Pcore::API::Proxy::airsocks =head1 SYNOPSIS use Pcore::API::Proxy::Airsocks; my $proxy = Pcore::API::Proxy::Airsocks->new( 'connect://user:password@host:port', 'session_key' ); P->http->get( $url, $proxy => proxy->{proxy} ); $proxy->change_ip; =head1 DESCRIPTION =head1 ATTRIBUTES =head1 METHODS =head1 SEE ALSO =cut