+ [to, context, object, %{}]
+ end
+
+ ActivityPub.create(to, user, context, object, additional, data)
+ end
+
+ def fetch_friend_statuses(user, opts \\ %{}) do
+ ActivityPub.fetch_activities([user.ap_id | user.following], opts)
+ |> activities_to_statuses(%{for: user})
+ end
+
+ def fetch_public_statuses(user, opts \\ %{}) do
+ ActivityPub.fetch_public_activities(opts)
+ |> activities_to_statuses(%{for: user})
+ end
+
+ def fetch_user_statuses(user, opts \\ %{}) do
+ ActivityPub.fetch_activities([], opts)
+ |> activities_to_statuses(%{for: user})
+ end
+
+ def fetch_mentions(user, opts \\ %{}) do
+ ActivityPub.fetch_activities([user.ap_id], opts)
+ |> activities_to_statuses(%{for: user})
+ end
+
+ def fetch_conversation(user, id) do
+ query = from activity in Activity,
+ where: fragment("? @> ?", activity.data, ^%{ statusnetConversationId: id}),
+ limit: 1
+
+ with %Activity{} = activity <- Repo.one(query),
+ context <- activity.data["context"],
+ activities <- ActivityPub.fetch_activities_for_context(context),
+ statuses <- activities |> activities_to_statuses(%{for: user})
+ do
+ statuses
+ else e ->
+ IO.inspect(e)
+ []
+ end
+ end
+
+ def fetch_status(user, id) do
+ with %Activity{} = activity <- Repo.get(Activity, id) do
+ activity_to_status(activity, %{for: user})
+ end
+ end
+
+ def follow(%User{} = follower, params) do
+ with { :ok, %User{} = followed } <- get_user(params),
+ { :ok, follower } <- User.follow(follower, followed),
+ { :ok, activity } <- ActivityPub.insert(%{
+ "type" => "Follow",
+ "actor" => follower.ap_id,
+ "object" => followed.ap_id,
+ "published" => make_date()
+ })
+ do
+ { :ok, follower, followed, activity }
+ else
+ err -> err
+ end
+ end
+
+ def unfollow(%User{} = follower, params) do
+ with { :ok, %User{} = unfollowed } <- get_user(params),
+ { :ok, follower } <- User.unfollow(follower, unfollowed)
+ do
+ { :ok, follower, unfollowed}
+ else
+ err -> err
+ end
+ end
+
+ def favorite(%User{} = user, %Activity{data: %{"object" => object}} = activity) do
+ object = Object.get_by_ap_id(object["id"])
+
+ {:ok, _like_activity, object} = ActivityPub.like(user, object)
+ new_data = activity.data
+ |> Map.put("object", object.data)
+
+ status = %{activity | data: new_data}
+ |> activity_to_status(%{for: user})
+
+ {:ok, status}
+ end
+
+ def unfavorite(%User{} = user, %Activity{data: %{"object" => object}} = activity) do
+ object = Object.get_by_ap_id(object["id"])
+
+ {:ok, object} = ActivityPub.unlike(user, object)
+ new_data = activity.data
+ |> Map.put("object", object.data)
+
+ status = %{activity | data: new_data}
+ |> activity_to_status(%{for: user})
+
+ {:ok, status}
+ end
+
+ def retweet(%User{} = user, %Activity{data: %{"object" => object}} = activity) do
+ object = Object.get_by_ap_id(object["id"])
+
+ {:ok, _announce_activity, object} = ActivityPub.announce(user, object)
+ new_data = activity.data
+ |> Map.put("object", object.data)
+
+ status = %{activity | data: new_data}
+ |> activity_to_status(%{for: user})
+
+ {:ok, status}
+ end
+
+ def upload(%Plug.Upload{} = file, format \\ "xml") do
+ {:ok, object} = ActivityPub.upload(file)
+
+ url = List.first(object.data["url"])
+ href = url["href"]
+ type = url["mediaType"]
+
+ case format do
+ "xml" ->
+ # Fake this as good as possible...
+ """
+ <?xml version="1.0" encoding="UTF-8"?>
+ <rsp stat="ok" xmlns:atom="http://www.w3.org/2005/Atom">
+ <mediaid>#{object.id}</mediaid>
+ <media_id>#{object.id}</media_id>
+ <media_id_string>#{object.id}</media_id_string>
+ <media_url>#{href}</media_url>
+ <mediaurl>#{href}</mediaurl>
+ <atom:link rel="enclosure" href="#{href}" type="#{type}"></atom:link>
+ </rsp>
+ """
+ "json" ->
+ %{
+ media_id: object.id,
+ media_id_string: "#{object.id}}",
+ media_url: href,
+ size: 0
+ } |> Poison.encode!
+ end
+ end
+
+ def parse_mentions(text) do
+ # Modified from https://www.w3.org/TR/html5/forms.html#valid-e-mail-address
+ regex = ~r/@[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@?[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*/
+
+ Regex.scan(regex, text)
+ |> List.flatten
+ |> Enum.uniq
+ |> Enum.map(fn ("@" <> match = full_match) -> {full_match, User.get_cached_by_nickname(match)} end)
+ |> Enum.filter(fn ({_match, user}) -> user end)
+ end
+
+ def add_user_links(text, mentions) do
+ Enum.reduce(mentions, text, fn ({match, %User{ap_id: ap_id}}, text) -> String.replace(text, match, "<a href='#{ap_id}'>#{match}</a>") end)
+ end
+
+ def register_user(params) do
+ params = %{
+ nickname: params["nickname"],
+ name: params["fullname"],
+ bio: params["bio"],
+ email: params["email"],
+ password: params["password"],
+ password_confirmation: params["confirm"]