Skip to content

Commit 00ef3b2

Browse files
committed
chore: conversion script
1 parent 26b795f commit 00ef3b2

File tree

3 files changed

+122
-2
lines changed

3 files changed

+122
-2
lines changed

lib/cesium_link/redirects/redirect.ex

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@ defmodule CesiumLink.Redirects.Redirect do
2727
|> validate_format(:slug, ~r{^[a-z0-9-]+$},
2828
message: "must contain only lowercase letters, numbers, and hyphens"
2929
)
30-
|> unique_constraint(:slug, message: "already in use")
30+
|> unique_constraint([:slug, :type], message: "already in use")
3131
end
3232
end

lib/mix/tasks/convert.ex

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
defmodule Mix.Tasks.Convert do
2+
@moduledoc """
3+
Task to read data exported (in CSV files, one for each table) from the old cesium.link project and import it to database following the new schemas.
4+
"""
5+
use Mix.Task
6+
7+
alias CesiumLink.Redirects.Redirect
8+
alias CesiumLink.Repo
9+
alias CesiumLink.Links.Link
10+
11+
def run(files) do
12+
case length(files) do
13+
3 ->
14+
Mix.Task.run("app.start")
15+
16+
convert_links(Enum.at(files, 0))
17+
convert_redirects(Enum.at(files, 1))
18+
convert_forms(Enum.at(files, 2))
19+
20+
_ ->
21+
Mix.shell().error("Invalid number of arguments")
22+
end
23+
end
24+
25+
defp convert_links(file) do
26+
file
27+
|> parse_csv()
28+
|> Enum.each(fn [
29+
_id,
30+
_version,
31+
archived,
32+
attention,
33+
visits,
34+
created_at,
35+
emoji,
36+
index,
37+
_slug,
38+
title,
39+
updated_at,
40+
url
41+
] ->
42+
%Link{
43+
archived: to_bool(archived),
44+
attention: to_bool(attention),
45+
visits: String.to_integer(visits),
46+
inserted_at: to_datetime(created_at),
47+
emoji: to_emoji(emoji),
48+
index: String.to_integer(index),
49+
name: title,
50+
edited_at: to_datetime(updated_at),
51+
url: url
52+
}
53+
|> Repo.insert()
54+
end)
55+
end
56+
57+
defp convert_redirects(file) do
58+
file
59+
|> parse_csv()
60+
|> Enum.each(fn [_id, _version, created_at, name, slug, updated_at, url, visits] ->
61+
%Redirect{
62+
inserted_at: to_datetime(created_at),
63+
name: name,
64+
slug: slug,
65+
edited_at: to_datetime(updated_at),
66+
url: url,
67+
visits: String.to_integer(visits),
68+
type: :default
69+
}
70+
|> Repo.insert()
71+
end)
72+
end
73+
74+
defp convert_forms(file) do
75+
file
76+
|> parse_csv()
77+
|> Enum.each(fn [_id, _version, created_at, name, slug, updated_at, url, visits] ->
78+
%Redirect{
79+
inserted_at: to_datetime(created_at),
80+
name: name,
81+
slug: slug,
82+
edited_at: to_datetime(updated_at),
83+
url: url,
84+
visits: String.to_integer(visits),
85+
type: :form
86+
}
87+
|> Repo.insert()
88+
end)
89+
end
90+
91+
defp parse_csv(path) do
92+
case path |> File.read() do
93+
{:ok, content} ->
94+
content
95+
|> String.replace(~r/\r\n/, "\n")
96+
|> String.split("\n")
97+
|> Enum.map(&String.split(&1, ","))
98+
|> Enum.drop(-1)
99+
100+
{:error, reason} ->
101+
raise reason
102+
end
103+
end
104+
105+
defp to_bool("true"), do: true
106+
defp to_bool("false"), do: false
107+
108+
defp to_datetime(date) do
109+
case Timex.parse(date, "{ISO:Extended}") do
110+
{:ok, date} -> date |> DateTime.truncate(:second)
111+
{:error, _} -> Timex.now() |> DateTime.truncate(:second)
112+
end
113+
end
114+
115+
defp to_emoji(emoji) do
116+
emoji
117+
|> String.replace(":", "")
118+
|> String.trim(" ")
119+
end
120+
end

priv/repo/migrations/20240418190329_create_redirects.exs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ defmodule CesiumLink.Repo.Migrations.CreateRedirects do
1414
timestamps(type: :utc_datetime)
1515
end
1616

17-
create unique_index(:redirects, [:slug])
17+
create unique_index(:redirects, [:slug, :type])
1818
end
1919
end

0 commit comments

Comments
 (0)