From 3ad658406b36d771cbfedbc6800e05653ba259a5 Mon Sep 17 00:00:00 2001
From: matt1432 <matt@nelim.org>
Date: Wed, 9 Oct 2024 14:24:07 -0400
Subject: [PATCH] feat(netd): add try catch to handle errors properly

---
 .../homie/modules/home-assistant/default.nix  |  1 -
 .../apps/Spotify/PlayAlbum/PlayAlbum.cs       | 50 +++++++++++------
 .../apps/Spotify/PlayArtist/PlayArtist.cs     | 48 ++++++++++------
 .../apps/Spotify/PlayPlaylist/PlayPlaylist.cs | 56 +++++++++++--------
 .../apps/Spotify/PlaySong/PlaySong.cs         | 49 ++++++++++------
 5 files changed, 130 insertions(+), 74 deletions(-)

diff --git a/devices/homie/modules/home-assistant/default.nix b/devices/homie/modules/home-assistant/default.nix
index 748535a1..f264c9d8 100644
--- a/devices/homie/modules/home-assistant/default.nix
+++ b/devices/homie/modules/home-assistant/default.nix
@@ -9,7 +9,6 @@
     ./timer.nix
   ];
 
-  # TODO: netd: make error handling with HA notifs
   # TODO: nix: add HA options for custom_sentences and stuff
 
   services.home-assistant = {
diff --git a/devices/homie/modules/home-assistant/netdaemon/apps/Spotify/PlayAlbum/PlayAlbum.cs b/devices/homie/modules/home-assistant/netdaemon/apps/Spotify/PlayAlbum/PlayAlbum.cs
index a4d21c38..a91952b2 100644
--- a/devices/homie/modules/home-assistant/netdaemon/apps/Spotify/PlayAlbum/PlayAlbum.cs
+++ b/devices/homie/modules/home-assistant/netdaemon/apps/Spotify/PlayAlbum/PlayAlbum.cs
@@ -4,6 +4,7 @@ using HomeAssistantGenerated;
 using NetDaemon.AppModel;
 using NetDaemon.HassModel;
 using NetDaemon.HassModel.Integration;
+using System;
 using System.Text.Json;
 
 record PlayAlbumData(string? artist, string? album);
@@ -24,24 +25,27 @@ public class PlayAlbum
             "spotify_play_album",
             async (e) =>
             {
-                var result = (await ha.CallServiceWithResponseAsync(
-                    "spotifyplus",
-                    "search_albums",
-                    data: new SpotifyplusSearchAlbumsParameters
-                    {
-                        Criteria = $"{e?.artist} {e?.album}",
-                        LimitTotal = 1,
-                        EntityId = Global.DEFAULT_ENTITY_ID,
-                        // My Defaults
-                        Market = "CA",
-                        IncludeExternal = "audio",
-                    }
-                )).Value.Deserialize<SpotifyplusSearchAlbumsResponse>(_jsonOptions);
-
-                string? uri = result?.Result?.Items?[0]?.Uri;
-
-                if (uri is not null)
+                try
                 {
+                    var result = (await ha.CallServiceWithResponseAsync(
+                        "spotifyplus",
+                        "search_albums",
+                        data: new SpotifyplusSearchAlbumsParameters
+                        {
+                            Criteria = $"{e?.artist} {e?.album}",
+                            LimitTotal = 1,
+                            EntityId = Global.DEFAULT_ENTITY_ID,
+                            // My Defaults
+                            Market = "CA",
+                            IncludeExternal = "audio",
+                        }
+                    )).Value.Deserialize<SpotifyplusSearchAlbumsResponse>(_jsonOptions);
+
+                    string uri = result?.Result?.Items?[0]?.Uri ??
+                        throw new NullReferenceException(
+                            $"The album {e?.album}{(e?.artist is null ? "" : $" by {e?.artist}")} could not be found."
+                        );
+
                     ha.CallService(
                         "spotifyplus",
                         "player_media_play_context",
@@ -56,6 +60,18 @@ public class PlayAlbum
                         }
                     );
                 }
+                catch (Exception error)
+                {
+                    ha.CallService(
+                        "notify",
+                        "persistent_notification",
+                        data: new PersistentNotificationCreateParameters
+                        {
+                            Message = error.Message,
+                            Title = "Erreur Spotify",
+                        }
+                    );
+                }
             }
         );
     }
