AP refactoring.
[akkoma] / lib / pleroma / web / twitter_api / twitter_api_controller.ex
1 defmodule Pleroma.Web.TwitterAPI.Controller do
2 use Pleroma.Web, :controller
3 alias Pleroma.Web.TwitterAPI.TwitterAPI
4 alias Pleroma.Web.TwitterAPI.Representers.{UserRepresenter, ActivityRepresenter}
5 alias Pleroma.{Web, Repo, Activity}
6 alias Pleroma.Web.ActivityPub.ActivityPub
7 alias Ecto.Changeset
8
9 def verify_credentials(%{assigns: %{user: user}} = conn, _params) do
10 response = user |> UserRepresenter.to_json(%{for: user})
11
12 conn
13 |> json_reply(200, response)
14 end
15
16 def status_update(%{assigns: %{user: user}} = conn, %{"status" => status_text} = status_data) do
17 l = status_text |> String.trim |> String.length
18 if l > 0 && l < 5000 do
19 media_ids = extract_media_ids(status_data)
20 {:ok, activity} = TwitterAPI.create_status(user, Map.put(status_data, "media_ids", media_ids))
21 conn
22 |> json_reply(200, ActivityRepresenter.to_json(activity, %{user: user}))
23 else
24 empty_status_reply(conn)
25 end
26 end
27
28 def status_update(conn, _status_data) do
29 empty_status_reply(conn)
30 end
31
32 defp empty_status_reply(conn) do
33 bad_request_reply(conn, "Client must provide a 'status' parameter with a value.")
34 end
35
36 defp extract_media_ids(status_data) do
37 with media_ids when not is_nil(media_ids) <- status_data["media_ids"],
38 split_ids <- String.split(media_ids, ","),
39 clean_ids <- Enum.reject(split_ids, fn (id) -> String.length(id) == 0 end)
40 do
41 clean_ids
42 else _e -> []
43 end
44 end
45
46 def public_and_external_timeline(%{assigns: %{user: user}} = conn, params) do
47 statuses = TwitterAPI.fetch_public_and_external_statuses(user, params)
48 {:ok, json} = Poison.encode(statuses)
49
50 conn
51 |> json_reply(200, json)
52 end
53
54 def public_timeline(%{assigns: %{user: user}} = conn, params) do
55 statuses = TwitterAPI.fetch_public_statuses(user, params)
56 {:ok, json} = Poison.encode(statuses)
57
58 conn
59 |> json_reply(200, json)
60 end
61
62 def friends_timeline(%{assigns: %{user: user}} = conn, params) do
63 statuses = TwitterAPI.fetch_friend_statuses(user, params)
64 {:ok, json} = Poison.encode(statuses)
65
66 conn
67 |> json_reply(200, json)
68 end
69
70 def user_timeline(%{assigns: %{user: user}} = conn, params) do
71 case TwitterAPI.get_user(user, params) do
72 {:ok, target_user} ->
73 params = Map.merge(params, %{"actor_id" => target_user.ap_id})
74 statuses = TwitterAPI.fetch_user_statuses(user, params)
75 conn
76 |> json_reply(200, statuses |> Poison.encode!)
77 {:error, msg} ->
78 bad_request_reply(conn, msg)
79 end
80 end
81
82 def mentions_timeline(%{assigns: %{user: user}} = conn, params) do
83 statuses = TwitterAPI.fetch_mentions(user, params)
84 {:ok, json} = Poison.encode(statuses)
85
86 conn
87 |> json_reply(200, json)
88 end
89
90 def follow(%{assigns: %{user: user}} = conn, params) do
91 case TwitterAPI.follow(user, params) do
92 {:ok, user, followed, _activity} ->
93 response = followed |> UserRepresenter.to_json(%{for: user})
94 conn
95 |> json_reply(200, response)
96 {:error, msg} -> forbidden_json_reply(conn, msg)
97 end
98 end
99
100 def unfollow(%{assigns: %{user: user}} = conn, params) do
101 case TwitterAPI.unfollow(user, params) do
102 {:ok, user, unfollowed} ->
103 response = unfollowed |> UserRepresenter.to_json(%{for: user})
104 conn
105 |> json_reply(200, response)
106 {:error, msg} -> forbidden_json_reply(conn, msg)
107 end
108 end
109
110 def fetch_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do
111 response = Poison.encode!(TwitterAPI.fetch_status(user, id))
112
113 conn
114 |> json_reply(200, response)
115 end
116
117 def fetch_conversation(%{assigns: %{user: user}} = conn, %{"id" => id}) do
118 id = String.to_integer(id)
119 response = Poison.encode!(TwitterAPI.fetch_conversation(user, id))
120
121 conn
122 |> json_reply(200, response)
123 end
124
125 def upload(conn, %{"media" => media}) do
126 response = TwitterAPI.upload(media)
127 conn
128 |> put_resp_content_type("application/atom+xml")
129 |> send_resp(200, response)
130 end
131
132 def help_test(conn, _params) do
133 conn |> json_reply(200, Poison.encode!("ok"))
134 end
135
136 def upload_json(conn, %{"media" => media}) do
137 response = TwitterAPI.upload(media, "json")
138 conn
139 |> json_reply(200, response)
140 end
141
142 def config(conn, _params) do
143 response = %{
144 site: %{
145 name: Web.base_url,
146 server: Web.base_url,
147 textlimit: -1
148 }
149 }
150 |> Poison.encode!
151
152 conn
153 |> json_reply(200, response)
154 end
155
156 def favorite(%{assigns: %{user: user}} = conn, %{"id" => id}) do
157 activity = Repo.get(Activity, id)
158 {:ok, status} = TwitterAPI.favorite(user, activity)
159 response = Poison.encode!(status)
160
161 conn
162 |> json_reply(200, response)
163 end
164
165 def unfavorite(%{assigns: %{user: user}} = conn, %{"id" => id}) do
166 activity = Repo.get(Activity, id)
167 {:ok, status} = TwitterAPI.unfavorite(user, activity)
168 response = Poison.encode!(status)
169
170 conn
171 |> json_reply(200, response)
172 end
173
174 def retweet(%{assigns: %{user: user}} = conn, %{"id" => id}) do
175 activity = Repo.get(Activity, id)
176 if activity.data["actor"] == user.ap_id do
177 bad_request_reply(conn, "You cannot repeat your own notice.")
178 else
179 {:ok, status} = TwitterAPI.retweet(user, activity)
180 response = Poison.encode!(status)
181
182 conn
183
184 |> json_reply(200, response)
185 end
186 end
187
188 def register(conn, params) do
189 with {:ok, user} <- TwitterAPI.register_user(params) do
190 conn
191 |> json_reply(200, Poison.encode!(user))
192 else
193 {:error, errors} ->
194 conn
195 |> json_reply(400, Poison.encode!(errors))
196 end
197 end
198
199 def update_avatar(%{assigns: %{user: user}} = conn, params) do
200 {:ok, object} = ActivityPub.upload(params)
201 change = Changeset.change(user, %{avatar: object.data})
202 {:ok, user} = Repo.update(change)
203
204 response = Poison.encode!(UserRepresenter.to_map(user, %{for: user}))
205
206 conn
207 |> json_reply(200, response)
208 end
209
210 def external_profile(%{assigns: %{user: current_user}} = conn, %{"profileurl" => uri}) do
211 with {:ok, user_map} <- TwitterAPI.get_external_profile(current_user, uri),
212 response <- Poison.encode!(user_map) do
213 conn
214 |> json_reply(200, response)
215 end
216 end
217
218 defp bad_request_reply(conn, error_message) do
219 json = error_json(conn, error_message)
220 json_reply(conn, 400, json)
221 end
222
223 defp json_reply(conn, status, json) do
224 conn
225 |> put_resp_content_type("application/json")
226 |> send_resp(status, json)
227 end
228
229 defp forbidden_json_reply(conn, error_message) do
230 json = error_json(conn, error_message)
231 json_reply(conn, 403, json)
232 end
233
234 defp error_json(conn, error_message) do
235 %{"error" => error_message, "request" => conn.request_path} |> Poison.encode!
236 end
237 end