diff --git a/CHANGELOG.md b/CHANGELOG.md
index 81265a7a6..25f79167d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - **Breaking:** Emoji API: changed methods and renamed routes.
 - Streaming: Repeats of a user's posts will no longer be pushed to the user's stream.
 - Mastodon API: Added `pleroma.metadata.fields_limits` to /api/v1/instance
+- Mastodon API: On deletion, returns the original post text.
 </details>
 
 <details>
diff --git a/lib/pleroma/config/loader.ex b/lib/pleroma/config/loader.ex
index 0f3ecf1ed..64e7de6df 100644
--- a/lib/pleroma/config/loader.ex
+++ b/lib/pleroma/config/loader.ex
@@ -12,6 +12,11 @@ defmodule Pleroma.Config.Loader do
     :swarm
   ]
 
+  @reject_groups [
+    :postgrex,
+    :tesla
+  ]
+
   if Code.ensure_loaded?(Config.Reader) do
     @reader Config.Reader
 
@@ -47,7 +52,8 @@ defp filter(configs) do
   @spec filter_group(atom(), keyword()) :: keyword()
   def filter_group(group, configs) do
     Enum.reject(configs[group], fn {key, _v} ->
-      key in @reject_keys or (group == :phoenix and key == :serve_endpoints) or group == :postgrex
+      key in @reject_keys or group in @reject_groups or
+        (group == :phoenix and key == :serve_endpoints)
     end)
   end
 end
diff --git a/lib/pleroma/migration_helper/notification_backfill.ex b/lib/pleroma/migration_helper/notification_backfill.ex
index b3770307a..d260e62ca 100644
--- a/lib/pleroma/migration_helper/notification_backfill.ex
+++ b/lib/pleroma/migration_helper/notification_backfill.ex
@@ -3,7 +3,6 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.MigrationHelper.NotificationBackfill do
-  alias Pleroma.Notification
   alias Pleroma.Object
   alias Pleroma.Repo
   alias Pleroma.User
@@ -25,18 +24,27 @@ def fill_in_notification_types do
         |> type_from_activity()
 
       notification
-      |> Notification.changeset(%{type: type})
+      |> Ecto.Changeset.change(%{type: type})
       |> Repo.update()
     end)
   end
 
+  defp get_by_ap_id(ap_id) do
+    q =
+      from(u in User,
+        select: u.id
+      )
+
+    Repo.get_by(q, ap_id: ap_id)
+  end
+
   # This is copied over from Notifications to keep this stable.
   defp type_from_activity(%{data: %{"type" => type}} = activity) do
     case type do
       "Follow" ->
         accepted_function = fn activity ->
-          with %User{} = follower <- User.get_by_ap_id(activity.data["actor"]),
-               %User{} = followed <- User.get_by_ap_id(activity.data["object"]) do
+          with %User{} = follower <- get_by_ap_id(activity.data["actor"]),
+               %User{} = followed <- get_by_ap_id(activity.data["object"]) do
             Pleroma.FollowingRelationship.following?(follower, followed)
           end
         end
diff --git a/lib/pleroma/user/search.ex b/lib/pleroma/user/search.ex
index cec59c372..42ff1de78 100644
--- a/lib/pleroma/user/search.ex
+++ b/lib/pleroma/user/search.ex
@@ -52,6 +52,7 @@ defp search_query(query_string, for_user, following) do
     |> base_query(following)
     |> filter_blocked_user(for_user)
     |> filter_invisible_users()
+    |> filter_internal_users()
     |> filter_blocked_domains(for_user)
     |> fts_search(query_string)
     |> trigram_rank(query_string)
@@ -109,6 +110,10 @@ defp filter_invisible_users(query) do
     from(q in query, where: q.invisible == false)
   end
 
