From b3bd02a9b4a5600328d53f187990b1e59a2b1a47 Mon Sep 17 00:00:00 2001 From: Leonhard Date: Mon, 21 Aug 2023 19:14:44 +0200 Subject: [PATCH 1/4] Send notifications about weather alerts --- meson.build | 2 ++ src/Application.vala | 4 ++++ src/meson.build | 3 +++ 3 files changed, 9 insertions(+) diff --git a/meson.build b/meson.build index 8b3a5ed6..c5707be6 100644 --- a/meson.build +++ b/meson.build @@ -9,6 +9,8 @@ fwupd_dep = dependency('fwupd') gio_dep = dependency ('gio-2.0') glib_dep = dependency('glib-2.0') granite_dep = dependency('granite', version: '>= 5.3.0') +json_dep = dependency('json-glib-1.0') +soup_dep = dependency('libsoup-3.0') i18n = import('i18n') gettext_name = meson.project_name() diff --git a/src/Application.vala b/src/Application.vala index 09855167..39db7773 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -17,6 +17,8 @@ public sealed class SettingsDaemon.Application : Gtk.Application { private Backends.Housekeeping housekeeping; + private Backends.WeatherAlerts weather_alerts; + private const string FDO_ACCOUNTS_NAME = "org.freedesktop.Accounts"; private const string FDO_ACCOUNTS_PATH = "/org/freedesktop/Accounts"; @@ -52,6 +54,8 @@ public sealed class SettingsDaemon.Application : Gtk.Application { housekeeping = new Backends.Housekeeping (); + weather_alerts = new Backends.WeatherAlerts (); + var check_firmware_updates_action = new GLib.SimpleAction ("check-firmware-updates", null); check_firmware_updates_action.activate.connect (check_firmware_updates); add_action (check_firmware_updates_action); diff --git a/src/meson.build b/src/meson.build index 9c05e9a7..6d5f48af 100644 --- a/src/meson.build +++ b/src/meson.build @@ -7,6 +7,7 @@ sources = files( 'Backends/MouseSettings.vala', 'Backends/NightLightSettings.vala', 'Backends/PrefersColorSchemeSettings.vala', + 'Backends/WeatherAlerts.vala', 'Utils/SunriseSunsetCalculator.vala', ) @@ -19,8 +20,10 @@ executable( gio_dep, glib_dep, granite_dep, + json_dep, libgeoclue_dep, m_dep, + soup_dep ], install: true, ) From 45c5cf40bd66719fda5536cb92f765d40e10153a Mon Sep 17 00:00:00 2001 From: Leonhard Date: Mon, 21 Aug 2023 19:15:39 +0200 Subject: [PATCH 2/4] Add missing file --- src/Backends/WeatherAlerts.vala | 123 ++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 src/Backends/WeatherAlerts.vala diff --git a/src/Backends/WeatherAlerts.vala b/src/Backends/WeatherAlerts.vala new file mode 100644 index 00000000..14ad34e9 --- /dev/null +++ b/src/Backends/WeatherAlerts.vala @@ -0,0 +1,123 @@ +public class SettingsDaemon.Backends.WeatherAlerts : Object { + private const string API_KEY = "9d9c2fa1c0024a4b9fc152215232108"; + + private double latitude; + private double longitude; + + construct { + init_location.begin (() => { + update_alerts.begin (); + }); + + Timeout.add_seconds (3600, () => { + update_alerts.begin (); + return Source.CONTINUE; + }); + } + + private async void init_location () { + try { + var simple = yield new GClue.Simple (Build.PROJECT_NAME, GClue.AccuracyLevel.CITY, null); + + simple.notify["location"].connect (() => { + latitude = simple.location.latitude; + longitude = simple.location.longitude; + update_alerts.begin (); + }); + + latitude = simple.location.latitude; + longitude = simple.location.longitude; + } catch (Error e) { + warning ("Failed to connect to GeoClue2 service: %s", e.message); + return; + } + } + + private async void update_alerts () { + var session = new Soup.Session (); + + var msg = new Soup.Message ( + "GET", + "http://api.weatherapi.com/v1/forecast.json?key=%s&q=%s,%s&days=1&aqi=no&alerts=yes".printf ( + API_KEY, + latitude.to_string (), + longitude.to_string () + ) + ); + + msg.finished.connect (() => { + if (msg.status_code != Soup.Status.OK) { + warning ("Failed with status code %u (%s)", msg.status_code, Soup.Status.get_phrase (msg.status_code)); + } + }); + + try { + var bytes = yield session.send_and_read_async (msg, Priority.DEFAULT, null); + var json_parser = new Json.Parser (); + try { + string data = (string) bytes.get_data (); + json_parser.load_from_data (data); + var node = json_parser.get_root (); + if (node == null) { + warning ("No JSON root node found!"); + return; + } + + unowned var obj = node.get_object (); + if (obj == null) { + warning ("No root object found!"); + return; + } + + unowned var location_obj = obj.get_object_member ("location"); + if (location_obj != null) { + debug ( + "Getting alerts for %s, %s, %s", + location_obj.get_string_member ("name"), + location_obj.get_string_member ("region"), + location_obj.get_string_member ("country") + ); + } + + unowned var alerts = obj.get_object_member ("alerts"); + if (alerts == null) { + warning ("No alerts object found!"); + return; + } + + unowned var array = alerts.get_array_member ("alert"); + if (array == null) { + warning ("No alerts array found!"); + return; + } + + unowned var app = GLib.Application.get_default (); + array.foreach_element ((array, index, element_node) => { + unowned var alert_obj = element_node.get_object (); + if (alert_obj == null) { + warning ("No alert object found!"); + return; + } + + var start_time = new DateTime.from_iso8601 (alert_obj.get_string_member ("effective"), null); + + var notification = new Notification ( + "%s starting %s on %s".printf ( + alert_obj.get_string_member ("event"), + start_time.format (Granite.DateTime.get_default_time_format ()), + start_time.format (Granite.DateTime.get_default_date_format ()) + ) + ); + notification.set_icon (new ThemedIcon ("dialog-error")); + notification.set_body (alert_obj.get_string_member ("desc")); + + app.send_notification (alert_obj.get_string_member ("headline"), notification); + }); + } catch (Error e) { + warning ("Failed to parse response as json: %s", e.message); + } + } catch (Error e) { + critical ("Failed to send soup message: %s", e.message); + } + } +} From 1ba58ef18f0acc85814d4643bdd13e384401a4bf Mon Sep 17 00:00:00 2001 From: Leonhard Date: Mon, 21 Aug 2023 19:20:03 +0200 Subject: [PATCH 3/4] Change text --- src/Backends/WeatherAlerts.vala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Backends/WeatherAlerts.vala b/src/Backends/WeatherAlerts.vala index 14ad34e9..5dd78505 100644 --- a/src/Backends/WeatherAlerts.vala +++ b/src/Backends/WeatherAlerts.vala @@ -109,7 +109,7 @@ public class SettingsDaemon.Backends.WeatherAlerts : Object { ) ); notification.set_icon (new ThemedIcon ("dialog-error")); - notification.set_body (alert_obj.get_string_member ("desc")); + notification.set_body (alert_obj.get_string_member ("headline")); app.send_notification (alert_obj.get_string_member ("headline"), notification); }); From c47edb08b60b70373eb23adbda130f7e355ea079 Mon Sep 17 00:00:00 2001 From: Leonhard Date: Mon, 21 Aug 2023 21:07:14 +0200 Subject: [PATCH 4/4] Fix lint and CI --- .github/workflows/main.yml | 2 +- src/Backends/WeatherAlerts.vala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7e87ae80..2366d7bb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,7 +25,7 @@ jobs: - name: Install Dependencies run: | apt update - apt install -y libaccountsservice-dev libdbus-1-dev libgranite-dev libgeoclue-2-dev libfwupd-dev meson valac + apt install -y libaccountsservice-dev libdbus-1-dev libgranite-dev libgeoclue-2-dev libfwupd-dev libsoup-3.0-dev libjson-glib-dev meson valac - name: Build env: DESTDIR: out diff --git a/src/Backends/WeatherAlerts.vala b/src/Backends/WeatherAlerts.vala index 5dd78505..960e53c0 100644 --- a/src/Backends/WeatherAlerts.vala +++ b/src/Backends/WeatherAlerts.vala @@ -117,7 +117,7 @@ public class SettingsDaemon.Backends.WeatherAlerts : Object { warning ("Failed to parse response as json: %s", e.message); } } catch (Error e) { - critical ("Failed to send soup message: %s", e.message); + critical ("Failed to send soup message: %s", e.message); } } }