Merge remote-tracking branch 'upstream/develop' into patch-image-description
authorWim Vanderbauwhede <wim.vanderbauwhede@mail.be>
Thu, 14 Feb 2019 16:41:40 +0000 (16:41 +0000)
committerWim Vanderbauwhede <wim.vanderbauwhede@mail.be>
Thu, 14 Feb 2019 16:41:40 +0000 (16:41 +0000)
1  2 
lib/pleroma/web/common_api/common_api.ex
lib/pleroma/web/common_api/utils.ex

index ef79b9c5d4a038f4a4797dffbf03b862d4b0a98a,86f249c54fb0fe620f2d48d8f25b414b7ba02477..90b208e540107bb19e5e5a0ccd757d418cc45aa0
@@@ -3,7 -3,11 +3,11 @@@
  # SPDX-License-Identifier: AGPL-3.0-only
  
  defmodule Pleroma.Web.CommonAPI do
-   alias Pleroma.{User, Repo, Activity, Object}
+   alias Pleroma.User
+   alias Pleroma.Repo
+   alias Pleroma.Activity
+   alias Pleroma.Object
+   alias Pleroma.ThreadMute
    alias Pleroma.Web.ActivityPub.ActivityPub
    alias Pleroma.Web.ActivityPub.Utils
    alias Pleroma.Formatter
@@@ -14,6 -18,7 +18,7 @@@
      with %Activity{data: %{"object" => %{"id" => object_id}}} <- Repo.get(Activity, activity_id),
           %Object{} = object <- Object.normalize(object_id),
           true <- user.info.is_moderator || user.ap_id == object.data["actor"],
+          {:ok, _} <- unpin(activity_id, user),
           {:ok, delete} <- ActivityPub.delete(object) do
        {:ok, delete}
      end
@@@ -90,7 -95,7 +95,7 @@@
      limit = Pleroma.Config.get([:instance, :limit])
  
      with status <- String.trim(status),
 -         attachments <- attachments_from_ids(data["media_ids"]),
 +         attachments <- attachments_from_ids(data),
           mentions <- Formatter.parse_mentions(status),
           inReplyTo <- get_replied_to_activity(data["in_reply_to_status_id"]),
           {to, cc} <- to_for_user_and_mentions(user, mentions, inReplyTo, visibility),
               attachments,
               tags,
               get_content_type(data["content_type"]),
-              Enum.member?([true, "true"], data["no_attachment_links"])
+              Enum.member?(
+                [true, "true"],
+                Map.get(
+                  data,
+                  "no_attachment_links",
+                  Pleroma.Config.get([:instance, :no_attachment_links], false)
+                )
+              )
             ),
           context <- make_context(inReplyTo),
           cw <- data["spoiler_text"],
             Map.put(
               object,
               "emoji",
-              Formatter.get_emoji(status)
+              (Formatter.get_emoji(status) ++ Formatter.get_emoji(data["spoiler_text"]))
               |> Enum.reduce(%{}, fn {name, file}, acc ->
                 Map.put(acc, name, "#{Pleroma.Web.Endpoint.static_url()}#{file}")
               end)
            actor: user,
            context: context,
            object: object,
-           additional: %{"cc" => cc}
+           additional: %{"cc" => cc, "directMessage" => visibility == "direct"}
          })
  
        res
        object: Pleroma.Web.ActivityPub.UserView.render("user.json", %{user: user})
      })
    end
+   def pin(id_or_ap_id, %{ap_id: user_ap_id} = user) do
+     with %Activity{
+            actor: ^user_ap_id,
+            data: %{
+              "type" => "Create",
+              "object" => %{
+                "to" => object_to,
+                "type" => "Note"
+              }
+            }
+          } = activity <- get_by_id_or_ap_id(id_or_ap_id),
+          true <- Enum.member?(object_to, "https://www.w3.org/ns/activitystreams#Public"),
+          %{valid?: true} = info_changeset <-
+            Pleroma.User.Info.add_pinnned_activity(user.info, activity),
+          changeset <-
+            Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_changeset),
+          {:ok, _user} <- User.update_and_set_cache(changeset) do
+       {:ok, activity}
+     else
+       %{errors: [pinned_activities: {err, _}]} ->
+         {:error, err}
+       _ ->
+         {:error, "Could not pin"}
+     end
+   end
+   def unpin(id_or_ap_id, user) do
+     with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id),
+          %{valid?: true} = info_changeset <-
+            Pleroma.User.Info.remove_pinnned_activity(user.info, activity),
+          changeset <-
+            Ecto.Changeset.change(user) |> Ecto.Changeset.put_embed(:info, info_changeset),
+          {:ok, _user} <- User.update_and_set_cache(changeset) do
+       {:ok, activity}
+     else
+       %{errors: [pinned_activities: {err, _}]} ->
+         {:error, err}
+       _ ->
+         {:error, "Could not unpin"}
+     end
+   end
+   def add_mute(user, activity) do
+     with {:ok, _} <- ThreadMute.add_mute(user.id, activity.data["context"]) do
+       {:ok, activity}
+     else
+       {:error, _} -> {:error, "conversation is already muted"}
+     end
+   end
+   def remove_mute(user, activity) do
+     ThreadMute.remove_mute(user.id, activity.data["context"])
+     {:ok, activity}
+   end
+   def thread_muted?(%{id: nil} = _user, _activity), do: false
+   def thread_muted?(user, activity) do
+     with [] <- ThreadMute.check_muted(user.id, activity.data["context"]) do
+       false
+     else
+       _ -> true
+     end
+   end
  end
