Преглед на файлове

Start adding queries/scraper/search code

theenglishway (time) преди 4 години
родител
ревизия
f072fe9c77
променени са 3 файла, в които са добавени 89 реда и са изтрити 0 реда
  1. 61 0
      lib/vaccins/queries.ex
  2. 18 0
      lib/vaccins/scraper.ex
  3. 10 0
      lib/vaccins/search.ex

+ 61 - 0
lib/vaccins/queries.ex

@@ -0,0 +1,61 @@
+defmodule Vaccins.Queries do
+  defmodule Query do
+    @callback to_url(any) :: String.t()
+  end
+
+  defmodule Doctolib do
+    @behaviour Query
+    alias __MODULE__, as: Doctolib
+
+    defstruct [
+      :start_date,
+      :visit_motive_ids,
+      :agenda_ids,
+      :practice_ids,
+      :limit,
+      insurance_sector: "public",
+      destroy_temporary: true,
+      _converter: Doctolib
+    ]
+
+    def new(kw_list),
+      do:
+        struct(Doctolib, kw_list)
+        |> Map.replace(:start_date, Date.utc_today() |> Date.to_string())
+
+    def motives(), do: %{premiere_injection_pfizer: 2_743_305}
+    def practices(), do: %{fontenay: 180_541}
+
+    def to_url(q = %__MODULE__{}) do
+      query_string = q |> Map.from_struct() |> URI.encode_query()
+
+      %URI{
+        authority: "partners.doctolib.fr",
+        fragment: nil,
+        host: "partners.doctolib.fr",
+        path: "/availabilities.json",
+        port: 443,
+        query: query_string,
+        scheme: "https",
+        userinfo: nil
+      }
+    end
+
+    def analyze_result(%{total: 0}), do: :no_availability
+  end
+
+  def valid_queries(),
+    do: %{
+      id: :olympe,
+      availability_query:
+        Doctolib.new(
+          visit_motive_ids: 2_549_915,
+          agenda_ids:
+            "434477-434486-434466-434472-440075-440077-440078-415625-434490-462178-462452-433984-462177-433604-433601-415628-440074-433997-434489-440076",
+          practice_ids: 164_922,
+          limit: 7
+        ),
+      booking_page:
+        "https://partners.doctolib.fr/centre-de-sante/fontenay-sous-bois/centre-de-vaccination-covid-19-fontenay-sous-bois?pid=practice-180541"
+    }
+end

+ 18 - 0
lib/vaccins/scraper.ex

@@ -0,0 +1,18 @@
+defmodule Vaccins.Scraper do
+  def get_json(url) do
+    with {:ok, body} <- get_body(url), do: body |> Jason.decode(keys: :atoms)
+  end
+
+  def get_body(url) when is_binary(url) do
+    case Finch.build(:get, url) |> Finch.request(Vaccins.Finch) do
+      {:ok, %{body: body, status: 200}} ->
+        {:ok, body}
+
+      {:ok, %{headers: headers, status: 301}} ->
+        headers |> Map.new() |> Map.get("location") |> get_body
+
+      e = {:error, _} ->
+        e
+    end
+  end
+end

+ 10 - 0
lib/vaccins/search.ex

@@ -0,0 +1,10 @@
+defmodule Vaccins.Search do
+  alias Vaccins.Scraper
+  alias Vaccins.Queries.Query
+
+  def do_query(q) do
+    with url <- q |> q._converter.to_url() |> URI.to_string(),
+         {:ok, result} <- url |> Vaccins.Scraper.get_json(),
+         do: result |> q._converter.analyze_result()
+  end
+end