Skip to content

Commit c563cfd

Browse files
committed
add hn page
1 parent c11c68a commit c563cfd

File tree

6 files changed

+1130
-17
lines changed

6 files changed

+1130
-17
lines changed

lib/algora/jobs/schemas/job_posting.ex

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@ defmodule Algora.Jobs.JobPosting do
1414
field :email, :string
1515
field :status, Ecto.Enum, values: [:initialized, :processing, :active, :expired], null: false, default: :initialized
1616
field :expires_at, :utc_datetime_usec
17+
# e.g. "SF Bay Area (Remote)"
1718
field :location, :string
19+
# e.g. ["US", "CA", "BR"]
1820
field :countries, {:array, :string}, default: []
21+
# e.g. ["LATAM", "NA"]
1922
field :regions, {:array, :string}, default: []
2023
field :compensation, :string
2124
field :seniority, :string

lib/algora/organizations/organizations.ex

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,82 @@ defmodule Algora.Organizations do
104104
end)
105105
end
106106

107+
def onboard_organization_from_domain(domain, opts \\ %{}) do
108+
case Algora.Crawler.fetch_site_metadata(domain) do
109+
{:ok, metadata} ->
110+
org_name =
111+
case get_in(metadata, [:display_name]) do
112+
nil ->
113+
domain
114+
|> String.split(".")
115+
|> List.first()
116+
|> String.capitalize()
117+
118+
name ->
119+
name
120+
end
121+
122+
org_handle =
123+
case get_in(metadata, [:handle]) do
124+
nil ->
125+
domain
126+
|> String.split(".")
127+
|> List.first()
128+
|> String.downcase()
129+
130+
handle ->
131+
handle
132+
end
133+
134+
params =
135+
Map.merge(
136+
%{
137+
display_name: org_name,
138+
bio:
139+
get_in(metadata, [:bio]) || get_in(metadata, [:og_description]) ||
140+
get_in(metadata, [:og_title]),
141+
avatar_url: get_in(metadata, [:avatar_url]) || get_in(metadata, [:favicon_url]),
142+
handle: org_handle,
143+
domain: domain,
144+
og_title: get_in(metadata, [:og_title]),
145+
og_image_url: get_in(metadata, [:og_image_url]),
146+
website_url: get_in(metadata, [:website_url]),
147+
twitter_url: get_in(metadata, [:socials, :twitter]),
148+
github_url: get_in(metadata, [:socials, :github]),
149+
youtube_url: get_in(metadata, [:socials, :youtube]),
150+
twitch_url: get_in(metadata, [:socials, :twitch]),
151+
discord_url: get_in(metadata, [:socials, :discord]),
152+
slack_url: get_in(metadata, [:socials, :slack]),
153+
linkedin_url: get_in(metadata, [:socials, :linkedin])
154+
},
155+
opts
156+
)
157+
158+
org = Repo.one(from o in User, where: o.domain == ^domain, limit: 1)
159+
160+
org_handle =
161+
case org do
162+
nil -> ensure_unique_org_handle(params.handle)
163+
org -> org.handle
164+
end
165+
166+
case org do
167+
nil ->
168+
%User{type: :organization}
169+
|> Org.changeset(Map.put(params, :handle, org_handle))
170+
|> Repo.insert()
171+
172+
existing_org ->
173+
existing_org
174+
|> Org.changeset(Map.delete(params, :handle))
175+
|> Repo.update()
176+
end
177+
178+
{:error, error} ->
179+
{:error, error}
180+
end
181+
end
182+
107183
def generate_handle_from_email(email) do
108184
email
109185
|> String.split("@")

lib/algora/settings/settings.ex

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,4 +244,26 @@ defmodule Algora.Settings do
244244
def set_subscription_price(price) do
245245
set("subscription", %{"price" => Algora.MoneyUtils.serialize(price)})
246246
end
247+
248+
def get_hn_job_ids do
249+
case get("hn_job_ids") do
250+
%{"ids" => ids} when is_list(ids) -> ids
251+
_ -> nil
252+
end
253+
end
254+
255+
def set_hn_job_ids(ids) when is_list(ids) do
256+
set("hn_job_ids", %{"ids" => ids})
257+
end
258+
259+
def get_hn_job_seekers do
260+
case get("hn_job_seekers") do
261+
%{"handles" => handles} when is_list(handles) -> handles
262+
_ -> nil
263+
end
264+
end
265+
266+
def set_hn_job_seekers(handles) when is_list(handles) do
267+
set("hn_job_seekers", %{"handles" => handles})
268+
end
247269
end

lib/algora_web/live/admin/seed_live.ex

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ defmodule AlgoraWeb.Admin.SeedLive do
44
use AlgoraWeb, :live_view
55