index 59df48ed638598efa25bf1194925c7b4df10d4ee,123107b56441a216c8589f29dcd10ce3978d855f..abdeee947516214e472e2daa70361c2789d7131d
@@@ -5,22 -5,25 +5,25 @@@
  defmodule Pleroma.Web.CommonAPI.Utils do
    alias Calendar.Strftime
    alias Comeonin.Pbkdf2
-   alias Pleroma.{Activity, Formatter, Object, Repo}
+   alias Pleroma.Activity
+   alias Pleroma.Formatter
+   alias Pleroma.Object
+   alias Pleroma.Repo
    alias Pleroma.User
    alias Pleroma.Web
-   alias Pleroma.Web.ActivityPub.Utils
    alias Pleroma.Web.Endpoint
    alias Pleroma.Web.MediaProxy
+   alias Pleroma.Web.ActivityPub.Utils
  
    # This is a hack for twidere.
    def get_by_id_or_ap_id(id) do
-     activity = Repo.get(Activity, id) || Activity.get_create_activity_by_object_ap_id(id)
+     activity = Repo.get(Activity, id) || Activity.get_create_by_object_ap_id(id)
  
      activity &&
        if activity.data["type"] == "Create" do
          activity
        else
-         Activity.get_create_activity_by_object_ap_id(activity.data["object"])
+         Activity.get_create_by_object_ap_id(activity.data["object"])
        end
    end
  
  
    def get_replied_to_activity(_), do: nil
  
 -  def attachments_from_ids(ids) do
 +  def attachments_from_ids(data) do
 +    if Map.has_key?(data, "descriptions") do
 +      attachments_from_ids_descs(data["media_ids"], data["descriptions"])
 +    else
 +      attachments_from_ids_no_descs(data["media_ids"])
 +    end
 +  end
 +
 +  def attachments_from_ids_no_descs(ids) do
      Enum.map(ids || [], fn media_id ->
        Repo.get(Object, media_id).data
      end)
    end
  
 +  def attachments_from_ids_descs(ids, descs_str) do
 +    {_, descs} = Jason.decode(descs_str)
 +
 +    Enum.map(ids || [], fn media_id ->
 +      Map.put(Repo.get(Object, media_id).data, "name", descs[media_id])
 +    end)
 +  end
 +
    def to_for_user_and_mentions(user, mentions, inReplyTo, "public") do
      mentioned_users = Enum.map(mentions, fn {_, %{ap_id: ap_id}} -> ap_id end)
  
    def make_context(%Activity{data: %{"context" => context}}), do: context
    def make_context(_), do: Utils.generate_context_id()
  
-   def maybe_add_attachments(text, _attachments, _no_links = true), do: text
+   def maybe_add_attachments(text, _attachments, true = _no_links), do: text
  
    def maybe_add_attachments(text, attachments, _no_links) do
      add_attachments(text, attachments)
      Enum.join([text | attachment_text], "<br>")
    end
  
+   def format_input(text, mentions, tags, format, options \\ [])
    @doc """
    Formatting text to plain text.
    """
-   def format_input(text, mentions, tags, "text/plain") do
+   def format_input(text, mentions, tags, "text/plain", options) do
      text
      |> Formatter.html_escape("text/plain")
      |> String.replace(~r/\r?\n/, "<br>")
      |> (&{[], &1}).()
      |> Formatter.add_links()
-     |> Formatter.add_user_links(mentions)
+     |> Formatter.add_user_links(mentions, options[:user_links] || [])
      |> Formatter.add_hashtag_links(tags)
      |> Formatter.finalize()
    end
    @doc """
    Formatting text to html.
    """
-   def format_input(text, mentions, _tags, "text/html") do
+   def format_input(text, mentions, _tags, "text/html", options) do
      text
      |> Formatter.html_escape("text/html")
-     |> String.replace(~r/\r?\n/, "<br>")
      |> (&{[], &1}).()
-     |> Formatter.add_user_links(mentions)
+     |> Formatter.add_user_links(mentions, options[:user_links] || [])
      |> Formatter.finalize()
    end
  
    @doc """
    Formatting text to markdown.
    """
-   def format_input(text, mentions, tags, "text/markdown") do
+   def format_input(text, mentions, tags, "text/markdown", options) do
      text
      |> Formatter.mentions_escape(mentions)
      |> Earmark.as_html!()
      |> Formatter.html_escape("text/html")
-     |> String.replace(~r/\r?\n/, "")
      |> (&{[], &1}).()
-     |> Formatter.add_user_links(mentions)
+     |> Formatter.add_user_links(mentions, options[:user_links] || [])
      |> Formatter.add_hashtag_links(tags)
      |> Formatter.finalize()
    end
        }
      end)
    end
+   def maybe_notify_to_recipients(
+         recipients,
+         %Activity{data: %{"to" => to, "type" => _type}} = _activity
+       ) do
+     recipients ++ to
+   end
+   def maybe_notify_mentioned_recipients(
+         recipients,
+         %Activity{data: %{"to" => _to, "type" => type} = data} = _activity
+       )
+       when type == "Create" do
+     object = Object.normalize(data["object"])
+     object_data =
+       cond do
+         !is_nil(object) ->
+           object.data
+         is_map(data["object"]) ->
+           data["object"]
+         true ->
+           %{}
+       end
+     tagged_mentions = maybe_extract_mentions(object_data)
+     recipients ++ tagged_mentions
+   end
+   def maybe_notify_mentioned_recipients(recipients, _), do: recipients
+   def maybe_extract_mentions(%{"tag" => tag}) do
+     tag
+     |> Enum.filter(fn x -> is_map(x) end)
+     |> Enum.filter(fn x -> x["type"] == "Mention" end)
+     |> Enum.map(fn x -> x["href"] end)
+   end
+   def maybe_extract_mentions(_), do: []
  end