diff --git a/devices/homie/modules/home-assistant/netdaemon/apps/Spotify/PlayArtist/PlayArtist.cs b/devices/homie/modules/home-assistant/netdaemon/apps/Spotify/PlayArtist/PlayArtist.cs
index 86d2cccb..81ffdb19 100644
--- a/devices/homie/modules/home-assistant/netdaemon/apps/Spotify/PlayArtist/PlayArtist.cs
+++ b/devices/homie/modules/home-assistant/netdaemon/apps/Spotify/PlayArtist/PlayArtist.cs
@@ -4,6 +4,7 @@ using HomeAssistantGenerated;
 using NetDaemon.AppModel;
 using NetDaemon.HassModel;
 using NetDaemon.HassModel.Integration;
+using System;
 using System.Text.Json;
 
 record PlayArtistData(string? artist);
@@ -24,24 +25,25 @@ public class PlayArtist
             "spotify_play_artist",
             async (e) =>
             {
-                var result = (await ha.CallServiceWithResponseAsync(
-                    "spotifyplus",
-                    "search_artists",
-                    data: new SpotifyplusSearchArtistsParameters
-                    {
-                        Criteria = e?.artist,
-                        LimitTotal = 1,
-                        EntityId = Global.DEFAULT_ENTITY_ID,
-                        // My Defaults
-                        Market = "CA",
-                        IncludeExternal = "audio",
-                    }
-                )).Value.Deserialize<SpotifyplusSearchArtistsResponse>(_jsonOptions);
-
-                string? uri = result?.Result?.Items?[0]?.Uri;
-
-                if (uri is not null)
+                try
                 {
+                    var result = (await ha.CallServiceWithResponseAsync(
+                        "spotifyplus",
+                        "search_artists",
+                        data: new SpotifyplusSearchArtistsParameters
+                        {
+                            Criteria = e?.artist,
+                            LimitTotal = 1,
+                            EntityId = Global.DEFAULT_ENTITY_ID,
+                            // My Defaults
+                            Market = "CA",
+                            IncludeExternal = "audio",
+                        }
+                    )).Value.Deserialize<SpotifyplusSearchArtistsResponse>(_jsonOptions);
+
+                    string uri = result?.Result?.Items?[0]?.Uri ??
+                        throw new NullReferenceException($"The artist {e?.artist} could not be found.");
+
                     ha.CallService(
                         "spotifyplus",
                         "player_media_play_context",
@@ -56,6 +58,18 @@ public class PlayArtist
                         }
                     );
                 }
+                catch (Exception error)
+                {
+                    ha.CallService(
+                        "notify",
+                        "persistent_notification",
+                        data: new PersistentNotificationCreateParameters
+                        {
+                            Message = error.Message,
+                            Title = "Erreur Spotify",
+                        }
+                    );
+                }
             }
         );
     }
diff --git a/devices/homie/modules/home-assistant/netdaemon/apps/Spotify/PlayPlaylist/PlayPlaylist.cs b/devices/homie/modules/home-assistant/netdaemon/apps/Spotify/PlayPlaylist/PlayPlaylist.cs
index 968e1427..da32b049 100644
--- a/devices/homie/modules/home-assistant/netdaemon/apps/Spotify/PlayPlaylist/PlayPlaylist.cs
+++ b/devices/homie/modules/home-assistant/netdaemon/apps/Spotify/PlayPlaylist/PlayPlaylist.cs
@@ -28,30 +28,32 @@ public class PlayPlaylist
             "spotify_play_playlist",
             async (e) =>
             {
-                string? query = e?.playlist;
-
-                var result = (await ha.CallServiceWithResponseAsync(
-                    "spotifyplus",
-                    "get_playlist_favorites",
-                    data: new SpotifyplusGetPlaylistFavoritesParameters
-                    {
-                        LimitTotal = 200,
-                        SortResult = true,
-                        EntityId = Global.DEFAULT_ENTITY_ID,
-                    }
-                )).Value.Deserialize<SpotifyplusPlaylistResponse>(_jsonOptions);
-
-                List<PlaylistsItem>? myPlaylists = result?.Result?.Items;
-
-                if (query is not null && myPlaylists is not null)
+                try
                 {
+                    string query = e?.playlist ?? throw new NullReferenceException("Query not found.");
+
+                    var result = (await ha.CallServiceWithResponseAsync(
+                        "spotifyplus",
+                        "get_playlist_favorites",
+                        data: new SpotifyplusGetPlaylistFavoritesParameters
+                        {
+                            LimitTotal = 200,
+                            SortResult = true,
+                            EntityId = Global.DEFAULT_ENTITY_ID,
+                        }
+                    )).Value.Deserialize<SpotifyplusPlaylistResponse>(_jsonOptions);
+
+                    List<PlaylistsItem> myPlaylists = result?.Result?.Items ??
+                        throw new NullReferenceException($"No playlists found for query {query}");
+
                     ExtractedResult<PlaylistsItem> match = Process.ExtractOne<PlaylistsItem>(
                         new PlaylistsItem { Name = query.ToLower() },
                         myPlaylists,
                         new Func<PlaylistsItem, string>((item) => (item.Name ?? "").ToLower())
                     );
 
-                    string uri = match.Value!.Uri!;
+                    string uri = match.Value?.Uri ??
+                        throw new NullReferenceException($"No matches found for query {query}");
 
                     // We search outside the user's playlists if the score is too low
                     if (match.Score < 85)
@@ -70,12 +72,10 @@ public class PlayPlaylist
                             }
                         )).Value.Deserialize<SpotifyplusPlaylistResponse>(_jsonOptions);
 
