defmodule Facebook do @moduledoc """ Provides API wrappers for the Facebook Graph API See: https://developers.facebook.com/docs/graph-api """ use Application alias Facebook.Config alias Facebook.GraphAPI alias Facebook.GraphVideoAPI alias Facebook.ResponseFormatter def start(_type, _args) do children = [Config] opts = [strategy: :one_for_one, name: Facebook.Supervisor] Supervisor.start_link(children, opts) end @typedoc """ A token which is used to authenticate requests to Facebook's Graph API. A user access token may be generated with [Facebook Login](https://developers.facebook.com/docs/facebook-login/). Access tokens for testing purposes may be retrieved from Facebook's [Access Token Tool](https://developers.facebook.com/tools/accesstoken/) or using the [Graph Api Explorer](https://developers.facebook.com/tools/explorer/). """ @type access_token :: String.t() @typedoc """ Also referred to as an App ID, this may be found on your app dashboard. """ @type client_id :: String.t() @typedoc """ Also referred to as an App Secret, this may be found on your app dashboard. """ @type client_secret :: String.t() @typedoc """ Query values used for supplying or requesting edge attributes. """ @type fields :: list @typedoc """ Relative path to media file. """ @type file_path :: String.t() @type limit :: number @type num_resp :: {:ok, number} | {:error, Map.t()} @typedoc """ An id composed of a page and post ids separated with an underscore. """ @type object_id :: String.t() @type page_id :: String.t() | integer @typedoc """ Additional attributes for media file uploads """ @type params :: list @typedoc """ Can be: * `:angry` * `:haha` * `:love` * `:none` * `:sad` * `:thankful` * `:wow` """ @type react_type :: atom @type reaction :: :reaction @type resp :: {:ok, Map.t()} | {:error, Map.t()} @typedoc """ A type of feed or object. Feed scopes: * `:feed` * `:posts` * `:promotabled_posts` (Admin permission needed) * `:tagged` Object scopes: * `:likes` * `:comments` """ @type scope :: atom | String.t() @typedoc """ A reason for settling a payment dispute. Reasons: * `:GRANTED_REPLACEMENT_ITEM` * `:DENIED_REFUND` * `:BANNED_USER` """ @type dispute_reason :: atom | String.t() @typedoc """ A reason for refunding a payment. Reasons: * `:MALICIOUS_FRAUD` * `:FRIENDLY_FRAUD` * `:CUSTOMER_SERVICE` """ @type refunds_reason :: atom | String.t() @type currency :: String.t() @type amount :: Number.t() @typedoc """ A base64-encoded JSON string, concatenated to a signature with a single dot. E.g.: "." """ @type signed_request :: String.t() @type using_app_secret :: boolean @doc """ If you want to use an appsecret proof, pass it into set_app_secret: ## Example iex> Facebook.set_app_secret("app_secret") See: https://developers.facebook.com/docs/graph-api/securing-requests """ def set_app_secret(app_secret) do Config.app_secret(app_secret) end @doc """ Basic user infos of the logged in user specified by the `t:access_token/0` ## Examples iex> Facebook.me("id,first_name", "") {:ok, %{"first_name" => "...", "id" => "..."}} iex> Facebook.me([fields: "id,first_name"], "") {:ok, %{"first_name" => "...", "id" => "..."}} See: https://developers.facebook.com/docs/graph-api/reference/user/ """ @spec me(fields :: String.t(), access_token) :: resp def me(fields, access_token) when is_binary(fields) do me([fields: fields], access_token) end @spec me(fields, access_token) :: resp def me(fields, access_token) do params = fields |> add_app_secret(access_token) |> add_access_token(access_token) ~s(/me) |> GraphAPI.get([], params: params) |> ResponseFormatter.format_response() end @doc """ Accounts for the logged in user specified by the `t:access_token/0` ## Examples iex> Facebook.my_accounts("") {:ok, %{"data" => [...]}} See: https://developers.facebook.com/docs/graph-api/reference/user/accounts """ @spec my_accounts(access_token) :: resp def my_accounts(access_token) do params = [] |> add_app_secret(access_token) |> add_access_token(access_token) ~s(/me/accounts) |> GraphAPI.get([], params: params) |> ResponseFormatter.format_response() end @doc """ Publish to a graph edge using the supplied token. Publish to a feed. Author (user or page) is determined from the supplied token. The `t:page_id/0` is the id for the user or page feed to publish to. Apps need both `manage_pages` and `publish_pages` permissions to be able to publish as a Page. The `publish_actions` permission is required to publish as an individual. See Facebook's publishing documentation for more info: * https://developers.facebook.com/docs/pages/publishing * https://developers.facebook.com/docs/pages/publishing#personal_post * https://developers.facebook.com/docs/facebook-login/permissions#reference-publish_pages ## Examples iex> # publish a message iex> Facebook.publish(:feed, "", [message: "") {:ok, %{"id" => "{page_id}_{post_id}"}} iex> # publish a link and message iex> Facebook.publish(:feed, "", [message: "") {:ok, %{"id" => "{page_id}_{post_id}"}} iex> # create a Facebook Campaign iex> Facebook.publish(:campaigns, "act_1234546", [objective: "LINK_CLICKS", name: "a campaign"], "") {:ok, %{"id" => "{campaign_id}"}} """ @spec publish(edge :: atom(), parent_id :: String.t(), params, access_token) :: resp def publish(edge, parent_id, params, access_token) do params = params |> add_app_secret(access_token) |> add_access_token(access_token) ~s(/#{parent_id}/#{edge}) |> GraphAPI.post("", [], params: params) |> ResponseFormatter.format_response() end @doc """ Publish media to a feed. Author (user or page) is determined from the supplied token. The `t:page_id/0` is the id for the user or page feed to publish to. Same `:feed` publishing permissions apply. ## Example iex> Facebook.publish(:photo, "", "", [], "") {:ok, %{"id" => photo_id, "post_id" => "{page_id}_{post_id}"} iex> Facebook.publish(:video, "", "