diff options
Diffstat (limited to 'lib/pleroma/web/twitter_api')
-rw-r--r-- | lib/pleroma/web/twitter_api/representers/activity_representer.ex | 57 | ||||
-rw-r--r-- | lib/pleroma/web/twitter_api/twitter_api.ex | 138 | ||||
-rw-r--r-- | lib/pleroma/web/twitter_api/twitter_api_controller.ex | 45 |
3 files changed, 220 insertions, 20 deletions
diff --git a/lib/pleroma/web/twitter_api/representers/activity_representer.ex b/lib/pleroma/web/twitter_api/representers/activity_representer.ex index 9e4ffaefe..f2bf93abb 100644 --- a/lib/pleroma/web/twitter_api/representers/activity_representer.ex +++ b/lib/pleroma/web/twitter_api/representers/activity_representer.ex @@ -4,6 +4,51 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do alias Pleroma.Activity + defp user_by_ap_id(user_list, ap_id) do + Enum.find(user_list, fn (%{ap_id: user_id}) -> ap_id == user_id end) + end + + def to_map(%Activity{data: %{"type" => "Announce", "actor" => actor}} = activity, %{users: users, announced_activity: announced_activity} = opts) do + user = user_by_ap_id(users, actor) + created_at = get_in(activity.data, ["published"]) + |> date_to_asctime + + text = "#{user.nickname} retweeted a status." + + announced_user = user_by_ap_id(users, announced_activity.data["actor"]) + retweeted_status = to_map(announced_activity, Map.merge(%{user: announced_user}, opts)) + %{ + "id" => activity.id, + "user" => UserRepresenter.to_map(user, opts), + "statusnet_html" => text, + "text" => text, + "is_local" => true, + "is_post_verb" => false, + "uri" => "tag:#{activity.data["id"]}:objectType=note", + "created_at" => created_at, + "retweeted_status" => retweeted_status + } + end + + def to_map(%Activity{data: %{"type" => "Like"}} = activity, %{user: user, liked_activity: liked_activity} = opts) do + created_at = get_in(activity.data, ["published"]) + |> date_to_asctime + + text = "#{user.nickname} favorited a status." + + %{ + "id" => activity.id, + "user" => UserRepresenter.to_map(user, opts), + "statusnet_html" => text, # TODO: add summary + "text" => text, + "is_local" => true, + "is_post_verb" => false, + "uri" => "tag:#{activity.data["id"]}:objectType=Favourite", + "created_at" => created_at, + "in_reply_to_status_id" => liked_activity.id, + } + end + def to_map(%Activity{data: %{"type" => "Follow"}} = activity, %{user: user} = opts) do created_at = get_in(activity.data, ["published"]) |> date_to_asctime @@ -25,6 +70,10 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do content = get_in(activity.data, ["object", "content"]) created_at = get_in(activity.data, ["object", "published"]) |> date_to_asctime + like_count = get_in(activity.data, ["object", "like_count"]) || 0 + announcement_count = get_in(activity.data, ["object", "announcement_count"]) || 0 + favorited = opts[:for] && opts[:for].ap_id in (activity.data["object"]["likes"] || []) + repeated = opts[:for] && opts[:for].ap_id in (activity.data["object"]["announcements"] || []) mentions = opts[:mentioned] || [] @@ -45,14 +94,18 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do "in_reply_to_status_id" => activity.data["object"]["inReplyToStatusId"], "statusnet_conversation_id" => activity.data["object"]["statusnetConversationId"], "attachments" => (activity.data["object"]["attachment"] || []) |> ObjectRepresenter.enum_to_list(opts), - "attentions" => attentions + "attentions" => attentions, + "fave_num" => like_count, + "repeat_num" => announcement_count, + "favorited" => !!favorited, + "repeated" => !!repeated, } end defp date_to_asctime(date) do with {:ok, date, _offset} <- date |> DateTime.from_iso8601 do Calendar.Strftime.strftime!(date, "%a %b %d %H:%M:%S %z %Y") - else e -> + else _e -> "" end end diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex index 0217b28d6..735d88832 100644 --- a/lib/pleroma/web/twitter_api/twitter_api.ex +++ b/lib/pleroma/web/twitter_api/twitter_api.ex @@ -1,7 +1,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do alias Pleroma.{User, Activity, Repo, Object} alias Pleroma.Web.ActivityPub.ActivityPub - alias Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter + alias Pleroma.Web.TwitterAPI.Representers.{ActivityRepresenter, UserRepresenter} import Ecto.Query @@ -13,6 +13,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do context = ActivityPub.generate_context_id content = HtmlSanitizeEx.strip_tags(data["status"]) + |> String.replace("\n", "<br>") mentions = parse_mentions(content) @@ -37,7 +38,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do "content" => content_html, "published" => date, "context" => context, - "attachment" => attachments + "attachment" => attachments, + "actor" => user.ap_id }, "published" => date, "context" => context @@ -123,25 +125,74 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do end end - def upload(%Plug.Upload{} = file) do + 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"] - # 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> - """ + 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 @@ -151,7 +202,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do Regex.scan(regex, text) |> List.flatten |> Enum.uniq - |> Enum.map(fn ("@" <> match = full_match) -> {full_match, Repo.get_by(User, nickname: match)} end) + |> Enum.map(fn ("@" <> match = full_match) -> {full_match, User.get_cached_by_nickname(match)} end) |> Enum.filter(fn ({_match, user}) -> user end) end @@ -167,21 +218,72 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do |> put_in(["object", "statusnetConversationId"], activity.id) |> put_in(["statusnetConversationId"], activity.id) + object = Object.get_by_ap_id(activity.data["object"]["id"]) + + changeset = Ecto.Changeset.change(object, data: data["object"]) + Repo.update(changeset) + changeset = Ecto.Changeset.change(activity, data: data) Repo.update(changeset) 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"] + } + + changeset = User.register_changeset(%User{}, params) + + with {:ok, user} <- Repo.insert(changeset) do + {:ok, UserRepresenter.to_map(user)} + else + {:error, changeset} -> + errors = Ecto.Changeset.traverse_errors(changeset, fn {msg, opts} -> msg end) + |> Poison.encode! + {:error, %{error: errors}} + end + end + defp activities_to_statuses(activities, opts) do Enum.map(activities, fn(activity) -> activity_to_status(activity, opts) end) end + # For likes, fetch the liked activity, too. + defp activity_to_status(%Activity{data: %{"type" => "Like"}} = activity, opts) do + actor = get_in(activity.data, ["actor"]) + user = User.get_cached_by_ap_id(actor) + [liked_activity] = Activity.all_by_object_ap_id(activity.data["object"]) + + ActivityRepresenter.to_map(activity, Map.merge(opts, %{user: user, liked_activity: liked_activity})) + end + + # For announces, fetch the announced activity and the user. + defp activity_to_status(%Activity{data: %{"type" => "Announce"}} = activity, opts) do + actor = get_in(activity.data, ["actor"]) + user = User.get_cached_by_ap_id(actor) + [announced_activity] = Activity.all_by_object_ap_id(activity.data["object"]) + announced_actor = User.get_cached_by_ap_id(announced_activity.data["actor"]) + + ActivityRepresenter.to_map(activity, Map.merge(opts, %{users: [user, announced_actor], announced_activity: announced_activity})) + end + defp activity_to_status(activity, opts) do actor = get_in(activity.data, ["actor"]) - user = Repo.get_by!(User, ap_id: actor) - mentioned_users = Repo.all(from user in User, where: user.ap_id in ^activity.data["to"]) + user = User.get_cached_by_ap_id(actor) + # mentioned_users = Repo.all(from user in User, where: user.ap_id in ^activity.data["to"]) + mentioned_users = Enum.map(activity.data["to"], fn (ap_id) -> + User.get_cached_by_ap_id(ap_id) + end) + |> Enum.filter(&(&1)) + ActivityRepresenter.to_map(activity, Map.merge(opts, %{user: user, mentioned: mentioned_users})) end diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex index 766da6c93..f2ca83915 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -2,6 +2,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do use Pleroma.Web, :controller alias Pleroma.Web.TwitterAPI.TwitterAPI alias Pleroma.Web.TwitterAPI.Representers.{UserRepresenter, ActivityRepresenter} + alias Pleroma.{Repo, Activity} def verify_credentials(%{assigns: %{user: user}} = conn, _params) do response = user |> UserRepresenter.to_json(%{for: user}) @@ -87,6 +88,12 @@ defmodule Pleroma.Web.TwitterAPI.Controller do conn |> json_reply(200, Poison.encode!("ok")) end + def upload_json(conn, %{"media" => media}) do + response = TwitterAPI.upload(media, "json") + conn + |> json_reply(200, response) + end + def config(conn, _params) do response = %{ site: %{ @@ -101,6 +108,44 @@ defmodule Pleroma.Web.TwitterAPI.Controller do |> json_reply(200, response) end + def favorite(%{assigns: %{user: user}} = conn, %{"id" => id}) do + activity = Repo.get(Activity, id) + {:ok, status} = TwitterAPI.favorite(user, activity) + response = Poison.encode!(status) + + conn + |> json_reply(200, response) + end + + def unfavorite(%{assigns: %{user: user}} = conn, %{"id" => id}) do + activity = Repo.get(Activity, id) + {:ok, status} = TwitterAPI.unfavorite(user, activity) + response = Poison.encode!(status) + + conn + |> json_reply(200, response) + end + + def retweet(%{assigns: %{user: user}} = conn, %{"id" => id}) do + activity = Repo.get(Activity, id) + {:ok, status} = TwitterAPI.retweet(user, activity) + response = Poison.encode!(status) + + conn + |> json_reply(200, response) + end + + def register(conn, params) do + with {:ok, user} <- TwitterAPI.register_user(params) do + conn + |> json_reply(200, Poison.encode!(user)) + else + {:error, errors} -> + conn + |> json_reply(400, Poison.encode!(errors)) + end + end + defp json_reply(conn, status, json) do conn |> put_resp_content_type("application/json") |