forked from AkkomaGang/akkoma
Merge remote-tracking branch 'upstream/develop' into feature/filter_exif
This commit is contained in:
commit
5469fb9561
27 changed files with 172 additions and 78 deletions
|
@ -14,6 +14,8 @@
|
||||||
uploads: "uploads",
|
uploads: "uploads",
|
||||||
strip_exif: false
|
strip_exif: false
|
||||||
|
|
||||||
|
config :pleroma, :emoji, shortcode_globs: ["/emoji/custom/**/*.png"]
|
||||||
|
|
||||||
# Configures the endpoint
|
# Configures the endpoint
|
||||||
config :pleroma, Pleroma.Web.Endpoint,
|
config :pleroma, Pleroma.Web.Endpoint,
|
||||||
url: [host: "localhost"],
|
url: [host: "localhost"],
|
||||||
|
|
|
@ -78,4 +78,8 @@ def get_create_activity_by_object_ap_id(ap_id) when is_binary(ap_id) do
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_create_activity_by_object_ap_id(_), do: nil
|
def get_create_activity_by_object_ap_id(_), do: nil
|
||||||
|
|
||||||
|
def normalize(obj) when is_map(obj), do: Activity.get_by_ap_id(obj["id"])
|
||||||
|
def normalize(ap_id) when is_binary(ap_id), do: Activity.get_by_ap_id(ap_id)
|
||||||
|
def normalize(_), do: nil
|
||||||
end
|
end
|
||||||
|
|
|
@ -116,7 +116,28 @@ def parse_mentions(text) do
|
||||||
_ -> []
|
_ -> []
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@emoji @finmoji_with_filenames ++ @emoji_from_file
|
@emoji_from_globs (
|
||||||
|
static_path = Path.join(:code.priv_dir(:pleroma), "static")
|
||||||
|
|
||||||
|
globs =
|
||||||
|
Application.get_env(:pleroma, :emoji, [])
|
||||||
|
|> Keyword.get(:shortcode_globs, [])
|
||||||
|
|
||||||
|
paths =
|
||||||
|
Enum.map(globs, fn glob ->
|
||||||
|
Path.join(static_path, glob)
|
||||||
|
|> Path.wildcard()
|
||||||
|
end)
|
||||||
|
|> Enum.concat()
|
||||||
|
|
||||||
|
Enum.map(paths, fn path ->
|
||||||
|
shortcode = Path.basename(path, Path.extname(path))
|
||||||
|
external_path = Path.join("/", Path.relative_to(path, static_path))
|
||||||
|
{shortcode, external_path}
|
||||||
|
end)
|
||||||
|
)
|
||||||
|
|
||||||
|
@emoji @finmoji_with_filenames ++ @emoji_from_globs ++ @emoji_from_file
|
||||||
|
|
||||||
def emojify(text, emoji \\ @emoji)
|
def emojify(text, emoji \\ @emoji)
|
||||||
def emojify(text, nil), do: text
|
def emojify(text, nil), do: text
|
||||||
|
|
|
@ -27,6 +27,10 @@ def get_by_ap_id(ap_id) do
|
||||||
Repo.one(from(object in Object, where: fragment("(?)->>'id' = ?", object.data, ^ap_id)))
|
Repo.one(from(object in Object, where: fragment("(?)->>'id' = ?", object.data, ^ap_id)))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def normalize(obj) when is_map(obj), do: Object.get_by_ap_id(obj["id"])
|
||||||
|
def normalize(ap_id) when is_binary(ap_id), do: Object.get_by_ap_id(ap_id)
|
||||||
|
def normalize(_), do: nil
|
||||||
|
|
||||||
def get_cached_by_ap_id(ap_id) do
|
def get_cached_by_ap_id(ap_id) do
|
||||||
if Mix.env() == :test do
|
if Mix.env() == :test do
|
||||||
get_by_ap_id(ap_id)
|
get_by_ap_id(ap_id)
|
||||||
|
|
|
@ -607,7 +607,7 @@ def delete(%User{} = user) do
|
||||||
|> Enum.each(fn activity ->
|
|> Enum.each(fn activity ->
|
||||||
case activity.data["type"] do
|
case activity.data["type"] do
|
||||||
"Create" ->
|
"Create" ->
|
||||||
ActivityPub.delete(Object.get_by_ap_id(activity.data["object"]["id"]))
|
ActivityPub.delete(Object.normalize(activity.data["object"]))
|
||||||
|
|
||||||
# TODO: Do something with likes, follows, repeats.
|
# TODO: Do something with likes, follows, repeats.
|
||||||
_ ->
|
_ ->
|
||||||
|
|
|
@ -30,7 +30,7 @@ defp check_actor_is_active(actor) do
|
||||||
end
|
end
|
||||||
|
|
||||||
def insert(map, local \\ true) when is_map(map) do
|
def insert(map, local \\ true) when is_map(map) do
|
||||||
with nil <- Activity.get_by_ap_id(map["id"]),
|
with nil <- Activity.normalize(map),
|
||||||
map <- lazy_put_activity_defaults(map),
|
map <- lazy_put_activity_defaults(map),
|
||||||
:ok <- check_actor_is_active(map["actor"]),
|
:ok <- check_actor_is_active(map["actor"]),
|
||||||
{:ok, map} <- MRF.filter(map),
|
{:ok, map} <- MRF.filter(map),
|
||||||
|
@ -670,7 +670,7 @@ def fetch_object_from_id(id) do
|
||||||
recv_timeout: 20000
|
recv_timeout: 20000
|
||||||
),
|
),
|
||||||
{:ok, data} <- Jason.decode(body),
|
{:ok, data} <- Jason.decode(body),
|
||||||
nil <- Object.get_by_ap_id(data["id"]),
|
nil <- Object.normalize(data),
|
||||||
params <- %{
|
params <- %{
|
||||||
"type" => "Create",
|
"type" => "Create",
|
||||||
"to" => data["to"],
|
"to" => data["to"],
|
||||||
|
@ -679,7 +679,7 @@ def fetch_object_from_id(id) do
|
||||||
"object" => data
|
"object" => data
|
||||||
},
|
},
|
||||||
{:ok, activity} <- Transmogrifier.handle_incoming(params) do
|
{:ok, activity} <- Transmogrifier.handle_incoming(params) do
|
||||||
{:ok, Object.get_by_ap_id(activity.data["object"]["id"])}
|
{:ok, Object.normalize(activity.data["object"])}
|
||||||
else
|
else
|
||||||
object = %Object{} ->
|
object = %Object{} ->
|
||||||
{:ok, object}
|
{:ok, object}
|
||||||
|
@ -688,7 +688,7 @@ def fetch_object_from_id(id) do
|
||||||
Logger.info("Couldn't get object via AP, trying out OStatus fetching...")
|
Logger.info("Couldn't get object via AP, trying out OStatus fetching...")
|
||||||
|
|
||||||
case OStatus.fetch_activity_from_url(id) do
|
case OStatus.fetch_activity_from_url(id) do
|
||||||
{:ok, [activity | _]} -> {:ok, Object.get_by_ap_id(activity.data["object"]["id"])}
|
{:ok, [activity | _]} -> {:ok, Object.normalize(activity.data["object"])}
|
||||||
e -> e
|
e -> e
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,7 +18,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
||||||
"""
|
"""
|
||||||
def fix_object(object) do
|
def fix_object(object) do
|
||||||
object
|
object
|
||||||
|> Map.put("actor", object["attributedTo"])
|
|> fix_actor
|
||||||
|> fix_attachments
|
|> fix_attachments
|
||||||
|> fix_context
|
|> fix_context
|
||||||
|> fix_in_reply_to
|
|> fix_in_reply_to
|
||||||
|
@ -27,6 +27,19 @@ def fix_object(object) do
|
||||||
|> fix_content_map
|
|> fix_content_map
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def fix_actor(%{"attributedTo" => actor} = object) do
|
||||||
|
# attributedTo can be a list in the case of peertube or plume
|
||||||
|
actor =
|
||||||
|
if is_list(actor) do
|
||||||
|
Enum.at(actor, 0)
|
||||||
|
else
|
||||||
|
actor
|
||||||
|
end
|
||||||
|
|
||||||
|
object
|
||||||
|
|> Map.put("actor", actor)
|
||||||
|
end
|
||||||
|
|
||||||
def fix_in_reply_to(%{"inReplyTo" => in_reply_to_id} = object)
|
def fix_in_reply_to(%{"inReplyTo" => in_reply_to_id} = object)
|
||||||
when not is_nil(in_reply_to_id) do
|
when not is_nil(in_reply_to_id) do
|
||||||
case ActivityPub.fetch_object_from_id(in_reply_to_id) do
|
case ActivityPub.fetch_object_from_id(in_reply_to_id) do
|
||||||
|
@ -122,10 +135,14 @@ def fix_content_map(object), do: object
|
||||||
# TODO: validate those with a Ecto scheme
|
# TODO: validate those with a Ecto scheme
|
||||||
# - tags
|
# - tags
|
||||||
# - emoji
|
# - emoji
|
||||||
def handle_incoming(%{"type" => "Create", "object" => %{"type" => "Note"} = object} = data) do
|
def handle_incoming(%{"type" => "Create", "object" => %{"type" => objtype} = object} = data)
|
||||||
|
when objtype in ["Article", "Note"] do
|
||||||
with nil <- Activity.get_create_activity_by_object_ap_id(object["id"]),
|
with nil <- Activity.get_create_activity_by_object_ap_id(object["id"]),
|
||||||
%User{} = user <- User.get_or_fetch_by_ap_id(data["actor"]) do
|
%User{} = user <- User.get_or_fetch_by_ap_id(data["actor"]) do
|
||||||
object = fix_object(data["object"])
|
# prefer the activity's actor instead of attributedTo
|
||||||
|
object =
|
||||||
|
fix_object(data["object"])
|
||||||
|
|> Map.put("actor", data["actor"])
|
||||||
|
|
||||||
params = %{
|
params = %{
|
||||||
to: data["to"],
|
to: data["to"],
|
||||||
|
@ -412,7 +429,7 @@ def handle_incoming(
|
||||||
def handle_incoming(_), do: :error
|
def handle_incoming(_), do: :error
|
||||||
|
|
||||||
def get_obj_helper(id) do
|
def get_obj_helper(id) do
|
||||||
if object = Object.get_by_ap_id(id), do: {:ok, object}, else: nil
|
if object = Object.normalize(id), do: {:ok, object}, else: nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_reply_to_uri(%{"inReplyTo" => inReplyTo} = object) do
|
def set_reply_to_uri(%{"inReplyTo" => inReplyTo} = object) do
|
||||||
|
@ -460,14 +477,7 @@ def prepare_outgoing(%{"type" => "Create", "object" => %{"type" => "Note"} = obj
|
||||||
# Mastodon Accept/Reject requires a non-normalized object containing the actor URIs,
|
# Mastodon Accept/Reject requires a non-normalized object containing the actor URIs,
|
||||||
# because of course it does.
|
# because of course it does.
|
||||||
def prepare_outgoing(%{"type" => "Accept"} = data) do
|
def prepare_outgoing(%{"type" => "Accept"} = data) do
|
||||||
follow_activity_id =
|
with follow_activity <- Activity.normalize(data["object"]) do
|
||||||
if is_binary(data["object"]) do
|
|
||||||
data["object"]
|
|
||||||
else
|
|
||||||
data["object"]["id"]
|
|
||||||
end
|
|
||||||
|
|
||||||
with follow_activity <- Activity.get_by_ap_id(follow_activity_id) do
|
|
||||||
object = %{
|
object = %{
|
||||||
"actor" => follow_activity.actor,
|
"actor" => follow_activity.actor,
|
||||||
"object" => follow_activity.data["object"],
|
"object" => follow_activity.data["object"],
|
||||||
|
@ -485,14 +495,7 @@ def prepare_outgoing(%{"type" => "Accept"} = data) do
|
||||||
end
|
end
|
||||||
|
|
||||||
def prepare_outgoing(%{"type" => "Reject"} = data) do
|
def prepare_outgoing(%{"type" => "Reject"} = data) do
|
||||||
follow_activity_id =
|
with follow_activity <- Activity.normalize(data["object"]) do
|
||||||
if is_binary(data["object"]) do
|
|
||||||
data["object"]
|
|
||||||
else
|
|
||||||
data["object"]["id"]
|
|
||||||
end
|
|
||||||
|
|
||||||
with follow_activity <- Activity.get_by_ap_id(follow_activity_id) do
|
|
||||||
object = %{
|
object = %{
|
||||||
"actor" => follow_activity.actor,
|
"actor" => follow_activity.actor,
|
||||||
"object" => follow_activity.data["object"],
|
"object" => follow_activity.data["object"],
|
||||||
|
|
|
@ -128,7 +128,7 @@ def lazy_put_object_defaults(map, activity \\ %{}) do
|
||||||
Inserts a full object if it is contained in an activity.
|
Inserts a full object if it is contained in an activity.
|
||||||
"""
|
"""
|
||||||
def insert_full_object(%{"object" => %{"type" => type} = object_data})
|
def insert_full_object(%{"object" => %{"type" => type} = object_data})
|
||||||
when is_map(object_data) and type in ["Note"] do
|
when is_map(object_data) and type in ["Article", "Note"] do
|
||||||
with {:ok, _} <- Object.create(object_data) do
|
with {:ok, _} <- Object.create(object_data) do
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,7 +12,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
||||||
def render("user.json", %{user: user}) do
|
def render("user.json", %{user: user}) do
|
||||||
{:ok, user} = WebFinger.ensure_keys_present(user)
|
{:ok, user} = WebFinger.ensure_keys_present(user)
|
||||||
{:ok, _, public_key} = Salmon.keys_from_pem(user.info["keys"])
|
{:ok, _, public_key} = Salmon.keys_from_pem(user.info["keys"])
|
||||||
public_key = :public_key.pem_entry_encode(:RSAPublicKey, public_key)
|
public_key = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, public_key)
|
||||||
public_key = :public_key.pem_encode([public_key])
|
public_key = :public_key.pem_encode([public_key])
|
||||||
|
|
||||||
%{
|
%{
|
||||||
|
|
|
@ -7,7 +7,7 @@ defmodule Pleroma.Web.CommonAPI do
|
||||||
|
|
||||||
def delete(activity_id, user) do
|
def delete(activity_id, user) do
|
||||||
with %Activity{data: %{"object" => %{"id" => object_id}}} <- Repo.get(Activity, activity_id),
|
with %Activity{data: %{"object" => %{"id" => object_id}}} <- Repo.get(Activity, activity_id),
|
||||||
%Object{} = object <- Object.get_by_ap_id(object_id),
|
%Object{} = object <- Object.normalize(object_id),
|
||||||
true <- user.info["is_moderator"] || user.ap_id == object.data["actor"],
|
true <- user.info["is_moderator"] || user.ap_id == object.data["actor"],
|
||||||
{:ok, delete} <- ActivityPub.delete(object) do
|
{:ok, delete} <- ActivityPub.delete(object) do
|
||||||
{:ok, delete}
|
{:ok, delete}
|
||||||
|
@ -16,7 +16,7 @@ def delete(activity_id, user) do
|
||||||
|
|
||||||
def repeat(id_or_ap_id, user) do
|
def repeat(id_or_ap_id, user) do
|
||||||
with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id),
|
with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id),
|
||||||
object <- Object.get_by_ap_id(activity.data["object"]["id"]) do
|
object <- Object.normalize(activity.data["object"]["id"]) do
|
||||||
ActivityPub.announce(user, object)
|
ActivityPub.announce(user, object)
|
||||||
else
|
else
|
||||||
_ ->
|
_ ->
|
||||||
|
@ -26,7 +26,7 @@ def repeat(id_or_ap_id, user) do
|
||||||
|
|
||||||
def unrepeat(id_or_ap_id, user) do
|
def unrepeat(id_or_ap_id, user) do
|
||||||
with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id),
|
with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id),
|
||||||
object <- Object.get_by_ap_id(activity.data["object"]["id"]) do
|
object <- Object.normalize(activity.data["object"]["id"]) do
|
||||||
ActivityPub.unannounce(user, object)
|
ActivityPub.unannounce(user, object)
|
||||||
else
|
else
|
||||||
_ ->
|
_ ->
|
||||||
|
@ -37,7 +37,7 @@ def unrepeat(id_or_ap_id, user) do
|
||||||
def favorite(id_or_ap_id, user) do
|
def favorite(id_or_ap_id, user) do
|
||||||
with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id),
|
with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id),
|
||||||
false <- activity.data["actor"] == user.ap_id,
|
false <- activity.data["actor"] == user.ap_id,
|
||||||
object <- Object.get_by_ap_id(activity.data["object"]["id"]) do
|
object <- Object.normalize(activity.data["object"]["id"]) do
|
||||||
ActivityPub.like(user, object)
|
ActivityPub.like(user, object)
|
||||||
else
|
else
|
||||||
_ ->
|
_ ->
|
||||||
|
@ -48,7 +48,7 @@ def favorite(id_or_ap_id, user) do
|
||||||
def unfavorite(id_or_ap_id, user) do
|
def unfavorite(id_or_ap_id, user) do
|
||||||
with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id),
|
with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id),
|
||||||
false <- activity.data["actor"] == user.ap_id,
|
false <- activity.data["actor"] == user.ap_id,
|
||||||
object <- Object.get_by_ap_id(activity.data["object"]["id"]) do
|
object <- Object.normalize(activity.data["object"]["id"]) do
|
||||||
ActivityPub.unlike(user, object)
|
ActivityPub.unlike(user, object)
|
||||||
else
|
else
|
||||||
_ ->
|
_ ->
|
||||||
|
|
|
@ -95,7 +95,7 @@ def handle(:incoming_ap_doc, params) do
|
||||||
params = Utils.normalize_params(params)
|
params = Utils.normalize_params(params)
|
||||||
|
|
||||||
with {:ok, _user} <- ap_enabled_actor(params["actor"]),
|
with {:ok, _user} <- ap_enabled_actor(params["actor"]),
|
||||||
nil <- Activity.get_by_ap_id(params["id"]),
|
nil <- Activity.normalize(params["id"]),
|
||||||
{:ok, _activity} <- Transmogrifier.handle_incoming(params) do
|
{:ok, _activity} <- Transmogrifier.handle_incoming(params) do
|
||||||
else
|
else
|
||||||
%Activity{} ->
|
%Activity{} ->
|
||||||
|
|
|
@ -868,9 +868,12 @@ def index(%{assigns: %{user: user}} = conn, _params) do
|
||||||
reduce_motion: false,
|
reduce_motion: false,
|
||||||
max_toot_chars: Keyword.get(@instance, :limit)
|
max_toot_chars: Keyword.get(@instance, :limit)
|
||||||
},
|
},
|
||||||
|
rights: %{
|
||||||
|
delete_others_notice: !!user.info["is_moderator"]
|
||||||
|
},
|
||||||
compose: %{
|
compose: %{
|
||||||
me: "#{user.id}",
|
me: "#{user.id}",
|
||||||
default_privacy: "public",
|
default_privacy: user.info["default_scope"] || "public",
|
||||||
default_sensitive: false
|
default_sensitive: false
|
||||||
},
|
},
|
||||||
media_attachments: %{
|
media_attachments: %{
|
||||||
|
|
|
@ -54,8 +54,7 @@ def render(
|
||||||
%{
|
%{
|
||||||
id: to_string(activity.id),
|
id: to_string(activity.id),
|
||||||
uri: object,
|
uri: object,
|
||||||
# TODO: This might be wrong, check with mastodon.
|
url: object,
|
||||||
url: nil,
|
|
||||||
account: AccountView.render("account.json", %{user: user}),
|
account: AccountView.render("account.json", %{user: user}),
|
||||||
in_reply_to_id: nil,
|
in_reply_to_id: nil,
|
||||||
in_reply_to_account_id: nil,
|
in_reply_to_account_id: nil,
|
||||||
|
@ -128,7 +127,7 @@ def render("status.json", %{activity: %{data: %{"object" => object}} = activity}
|
||||||
in_reply_to_id: reply_to && to_string(reply_to.id),
|
in_reply_to_id: reply_to && to_string(reply_to.id),
|
||||||
in_reply_to_account_id: reply_to_user && to_string(reply_to_user.id),
|
in_reply_to_account_id: reply_to_user && to_string(reply_to_user.id),
|
||||||
reblog: nil,
|
reblog: nil,
|
||||||
content: HtmlSanitizeEx.basic_html(object["content"]),
|
content: render_content(object),
|
||||||
created_at: created_at,
|
created_at: created_at,
|
||||||
reblogs_count: announcement_count,
|
reblogs_count: announcement_count,
|
||||||
favourites_count: like_count,
|
favourites_count: like_count,
|
||||||
|
@ -207,4 +206,21 @@ def get_visibility(object) do
|
||||||
"direct"
|
"direct"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def render_content(%{"type" => "Article"} = object) do
|
||||||
|
summary = object["name"]
|
||||||
|
|
||||||
|
content =
|
||||||
|
if !!summary and summary != "" do
|
||||||
|
"<p><a href=\"#{object["url"]}\">#{summary}</a></p>#{object["content"]}"
|
||||||
|
else
|
||||||
|
object["content"]
|
||||||
|
end
|
||||||
|
|
||||||
|
HtmlSanitizeEx.basic_html(content)
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_content(object) do
|
||||||
|
HtmlSanitizeEx.basic_html(object["content"])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,8 +4,6 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
|
||||||
alias Pleroma.Stats
|
alias Pleroma.Stats
|
||||||
alias Pleroma.Web
|
alias Pleroma.Web
|
||||||
|
|
||||||
@instance Application.get_env(:pleroma, :instance)
|
|
||||||
|
|
||||||
def schemas(conn, _params) do
|
def schemas(conn, _params) do
|
||||||
response = %{
|
response = %{
|
||||||
links: [
|
links: [
|
||||||
|
@ -21,20 +19,22 @@ def schemas(conn, _params) do
|
||||||
|
|
||||||
# Schema definition: https://github.com/jhass/nodeinfo/blob/master/schemas/2.0/schema.json
|
# Schema definition: https://github.com/jhass/nodeinfo/blob/master/schemas/2.0/schema.json
|
||||||
def nodeinfo(conn, %{"version" => "2.0"}) do
|
def nodeinfo(conn, %{"version" => "2.0"}) do
|
||||||
|
instance = Application.get_env(:pleroma, :instance)
|
||||||
|
media_proxy = Application.get_env(:pleroma, :media_proxy)
|
||||||
stats = Stats.get_stats()
|
stats = Stats.get_stats()
|
||||||
|
|
||||||
response = %{
|
response = %{
|
||||||
version: "2.0",
|
version: "2.0",
|
||||||
software: %{
|
software: %{
|
||||||
name: "pleroma",
|
name: "pleroma",
|
||||||
version: Keyword.get(@instance, :version)
|
version: Keyword.get(instance, :version)
|
||||||
},
|
},
|
||||||
protocols: ["ostatus", "activitypub"],
|
protocols: ["ostatus", "activitypub"],
|
||||||
services: %{
|
services: %{
|
||||||
inbound: [],
|
inbound: [],
|
||||||
outbound: []
|
outbound: []
|
||||||
},
|
},
|
||||||
openRegistrations: Keyword.get(@instance, :registrations_open),
|
openRegistrations: Keyword.get(instance, :registrations_open),
|
||||||
usage: %{
|
usage: %{
|
||||||
users: %{
|
users: %{
|
||||||
total: stats.user_count || 0
|
total: stats.user_count || 0
|
||||||
|
@ -42,7 +42,8 @@ def nodeinfo(conn, %{"version" => "2.0"}) do
|
||||||
localPosts: stats.status_count || 0
|
localPosts: stats.status_count || 0
|
||||||
},
|
},
|
||||||
metadata: %{
|
metadata: %{
|
||||||
nodeName: Keyword.get(@instance, :name)
|
nodeName: Keyword.get(instance, :name),
|
||||||
|
mediaProxy: Keyword.get(media_proxy, :enabled)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -246,7 +246,7 @@ def to_simple_form(
|
||||||
author = if with_author, do: [{:author, UserRepresenter.to_simple_form(user)}], else: []
|
author = if with_author, do: [{:author, UserRepresenter.to_simple_form(user)}], else: []
|
||||||
|
|
||||||
mentions = (activity.recipients || []) |> get_mentions
|
mentions = (activity.recipients || []) |> get_mentions
|
||||||
follow_activity = Activity.get_by_ap_id(follow_activity["id"])
|
follow_activity = Activity.normalize(follow_activity)
|
||||||
|
|
||||||
[
|
[
|
||||||
{:"activity:object-type", ['http://activitystrea.ms/schema/1.0/activity']},
|
{:"activity:object-type", ['http://activitystrea.ms/schema/1.0/activity']},
|
||||||
|
|
|
@ -6,7 +6,7 @@ defmodule Pleroma.Web.OStatus.DeleteHandler do
|
||||||
|
|
||||||
def handle_delete(entry, _doc \\ nil) do
|
def handle_delete(entry, _doc \\ nil) do
|
||||||
with id <- XML.string_from_xpath("//id", entry),
|
with id <- XML.string_from_xpath("//id", entry),
|
||||||
object when not is_nil(object) <- Object.get_by_ap_id(id),
|
%Object{} = object <- Object.normalize(id),
|
||||||
{:ok, delete} <- ActivityPub.delete(object, false) do
|
{:ok, delete} <- ActivityPub.delete(object, false) do
|
||||||
delete
|
delete
|
||||||
end
|
end
|
||||||
|
|
|
@ -89,7 +89,7 @@ def handle_incoming(xml_string) do
|
||||||
|
|
||||||
def make_share(entry, doc, retweeted_activity) do
|
def make_share(entry, doc, retweeted_activity) do
|
||||||
with {:ok, actor} <- find_make_or_update_user(doc),
|
with {:ok, actor} <- find_make_or_update_user(doc),
|
||||||
%Object{} = object <- Object.get_by_ap_id(retweeted_activity.data["object"]["id"]),
|
%Object{} = object <- Object.normalize(retweeted_activity.data["object"]),
|
||||||
id when not is_nil(id) <- string_from_xpath("/entry/id", entry),
|
id when not is_nil(id) <- string_from_xpath("/entry/id", entry),
|
||||||
{:ok, activity, _object} = ActivityPub.announce(actor, object, id, false) do
|
{:ok, activity, _object} = ActivityPub.announce(actor, object, id, false) do
|
||||||
{:ok, activity}
|
{:ok, activity}
|
||||||
|
@ -107,7 +107,7 @@ def handle_share(entry, doc) do
|
||||||
|
|
||||||
def make_favorite(entry, doc, favorited_activity) do
|
def make_favorite(entry, doc, favorited_activity) do
|
||||||
with {:ok, actor} <- find_make_or_update_user(doc),
|
with {:ok, actor} <- find_make_or_update_user(doc),
|
||||||
%Object{} = object <- Object.get_by_ap_id(favorited_activity.data["object"]["id"]),
|
%Object{} = object <- Object.normalize(favorited_activity.data["object"]),
|
||||||
id when not is_nil(id) <- string_from_xpath("/entry/id", entry),
|
id when not is_nil(id) <- string_from_xpath("/entry/id", entry),
|
||||||
{:ok, activity, _object} = ActivityPub.like(actor, object, id, false) do
|
{:ok, activity, _object} = ActivityPub.like(actor, object, id, false) do
|
||||||
{:ok, activity}
|
{:ok, activity}
|
||||||
|
|
|
@ -107,7 +107,7 @@ def object(conn, %{"uuid" => uuid}) do
|
||||||
|
|
||||||
def activity(conn, %{"uuid" => uuid}) do
|
def activity(conn, %{"uuid" => uuid}) do
|
||||||
with id <- o_status_url(conn, :activity, uuid),
|
with id <- o_status_url(conn, :activity, uuid),
|
||||||
{_, %Activity{} = activity} <- {:activity, Activity.get_by_ap_id(id)},
|
{_, %Activity{} = activity} <- {:activity, Activity.normalize(id)},
|
||||||
{_, true} <- {:public?, ActivityPub.is_public?(activity)},
|
{_, true} <- {:public?, ActivityPub.is_public?(activity)},
|
||||||
%User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
|
%User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
|
||||||
case get_format(conn) do
|
case get_format(conn) do
|
||||||
|
|
|
@ -158,7 +158,7 @@ def push_to_socket(topics, topic, %Activity{data: %{"type" => "Announce"}} = ite
|
||||||
user = User.get_cached_by_ap_id(socket.assigns[:user].ap_id)
|
user = User.get_cached_by_ap_id(socket.assigns[:user].ap_id)
|
||||||
blocks = user.info["blocks"] || []
|
blocks = user.info["blocks"] || []
|
||||||
|
|
||||||
parent = Object.get_by_ap_id(item.data["object"])
|
parent = Object.normalize(item.data["object"])
|
||||||
|
|
||||||
unless is_nil(parent) or item.actor in blocks or parent.data["actor"] in blocks do
|
unless is_nil(parent) or item.actor in blocks or parent.data["actor"] in blocks do
|
||||||
send(socket.transport_pid, {:text, represent_update(item, user)})
|
send(socket.transport_pid, {:text, represent_update(item, user)})
|
||||||
|
|
|
@ -4,7 +4,7 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do
|
||||||
use Pleroma.Web.TwitterAPI.Representers.BaseRepresenter
|
use Pleroma.Web.TwitterAPI.Representers.BaseRepresenter
|
||||||
alias Pleroma.Web.TwitterAPI.Representers.ObjectRepresenter
|
alias Pleroma.Web.TwitterAPI.Representers.ObjectRepresenter
|
||||||
alias Pleroma.{Activity, User}
|
alias Pleroma.{Activity, User}
|
||||||
alias Pleroma.Web.TwitterAPI.{TwitterAPI, UserView}
|
alias Pleroma.Web.TwitterAPI.{TwitterAPI, UserView, ActivityView}
|
||||||
alias Pleroma.Web.CommonAPI.Utils
|
alias Pleroma.Web.CommonAPI.Utils
|
||||||
alias Pleroma.Formatter
|
alias Pleroma.Formatter
|
||||||
|
|
||||||
|
@ -164,14 +164,7 @@ def to_map(
|
||||||
|
|
||||||
tags = if possibly_sensitive, do: Enum.uniq(["nsfw" | tags]), else: tags
|
tags = if possibly_sensitive, do: Enum.uniq(["nsfw" | tags]), else: tags
|
||||||
|
|
||||||
summary = activity.data["object"]["summary"]
|
{summary, content} = ActivityView.render_content(object)
|
||||||
|
|
||||||
content =
|
|
||||||
if !!summary and summary != "" do
|
|
||||||
"<span>#{activity.data["object"]["summary"]}</span><br />#{content}</span>"
|
|
||||||
else
|
|
||||||
content
|
|
||||||
end
|
|
||||||
|
|
||||||
html =
|
html =
|
||||||
HtmlSanitizeEx.basic_html(content)
|
HtmlSanitizeEx.basic_html(content)
|
||||||
|
@ -198,7 +191,8 @@ def to_map(
|
||||||
"tags" => tags,
|
"tags" => tags,
|
||||||
"activity_type" => "post",
|
"activity_type" => "post",
|
||||||
"possibly_sensitive" => possibly_sensitive,
|
"possibly_sensitive" => possibly_sensitive,
|
||||||
"visibility" => Pleroma.Web.MastodonAPI.StatusView.get_visibility(object)
|
"visibility" => Pleroma.Web.MastodonAPI.StatusView.get_visibility(object),
|
||||||
|
"summary" => object["summary"]
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -431,6 +431,19 @@ def update_profile(%{assigns: %{user: user}} = conn, params) do
|
||||||
user
|
user
|
||||||
end
|
end
|
||||||
|
|
||||||
|
user =
|
||||||
|
if default_scope = params["default_scope"] do
|
||||||
|
with new_info <- Map.put(user.info, "default_scope", default_scope),
|
||||||
|
change <- User.info_changeset(user, %{info: new_info}),
|
||||||
|
{:ok, user} <- User.update_and_set_cache(change) do
|
||||||
|
user
|
||||||
|
else
|
||||||
|
_e -> user
|
||||||
|
end
|
||||||
|
else
|
||||||
|
user
|
||||||
|
end
|
||||||
|
|
||||||
with changeset <- User.update_changeset(user, params),
|
with changeset <- User.update_changeset(user, params),
|
||||||
{:ok, user} <- User.update_and_set_cache(changeset) do
|
{:ok, user} <- User.update_and_set_cache(changeset) do
|
||||||
CommonAPI.update(user)
|
CommonAPI.update(user)
|
||||||
|
|
|
@ -228,15 +228,7 @@ def render(
|
||||||
|
|
||||||
tags = if possibly_sensitive, do: Enum.uniq(["nsfw" | tags]), else: tags
|
tags = if possibly_sensitive, do: Enum.uniq(["nsfw" | tags]), else: tags
|
||||||
|
|
||||||
summary = activity.data["object"]["summary"]
|
{summary, content} = render_content(object)
|
||||||
content = object["content"]
|
|
||||||
|
|
||||||
content =
|
|
||||||
if !!summary and summary != "" do
|
|
||||||
"<span>#{activity.data["object"]["summary"]}</span><br />#{content}</span>"
|
|
||||||
else
|
|
||||||
content
|
|
||||||
end
|
|
||||||
|
|
||||||
html =
|
html =
|
||||||
HtmlSanitizeEx.basic_html(content)
|
HtmlSanitizeEx.basic_html(content)
|
||||||
|
@ -263,7 +255,41 @@ def render(
|
||||||
"tags" => tags,
|
"tags" => tags,
|
||||||
"activity_type" => "post",
|
"activity_type" => "post",
|
||||||
"possibly_sensitive" => possibly_sensitive,
|
"possibly_sensitive" => possibly_sensitive,
|
||||||
"visibility" => Pleroma.Web.MastodonAPI.StatusView.get_visibility(object)
|
"visibility" => Pleroma.Web.MastodonAPI.StatusView.get_visibility(object),
|
||||||
|
"summary" => summary
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def render_content(%{"type" => "Note"} = object) do
|
||||||
|
summary = object["summary"]
|
||||||
|
|
||||||
|
content =
|
||||||
|
if !!summary and summary != "" do
|
||||||
|
"<p>#{summary}</p>#{object["content"]}"
|
||||||
|
else
|
||||||
|
object["content"]
|
||||||
|
end
|
||||||
|
|
||||||
|
{summary, content}
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_content(%{"type" => "Article"} = object) do
|
||||||
|
summary = object["name"] || object["summary"]
|
||||||
|
|
||||||
|
content =
|
||||||
|
if !!summary and summary != "" do
|
||||||
|
"<p><a href=\"#{object["url"]}\">#{summary}</a></p>#{object["content"]}"
|
||||||
|
else
|
||||||
|
object["content"]
|
||||||
|
end
|
||||||
|
|
||||||
|
{summary, content}
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_content(object) do
|
||||||
|
summary = object["summary"] || "Unhandled activity type: #{object["type"]}"
|
||||||
|
content = "<p>#{summary}</p>#{object["content"]}"
|
||||||
|
|
||||||
|
{summary, content}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -52,7 +52,8 @@ def render("user.json", %{user: user = %User{}} = assigns) do
|
||||||
"cover_photo" => User.banner_url(user) |> MediaProxy.url(),
|
"cover_photo" => User.banner_url(user) |> MediaProxy.url(),
|
||||||
"background_image" => image_url(user.info["background"]) |> MediaProxy.url(),
|
"background_image" => image_url(user.info["background"]) |> MediaProxy.url(),
|
||||||
"is_local" => user.local,
|
"is_local" => user.local,
|
||||||
"locked" => !!user.info["locked"]
|
"locked" => !!user.info["locked"],
|
||||||
|
"default_scope" => user.info["default_scope"] || "public"
|
||||||
}
|
}
|
||||||
|
|
||||||
if assigns[:token] do
|
if assigns[:token] do
|
||||||
|
|
|
@ -13,6 +13,6 @@ test "Renders a user, including the public key" do
|
||||||
assert result["id"] == user.ap_id
|
assert result["id"] == user.ap_id
|
||||||
assert result["preferredUsername"] == user.nickname
|
assert result["preferredUsername"] == user.nickname
|
||||||
|
|
||||||
assert String.contains?(result["publicKey"]["publicKeyPem"], "BEGIN RSA PUBLIC KEY")
|
assert String.contains?(result["publicKey"]["publicKeyPem"], "BEGIN PUBLIC KEY")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -126,7 +126,7 @@ test "an activity" do
|
||||||
}
|
}
|
||||||
|
|
||||||
expected_html =
|
expected_html =
|
||||||
"<span>2hu</span><br />alert('YAY')Some <img height='32px' width='32px' alt='2hu' title='2hu' src='corndog.png' /> content mentioning <a href=\"#{
|
"<p>2hu</p>alert('YAY')Some <img height='32px' width='32px' alt='2hu' title='2hu' src='corndog.png' /> content mentioning <a href=\"#{
|
||||||
mentioned_user.ap_id
|
mentioned_user.ap_id
|
||||||
}\">@shp</a>"
|
}\">@shp</a>"
|
||||||
|
|
||||||
|
@ -155,7 +155,8 @@ test "an activity" do
|
||||||
"activity_type" => "post",
|
"activity_type" => "post",
|
||||||
"possibly_sensitive" => true,
|
"possibly_sensitive" => true,
|
||||||
"uri" => activity.data["object"]["id"],
|
"uri" => activity.data["object"]["id"],
|
||||||
"visibility" => "direct"
|
"visibility" => "direct",
|
||||||
|
"summary" => "2hu"
|
||||||
}
|
}
|
||||||
|
|
||||||
assert ActivityRepresenter.to_map(activity, %{
|
assert ActivityRepresenter.to_map(activity, %{
|
||||||
|
|
|
@ -48,7 +48,8 @@ test "a create activity with a note" do
|
||||||
"text" => "Hey @shp!",
|
"text" => "Hey @shp!",
|
||||||
"uri" => activity.data["object"]["id"],
|
"uri" => activity.data["object"]["id"],
|
||||||
"user" => UserView.render("show.json", %{user: user}),
|
"user" => UserView.render("show.json", %{user: user}),
|
||||||
"visibility" => "direct"
|
"visibility" => "direct",
|
||||||
|
"summary" => nil
|
||||||
}
|
}
|
||||||
|
|
||||||
assert result == expected
|
assert result == expected
|
||||||
|
|
|
@ -60,7 +60,8 @@ test "A user" do
|
||||||
"cover_photo" => banner,
|
"cover_photo" => banner,
|
||||||
"background_image" => nil,
|
"background_image" => nil,
|
||||||
"is_local" => true,
|
"is_local" => true,
|
||||||
"locked" => false
|
"locked" => false,
|
||||||
|
"default_scope" => "public"
|
||||||
}
|
}
|
||||||
|
|
||||||
assert represented == UserView.render("show.json", %{user: user})
|
assert represented == UserView.render("show.json", %{user: user})
|
||||||
|
@ -96,7 +97,8 @@ test "A user for a given other follower", %{user: user} do
|
||||||
"cover_photo" => banner,
|
"cover_photo" => banner,
|
||||||
"background_image" => nil,
|
"background_image" => nil,
|
||||||
"is_local" => true,
|
"is_local" => true,
|
||||||
"locked" => false
|
"locked" => false,
|
||||||
|
"default_scope" => "public"
|
||||||
}
|
}
|
||||||
|
|
||||||
assert represented == UserView.render("show.json", %{user: user, for: follower})
|
assert represented == UserView.render("show.json", %{user: user, for: follower})
|
||||||
|
@ -133,7 +135,8 @@ test "A user that follows you", %{user: user} do
|
||||||
"cover_photo" => banner,
|
"cover_photo" => banner,
|
||||||
"background_image" => nil,
|
"background_image" => nil,
|
||||||
"is_local" => true,
|
"is_local" => true,
|
||||||
"locked" => false
|
"locked" => false,
|
||||||
|
"default_scope" => "public"
|
||||||
}
|
}
|
||||||
|
|
||||||
assert represented == UserView.render("show.json", %{user: follower, for: user})
|
assert represented == UserView.render("show.json", %{user: follower, for: user})
|
||||||
|
@ -177,7 +180,8 @@ test "A blocked user for the blocker" do
|
||||||
"cover_photo" => banner,
|
"cover_photo" => banner,
|
||||||
"background_image" => nil,
|
"background_image" => nil,
|
||||||
"is_local" => true,
|
"is_local" => true,
|
||||||
"locked" => false
|
"locked" => false,
|
||||||
|
"default_scope" => "public"
|
||||||
}
|
}
|
||||||
|
|
||||||
blocker = Repo.get(User, blocker.id)
|
blocker = Repo.get(User, blocker.id)
|
||||||
|
|
Loading…
Reference in a new issue