summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/pleroma/application.ex34
-rw-r--r--lib/pleroma/http/connection.ex3
-rw-r--r--lib/pleroma/uploaders/mdii.ex3
-rw-r--r--lib/pleroma/user.ex85
-rw-r--r--lib/pleroma/web/mastodon_api/mastodon_api_controller.ex38
-rw-r--r--lib/pleroma/web/mastodon_api/views/status_view.ex3
-rw-r--r--lib/pleroma/web/rich_media/helpers.ex3
-rw-r--r--lib/pleroma/web/rich_media/parser.ex30
-rw-r--r--lib/pleroma/web/rich_media/parsers/oembed_parser.ex2
-rw-r--r--lib/pleroma/web/router.ex3
-rw-r--r--lib/pleroma/web/templates/mastodon_api/mastodon/index.html.eex27
11 files changed, 179 insertions, 52 deletions
diff --git a/lib/pleroma/application.ex b/lib/pleroma/application.ex
index c65bebb3b..40bff08c7 100644
--- a/lib/pleroma/application.ex
+++ b/lib/pleroma/application.ex
@@ -101,12 +101,15 @@ defmodule Pleroma.Application do
],
id: :cachex_idem
),
- worker(Pleroma.FlakeId, []),
- worker(Pleroma.Web.Federator.RetryQueue, []),
- worker(Pleroma.Web.Federator, []),
- worker(Pleroma.Stats, []),
- worker(Pleroma.Web.Push, [])
+ worker(Pleroma.FlakeId, [])
] ++
+ hackney_pool_children() ++
+ [
+ worker(Pleroma.Web.Federator.RetryQueue, []),
+ worker(Pleroma.Web.Federator, []),
+ worker(Pleroma.Stats, []),
+ worker(Pleroma.Web.Push, [])
+ ] ++
streamer_child() ++
chat_child() ++
[
@@ -121,6 +124,20 @@ defmodule Pleroma.Application do
Supervisor.start_link(children, opts)
end
+ def enabled_hackney_pools() do
+ [:media] ++
+ if Application.get_env(:tesla, :adapter) == Tesla.Adapter.Hackney do
+ [:federation]
+ else
+ []
+ end ++
+ if Pleroma.Config.get([Pleroma.Uploader, :proxy_remote]) do
+ [:upload]
+ else
+ []
+ end
+ end
+
if Mix.env() == :test do
defp streamer_child(), do: []
defp chat_child(), do: []
@@ -137,4 +154,11 @@ defmodule Pleroma.Application do
end
end
end
+
+ defp hackney_pool_children() do
+ for pool <- enabled_hackney_pools() do
+ options = Pleroma.Config.get([:hackney_pools, pool])
+ :hackney_pool.child_spec(pool, options)
+ end
+ end
end
diff --git a/lib/pleroma/http/connection.ex b/lib/pleroma/http/connection.ex
index 699d80cd7..b798eaa5a 100644
--- a/lib/pleroma/http/connection.ex
+++ b/lib/pleroma/http/connection.ex
@@ -10,7 +10,8 @@ defmodule Pleroma.HTTP.Connection do
@hackney_options [
timeout: 10000,
recv_timeout: 20000,
- follow_redirect: true
+ follow_redirect: true,
+ pool: :federation
]
@adapter Application.get_env(:tesla, :adapter)
diff --git a/lib/pleroma/uploaders/mdii.ex b/lib/pleroma/uploaders/mdii.ex
index 530b34362..320b07abd 100644
--- a/lib/pleroma/uploaders/mdii.ex
+++ b/lib/pleroma/uploaders/mdii.ex
@@ -24,7 +24,8 @@ defmodule Pleroma.Uploaders.MDII do
extension = String.split(upload.name, ".") |> List.last()
query = "#{cgi}?#{extension}"
- with {:ok, %{status: 200, body: body}} <- @httpoison.post(query, file_data) do
+ with {:ok, %{status: 200, body: body}} <-
+ @httpoison.post(query, file_data, adapter: [pool: :default]) do
remote_file_name = String.split(body) |> List.first()
public_url = "#{files}/#{remote_file_name}.#{extension}"
{:ok, {:url, public_url}}
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 1468cc133..33630ac7c 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -39,6 +39,7 @@ defmodule Pleroma.User do
field(:follower_address, :string)
field(:search_rank, :float, virtual: true)
field(:tags, {:array, :string}, default: [])
+ field(:bookmarks, {:array, :string}, default: [])
field(:last_refreshed_at, :naive_datetime)
has_many(:notifications, Notification)
embeds_one(:info, Pleroma.User.Info)
@@ -309,20 +310,30 @@ defmodule Pleroma.User do
@doc "A mass follow for local users. Ignores blocks and has no side effects"
@spec follow_all(User.t(), list(User.t())) :: {atom(), User.t()}
def follow_all(follower, followeds) do
- following =
- (follower.following ++ Enum.map(followeds, fn %{follower_address: fa} -> fa end))
- |> Enum.uniq()
+ followed_addresses = Enum.map(followeds, fn %{follower_address: fa} -> fa end)
+
+ q =
+ from(u in User,
+ where: u.id == ^follower.id,
+ update: [
+ set: [
+ following:
+ fragment(
+ "array(select distinct unnest (array_cat(?, ?)))",
+ u.following,
+ ^followed_addresses
+ )
+ ]
+ ]
+ )
- {:ok, follower} =
- follower
- |> follow_changeset(%{following: following})
- |> update_and_set_cache
+ {1, [follower]} = Repo.update_all(q, [], returning: true)
Enum.each(followeds, fn followed ->
update_follower_count(followed)
end)
- {:ok, follower}
+ set_cache(follower)
end
def follow(%User{} = follower, %User{info: info} = followed) do
@@ -343,18 +354,17 @@ defmodule Pleroma.User do
Websub.subscribe(follower, followed)
end
- following =
- [ap_followers | follower.following]
- |> Enum.uniq()
+ q =
+ from(u in User,
+ where: u.id == ^follower.id,
+ update: [push: [following: ^ap_followers]]
+ )
- follower =
- follower
- |> follow_changeset(%{following: following})
- |> update_and_set_cache
+ {1, [follower]} = Repo.update_all(q, [], returning: true)
{:ok, _} = update_follower_count(followed)
- follower
+ set_cache(follower)
end
end
@@ -362,17 +372,18 @@ defmodule Pleroma.User do
ap_followers = followed.follower_address
if following?(follower, followed) and follower.ap_id != followed.ap_id do
- following =
- follower.following
- |> List.delete(ap_followers)
+ q =
+ from(u in User,
+ where: u.id == ^follower.id,
+ update: [pull: [following: ^ap_followers]]
+ )
- {:ok, follower} =
- follower
- |> follow_changeset(%{following: following})
- |> update_and_set_cache
+ {1, [follower]} = Repo.update_all(q, [], returning: true)
{:ok, followed} = update_follower_count(followed)
+ set_cache(follower)
+
{:ok, follower, Utils.fetch_latest_follow(follower, followed)}
else
{:error, "Not subscribed!"}
@@ -423,12 +434,16 @@ defmodule Pleroma.User do
get_by_nickname(nickname)
end
+ def set_cache(user) do
+ Cachex.put(:user_cache, "ap_id:#{user.ap_id}", user)
+ Cachex.put(:user_cache, "nickname:#{user.nickname}", user)
+ Cachex.put(:user_cache, "user_info:#{user.id}", user_info(user))
+ {:ok, user}
+ end
+
def update_and_set_cache(changeset) do
with {:ok, user} <- Repo.update(changeset) do
- Cachex.put(:user_cache, "ap_id:#{user.ap_id}", user)
- Cachex.put(:user_cache, "nickname:#{user.nickname}", user)
- Cachex.put(:user_cache, "user_info:#{user.id}", user_info(user))
- {:ok, user}
+ set_cache(user)
else
e -> e
end
@@ -1156,6 +1171,22 @@ defmodule Pleroma.User do
updated_user
end
+ def bookmark(%User{} = user, status_id) do
+ bookmarks = Enum.uniq(user.bookmarks ++ [status_id])
+ update_bookmarks(user, bookmarks)
+ end
+
+ def unbookmark(%User{} = user, status_id) do
+ bookmarks = Enum.uniq(user.bookmarks -- [status_id])
+ update_bookmarks(user, bookmarks)
+ end
+
+ def update_bookmarks(%User{} = user, bookmarks) do
+ user
+ |> change(%{bookmarks: bookmarks})
+ |> update_and_set_cache
+ end
+
defp normalize_tags(tags) do
[tags]
|> List.flatten()
diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
index 65b612026..0726e6ac4 100644
--- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
+++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
@@ -423,6 +423,28 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
end
+ def bookmark_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do
+ with %Activity{} = activity <- Repo.get(Activity, id),
+ %User{} = user <- User.get_by_nickname(user.nickname),
+ true <- ActivityPub.visible_for_user?(activity, user),
+ {:ok, user} <- User.bookmark(user, activity.data["object"]["id"]) do
+ conn
+ |> put_view(StatusView)
+ |> try_render("status.json", %{activity: activity, for: user, as: :activity})
+ end
+ end
+
+ def unbookmark_status(%{assigns: %{user: user}} = conn, %{"id" => id}) do
+ with %Activity{} = activity <- Repo.get(Activity, id),
+ %User{} = user <- User.get_by_nickname(user.nickname),
+ true <- ActivityPub.visible_for_user?(activity, user),
+ {:ok, user} <- User.unbookmark(user, activity.data["object"]["id"]) do
+ conn
+ |> put_view(StatusView)
+ |> try_render("status.json", %{activity: activity, for: user, as: :activity})
+ end
+ end
+
def notifications(%{assigns: %{user: user}} = conn, params) do
notifications = Notification.for_user(user, params)
@@ -859,6 +881,19 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|> render("index.json", %{activities: activities, for: user, as: :activity})
end
+ def bookmarks(%{assigns: %{user: user}} = conn, _) do
+ user = Repo.get(User, user.id)
+
+ activities =
+ user.bookmarks
+ |> Enum.map(fn id -> Activity.get_create_by_object_ap_id(id) end)
+ |> Enum.reverse()
+
+ conn
+ |> put_view(StatusView)
+ |> render("index.json", %{activities: activities, for: user, as: :activity})
+ end
+
def get_lists(%{assigns: %{user: user}} = conn, opts) do
lists = Pleroma.List.for_user(user, opts)
res = ListView.render("lists.json", lists: lists)
@@ -1311,7 +1346,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
[],
adapter: [
timeout: timeout,
- recv_timeout: timeout
+ recv_timeout: timeout,
+ pool: :default
]
),
{:ok, data} <- Jason.decode(body) do
diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex
index b14ca9f5d..d5b7e68c7 100644
--- a/lib/pleroma/web/mastodon_api/views/status_view.ex
+++ b/lib/pleroma/web/mastodon_api/views/status_view.ex
@@ -87,6 +87,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
favourites_count: 0,
reblogged: false,
favourited: false,
+ bookmarked: false,
muted: false,
pinned: pinned?(activity, user),
sensitive: false,
@@ -121,6 +122,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
repeated = opts[:for] && opts[:for].ap_id in (object["announcements"] || [])
favorited = opts[:for] && opts[:for].ap_id in (object["likes"] || [])
+ bookmarked = opts[:for] && object["id"] in opts[:for].bookmarks
attachment_data = object["attachment"] || []
attachments = render_many(attachment_data, StatusView, "attachment.json", as: :attachment)
@@ -157,6 +159,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
favourites_count: like_count,
reblogged: present?(repeated),
favourited: present?(favorited),
+ bookmarked: present?(bookmarked),
muted: false,
pinned: pinned?(activity, user),
sensitive: sensitive,
diff --git a/lib/pleroma/web/rich_media/helpers.ex b/lib/pleroma/web/rich_media/helpers.ex
index 71fdddef9..44e876777 100644
--- a/lib/pleroma/web/rich_media/helpers.ex
+++ b/lib/pleroma/web/rich_media/helpers.ex
@@ -7,7 +7,8 @@ defmodule Pleroma.Web.RichMedia.Helpers do
alias Pleroma.Web.RichMedia.Parser
def fetch_data_for_activity(%Activity{} = activity) do
- with %Object{} = object <- Object.normalize(activity.data["object"]),
+ with true <- Pleroma.Config.get([:rich_media, :enabled], true),
+ %Object{} = object <- Object.normalize(activity.data["object"]),
{:ok, page_url} <- HTML.extract_first_external_url(object, object.data["content"]),
{:ok, rich_media} <- Parser.parse(page_url) do
%{page_url: page_url, rich_media: rich_media}
diff --git a/lib/pleroma/web/rich_media/parser.ex b/lib/pleroma/web/rich_media/parser.ex
index 76d977ac2..32dec9887 100644
--- a/lib/pleroma/web/rich_media/parser.ex
+++ b/lib/pleroma/web/rich_media/parser.ex
@@ -28,9 +28,9 @@ defmodule Pleroma.Web.RichMedia.Parser do
defp parse_url(url) do
try do
- {:ok, %Tesla.Env{body: html}} = Pleroma.HTTP.get(url)
+ {:ok, %Tesla.Env{body: html}} = Pleroma.HTTP.get(url, [], adapter: [pool: :media])
- html |> maybe_parse() |> get_parsed_data()
+ html |> maybe_parse() |> clean_parsed_data() |> check_parsed_data()
rescue
e ->
{:error, "Parsing error: #{inspect(e)}"}
@@ -46,11 +46,33 @@ defmodule Pleroma.Web.RichMedia.Parser do
end)
end
- defp get_parsed_data(%{title: title} = data) when is_binary(title) and byte_size(title) > 0 do
+ defp check_parsed_data(%{title: title} = data) when is_binary(title) and byte_size(title) > 0 do
{:ok, data}
end
- defp get_parsed_data(data) do
+ defp check_parsed_data(data) do
{:error, "Found metadata was invalid or incomplete: #{inspect(data)}"}
end
+
+ defp string_is_valid_unicode(data) when is_binary(data) do
+ data
+ |> :unicode.characters_to_binary()
+ |> clean_string()
+ end
+
+ defp string_is_valid_unicode(data), do: {:ok, data}
+
+ defp clean_string({:error, _, _}), do: {:error, "Invalid data"}
+ defp clean_string(data), do: {:ok, data}
+
+ defp clean_parsed_data(data) do
+ data
+ |> Enum.reject(fn {_, val} ->
+ case string_is_valid_unicode(val) do
+ {:ok, _} -> false
+ _ -> true
+ end
+ end)
+ |> Map.new()
+ end
end
diff --git a/lib/pleroma/web/rich_media/parsers/oembed_parser.ex b/lib/pleroma/web/rich_media/parsers/oembed_parser.ex
index efa98bc2c..2530b8c9d 100644
--- a/lib/pleroma/web/rich_media/parsers/oembed_parser.ex
+++ b/lib/pleroma/web/rich_media/parsers/oembed_parser.ex
@@ -20,7 +20,7 @@ defmodule Pleroma.Web.RichMedia.Parsers.OEmbed do
end
defp get_oembed_data(url) do
- {:ok, %Tesla.Env{body: json}} = Pleroma.HTTP.get(url)
+ {:ok, %Tesla.Env{body: json}} = Pleroma.HTTP.get(url, [], adapter: [pool: :media])
{:ok, data} = Jason.decode(json)
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index bfa10451a..c6b4d37ab 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -185,6 +185,7 @@ defmodule Pleroma.Web.Router do
get("/timelines/direct", MastodonAPIController, :dm_timeline)
get("/favourites", MastodonAPIController, :favourites)
+ get("/bookmarks", MastodonAPIController, :bookmarks)
post("/statuses", MastodonAPIController, :post_status)
delete("/statuses/:id", MastodonAPIController, :delete_status)
@@ -195,6 +196,8 @@ defmodule Pleroma.Web.Router do
post("/statuses/:id/unfavourite", MastodonAPIController, :unfav_status)
post("/statuses/:id/pin", MastodonAPIController, :pin_status)
post("/statuses/:id/unpin", MastodonAPIController, :unpin_status)
+ post("/statuses/:id/bookmark", MastodonAPIController, :bookmark_status)
+ post("/statuses/:id/unbookmark", MastodonAPIController, :unbookmark_status)
post("/notifications/clear", MastodonAPIController, :clear_notifications)
post("/notifications/dismiss", MastodonAPIController, :dismiss_notification)
diff --git a/lib/pleroma/web/templates/mastodon_api/mastodon/index.html.eex b/lib/pleroma/web/templates/mastodon_api/mastodon/index.html.eex
index 0862412ea..9a725e420 100644
--- a/lib/pleroma/web/templates/mastodon_api/mastodon/index.html.eex
+++ b/lib/pleroma/web/templates/mastodon_api/mastodon/index.html.eex
@@ -1,23 +1,28 @@
<!DOCTYPE html>
<html lang='en'>
<head>
+<meta charset='utf-8'>
+<meta content='width=device-width, initial-scale=1' name='viewport'>
<title>
<%= Application.get_env(:pleroma, :instance)[:name] %>
</title>
-<meta charset='utf-8'>
-<meta content='width=device-width, initial-scale=1' name='viewport'>
<link rel="icon" type="image/png" href="/favicon.png"/>
-<link rel="stylesheet" media="all" href="/packs/common.css" />
-<link rel="stylesheet" media="all" href="/packs/default.css" />
+<script crossorigin='anonymous' src="/packs/locales.js"></script>
+<script crossorigin='anonymous' src="/packs/locales/glitch/en.js"></script>
-<script src="/packs/common.js"></script>
-<script src="/packs/locale_en.js"></script>
-<link as='script' crossorigin='anonymous' href='/packs/features/getting_started.js' rel='preload'>
-<link as='script' crossorigin='anonymous' href='/packs/features/compose.js' rel='preload'>
-<link as='script' crossorigin='anonymous' href='/packs/features/home_timeline.js' rel='preload'>
-<link as='script' crossorigin='anonymous' href='/packs/features/notifications.js' rel='preload'>
+<link rel='preload' as='script' crossorigin='anonymous' href='/packs/features/getting_started.js'>
+<link rel='preload' as='script' crossorigin='anonymous' href='/packs/features/compose.js'>
+<link rel='preload' as='script' crossorigin='anonymous' href='/packs/features/home_timeline.js'>
+<link rel='preload' as='script' crossorigin='anonymous' href='/packs/features/notifications.js'>
<script id='initial-state' type='application/json'><%= raw @initial_state %></script>
-<script src="/packs/application.js"></script>
+
+<script src="/packs/core/common.js"></script>
+<link rel="stylesheet" media="all" href="/packs/core/common.css" />
+
+<script src="/packs/flavours/glitch/common.js"></script>
+<link rel="stylesheet" media="all" href="/packs/flavours/glitch/common.css" />
+
+<script src="/packs/flavours/glitch/home.js"></script>
</head>
<body class='app-body no-reduce-motion system-font'>
<div class='app-holder' data-props='{&quot;locale&quot;:&quot;en&quot;}' id='mastodon'>