Skip to content

Commit ff1705e

Browse files
committed
- Update the list of usernames on-demand, to prevent data loss.
- Fixed an warning in the Gtk3 version when listing playlists from a given channel. - Minor code simplifications and improvements.
1 parent a272c15 commit ff1705e

File tree

3 files changed

+162
-179
lines changed

3 files changed

+162
-179
lines changed

bin/gtk-youtube-viewer

Lines changed: 148 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ my @VIDEO_QUEUE;
118118
# Keep track of watched videos
119119
my %WATCHED_VIDEOS;
120120

121+
# Saved channels
122+
my %channels;
123+
121124
sub which_command {
122125
my ($cmd) = @_;
123126

@@ -2076,217 +2079,188 @@ sub set_local_playlists {
20762079

20772080
set_local_playlists();
20782081

2079-
{
2080-
my %channels;
2081-
my %removed_channels;
2082-
2083-
# ------------ Usernames list window ------------ #
2084-
sub set_usernames {
2085-
if (-e $CONFIG{youtube_users_file}) {
2086-
if (open my $fh, '<:utf8', $CONFIG{youtube_users_file}) {
2087-
while (defined(my $entry = <$fh>)) {
2088-
2089-
$entry = unpack('A*', $entry);
2090-
my ($channel, $label) = split(' ', $entry, 2);
2091-
2092-
if (defined($channel) and $channel =~ /$valid_channel_id_re/) {
2093-
$channel = $+{channel_id};
2094-
if (defined($label) and $label =~ /\S/) {
2095-
$channels{$channel} = $label;
2096-
}
2097-
else {
2098-
$channels{$channel} = undef;
2099-
}
2100-
}
2101-
}
2102-
close $fh;
2103-
}
2104-
}
2105-
else {
2106-
# Default channels
2107-
%channels = (
2108-
'UC1_uAIS3r8Vu6JjXWvastJg' => 'Mathologer',
2109-
'UCSju5G2aFaWMqn-_0YBtq5A' => 'Stand-Up Maths',
2110-
'UC-WICcSW1k3HsScuXxDrp0w' => 'Curry On!',
2111-
'UCShHFwKyhcDo3g7hr4f1R8A' => 'World Science Festival',
2112-
'UCYO_jab_esuFRV4b17AJtAw' => '3Blue1Brown',
2113-
'UCWnPjmqvljcafA0z2U1fwKQ' => 'Confreaks',
2114-
'UC_QIfHvN9auy2CoOdSfMWDw' => 'Strange Loop',
2115-
'UCseUQK4kC3x2x543nHtGpzw' => 'Brian Will',
2116-
'UC9-y-6csu5WGm29I7JiwpnA' => 'Computerphile',
2117-
'UCoxcjq-8xIDTYp3uz647V5A' => 'Numberphile',
2118-
'UCvBqzzvUBLCs8Y7Axb-jZew' => 'Sixty Symbols',
2119-
'UC6107grRI4m0o2-emgoDnAA' => 'SmarterEveryDay',
2120-
'UCF6F8LdCSWlRwQm_hfA2bcQ' => 'Coding Math',
2121-
'UC1znqKFL3jeR0eoA0pHpzvw' => 'SpaceRip',
2122-
'UCvjgXvBlbQiydffZU7m1_aw' => 'The Coding Train',
2123-
'UC0wbcfzV-bHhABbWGXKHwdg' => 'Utah Open Source',
2124-
'UCotwjyJnb-4KW7bmsOoLfkg' => 'Art of the Problem',
2125-
'UC7y4qaRSb5w2O8cCHOsKZDw' => 'YAPC NA',
2126-
'UCGHZpIpAWJQ-Jy_CeCdXhMA' => 'Cool Worlds',
2127-
'UCmG6gHgD8JaEZVxuHWJijGQ' => 'UConn Mathematics',
2128-
'UC81mayGa63QaJE1SjKIYp0w' => 'metaRising',
2129-
'UCSHZKyawb77ixDdsGog4iWA' => 'Lex Fridman',
2130-
'UCBa659QWEk1AI4Tg--mrJ2A' => 'Tom Scott',
2131-
);
2132-
}
2082+
# ------------ Usernames list window ------------ #
2083+
sub set_usernames {
21332084

2134-
foreach my $channel (sort { CORE::fc($channels{$a} // $a) cmp CORE::fc($channels{$b} // $b) } keys %channels) {
2135-
my $iter = $users_liststore->append;
2085+
if (-e $CONFIG{youtube_users_file}) {
2086+
%channels = ((map { @$_ } $yv_utils->read_channels_from_file($CONFIG{youtube_users_file})), %channels,);
2087+
}
2088+
else {
2089+
# Default channels
2090+
%channels = (
2091+
'UC1_uAIS3r8Vu6JjXWvastJg' => 'Mathologer',
2092+
'UCSju5G2aFaWMqn-_0YBtq5A' => 'Stand-Up Maths',
2093+
'UC-WICcSW1k3HsScuXxDrp0w' => 'Curry On!',
2094+
'UCShHFwKyhcDo3g7hr4f1R8A' => 'World Science Festival',
2095+
'UCYO_jab_esuFRV4b17AJtAw' => '3Blue1Brown',
2096+
'UCWnPjmqvljcafA0z2U1fwKQ' => 'Confreaks',
2097+
'UC_QIfHvN9auy2CoOdSfMWDw' => 'Strange Loop',
2098+
'UCseUQK4kC3x2x543nHtGpzw' => 'Brian Will',
2099+
'UC9-y-6csu5WGm29I7JiwpnA' => 'Computerphile',
2100+
'UCoxcjq-8xIDTYp3uz647V5A' => 'Numberphile',
2101+
'UCvBqzzvUBLCs8Y7Axb-jZew' => 'Sixty Symbols',
2102+
'UC6107grRI4m0o2-emgoDnAA' => 'SmarterEveryDay',
2103+
'UCF6F8LdCSWlRwQm_hfA2bcQ' => 'Coding Math',
2104+
'UC1znqKFL3jeR0eoA0pHpzvw' => 'SpaceRip',
2105+
'UCvjgXvBlbQiydffZU7m1_aw' => 'The Coding Train',
2106+
'UC0wbcfzV-bHhABbWGXKHwdg' => 'Utah Open Source',
2107+
'UCotwjyJnb-4KW7bmsOoLfkg' => 'Art of the Problem',
2108+
'UC7y4qaRSb5w2O8cCHOsKZDw' => 'YAPC NA',
2109+
'UCGHZpIpAWJQ-Jy_CeCdXhMA' => 'Cool Worlds',
2110+
'UCmG6gHgD8JaEZVxuHWJijGQ' => 'UConn Mathematics',
2111+
'UC81mayGa63QaJE1SjKIYp0w' => 'metaRising',
2112+
'UCSHZKyawb77ixDdsGog4iWA' => 'Lex Fridman',
2113+
'UCBa659QWEk1AI4Tg--mrJ2A' => 'Tom Scott',
2114+
);
2115+
}
2116+
2117+
$users_liststore->clear; # clear the list
2118+
2119+
foreach my $channel (sort { CORE::fc($channels{$a} // $a) cmp CORE::fc($channels{$b} // $b) } keys %channels) {
2120+
my $iter = $users_liststore->append;
21362121

2137-
if (defined $channels{$channel}) {
2138-
$users_liststore->set(
2139-
$iter,
2140-
0 => $channel,
2141-
1 => $channels{$channel},
2142-
2 => 'channel',
2143-
);
2144-
}
2145-
else {
2146-
$users_liststore->set(
2147-
$iter,
2148-
0 => $channel,
2149-
1 => $channel,
2150-
2 => 'username',
2151-
);
2152-
}
2122+
$channels{$channel} // next;
21532123

2154-
$users_liststore->set($iter, [3], [$user_icon_pixbuf]);
2155-
}
2124+
$users_liststore->set(
2125+
$iter,
2126+
0 => $channel,
2127+
1 => $channels{$channel},
2128+
2 => 'channel',
2129+
3 => $user_icon_pixbuf,
2130+
);
21562131
}
2132+
}
21572133

2158-
sub save_channel {
2159-
my $channel_name = $save_channel_name_entry->get_text;
2160-
my $channel_id = $save_channel_id_entry->get_text;
2134+
sub save_channel {
2135+
my $channel_name = $save_channel_name_entry->get_text;
2136+
my $channel_id = $save_channel_id_entry->get_text;
21612137

2162-
# Validate the channel id
2163-
if (defined($channel_id) and $channel_id =~ /$valid_channel_id_re/) {
2138+
# Validate the channel id
2139+
if (defined($channel_id) and $channel_id =~ /$valid_channel_id_re/) {
21642140

2165-
$channel_id = $+{channel_id};
2141+
$channel_id = $+{channel_id};
21662142

2167-
# Get the channel name when empty
2168-
if (not defined($channel_name) or not $channel_name =~ /\S/) {
2169-
$channel_name = $yv_obj->channel_title_from_id($channel_id) // die "Invalid channel ID: <<$channel_id>>";
2170-
}
2143+
# Get the channel name when empty
2144+
if (not defined($channel_name) or not $channel_name =~ /\S/) {
2145+
$channel_name = $yv_obj->channel_title_from_id($channel_id) // die "Invalid channel ID: <<$channel_id>>";
21712146
}
2172-
elsif (defined($channel_name) and $channel_name =~ /$valid_channel_id_re/) {
2147+
}
2148+
elsif (defined($channel_name) and $channel_name =~ /$valid_channel_id_re/) {
21732149

2174-
$channel_name = $+{channel_id};
2175-
$channel_id = $yv_obj->channel_id_from_username($channel_name);
2150+
$channel_name = $+{channel_id};
2151+
$channel_id = $yv_obj->channel_id_from_username($channel_name);
21762152

2177-
if (not defined $channel_id) {
2178-
die "Can't get channel ID from username: <<$channel_name>>";
2179-
}
2180-
}
2181-
elsif (defined($channel_id) and $channel_id =~ /\S/) {
2182-
die "Invalid channel ID: <<$channel_id>>";
2183-
}
2184-
else {
2185-
return;
2153+
if (not defined $channel_id) {
2154+
die "Can't get channel ID from username: <<$channel_name>>";
21862155
}
2156+
}
2157+
elsif (defined($channel_id) and $channel_id =~ /\S/) {
2158+
die "Invalid channel ID: <<$channel_id>>";
2159+
}
2160+
else {
2161+
return;
2162+
}
2163+
2164+
save_channel_by_id($channel_id, $channel_name);
2165+
}
21872166

2188-
save_channel_by_id($channel_id, $channel_name);
2167+
sub save_channel_by_id {
2168+
my ($channel_id, $channel_name) = @_;
2169+
2170+
# Validate the channel ID
2171+
if (not defined($channel_id) or not $channel_id =~ /$valid_channel_id_re/) {
2172+
return;
21892173
}
21902174

2191-
sub save_channel_by_id {
2192-
my ($channel_id, $channel_name) = @_;
2175+
if ($channel_id =~ /$valid_channel_id_re/) {
2176+
$channel_id = $+{channel_id};
2177+
}
21932178

2194-
# Validate the channel ID
2195-
if (not defined($channel_id) or not $channel_id =~ /$valid_channel_id_re/) {
2196-
return;
2197-
}
2179+
# Channel ID already exists in the list
2180+
if (exists($channels{$channel_id})) {
2181+
return;
2182+
}
21982183

2199-
if ($channel_id =~ /$valid_channel_id_re/) {
2200-
$channel_id = $+{channel_id};
2201-
}
2184+
# Get the channel name
2185+
if (not defined($channel_name) or not $channel_name =~ /\S/) {
2186+
$channel_name = $yv_obj->channel_title_from_id($channel_id) // $channel_id;
2187+
}
22022188

2203-
# Channel ID already exists in the list
2204-
if (exists($channels{$channel_id})) {
2205-
return;
2206-
}
2189+
# Save channel to file
2190+
say ":: Saving channel: $channel_name" if $yv_obj->get_debug;
2191+
$channels{$channel_id} = $channel_name;
2192+
write_channels_to_file(\%channels, $CONFIG{youtube_users_file});
2193+
set_usernames();
2194+
}
22072195

2208-
# Get the channel name
2209-
if (not defined($channel_name) or not $channel_name =~ /\S/) {
2210-
$channel_name = $yv_obj->channel_title_from_id($channel_id) // $channel_id;
2211-
}
2196+
sub add_user_to_favorites {
2197+
my $channel_id = get_channel_id_for_selected_video() // return;
2198+
save_channel_by_id($channel_id);
2199+
}
22122200

2213-
# Store it internally
2214-
$channels{$channel_id} = $channel_name;
2201+
sub remove_selected_username {
22152202

2216-
# Append it to the list
2217-
my $iter = $users_liststore->append;
2203+
my $selection = $users_treeview->get_selection // return;
2204+
my $iter = $selection->get_selected // return;
2205+
my $channel_id = $users_liststore->get($iter, 0);
22182206

2219-
$users_liststore->set(
2220-
$iter,
2221-
0 => $channel_id,
2222-
1 => $channel_name,
2223-
2 => 'channel',
2224-
3 => $user_icon_pixbuf,
2225-
);
2226-
}
2207+
delete $channels{$channel_id};
2208+
$users_liststore->remove($iter);
22272209

2228-
sub add_user_to_favorites {
2229-
my $channel_id = get_channel_id_for_selected_video() // return;
2230-
save_channel_by_id($channel_id);
2231-
}
2210+
write_channels_to_file(\%channels, $CONFIG{youtube_users_file});
2211+
}
22322212

2233-
sub remove_selected_user {
2234-
my $selection = $users_treeview->get_selection // return;
2235-
my $iter = $selection->get_selected // return;
2236-
my $channel_id = $users_liststore->get($iter, 0);
2237-
delete $channels{$channel_id};
2238-
$removed_channels{$channel_id} = 1;
2239-
$users_liststore->remove($iter);
2240-
}
2213+
sub write_channels_to_file {
2214+
my ($channels, $file) = @_;
22412215

2242-
sub save_usernames_to_file {
2216+
my %new_channels = %$channels;
22432217

2244-
set_usernames(); # update %channels
2218+
open(my $fh, '>:utf8', $file) or return;
22452219

2246-
foreach my $id (keys %removed_channels) {
2247-
delete $channels{$id};
2220+
foreach my $channel (
2221+
sort { CORE::fc($new_channels{$a} // $a) cmp CORE::fc($new_channels{$b} // $b) }
2222+
keys %new_channels
2223+
) {
2224+
if (defined($new_channels{$channel})) {
2225+
say $fh "$channel $new_channels{$channel}";
22482226
}
2249-
2250-
open(my $fh, '>:utf8', $CONFIG{youtube_users_file}) or return;
2251-
foreach my $channel (
2252-
sort { CORE::fc($channels{$a} // $a) cmp CORE::fc($channels{$b} // $b) }
2253-
keys %channels
2254-
) {
2255-
if (defined($channels{$channel})) {
2256-
say $fh "$channel $channels{$channel}";
2257-
}
2258-
else {
2259-
say $fh $channel;
2260-
}
2227+
else {
2228+
say $fh "$channel $channel";
22612229
}
2262-
close $fh;
22632230
}
22642231

2265-
# Get playlists from username
2266-
sub playlists_from_selected_username {
2267-
my $selection = $users_treeview->get_selection() // return;
2268-
my $iter = $selection->get_selected() // return;
2232+
close $fh;
2233+
}
22692234

2270-
my $type = $users_liststore->get($iter, 2);
2271-
my $channel = $users_liststore->get($iter, 0);
2235+
sub save_usernames_to_file {
2236+
set_usernames(); # update channels
2237+
write_channels_to_file(\%channels, $CONFIG{youtube_users_file});
2238+
}
22722239

2273-
playlists($type, $channel);
2274-
}
2240+
# Get playlists from username
2241+
sub playlists_from_selected_username {
2242+
my $selection = $users_treeview->get_selection() // return;
2243+
my $iter = $selection->get_selected() // return;
2244+
2245+
my $type = $users_liststore->get($iter, 2);
2246+
my $channel = $users_liststore->get($iter, 0);
22752247

2276-
sub videos_from_selected_username {
2277-
my $selection = $users_treeview->get_selection() // return;
2278-
my $iter = $selection->get_selected() // return;
2248+
playlists($type, $channel);
2249+
}
22792250

2280-
my $type = $users_liststore->get($iter, 2);
2281-
my $channel = $users_liststore->get($iter, 0);
2251+
sub videos_from_selected_username {
2252+
my $selection = $users_treeview->get_selection() // return;
2253+
my $iter = $selection->get_selected() // return;
22822254

2283-
uploads($type, $channel);
2284-
}
2255+
my $type = $users_liststore->get($iter, 2);
2256+
my $channel = $users_liststore->get($iter, 0);
22852257

2286-
sub videos_from_saved_channel {
2287-
hide_users_list_window();
2288-
videos_from_selected_username();
2289-
}
2258+
uploads($type, $channel);
2259+
}
2260+
2261+
sub videos_from_saved_channel {
2262+
hide_users_list_window();
2263+
videos_from_selected_username();
22902264
}
22912265

22922266
# ----- My panel settings ----- #

0 commit comments

Comments
 (0)