From 8a4bdfc11810e3aa7fa1d2cef41a7313650e92cb Mon Sep 17 00:00:00 2001 From: Kip Cole Date: Wed, 26 Mar 2025 10:12:15 +1100 Subject: [PATCH] Add basic support for parsing VALARM --- lib/magical/alarm.ex | 24 ++++++++++++ lib/magical/event.ex | 6 ++- lib/magical/parser/alarm_parser.ex | 53 +++++++++++++++++++++++++++ lib/magical/parser/duration_parser.ex | 21 +++++++++++ lib/magical/parser/event_parser.ex | 6 ++- 5 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 lib/magical/alarm.ex create mode 100644 lib/magical/parser/alarm_parser.ex create mode 100644 lib/magical/parser/duration_parser.ex diff --git a/lib/magical/alarm.ex b/lib/magical/alarm.ex new file mode 100644 index 0000000..3629bc8 --- /dev/null +++ b/lib/magical/alarm.ex @@ -0,0 +1,24 @@ +defmodule Magical.Alarm do + @moduledoc """ + A representation of a iCalendar VALARM + """ + + defstruct uid: nil, + acknowledged: nil, + action: nil, + description: nil, + trigger: nil, + x_wr_alarm_uid: nil, + x_apple_default_alarm: nil + + + @type t :: %__MODULE__{ + uid: String.t(), + acknowledged: DateTime.t(), + action: String.t(), + description: String.t(), + trigger: Duration.t() | DateTime.t(), + x_wr_alarm_uid: String.t(), + x_apple_default_alarm: boolean() | nil + } +end \ No newline at end of file diff --git a/lib/magical/event.ex b/lib/magical/event.ex index 0301603..8ad718f 100644 --- a/lib/magical/event.ex +++ b/lib/magical/event.ex @@ -31,7 +31,8 @@ defmodule Magical.Event do rstatus: nil, related: nil, resources: nil, - rdate: nil + rdate: nil, + alarm: nil @type t :: %__MODULE__{ uid: String.t(), @@ -62,6 +63,7 @@ defmodule Magical.Event do rstatus: String.t(), related: String.t(), resources: String.t(), - rdate: String.t() + rdate: String.t(), + alarm: Magical.Alarm.t() } end diff --git a/lib/magical/parser/alarm_parser.ex b/lib/magical/parser/alarm_parser.ex new file mode 100644 index 0000000..9927ddd --- /dev/null +++ b/lib/magical/parser/alarm_parser.ex @@ -0,0 +1,53 @@ +defmodule Magical.Parser.AlarmParser do + @moduledoc false + + alias Magical.Alarm + alias Magical.Parser.DateParser + alias Magical.Parser.TextParser + alias Magical.Parser.DurationParser + + def parse(lines) do + Enum.reduce(lines, %Alarm{}, &parse_alarm/2) + end + + defp parse_alarm({"uid", uid, _args}, alarm) do + Map.put(alarm, :uid, TextParser.parse(uid)) + end + + defp parse_alarm({"x-wr-alarmuid", uid, _args}, alarm) do + Map.put(alarm, :x_wr_alarm_uid, TextParser.parse(uid)) + end + + defp parse_alarm({"acknowledged", datetime, args}, alarm) do + Map.put(alarm, :acknowledged, DateParser.parse(datetime, args)) + end + + defp parse_alarm({"action", action, _args}, alarm) do + Map.put(alarm, :action, TextParser.parse(action)) + end + + defp parse_alarm({"description", description, _args}, alarm) do + Map.put(alarm, :action, TextParser.parse(description)) + end + + defp parse_alarm({"trigger", trigger, args}, alarm) do + Map.put(alarm, :trigger, DurationParser.parse(trigger, args)) + end + + defp parse_alarm({"x-apple-default-alarm", "TRUE", _args}, alarm) do + Map.put(alarm, :x_apple_default_alarm, true) + end + + defp parse_alarm({"x-apple-default-alarm", "FALSE", _args}, alarm) do + Map.put(alarm, :x_apple_default_alarm, false) + end + + defp parse_alarm({"x-apple-default-alarm", _, _args}, alarm) do + Map.put(alarm, :x_apple_default_alarm, nil) + end + + defp parse_alarm({"end", "VALARM", _args}, alarm) do + alarm + end + +end \ No newline at end of file diff --git a/lib/magical/parser/duration_parser.ex b/lib/magical/parser/duration_parser.ex new file mode 100644 index 0000000..a363389 --- /dev/null +++ b/lib/magical/parser/duration_parser.ex @@ -0,0 +1,21 @@ +defmodule Magical.Parser.DurationParser do + @moduledoc """ + Responsible for parsing durations or delegating to + datetime parsing. + """ + + alias Magical.Parser.DateParser + + def parse("P" <> _rest = duration_string, _args) do + Duration.from_iso8601!(duration_string) + end + + def parse("-P" <> _rest = duration_string, _args) do + Duration.from_iso8601!(duration_string) + end + + def parse(datetime_string, args) do + DateParser.parse(datetime_string, args) + end + +end \ No newline at end of file diff --git a/lib/magical/parser/event_parser.ex b/lib/magical/parser/event_parser.ex index d47ef48..d568adb 100644 --- a/lib/magical/parser/event_parser.ex +++ b/lib/magical/parser/event_parser.ex @@ -1,9 +1,10 @@ defmodule Magical.Parser.EventParser do @moduledoc false - alias Magical.Parser.TextParser alias Magical.Event + alias Magical.Parser.TextParser alias Magical.Parser.DateParser + alias Magical.Parser.AlarmParser def parse(lines) do Enum.reduce(lines, %Event{}, &parse_event/2) @@ -27,6 +28,9 @@ defmodule Magical.Parser.EventParser do defp parse_event({"created", created, _}, event), do: Map.put(event, :created, DateParser.parse(created, %{})) + defp parse_event([{"begin", "VALARM", _} | alarm], event), + do: Map.put(event, :alarm, AlarmParser.parse(alarm)) + defp parse_event({field, value, _}, event) do keys = Magical.Event.__struct__()