+
+ def replies(object, opts \\ []) do
+ object = Object.normalize(object)
+
+ query =
+ Object
+ |> where(
+ [o],
+ fragment("(?)->>'inReplyTo' = ?", o.data, ^object.data["id"])
+ )
+ |> order_by([o], asc: o.id)
+
+ if opts[:self_only] do
+ actor = object.data["actor"]
+ where(query, [o], fragment("(?)->>'actor' = ?", o.data, ^actor))
+ else
+ query
+ end
+ end
+
+ def self_replies(object, opts \\ []),
+ do: replies(object, Keyword.put(opts, :self_only, true))
+
+ def tags(%Object{data: %{"tag" => tags}}) when is_list(tags), do: tags
+
+ def tags(_), do: []
+
+ def hashtags(object), do: embedded_hashtags(object)
+
+ defp embedded_hashtags(%Object{data: data}) do
+ object_data_hashtags(data)
+ end
+
+ defp embedded_hashtags(_), do: []
+
+ defp object_data_hashtags(%{"tag" => tags}) when is_list(tags) do
+ # Note: AS2 map-type elements are ignored
+ Enum.filter(tags, &is_bitstring(&1))
+ end
+
+ defp object_data_hashtags(_), do: []