66
import Ecto.Changeset
7+
import Ecto.Query
78

89
alias Algora.Accounts.User
910
alias Algora.Jobs.JobPosting
@@ -234,8 +235,9 @@ defmodule AlgoraWeb.Admin.SeedLive do
234235
rows =
235236
rows
236237
|> Stream.map(fn row -> Enum.zip_reduce(cols, row, Map.new(), fn col, val, acc -> Map.put(acc, col, val) end) end)
237-
|> Stream.map(&add_user/1)
238238
|> Stream.map(&process_row/1)
239+
|> Task.async_stream(&add_user/1, max_concurrency: 10, timeout: :infinity)
240+
|> Stream.map(fn {:ok, row} -> row end)
239241
|> Enum.to_list()
240242

241243
socket
@@ -253,29 +255,66 @@ defmodule AlgoraWeb.Admin.SeedLive do
253255
)
254256
end
255257

256-
defp add_user(row) do
257-
key = row["org_handle"]
258-
258+
defp add_user(%{"org_handle" => key} = row) when is_binary(key) and key != "" do
259259
user =
260-
if not is_nil(key) do
261-
case :ets.lookup(@user_cache_table, key) do
262-
[{_, user}] ->
260+
case :ets.lookup(@user_cache_table, key) do
261+
[{_, user}] ->
262+
user
263+
264+
_ ->
265+
with {:ok, user} <- Workspace.ensure_user(Algora.Admin.token(), key),
266+
{:ok, user} <- Repo.fetch(User, user.id) do
267+
:ets.insert(@user_cache_table, {key, user})
263268
user
269+
else
270+
_ -> nil
271+
end
272+
end
264273

265-
_ ->
266-
with {:ok, user} <- Workspace.ensure_user(Algora.Admin.token(), key),
267-
{:ok, user} <- Repo.fetch(User, user.id) do
268-
:ets.insert(@user_cache_table, {key, user})
269-
user
270-
else
271-
_ -> nil
272-
end
273-
end
274+
Map.put(row, "org", user)
275+
end
276+
277+
defp add_user(%{"company_url" => url} = row) when is_binary(url) and url != "" do
278+
user =
279+
case :ets.lookup(@user_cache_table, url) do
280+
[{_, user}] ->
281+
user
282+
283+
_ ->
284+
domain =
285+
url
286+
|> String.trim_leading("https://")
287+
|> String.trim_leading("http://")
288+
|> String.trim_leading("www.")
289+
290+
with {:ok, user} <-
291+
fetch_or_create_user(domain, %{hiring: true, tech_stack: row["tech_stack"]}),
292+
{:ok, user} <- Repo.fetch(User, user.id) do
293+
:ets.insert(@user_cache_table, {url, user})
294+
user
295+
else
296+
_ ->
297+
:ets.insert(@user_cache_table, {url, nil})
298+
nil
299+
end
274300
end
275301

276302
Map.put(row, "org", user)
277303
end
278304

305+
defp add_user(row), do: row
306+
307+
def fetch_or_create_user(domain, opts) do
308+
case Repo.one(from o in User, where: o.domain == ^domain, limit: 1) do
309+
%User{} = user ->
310+
{:ok, user}
311+
312+
_ ->
313+
res = Organizations.onboard_organization_from_domain(domain, opts)
314+
res
315+
end
316+
end
317+
279318
defp list_from_string(s) when is_binary(s) and s != "" do
280319
s
281320
|> String.split(",")
@@ -285,6 +324,14 @@ defmodule AlgoraWeb.Admin.SeedLive do
285324

286325
defp list_from_string(_s), do: []
287326

327+
defp money_from_string(s) when is_binary(s) and s != "" do
328+
s
329+
|> Decimal.new()
330+
|> Money.new!(:USD)
331+
end
332+
333+
defp money_from_string(_s), do: nil
334+
288335
defp process_row(row) do
289336
Map.merge(row, %{
290337
"tech_stack" =>
@@ -295,14 +342,15 @@ defmodule AlgoraWeb.Admin.SeedLive do
295342
end,
296343
"countries" => list_from_string(row["countries"]),
297344
"regions" => list_from_string(row["regions"]),
298-
"price" => row["price"] |> Decimal.new() |> Money.new!(:USD)
345+
"price" => money_from_string(row["price"])
299346
})
300347
end
301348

302349
defp seed_rows(rows) do
303350
Repo.transact(
304351
fn ->
305352
rows
353+
|> Enum.filter(& &1["org"])
306354
|> Enum.map(&seed_row/1)
307355
|> Enum.reduce_while(:ok, fn result, _acc ->
308356
case result do

0 commit comments

Comments
 (0)