Merge remote-tracking branch 'origin/develop' into revert-48552b38
This commit is contained in:
commit
ea864bdb96
|
@ -16,7 +16,8 @@ config :pleroma, Pleroma.Web.Endpoint,
|
|||
debug_errors: true,
|
||||
code_reloader: true,
|
||||
check_origin: false,
|
||||
watchers: []
|
||||
watchers: [],
|
||||
secure_cookie_flag: false
|
||||
|
||||
config :pleroma, Pleroma.Mailer, adapter: Swoosh.Adapters.Local
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ Feel free to contact us to be added to this list!
|
|||
- Homepage: <http://www.pleroma.com/desktop-app/>
|
||||
- Source Code: ???
|
||||
- Platforms: Windows, Mac, (Linux?)
|
||||
- Features: Streaming Ready
|
||||
|
||||
### Social
|
||||
- Source Code: <https://gitlab.gnome.org/BrainBlasted/Social>
|
||||
|
@ -19,6 +20,7 @@ Feel free to contact us to be added to this list!
|
|||
- Source Code: <https://github.com/h3poteto/whalebird-desktop>
|
||||
- Contact: [@h3poteto@pleroma.io](https://pleroma.io/users/h3poteto)
|
||||
- Platforms: Windows, Mac, Linux
|
||||
- Features: Streaming Ready
|
||||
|
||||
## Handheld
|
||||
### Amaroq
|
||||
|
@ -26,60 +28,71 @@ Feel free to contact us to be added to this list!
|
|||
- Source Code: <https://github.com/ReticentJohn/Amaroq>
|
||||
- Contact: [@eurasierboy@mastodon.social](https://mastodon.social/users/eurasierboy)
|
||||
- Platforms: iOS
|
||||
- Features: No Streaming
|
||||
|
||||
### Nekonium
|
||||
- Homepage: [F-Droid Repository](https://repo.gdgd.jp.net/), [Google Play](https://play.google.com/store/apps/details?id=com.apps.nekonium), [Amazon](https://www.amazon.co.jp/dp/B076FXPRBC/)
|
||||
- Source: <https://git.gdgd.jp.net/lin/nekonium/>
|
||||
- Contact: [@lin@pleroma.gdgd.jp.net](https://pleroma.gdgd.jp.net/users/lin)
|
||||
- Platforms: Android
|
||||
- Features: Streaming Ready
|
||||
|
||||
### Mastalab
|
||||
- Source Code: <https://gitlab.com/tom79/mastalab/>
|
||||
- Contact: [@tom79@mastodon.social](https://mastodon.social/users/tom79)
|
||||
- Platforms: Android
|
||||
- Features: Streaming Ready
|
||||
|
||||
### Roma
|
||||
- Homepage: <http://www.pleroma.com/>
|
||||
- Source Code: ???
|
||||
- Platforms: iOS, Android
|
||||
- Features: No Streaming
|
||||
|
||||
### Tootdon
|
||||
- Homepage: <http://tootdon.club/>, <http://blog.mastodon-tootdon.com/>
|
||||
- Source Code: ???
|
||||
- Contact: [@tootdon@mstdn.jp](https://mstdn.jp/users/tootdon)
|
||||
- Platforms: Android, iOS
|
||||
- Features: No Streaming
|
||||
|
||||
### Tusky
|
||||
- Homepage: <https://tuskyapp.github.io/>
|
||||
- Source Code: <https://github.com/tuskyapp/Tusky>
|
||||
- Contact: [@ConnyDuck@mastodon.social](https://mastodon.social/users/ConnyDuck)
|
||||
- Platforms: Android
|
||||
- Features: No Streaming
|
||||
|
||||
### Twidere
|
||||
- Homepage: <https://twidere.mariotaku.org/>
|
||||
- Source Code: <https://github.com/TwidereProject/Twidere-Android/>, <https://github.com/TwidereProject/Twidere-iOS/>
|
||||
- Contact: <me@mariotaku.org>
|
||||
- Platform: Android, iOS
|
||||
- Features: No Streaming
|
||||
|
||||
## Alternative Web Interfaces
|
||||
### Brutaldon
|
||||
- Homepage: <https://jfm.carcosa.net/projects/software/brutaldon/>
|
||||
- Source Code: <https://github.com/jfmcbrayer/brutaldon>
|
||||
- Contact: [@gcupc@glitch.social](https://glitch.social/users/gcupc)
|
||||
- Features: No Streaming
|
||||
|
||||
### Feather
|
||||
- Source Code: <https://github.com/kaniini/feather>
|
||||
- Contact: [@kaniini@pleroma.site](https://pleroma.site/kaniini)
|
||||
- Features: No Streaming
|
||||
|
||||
### Halcyon
|
||||
- Source Code: <https://notabug.org/halcyon-suite/halcyon>
|
||||
- Contact: [@halcyon@social.csswg.org](https://social.csswg.org/users/halcyon)
|
||||
- Features: Streaming Ready
|
||||
|
||||
### Pinafore
|
||||
- Homepage: <https://pinafore.social/>
|
||||
- Source Code: <https://github.com/nolanlawson/pinafore>
|
||||
- Contact: [@pinafore@mastodon.technology](https://mastodon.technology/users/pinafore)
|
||||
- Note: Pleroma support is a secondary goal
|
||||
- Features: No Streaming
|
||||
|
||||
### Sengi
|
||||
- Source Code: <https://github.com/NicolasConstant/sengi>
|
||||
|
|
|
@ -10,6 +10,7 @@ defmodule Pleroma.Notification do
|
|||
alias Pleroma.Notification
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.Web.CommonAPI.Utils
|
||||
alias Pleroma.Web.CommonAPI
|
||||
|
||||
import Ecto.Query
|
||||
|
||||
|
@ -117,7 +118,7 @@ defmodule Pleroma.Notification do
|
|||
# TODO move to sql, too.
|
||||
def create_notification(%Activity{} = activity, %User{} = user) do
|
||||
unless User.blocks?(user, %{ap_id: activity.data["actor"]}) or
|
||||
user.ap_id == activity.data["actor"] or
|
||||
CommonAPI.thread_muted?(user, activity) or user.ap_id == activity.data["actor"] or
|
||||
(activity.data["type"] == "Follow" and
|
||||
Enum.any?(Notification.for_user(user), fn notif ->
|
||||
notif.activity.data["type"] == "Follow" and
|
||||
|
|
|
@ -33,7 +33,22 @@ defmodule Pleroma.Plugs.HTTPSecurityPlug do
|
|||
end
|
||||
|
||||
defp csp_string do
|
||||
protocol = Config.get([Pleroma.Web.Endpoint, :protocol])
|
||||
scheme = Config.get([Pleroma.Web.Endpoint, :url])[:scheme]
|
||||
websocket_url = String.replace(Pleroma.Web.Endpoint.static_url(), "http", "ws")
|
||||
|
||||
connect_src =
|
||||
if Mix.env() == :dev do
|
||||
"connect-src 'self' http://localhost:3035/ " <> websocket_url
|
||||
else
|
||||
"connect-src 'self' " <> websocket_url
|
||||
end
|
||||
|
||||
script_src =
|
||||
if Mix.env() == :dev do
|
||||
"script-src 'self' 'unsafe-eval'"
|
||||
else
|
||||
"script-src 'self'"
|
||||
end
|
||||
|
||||
[
|
||||
"default-src 'none'",
|
||||
|
@ -43,10 +58,10 @@ defmodule Pleroma.Plugs.HTTPSecurityPlug do
|
|||
"media-src 'self' https:",
|
||||
"style-src 'self' 'unsafe-inline'",
|
||||
"font-src 'self'",
|
||||
"script-src 'self'",
|
||||
"connect-src 'self' " <> String.replace(Pleroma.Web.Endpoint.static_url(), "http", "ws"),
|
||||
"manifest-src 'self'",
|
||||
if protocol == "https" do
|
||||
connect_src,
|
||||
script_src,
|
||||
if scheme == "https" do
|
||||
"upgrade-insecure-requests"
|
||||
end
|
||||
]
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.ThreadMute do
|
||||
use Ecto.Schema
|
||||
alias Pleroma.{Repo, User, ThreadMute}
|
||||
require Ecto.Query
|
||||
|
||||
schema "thread_mutes" do
|
||||
belongs_to(:user, User, type: Pleroma.FlakeId)
|
||||
field(:context, :string)
|
||||
end
|
||||
|
||||
def changeset(mute, params \\ %{}) do
|
||||
mute
|
||||
|> Ecto.Changeset.cast(params, [:user_id, :context])
|
||||
|> Ecto.Changeset.foreign_key_constraint(:user_id)
|
||||
|> Ecto.Changeset.unique_constraint(:user_id, name: :unique_index)
|
||||
end
|
||||
|
||||
def query(user_id, context) do
|
||||
user_id = Pleroma.FlakeId.from_string(user_id)
|
||||
|
||||
ThreadMute
|
||||
|> Ecto.Query.where(user_id: ^user_id)
|
||||
|> Ecto.Query.where(context: ^context)
|
||||
end
|
||||
|
||||
def add_mute(user_id, context) do
|
||||
%ThreadMute{}
|
||||
|> changeset(%{user_id: user_id, context: context})
|
||||
|> Repo.insert()
|
||||
end
|
||||
|
||||
def remove_mute(user_id, context) do
|
||||
query(user_id, context)
|
||||
|> Repo.delete_all()
|
||||
end
|
||||
|
||||
def check_muted(user_id, context) do
|
||||
query(user_id, context)
|
||||
|> Repo.all()
|
||||
end
|
||||
end
|
|
@ -25,7 +25,7 @@ defmodule Pleroma.Uploaders.MDII do
|
|||
query = "#{cgi}?#{extension}"
|
||||
|
||||
with {:ok, %{status: 200, body: body}} <-
|
||||
@httpoison.post(query, file_data, adapter: [pool: :default]) do
|
||||
@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}}
|
||||
|
|
|
@ -311,12 +311,12 @@ defmodule Pleroma.User do
|
|||
end
|
||||
end
|
||||
|
||||
@doc "A mass follow for local users. Respects blocks but does not create activities."
|
||||
@doc "A mass follow for local users. Respects blocks in both directions but does not create activities."
|
||||
@spec follow_all(User.t(), list(User.t())) :: {atom(), User.t()}
|
||||
def follow_all(follower, followeds) do
|
||||
followed_addresses =
|
||||
followeds
|
||||
|> Enum.reject(fn %{ap_id: ap_id} -> ap_id in follower.info.blocks end)
|
||||
|> Enum.reject(fn followed -> blocks?(follower, followed) || blocks?(followed, follower) end)
|
||||
|> Enum.map(fn %{follower_address: fa} -> fa end)
|
||||
|
||||
q =
|
||||
|
|
|
@ -12,9 +12,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
|
|||
String.match?(string, pattern)
|
||||
end
|
||||
|
||||
defp check_reject(%{"object" => %{"content" => content}} = message) do
|
||||
defp check_reject(%{"object" => %{"content" => content, "summary" => summary}} = message) do
|
||||
if Enum.any?(Pleroma.Config.get([:mrf_keyword, :reject]), fn pattern ->
|
||||
string_matches?(content, pattern)
|
||||
string_matches?(content, pattern) or string_matches?(summary, pattern)
|
||||
end) do
|
||||
{:reject, nil}
|
||||
else
|
||||
|
@ -22,10 +22,12 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
|
|||
end
|
||||
end
|
||||
|
||||
defp check_ftl_removal(%{"to" => to, "object" => %{"content" => content}} = message) do
|
||||
defp check_ftl_removal(
|
||||
%{"to" => to, "object" => %{"content" => content, "summary" => summary}} = message
|
||||
) do
|
||||
if "https://www.w3.org/ns/activitystreams#Public" in to and
|
||||
Enum.any?(Pleroma.Config.get([:mrf_keyword, :federated_timeline_removal]), fn pattern ->
|
||||
string_matches?(content, pattern)
|
||||
string_matches?(content, pattern) or string_matches?(summary, pattern)
|
||||
end) do
|
||||
to = List.delete(to, "https://www.w3.org/ns/activitystreams#Public")
|
||||
cc = ["https://www.w3.org/ns/activitystreams#Public" | message["cc"] || []]
|
||||
|
@ -41,14 +43,20 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicy do
|
|||
end
|
||||
end
|
||||
|
||||
defp check_replace(%{"object" => %{"content" => content}} = message) do
|
||||
content =
|
||||
Enum.reduce(Pleroma.Config.get([:mrf_keyword, :replace]), content, fn {pattern, replacement},
|
||||
acc ->
|
||||
String.replace(acc, pattern, replacement)
|
||||
defp check_replace(%{"object" => %{"content" => content, "summary" => summary}} = message) do
|
||||
{content, summary} =
|
||||
Enum.reduce(Pleroma.Config.get([:mrf_keyword, :replace]), {content, summary}, fn {pattern,
|
||||
replacement},
|
||||
{content_acc,
|
||||
summary_acc} ->
|
||||
{String.replace(content_acc, pattern, replacement),
|
||||
String.replace(summary_acc, pattern, replacement)}
|
||||
end)
|
||||
|
||||
{:ok, put_in(message["object"]["content"], content)}
|
||||
{:ok,
|
||||
message
|
||||
|> put_in(["object", "content"], content)
|
||||
|> put_in(["object", "summary"], summary)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
|
|
|
@ -7,6 +7,7 @@ defmodule Pleroma.Web.CommonAPI do
|
|||
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
|
||||
|
@ -219,4 +220,27 @@ defmodule Pleroma.Web.CommonAPI do
|
|||
{: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
|
||||
|
|
|
@ -456,6 +456,31 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
end
|
||||
end
|
||||
|
||||
def mute_conversation(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||
activity = Activity.get_by_id(id)
|
||||
|
||||
with {:ok, activity} <- CommonAPI.add_mute(user, activity) do
|
||||
conn
|
||||
|> put_view(StatusView)
|
||||
|> try_render("status.json", %{activity: activity, for: user, as: :activity})
|
||||
else
|
||||
{:error, reason} ->
|
||||
conn
|
||||
|> put_resp_content_type("application/json")
|
||||
|> send_resp(:bad_request, Jason.encode!(%{"error" => reason}))
|
||||
end
|
||||
end
|
||||
|
||||
def unmute_conversation(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||
activity = Activity.get_by_id(id)
|
||||
|
||||
with {:ok, activity} <- CommonAPI.remove_mute(user, activity) 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)
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||
alias Pleroma.HTML
|
||||
alias Pleroma.Repo
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Web.CommonAPI
|
||||
alias Pleroma.Web.CommonAPI.Utils
|
||||
alias Pleroma.Web.MastodonAPI.AccountView
|
||||
alias Pleroma.Web.MastodonAPI.StatusView
|
||||
|
@ -160,7 +161,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||
reblogged: present?(repeated),
|
||||
favourited: present?(favorited),
|
||||
bookmarked: present?(bookmarked),
|
||||
muted: false,
|
||||
muted: CommonAPI.thread_muted?(user, activity),
|
||||
pinned: pinned?(activity, user),
|
||||
sensitive: sensitive,
|
||||
spoiler_text: object["summary"] || "",
|
||||
|
|
|
@ -9,6 +9,13 @@ defmodule Pleroma.Web.RichMedia.Parser do
|
|||
Pleroma.Web.RichMedia.Parsers.OEmbed
|
||||
]
|
||||
|
||||
@hackney_options [
|
||||
pool: :media,
|
||||
timeout: 2_000,
|
||||
recv_timeout: 2_000,
|
||||
max_body: 2_000_000
|
||||
]
|
||||
|
||||
def parse(nil), do: {:error, "No URL provided"}
|
||||
|
||||
if Mix.env() == :test do
|
||||
|
@ -28,7 +35,7 @@ defmodule Pleroma.Web.RichMedia.Parser do
|
|||
|
||||
defp parse_url(url) do
|
||||
try do
|
||||
{:ok, %Tesla.Env{body: html}} = Pleroma.HTTP.get(url, [], adapter: [pool: :media])
|
||||
{:ok, %Tesla.Env{body: html}} = Pleroma.HTTP.get(url, [], adapter: @hackney_options)
|
||||
|
||||
html |> maybe_parse() |> clean_parsed_data() |> check_parsed_data()
|
||||
rescue
|
||||
|
|
|
@ -198,6 +198,8 @@ defmodule Pleroma.Web.Router do
|
|||
post("/statuses/:id/unpin", MastodonAPIController, :unpin_status)
|
||||
post("/statuses/:id/bookmark", MastodonAPIController, :bookmark_status)
|
||||
post("/statuses/:id/unbookmark", MastodonAPIController, :unbookmark_status)
|
||||
post("/statuses/:id/mute", MastodonAPIController, :mute_conversation)
|
||||
post("/statuses/:id/unmute", MastodonAPIController, :unmute_conversation)
|
||||
|
||||
post("/notifications/clear", MastodonAPIController, :clear_notifications)
|
||||
post("/notifications/dismiss", MastodonAPIController, :dismiss_notification)
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
defmodule Pleroma.Repo.Migrations.CreateThreadMutes do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
create table(:thread_mutes) do
|
||||
add :user_id, references(:users, type: :uuid, on_delete: :delete_all)
|
||||
add :context, :string
|
||||
end
|
||||
|
||||
create unique_index(:thread_mutes, [:user_id, :context], name: :unique_index)
|
||||
end
|
||||
end
|
|
@ -55,18 +55,21 @@ defmodule Pleroma.UserTest do
|
|||
followed_two = insert(:user)
|
||||
blocked = insert(:user)
|
||||
not_followed = insert(:user)
|
||||
reverse_blocked = insert(:user)
|
||||
|
||||
{:ok, user} = User.block(user, blocked)
|
||||
{:ok, reverse_blocked} = User.block(reverse_blocked, user)
|
||||
|
||||
{:ok, user} = User.follow(user, followed_zero)
|
||||
|
||||
{:ok, user} = User.follow_all(user, [followed_one, followed_two, blocked])
|
||||
{:ok, user} = User.follow_all(user, [followed_one, followed_two, blocked, reverse_blocked])
|
||||
|
||||
assert User.following?(user, followed_one)
|
||||
assert User.following?(user, followed_two)
|
||||
assert User.following?(user, followed_zero)
|
||||
refute User.following?(user, not_followed)
|
||||
refute User.following?(user, blocked)
|
||||
refute User.following?(user, reverse_blocked)
|
||||
end
|
||||
|
||||
test "follow_all follows mutliple users without duplicating" do
|
||||
|
|
|
@ -12,18 +12,35 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
|
|||
end
|
||||
|
||||
describe "rejecting based on keywords" do
|
||||
test "rejects if string matches" do
|
||||
test "rejects if string matches in content" do
|
||||
Pleroma.Config.put([:mrf_keyword, :reject], ["pun"])
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => %{"content" => "just a daily reminder that compLAINer is a good pun"}
|
||||
"object" => %{
|
||||
"content" => "just a daily reminder that compLAINer is a good pun",
|
||||
"summary" => ""
|
||||
}
|
||||
}
|
||||
|
||||
assert {:reject, nil} == KeywordPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "rejects if regex matches" do
|
||||
test "rejects if string matches in summary" do
|
||||
Pleroma.Config.put([:mrf_keyword, :reject], ["pun"])
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"summary" => "just a daily reminder that compLAINer is a good pun",
|
||||
"content" => ""
|
||||
}
|
||||
}
|
||||
|
||||
assert {:reject, nil} == KeywordPolicy.filter(message)
|
||||
end
|
||||
|
||||
test "rejects if regex matches in content" do
|
||||
Pleroma.Config.put([:mrf_keyword, :reject], [~r/comp[lL][aA][iI][nN]er/])
|
||||
|
||||
assert true ==
|
||||
|
@ -31,7 +48,25 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
|
|||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"content" => "just a daily reminder that #{content} is a good pun"
|
||||
"content" => "just a daily reminder that #{content} is a good pun",
|
||||
"summary" => ""
|
||||
}
|
||||
}
|
||||
|
||||
{:reject, nil} == KeywordPolicy.filter(message)
|
||||
end)
|
||||
end
|
||||
|
||||
test "rejects if regex matches in summary" do
|
||||
Pleroma.Config.put([:mrf_keyword, :reject], [~r/comp[lL][aA][iI][nN]er/])
|
||||
|
||||
assert true ==
|
||||
Enum.all?(["complainer", "compLainer", "compLAiNer", "compLAINer"], fn content ->
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"summary" => "just a daily reminder that #{content} is a good pun",
|
||||
"content" => ""
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,13 +76,16 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
|
|||
end
|
||||
|
||||
describe "delisting from ftl based on keywords" do
|
||||
test "delists if string matches" do
|
||||
test "delists if string matches in content" do
|
||||
Pleroma.Config.put([:mrf_keyword, :federated_timeline_removal], ["pun"])
|
||||
|
||||
message = %{
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"type" => "Create",
|
||||
"object" => %{"content" => "just a daily reminder that compLAINer is a good pun"}
|
||||
"object" => %{
|
||||
"content" => "just a daily reminder that compLAINer is a good pun",
|
||||
"summary" => ""
|
||||
}
|
||||
}
|
||||
|
||||
{:ok, result} = KeywordPolicy.filter(message)
|
||||
|
@ -55,7 +93,24 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
|
|||
refute ["https://www.w3.org/ns/activitystreams#Public"] == result["to"]
|
||||
end
|
||||
|
||||
test "delists if regex matches" do
|
||||
test "delists if string matches in summary" do
|
||||
Pleroma.Config.put([:mrf_keyword, :federated_timeline_removal], ["pun"])
|
||||
|
||||
message = %{
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"type" => "Create",
|
||||
"object" => %{
|
||||
"summary" => "just a daily reminder that compLAINer is a good pun",
|
||||
"content" => ""
|
||||
}
|
||||
}
|
||||
|
||||
{:ok, result} = KeywordPolicy.filter(message)
|
||||
assert ["https://www.w3.org/ns/activitystreams#Public"] == result["cc"]
|
||||
refute ["https://www.w3.org/ns/activitystreams#Public"] == result["to"]
|
||||
end
|
||||
|
||||
test "delists if regex matches in content" do
|
||||
Pleroma.Config.put([:mrf_keyword, :federated_timeline_removal], [~r/comp[lL][aA][iI][nN]er/])
|
||||
|
||||
assert true ==
|
||||
|
@ -64,7 +119,29 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
|
|||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"object" => %{
|
||||
"content" => "just a daily reminder that #{content} is a good pun"
|
||||
"content" => "just a daily reminder that #{content} is a good pun",
|
||||
"summary" => ""
|
||||
}
|
||||
}
|
||||
|
||||
{:ok, result} = KeywordPolicy.filter(message)
|
||||
|
||||
["https://www.w3.org/ns/activitystreams#Public"] == result["cc"] and
|
||||
not (["https://www.w3.org/ns/activitystreams#Public"] == result["to"])
|
||||
end)
|
||||
end
|
||||
|
||||
test "delists if regex matches in summary" do
|
||||
Pleroma.Config.put([:mrf_keyword, :federated_timeline_removal], [~r/comp[lL][aA][iI][nN]er/])
|
||||
|
||||
assert true ==
|
||||
Enum.all?(["complainer", "compLainer", "compLAiNer", "compLAINer"], fn content ->
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"object" => %{
|
||||
"summary" => "just a daily reminder that #{content} is a good pun",
|
||||
"content" => ""
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,20 +154,33 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
|
|||
end
|
||||
|
||||
describe "replacing keywords" do
|
||||
test "replaces keyword if string matches" do
|
||||
test "replaces keyword if string matches in content" do
|
||||
Pleroma.Config.put([:mrf_keyword, :replace], [{"opensource", "free software"}])
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"object" => %{"content" => "ZFS is opensource"}
|
||||
"object" => %{"content" => "ZFS is opensource", "summary" => ""}
|
||||
}
|
||||
|
||||
{:ok, %{"object" => %{"content" => result}}} = KeywordPolicy.filter(message)
|
||||
assert result == "ZFS is free software"
|
||||
end
|
||||
|
||||
test "replaces keyword if regex matches" do
|
||||
test "replaces keyword if string matches in summary" do
|
||||
Pleroma.Config.put([:mrf_keyword, :replace], [{"opensource", "free software"}])
|
||||
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"object" => %{"summary" => "ZFS is opensource", "content" => ""}
|
||||
}
|
||||
|
||||
{:ok, %{"object" => %{"summary" => result}}} = KeywordPolicy.filter(message)
|
||||
assert result == "ZFS is free software"
|
||||
end
|
||||
|
||||
test "replaces keyword if regex matches in content" do
|
||||
Pleroma.Config.put([:mrf_keyword, :replace], [
|
||||
{~r/open(-|\s)?source\s?(software)?/, "free software"}
|
||||
])
|
||||
|
@ -100,12 +190,30 @@ defmodule Pleroma.Web.ActivityPub.MRF.KeywordPolicyTest do
|
|||
message = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"object" => %{"content" => "ZFS is #{content}"}
|
||||
"object" => %{"content" => "ZFS is #{content}", "summary" => ""}
|
||||
}
|
||||
|
||||
{:ok, %{"object" => %{"content" => result}}} = KeywordPolicy.filter(message)
|
||||
result == "ZFS is free software"
|
||||
end)
|
||||
end
|
||||
|
||||
test "replaces keyword if regex matches in summary" do
|
||||
Pleroma.Config.put([:mrf_keyword, :replace], [
|
||||
{~r/open(-|\s)?source\s?(software)?/, "free software"}
|
||||
])
|
||||
|
||||
assert true ==
|
||||
Enum.all?(["opensource", "open-source", "open source"], fn content ->
|
||||
message = %{
|
||||
"type" => "Create",
|
||||
"to" => ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"object" => %{"summary" => "ZFS is #{content}", "content" => ""}
|
||||
}
|
||||
|
||||
{:ok, %{"object" => %{"summary" => result}}} = KeywordPolicy.filter(message)
|
||||
result == "ZFS is free software"
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -164,4 +164,30 @@ defmodule Pleroma.Web.CommonAPI.Test do
|
|||
assert %User{info: %{pinned_activities: []}} = user
|
||||
end
|
||||
end
|
||||
|
||||
describe "mute tests" do
|
||||
setup do
|
||||
user = insert(:user)
|
||||
|
||||
activity = insert(:note_activity)
|
||||
|
||||
[user: user, activity: activity]
|
||||
end
|
||||
|
||||
test "add mute", %{user: user, activity: activity} do
|
||||
{:ok, _} = CommonAPI.add_mute(user, activity)
|
||||
assert CommonAPI.thread_muted?(user, activity)
|
||||
end
|
||||
|
||||
test "remove mute", %{user: user, activity: activity} do
|
||||
CommonAPI.add_mute(user, activity)
|
||||
{:ok, _} = CommonAPI.remove_mute(user, activity)
|
||||
refute CommonAPI.thread_muted?(user, activity)
|
||||
end
|
||||
|
||||
test "check that mutes can't be duplicate", %{user: user, activity: activity} do
|
||||
CommonAPI.add_mute(user, activity)
|
||||
{:error, _} = CommonAPI.add_mute(user, activity)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1749,4 +1749,36 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
|
|||
|
||||
assert [json_response(response2, 200)] == json_response(bookmarks, 200)
|
||||
end
|
||||
|
||||
describe "conversation muting" do
|
||||
setup do
|
||||
user = insert(:user)
|
||||
{:ok, activity} = CommonAPI.post(user, %{"status" => "HIE"})
|
||||
|
||||
[user: user, activity: activity]
|
||||
end
|
||||
|
||||
test "mute conversation", %{conn: conn, user: user, activity: activity} do
|
||||
id_str = to_string(activity.id)
|
||||
|
||||
assert %{"id" => ^id_str, "muted" => true} =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> post("/api/v1/statuses/#{activity.id}/mute")
|
||||
|> json_response(200)
|
||||
end
|
||||
|
||||
test "unmute conversation", %{conn: conn, user: user, activity: activity} do
|
||||
{:ok, _} = CommonAPI.add_mute(user, activity)
|
||||
|
||||
id_str = to_string(activity.id)
|
||||
user = refresh_record(user)
|
||||
|
||||
assert %{"id" => ^id_str, "muted" => false} =
|
||||
conn
|
||||
|> assign(:user, user)
|
||||
|> post("/api/v1/statuses/#{activity.id}/unmute")
|
||||
|> json_response(200)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue