Current section
Files
Jump to
Current section
Files
lib/instagram/instagram.ex
defmodule Metaex.Instagram do
import Metaex.Auth
def user_info_url(access_token, ig_user_id),
do:
access_token_endpoint()
|> URI.merge("/#{api_version()}/#{ig_user_id}")
|> Map.put(
:query,
URI.encode_query(%{
access_token: access_token,
fields:
"biography,ig_id,followers_count,follows_count,media_count,name,profile_picture_url,username,website"
})
)
|> to_string
def user_insights_url(
access_token,
ig_user_id,
metric \\ "reach,impressions",
period \\ "days_28"
),
do:
access_token_endpoint()
|> URI.merge("/#{api_version()}/#{ig_user_id}/insights")
|> Map.put(
:query,
URI.encode_query(%{
access_token: access_token,
metric: metric,
period: period
})
)
|> to_string
def ig_user_tags_url(
access_token,
ig_user_id
),
do:
access_token_endpoint()
|> URI.merge("/#{api_version()}/#{ig_user_id}/tags")
|> Map.put(
:query,
URI.encode_query(%{
access_token: access_token,
fields:
"id,username,thumbnail_url,media_url,media_type,media_product_type,like_count,ig_id,comments_count,caption"
})
)
|> to_string
def business_info_url(access_token, page_id),
do:
access_token_endpoint()
|> URI.merge("/#{api_version()}/#{page_id}")
|> Map.put(
:query,
URI.encode_query(%{
access_token: access_token,
fields:
"instagram_business_account,link,name,username,website,general_info,followers_count,description,cover,category,id"
})
)
|> to_string
@doc """
Returns a list of Media IDs
"""
def ig_stories_url(access_token, ig_user_id),
do:
access_token_endpoint()
|> URI.merge("/#{api_version()}/#{ig_user_id}/stories")
|> Map.put(
:query,
URI.encode_query(%{
access_token: access_token
})
)
|> to_string()
def search_ig_user_url(access_token, ig_user_id, ig_username),
do:
access_token_endpoint()
|> URI.merge("/#{api_version()}/#{ig_user_id}")
|> Map.put(
:query,
URI.encode_query(%{
access_token: access_token,
fields:
"business_discovery.username(#{ig_username}){biography,public,ig_id,followers_count,follows_count,media_count,name,profile_picture_url,username,website}}"
})
)
|> to_string()
def feed_url(%{access_token: access_token, instagram_page_id: instagram_page_id} = params),
do:
access_token_endpoint()
|> URI.merge("/#{api_version()}/#{instagram_page_id}/media")
|> Map.put(
:query,
URI.encode_query(%{
access_token: access_token,
fields:
"is_comment_enabled,ig_id,permalink,shortcode,timestamp,thumbnail_url,username,caption,like_count",
after: Map.get(params, :after),
before: Map.get(params, :before)
})
)
|> to_string()
def media_object_url(access_token, instagram_media_id),
do:
access_token_endpoint()
|> URI.merge("/#{api_version()}/#{instagram_media_id}")
|> Map.put(
:query,
URI.encode_query(%{
access_token: access_token,
fields:
"caption,comments_count,is_comment_enabled,like_count,media_url,media_product_type,media_type,thumbnail_url,timestamp,username"
})
)
|> to_string()
def media_object_comments_url(access_token, instagram_media_id),
do:
access_token_endpoint()
|> URI.merge("/#{api_version()}/#{instagram_media_id}/comments")
|> Map.put(
:query,
URI.encode_query(%{
access_token: access_token
})
)
|> to_string()
def media_object_insights_url(
access_token,
instagram_media_id,
insight_merics \\ "ig_reels_avg_watch_time,ig_reels_video_view_total_time,likes,reach,saved,shares,total_interactions"
),
do:
access_token_endpoint()
|> URI.merge("/#{api_version()}/#{instagram_media_id}/insights")
|> Map.put(
:query,
URI.encode_query(%{
access_token: access_token,
metric: insight_merics
})
)
|> to_string()
@doc """
Maximum of 30 unique calls within 7 days
"""
def hashtag_search_url(access_token, hashtag, ig_user_id),
do:
access_token_endpoint()
|> URI.merge("/#{api_version()}/ig_hashtag_search")
|> Map.put(
:query,
URI.encode_query(%{
access_token: access_token,
q: hashtag,
user_id: ig_user_id
})
)
|> to_string()
def hashtag_recent_media_object_url(access_token, hashtag_id, ig_user_id),
do:
access_token_endpoint()
|> URI.merge("/#{api_version()}/#{hashtag_id}/recent_media")
|> Map.put(
:query,
URI.encode_query(%{
access_token: access_token,
fields:
"caption,comments_count,id,like_count,media_type,media_url,permalink,timestamp,children",
user_id: ig_user_id
})
)
|> to_string()
@doc """
30 Maximum unique hashtags within a 7 day period.
Does not return the username of the publisher
"""
def hashtag_top_media_object_url(access_token, hashtag_id, ig_user_id),
do:
access_token_endpoint()
|> URI.merge("/#{api_version()}/#{hashtag_id}/top_media")
|> Map.put(
:query,
URI.encode_query(%{
access_token: access_token,
fields:
"caption,comments_count,id,like_count,media_type,media_url,permalink,timestamp,children",
user_id: ig_user_id
})
)
|> to_string()
def user_info(access_token, ig_user_id) do
with {:ok, %Req.Response{body: response}} <-
Req.get(user_info_url(access_token, ig_user_id)) do
{:ok, response}
else
error ->
{:error, error}
end
end
def user_insights(access_token, ig_user_id) do
with {:ok, %Req.Response{body: body}} <-
Req.get(user_insights_url(access_token, ig_user_id)),
%{
"data" => [
%{
"name" => "reach",
"title" => "Reach",
"values" => reach_values
} = _reach_details,
%{
"name" => "impressions",
"title" => "Impressions",
"values" => impression_values
} = _impressions_details
]
} = _ <- body do
[impression_value | _] = impression_values
[reach_value | _] = reach_values
{:ok,
%{
"impressions" => Map.get(impression_value, "value"),
"reach" => Map.get(reach_value, "value")
}}
else
error ->
{:error, error}
end
end
def feed(%{access_token: access_token, instagram_page_id: instagram_page_id} = params) do
url =
feed_url(%{
access_token: access_token,
instagram_page_id: instagram_page_id,
after: Map.get(params, :after),
before: Map.get(params, :before)
})
with {:ok, %Req.Response{body: body}} <-
Req.get(url),
{:ok, response} <- Jason.decode(body) do
{:ok, cursor_based_media_pagination(response, params)}
else
error ->
{:error, error}
{:ok, []}
end
end
def cursor_based_media_pagination(
%{
"data" => []
},
_
),
do: []
def cursor_based_media_pagination(
%{
"data" => data,
"paging" => %{"cursors" => %{"after" => next, "before" => _}}
},
params
) do
case feed(Map.merge(params, %{after: next})) do
{:ok, second_call} ->
Enum.concat(data, second_call)
|> Enum.reduce_while([], fn current_item, acc ->
cond do
is_map(current_item) ->
{:cont, [current_item] ++ acc}
is_binary(current_item) ->
{:cont, [current_item] ++ acc}
true ->
{:cont, acc}
end
end)
_ ->
Enum.concat(data, [])
|> Enum.reduce_while([], fn current_item, acc ->
cond do
is_map(current_item) ->
{:cont, [current_item] ++ acc}
is_binary(current_item) ->
{:cont, [current_item] ++ acc}
true ->
{:cont, acc}
end
end)
end
end
def cursor_based_media_pagination(
_,
_
),
do: []
end