defmodule ExTDLib do
@moduledoc """
This module allow you to interact with and manage sessions.
"""
alias ExTDLib.Method
alias ExTDLib.Session
alias ExTDLib.Session.Registry
@default_config %Method.SetTdlibParameters{
database_encryption_key: nil,
use_test_dc: false,
database_directory: "/tmp/tdlib",
files_directory: "",
use_file_database: true,
use_chat_info_database: true,
use_message_database: true,
use_secret_chats: false,
api_id: "0",
api_hash: "0",
system_language_code: "en",
device_model: "Unknown",
system_version: "Unknown",
application_version: "Unknown",
enable_storage_optimizer: true,
ignore_file_names: true
}
@doc """
Configuration template for TDLib, to be modified and used as parameter of
`open/3`.
See `ExTDLib.Object.TdlibParameters` and
[core.telegram.org/tdlib/options](https://core.telegram.org/tdlib/options)
for details. You can obtain an `:api_id` and an `:api_hash` on
[my.telegram.org](https://my.telegram.org/) : they are required by TDLib,
**don't forget to set them !**
Be careful not to use the same `:database_directory` for two different
sessions !
"""
def default_config, do: @default_config
@doc """
Open a new session. Spawns a new instance of `tdlib-json-cli`.
* `session_name` is the identifier of the session
* `client_pid` is the PID of the process receiving the incoming messages
(`{:recv, struct}`)
* `config` is the configuration of TDLib, see `default_config/0`
* `encryption_key` is the key used to encrypt the local database, it allows to
store the session's cache and authorization key even if the client is offline
Return either `{:ok, pid}` or `{:error, reason}`.
"""
def open(session_name, client_pid, config, encryption_key \\ "") do
Session.create(session_name, client_pid, config, encryption_key)
end
@doc """
Close the session identified by `session_name`.
"""
def close(session_name) do
Session.destroy(session_name)
end
@doc """
Transmit a message over the session identified by `session_name`.
The parameter `msg` must be a struct (any map in reality) since it is
directly encoded into JSON and transmitted via TDLib. You should use the
structures generated from TDLib's documentation and provided by the
submodules of `ExTDLib.Object` and `ExTDLib.Methods`.
Alternatively it is also possible to directly provide an already encoded
binary or string, althrough you should not need it.
"""
def transmit(session_name, msg) when is_map(msg) do
json =
msg
|> Map.delete(:__struct__)
|> Map.new(fn {k, v} -> {k, transform_struct(v)} end)
|> Jason.encode!()
transmit(session_name, json)
end
def transmit(session_name, json) when is_binary(json) do
backend_pid = Registry.get(session_name, :backend_pid)
GenServer.call(backend_pid, {:transmit, json})
end
@doc """
Set the process receiving the incoming update for session
`session_name` to `client_pid`. The incoming messages can be handled with
`def handle_info({:recv, msg}, state), do: ...` using GenServer.
The client is initially set when the session is create, using `open/3`.
"""
def update_client(session_name, client_pid) do
handler_pid = Registry.get(session_name, :handler_pid)
GenServer.call(handler_pid, {:set_client, client_pid})
end
@doc false
def get_backend_binary do
config = Application.get_env(:ex_tdlib, :backend_binary)
case config do
nil -> Path.join(Mix.Project.build_path(), "/lib/tdlib_json_cli/bin/tdlib_json_cli")
_ -> config
end
end
@doc """
Converts the first letter of a string to uppercase, while leaving the rest of the string unchanged.
"""
def titlecase_once(str) do
first_letter = String.first(str)
String.replace_prefix(str, first_letter, String.upcase(first_letter))
end
defp transform_struct(map) when is_map(map) do
map
|> Map.delete(:__struct__)
|> Map.new(fn {k, v} -> {k, transform_struct(v)} end)
end
defp transform_struct(value), do: value
end