diff --git a/YouTubeMusic/API.pm b/YouTubeMusic/API.pm
index db162f6..d26cc22 100644
--- a/YouTubeMusic/API.pm
+++ b/YouTubeMusic/API.pm
@@ -2,16 +2,17 @@ package Plugins::YouTubeMusic::API;
use strict;
-use Digest::MD5 qw(md5_hex);
+use Digest::MD5 qw(md5_hex);
use File::Spec::Functions qw(catdir);
use JSON::XS::VersionOneAndTwo;
-use List::Util qw(min max);
-use URI::Escape qw(uri_escape uri_escape_utf8);
+use List::Util qw(min max);
+use URI::Escape qw(uri_escape uri_escape_utf8);
use MIME::Base64 qw(decode_base64);
-use constant API_URL => 'https://music.youtube.com/youtubei/v1/';
+use constant API_URL => 'https://music.youtube.com/youtubei/v1/';
use constant DEFAULT_CACHE_TTL => 24 * 3600;
-use constant DEFAULT_API_KEY => 'QUl6YVN5Qi1wd1B0RGt4RjZKUW1BOHFxOWgxbWQ2ME15STVRNWlB';
+use constant DEFAULT_API_KEY =>
+ 'QUl6YVN5Qi1wd1B0RGt4RjZKUW1BOHFxOWgxbWQ2ME15STVRNWlB';
use Slim::Utils::Cache;
use Slim::Utils::Log;
@@ -24,156 +25,198 @@ my $cache = Slim::Utils::Cache->new();
sub flushCache { $cache->cleanup(); }
sub search {
- my ( $class, $cb, $args ) = @_;
+ my ( $class, $cb, $args ) = @_;
- $args ||= {};
- $args->{part} = 'snippet';
- $args->{type} ||= 'video';
- $args->{order} ||= $prefs->get('search_rank');
- $args->{relevanceLanguage} = Slim::Utils::Strings::getLanguage();
+ $args ||= {};
+ $args->{part} = 'snippet';
+ $args->{type} ||= 'video';
+ $args->{order} ||= $prefs->get('search_rank');
+ $args->{relevanceLanguage} = Slim::Utils::Strings::getLanguage();
- _pagedCall('search', $args, $cb);
+ _pagedCall( 'search', $args, $cb );
}
sub searchDirect {
- my ( $class, $type, $cb, $args ) = @_;
+ my ( $class, $type, $cb, $args ) = @_;
- $args ||= {};
- $args->{_noRegion} = 1;
+ $args ||= {};
+ $args->{_noRegion} = 1;
- _pagedCall( $type, $args, $cb);
+ _pagedCall( $type, $args, $cb );
}
sub getCategories {
- my ( $class, $type, $cb, $args ) = @_;
+ my ( $class, $type, $cb, $args ) = @_;
- $args ||= {};
- $args->{hl} = Slim::Utils::Strings::getLanguage();
- $args->{_cache_ttl} = 7 * 86400;
+ $args ||= {};
+ $args->{hl} = Slim::Utils::Strings::getLanguage();
+ $args->{_cache_ttl} = 7 * 86400;
- _pagedCall($type, $args, $cb);
+ _pagedCall( $type, $args, $cb );
}
sub getVideoDetails {
- my ( $class, $cb, $ids ) = @_;
+ my ( $class, $cb, $ids ) = @_;
- _call('videos', {
- part => 'snippet,contentDetails',
- id => $ids,
- # cache video details a bit longer
- _cache_ttl => 7 * 86400,
- }, $cb);
+ _call(
+ 'videos',
+ {
+ part => 'snippet,contentDetails',
+ id => $ids,
+
+ # cache video details a bit longer
+ _cache_ttl => 7 * 86400,
+ },
+ $cb
+ );
}
sub _pagedCall {
- my ( $method, $args, $cb ) = @_;
- my $wantedItems = $args->{_quantity} || $prefs->get('max_items');
- # ignore $args->{_index} and let LMS handle offset
- my $wantedIndex = 0;
- my @items;
- my $pagingCb;
- my $pageIndex = 0;
-
- # we want them starting from current index
- $wantedItems += $args->{_index} || 0;
+ my ( $method, $args, $cb ) = @_;
+ my $wantedItems = $args->{_quantity} || $prefs->get('max_items');
- main::INFOLOG && $log->info("Searching by [$args->{order}]");
- main::INFOLOG && $log->info("Querying [$args->{_quantity}] from [$args->{_index}] to [", $wantedItems-1, "] using [$method]");
+ # ignore $args->{_index} and let LMS handle offset
+ my $wantedIndex = 0;
+ my @items;
+ my $pagingCb;
+ my $pageIndex = 0;
- # doing a search with a display order, so need to give precedence to 'query_size'
- if ($prefs->get('search_sort') || $prefs->get('channel_sort') || $prefs->get('playlist_sort')) {
- $wantedItems = (int(($wantedItems - 1) / $prefs->get('query_size')) + 1) * $prefs->get('query_size');
- main::INFOLOG && $log->info("Stretching quantity to [$wantedItems] due to sorting");
- }
-
- # that the maximum we'll get anyway
- $wantedItems = $prefs->get('max_items') if $wantedItems > $prefs->get('max_items');
+ # we want them starting from current index
+ $wantedItems += $args->{_index} || 0;
- $pagingCb = sub {
- my $results = shift;
+ main::INFOLOG && $log->info("Searching by [$args->{order}]");
+ main::INFOLOG && $log->info(
+ "Querying [$args->{_quantity}] from [$args->{_index}] to [",
+ $wantedItems - 1,
+ "] using [$method]"
+ );
- if ( $results->{error} || !$results->{items} ) {
- $log->error("no results");
- $cb->( { items => undef, total => 0 } ) if ( $results->{error} );
- return;
- }
+# doing a search with a display order, so need to give precedence to 'query_size'
+ if ( $prefs->get('search_sort')
+ || $prefs->get('channel_sort')
+ || $prefs->get('playlist_sort') )
+ {
+ $wantedItems =
+ ( int( ( $wantedItems - 1 ) / $prefs->get('query_size') ) + 1 ) *
+ $prefs->get('query_size');
+ main::INFOLOG
+ && $log->info("Stretching quantity to [$wantedItems] due to sorting");
+ }
- push @items, @{$results->{items}};
- $pageIndex += scalar @{$results->{items}};
+ # that the maximum we'll get anyway
+ $wantedItems = $prefs->get('max_items')
+ if $wantedItems > $prefs->get('max_items');
- main::INFOLOG && $log->info("Want $wantedItems items from offset ", $wantedIndex, ", have " . scalar @items . " so far [acquired $pageIndex]");
+ $pagingCb = sub {
+ my $results = shift;
- if (@items < $wantedItems && $results->{nextPageToken}) {
- $args->{pageToken} = $results->{nextPageToken};
- main::INFOLOG && $log->info("Get next page using token " . $args->{pageToken});
- _call($method, $args, $pagingCb);
- } else {
- my $total = min($results->{'pageInfo'}->{'totalResults'} || $pageIndex, $prefs->get('max_items'));
- main::INFOLOG && $log->info("Got all we wanted, return " . scalar @items . "/$total. (YT total ", $results->{'pageInfo'}->{'totalResults'} || 'N/A', ")");
- $cb->( { items => \@items, offset => $wantedIndex, total => $total } );
- }
- };
+ if ( $results->{error} || !$results->{items} ) {
+ $log->error("no results");
+ $cb->( { items => undef, total => 0 } ) if ( $results->{error} );
+ return;
+ }
- _call($method, $args, $pagingCb);
+ push @items, @{ $results->{items} };
+ $pageIndex += scalar @{ $results->{items} };
+
+ main::INFOLOG && $log->info( "Want $wantedItems items from offset ",
+ $wantedIndex,
+ ", have " . scalar @items . " so far [acquired $pageIndex]" );
+
+ if ( @items < $wantedItems && $results->{nextPageToken} ) {
+ $args->{pageToken} = $results->{nextPageToken};
+ main::INFOLOG
+ && $log->info(
+ "Get next page using token " . $args->{pageToken} );
+ _call( $method, $args, $pagingCb );
+ }
+ else {
+ my $total =
+ min( $results->{'pageInfo'}->{'totalResults'} || $pageIndex,
+ $prefs->get('max_items') );
+ main::INFOLOG && $log->info(
+ "Got all we wanted, return "
+ . scalar @items
+ . "/$total. (YT total ",
+ $results->{'pageInfo'}->{'totalResults'} || 'N/A',
+ ")"
+ );
+ $cb->(
+ { items => \@items, offset => $wantedIndex, total => $total } );
+ }
+ };
+
+ _call( $method, $args, $pagingCb );
}
sub _call {
- my ( $method, $args, $cb ) = @_;
+ my ( $method, $args, $cb ) = @_;
- my $API_KEY = $prefs->get('APIkey') || MIME::Base64::decode_base64(DEFAULT_API_KEY);
- my $url = '?' . ($args->{_noKey} ? '' : 'key=' . $API_KEY . '&');
+ my $API_KEY =
+ $prefs->get('APIkey') || MIME::Base64::decode_base64(DEFAULT_API_KEY);
+ my $url = '?' . ( $args->{_noKey} ? '' : 'key=' . $API_KEY . '&' );
- $args->{regionCode} ||= $prefs->get('country') unless $args->{_noRegion};
- $args->{part} ||= 'snippet' unless $args->{_noPart};
- $args->{maxResults} ||= 50;
+ $args->{regionCode} ||= $prefs->get('country') unless $args->{_noRegion};
+ $args->{part} ||= 'snippet' unless $args->{_noPart};
+ $args->{maxResults} ||= 50;
- for my $k ( sort keys %{$args} ) {
- next if $k =~ /^_/;
- $url .= $k . '=' . URI::Escape::uri_escape_utf8( Encode::decode( 'utf8', $args->{$k} ) ) . '&';
- }
+ for my $k ( sort keys %{$args} ) {
+ next if $k =~ /^_/;
+ $url .=
+ $k . '='
+ . URI::Escape::uri_escape_utf8(
+ Encode::decode( 'utf8', $args->{$k} ) )
+ . '&';
+ }
- $url =~ s/&$//;
- $url = API_URL . $method . $url;
+ $url =~ s/&$//;
+ $url = API_URL . $method . $url;
- my $cacheKey = $args->{_noCache} ? '' : md5_hex($url);
+ my $cacheKey = $args->{_noCache} ? '' : md5_hex($url);
- if ( $cacheKey && (my $cached = $cache->get($cacheKey)) ) {
- main::INFOLOG && $log->info("Returning cached data for: $url");
- $cb->($cached);
- return;
- }
+ if ( $cacheKey && ( my $cached = $cache->get($cacheKey) ) ) {
+ main::INFOLOG && $log->info("Returning cached data for: $url");
+ $cb->($cached);
+ return;
+ }
- main::INFOLOG && $log->info("Calling API (will cache for ", $args->{_cache_ttl} || DEFAULT_CACHE_TTL, "s): $url");
+ main::INFOLOG && $log->info(
+ "Calling API (will cache for ",
+ $args->{_cache_ttl} || DEFAULT_CACHE_TTL,
+ "s): $url"
+ );
- Slim::Networking::SimpleAsyncHTTP->new(
- sub {
- my $response = shift;
- my $result = eval { from_json($response->content) };
+ Slim::Networking::SimpleAsyncHTTP->new(
+ sub {
+ my $response = shift;
+ my $result = eval { from_json( $response->content ) };
- if ($@) {
- $log->error(Data::Dump::dump($response)) unless main::DEBUGLOG && $log->is_debug;
- $log->error($@);
- }
+ if ($@) {
+ $log->error( Data::Dump::dump($response) )
+ unless main::DEBUGLOG && $log->is_debug;
+ $log->error($@);
+ }
- main::DEBUGLOG && $log->is_debug && warn Data::Dump::dump($result);
+ main::DEBUGLOG && $log->is_debug && warn Data::Dump::dump($result);
- $result ||= {};
- $cache->set($cacheKey, $result, $args->{_cache_ttl} || DEFAULT_CACHE_TTL);
+ $result ||= {};
+ $cache->set( $cacheKey, $result,
+ $args->{_cache_ttl} || DEFAULT_CACHE_TTL );
- $cb->($result);
- },
+ $cb->($result);
+ },
- sub {
- warn Data::Dump::dump(@_);
- $log->error($_[1]);
- $cb->( { error => $_[1] } );
- },
+ sub {
+ warn Data::Dump::dump(@_);
+ $log->error( $_[1] );
+ $cb->( { error => $_[1] } );
+ },
- {
- timeout => 15,
- }
+ {
+ timeout => 15,
+ }
- )->get($url);
+ )->get($url);
}
1;
diff --git a/YouTubeMusic/HTML/EN/plugins/YouTubeMusic/settings/basic.html b/YouTubeMusic/HTML/EN/plugins/YouTubeMusic/settings/basic.html
index bfeda90..6e6ab52 100644
--- a/YouTubeMusic/HTML/EN/plugins/YouTubeMusic/settings/basic.html
+++ b/YouTubeMusic/HTML/EN/plugins/YouTubeMusic/settings/basic.html
@@ -1,26 +1,26 @@
[% PROCESS settings/header.html %]
-
Hello World
+Hello World
- [% WRAPPER setting title="PLUGIN_YOUTUBEMUSIC_TESTPREF" desc="PLUGIN_YOUTUBEMUSIC_TESTPREF_DESC" %]
-
+[% WRAPPER setting title="PLUGIN_YOUTUBEMUSIC_TESTPREF" desc="PLUGIN_YOUTUBEMUSIC_TESTPREF_DESC" %]
+
+[% END %]
+
+[% WRAPPER setting title="PLUGIN_YOUTUBEMUSIC_AUTH" desc="PLUGIN_YOUTUBEMUSIC_AUTH_DESC" %]
+
+ [% IF !user_code %]
+
+ [% ELSE %]
+
[% "PLUGIN_YOUTUBEMUSIC_VERIFICATIONURL" | string %]
+
[% user_code %]
[% END %]
-
- [% WRAPPER setting title="PLUGIN_YOUTUBEMUSIC_AUTH" desc="PLUGIN_YOUTUBEMUSIC_AUTH_DESC" %]
-
-
-
- [% IF access_token %]
-
Success
- [% END %]
-
+
+
+
+ [% IF access_token %]
+
Success
[% END %]
+
+[% END %]
-[% PROCESS settings/footer.html %]
+[% PROCESS settings/footer.html %]
\ No newline at end of file
diff --git a/YouTubeMusic/OAuth2.pm b/YouTubeMusic/OAuth2.pm
index 65c39f2..3bd3c34 100644
--- a/YouTubeMusic/OAuth2.pm
+++ b/YouTubeMusic/OAuth2.pm
@@ -8,93 +8,114 @@ use Slim::Utils::Strings qw(string cstring);
use JSON::XS::VersionOneAndTwo;
use Data::Dumper;
-use constant CLIENT_ID => "861556708454-d6dlm3lh05idd8npek18k6be8ba3oc68.apps.googleusercontent.com";
+use constant CLIENT_ID =>
+ "861556708454-d6dlm3lh05idd8npek18k6be8ba3oc68.apps.googleusercontent.com";
use constant CLIENT_SECRET => "SboVhoG9s0rNafixCSGGKXAT";
my $log = logger('plugin.youtubemusic');
my $cache = Slim::Utils::Cache->new();
sub getDeviceCode {
- my $post = "client_id=" . CLIENT_ID . "&scope=https://www.googleapis.com/auth/youtube";
-
- my $http = Slim::Networking::SimpleAsyncHTTP->new(
- sub {
- my $response = shift;
- my $result = eval { from_json($response->content) };
+ my $post =
+ "client_id="
+ . CLIENT_ID
+ . "&scope=https://www.googleapis.com/auth/youtube";
- if ($@) {
- $log->error(Data::Dump::dump($response)) unless main::DEBUGLOG && $log->is_debug;
- $log->error($@);
- } else {
- $cache->set("yt:device_code", $result->{device_code}, $result->{expires_in});
- $cache->set("yt:verification_url", $result->{verification_url}, $result->{expires_in});
- $cache->set("yt:user_code", $result->{user_code}, $result->{expires_in});
+ my $http = Slim::Networking::SimpleAsyncHTTP->new(
+ sub {
+ my $response = shift;
+ my $result = eval { from_json( $response->content ) };
- $log->debug("content:", $response->content);
- }
- },
- sub {
- $log->error($_[1]);
- },
- {
- timeout => 15,
- }
- );
-
- $http->post(
- "https://www.youtube.com/o/oauth2/device/code",
- 'Content-Type' => 'application/x-www-form-urlencoded',
- $post,
- );
+ if ($@) {
+ $log->error( Data::Dump::dump($response) )
+ unless main::DEBUGLOG && $log->is_debug;
+ $log->error($@);
+ }
+ else {
+ $cache->set( "yt:device_code", $result->{device_code},
+ $result->{expires_in} );
+ $cache->set( "yt:verification_url", $result->{verification_url},
+ $result->{expires_in} );
+ $cache->set( "yt:user_code", $result->{user_code},
+ $result->{expires_in} );
+
+ $log->debug( "content:", $response->content );
+ }
+ },
+ sub {
+ $log->error( $_[1] );
+ },
+ {
+ timeout => 15,
+ }
+ );
+
+ $http->post(
+ "https://www.youtube.com/o/oauth2/device/code",
+ 'Content-Type' => 'application/x-www-form-urlencoded',
+ $post,
+ );
}
sub getToken {
- my $cb = shift;
- my @params = @_;
- my $post = "client_id=" . CLIENT_ID . "&client_secret=" . CLIENT_SECRET;
- my $code = $cache->get('yt:device_code');
-
- if (defined $code) {
- $post .= "&code=$code&grant_type=http://oauth.net/grant_type/device/1.0";
- } else {
- $post .= "&refresh_token=" . $cache->get('yt:refresh_token') . "&grant_type=refresh_token";
- }
-
- my $http = Slim::Networking::SimpleAsyncHTTP->new(
- sub {
- my $response = shift;
- my $result = eval { from_json($response->content) };
+ my $cb = shift;
+ my @params = @_;
+ my $post = "client_id=" . CLIENT_ID . "&client_secret=" . CLIENT_SECRET;
+ my $code = $cache->get('yt:device_code');
- if ($@) {
- $log->error(Data::Dump::dump($response)) unless main::DEBUGLOG && $log->is_debug;
- $log->error($@);
- } else {
- $cache->set("yt:access_token", $result->{access_token}, $result->{expires_in} - 60);
- $cache->set('yt:refresh_token', $result->{refresh_token}) if $result->{refresh_token};
-
- $cache->remove('yt:user_code');
- $cache->remove('yt:verification_url');
- $cache->remove('yt:device_code');
-
- $log->debug("content:", $response->content);
+ if ( defined $code ) {
+ $post .=
+ "&code=$code&grant_type=http://oauth.net/grant_type/device/1.0";
+ }
+ else {
+ $post .=
+ "&refresh_token="
+ . $cache->get('yt:refresh_token')
+ . "&grant_type=refresh_token";
+ }
- $cb->(@params) if $cb;
- }
- },
- sub {
- $log->error($_[1]);
- $cb->(@params) if $cb;
- },
- {
- timeout => 15,
- }
- );
-
- $http->post(
- "https://oauth2.googleapis.com/token",
- 'Content-Type' => 'application/x-www-form-urlencoded',
- $post,
- );
+ my $http = Slim::Networking::SimpleAsyncHTTP->new(
+ sub {
+ my $response = shift;
+ my $result = eval { from_json( $response->content ) };
+
+ if ($@) {
+ $log->error( Data::Dump::dump($response) )
+ unless main::DEBUGLOG && $log->is_debug;
+ $log->error($@);
+ }
+ else {
+ $cache->set(
+ "yt:access_token",
+ $result->{access_token},
+ $result->{expires_in} - 60
+ );
+ $cache->set( 'yt:refresh_token', $result->{refresh_token} )
+ if $result->{refresh_token};
+
+ $cache->remove('yt:user_code');
+ $cache->remove('yt:verification_url');
+ $cache->remove('yt:device_code');
+
+ $log->debug( "content:", $response->content );
+
+ $cb->(@params) if $cb;
+ }
+ },
+ sub {
+ $log->error( $_[1] );
+ $cb->(@params) if $cb;
+ },
+ {
+ timeout => 15,
+ }
+ );
+
+ $http->post(
+ "https://oauth2.googleapis.com/token",
+ 'Content-Type' => 'application/x-www-form-urlencoded',
+ $post,
+ );
}
1;
diff --git a/YouTubeMusic/Plugin.pm b/YouTubeMusic/Plugin.pm
index a6d9ea3..e57f69f 100644
--- a/YouTubeMusic/Plugin.pm
+++ b/YouTubeMusic/Plugin.pm
@@ -11,34 +11,38 @@ use Slim::Utils::Cache;
use Plugins::YouTubeMusic::OAuth2;
-my $log = Slim::Utils::Log->addLogCategory({
- 'category' => 'plugin.youtubemusic',
- 'defaultLevel' => 'WARN',
- 'description' => 'PLUGIN_YOUTUBEMUSIC',
-});
+my $log = Slim::Utils::Log->addLogCategory(
+ {
+ 'category' => 'plugin.youtubemusic',
+ 'defaultLevel' => 'WARN',
+ 'description' => 'PLUGIN_YOUTUBEMUSIC',
+ }
+);
my $prefs = preferences('plugin.youtubemusic');
my $cache = Slim::Utils::Cache->new();
-$prefs->init({
- testPref => 'test'
-});
+$prefs->init(
+ {
+ testPref => 'test'
+ }
+);
sub initPlugin {
- my $class = shift;
+ my $class = shift;
- $class->SUPER::initPlugin(
- feed => \&mainMenu,
- tag => 'youtubemusic',
- menu => 'radios',
- is_app => 1,
- weight => 1,
- );
+ $class->SUPER::initPlugin(
+ feed => \&mainMenu,
+ tag => 'youtubemusic',
+ menu => 'radios',
+ is_app => 1,
+ weight => 1,
+ );
- if (main::WEBUI) {
- require Plugins::YouTubeMusic::Settings;
- Plugins::YouTubeMusic::Settings->new();
- }
+ if (main::WEBUI) {
+ require Plugins::YouTubeMusic::Settings;
+ Plugins::YouTubeMusic::Settings->new();
+ }
}
sub shutdownPlugin {
@@ -48,59 +52,68 @@ sub shutdownPlugin {
sub getDisplayName { 'PLUGIN_YOUTUBEMUSIC' }
sub mainMenu {
- my ($client, $callback, $args) = @_;
+ my ( $client, $callback, $args ) = @_;
- $callback->([
- { name => cstring($client, 'PLUGIN_YOUTUBEMUSIC_MYPLAYLISTS'), type => 'url', url => \&myPlaylistHandler, passthrough => [ { count => 2 } ] },
- ]);
+ $callback->(
+ [
+ {
+ name => cstring( $client, 'PLUGIN_YOUTUBEMUSIC_MYPLAYLISTS' ),
+ type => 'url',
+ url => \&myPlaylistHandler,
+ passthrough => [ { count => 2 } ]
+ },
+ ]
+ );
}
-
sub myPlaylistHandler {
- my ($client, $cb, $args, $params) = @_;
+ my ( $client, $cb, $args, $params ) = @_;
- if (!$cache->get('yt:access_token')) {
- Plugins::YouTubeMusic::OAuth2::getToken(\&myPlaylistHandler, @_);
- return;
- }
+ if ( !$cache->get('yt:access_token') ) {
+ Plugins::YouTubeMusic::OAuth2::getToken( \&myPlaylistHandler, @_ );
+ return;
+ }
- my $account = {
- _cache_ttl => 60,
- _noKey => 1,
- mine => 'true',
- access_token => $cache->get('yt:access_token'),
- };
+ my $account = {
+ _cache_ttl => 60,
+ _noKey => 1,
+ mine => 'true',
+ access_token => $cache->get('yt:access_token'),
+ };
- Plugins::YouTubeMusic::API->searchDirect('playlists', sub {
- $cb->(_renderList($_[0], 'title', $account));
- }, {
- %$account,
- _index => $args->{index},
- _quantity => $args->{quantity},
- });
+ Plugins::YouTubeMusic::API->searchDirect(
+ 'playlists',
+ sub {
+ $cb->( _renderList( $_[0], 'title', $account ) );
+ },
+ {
+ %$account,
+ _index => $args->{index},
+ _quantity => $args->{quantity},
+ }
+ );
}
sub _renderList {
- my ($list, $sort, $passthrough, $tags) = @_;
- my $sortedList = $list->{items};
- my @items;
+ my ( $list, $sort, $passthrough, $tags ) = @_;
+ my $sortedList = $list->{items};
+ my @items;
- for my $entry (@$sortedList) {
- my $snippet = $entry->{snippet} || next;
- my $title = $snippet->{title} || next;
+ for my $entry (@$sortedList) {
+ my $snippet = $entry->{snippet} || next;
+ my $title = $snippet->{title} || next;
- my $item = {
- name => $title,
- type => 'playlist',
- };
+ my $item = {
+ name => $title,
+ type => 'playlist',
+ };
- push @items, $item;
- }
+ push @items, $item;
+ }
- $list->{items} = \@items;
+ $list->{items} = \@items;
- return $list;
+ return $list;
}
1;
-
diff --git a/YouTubeMusic/Settings.pm b/YouTubeMusic/Settings.pm
index 666acd2..cae11a8 100644
--- a/YouTubeMusic/Settings.pm
+++ b/YouTubeMusic/Settings.pm
@@ -6,37 +6,37 @@ use base qw(Slim::Web::Settings);
use Slim::Utils::Log;
use Slim::Utils::Prefs;
-my $log = logger('plugin.youtubemusic');
+my $log = logger('plugin.youtubemusic');
my $cache = Slim::Utils::Cache->new();
sub name {
- return 'PLUGIN_YOUTUBEMUSIC';
+ return 'PLUGIN_YOUTUBEMUSIC';
}
sub page {
- return 'plugins/YouTubeMusic/settings/basic.html';
+ return 'plugins/YouTubeMusic/settings/basic.html';
}
sub prefs {
- return (preferences('plugin.youtubemusic'), qw(testPref));
+ return ( preferences('plugin.youtubemusic'), qw(testPref) );
}
sub handler {
- my ($class, $client, $params) = @_;
+ my ( $class, $client, $params ) = @_;
- if ($params->{'saveSettings'}) {
- preferences('plugin.youtubemusic')->set('testPref', $params->{'pref_testPref'});
- }
+ if ( $params->{'saveSettings'} ) {
+ preferences('plugin.youtubemusic')
+ ->set( 'testPref', $params->{'pref_testPref'} );
+ }
- Plugins::YouTubeMusic::OAuth2::getDeviceCode if $params->{get_device_code};
- Plugins::YouTubeMusic::OAuth2::getToken if $params->{get_token};
+ Plugins::YouTubeMusic::OAuth2::getDeviceCode if $params->{get_device_code};
+ Plugins::YouTubeMusic::OAuth2::getToken if $params->{get_token};
- $params->{user_code} = $cache->get('yt:user_code');
- $params->{verification_url} = $cache->get('yt:verification_url');
- $params->{access_token} = $cache->get('yt:access_token');
+ $params->{user_code} = $cache->get('yt:user_code');
+ $params->{verification_url} = $cache->get('yt:verification_url');
+ $params->{access_token} = $cache->get('yt:access_token');
- return $class->SUPER::handler($client, $params);
+ return $class->SUPER::handler( $client, $params );
}
1;
-