From 42cb995dc7ee11e6daac1c9fa06380bf9261ed3c Mon Sep 17 00:00:00 2001 From: Alexandre Morignot <erdnaxeli@cervoi.se> Date: Mon, 1 Nov 2021 23:12:58 +0100 Subject: [PATCH] Implement new soundcloud auth --- PlayBot/sessions/irc.pm | 10 ++- PlayBot/sites/soundcloud.pm | 168 ++++++++++++++++++++---------------- playbot-example.conf | 1 + 3 files changed, 101 insertions(+), 78 deletions(-) diff --git a/PlayBot/sessions/irc.pm b/PlayBot/sessions/irc.pm index 1c75cc5..f78870b 100644 --- a/PlayBot/sessions/irc.pm +++ b/PlayBot/sessions/irc.pm @@ -15,6 +15,7 @@ use Module::Reload; use PlayBot::utils::Logging; use PlayBot::sessions::irc::later; use PlayBot::sites; +use PlayBot::sites::soundcloud; use PlayBot::commands::parser; my $log = PlayBot::utils::Logging->new('STDOUT', 1); @@ -24,7 +25,7 @@ open CONF, '<', 'playbot.conf'; my $json = <CONF>; my $conf = decode_json($json); -## CONNEXION +## CONNEXION my ($irc) = POE::Component::IRC::State->spawn(); my $dbh = DBI->connect('DBI:mysql:'.$conf->{'bdd'}.';host='.$conf->{'host'}, $conf->{'user'}, $conf->{'passwd'}, { PrintError => 0, @@ -113,12 +114,13 @@ sub cycle } -sub setConf +sub setConf { PlayBot::commands::parser::setConf($irc, $dbh, $log, \%lastID); $PlayBot::sites::irc = $irc; $PlayBot::sites::log = $log; + $PlayBot::sites::soundcloud::clientSecret = $conf->{'soundcloud_secret'}; } @@ -135,7 +137,7 @@ sub bot_start { $irc->yield( connect => { Nick => $nick, - Username => $username, + Username => $username, Ircname => $ircname, Server => $serveur, Port => $port, @@ -177,7 +179,7 @@ sub on_query return if (PlayBot::commands::parser::exec(@args)); if ($msg =~ m/^!/ && $nick eq $admin) { - my $commande = ( $msg =~ m/^!([^ ]*)/ )[0]; + my $commande = ( $msg =~ m/^!([^ ]*)/ )[0]; my @params = grep {!/^\s*$/} split(/\s+/, substr($msg, length("!$commande"))); foreach (keys(%commandes_admin)) { diff --git a/PlayBot/sites/soundcloud.pm b/PlayBot/sites/soundcloud.pm index 145f9d1..98e85ea 100644 --- a/PlayBot/sites/soundcloud.pm +++ b/PlayBot/sites/soundcloud.pm @@ -12,117 +12,137 @@ use PlayBot::utils::Logging; my $log = PlayBot::utils::Logging->new('STDOUT', 1); -my $root = 'http://api.soundcloud.com'; +my $root = 'https://api.soundcloud.com'; my $clientId = 'f4956716fe1a9dc9c3725af822963365'; +our $clientSecret; +my $access_token = ''; +my $access_token_time; sub regex_playlist { - return qr#(?:^|[^!])https?://(?:www\.)?soundcloud.com/([a-zA-Z0-9_-]+/sets/[a-zA-Z0-9_-]+)(?:\?.+)?#; + return qr#(?:^|[^!])https?://(?:www\.)?soundcloud.com/([a-zA-Z0-9_-]+/sets/[a-zA-Z0-9_-]+)(?:\?.+)?#; } -sub regex +sub regex { - return qr#(?:^|[^!])https?://(?:www\.)?soundcloud.com/([a-zA-Z0-9_-]+/[a-zA-Z0-9_-]+)(?:\?.+)?#; + return qr#(?:^|[^!])https?://(?:www\.)?soundcloud.com/([a-zA-Z0-9_-]+/[a-zA-Z0-9_-]+)(?:\?.+)?#; +} + +sub get_access_token +{ + if ($access_token ne '' && time() - $access_token_time <= 3000) + { + return $access_token; + } + + $log->info("Get a new soundcloud token"); + + my $ua = LWP::UserAgent->new( + timeout => 30, + env_proxy => 1, + ); + $log->info("the url is ".$root.'/oauth2/token?grant_type=client_credentials&client_id='.$clientId.'&client_secret='.$clientSecret); + my $response = $ua->post( + $root.'/oauth2/token?grant_type=client_credentials&client_id='.$clientId.'&client_secret='.$clientSecret, + ); + die($response->status_line) unless ($response->is_success); + + my $content = decode_json($response->decoded_content); + $access_token = $content->{'access_token'}; + $access_token_time = time(); + + return $access_token; } sub get_playlist { - shift; - my $id = shift; + shift; + my $id = shift; my $ua = LWP::UserAgent->new( - timeout => 30, - env_proxy => 1, - ); - - my $response; - if (looks_like_number($id)) - { - $response = $ua->get($root.'/playlists/'.$id.'?client_id='.$clientId); - } - else - { - my $url = 'https://www.soundcloud.com/'.$id; - $response = $ua->get($root.'/resolve.json?url='.$url.'&client_id='.$clientId); - } + timeout => 30, + env_proxy => 1, + ); + + my $response; + if (looks_like_number($id)) + { + $response = $ua->get($root.'/playlists/'.$id.'?client_id='.$clientId); + } + else + { + my $url = 'https://www.soundcloud.com/'.$id; + $response = $ua->get($root.'/resolve.json?url='.$url.'&client_id='.$clientId); + } die($response->status_line) unless ($response->is_success); my $content = decode_json($response->decoded_content); - my $infos = { - author => $content->{'user'}->{'username'}, - external_id => $content->{'id'}, - duration => $content->{'track_count'}, - site => 'soundcloud', - title => $content->{'title'}, - url => $content->{permalink_url}, - }; - - my @urls; - foreach my $item (@{ $content->{'tracks'} }) - { - push @urls, $item->{'permalink_url'}; - } - - $infos->{'urls'} = \@urls; + my $infos = { + author => $content->{'user'}->{'username'}, + external_id => $content->{'id'}, + duration => $content->{'track_count'}, + site => 'soundcloud', + title => $content->{'title'}, + url => $content->{permalink_url}, + }; + + my @urls; + foreach my $item (@{ $content->{'tracks'} }) + { + push @urls, $item->{'permalink_url'}; + } + + $infos->{'urls'} = \@urls; return %$infos; } sub get { - shift; + shift; my $id = shift; my $ua = LWP::UserAgent->new( - timeout => 30, - env_proxy => 1, - ); - - my $response; - $log->info("the id is ".$id); - - my $retries = 0; - while ($retries < 10) { - $log->info("Soundcloud API is half break, try number ".($retries + 1)); - - if (looks_like_number($id)) - { - $response = $ua->get($root.'/tracks/'.$id.'?client_id='.$clientId); - } - else - { - my $url = 'https://www.soundcloud.com/'.$id; - $log->info("the url is ".$root.'/resolve.json?url='.$url.'&client_id='.$clientId); - $response = $ua->get($root.'/resolve.json?url='.$url.'&client_id='.$clientId); - } - - if ($response->code == 404) + timeout => 30, + env_proxy => 1, + ); + + my $response; + $log->info("the id is ".$id); + + if (looks_like_number($id)) { - $retries++; - sleep(1); + $response = $ua->get( + $root.'/tracks/'.$id, + 'Authorization' => 'OAuth '.get_access_token(), + ); } else { - last; + my $url = 'https://soundcloud.com/'.$id; + $response = $ua->get( + $root.'/resolve?url='.$url, + 'Authorization' => 'OAuth '.get_access_token(), + ); } - } - die($response->status_line) unless ($response->is_success); + + die($response->status_line) unless ($response->is_success); my $content = decode_json($response->decoded_content); - my $infos = { - author => $content->{'user'}->{'username'}, - external_id => $content->{'id'}, - duration => int(0.5 + $content->{'duration'} / 1000), - site => 'soundcloud', - title => $content->{'title'}, - url => $content->{permalink_url}, - }; + my $infos = { + author => $content->{'user'}->{'username'}, + external_id => $content->{'id'}, + duration => int(0.5 + $content->{'duration'} / 1000), + site => 'soundcloud', + title => $content->{'title'}, + url => $content->{permalink_url}, + }; if ($content->{'downloadable'}) { $infos->{'ddl'} = $content->{'download_url'}; } - + return %$infos; } diff --git a/playbot-example.conf b/playbot-example.conf index 8167035..ceb555b 100644 --- a/playbot-example.conf +++ b/playbot-example.conf @@ -7,6 +7,7 @@ "youtube_api_key": "somegarbage", "facebook_access_token": "myid|myscret", "nick": "PlayBot", + "soundcloud_secret": SOUNDCLOUD_SECRET, "channels": [ "#hello", "#world" -- GitLab