+  defp filter_internal_users(query) do
+    from(q in query, where: q.actor_type != "Application")
+  end
+
   defp filter_blocked_user(query, %User{} = blocker) do
     query
     |> join(:left, [u], b in Pleroma.UserRelationship,
diff --git a/lib/pleroma/web/api_spec/operations/status_operation.ex b/lib/pleroma/web/api_spec/operations/status_operation.ex
index 0b7fad793..5bd4619d5 100644
--- a/lib/pleroma/web/api_spec/operations/status_operation.ex
+++ b/lib/pleroma/web/api_spec/operations/status_operation.ex
@@ -84,7 +84,7 @@ def delete_operation do
       operationId: "StatusController.delete",
       parameters: [id_param()],
       responses: %{
-        200 => empty_object_response(),
+        200 => status_response(),
         403 => Operation.response("Forbidden", "application/json", ApiError),
         404 => Operation.response("Not Found", "application/json", ApiError)
       }
diff --git a/lib/pleroma/web/api_spec/schemas/status.ex b/lib/pleroma/web/api_spec/schemas/status.ex
index 28cde963e..947e42890 100644
--- a/lib/pleroma/web/api_spec/schemas/status.ex
+++ b/lib/pleroma/web/api_spec/schemas/status.ex
@@ -62,6 +62,11 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Status do
         }
       },
       content: %Schema{type: :string, format: :html, description: "HTML-encoded status content"},
+      text: %Schema{
+        type: :string,
+        description: "Original unformatted content in plain text",
+        nullable: true
+      },
       created_at: %Schema{
         type: :string,
         format: "date-time",
diff --git a/lib/pleroma/web/common_api/activity_draft.ex b/lib/pleroma/web/common_api/activity_draft.ex
index 9bcb9f587..f849b2e01 100644
--- a/lib/pleroma/web/common_api/activity_draft.ex
+++ b/lib/pleroma/web/common_api/activity_draft.ex
@@ -186,6 +186,7 @@ defp object(draft) do
         draft.poll
       )
       |> Map.put("emoji", emoji)
+      |> Map.put("source", draft.status)
 
     %__MODULE__{draft | object: object}
   end
diff --git a/lib/pleroma/web/mastodon_api/controllers/search_controller.ex b/lib/pleroma/web/mastodon_api/controllers/search_controller.ex
index e50980122..29affa7d5 100644
--- a/lib/pleroma/web/mastodon_api/controllers/search_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/search_controller.ex
@@ -44,6 +44,7 @@ def search2(conn, params), do: do_search(:v2, conn, params)
   def search(conn, params), do: do_search(:v1, conn, params)
 
   defp do_search(version, %{assigns: %{user: user}} = conn, %{q: query} = params) do
+    query = String.trim(query)
     options = search_options(params, user)
     timeout = Keyword.get(Repo.config(), :timeout, 15_000)
     default_values = %{"statuses" => [], "accounts" => [], "hashtags" => []}
diff --git a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex
index 468b44b67..3f4c53437 100644
--- a/lib/pleroma/web/mastodon_api/controllers/status_controller.ex
+++ b/lib/pleroma/web/mastodon_api/controllers/status_controller.ex
@@ -200,11 +200,18 @@ def show(%{assigns: %{user: user}} = conn, %{id: id}) do
 
   @doc "DELETE /api/v1/statuses/:id"
   def delete(%{assigns: %{user: user}} = conn, %{id: id}) do
-    with {:ok, %Activity{}} <- CommonAPI.delete(id, user) do
-      json(conn, %{})
+    with %Activity{} = activity <- Activity.get_by_id_with_object(id),
+         render <-
+           try_render(conn, "show.json",
+             activity: activity,
+             for: user,
+             with_direct_conversation_id: true,
+             with_source: true
+           ),
+         {:ok, %Activity{}} <- CommonAPI.delete(id, user) do
+      render
     else
-      {:error, :not_found} = e -> e
-      _e -> render_error(conn, :forbidden, "Can't delete this post")
+      _e -> {:error, :not_found}
     end
   end
 
diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex
index 6ee17f4dd..fa9d695f3 100644
--- a/lib/pleroma/web/mastodon_api/views/status_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/status_view.ex
@@ -333,6 +333,7 @@ def render("show.json", %{activity: %{data: %{"object" => _object}} = activity}
       reblog: nil,
       card: card,
       content: content_html,
+      text: opts[:with_source] && object.data["source"],
       created_at: created_at,
       reblogs_count: announcement_count,
       replies_count: object.data["repliesCount"] || 0,
diff --git a/lib/pleroma/web/streamer/streamer.ex b/lib/pleroma/web/streamer/streamer.ex
index 73ee3e1e1..d1d70e556 100644
--- a/lib/pleroma/web/streamer/streamer.ex
+++ b/lib/pleroma/web/streamer/streamer.ex
@@ -104,7 +104,9 @@ def stream(topics, items) do
     :ok
   end
 
-  def filtered_by_user?(%User{} = user, %Activity{} = item) do
+  def filtered_by_user?(user, item, streamed_type \\ :activity)
+
+  def filtered_by_user?(%User{} = user, %Activity{} = item, streamed_type) do
     %{block: blocked_ap_ids, mute: muted_ap_ids, reblog_mute: reblog_muted_ap_ids} =
       User.outgoing_relationships_ap_ids(user, [:block, :mute, :reblog_mute])
 
@@ -116,7 +118,9 @@ def filtered_by_user?(%User{} = user, %Activity{} = item) do
          true <-
            Enum.all?([blocked_ap_ids, muted_ap_ids], &(item.actor not in &1)),
          true <- item.data["type"] != "Announce" || item.actor not in reblog_muted_ap_ids,
-         true <- !(item.data["type"] == "Announce" && parent.data["actor"] == user.ap_id),
+         true <-
+           !(streamed_type == :activity && item.data["type"] == "Announce" &&
+               parent.data["actor"] == user.ap_id),
          true <- Enum.all?([blocked_ap_ids, muted_ap_ids], &(parent.data["actor"] not in &1)),
          true <- MapSet.disjoint?(recipients, recipient_blocks),
          %{host: item_host} <- URI.parse(item.actor),
@@ -131,8 +135,8 @@ def filtered_by_user?(%User{} = user, %Activity{} = item) do
     end
   end
 
-  def filtered_by_user?(%User{} = user, %Notification{activity: activity}) do
-    filtered_by_user?(user, activity)
+  def filtered_by_user?(%User{} = user, %Notification{activity: activity}, _) do
+    filtered_by_user?(user, activity, :notification)
   end
 
   defp do_stream("direct", item) do
diff --git a/priv/repo/migrations/20200706060258_remove_tesla_from_config.exs b/priv/repo/migrations/20200706060258_remove_tesla_from_config.exs
new file mode 100644
index 000000000..798687f8a
--- /dev/null
+++ b/priv/repo/migrations/20200706060258_remove_tesla_from_config.exs
@@ -0,0 +1,10 @@
+defmodule Pleroma.Repo.Migrations.RemoveTeslaFromConfig do
+  use Ecto.Migration
+
+  def up do
+    execute("DELETE FROM config WHERE config.group = ':tesla'")
+  end
+
+  def down do
+  end
+end
diff --git a/test/config/holder_test.exs b/test/config/holder_test.exs
index 15d48b5c7..abcaa27dd 100644
--- a/test/config/holder_test.exs
+++ b/test/config/holder_test.exs
@@ -10,7 +10,6 @@ defmodule Pleroma.Config.HolderTest do
   test "default_config/0" do
     config = Holder.default_config()
     assert config[:pleroma][Pleroma.Uploaders.Local][:uploads] == "test/uploads"
-    assert config[:tesla][:adapter] == Tesla.Mock
 
     refute config[:pleroma][Pleroma.Repo]
     refute config[:pleroma][Pleroma.Web.Endpoint]
@@ -18,17 +17,15 @@ test "default_config/0" do
     refute config[:pleroma][:configurable_from_database]
     refute config[:pleroma][:database]
     refute config[:phoenix][:serve_endpoints]
+    refute config[:tesla][:adapter]
   end
 
   test "default_config/1" do
     pleroma_config = Holder.default_config(:pleroma)
     assert pleroma_config[Pleroma.Uploaders.Local][:uploads] == "test/uploads"
-    tesla_config = Holder.default_config(:tesla)
-    assert tesla_config[:adapter] == Tesla.Mock
   end
 
   test "default_config/2" do
     assert Holder.default_config(:pleroma, Pleroma.Uploaders.Local) == [uploads: "test/uploads"]
-    assert Holder.default_config(:tesla, :adapter) == Tesla.Mock
   end
 end
diff --git a/test/support/factory.ex b/test/support/factory.ex
index 6e22b66a4..af580021c 100644
--- a/test/support/factory.ex
+++ b/test/support/factory.ex
@@ -67,6 +67,7 @@ def note_factory(attrs \\ %{}) do
     data = %{
       "type" => "Note",
       "content" => text,
+      "source" => text,
       "id" => Pleroma.Web.ActivityPub.Utils.generate_object_id(),
       "actor" => user.ap_id,
       "to" => ["https://www.w3.org/ns/activitystreams#Public"],
diff --git a/test/user_search_test.exs b/test/user_search_test.exs
index 17c63322a..f030523d3 100644
--- a/test/user_search_test.exs
+++ b/test/user_search_test.exs
@@ -17,7 +17,7 @@ defmodule Pleroma.UserSearchTest do
   describe "User.search" do
     setup do: clear_config([:instance, :limit_to_local_content])
 
-    test "excluded invisible users from results" do
+    test "excludes invisible users from results" do
       user = insert(:user, %{nickname: "john t1000"})
       insert(:user, %{invisible: true, nickname: "john t800"})
 
@@ -25,6 +25,15 @@ test "excluded invisible users from results" do
       assert found_user.id == user.id
     end
 
+    test "excludes service actors from results" do
+      insert(:user, actor_type: "Application", nickname: "user1")
+      service = insert(:user, actor_type: "Service", nickname: "user2")
+      person = insert(:user, actor_type: "Person", nickname: "user3")
+
+      assert [found_user1, found_user2] = User.search("user")
+      assert [found_user1.id, found_user2.id] -- [service.id, person.id] == []
+    end
+
     test "accepts limit parameter" do
       Enum.each(0..4, &insert(:user, %{nickname: "john#{&1}"}))
       assert length(User.search("john", limit: 3)) == 3
diff --git a/test/web/common_api/common_api_test.exs b/test/web/common_api/common_api_test.exs
index fc3bb845d..908ee5484 100644
--- a/test/web/common_api/common_api_test.exs
+++ b/test/web/common_api/common_api_test.exs
@@ -491,6 +491,7 @@ test "it filters out obviously bad tags when accepting a post as HTML" do
       object = Object.normalize(activity)
 
       assert object.data["content"] == "<p><b>2hu</b></p>alert(&#39;xss&#39;)"
+      assert object.data["source"] == post
     end
 
     test "it filters out obviously bad tags when accepting a post as Markdown" do
@@ -507,6 +508,7 @@ test "it filters out obviously bad tags when accepting a post as Markdown" do
       object = Object.normalize(activity)
 
       assert object.data["content"] == "<p><b>2hu</b></p>alert(&#39;xss&#39;)"
+      assert object.data["source"] == post
     end
 
     test "it does not allow replies to direct messages that are not direct messages themselves" do
diff --git a/test/web/mastodon_api/controllers/search_controller_test.exs b/test/web/mastodon_api/controllers/search_controller_test.exs
index 826f37fbc..24d1959f8 100644
--- a/test/web/mastodon_api/controllers/search_controller_test.exs
+++ b/test/web/mastodon_api/controllers/search_controller_test.exs
@@ -79,6 +79,7 @@ test "search", %{conn: conn} do
       assert status["id"] == to_string(activity.id)
     end
 
+    @tag capture_log: true
     test "constructs hashtags from search query", %{conn: conn} do
       results =
         conn
@@ -318,11 +319,13 @@ test "search doesn't show statuses that it shouldn't", %{conn: conn} do
     test "search fetches remote accounts", %{conn: conn} do
       user = insert(:user)
 
+      query = URI.encode_query(%{q: "       mike@osada.macgirvin.com          ", resolve: true})
+
       results =
         conn
         |> assign(:user, user)
         |> assign(:token, insert(:oauth_token, user: user, scopes: ["read"]))
-        |> get("/api/v1/search?q=mike@osada.macgirvin.com&resolve=true")
+        |> get("/api/v1/search?#{query}")
         |> json_response_and_validate_schema(200)
 
       [account] = results["accounts"]
diff --git a/test/web/mastodon_api/controllers/status_controller_test.exs b/test/web/mastodon_api/controllers/status_controller_test.exs
index a98e939e8..fd2de8d80 100644
--- a/test/web/mastodon_api/controllers/status_controller_test.exs
+++ b/test/web/mastodon_api/controllers/status_controller_test.exs
@@ -760,13 +760,18 @@ test "if user is authenticated", %{local: local, remote: remote} do
     test "when you created it" do
       %{user: author, conn: conn} = oauth_access(["write:statuses"])
       activity = insert(:note_activity, user: author)
+      object = Object.normalize(activity)
 
-      conn =
+      content = object.data["content"]
+      source = object.data["source"]
+
+      result =
         conn
         |> assign(:user, author)
         |> delete("/api/v1/statuses/#{activity.id}")
+        |> json_response_and_validate_schema(200)
 
-      assert %{} = json_response_and_validate_schema(conn, 200)
+      assert match?(%{"content" => ^content, "text" => ^source}, result)
 
       refute Activity.get_by_id(activity.id)
     end
@@ -789,7 +794,7 @@ test "when you didn't create it" do
 
       conn = delete(conn, "/api/v1/statuses/#{activity.id}")
 
-      assert %{"error" => _} = json_response_and_validate_schema(conn, 403)
+      assert %{"error" => "Record not found"} == json_response_and_validate_schema(conn, 404)
 
       assert Activity.get_by_id(activity.id) == activity
     end
diff --git a/test/web/mastodon_api/views/status_view_test.exs b/test/web/mastodon_api/views/status_view_test.exs
index f90a0c273..fa26b3129 100644
--- a/test/web/mastodon_api/views/status_view_test.exs
+++ b/test/web/mastodon_api/views/status_view_test.exs
@@ -183,6 +183,7 @@ test "a note activity" do
       card: nil,
       reblog: nil,
       content: HTML.filter_tags(object_data["content"]),
+      text: nil,
       created_at: created_at,
       reblogs_count: 0,
       replies_count: 0,
diff --git a/test/web/streamer/streamer_test.exs b/test/web/streamer/streamer_test.exs
index dfe341b34..d56d74464 100644
--- a/test/web/streamer/streamer_test.exs
+++ b/test/web/streamer/streamer_test.exs
@@ -128,6 +128,23 @@ test "it does not stream announces of the user's own posts in the 'user' stream"
       assert Streamer.filtered_by_user?(user, announce)
     end
 
+    test "it does stream notifications announces of the user's own posts in the 'user' stream", %{
+      user: user
+    } do
+      Streamer.get_topic_and_add_socket("user", user)
+
+      other_user = insert(:user)
+      {:ok, activity} = CommonAPI.post(user, %{status: "hey"})
+      {:ok, announce} = CommonAPI.repeat(activity.id, other_user)
+
+      notification =
+        Pleroma.Notification
+        |> Repo.get_by(%{user_id: user.id, activity_id: announce.id})
+        |> Repo.preload(:activity)
+
+      refute Streamer.filtered_by_user?(user, notification)
+    end
+
     test "it streams boosts of mastodon user in the 'user' stream", %{user: user} do
       Streamer.get_topic_and_add_socket("user", user)