diff --git a/lib/mix/tasks/obsidian/import.ex b/lib/mix/tasks/obsidian/import.ex new file mode 100644 index 00000000..403df123 --- /dev/null +++ b/lib/mix/tasks/obsidian/import.ex @@ -0,0 +1,64 @@ +defmodule Mix.Tasks.Obsidian.Import do + use Mix.Task + + @shortdoc "Import records from an Obsidian Vault containing Media entries " + @moduledoc """ + Import records from an Obsidian Vault containing Media entries. + + Requires the path of the vault as argument to the task: + + `mix obsidian.import path/to/vault` + """ + + @impl Mix.Task + def run(args) do + case args do + [] -> + Mix.Shell.IO.error("Error: requires the path to the obsidian vault record folder") + System.halt(1) + + [path] -> + Mix.Shell.IO.info("Seeding the database from #{path}") + + %{valid: valid, errors: errors} = + Path.wildcard("#{path}/*.md") + |> Enum.reduce(%{valid: [], errors: []}, fn entry, acc -> + file_stat = File.stat!(entry) + + case entry + |> File.read!() + |> Obsidian.Parser.from_file_contents() do + {:ok, parsed_entry} -> + inserted_at = + file_stat.ctime + |> NaiveDateTime.from_erl!() + |> DateTime.from_naive!("Etc/UTC") + + updated_at = + file_stat.mtime + |> NaiveDateTime.from_erl!() + |> DateTime.from_naive!("Etc/UTC") + + data = + parsed_entry + |> Map.put(:inserted_at, inserted_at) + |> Map.put(:updated_at, updated_at) + + %{acc | valid: [data | acc.valid]} + + {:error, error} -> + %{acc | errors: [{entry, error} | acc.errors]} + end + end) + + Mix.Shell.IO.info("Parsed #{length(valid)} entries") + Mix.Shell.IO.error("Failed to parse #{length(errors)} entries") + + MusicLibrary.Repo.insert_all(MusicLibrary.Records.Record, valid) + + _other -> + Mix.Shell.IO.error("Error: too many arguments") + System.halt(1) + end + end +end diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs index 78eaabef..7fd82d8e 100644 --- a/priv/repo/seeds.exs +++ b/priv/repo/seeds.exs @@ -9,53 +9,3 @@ # # We recommend using the bang functions (`insert!`, `update!` # and so on) as they will fail if something goes wrong. - -case System.argv() do - [] -> - IO.puts("Error: requires the path to the obsidian vault record folder") - System.halt(1) - - [path] -> - # TODO: validate path - IO.puts("Seeding the database from #{path}") - - %{valid: valid, errors: errors} = - Path.wildcard("#{path}/*.md") - |> Enum.reduce(%{valid: [], errors: []}, fn entry, acc -> - file_stat = File.stat!(entry) - - case entry - |> File.read!() - |> Obsidian.Parser.from_file_contents() do - {:ok, parsed_entry} -> - inserted_at = - file_stat.ctime - |> NaiveDateTime.from_erl!() - |> DateTime.from_naive!("Etc/UTC") - - updated_at = - file_stat.mtime - |> NaiveDateTime.from_erl!() - |> DateTime.from_naive!("Etc/UTC") - - data = - parsed_entry - |> Map.put(:inserted_at, inserted_at) - |> Map.put(:updated_at, updated_at) - - %{acc | valid: [data | acc.valid]} - - {:error, error} -> - %{acc | errors: [{entry, error} | acc.errors]} - end - end) - - IO.puts("Parsed #{length(valid)} entries") - IO.puts("Failed to parse #{length(errors)} entries") - - MusicLibrary.Repo.insert_all(MusicLibrary.Records.Record, valid) - - _other -> - IO.puts("Error: too many arguments") - System.halt(1) -end