-                        string? potentialUri = otherResult?.Result?.Items?[0]?.Uri;
+                        string potentialUri = otherResult?.Result?.Items?[0]?.Uri ??
+                            throw new NullReferenceException($"No public matches found for query {query}");
 
-                        if (potentialUri is not null)
-                        {
-                            uri = potentialUri;
-                        }
+                        uri = potentialUri;
                     }
 
                     ha.CallService(
@@ -92,6 +92,18 @@ public class PlayPlaylist
                         }
                     );
                 }
+                catch (Exception error)
+                {
+                    ha.CallService(
+                        "notify",
+                        "persistent_notification",
+                        data: new PersistentNotificationCreateParameters
+                        {
+                            Message = error.Message,
+                            Title = "Erreur Spotify",
+                        }
+                    );
+                }
             }
         );
     }
diff --git a/devices/homie/modules/home-assistant/netdaemon/apps/Spotify/PlaySong/PlaySong.cs b/devices/homie/modules/home-assistant/netdaemon/apps/Spotify/PlaySong/PlaySong.cs
index 450fa723..3aac5c3d 100644
--- a/devices/homie/modules/home-assistant/netdaemon/apps/Spotify/PlaySong/PlaySong.cs
+++ b/devices/homie/modules/home-assistant/netdaemon/apps/Spotify/PlaySong/PlaySong.cs
@@ -4,6 +4,7 @@ using HomeAssistantGenerated;
 using NetDaemon.AppModel;
 using NetDaemon.HassModel;
 using NetDaemon.HassModel.Integration;
+using System;
 using System.Text.Json;
 
 record PlaySongData(string? artist, string? song);
@@ -23,24 +24,26 @@ public class PlaySong
             "spotify_play_song",
             async (e) =>
             {
-                var result = (await ha.CallServiceWithResponseAsync(
-                    "spotifyplus",
-                    "search_tracks",
-                    data: new SpotifyplusSearchTracksParameters
-                    {
-                        Criteria = $"{e?.artist} {e?.song}",
-                        LimitTotal = 1,
-                        EntityId = Global.DEFAULT_ENTITY_ID,
-                        // My Defaults
-                        Market = "CA",
-                        IncludeExternal = "audio",
-                    }
-                )).Value.Deserialize<SpotifyplusSearchTracksResponse>(_jsonOptions);
-
-                string? uri = result?.Result?.Items?[0]?.Uri;
-
-                if (uri is not null)
+                try
                 {
+                    var result = (await ha.CallServiceWithResponseAsync(
+                        "spotifyplus",
+                        "search_tracks",
+                        data: new SpotifyplusSearchTracksParameters
+                        {
+                            Criteria = $"{e?.artist} {e?.song}",
+                            LimitTotal = 1,
+                            EntityId = Global.DEFAULT_ENTITY_ID,
+                            // My Defaults
+                            Market = "CA",
+                            IncludeExternal = "audio",
+                        }
+                    )).Value.Deserialize<SpotifyplusSearchTracksResponse>(_jsonOptions);
+
+                    string uri = result?.Result?.Items?[0]?.Uri ?? throw new NullReferenceException(
+                        $"The song {e?.song}{(e?.artist is null ? "" : $" by {e?.artist}")} could not be found."
+                    );
+
                     ha.CallService(
                         "spotifyplus",
                         "player_media_play_tracks",
@@ -55,6 +58,18 @@ public class PlaySong
                         }
                     );
                 }
+                catch (Exception error)
+                {
+                    ha.CallService(
+                        "notify",
+                        "persistent_notification",
+                        data: new PersistentNotificationCreateParameters
+                        {
+                            Message = error.Message,
+                            Title = "Erreur Spotify",
+                        }
+                    );
+                }
             }
         );
     }