View Source Glific.Contacts (Glific v5.1.6)
The Contacts context.
Link to this section Summary
Functions
Add permission specific to groups, in this case we want to restrict the visibility of groups that the user can see
Check if we can send a message to the contact
Check if we can send a session message to the contact
Check if we can send a session message to the contact with some extra parameters Specifically designed for when we are trying to optin an opted out contact
create new contact history record.
Returns an %Ecto.Changeset{}
for tracking contact changes.
Get contact's current location
Update DB fields when contact opted in and ignore if it's blocked
Update DB fields when contact opted out
count contact history
Return the count of contacts, using the same filter as list_contacts
Creates a contact.
Creates a location.
Perform a DELETE request.
Perform a DELETE request.
Deletes a contact.
Perform a GET request.
Perform a GET request.
Gets a single contact.
Gets a single contact by phone number.
Convert contact field to map for variable substitution
Perform a HEAD request.
Perform a HEAD request.
check if contact is blocked or not
Check if this contact id is a new contact. We set the last message number in the contact. So if this is a first message then we can assume that this is a new contact.
Checks if the contact passed in argument is organization root contact or not
Lets centralize the code to detect simulator messages and interaction
Get contact history
Returns the list of contacts.
Return the list of contacts who are also users
This function is called by the messaging framework for all incoming messages, hence might be a good candidate to maintain a contact level cache at some point
This function will be use just by ngo user where they can only update the contacts.
Opt out a contact if the provider returns an error code about Number not existing or not on whatsapp
Upload a contact phone as opted in
Perform a OPTIONS request.
Perform a OPTIONS request.
Perform a PATCH request.
Perform a PATCH request.
Perform a POST request.
Perform a POST request.
Perform a PUT request.
Perform a PUT request.
Perform a request.
Perform request and raise in case of error.
Set session status for opted in and opted out contacts
Perform a TRACE request.
Perform a TRACE request.
Updates a contact.
Invoked from cron jobs to mass update the status of contacts belonging to a specific organization
Gets or Creates a Contact based on the unique indexes in the table. If there is a match it returns the existing contact, else it creates a new one
Link to this section Types
@type option() :: {:method, Tesla.Env.method()} | {:url, Tesla.Env.url()} | {:query, Tesla.Env.query()} | {:headers, Tesla.Env.headers()} | {:body, Tesla.Env.body()} | {:opts, Tesla.Env.opts()}
Options that may be passed to a request function. See request/2
for detailed descriptions.
Link to this section Functions
@spec add_permission(Ecto.Query.t(), Glific.Users.User.t()) :: Ecto.Query.t()
Add permission specific to groups, in this case we want to restrict the visibility of groups that the user can see
@spec can_send_message_to?(Glific.Contacts.Contact.t()) :: {:ok | :error, String.t() | nil}
Check if we can send a message to the contact
@spec can_send_message_to?(Glific.Contacts.Contact.t(), boolean()) :: {:ok | :error, String.t() | nil}
Check if we can send a session message to the contact
@spec can_send_message_to?(Glific.Contacts.Contact.t(), boolean(), map()) :: {:ok | :error, String.t() | nil}
Check if we can send a session message to the contact with some extra parameters Specifically designed for when we are trying to optin an opted out contact
@spec capture_history(Glific.Contacts.Contact.t() | non_neg_integer(), atom(), map()) :: {:ok, Glific.Contacts.ContactHistory.t()} | {:error, Ecto.Changeset.t()}
create new contact history record.
@spec change_contact(Glific.Contacts.Contact.t(), map()) :: Ecto.Changeset.t()
Returns an %Ecto.Changeset{}
for tracking contact changes.
examples
Examples
iex> change_contact(contact)
%Ecto.Changeset{data: %Contact{}}
@spec contact_location(Glific.Contacts.Contact.t()) :: {:ok, Glific.Contacts.Location.t()}
Get contact's current location
contact_opted_in(contact_attrs, organization_id, utc_time, opts \\ [])
View Source@spec contact_opted_in(map(), non_neg_integer(), DateTime.t(), Keyword.t()) :: {:ok, Glific.Contacts.Contact.t()} | {:error, Ecto.Changeset.t()}
Update DB fields when contact opted in and ignore if it's blocked
contact_opted_out(phone, organization_id, utc_time, method \\ "Glific Flows")
View Source@spec contact_opted_out(String.t(), non_neg_integer(), DateTime.t(), String.t()) :: :ok | :error
Update DB fields when contact opted out
count contact history
Return the count of contacts, using the same filter as list_contacts
@spec create_contact(map()) :: {:ok, Glific.Contacts.Contact.t()} | {:error, Ecto.Changeset.t()}
Creates a contact.
examples
Examples
iex> create_contact(%{field: value})
{:ok, %Contact{}}
iex> create_contact(%{field: bad_value})
{:error, %Ecto.Changeset{}}
@spec create_location(map()) :: {:ok, Glific.Contacts.Location.t()} | {:error, Ecto.Changeset.t()}
Creates a location.
examples
Examples
iex> Glific.Contacts.create_location(%{name: value})
{:ok, %Glific.Contacts.Location{}}
iex> Glific.Contacts.create_location(%{bad_field: bad_value})
{:error, %Ecto.Changeset{}}
@spec delete(Tesla.Env.client(), Tesla.Env.url(), [option()]) :: Tesla.Env.result()
Perform a DELETE request.
See request/1
or request/2
for options definition.
delete("/users")
delete("/users", query: [scope: "admin"])
delete(client, "/users")
delete(client, "/users", query: [scope: "admin"])
delete(client, "/users", body: %{name: "Jon"})
@spec delete!(Tesla.Env.client(), Tesla.Env.url(), [option()]) :: Tesla.Env.t() | no_return()
Perform a DELETE request.
See request!/1
or request!/2
for options definition.
delete!("/users")
delete!("/users", query: [scope: "admin"])
delete!(client, "/users")
delete!(client, "/users", query: [scope: "admin"])
delete!(client, "/users", body: %{name: "Jon"})
@spec delete_contact(Glific.Contacts.Contact.t()) :: {:ok, Glific.Contacts.Contact.t()} | {:error, Ecto.Changeset.t()}
Deletes a contact.
examples
Examples
iex> delete_contact(contact)
{:ok, %Contact{}}
iex> delete_contact(contact)
{:error, %Ecto.Changeset{}}
@spec get(Tesla.Env.client(), Tesla.Env.url(), [option()]) :: Tesla.Env.result()
Perform a GET request.
See request/1
or request/2
for options definition.
get("/users")
get("/users", query: [scope: "admin"])
get(client, "/users")
get(client, "/users", query: [scope: "admin"])
get(client, "/users", body: %{name: "Jon"})
@spec get!(Tesla.Env.client(), Tesla.Env.url(), [option()]) :: Tesla.Env.t() | no_return()
Perform a GET request.
See request!/1
or request!/2
for options definition.
get!("/users")
get!("/users", query: [scope: "admin"])
get!(client, "/users")
get!(client, "/users", query: [scope: "admin"])
get!(client, "/users", body: %{name: "Jon"})
@spec get_contact!(integer()) :: Glific.Contacts.Contact.t()
Gets a single contact.
Raises Ecto.NoResultsError
if the Contact does not exist.
examples
Examples
iex> get_contact!(123)
%Contact{}
iex> get_contact!(456)
** (Ecto.NoResultsError)
@spec get_contact_by_phone!(String.t()) :: Glific.Contacts.Contact.t()
Gets a single contact by phone number.
Raises Ecto.NoResultsError
if the Contact does not exist.
examples
Examples
iex> get_contact_by_phone!("9876543210_1")
%Contact{}
iex> get_contact!("123")
** (Ecto.NoResultsError)
Convert contact field to map for variable substitution
@spec head(Tesla.Env.client(), Tesla.Env.url(), [option()]) :: Tesla.Env.result()
Perform a HEAD request.
See request/1
or request/2
for options definition.
head("/users")
head("/users", query: [scope: "admin"])
head(client, "/users")
head(client, "/users", query: [scope: "admin"])
head(client, "/users", body: %{name: "Jon"})
@spec head!(Tesla.Env.client(), Tesla.Env.url(), [option()]) :: Tesla.Env.t() | no_return()
Perform a HEAD request.
See request!/1
or request!/2
for options definition.
head!("/users")
head!("/users", query: [scope: "admin"])
head!(client, "/users")
head!(client, "/users", query: [scope: "admin"])
head!(client, "/users", body: %{name: "Jon"})
@spec is_contact_blocked?(Glific.Contacts.Contact.t()) :: boolean()
check if contact is blocked or not
Check if this contact id is a new contact. We set the last message number in the contact. So if this is a first message then we can assume that this is a new contact.
@spec is_org_root_contact?(Glific.Contacts.Contact.t()) :: boolean()
Checks if the contact passed in argument is organization root contact or not
Lets centralize the code to detect simulator messages and interaction
@spec list_contact_history(map()) :: [Glific.Contacts.ContactHistory.t()]
Get contact history
@spec list_contacts(map()) :: [Glific.Contacts.Contact.t()]
Returns the list of contacts.
examples
Examples
iex> list_contacts()
[%Contact{}, ...]
Get the list of contacts filtered by various search options Include contacts only if within list of groups Include contacts only if have list of tags
@spec list_user_contacts(map()) :: [Glific.Contacts.Contact.t()]
Return the list of contacts who are also users
@spec maybe_create_contact(map()) :: {:ok, Glific.Contacts.Contact.t()} | {:error, Ecto.Changeset.t()}
This function is called by the messaging framework for all incoming messages, hence might be a good candidate to maintain a contact level cache at some point
We use a fetch followed by create, to avoid the explosion in the id namespace. We also avoid updating the contact to skip the DB call, and only do so if the name has changed
@spec maybe_update_contact(map()) :: {:ok, Glific.Contacts.Contact.t()} | {:error, Ecto.Changeset.t()} | {:error, any()}
This function will be use just by ngo user where they can only update the contacts.
number_does_not_exist(contact_id, method \\ "Number does not exist")
View Source@spec number_does_not_exist(non_neg_integer(), String.t()) :: any()
Opt out a contact if the provider returns an error code about Number not existing or not on whatsapp
@spec optin_contact(map()) :: {:ok, Glific.Contacts.Contact.t()} | {:error, Ecto.Changeset.t()} | {:error, String.t()}
Upload a contact phone as opted in
@spec options(Tesla.Env.client(), Tesla.Env.url(), [option()]) :: Tesla.Env.result()
Perform a OPTIONS request.
See request/1
or request/2
for options definition.
options("/users")
options("/users", query: [scope: "admin"])
options(client, "/users")
options(client, "/users", query: [scope: "admin"])
options(client, "/users", body: %{name: "Jon"})
@spec options!(Tesla.Env.client(), Tesla.Env.url(), [option()]) :: Tesla.Env.t() | no_return()
Perform a OPTIONS request.
See request!/1
or request!/2
for options definition.
options!("/users")
options!("/users", query: [scope: "admin"])
options!(client, "/users")
options!(client, "/users", query: [scope: "admin"])
options!(client, "/users", body: %{name: "Jon"})
@spec patch(Tesla.Env.client(), Tesla.Env.url(), Tesla.Env.body(), [option()]) :: Tesla.Env.result()
Perform a PATCH request.
See request/1
or request/2
for options definition.
patch("/users", %{name: "Jon"})
patch("/users", %{name: "Jon"}, query: [scope: "admin"])
patch(client, "/users", %{name: "Jon"})
patch(client, "/users", %{name: "Jon"}, query: [scope: "admin"])
@spec patch!(Tesla.Env.client(), Tesla.Env.url(), Tesla.Env.body(), [option()]) :: Tesla.Env.t() | no_return()
Perform a PATCH request.
See request!/1
or request!/2
for options definition.
patch!("/users", %{name: "Jon"})
patch!("/users", %{name: "Jon"}, query: [scope: "admin"])
patch!(client, "/users", %{name: "Jon"})
patch!(client, "/users", %{name: "Jon"}, query: [scope: "admin"])
@spec post(Tesla.Env.client(), Tesla.Env.url(), Tesla.Env.body(), [option()]) :: Tesla.Env.result()
Perform a POST request.
See request/1
or request/2
for options definition.
post("/users", %{name: "Jon"})
post("/users", %{name: "Jon"}, query: [scope: "admin"])
post(client, "/users", %{name: "Jon"})
post(client, "/users", %{name: "Jon"}, query: [scope: "admin"])
@spec post!(Tesla.Env.client(), Tesla.Env.url(), Tesla.Env.body(), [option()]) :: Tesla.Env.t() | no_return()
Perform a POST request.
See request!/1
or request!/2
for options definition.
post!("/users", %{name: "Jon"})
post!("/users", %{name: "Jon"}, query: [scope: "admin"])
post!(client, "/users", %{name: "Jon"})
post!(client, "/users", %{name: "Jon"}, query: [scope: "admin"])
@spec put(Tesla.Env.client(), Tesla.Env.url(), Tesla.Env.body(), [option()]) :: Tesla.Env.result()
Perform a PUT request.
See request/1
or request/2
for options definition.
put("/users", %{name: "Jon"})
put("/users", %{name: "Jon"}, query: [scope: "admin"])
put(client, "/users", %{name: "Jon"})
put(client, "/users", %{name: "Jon"}, query: [scope: "admin"])
@spec put!(Tesla.Env.client(), Tesla.Env.url(), Tesla.Env.body(), [option()]) :: Tesla.Env.t() | no_return()
Perform a PUT request.
See request!/1
or request!/2
for options definition.
put!("/users", %{name: "Jon"})
put!("/users", %{name: "Jon"}, query: [scope: "admin"])
put!(client, "/users", %{name: "Jon"})
put!(client, "/users", %{name: "Jon"}, query: [scope: "admin"])
@spec request(Tesla.Env.client(), [option()]) :: Tesla.Env.result()
Perform a request.
options
Options
:method
- the request method, one of [:head
,:get
,:delete
,:trace
,:options
,:post
,:put
,:patch
]:url
- either full url e.g. "http://example.com/some/path" or just "/some/path" if usingTesla.Middleware.BaseUrl
:query
- a keyword list of query params, e.g.[page: 1, per_page: 100]
:headers
- a keyworld list of headers, e.g.[{"content-type", "text/plain"}]
:body
- depends on used middleware:- by default it can be a binary
- if using e.g. JSON encoding middleware it can be a nested map
- if adapter supports it it can be a Stream with any of the above
:opts
- custom, per-request middleware or adapter options
examples
Examples
ExampleApi.request(method: :get, url: "/users/path")
# use shortcut methods
ExampleApi.get("/users/1")
ExampleApi.post(client, "/users", %{name: "Jon"})
@spec request!(Tesla.Env.client(), [option()]) :: Tesla.Env.t() | no_return()
Perform request and raise in case of error.
This is similar to request/2
behaviour from Tesla 0.x
See request/2
for list of available options.
@spec set_session_status(Glific.Contacts.Contact.t() | [non_neg_integer()], atom()) :: {:ok, Glific.Contacts.Contact.t()} | {:error, Ecto.Changeset.t()} | :ok
Set session status for opted in and opted out contacts
@spec trace(Tesla.Env.client(), Tesla.Env.url(), [option()]) :: Tesla.Env.result()
Perform a TRACE request.
See request/1
or request/2
for options definition.
trace("/users")
trace("/users", query: [scope: "admin"])
trace(client, "/users")
trace(client, "/users", query: [scope: "admin"])
trace(client, "/users", body: %{name: "Jon"})
@spec trace!(Tesla.Env.client(), Tesla.Env.url(), [option()]) :: Tesla.Env.t() | no_return()
Perform a TRACE request.
See request!/1
or request!/2
for options definition.
trace!("/users")
trace!("/users", query: [scope: "admin"])
trace!(client, "/users")
trace!(client, "/users", query: [scope: "admin"])
trace!(client, "/users", body: %{name: "Jon"})
@spec update_contact(Glific.Contacts.Contact.t(), map()) :: {:ok, Glific.Contacts.Contact.t()} | {:error, Ecto.Changeset.t()}
Updates a contact.
examples
Examples
iex> update_contact(contact, %{field: new_value})
{:ok, %Contact{}}
iex> update_contact(contact, %{field: bad_value})
{:error, %Ecto.Changeset{}}
@spec update_contact_status(non_neg_integer(), map()) :: :ok
Invoked from cron jobs to mass update the status of contacts belonging to a specific organization
In this case, if we can, we might want to do it across the entire DB since the update is across all organizations. The main issue might be the row level security of postgres and how it ties in. For now, lets stick to per organization
@spec upsert(map()) :: {:ok, Glific.Contacts.Contact.t()}
Gets or Creates a Contact based on the unique indexes in the table. If there is a match it returns the existing contact, else it creates a new one