|
@@ -1,10 +1,15 @@
|
|
|
defmodule Vaccins.Queries do
|
|
defmodule Vaccins.Queries do
|
|
|
- defmodule Query do
|
|
|
|
|
|
|
+ defmodule Provider do
|
|
|
|
|
+ @callback new(list) :: any
|
|
|
|
|
+
|
|
|
@callback to_url(any) :: String.t()
|
|
@callback to_url(any) :: String.t()
|
|
|
|
|
+
|
|
|
|
|
+ @doc "Find slots in the result from the query, if any"
|
|
|
|
|
+ @callback analyze_result(any) :: any
|
|
|
end
|
|
end
|
|
|
|
|
|
|
|
defmodule Doctolib do
|
|
defmodule Doctolib do
|
|
|
- @behaviour Query
|
|
|
|
|
|
|
+ @behaviour Provider
|
|
|
alias __MODULE__, as: Doctolib
|
|
alias __MODULE__, as: Doctolib
|
|
|
|
|
|
|
|
defstruct [
|
|
defstruct [
|
|
@@ -23,9 +28,6 @@ defmodule Vaccins.Queries do
|
|
|
struct(Doctolib, kw_list)
|
|
struct(Doctolib, kw_list)
|
|
|
|> Map.replace(:start_date, Date.utc_today() |> Date.to_string())
|
|
|> 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
|
|
def to_url(q = %__MODULE__{}) do
|
|
|
query_string = q |> Map.from_struct() |> URI.encode_query()
|
|
query_string = q |> Map.from_struct() |> URI.encode_query()
|
|
|
|
|
|
|
@@ -53,45 +55,68 @@ defmodule Vaccins.Queries do
|
|
|
end
|
|
end
|
|
|
end
|
|
end
|
|
|
|
|
|
|
|
- def valid_queries(),
|
|
|
|
|
- do: [
|
|
|
|
|
- %{
|
|
|
|
|
- id: "Centre de Vaccination - Salle Olympe de Gouges",
|
|
|
|
|
- availability_query:
|
|
|
|
|
- Doctolib.new(
|
|
|
|
|
|
|
+ defmodule Location do
|
|
|
|
|
+ alias __MODULE__, as: Location
|
|
|
|
|
+ defstruct [:id, :availability_query, :booking_page, :provider, availability_query_params: []]
|
|
|
|
|
+
|
|
|
|
|
+ def build_query(l = %Location{availability_query_params: params, provider: provider})
|
|
|
|
|
+ when params != [],
|
|
|
|
|
+ do: %{l | availability_query: params |> provider.new}
|
|
|
|
|
+
|
|
|
|
|
+ def query_availability(
|
|
|
|
|
+ l = %Location{id: id, availability_query: q, booking_page: bp, provider: provider}
|
|
|
|
|
+ ) do
|
|
|
|
|
+ with url <- q |> provider.to_url() |> URI.to_string(),
|
|
|
|
|
+ {:ok, result} <- url |> Vaccins.Scraper.get_json() do
|
|
|
|
|
+ case result |> provider.analyze_result() do
|
|
|
|
|
+ {:ok, slots} -> {id, slots, bp}
|
|
|
|
|
+ {:error, reason} when reason in [:no_availability] -> {id, reason}
|
|
|
|
|
+ end
|
|
|
|
|
+ end
|
|
|
|
|
+ end
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ def get_locations(),
|
|
|
|
|
+ do:
|
|
|
|
|
+ [
|
|
|
|
|
+ %Location{
|
|
|
|
|
+ id: "Centre de Vaccination - Salle Olympe de Gouges",
|
|
|
|
|
+ provider: Doctolib,
|
|
|
|
|
+ availability_query_params: [
|
|
|
visit_motive_ids: 2_549_915,
|
|
visit_motive_ids: 2_549_915,
|
|
|
agenda_ids:
|
|
agenda_ids:
|
|
|
"434477-434486-434466-434472-440075-440077-440078-415625-434490-462178-462452-433984-462177-433604-433601-415628-440074-433997-434489-440076",
|
|
"434477-434486-434466-434472-440075-440077-440078-415625-434490-462178-462452-433984-462177-433604-433601-415628-440074-433997-434489-440076",
|
|
|
practice_ids: 164_922,
|
|
practice_ids: 164_922,
|
|
|
limit: 7
|
|
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"
|
|
|
|
|
- },
|
|
|
|
|
- %{
|
|
|
|
|
- id: "Centre de Vaccination - Paris 20e",
|
|
|
|
|
- availability_query:
|
|
|
|
|
- Doctolib.new(
|
|
|
|
|
|
|
+ ],
|
|
|
|
|
+ booking_page:
|
|
|
|
|
+ "https://partners.doctolib.fr/centre-de-sante/fontenay-sous-bois/centre-de-vaccination-covid-19-fontenay-sous-bois?pid=practice-180541"
|
|
|
|
|
+ },
|
|
|
|
|
+ %Location{
|
|
|
|
|
+ id: "Centre de Vaccination - Paris 20e",
|
|
|
|
|
+ provider: Doctolib,
|
|
|
|
|
+ availability_query_params: [
|
|
|
visit_motive_ids: 2_549_915,
|
|
visit_motive_ids: 2_549_915,
|
|
|
agenda_ids:
|
|
agenda_ids:
|
|
|
"463167-415613-463168-415615-429620-434343-463166-463170-463171-447048-440655-434052-440654-462614-462613-433994-434337-434338",
|
|
"463167-415613-463168-415615-429620-434343-463166-463170-463171-447048-440655-434052-440654-462614-462613-433994-434337-434338",
|
|
|
practice_ids: 166_459,
|
|
practice_ids: 166_459,
|
|
|
limit: 3
|
|
limit: 3
|
|
|
- ),
|
|
|
|
|
- booking_page:
|
|
|
|
|
- "https://www.doctolib.fr/centre-de-sante/paris/centre-de-vaccination-covid-19-ville-de-paris?pid=practice-166459"
|
|
|
|
|
- },
|
|
|
|
|
- %{
|
|
|
|
|
- id: "Hotel de ville de Fontenay-sous-Bois",
|
|
|
|
|
- availability_query:
|
|
|
|
|
- Doctolib.new(
|
|
|
|
|
|
|
+ ],
|
|
|
|
|
+ booking_page:
|
|
|
|
|
+ "https://www.doctolib.fr/centre-de-sante/paris/centre-de-vaccination-covid-19-ville-de-paris?pid=practice-166459"
|
|
|
|
|
+ },
|
|
|
|
|
+ %Location{
|
|
|
|
|
+ id: "Hotel de ville de Fontenay-sous-Bois",
|
|
|
|
|
+ provider: Doctolib,
|
|
|
|
|
+ availability_query_params: [
|
|
|
visit_motive_ids: 2_743_304,
|
|
visit_motive_ids: 2_743_304,
|
|
|
agenda_ids: "449169-449170-466472",
|
|
agenda_ids: "449169-449170-466472",
|
|
|
practice_ids: 180_541,
|
|
practice_ids: 180_541,
|
|
|
limit: 15
|
|
limit: 15
|
|
|
- ),
|
|
|
|
|
- booking_page:
|
|
|
|
|
- "https://partners.doctolib.fr/centre-de-sante/fontenay-sous-bois/centre-de-vaccination-covid-19-fontenay-sous-bois?pid=practice-180541&enable_cookies_consent=1"
|
|
|
|
|
- }
|
|
|
|
|
- ]
|
|
|
|
|
|
|
+ ],
|
|
|
|
|
+ booking_page:
|
|
|
|
|
+ "https://partners.doctolib.fr/centre-de-sante/fontenay-sous-bois/centre-de-vaccination-covid-19-fontenay-sous-bois?pid=practice-180541&enable_cookies_consent=1"
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+ |> Enum.map(&Location.build_query/1)
|
|
|
end
|
|
end
|