Files
ytmusicapi-perl/YTMusicAPI/Auth/OAuth/OAuthCredentials.pm
mschuepbach 8c0319f293 Add OAuth
2024-03-27 15:25:17 +01:00

110 lines
2.9 KiB
Perl

package YTMusicAPI::Auth::OAuth::OAuthCredentials;
use strict;
use warnings;
use JSON;
use LWP::UserAgent;
use Data::Dumper;
use YTMusicAPI::Constants qw(
OAUTH_CLIENT_ID
OAUTH_CLIENT_SECRET
OAUTH_CODE_URL
OAUTH_SCOPE
OAUTH_TOKEN_URL
OAUTH_USER_AGENT
);
sub new {
my ( $class, $args ) = @_;
unless ( defined $args->{client_id} == defined $args->{client_secret} ) {
die "OAuthCredential init failure. "
. "Provide both client_id and client_secret or neither.";
}
my $self = {};
bless $self, $class;
$self->{client_id} =
$args->{client_id} ? $args->{client_id} : OAUTH_CLIENT_ID;
$self->{client_secret} =
$args->{client_secret} ? $args->{client_secret} : OAUTH_CLIENT_SECRET;
$self->{_session} =
$args->{session} ? $args->{session} : LWP::UserAgent->new;
if ( $args->{proxies} ) {
@$self->{_session}{ keys %{ $args->{proxies} } } =
values %{ $args->{proxies} };
}
return $self;
}
sub get_code {
my ($self) = @_;
my $code_response =
$self->_send_request( OAUTH_CODE_URL, { "scope" => OAUTH_SCOPE } );
return decode_json( $code_response->decoded_content );
}
sub _send_request {
my ( $self, $url, $data ) = @_;
$data->{"client_id"} = $self->{client_id};
my $request = HTTP::Request->new( POST => $url );
$request->header( "User-Agent" => OAUTH_USER_AGENT );
$request->content( encode_json($data) );
my $response = $self->{_session}->request($request);
if ( $response->code == 401 ) {
my $data = $response->decode_json;
my $issue = $data->{"error"};
if ( $issue eq "unauthorized_client" ) {
die "Token refresh error. Most likely client/token mismatch.";
}
elsif ( $issue eq "invalid_client" ) {
die "OAuth client failure. Most likely client_id and client_secret "
. "mismatch or YouTubeData API is not enabled.";
}
else {
die "OAuth request error. status_code: "
. $response->code
. ", url: $url, content: "
. Dumper($data);
}
}
return $response;
}
sub token_from_code {
my ( $self, $device_code ) = @_;
my $response = $self->_send_request(
OAUTH_TOKEN_URL,
{
"client_secret" => $self->{client_secret},
"grant_type" => "http://oauth.net/grant_type/device/1.0",
"code" => $device_code,
}
);
return decode_json( $response->decoded_content );
}
sub refresh_token {
my ( $self, $refresh_token ) = @_;
my $response = $self->_send_request(
OAUTH_TOKEN_URL,
{
"client_secret" => $self->{client_secret},
"grant_type" => "refresh_token",
"refresh_token" => $refresh_token,
}
);
return decode_json( $response->decoded_content );
}
1;