From 9b046d2a8481c50e244071be1192830e0bbd08bc Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Wed, 22 Aug 2018 16:10:59 +0300 Subject: [PATCH 01/16] fixed notifications API completely breaking if there's a like for missing (deleted) post. --- lib/pleroma/web/twitter_api/views/activity_view.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pleroma/web/twitter_api/views/activity_view.ex b/lib/pleroma/web/twitter_api/views/activity_view.ex index 55b5287f5..0efc0df2e 100644 --- a/lib/pleroma/web/twitter_api/views/activity_view.ex +++ b/lib/pleroma/web/twitter_api/views/activity_view.ex @@ -188,7 +188,7 @@ def render("activity.json", %{activity: %{data: %{"type" => "Like"}} = activity} text = "#{user.nickname} favorited a status." - %{ + if liked_activity, do: %{ "id" => activity.id, "user" => UserView.render("show.json", %{user: user, for: opts[:for]}), "statusnet_html" => text, @@ -200,7 +200,7 @@ def render("activity.json", %{activity: %{data: %{"type" => "Like"}} = activity} "in_reply_to_status_id" => liked_activity.id, "external_url" => activity.data["id"], "activity_type" => "like" - } + }, else: %{} end def render( From 83efaa3af6470485c5b47959ea94f7089971e205 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Tue, 7 Aug 2018 22:45:40 +0200 Subject: [PATCH 02/16] [MastodonAPI] Add streaming of hashtags --- lib/pleroma/web/activity_pub/activity_pub.ex | 3 +++ lib/pleroma/web/mastodon_api/mastodon_socket.ex | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 68b398786..749ffbcd4 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -84,6 +84,9 @@ def stream_out(activity) do Pleroma.Web.Streamer.stream("public:local", activity) end + activity.data["object"]["tag"] + |> Enum.map(fn tag -> Pleroma.Web.Streamer.stream("hashtag:" <> tag, activity) end) + if activity.data["object"]["attachment"] != [] do Pleroma.Web.Streamer.stream("public:media", activity) diff --git a/lib/pleroma/web/mastodon_api/mastodon_socket.ex b/lib/pleroma/web/mastodon_api/mastodon_socket.ex index 174293906..bc628ba56 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_socket.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_socket.ex @@ -23,16 +23,18 @@ def connect(params, socket) do "public:local:media", "user", "direct", - "list" + "list", + "hashtag" ] <- params["stream"] do topic = if stream == "list", do: "list:#{params["list"]}", else: stream + socket_stream = if stream == "hashtag", do: "hashtag:#{params["tag"]}", else: stream socket = socket |> assign(:topic, topic) |> assign(:user, user) - Pleroma.Web.Streamer.add_socket(params["stream"], socket) + Pleroma.Web.Streamer.add_socket(socket_stream, socket) {:ok, socket} else _e -> :error From 97e20d293266689d57c23abc7ae12ee05996517a Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Tue, 7 Aug 2018 23:49:35 +0200 Subject: [PATCH 03/16] =?UTF-8?q?[MastodonAPI]=20the=20tag=20field=20isn?= =?UTF-8?q?=E2=80=99t=20fixed=20to=20a=20static=20type=20in=20pleroma?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pleroma/web/activity_pub/activity_pub.ex | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 749ffbcd4..ed2240530 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -84,7 +84,9 @@ def stream_out(activity) do Pleroma.Web.Streamer.stream("public:local", activity) end - activity.data["object"]["tag"] + activity.data["object"] + |> Map.get("tag", []) + |> Enum.filter(fn tag -> is_bitstring(tag) end) |> Enum.map(fn tag -> Pleroma.Web.Streamer.stream("hashtag:" <> tag, activity) end) if activity.data["object"]["attachment"] != [] do From d008f2d69c96616f8d665851994414d1b42f8761 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Fri, 10 Aug 2018 01:44:38 +0200 Subject: [PATCH 04/16] [Pleroma.Web.MastodonAPI.AccountView]: Add bot field --- .../web/mastodon_api/views/account_view.ex | 2 + test/web/mastodon_api/account_view_test.exs | 38 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index d9edcae7f..9dd635a63 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -13,6 +13,7 @@ def render("account.json", %{user: user}) do image = User.avatar_url(user) |> MediaProxy.url() header = User.banner_url(user) |> MediaProxy.url() user_info = User.user_info(user) + bot = (user.info["source_data"]["type"] || "Person") in ["Application", "Service"] emojis = (user.info["source_data"]["tag"] || []) @@ -44,6 +45,7 @@ def render("account.json", %{user: user}) do header_static: header, emojis: emojis, fields: [], + bot: bot, source: %{ note: "", privacy: "public", diff --git a/test/web/mastodon_api/account_view_test.exs b/test/web/mastodon_api/account_view_test.exs index 35c8a1fb0..5393732eb 100644 --- a/test/web/mastodon_api/account_view_test.exs +++ b/test/web/mastodon_api/account_view_test.exs @@ -49,6 +49,44 @@ test "Represent a user account" do } ], fields: [], + bot: false, + source: %{ + note: "", + privacy: "public", + sensitive: "false" + } + } + + assert expected == AccountView.render("account.json", %{user: user}) + end + + test "Represent a Service(bot) account" do + user = + insert(:user, %{ + info: %{"note_count" => 5, "follower_count" => 3, "source_data" => %{"type" => "Service"}}, + nickname: "shp@shitposter.club", + inserted_at: ~N[2017-08-15 15:47:06.597036] + }) + + expected = %{ + id: to_string(user.id), + username: "shp", + acct: user.nickname, + display_name: user.name, + locked: false, + created_at: "2017-08-15T15:47:06.000Z", + followers_count: 3, + following_count: 0, + statuses_count: 5, + note: user.bio, + url: user.ap_id, + avatar: "http://localhost:4001/images/avi.png", + avatar_static: "http://localhost:4001/images/avi.png", + header: "http://localhost:4001/images/banner.png", + header_static: "http://localhost:4001/images/banner.png", + emojis: [], + fields: [], + bot: true, source: %{ note: "", privacy: "public", From a5adb251ab101e7ad1084a772b66b049998c72a5 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Fri, 10 Aug 2018 02:41:01 +0200 Subject: [PATCH 05/16] [Pleroma.Web.MastodonAPI.AccountView]: Add fields support --- lib/pleroma/web/mastodon_api/views/account_view.ex | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index 9dd635a63..634985fb6 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -27,6 +27,11 @@ def render("account.json", %{user: user}) do } end) + fields = + (user.info["source_data"]["attachment"] || []) + |> Enum.filter(fn %{"type" => t} -> t == "PropertyValue" end) + |> Enum.map(fn fields -> Map.take(fields, ["name", "value"]) end) + %{ id: to_string(user.id), username: hd(String.split(user.nickname, "@")), @@ -44,7 +49,7 @@ def render("account.json", %{user: user}) do header: header, header_static: header, emojis: emojis, - fields: [], + fields: fields, bot: bot, source: %{ note: "", From 6e030129fb33926e6a5bd75c27af6f657f9da2a5 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Tue, 14 Aug 2018 04:27:28 +0200 Subject: [PATCH 06/16] [MastodonAPI] Add filters --- lib/pleroma/filter.ex | 62 +++++++++ .../mastodon_api/mastodon_api_controller.ex | 61 ++++++++- .../web/mastodon_api/views/filter_view.ex | 20 +++ lib/pleroma/web/router.ex | 6 + .../20180813003722_create_filters.exs | 20 +++ test/filter_test.exs | 85 +++++++++++++ .../mastodon_api_controller_test.exs | 119 ++++++++++++++++++ 7 files changed, 372 insertions(+), 1 deletion(-) create mode 100644 lib/pleroma/filter.ex create mode 100644 lib/pleroma/web/mastodon_api/views/filter_view.ex create mode 100644 priv/repo/migrations/20180813003722_create_filters.exs create mode 100644 test/filter_test.exs diff --git a/lib/pleroma/filter.ex b/lib/pleroma/filter.ex new file mode 100644 index 000000000..fe904df3a --- /dev/null +++ b/lib/pleroma/filter.ex @@ -0,0 +1,62 @@ +defmodule Pleroma.Filter do + use Ecto.Schema + import Ecto.{Changeset, Query} + alias Pleroma.{User, Repo, Activity} + + schema "filters" do + belongs_to(:user, Pleroma.User) + field(:filter_id, :integer) + field(:hide, :boolean, default: false) + field(:whole_word, :boolean, default: true) + field(:phrase, :string) + field(:context, {:array, :string}) + field(:expires_at, :utc_datetime) + + timestamps() + end + + def get(id, %{id: user_id} = _user) do + query = + from( + f in Pleroma.Filter, + where: f.filter_id == ^id, + where: f.user_id == ^user_id + ) + + Repo.one(query) + end + + def get_filters(%Pleroma.User{id: user_id} = user) do + query = + from( + f in Pleroma.Filter, + where: f.user_id == ^user_id + ) + + Repo.all(query) + end + + def create(%Pleroma.Filter{} = filter) do + Repo.insert(filter) + end + + def delete(%Pleroma.Filter{id: filter_key} = filter) when is_number(filter_key) do + Repo.delete(filter) + end + + def delete(%Pleroma.Filter{id: filter_key} = filter) when is_nil(filter_key) do + %Pleroma.Filter{id: id} = get(filter.filter_id, %{id: filter.user_id}) + + filter + |> Map.put(:id, id) + |> Repo.delete() + end + + def update(%Pleroma.Filter{} = filter) do + destination = Map.from_struct(filter) + + Pleroma.Filter.get(filter.filter_id, %{id: filter.user_id}) + |> cast(destination, [:phrase, :context, :hide, :expires_at, :whole_word]) + |> Repo.update() + end +end diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index f482de6fd..649ee033e 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -2,7 +2,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do use Pleroma.Web, :controller alias Pleroma.{Repo, Object, Activity, User, Notification, Stats} alias Pleroma.Web - alias Pleroma.Web.MastodonAPI.{StatusView, AccountView, MastodonView, ListView} + alias Pleroma.Web.MastodonAPI.{StatusView, AccountView, MastodonView, ListView, FilterView} alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.CommonAPI @@ -1089,6 +1089,65 @@ def render_notification(user, %{id: id, activity: activity, inserted_at: created end end + def get_filters(%{assigns: %{user: user}} = conn, params) do + filters = Pleroma.Filter.get_filters(user) + res = FilterView.render("filters.json", filters: filters) + json(conn, res) + end + + def create_filter( + %{assigns: %{user: user}} = conn, + %{"phrase" => phrase, "context" => context} = params + ) do + query = %Pleroma.Filter{ + user_id: user.id, + phrase: phrase, + context: context, + hide: Map.get(params, "irreversible", nil), + whole_word: Map.get(params, "boolean", true) + # expires_at + } + + {:ok, response} = Pleroma.Filter.create(query) + res = FilterView.render("filter.json", filter: response) + json(conn, res) + end + + def get_filter(%{assigns: %{user: user}} = conn, %{"id" => filter_id} = params) do + filter = Pleroma.Filter.get(filter_id, user) + res = FilterView.render("filter.json", filter: filter) + json(conn, res) + end + + def update_filter( + %{assigns: %{user: user}} = conn, + %{"phrase" => phrase, "context" => context, "id" => filter_id} = params + ) do + query = %Pleroma.Filter{ + user_id: user.id, + filter_id: filter_id, + phrase: phrase, + context: context, + hide: Map.get(params, "irreversible", nil), + whole_word: Map.get(params, "boolean", true) + # expires_at + } + + {:ok, response} = Pleroma.Filter.update(query) + res = FilterView.render("filter.json", filter: response) + json(conn, res) + end + + def delete_filter(%{assigns: %{user: user}} = conn, %{"id" => filter_id} = params) do + query = %Pleroma.Filter{ + user_id: user.id, + filter_id: filter_id + } + + {:ok, response} = Pleroma.Filter.delete(query) + json(conn, %{}) + end + def errors(conn, _) do conn |> put_status(500) diff --git a/lib/pleroma/web/mastodon_api/views/filter_view.ex b/lib/pleroma/web/mastodon_api/views/filter_view.ex new file mode 100644 index 000000000..3f8c62f24 --- /dev/null +++ b/lib/pleroma/web/mastodon_api/views/filter_view.ex @@ -0,0 +1,20 @@ +defmodule Pleroma.Web.MastodonAPI.FilterView do + use Pleroma.Web, :view + alias Pleroma.Web.MastodonAPI.FilterView + alias Pleroma.Web.CommonAPI.Utils + + def render("filters.json", %{filters: filters} = opts) do + render_many(filters, FilterView, "filter.json", opts) + end + + def render("filter.json", %{filter: filter}) do + %{ + id: to_string(filter.filter_id), + phrase: filter.phrase, + context: filter.context, + expires_at: Utils.to_masto_date(filter.expires_at), + irreversible: filter.hide, + whole_word: false + } + end +end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 927323794..b212a2909 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -154,6 +154,12 @@ def user_fetcher(username_or_email) do post("/domain_blocks", MastodonAPIController, :block_domain) delete("/domain_blocks", MastodonAPIController, :unblock_domain) + get("/filters", MastodonAPIController, :get_filters) + post("/filters", MastodonAPIController, :create_filter) + get("/filters/:id", MastodonAPIController, :get_filter) + put("/filters/:id", MastodonAPIController, :update_filter) + delete("/filters/:id", MastodonAPIController, :delete_filter) + get("/suggestions", MastodonAPIController, :suggestions) end diff --git a/priv/repo/migrations/20180813003722_create_filters.exs b/priv/repo/migrations/20180813003722_create_filters.exs new file mode 100644 index 000000000..a273004ee --- /dev/null +++ b/priv/repo/migrations/20180813003722_create_filters.exs @@ -0,0 +1,20 @@ +defmodule Pleroma.Repo.Migrations.CreateFilters do + use Ecto.Migration + + def change do + create table(:filters) do + add :user_id, references(:users, on_delete: :delete_all) + add :filter_id, :integer + add :hide, :boolean + add :phrase, :string + add :context, {:array, :string} + add :expires_at, :datetime + add :whole_word, :boolean + + timestamps() + end + + create index(:filters, [:user_id]) + create index(:filters, [:phrase], where: "hide = true", name: :hided_phrases_index) + end +end diff --git a/test/filter_test.exs b/test/filter_test.exs new file mode 100644 index 000000000..d81c92f08 --- /dev/null +++ b/test/filter_test.exs @@ -0,0 +1,85 @@ +defmodule Pleroma.FilterTest do + alias Pleroma.{User, Repo} + use Pleroma.DataCase + + import Pleroma.Factory + import Ecto.Query + + test "creating a filter" do + user = insert(:user) + + query = %Pleroma.Filter{ + user_id: user.id, + filter_id: 42, + phrase: "knights", + context: ["home"] + } + + {:ok, %Pleroma.Filter{} = filter} = Pleroma.Filter.create(query) + result = Pleroma.Filter.get(filter.filter_id, user) + assert query.phrase == result.phrase + end + + test "deleting a filter" do + user = insert(:user) + + query = %Pleroma.Filter{ + user_id: user.id, + filter_id: 0, + phrase: "knights", + context: ["home"] + } + + {:ok, filter} = Pleroma.Filter.create(query) + {:ok, filter} = Pleroma.Filter.delete(query) + assert is_nil(Repo.get(Pleroma.Filter, filter.filter_id)) + end + + test "getting all filters by an user" do + user = insert(:user) + + query_one = %Pleroma.Filter{ + user_id: user.id, + filter_id: 1, + phrase: "knights", + context: ["home"] + } + + query_two = %Pleroma.Filter{ + user_id: user.id, + filter_id: 2, + phrase: "who", + context: ["home"] + } + + {:ok, filter_one} = Pleroma.Filter.create(query_one) + {:ok, filter_two} = Pleroma.Filter.create(query_two) + filters = Pleroma.Filter.get_filters(user) + assert filter_one in filters + assert filter_two in filters + end + + test "updating a filter" do + user = insert(:user) + + query_one = %Pleroma.Filter{ + user_id: user.id, + filter_id: 1, + phrase: "knights", + context: ["home"] + } + + query_two = %Pleroma.Filter{ + user_id: user.id, + filter_id: 1, + phrase: "who", + context: ["home", "timeline"] + } + + {:ok, filter_one} = Pleroma.Filter.create(query_one) + {:ok, filter_two} = Pleroma.Filter.update(query_two) + assert filter_one != filter_two + assert filter_two.phrase == query_two.phrase + assert filter_two.context == query_two.context + end +end diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs index 9e33c1d04..770776a3b 100644 --- a/test/web/mastodon_api/mastodon_api_controller_test.exs +++ b/test/web/mastodon_api/mastodon_api_controller_test.exs @@ -251,6 +251,125 @@ test "when you didn't create it", %{conn: conn} do end end + describe "filters" do + test "creating a filter", %{conn: conn} do + user = insert(:user) + + filter = %Pleroma.Filter{ + phrase: "knights", + context: ["home"] + } + + conn = + conn + |> assign(:user, user) + |> post("/api/v1/filters", %{"phrase" => filter.phrase, context: filter.context}) + + assert response = json_response(conn, 200) + assert response["phrase"] == filter.phrase + assert response["context"] == filter.context + end + + test "fetching a list of filters", %{conn: conn} do + user = insert(:user) + + query_one = %Pleroma.Filter{ + user_id: user.id, + filter_id: 1, + phrase: "knights", + context: ["home"] + } + + query_two = %Pleroma.Filter{ + user_id: user.id, + filter_id: 2, + phrase: "who", + context: ["home"] + } + + {:ok, filter_one} = Pleroma.Filter.create(query_one) + {:ok, filter_two} = Pleroma.Filter.create(query_two) + + conn = + conn + |> assign(:user, user) + |> get("/api/v1/filters") + + assert response = json_response(conn, 200) + end + + test "get a filter", %{conn: conn} do + user = insert(:user) + + query = %Pleroma.Filter{ + user_id: user.id, + filter_id: 2, + phrase: "knight", + context: ["home"] + } + + {:ok, filter} = Pleroma.Filter.create(query) + + conn = + conn + |> assign(:user, user) + |> get("/api/v1/filters/#{filter.filter_id}") + + assert response = json_response(conn, 200) + end + + test "update a filter", %{conn: conn} do + user = insert(:user) + + query = %Pleroma.Filter{ + user_id: user.id, + filter_id: 2, + phrase: "knight", + context: ["home"] + } + + {:ok, filter} = Pleroma.Filter.create(query) + + new = %Pleroma.Filter{ + phrase: "nii", + context: ["home"] + } + + conn = + conn + |> assign(:user, user) + |> put("/api/v1/filters/#{query.filter_id}", %{ + phrase: new.phrase, + context: new.context + }) + + assert response = json_response(conn, 200) + assert response["phrase"] == new.phrase + assert response["context"] == new.context + end + + test "delete a filter", %{conn: conn} do + user = insert(:user) + + query = %Pleroma.Filter{ + user_id: user.id, + filter_id: 2, + phrase: "knight", + context: ["home"] + } + + {:ok, filter} = Pleroma.Filter.create(query) + + conn = + conn + |> assign(:user, user) + |> delete("/api/v1/filters/#{filter.filter_id}") + + assert response = json_response(conn, 200) + assert response == %{} + end + end + describe "lists" do test "creating a list", %{conn: conn} do user = insert(:user) From d571a571fe969821923ea26c874c7cd77eec5465 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Fri, 10 Aug 2018 04:28:29 +0200 Subject: [PATCH 07/16] [Pleroma.Web.MastodonAPI.MastodonAPIController]: Bump mastodon_api_level to 2.4.3 --- lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 649ee033e..b930b002e 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -124,7 +124,7 @@ def user(conn, %{"id" => id}) do end @instance Application.get_env(:pleroma, :instance) - @mastodon_api_level "2.3.3" + @mastodon_api_level "2.4.3" def masto_instance(conn, _params) do response = %{ From 9bddb39ff097d527ef71860a1d0498dc57f7cd06 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Tue, 21 Aug 2018 19:45:58 +0200 Subject: [PATCH 08/16] [Pleroma.Web.MastodonAPI.FilterView]: expires_at should be null when N/A --- lib/pleroma/web/mastodon_api/views/filter_view.ex | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/mastodon_api/views/filter_view.ex b/lib/pleroma/web/mastodon_api/views/filter_view.ex index 3f8c62f24..e8401cc2d 100644 --- a/lib/pleroma/web/mastodon_api/views/filter_view.ex +++ b/lib/pleroma/web/mastodon_api/views/filter_view.ex @@ -8,11 +8,17 @@ def render("filters.json", %{filters: filters} = opts) do end def render("filter.json", %{filter: filter}) do + if filter.expires_at do + expires_at = Utils.to_masto_date(filter.expires_at) + else + expires_at = nil + end + %{ id: to_string(filter.filter_id), phrase: filter.phrase, context: filter.context, - expires_at: Utils.to_masto_date(filter.expires_at), + expires_at: expires_at, irreversible: filter.hide, whole_word: false } From 6973b77e9462475361772907ddd690a960041b64 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Tue, 21 Aug 2018 20:35:14 +0200 Subject: [PATCH 09/16] [Pleroma.Web.MastodonAPI.FilterView] fix expires_at being a unsafe variable --- lib/pleroma/web/mastodon_api/views/filter_view.ex | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/pleroma/web/mastodon_api/views/filter_view.ex b/lib/pleroma/web/mastodon_api/views/filter_view.ex index e8401cc2d..6bd687d46 100644 --- a/lib/pleroma/web/mastodon_api/views/filter_view.ex +++ b/lib/pleroma/web/mastodon_api/views/filter_view.ex @@ -8,11 +8,12 @@ def render("filters.json", %{filters: filters} = opts) do end def render("filter.json", %{filter: filter}) do - if filter.expires_at do - expires_at = Utils.to_masto_date(filter.expires_at) - else - expires_at = nil - end + expires_at = + if filter.expires_at do + Utils.to_masto_date(filter.expires_at) + else + nil + end %{ id: to_string(filter.filter_id), From 0f1c629d657f569058c36fb0f0c7855a261d5257 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 27 Aug 2018 17:07:26 +0300 Subject: [PATCH 10/16] better solution, added test. --- .../web/twitter_api/views/activity_view.ex | 7 ++--- .../twitter_api/views/activity_view_test.exs | 27 +++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/lib/pleroma/web/twitter_api/views/activity_view.ex b/lib/pleroma/web/twitter_api/views/activity_view.ex index 0efc0df2e..909eefdd8 100644 --- a/lib/pleroma/web/twitter_api/views/activity_view.ex +++ b/lib/pleroma/web/twitter_api/views/activity_view.ex @@ -181,6 +181,7 @@ def render("activity.json", %{activity: %{data: %{"type" => "Announce"}} = activ def render("activity.json", %{activity: %{data: %{"type" => "Like"}} = activity} = opts) do user = get_user(activity.data["actor"], opts) liked_activity = Activity.get_create_activity_by_object_ap_id(activity.data["object"]) + liked_activity_id = if liked_activity, do: liked_activity.id, else: nil created_at = activity.data["published"] @@ -188,7 +189,7 @@ def render("activity.json", %{activity: %{data: %{"type" => "Like"}} = activity} text = "#{user.nickname} favorited a status." - if liked_activity, do: %{ + %{ "id" => activity.id, "user" => UserView.render("show.json", %{user: user, for: opts[:for]}), "statusnet_html" => text, @@ -197,10 +198,10 @@ def render("activity.json", %{activity: %{data: %{"type" => "Like"}} = activity} "is_post_verb" => false, "uri" => "tag:#{activity.data["id"]}:objectType=Favourite", "created_at" => created_at, - "in_reply_to_status_id" => liked_activity.id, + "in_reply_to_status_id" => liked_activity_id, "external_url" => activity.data["id"], "activity_type" => "like" - }, else: %{} + } end def render( diff --git a/test/web/twitter_api/views/activity_view_test.exs b/test/web/twitter_api/views/activity_view_test.exs index a101e4ae8..b9a8efdad 100644 --- a/test/web/twitter_api/views/activity_view_test.exs +++ b/test/web/twitter_api/views/activity_view_test.exs @@ -126,6 +126,33 @@ test "a like activity" do assert result == expected end + test "a like activity for deleted post" do + user = insert(:user) + other_user = insert(:user, %{nickname: "shp"}) + + {:ok, activity} = CommonAPI.post(user, %{"status" => "Hey @shp!"}) + {:ok, like, _object} = CommonAPI.favorite(activity.id, other_user) + CommonAPI.delete(activity.id, user) + + result = ActivityView.render("activity.json", activity: like) + + expected = %{ + "activity_type" => "like", + "created_at" => like.data["published"] |> Utils.date_to_asctime(), + "external_url" => like.data["id"], + "id" => like.id, + "in_reply_to_status_id" => nil, + "is_local" => true, + "is_post_verb" => false, + "statusnet_html" => "shp favorited a status.", + "text" => "shp favorited a status.", + "uri" => "tag:#{like.data["id"]}:objectType=Favourite", + "user" => UserView.render("show.json", user: other_user) + } + + assert result == expected + end + test "an announce activity" do user = insert(:user) other_user = insert(:user, %{nickname: "shp"}) From a9c0f395cb4d854e552a3205cb5b38ff610f8e27 Mon Sep 17 00:00:00 2001 From: Thurloat Date: Fri, 31 Aug 2018 14:28:39 -0300 Subject: [PATCH 11/16] add nil clause for Formatter.get_emoji/1 to return an empty result --- lib/pleroma/formatter.ex | 2 ++ test/formatter_test.exs | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/lib/pleroma/formatter.ex b/lib/pleroma/formatter.ex index cf2944c38..fc2c643da 100644 --- a/lib/pleroma/formatter.ex +++ b/lib/pleroma/formatter.ex @@ -157,6 +157,8 @@ def emojify(text, emoji) do end) end + def get_emoji(nil), do: [] + def get_emoji(text) do Enum.filter(@emoji, fn {emoji, _} -> String.contains?(text, ":#{emoji}:") end) end diff --git a/test/formatter_test.exs b/test/formatter_test.exs index 95558089b..4e27efe06 100644 --- a/test/formatter_test.exs +++ b/test/formatter_test.exs @@ -199,4 +199,14 @@ test "it returns the emoji used in the text" do assert Formatter.get_emoji(text) == [{"moominmamma", "/finmoji/128px/moominmamma-128.png"}] end + + test "it returns a nice empty result when no emojis are present" do + text = "I love moominamma" + assert Formatter.get_emoji(text) == [] + end + + test "it doesn't die when text is absent" do + text = nil + assert Formatter.get_emoji(text) == [] + end end From 4257f784bc8e742888e978fccbab0f566c549376 Mon Sep 17 00:00:00 2001 From: Thurloat Date: Sun, 2 Sep 2018 20:44:37 -0300 Subject: [PATCH 12/16] sloop around get_emoji/1 to check is_binary and have a fallthrough default that returns empty --- lib/pleroma/formatter.ex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/pleroma/formatter.ex b/lib/pleroma/formatter.ex index fc2c643da..e5ccc7a49 100644 --- a/lib/pleroma/formatter.ex +++ b/lib/pleroma/formatter.ex @@ -157,12 +157,12 @@ def emojify(text, emoji) do end) end - def get_emoji(nil), do: [] - - def get_emoji(text) do + def get_emoji(text) when is_binary(text) do Enum.filter(@emoji, fn {emoji, _} -> String.contains?(text, ":#{emoji}:") end) end + def get_emoji(_), do: [] + def get_custom_emoji() do @emoji end From 2b2bd0e047c96085dda003f0ae11ddc05bbc8c12 Mon Sep 17 00:00:00 2001 From: shadowfacts Date: Mon, 3 Sep 2018 01:40:05 +0000 Subject: [PATCH 13/16] Render notification IDs as strings, not numbers --- lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index e0267f1dc..b3c234010 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -1033,7 +1033,7 @@ def render_notification(user, %{id: id, activity: activity, inserted_at: created case activity.data["type"] do "Create" -> %{ - id: id, + id: id |> to_string, type: "mention", created_at: created_at, account: AccountView.render("account.json", %{user: actor}), @@ -1044,7 +1044,7 @@ def render_notification(user, %{id: id, activity: activity, inserted_at: created liked_activity = Activity.get_create_activity_by_object_ap_id(activity.data["object"]) %{ - id: id, + id: id |> to_string, type: "favourite", created_at: created_at, account: AccountView.render("account.json", %{user: actor}), @@ -1055,7 +1055,7 @@ def render_notification(user, %{id: id, activity: activity, inserted_at: created announced_activity = Activity.get_create_activity_by_object_ap_id(activity.data["object"]) %{ - id: id, + id: id |> to_string, type: "reblog", created_at: created_at, account: AccountView.render("account.json", %{user: actor}), @@ -1064,7 +1064,7 @@ def render_notification(user, %{id: id, activity: activity, inserted_at: created "Follow" -> %{ - id: id, + id: id |> to_string, type: "follow", created_at: created_at, account: AccountView.render("account.json", %{user: actor}) From 26f8697400cf9c9fd4d33748bf3aadedbb55d981 Mon Sep 17 00:00:00 2001 From: shadowfacts Date: Mon, 3 Sep 2018 01:52:02 +0000 Subject: [PATCH 14/16] Update mastodon_api_controller.ex --- .../web/mastodon_api/mastodon_api_controller.ex | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index b3c234010..576e9d3ce 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -1029,11 +1029,13 @@ def render_notification(user, %{id: id, activity: activity, inserted_at: created created_at = NaiveDateTime.to_iso8601(created_at) |> String.replace(~r/(\.\d+)?$/, ".000Z", global: false) + + id = id |> to_string case activity.data["type"] do "Create" -> %{ - id: id |> to_string, + id: id, type: "mention", created_at: created_at, account: AccountView.render("account.json", %{user: actor}), @@ -1044,7 +1046,7 @@ def render_notification(user, %{id: id, activity: activity, inserted_at: created liked_activity = Activity.get_create_activity_by_object_ap_id(activity.data["object"]) %{ - id: id |> to_string, + id: id, type: "favourite", created_at: created_at, account: AccountView.render("account.json", %{user: actor}), @@ -1055,7 +1057,7 @@ def render_notification(user, %{id: id, activity: activity, inserted_at: created announced_activity = Activity.get_create_activity_by_object_ap_id(activity.data["object"]) %{ - id: id |> to_string, + id: id, type: "reblog", created_at: created_at, account: AccountView.render("account.json", %{user: actor}), @@ -1064,7 +1066,7 @@ def render_notification(user, %{id: id, activity: activity, inserted_at: created "Follow" -> %{ - id: id |> to_string, + id: id, type: "follow", created_at: created_at, account: AccountView.render("account.json", %{user: actor}) From 35515cfa66f39d618be5702137d296b7bc25b65e Mon Sep 17 00:00:00 2001 From: shadowfacts Date: Mon, 3 Sep 2018 01:58:55 +0000 Subject: [PATCH 15/16] Update mastodon_api_controller.ex --- lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 576e9d3ce..8279db93e 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -1029,7 +1029,7 @@ def render_notification(user, %{id: id, activity: activity, inserted_at: created created_at = NaiveDateTime.to_iso8601(created_at) |> String.replace(~r/(\.\d+)?$/, ".000Z", global: false) - + id = id |> to_string case activity.data["type"] do From b1124f1605717ec841d3693745536e49bdadd8c5 Mon Sep 17 00:00:00 2001 From: Hakaba Hitoyo Date: Mon, 3 Sep 2018 21:13:30 +0900 Subject: [PATCH 16/16] report chat and gopher support at /nodeinfo/2.0.json --- lib/pleroma/web/nodeinfo/nodeinfo_controller.ex | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex index 2fab60274..9155e42cd 100644 --- a/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex +++ b/lib/pleroma/web/nodeinfo/nodeinfo_controller.ex @@ -22,6 +22,8 @@ def nodeinfo(conn, %{"version" => "2.0"}) do instance = Application.get_env(:pleroma, :instance) media_proxy = Application.get_env(:pleroma, :media_proxy) suggestions = Application.get_env(:pleroma, :suggestions) + chat = Application.get_env(:pleroma, :chat) + gopher = Application.get_env(:pleroma, :gopher) stats = Stats.get_stats() response = %{ @@ -52,7 +54,9 @@ def nodeinfo(conn, %{"version" => "2.0"}) do thirdPartyEngine: Keyword.get(suggestions, :third_party_engine, ""), timeout: Keyword.get(suggestions, :timeout, 5000), web: Keyword.get(suggestions, :web, "") - } + }, + chat: Keyword.get(chat, :enabled), + gopher: Keyword.get(gopher, :enabled) } }