diff --git a/CONFIGURATION.md b/CONFIGURATION.md new file mode 100644 index 000000000..4174dd114 --- /dev/null +++ b/CONFIGURATION.md @@ -0,0 +1,72 @@ +# Configuring Pleroma + +In the `config/` directory, you will find the following relevant files: + +* `config.exs`: default base configuration +* `dev.exs`: default additional configuration for `MIX_ENV=dev` +* `prod.exs`: default additional configuration for `MIX_ENV=prod` + + +Do not modify files in the list above. +Instead, overload the settings by editing the following files: + +* `dev.secret.exs`: custom additional configuration for `MIX_ENV=dev` +* `prod.secret.exs`: custom additional configuration for `MIX_ENV=prod` + +## Message Rewrite Filters (MRFs) + +Modify incoming and outgoing posts. + + config :pleroma, :instance, + rewrite_policy: Pleroma.Web.ActivityPub.MRF.NoOpPolicy + +`rewrite_policy` specifies which MRF policies to apply. +It can either be a single policy or a list of policies. +Currently, MRFs availible by default are: + +* `Pleroma.Web.ActivityPub.MRF.NoOpPolicy` +* `Pleroma.Web.ActivityPub.MRF.DropPolicy` +* `Pleroma.Web.ActivityPub.MRF.SimplePolicy` +* `Pleroma.Web.ActivityPub.MRF.RejectNonPublic` + +Some policies, such as SimplePolicy and RejectNonPublic, +can be additionally configured in their respective sections. + +### NoOpPolicy + +Does not modify posts (this is the default `rewrite_policy`) + +### DropPolicy + +Drops all posts. +It generally does not make sense to use this in production. + +### SimplePolicy + +Restricts the visibility of posts from certain instances. + + config :pleroma, :mrf_simple, + media_removal: [], + media_nsfw: [], + federated_timeline_removal: [], + reject: [] + +* `media_removal`: posts from these instances will have attachments + removed +* `media_nsfw`: posts from these instances will have attachments marked + as nsfw +* `federated_timeline_removal`: posts from these instances will be + marked as unlisted +* `reject`: posts from these instances will be dropped + +### RejectNonPublic + +Drops posts with non-public visibility settings. + + config :pleroma :mrf_rejectnonpublic + allow_followersonly: false, + allow_direct: false, + +* `allow_followersonly`: whether to allow follower-only posts through + the filter +* `allow_direct`: whether to allow direct messages through the filter diff --git a/config/config.exs b/config/config.exs index b8dd867c4..e1a77d3e1 100644 --- a/config/config.exs +++ b/config/config.exs @@ -64,6 +64,10 @@ config :pleroma, :user, deny_follow_blocked: true +config :pleroma, :mrf_rejectnonpublic, + allow_followersonly: false, + allow_direct: false + config :pleroma, :mrf_simple, media_removal: [], media_nsfw: [], diff --git a/installation/pleroma.nginx b/installation/pleroma.nginx index 42323dd95..e9eeb1848 100644 --- a/installation/pleroma.nginx +++ b/installation/pleroma.nginx @@ -24,18 +24,27 @@ server { # } } +# Enable SSL session caching for improved performance +ssl_session_cache shared:ssl_session_cache:10m; + server { listen 443 ssl http2; - ssl on; ssl_session_timeout 5m; + ssl_trusted_certificate /etc/letsencrypt/live/example.tld/fullchain.pem; ssl_certificate /etc/letsencrypt/live/example.tld/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.tld/privkey.pem; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES"; + # Add TLSv1.0 to support older devices + ssl_protocols TLSv1.2; + # Uncomment line below if you want to support older devices (Before Android 4.4.2, IE 8, etc.) + # ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES"; + ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; ssl_prefer_server_ciphers on; - + ssl_ecdh_curve X25519:prime256v1:secp384r1:secp521r1; + ssl_stapling on; + ssl_stapling_verify on; + server_name example.tld; gzip_vary on; diff --git a/lib/mix/tasks/make_moderator.ex b/lib/mix/tasks/make_moderator.ex index 20f04c54c..a454a958e 100644 --- a/lib/mix/tasks/make_moderator.ex +++ b/lib/mix/tasks/make_moderator.ex @@ -5,7 +5,7 @@ defmodule Mix.Tasks.SetModerator do @shortdoc "Set moderator status" def run([nickname | rest]) do - ensure_started(Repo, []) + Application.ensure_all_started(:pleroma) moderator = case rest do @@ -19,7 +19,7 @@ def run([nickname | rest]) do |> Map.put("is_moderator", !!moderator) cng = User.info_changeset(user, %{info: info}) - user = Repo.update!(cng) + {:ok, user} = User.update_and_set_cache(cng) IO.puts("Moderator status of #{nickname}: #{user.info["is_moderator"]}") else diff --git a/lib/mix/tasks/sample_config.eex b/lib/mix/tasks/sample_config.eex index e37c864c0..6db36fa09 100644 --- a/lib/mix/tasks/sample_config.eex +++ b/lib/mix/tasks/sample_config.eex @@ -8,7 +8,8 @@ config :pleroma, :instance, name: "<%= name %>", email: "<%= email %>", limit: 5000, - registrations_open: true + registrations_open: true, + dedupe_media: false config :pleroma, :media_proxy, enabled: false, diff --git a/lib/mix/tasks/set_locked.ex b/lib/mix/tasks/set_locked.ex new file mode 100644 index 000000000..2b3b18b09 --- /dev/null +++ b/lib/mix/tasks/set_locked.ex @@ -0,0 +1,30 @@ +defmodule Mix.Tasks.SetLocked do + use Mix.Task + import Mix.Ecto + alias Pleroma.{Repo, User} + + @shortdoc "Set locked status" + def run([nickname | rest]) do + ensure_started(Repo, []) + + locked = + case rest do + [locked] -> locked == "true" + _ -> true + end + + with %User{local: true} = user <- User.get_by_nickname(nickname) do + info = + user.info + |> Map.put("locked", !!locked) + + cng = User.info_changeset(user, %{info: info}) + user = Repo.update!(cng) + + IO.puts("locked status of #{nickname}: #{user.info["locked"]}") + else + _ -> + IO.puts("No local user #{nickname}") + end + end +end diff --git a/lib/pleroma/list.ex b/lib/pleroma/list.ex index 9d0b9285b..53d98665b 100644 --- a/lib/pleroma/list.ex +++ b/lib/pleroma/list.ex @@ -1,7 +1,7 @@ defmodule Pleroma.List do use Ecto.Schema import Ecto.{Changeset, Query} - alias Pleroma.{User, Repo} + alias Pleroma.{User, Repo, Activity} schema "lists" do belongs_to(:user, Pleroma.User) @@ -56,6 +56,19 @@ def get_following(%Pleroma.List{following: following} = list) do {:ok, Repo.all(q)} end + # Get lists the activity should be streamed to. + def get_lists_from_activity(%Activity{actor: ap_id}) do + actor = User.get_cached_by_ap_id(ap_id) + + query = + from( + l in Pleroma.List, + where: fragment("? && ?", l.following, ^[actor.follower_address]) + ) + + Repo.all(query) + end + def rename(%Pleroma.List{} = list, title) do list |> title_changeset(%{title: title}) diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex index e5df94009..43df0d418 100644 --- a/lib/pleroma/upload.ex +++ b/lib/pleroma/upload.ex @@ -2,20 +2,21 @@ defmodule Pleroma.Upload do alias Ecto.UUID alias Pleroma.Web - def store(%Plug.Upload{} = file) do - uuid = UUID.generate() - upload_folder = Path.join(upload_path(), uuid) - File.mkdir_p!(upload_folder) - result_file = Path.join(upload_folder, file.filename) - File.cp!(file.path, result_file) + def store(%Plug.Upload{} = file, should_dedupe) do + content_type = get_content_type(file.path) + uuid = get_uuid(file, should_dedupe) + name = get_name(file, uuid, content_type, should_dedupe) + upload_folder = get_upload_path(uuid, should_dedupe) + url_path = get_url(name, uuid, should_dedupe) - # fix content type on some image uploads - content_type = - if file.content_type in [nil, "application/octet-stream"] do - get_content_type(file.path) - else - file.content_type - end + File.mkdir_p!(upload_folder) + result_file = Path.join(upload_folder, name) + + if File.exists?(result_file) do + File.rm!(file.path) + else + File.cp!(file.path, result_file) + end %{ "type" => "Image", @@ -23,26 +24,48 @@ def store(%Plug.Upload{} = file) do %{ "type" => "Link", "mediaType" => content_type, - "href" => url_for(Path.join(uuid, :cow_uri.urlencode(file.filename))) + "href" => url_path } ], - "name" => file.filename, - "uuid" => uuid + "name" => name } end - def store(%{"img" => "data:image/" <> image_data}) do + def store(%{"img" => "data:image/" <> image_data}, should_dedupe) do parsed = Regex.named_captures(~r/(?jpeg|png|gif);base64,(?.*)/, image_data) - data = Base.decode64!(parsed["data"]) + data = Base.decode64!(parsed["data"], ignore: :whitespace) uuid = UUID.generate() - upload_folder = Path.join(upload_path(), uuid) + uuidpath = Path.join(upload_path(), uuid) + uuid = UUID.generate() + + File.mkdir_p!(upload_path()) + + File.write!(uuidpath, data) + + content_type = get_content_type(uuidpath) + + name = + create_name( + String.downcase(Base.encode16(:crypto.hash(:sha256, data))), + parsed["filetype"], + content_type + ) + + upload_folder = get_upload_path(uuid, should_dedupe) + url_path = get_url(name, uuid, should_dedupe) + File.mkdir_p!(upload_folder) - filename = Base.encode16(:crypto.hash(:sha256, data)) <> ".#{parsed["filetype"]}" - result_file = Path.join(upload_folder, filename) + result_file = Path.join(upload_folder, name) - File.write!(result_file, data) - - content_type = "image/#{parsed["filetype"]}" + if should_dedupe do + if !File.exists?(result_file) do + File.rename(uuidpath, result_file) + else + File.rm!(uuidpath) + end + else + File.rename(uuidpath, result_file) + end %{ "type" => "Image", @@ -50,11 +73,10 @@ def store(%{"img" => "data:image/" <> image_data}) do %{ "type" => "Link", "mediaType" => content_type, - "href" => url_for(Path.join(uuid, :cow_uri.urlencode(filename))) + "href" => url_path } ], - "name" => filename, - "uuid" => uuid + "name" => name } end @@ -63,6 +85,65 @@ def upload_path do Keyword.fetch!(settings, :uploads) end + defp create_name(uuid, ext, type) do + case type do + "application/octet-stream" -> + String.downcase(Enum.join([uuid, ext], ".")) + + "audio/mpeg" -> + String.downcase(Enum.join([uuid, "mp3"], ".")) + + _ -> + String.downcase(Enum.join([uuid, List.last(String.split(type, "/"))], ".")) + end + end + + defp get_uuid(file, should_dedupe) do + if should_dedupe do + Base.encode16(:crypto.hash(:sha256, File.read!(file.path))) + else + UUID.generate() + end + end + + defp get_name(file, uuid, type, should_dedupe) do + if should_dedupe do + create_name(uuid, List.last(String.split(file.filename, ".")), type) + else + unless String.contains?(file.filename, ".") do + case type do + "image/png" -> file.filename <> ".png" + "image/jpeg" -> file.filename <> ".jpg" + "image/gif" -> file.filename <> ".gif" + "video/webm" -> file.filename <> ".webm" + "video/mp4" -> file.filename <> ".mp4" + "audio/mpeg" -> file.filename <> ".mp3" + "audio/ogg" -> file.filename <> ".ogg" + "audio/wav" -> file.filename <> ".wav" + _ -> file.filename + end + else + file.filename + end + end + end + + defp get_upload_path(uuid, should_dedupe) do + if should_dedupe do + upload_path() + else + Path.join(upload_path(), uuid) + end + end + + defp get_url(name, uuid, should_dedupe) do + if should_dedupe do + url_for(:cow_uri.urlencode(name)) + else + url_for(Path.join(uuid, :cow_uri.urlencode(name))) + end + end + defp url_for(file) do "#{Web.base_url()}/media/#{file}" end @@ -89,6 +170,9 @@ def get_content_type(file) do <<0x49, 0x44, 0x33, _, _, _, _, _>> -> "audio/mpeg" + <<255, 251, _, 68, 0, 0, 0, 0>> -> + "audio/mpeg" + <<0x4F, 0x67, 0x67, 0x53, 0x00, 0x02, 0x00, 0x00>> -> "audio/ogg" diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index dd645b2e5..1fcec479f 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -201,6 +201,14 @@ def maybe_direct_follow(%User{} = follower, %User{info: info} = followed) do end end + def maybe_follow(%User{} = follower, %User{info: info} = followed) do + if not following?(follower, followed) do + follow(follower, followed) + else + {:ok, follower} + end + end + @user_config Application.get_env(:pleroma, :user) @deny_follow_blocked Keyword.get(@user_config, :deny_follow_blocked) @@ -259,6 +267,10 @@ def following?(%User{} = follower, %User{} = followed) do Enum.member?(follower.following, followed.follower_address) end + def locked?(%User{} = user) do + user.info["locked"] || false + end + def get_by_ap_id(ap_id) do Repo.get_by(User, ap_id: ap_id) end @@ -356,6 +368,40 @@ def get_friends(user) do {:ok, Repo.all(q)} end + def get_follow_requests_query(%User{} = user) do + from( + a in Activity, + where: + fragment( + "? ->> 'type' = 'Follow'", + a.data + ), + where: + fragment( + "? ->> 'state' = 'pending'", + a.data + ), + where: + fragment( + "? @> ?", + a.data, + ^%{"object" => user.ap_id} + ) + ) + end + + def get_follow_requests(%User{} = user) do + q = get_follow_requests_query(user) + reqs = Repo.all(q) + + users = + Enum.map(reqs, fn req -> req.actor end) + |> Enum.uniq() + |> Enum.map(fn ap_id -> get_by_ap_id(ap_id) end) + + {:ok, users} + end + def increase_note_count(%User{} = user) do note_count = (user.info["note_count"] || 0) + 1 new_info = Map.put(user.info, "note_count", note_count) @@ -486,7 +532,31 @@ def unblock(user, %{ap_id: ap_id}) do def blocks?(user, %{ap_id: ap_id}) do blocks = user.info["blocks"] || [] - Enum.member?(blocks, ap_id) + domain_blocks = user.info["domain_blocks"] || [] + %{host: host} = URI.parse(ap_id) + + Enum.member?(blocks, ap_id) || + Enum.any?(domain_blocks, fn domain -> + host == domain + end) + end + + def block_domain(user, domain) do + domain_blocks = user.info["domain_blocks"] || [] + new_blocks = Enum.uniq([domain | domain_blocks]) + new_info = Map.put(user.info, "domain_blocks", new_blocks) + + cs = User.info_changeset(user, %{info: new_info}) + update_and_set_cache(cs) + end + + def unblock_domain(user, domain) do + blocks = user.info["domain_blocks"] || [] + new_blocks = List.delete(blocks, domain) + new_info = Map.put(user.info, "domain_blocks", new_blocks) + + cs = User.info_changeset(user, %{info: new_info}) + update_and_set_cache(cs) end def local_user_query() do diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index a12bd5b58..b174af7ce 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -57,6 +57,7 @@ def stream_out(activity) do if activity.data["type"] in ["Create", "Announce"] do Pleroma.Web.Streamer.stream("user", activity) + Pleroma.Web.Streamer.stream("list", activity) if Enum.member?(activity.data["to"], public) do Pleroma.Web.Streamer.stream("public", activity) @@ -198,7 +199,7 @@ def unannounce( :ok <- maybe_federate(unannounce_activity), {:ok, _activity} <- Repo.delete(announce_activity), {:ok, object} <- remove_announce_from_object(announce_activity, object) do - {:ok, unannounce_activity, announce_activity, object} + {:ok, unannounce_activity, object} else _e -> {:ok, object} end @@ -214,6 +215,7 @@ def follow(follower, followed, activity_id \\ nil, local \\ true) do def unfollow(follower, followed, activity_id \\ nil, local \\ true) do with %Activity{} = follow_activity <- fetch_latest_follow(follower, followed), + {:ok, follow_activity} <- update_follow_state(follow_activity, "cancelled"), unfollow_data <- make_unfollow_data(follower, followed, follow_activity, activity_id), {:ok, activity} <- insert(unfollow_data, local), :ok <- maybe_federate(activity) do @@ -449,11 +451,13 @@ defp restrict_recent(query, _) do defp restrict_blocked(query, %{"blocking_user" => %User{info: info}}) do blocks = info["blocks"] || [] + domain_blocks = info["domain_blocks"] || [] from( activity in query, where: fragment("not (? = ANY(?))", activity.actor, ^blocks), - where: fragment("not (?->'to' \\?| ?)", activity.data, ^blocks) + where: fragment("not (?->'to' \\?| ?)", activity.data, ^blocks), + where: fragment("not (split_part(?, '/', 3) = ANY(?))", activity.actor, ^domain_blocks) ) end @@ -502,7 +506,7 @@ def fetch_activities(recipients, opts \\ %{}) do end def upload(file) do - data = Upload.store(file) + data = Upload.store(file, Application.get_env(:pleroma, :instance)[:dedupe_media]) Repo.insert(%Object{data: data}) end diff --git a/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex b/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex index 879cbe6de..b6936fe90 100644 --- a/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex +++ b/lib/pleroma/web/activity_pub/mrf/reject_non_public.ex @@ -2,6 +2,10 @@ defmodule Pleroma.Web.ActivityPub.MRF.RejectNonPublic do alias Pleroma.User @behaviour Pleroma.Web.ActivityPub.MRF + @mrf_rejectnonpublic Application.get_env(:pleroma, :mrf_rejectnonpublic) + @allow_followersonly Keyword.get(@mrf_rejectnonpublic, :allow_followersonly) + @allow_direct Keyword.get(@mrf_rejectnonpublic, :allow_direct) + @impl true def filter(object) do if object["type"] == "Create" do @@ -18,9 +22,25 @@ def filter(object) do end case visibility do - "public" -> {:ok, object} - "unlisted" -> {:ok, object} - _ -> {:reject, nil} + "public" -> + {:ok, object} + + "unlisted" -> + {:ok, object} + + "followers" -> + with true <- @allow_followersonly do + {:ok, object} + else + _e -> {:reject, nil} + end + + "direct" -> + with true <- @allow_direct do + {:ok, object} + else + _e -> {:reject, nil} + end end else {:ok, object} diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 75ba36729..300e0fcdd 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -30,14 +30,19 @@ def fix_in_reply_to(%{"inReplyTo" => in_reply_to_id} = object) when not is_nil(in_reply_to_id) do case ActivityPub.fetch_object_from_id(in_reply_to_id) do {:ok, replied_object} -> - activity = Activity.get_create_activity_by_object_ap_id(replied_object.data["id"]) - - object - |> Map.put("inReplyTo", replied_object.data["id"]) - |> Map.put("inReplyToAtomUri", object["inReplyToAtomUri"] || in_reply_to_id) - |> Map.put("inReplyToStatusId", activity.id) - |> Map.put("conversation", replied_object.data["context"] || object["conversation"]) - |> Map.put("context", replied_object.data["context"] || object["conversation"]) + with %Activity{} = activity <- + Activity.get_create_activity_by_object_ap_id(replied_object.data["id"]) do + object + |> Map.put("inReplyTo", replied_object.data["id"]) + |> Map.put("inReplyToAtomUri", object["inReplyToAtomUri"] || in_reply_to_id) + |> Map.put("inReplyToStatusId", activity.id) + |> Map.put("conversation", replied_object.data["context"] || object["conversation"]) + |> Map.put("context", replied_object.data["context"] || object["conversation"]) + else + e -> + Logger.error("Couldn't fetch #{object["inReplyTo"]} #{inspect(e)}") + object + end e -> Logger.error("Couldn't fetch #{object["inReplyTo"]} #{inspect(e)}") @@ -137,9 +142,17 @@ def handle_incoming( with %User{local: true} = followed <- User.get_cached_by_ap_id(followed), %User{} = follower <- User.get_or_fetch_by_ap_id(follower), {:ok, activity} <- ActivityPub.follow(follower, followed, id, false) do - ActivityPub.accept(%{to: [follower.ap_id], actor: followed.ap_id, object: data, local: true}) + if not User.locked?(followed) do + ActivityPub.accept(%{ + to: [follower.ap_id], + actor: followed.ap_id, + object: data, + local: true + }) + + User.follow(follower, followed) + end - User.follow(follower, followed) {:ok, activity} else _e -> :error @@ -252,7 +265,7 @@ def handle_incoming( {:ok, new_user_data} = ActivityPub.user_data_from_user_object(object) banner = new_user_data[:info]["banner"] - locked = new_user_data[:info]["locked"] + locked = new_user_data[:info]["locked"] || false update_data = new_user_data @@ -304,7 +317,7 @@ def handle_incoming( with %User{} = actor <- User.get_or_fetch_by_ap_id(actor), {:ok, object} <- get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id), - {:ok, activity, _, _} <- ActivityPub.unannounce(actor, object, id, false) do + {:ok, activity, _} <- ActivityPub.unannounce(actor, object, id, false) do {:ok, activity} else _e -> :error @@ -432,6 +445,58 @@ def prepare_outgoing(%{"type" => "Create", "object" => %{"type" => "Note"} = obj {:ok, data} end + # Mastodon Accept/Reject requires a non-normalized object containing the actor URIs, + # because of course it does. + def prepare_outgoing(%{"type" => "Accept"} = data) do + follow_activity_id = + 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 = %{ + "actor" => follow_activity.actor, + "object" => follow_activity.data["object"], + "id" => follow_activity.data["id"], + "type" => "Follow" + } + + data = + data + |> Map.put("object", object) + |> Map.put("@context", "https://www.w3.org/ns/activitystreams") + + {:ok, data} + end + end + + def prepare_outgoing(%{"type" => "Reject"} = data) do + follow_activity_id = + 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 = %{ + "actor" => follow_activity.actor, + "object" => follow_activity.data["object"], + "id" => follow_activity.data["id"], + "type" => "Follow" + } + + data = + data + |> Map.put("object", object) + |> Map.put("@context", "https://www.w3.org/ns/activitystreams") + + {:ok, data} + end + end + def prepare_outgoing(%{"type" => _type} = data) do data = data diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index 56b80a8db..64329b710 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -4,6 +4,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do alias Pleroma.Web.Endpoint alias Ecto.{Changeset, UUID} import Ecto.Query + require Logger # Some implementations send the actor URI as the actor field, others send the entire actor object, # so figure out what the actor's URI is based on what we have. @@ -216,10 +217,27 @@ def remove_like_from_object(%Activity{data: %{"actor" => actor}}, object) do #### Follow-related helpers + @doc """ + Updates a follow activity's state (for locked accounts). + """ + def update_follow_state(%Activity{} = activity, state) do + with new_data <- + activity.data + |> Map.put("state", state), + changeset <- Changeset.change(activity, data: new_data), + {:ok, activity} <- Repo.update(changeset) do + {:ok, activity} + end + end + @doc """ Makes a follow activity data for the given follower and followed """ - def make_follow_data(%User{ap_id: follower_id}, %User{ap_id: followed_id}, activity_id) do + def make_follow_data( + %User{ap_id: follower_id}, + %User{ap_id: followed_id} = followed, + activity_id + ) do data = %{ "type" => "Follow", "actor" => follower_id, @@ -228,7 +246,10 @@ def make_follow_data(%User{ap_id: follower_id}, %User{ap_id: followed_id}, activ "object" => followed_id } - if activity_id, do: Map.put(data, "id", activity_id), else: data + data = if activity_id, do: Map.put(data, "id", activity_id), else: data + data = if User.locked?(followed), do: Map.put(data, "state", "pending"), else: data + + data end def fetch_latest_follow(%User{ap_id: follower_id}, %User{ap_id: followed_id}) do diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 974da5203..8a8d1e050 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -4,6 +4,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do alias Pleroma.Web alias Pleroma.Web.MastodonAPI.{StatusView, AccountView, MastodonView, ListView} alias Pleroma.Web.ActivityPub.ActivityPub + alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.{CommonAPI, OStatus} alias Pleroma.Web.OAuth.{Authorization, Token, App} alias Comeonin.Pbkdf2 @@ -71,6 +72,20 @@ def update_credentials(%{assigns: %{user: user}} = conn, params) do user end + user = + if locked = params["locked"] do + with locked <- locked == "true", + new_info <- Map.put(user.info, "locked", locked), + 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), {:ok, user} <- User.update_and_set_cache(changeset) do if original_user != user do @@ -345,7 +360,7 @@ def reblog_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do end def unreblog_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do - with {:ok, _, _, %{data: %{"id" => id}}} <- CommonAPI.unrepeat(ap_id_or_id, user), + with {:ok, _unannounce, %{data: %{"id" => id}}} <- CommonAPI.unrepeat(ap_id_or_id, user), %Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id) do render(conn, StatusView, "status.json", %{activity: activity, for: user, as: :activity}) end @@ -476,6 +491,53 @@ def following(conn, %{"id" => id}) do end end + def follow_requests(%{assigns: %{user: followed}} = conn, _params) do + with {:ok, follow_requests} <- User.get_follow_requests(followed) do + render(conn, AccountView, "accounts.json", %{users: follow_requests, as: :user}) + end + end + + def authorize_follow_request(%{assigns: %{user: followed}} = conn, %{"id" => id}) do + with %User{} = follower <- Repo.get(User, id), + {:ok, follower} <- User.maybe_follow(follower, followed), + %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed), + {:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "accept"), + {:ok, _activity} <- + ActivityPub.accept(%{ + to: [follower.ap_id], + actor: followed.ap_id, + object: follow_activity.data["id"], + type: "Accept" + }) do + render(conn, AccountView, "relationship.json", %{user: followed, target: follower}) + else + {:error, message} -> + conn + |> put_resp_content_type("application/json") + |> send_resp(403, Jason.encode!(%{"error" => message})) + end + end + + def reject_follow_request(%{assigns: %{user: followed}} = conn, %{"id" => id}) do + with %User{} = follower <- Repo.get(User, id), + %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed), + {:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "reject"), + {:ok, _activity} <- + ActivityPub.reject(%{ + to: [follower.ap_id], + actor: followed.ap_id, + object: follow_activity.data["id"], + type: "Reject" + }) do + render(conn, AccountView, "relationship.json", %{user: followed, target: follower}) + else + {:error, message} -> + conn + |> put_resp_content_type("application/json") + |> send_resp(403, Jason.encode!(%{"error" => message})) + end + end + def follow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do with %User{} = followed <- Repo.get(User, id), {:ok, follower} <- User.maybe_direct_follow(follower, followed), @@ -545,6 +607,20 @@ def blocks(%{assigns: %{user: user}} = conn, _) do end end + def domain_blocks(%{assigns: %{user: %{info: info}}} = conn, _) do + json(conn, info["domain_blocks"] || []) + end + + def block_domain(%{assigns: %{user: blocker}} = conn, %{"domain" => domain}) do + User.block_domain(blocker, domain) + json(conn, %{}) + end + + def unblock_domain(%{assigns: %{user: blocker}} = conn, %{"domain" => domain}) do + User.unblock_domain(blocker, domain) + json(conn, %{}) + end + def search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do accounts = User.search(query, params["resolve"] == "true") diff --git a/lib/pleroma/web/mastodon_api/mastodon_socket.ex b/lib/pleroma/web/mastodon_api/mastodon_socket.ex index 080f62b31..46648c366 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_socket.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_socket.ex @@ -15,10 +15,13 @@ def connect(params, socket) do with token when not is_nil(token) <- params["access_token"], %Token{user_id: user_id} <- Repo.get_by(Token, token: token), %User{} = user <- Repo.get(User, user_id), - stream when stream in ["public", "public:local", "user", "direct"] <- params["stream"] do + stream when stream in ["public", "public:local", "user", "direct", "list"] <- + params["stream"] do + topic = if stream == "list", do: "list:#{params["list"]}", else: stream + socket = socket - |> assign(:topic, params["stream"]) + |> assign(:topic, topic) |> assign(:user, user) Pleroma.Web.Streamer.add_socket(params["stream"], socket) diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index d1d48cd0a..59898457b 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -125,8 +125,8 @@ def render("status.json", %{activity: %{data: %{"object" => object}} = activity} uri: object["id"], url: object["external_url"] || object["id"], account: AccountView.render("account.json", %{user: user}), - in_reply_to_id: reply_to && reply_to.id, - in_reply_to_account_id: reply_to_user && reply_to_user.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), reblog: nil, content: HtmlSanitizeEx.basic_html(object["content"]), created_at: created_at, diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex index 3dd87d0ab..a5fb32a4e 100644 --- a/lib/pleroma/web/oauth/oauth_controller.ex +++ b/lib/pleroma/web/oauth/oauth_controller.ex @@ -81,10 +81,10 @@ def token_exchange(conn, %{"grant_type" => "authorization_code"} = params) do # - investigate a way to verify the user wants to grant read/write/follow once scope handling is done def token_exchange( conn, - %{"grant_type" => "password", "name" => name, "password" => password} = params + %{"grant_type" => "password", "username" => name, "password" => password} = params ) do with %App{} = app <- get_app_from_request(conn, params), - %User{} = user <- User.get_cached_by_nickname(name), + %User{} = user <- User.get_by_nickname_or_email(name), true <- Pbkdf2.checkpw(password, user.password_hash), {:ok, auth} <- Authorization.create_authorization(app, user), {:ok, token} <- Token.exchange_token(app, auth) do @@ -104,6 +104,18 @@ def token_exchange( end end + def token_exchange( + conn, + %{"grant_type" => "password", "name" => name, "password" => password} = params + ) do + params = + params + |> Map.delete("name") + |> Map.put("username", name) + + token_exchange(conn, params) + end + defp fix_padding(token) do token |> Base.url_decode64!(padding: false) diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 924254895..13bd393ab 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -41,7 +41,7 @@ def user_fetcher(username) do end pipeline :well_known do - plug(:accepts, ["xml", "xrd+xml", "json", "jrd+json"]) + plug(:accepts, ["json", "jrd+json", "xml", "xrd+xml"]) end pipeline :config do @@ -97,12 +97,14 @@ def user_fetcher(username) do post("/accounts/:id/mute", MastodonAPIController, :relationship_noop) post("/accounts/:id/unmute", MastodonAPIController, :relationship_noop) + get("/follow_requests", MastodonAPIController, :follow_requests) + post("/follow_requests/:id/authorize", MastodonAPIController, :authorize_follow_request) + post("/follow_requests/:id/reject", MastodonAPIController, :reject_follow_request) + post("/follows", MastodonAPIController, :follow) get("/blocks", MastodonAPIController, :blocks) - get("/domain_blocks", MastodonAPIController, :empty_array) - get("/follow_requests", MastodonAPIController, :empty_array) get("/mutes", MastodonAPIController, :empty_array) get("/timelines/home", MastodonAPIController, :home_timeline) @@ -134,6 +136,10 @@ def user_fetcher(username) do get("/lists/:id/accounts", MastodonAPIController, :list_accounts) post("/lists/:id/accounts", MastodonAPIController, :add_to_list) delete("/lists/:id/accounts", MastodonAPIController, :remove_from_list) + + get("/domain_blocks", MastodonAPIController, :domain_blocks) + post("/domain_blocks", MastodonAPIController, :block_domain) + delete("/domain_blocks", MastodonAPIController, :unblock_domain) end scope "/api/web", Pleroma.Web.MastodonAPI do @@ -238,8 +244,13 @@ def user_fetcher(username) do post("/statuses/update", TwitterAPI.Controller, :status_update) post("/statuses/retweet/:id", TwitterAPI.Controller, :retweet) + post("/statuses/unretweet/:id", TwitterAPI.Controller, :unretweet) post("/statuses/destroy/:id", TwitterAPI.Controller, :delete_post) + get("/pleroma/friend_requests", TwitterAPI.Controller, :friend_requests) + post("/pleroma/friendships/approve", TwitterAPI.Controller, :approve_friend_request) + post("/pleroma/friendships/deny", TwitterAPI.Controller, :deny_friend_request) + post("/friendships/create", TwitterAPI.Controller, :follow) post("/friendships/destroy", TwitterAPI.Controller, :unfollow) post("/blocks/create", TwitterAPI.Controller, :block) diff --git a/lib/pleroma/web/streamer.ex b/lib/pleroma/web/streamer.ex index 6ed9035fb..ce38f3cc3 100644 --- a/lib/pleroma/web/streamer.ex +++ b/lib/pleroma/web/streamer.ex @@ -1,7 +1,7 @@ defmodule Pleroma.Web.Streamer do use GenServer require Logger - alias Pleroma.{User, Notification} + alias Pleroma.{User, Notification, Activity, Object} def init(args) do {:ok, args} @@ -59,6 +59,19 @@ def handle_cast(%{action: :stream, topic: "direct", item: item}, topics) do {:noreply, topics} end + def handle_cast(%{action: :stream, topic: "list", item: item}, topics) do + recipient_topics = + Pleroma.List.get_lists_from_activity(item) + |> Enum.map(fn %{id: id} -> "list:#{id}" end) + + Enum.each(recipient_topics || [], fn list_topic -> + Logger.debug("Trying to push message to #{list_topic}\n\n") + push_to_socket(topics, list_topic, item) + end) + + {:noreply, topics} + end + def handle_cast(%{action: :stream, topic: "user", item: %Notification{} = item}, topics) do topic = "user:#{item.user_id}" @@ -125,6 +138,34 @@ def handle_cast(m, state) do {:noreply, state} end + defp represent_update(%Activity{} = activity, %User{} = user) do + %{ + event: "update", + payload: + Pleroma.Web.MastodonAPI.StatusView.render( + "status.json", + activity: activity, + for: user + ) + |> Jason.encode!() + } + |> Jason.encode!() + end + + def push_to_socket(topics, topic, %Activity{data: %{"type" => "Announce"}} = item) do + Enum.each(topics[topic] || [], fn socket -> + # Get the current user so we have up-to-date blocks etc. + user = User.get_cached_by_ap_id(socket.assigns[:user].ap_id) + blocks = user.info["blocks"] || [] + + parent = Object.get_by_ap_id(item.data["object"]) + + 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)}) + end + end) + end + def push_to_socket(topics, topic, item) do Enum.each(topics[topic] || [], fn socket -> # Get the current user so we have up-to-date blocks etc. @@ -132,20 +173,7 @@ def push_to_socket(topics, topic, item) do blocks = user.info["blocks"] || [] unless item.actor in blocks do - json = - %{ - event: "update", - payload: - Pleroma.Web.MastodonAPI.StatusView.render( - "status.json", - activity: item, - for: user - ) - |> Jason.encode!() - } - |> Jason.encode!() - - send(socket.transport_pid, {:text, json}) + send(socket.transport_pid, {:text, represent_update(item, user)}) end end) end diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex index ccc6fe8e7..c23b3c2c4 100644 --- a/lib/pleroma/web/twitter_api/twitter_api.ex +++ b/lib/pleroma/web/twitter_api/twitter_api.ex @@ -12,14 +12,9 @@ def create_status(%User{} = user, %{"status" => _} = data) do end def delete(%User{} = user, id) do - # TwitterAPI does not have an "unretweet" endpoint; instead this is done - # via the "destroy" endpoint. Therefore, we need to handle - # when the status to "delete" is actually an Announce (repeat) object. - with %Activity{data: %{"type" => type}} <- Repo.get(Activity, id) do - case type do - "Announce" -> unrepeat(user, id) - _ -> CommonAPI.delete(id, user) - end + with %Activity{data: %{"type" => type}} <- Repo.get(Activity, id), + {:ok, activity} <- CommonAPI.delete(id, user) do + {:ok, activity} end end @@ -70,8 +65,9 @@ def repeat(%User{} = user, ap_id_or_id) do end end - defp unrepeat(%User{} = user, ap_id_or_id) do - with {:ok, _unannounce, activity, _object} <- CommonAPI.unrepeat(ap_id_or_id, user) do + def unrepeat(%User{} = user, ap_id_or_id) do + with {:ok, _unannounce, %{data: %{"id" => id}}} <- CommonAPI.unrepeat(ap_id_or_id, user), + %Activity{} = activity <- Activity.get_create_activity_by_object_ap_id(id) do {:ok, activity} end end diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex index d53dd0c44..ff5921807 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -4,6 +4,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do alias Pleroma.Web.CommonAPI alias Pleroma.{Repo, Activity, User, Notification} alias Pleroma.Web.ActivityPub.ActivityPub + alias Pleroma.Web.ActivityPub.Utils alias Ecto.Changeset require Logger @@ -240,6 +241,13 @@ def retweet(%{assigns: %{user: user}} = conn, %{"id" => id}) do end end + def unretweet(%{assigns: %{user: user}} = conn, %{"id" => id}) do + with {_, {:ok, id}} <- {:param_cast, Ecto.Type.cast(:integer, id)}, + {:ok, activity} <- TwitterAPI.unrepeat(user, id) do + render(conn, ActivityView, "activity.json", %{activity: activity, for: user}) + end + end + def register(conn, params) do with {:ok, user} <- TwitterAPI.register_user(params) do render(conn, UserView, "show.json", %{user: user}) @@ -331,6 +339,54 @@ def friends(conn, params) do end end + def friend_requests(conn, params) do + with {:ok, user} <- TwitterAPI.get_user(conn.assigns[:user], params), + {:ok, friend_requests} <- User.get_follow_requests(user) do + render(conn, UserView, "index.json", %{users: friend_requests, for: conn.assigns[:user]}) + else + _e -> bad_request_reply(conn, "Can't get friend requests") + end + end + + def approve_friend_request(conn, %{"user_id" => uid} = params) do + with followed <- conn.assigns[:user], + uid when is_number(uid) <- String.to_integer(uid), + %User{} = follower <- Repo.get(User, uid), + {:ok, follower} <- User.maybe_follow(follower, followed), + %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed), + {:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "accept"), + {:ok, _activity} <- + ActivityPub.accept(%{ + to: [follower.ap_id], + actor: followed.ap_id, + object: follow_activity.data["id"], + type: "Accept" + }) do + render(conn, UserView, "show.json", %{user: follower, for: followed}) + else + e -> bad_request_reply(conn, "Can't approve user: #{inspect(e)}") + end + end + + def deny_friend_request(conn, %{"user_id" => uid} = params) do + with followed <- conn.assigns[:user], + uid when is_number(uid) <- String.to_integer(uid), + %User{} = follower <- Repo.get(User, uid), + %Activity{} = follow_activity <- Utils.fetch_latest_follow(follower, followed), + {:ok, follow_activity} <- Utils.update_follow_state(follow_activity, "reject"), + {:ok, _activity} <- + ActivityPub.reject(%{ + to: [follower.ap_id], + actor: followed.ap_id, + object: follow_activity.data["id"], + type: "Reject" + }) do + render(conn, UserView, "show.json", %{user: follower, for: followed}) + else + e -> bad_request_reply(conn, "Can't deny user: #{inspect(e)}") + end + end + def friends_ids(%{assigns: %{user: user}} = conn, _params) do with {:ok, friends} <- User.get_friends(user) do ids = @@ -357,6 +413,20 @@ def update_profile(%{assigns: %{user: user}} = conn, params) do params end + user = + if locked = params["locked"] do + with locked <- locked == "true", + new_info <- Map.put(user.info, "locked", locked), + 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), {:ok, user} <- User.update_and_set_cache(changeset) do CommonAPI.update(user) diff --git a/lib/pleroma/web/twitter_api/views/user_view.ex b/lib/pleroma/web/twitter_api/views/user_view.ex index 31527caae..711008973 100644 --- a/lib/pleroma/web/twitter_api/views/user_view.ex +++ b/lib/pleroma/web/twitter_api/views/user_view.ex @@ -51,7 +51,8 @@ def render("user.json", %{user: user = %User{}} = assigns) do "statusnet_profile_url" => user.ap_id, "cover_photo" => User.banner_url(user) |> MediaProxy.url(), "background_image" => image_url(user.info["background"]) |> MediaProxy.url(), - "is_local" => user.local + "is_local" => user.local, + "locked" => !!user.info["locked"] } if assigns[:token] do diff --git a/lib/pleroma/web/web_finger/web_finger.ex b/lib/pleroma/web/web_finger/web_finger.ex index e7ee810f9..9f554d286 100644 --- a/lib/pleroma/web/web_finger/web_finger.ex +++ b/lib/pleroma/web/web_finger/web_finger.ex @@ -25,35 +25,17 @@ def host_meta do |> XmlBuilder.to_doc() end - def webfinger(resource, "JSON") do + def webfinger(resource, fmt) when fmt in ["XML", "JSON"] do host = Pleroma.Web.Endpoint.host() regex = ~r/(acct:)?(?\w+)@#{host}/ - with %{"username" => username} <- Regex.named_captures(regex, resource) do - user = User.get_by_nickname(username) - {:ok, represent_user(user, "JSON")} + with %{"username" => username} <- Regex.named_captures(regex, resource), + %User{} = user <- User.get_by_nickname(username) do + {:ok, represent_user(user, fmt)} else _e -> - with user when not is_nil(user) <- User.get_cached_by_ap_id(resource) do - {:ok, represent_user(user, "JSON")} - else - _e -> - {:error, "Couldn't find user"} - end - end - end - - def webfinger(resource, "XML") do - host = Pleroma.Web.Endpoint.host() - regex = ~r/(acct:)?(?\w+)@#{host}/ - - with %{"username" => username} <- Regex.named_captures(regex, resource) do - user = User.get_by_nickname(username) - {:ok, represent_user(user, "XML")} - else - _e -> - with user when not is_nil(user) <- User.get_cached_by_ap_id(resource) do - {:ok, represent_user(user, "XML")} + with %User{} = user <- User.get_cached_by_ap_id(resource) do + {:ok, represent_user(user, fmt)} else _e -> {:error, "Couldn't find user"} diff --git a/priv/repo/migrations/20180530123448_add_list_follow_index.exs b/priv/repo/migrations/20180530123448_add_list_follow_index.exs new file mode 100644 index 000000000..d6603e916 --- /dev/null +++ b/priv/repo/migrations/20180530123448_add_list_follow_index.exs @@ -0,0 +1,7 @@ +defmodule Pleroma.Repo.Migrations.AddListFollowIndex do + use Ecto.Migration + + def change do + create index(:lists, [:following]) + end +end diff --git a/priv/repo/migrations/20180606173637_create_apid_host_extraction_index.exs b/priv/repo/migrations/20180606173637_create_apid_host_extraction_index.exs new file mode 100644 index 000000000..9831a1b82 --- /dev/null +++ b/priv/repo/migrations/20180606173637_create_apid_host_extraction_index.exs @@ -0,0 +1,8 @@ +defmodule Pleroma.Repo.Migrations.CreateApidHostExtractionIndex do + use Ecto.Migration + @disable_ddl_transaction true + + def change do + create index(:activities, ["(split_part(actor, '/', 3))"], concurrently: true, name: :activities_hosts) + end +end diff --git a/priv/static/images/avi.png b/priv/static/images/avi.png index 336fd15ef..3fc699c12 100644 Binary files a/priv/static/images/avi.png and b/priv/static/images/avi.png differ diff --git a/priv/static/index.html b/priv/static/index.html index ae3cde3a4..380dd1687 100644 --- a/priv/static/index.html +++ b/priv/static/index.html @@ -1 +1 @@ -Pleroma
\ No newline at end of file +Pleroma
\ No newline at end of file diff --git a/priv/static/static/config.json b/priv/static/static/config.json index 9cdb22d59..4dacfebed 100644 --- a/priv/static/static/config.json +++ b/priv/static/static/config.json @@ -10,5 +10,6 @@ "whoToFollowProviderDummy2": "https://followlink.osa-p.net/api/get_recommend.json?acct=@{{user}}@{{host}}", "whoToFollowLink": "https://vinayaka.distsn.org/?{{host}}+{{user}}", "whoToFollowLinkDummy2": "https://followlink.osa-p.net/recommend.html", - "showInstanceSpecificPanel": false + "showInstanceSpecificPanel": false, + "scopeOptionsEnabled": false } diff --git a/priv/static/static/css/app.5d0189b6f119febde070b703869bbd06.css b/priv/static/static/css/app.5d0189b6f119febde070b703869bbd06.css new file mode 100644 index 000000000..9df919fca Binary files /dev/null and b/priv/static/static/css/app.5d0189b6f119febde070b703869bbd06.css differ diff --git a/priv/static/static/css/app.5d0189b6f119febde070b703869bbd06.css.map b/priv/static/static/css/app.5d0189b6f119febde070b703869bbd06.css.map new file mode 100644 index 000000000..35cbec774 --- /dev/null +++ b/priv/static/static/css/app.5d0189b6f119febde070b703869bbd06.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///webpack:///src/App.scss","webpack:///webpack:///src/components/user_panel/user_panel.vue","webpack:///webpack:///src/components/login_form/login_form.vue","webpack:///webpack:///src/components/post_status_form/post_status_form.vue","webpack:///webpack:///src/components/media_upload/media_upload.vue","webpack:///webpack:///src/components/user_card_content/user_card_content.vue","webpack:///webpack:///src/components/still-image/still-image.vue","webpack:///webpack:///src/components/nav_panel/nav_panel.vue","webpack:///webpack:///src/components/notifications/notifications.scss","webpack:///webpack:///src/components/status/status.vue","webpack:///webpack:///src/components/attachment/attachment.vue","webpack:///webpack:///src/components/favorite_button/favorite_button.vue","webpack:///webpack:///src/components/retweet_button/retweet_button.vue","webpack:///webpack:///src/components/delete_button/delete_button.vue","webpack:///webpack:///src/components/user_finder/user_finder.vue","webpack:///webpack:///src/components/who_to_follow_panel/who_to_follow_panel.vue","webpack:///webpack:///src/components/chat_panel/chat_panel.vue","webpack:///webpack:///src/components/timeline/timeline.vue","webpack:///webpack:///src/components/status_or_conversation/status_or_conversation.vue","webpack:///webpack:///src/components/user_card/user_card.vue","webpack:///webpack:///src/components/user_profile/user_profile.vue","webpack:///webpack:///src/components/settings/settings.vue","webpack:///webpack:///src/components/style_switcher/style_switcher.vue","webpack:///webpack:///src/components/registration/registration.vue","webpack:///webpack:///src/components/user_settings/user_settings.vue"],"names":[],"mappings":"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","file":"static/css/app.5d0189b6f119febde070b703869bbd06.css","sourcesContent":["\n#app{background-size:cover;background-attachment:fixed;background-repeat:no-repeat;background-position:0 50px;min-height:100vh;max-width:100%;overflow:hidden\n}\ni{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none\n}\nh4{margin:0\n}\n#content{box-sizing:border-box;padding-top:60px;margin:auto;min-height:100vh;max-width:980px;background-color:rgba(0,0,0,0.15);-ms-flex-line-pack:start;align-content:flex-start\n}\n.text-center{text-align:center\n}\nbody{font-family:sans-serif;font-size:14px;margin:0;color:#b9b9ba;color:var(--fg, #b9b9ba);max-width:100vw;overflow-x:hidden\n}\na{text-decoration:none;color:#d8a070;color:var(--link, #d8a070)\n}\nbutton{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;color:#b9b9ba;color:var(--fg, #b9b9ba);background-color:#182230;background-color:var(--btn, #182230);border:none;border-radius:4px;border-radius:var(--btnRadius, 4px);cursor:pointer;border-top:1px solid rgba(255,255,255,0.2);border-bottom:1px solid rgba(0,0,0,0.2);box-shadow:0px 0px 2px black;font-size:14px;font-family:sans-serif\n}\nbutton:hover{box-shadow:0px 0px 4px rgba(255,255,255,0.3)\n}\nbutton:disabled{cursor:not-allowed;opacity:0.5\n}\nbutton.pressed{color:rgba(185,185,186,0.5);color:var(--faint, rgba(185,185,186,0.5));background-color:#121a24;background-color:var(--bg, #121a24)\n}\nlabel.select{padding:0\n}\ninput,textarea,.select{border:none;border-radius:4px;border-radius:var(--inputRadius, 4px);border-bottom:1px solid rgba(255,255,255,0.2);border-top:1px solid rgba(0,0,0,0.2);box-shadow:0px 0px 2px black inset;background-color:#182230;background-color:var(--input, #182230);color:#b9b9ba;color:var(--lightFg, #b9b9ba);font-family:sans-serif;font-size:14px;padding:8px 7px;box-sizing:border-box;display:inline-block;position:relative;height:29px;line-height:16px\n}\ninput .icon-down-open,textarea .icon-down-open,.select .icon-down-open{position:absolute;top:0;bottom:0;right:5px;height:100%;color:#b9b9ba;color:var(--fg, #b9b9ba);line-height:29px;z-index:0;pointer-events:none\n}\ninput select,textarea select,.select select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:none;margin:0;color:#b9b9ba;color:var(--fg, #b9b9ba);padding:4px 2em 3px 3px;width:100%;z-index:1;height:29px;line-height:16px\n}\ninput[type=radio],input[type=checkbox],textarea[type=radio],textarea[type=checkbox],.select[type=radio],.select[type=checkbox]{display:none\n}\ninput[type=radio]:checked+label::before,input[type=checkbox]:checked+label::before,textarea[type=radio]:checked+label::before,textarea[type=checkbox]:checked+label::before,.select[type=radio]:checked+label::before,.select[type=checkbox]:checked+label::before{color:#b9b9ba;color:var(--fg, #b9b9ba)\n}\ninput[type=radio]+label::before,input[type=checkbox]+label::before,textarea[type=radio]+label::before,textarea[type=checkbox]+label::before,.select[type=radio]+label::before,.select[type=checkbox]+label::before{display:inline-block;content:'✔';transition:color 200ms;width:1.1em;height:1.1em;border-radius:2px;border-radius:var(--checkBoxRadius, 2px);border-bottom:1px solid rgba(255,255,255,0.2);border-top:1px solid rgba(0,0,0,0.2);box-shadow:0px 0px 2px black inset;margin-right:.5em;background-color:#182230;background-color:var(--input, #182230);vertical-align:top;text-align:center;line-height:1.1em;font-size:1.1em;box-sizing:border-box;color:transparent;overflow:hidden;box-sizing:border-box\n}\ni[class*=icon-]{color:#666;color:var(--icon, #666)\n}\n.container{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin:0;padding:0 10px 0 10px\n}\n.gaps{margin:-1em 0 0 -1em\n}\n.item{-ms-flex:1;flex:1;line-height:50px;height:50px;overflow:hidden\n}\n.item .nav-icon{font-size:1.1em;margin-left:0.4em\n}\n.gaps>.item{padding:1em 0 0 1em\n}\n.auto-size{-ms-flex:1;flex:1\n}\nnav{width:100%;-ms-flex-align:center;align-items:center;position:fixed;height:50px\n}\nnav .inner-nav{padding-left:20px;padding-right:20px;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-preferred-size:970px;flex-basis:970px;margin:auto;height:50px;background-repeat:no-repeat;background-position:center;background-size:auto 80%\n}\nnav .inner-nav a i{color:#d8a070;color:var(--link, #d8a070)\n}\nmain-router{-ms-flex:1;flex:1\n}\n.status.compact{color:rgba(0,0,0,0.42);font-weight:300\n}\n.status.compact p{margin:0;font-size:0.8em\n}\n.panel{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;margin:0.5em;background-color:#121a24;background-color:var(--bg, #121a24);border-radius:10px;border-radius:var(--panelRadius, 10px);box-shadow:1px 1px 4px rgba(0,0,0,0.6)\n}\n.panel-body:empty::before{content:\"¯\\\\_(ツ)_/¯\";display:block;margin:1em;text-align:center\n}\n.panel-heading{border-radius:10px 10px 0 0;border-radius:var(--panelRadius, 10px) var(--panelRadius, 10px) 0 0;background-size:cover;padding:0.6em 1.0em;text-align:left;font-size:1.3em;line-height:24px;background-color:#182230;background-color:var(--btn, #182230)\n}\n.panel-heading.stub{border-radius:10px;border-radius:var(--panelRadius, 10px)\n}\n.panel-footer{border-radius:0 0 10px 10px;border-radius:0 0 var(--panelRadius, 10px) var(--panelRadius, 10px)\n}\n.panel-body>p{line-height:18px;padding:1em;margin:0\n}\n.container>*{min-width:0px\n}\n.fa{color:grey\n}\nnav{z-index:1000;background-color:#182230;background-color:var(--btn, #182230);color:rgba(185,185,186,0.5);color:var(--faint, rgba(185,185,186,0.5));box-shadow:0px 0px 4px rgba(0,0,0,0.6)\n}\n.fade-enter-active,.fade-leave-active{transition:opacity .2s\n}\n.fade-enter,.fade-leave-active{opacity:0\n}\n.main{-ms-flex-preferred-size:60%;flex-basis:60%;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1\n}\n.sidebar-bounds{-ms-flex:0;flex:0;-ms-flex-preferred-size:35%;flex-basis:35%\n}\n.sidebar-flexer{-ms-flex:1;flex:1;-ms-flex-preferred-size:345px;flex-basis:345px;width:365px\n}\n.mobile-shown{display:none\n}\n.panel-switcher{display:none;width:100%;height:46px\n}\n.panel-switcher button{display:block;-ms-flex:1;flex:1;max-height:32px;margin:0.5em;padding:0.5em\n}\n@media all and (min-width: 960px){\nbody{overflow-y:scroll\n}\n.sidebar-bounds{overflow:hidden;max-height:100vh;width:345px;position:fixed;margin-top:-10px\n}\n.sidebar-bounds .sidebar-scroller{height:96vh;width:365px;padding-top:10px;padding-right:50px;overflow-x:hidden;overflow-y:scroll\n}\n.sidebar-bounds .sidebar{width:345px\n}\n.sidebar-flexer{max-height:96vh;-ms-flex-negative:0;flex-shrink:0;-ms-flex-positive:0;flex-grow:0\n}\n}\n.alert{margin:0.35em;padding:0.25em;border-radius:5px;border-radius:var(--tooltipRadius, 5px);color:rgba(185,185,186,0.5);color:var(--faint, rgba(185,185,186,0.5));min-height:28px;line-height:28px\n}\n.alert.error{background-color:rgba(211,16,20,0.5);background-color:var(--cAlertRed, rgba(211,16,20,0.5))\n}\n.faint{color:rgba(185,185,186,0.5);color:var(--faint, rgba(185,185,186,0.5))\n}\n@media all and (max-width: 959px){\n.mobile-hidden{display:none\n}\n.panel-switcher{display:-ms-flexbox;display:flex\n}\n.container{padding:0 0 0 0\n}\n.panel{margin:0.5em 0 0.5em 0\n}\n}\n.item.right{text-align:right;padding-right:20px\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/App.scss","\n.user-panel .profile-panel-background .panel-heading{background:transparent\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/user_panel/user_panel.vue","\n.login-form .btn{min-height:28px;width:10em\n}\n.login-form .error{text-align:center\n}\n.login-form .register{-ms-flex:1 1;flex:1 1\n}\n.login-form .login-bottom{margin-top:1.0em;display:-ms-flexbox;display:flex;-ms-flex-direction:row;flex-direction:row;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/login_form/login_form.vue","\n.tribute-container ul{padding:0px\n}\n.tribute-container ul li{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center\n}\n.tribute-container img{padding:3px;width:16px;height:16px;border-radius:10px;border-radius:var(--avatarAltRadius, 10px)\n}\n.post-status-form .visibility-tray{font-size:1.2em;padding:3px;cursor:pointer\n}\n.post-status-form .visibility-tray .selected{color:#b9b9ba;color:var(--lightFg, #b9b9ba)\n}\n.post-status-form .form-bottom,.login .form-bottom{display:-ms-flexbox;display:flex;padding:0.5em;height:32px\n}\n.post-status-form .form-bottom button,.login .form-bottom button{width:10em\n}\n.post-status-form .form-bottom p,.login .form-bottom p{margin:0.35em;padding:0.35em;display:-ms-flexbox;display:flex\n}\n.post-status-form .error,.login .error{text-align:center\n}\n.post-status-form .attachments,.login .attachments{padding:0 0.5em\n}\n.post-status-form .attachments .attachment,.login .attachments .attachment{position:relative;border:1px solid #222;border:1px solid var(--border, #222);margin:0.5em 0.8em 0.2em 0\n}\n.post-status-form .attachments i,.login .attachments i{position:absolute;margin:10px;padding:5px;background:rgba(230,230,230,0.6);border-radius:10px;border-radius:var(--attachmentRadius, 10px);font-weight:bold\n}\n.post-status-form .btn,.login .btn{cursor:pointer\n}\n.post-status-form .btn[disabled],.login .btn[disabled]{cursor:not-allowed\n}\n.post-status-form form,.login form{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding:0.6em\n}\n.post-status-form .form-group,.login .form-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding:0.3em 0.5em 0.6em;line-height:24px\n}\n.post-status-form form textarea.form-cw,.login form textarea.form-cw{line-height:16px;resize:none;overflow:hidden;transition:min-height 200ms 100ms;min-height:1px\n}\n.post-status-form form textarea.form-control,.login form textarea.form-control{line-height:16px;resize:none;overflow:hidden;transition:min-height 200ms 100ms;min-height:1px;box-sizing:content-box\n}\n.post-status-form form textarea.form-control:focus,.login form textarea.form-control:focus{min-height:48px\n}\n.post-status-form .btn,.login .btn{cursor:pointer\n}\n.post-status-form .btn[disabled],.login .btn[disabled]{cursor:not-allowed\n}\n.post-status-form .icon-cancel,.login .icon-cancel{cursor:pointer;z-index:4\n}\n.post-status-form .autocomplete-panel,.login .autocomplete-panel{margin:0 0.5em 0 0.5em;border-radius:5px;border-radius:var(--tooltipRadius, 5px);position:absolute;z-index:1;box-shadow:1px 2px 4px rgba(0,0,0,0.5);min-width:75%;background:#121a24;background:var(--bg, #121a24);color:#b9b9ba;color:var(--lightFg, #b9b9ba)\n}\n.post-status-form .autocomplete,.login .autocomplete{cursor:pointer;padding:0.2em 0.4em 0.2em 0.4em;border-bottom:1px solid rgba(0,0,0,0.4);display:-ms-flexbox;display:flex\n}\n.post-status-form .autocomplete img,.login .autocomplete img{width:24px;height:24px;border-radius:4px;border-radius:var(--avatarRadius, 4px);object-fit:contain\n}\n.post-status-form .autocomplete span,.login .autocomplete span{line-height:24px;margin:0 0.1em 0 0.2em\n}\n.post-status-form .autocomplete small,.login .autocomplete small{margin-left:.5em;color:rgba(185,185,186,0.5);color:var(--faint, rgba(185,185,186,0.5))\n}\n.post-status-form .autocomplete.highlighted,.login .autocomplete.highlighted{background-color:#182230;background-color:var(--btn, #182230)\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/post_status_form/post_status_form.vue","\n.media-upload {\n font-size: 26px;\n -ms-flex: 1;\n flex: 1;\n}\n.icon-upload {\n cursor: pointer;\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/media_upload/media_upload.vue","\n.profile-panel-background{background-size:cover;border-radius:10px;border-radius:var(--panelRadius, 10px)\n}\n.profile-panel-background .panel-heading{padding:0.6em 0em;text-align:center\n}\n.profile-panel-body{word-wrap:break-word;background:linear-gradient(to bottom, transparent, #121a24 80%);background:linear-gradient(to bottom, transparent, var(--bg, #121a24) 80%)\n}\n.user-info{color:#b9b9ba;color:var(--lightFg, #b9b9ba);padding:0 16px\n}\n.user-info .container{padding:16px 10px 6px 10px;display:-ms-flexbox;display:flex;max-height:56px;overflow:hidden\n}\n.user-info .container .avatar{border-radius:4px;border-radius:var(--avatarRadius, 4px);-ms-flex:1 0 100%;flex:1 0 100%;width:56px;height:56px;box-shadow:0px 1px 8px rgba(0,0,0,0.75);object-fit:cover\n}\n.user-info .container .avatar.animated::before{display:none\n}\n.user-info:hover .animated.avatar canvas{display:none\n}\n.user-info:hover .animated.avatar img{visibility:visible\n}\n.user-info .usersettings{color:#b9b9ba;color:var(--lightFg, #b9b9ba);opacity:.8\n}\n.user-info .name-and-screen-name{display:block;margin-left:0.6em;text-align:left;text-overflow:ellipsis;white-space:nowrap;-ms-flex:1 1 0px;flex:1 1 0\n}\n.user-info .user-name{text-overflow:ellipsis;overflow:hidden\n}\n.user-info .user-screen-name{color:#b9b9ba;color:var(--lightFg, #b9b9ba);display:inline-block;font-weight:light;font-size:15px;padding-right:0.1em\n}\n.user-info .user-interactions{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-pack:justify;justify-content:space-between\n}\n.user-info .user-interactions div{-ms-flex:1;flex:1\n}\n.user-info .user-interactions .following{font-size:14px;-ms-flex:0 0 100%;flex:0 0 100%;margin:0 0 .4em 0;padding-left:16px;text-align:left\n}\n.user-info .user-interactions .mute{max-width:220px;min-height:28px\n}\n.user-info .user-interactions .remote-follow{max-width:220px;min-height:28px\n}\n.user-info .user-interactions .follow{max-width:220px;min-height:28px\n}\n.user-info .user-interactions button{width:92%;height:100%\n}\n.user-info .user-interactions .remote-button{height:28px !important;width:92%\n}\n.user-info .user-interactions .pressed{border-bottom-color:rgba(255,255,255,0.2);border-top-color:rgba(0,0,0,0.2)\n}\n.user-counts{display:-ms-flexbox;display:flex;line-height:16px;padding:.5em 1.5em 0em 1.5em;text-align:center;-ms-flex-pack:justify;justify-content:space-between;color:#b9b9ba;color:var(--lightFg, #b9b9ba)\n}\n.user-counts.clickable .user-count{cursor:pointer\n}\n.user-counts.clickable .user-count:hover:not(.selected){transition:border-bottom 100ms;border-bottom:3px solid #d8a070;border-bottom:3px solid var(--link, #d8a070)\n}\n.user-count{-ms-flex:1;flex:1;padding:.5em 0 .5em 0;margin:0 .5em\n}\n.user-count.selected{transition:none;border-bottom:5px solid #d8a070;border-bottom:5px solid var(--link, #d8a070);border-radius:4px;border-radius:var(--btnRadius, 4px)\n}\n.user-count h5{font-size:1em;font-weight:bolder;margin:0 0 0.25em\n}\n.user-count a{text-decoration:none\n}\n.dailyAvg{margin-left:1em;font-size:0.7em;color:#CCC\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/user_card_content/user_card_content.vue","\n.still-image{position:relative;line-height:0;overflow:hidden;width:100%;height:100%\n}\n.still-image:hover canvas{display:none\n}\n.still-image img{width:100%;height:100%\n}\n.still-image.animated:hover::before,.still-image.animated img{visibility:hidden\n}\n.still-image.animated:hover img{visibility:visible\n}\n.still-image.animated::before{content:'gif';position:absolute;line-height:10px;font-size:10px;top:5px;left:5px;background:rgba(127,127,127,0.5);color:#FFF;display:block;padding:2px 4px;border-radius:5px;border-radius:var(--tooltipRadius, 5px);z-index:2\n}\n.still-image canvas{position:absolute;top:0;bottom:0;left:0;right:0;width:100%;height:100%\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/still-image/still-image.vue","\n.nav-panel .panel{overflow:hidden\n}\n.nav-panel ul{list-style:none;margin:0;padding:0\n}\n.nav-panel li{border-bottom:1px solid;border-color:#222;border-color:var(--border, #222);padding:0\n}\n.nav-panel li:first-child a{border-top-right-radius:10px;border-top-right-radius:var(--panelRadius, 10px);border-top-left-radius:10px;border-top-left-radius:var(--panelRadius, 10px)\n}\n.nav-panel li:last-child a{border-bottom-right-radius:10px;border-bottom-right-radius:var(--panelRadius, 10px);border-bottom-left-radius:10px;border-bottom-left-radius:var(--panelRadius, 10px)\n}\n.nav-panel li:last-child{border:none\n}\n.nav-panel a{display:block;padding:0.8em 0.85em\n}\n.nav-panel a:hover{background-color:#151e2a;background-color:var(--lightBg, #151e2a)\n}\n.nav-panel a.router-link-active{font-weight:bolder;background-color:#151e2a;background-color:var(--lightBg, #151e2a)\n}\n.nav-panel a.router-link-active:hover{text-decoration:underline\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/nav_panel/nav_panel.vue","\n.notifications{padding-bottom:15em\n}\n.notifications .panel{background:#121a24;background:var(--bg, #121a24)\n}\n.notifications .panel-body{border-color:#222;border-color:var(--border, #222)\n}\n.notifications .panel-heading{position:relative;background:#182230;background:var(--btn, #182230);color:#b9b9ba;color:var(--fg, #b9b9ba)\n}\n.notifications .panel-heading .read-button{position:absolute;right:0.7em;height:1.8em;line-height:100%\n}\n.notifications .unseen-count{display:inline-block;background-color:red;background-color:var(--cRed, red);text-shadow:0px 0px 3px rgba(0,0,0,0.5);min-width:1.3em;border-radius:1.3em;margin:0 0.2em 0 -0.4em;color:white;font-size:0.9em;text-align:center;line-height:1.3em\n}\n.notifications .unseen{border-left:4px solid red;border-left:4px solid var(--cRed, red);padding-left:0\n}\n.notification{box-sizing:border-box;display:-ms-flexbox;display:flex;border-bottom:1px solid;border-bottom-color:inherit;padding-left:4px\n}\n.notification .avatar-compact{width:32px;height:32px;border-radius:10px;border-radius:var(--avatarAltRadius, 10px);overflow:hidden;line-height:0\n}\n.notification .avatar-compact.animated::before{display:none\n}\n.notification:hover .animated.avatar canvas{display:none\n}\n.notification:hover .animated.avatar img{visibility:visible\n}\n.notification .notification-usercard{margin:0\n}\n.notification .non-mention{display:-ms-flexbox;display:flex;-ms-flex:1;flex:1;-ms-flex-wrap:nowrap;flex-wrap:nowrap;padding:0.6em;min-width:0\n}\n.notification .non-mention .avatar-container{width:32px;height:32px\n}\n.notification .non-mention .status-el{padding:0\n}\n.notification .non-mention .status-el .status{padding:0.25em 0;color:rgba(185,185,186,0.5);color:var(--faint, rgba(185,185,186,0.5))\n}\n.notification .non-mention .status-el .media-body{margin:0\n}\n.notification .follow-text{padding:0.5em 0\n}\n.notification .status-el{-ms-flex:1;flex:1\n}\n.notification time{white-space:nowrap\n}\n.notification .notification-right{-ms-flex:1;flex:1;padding-left:0.8em;min-width:0\n}\n.notification .notification-details{min-width:0px;word-wrap:break-word;line-height:18px;position:relative;overflow:hidden;width:100%;-ms-flex:1 1 0px;flex:1 1 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:nowrap;flex-wrap:nowrap\n}\n.notification .notification-details .name-and-action{-ms-flex:1;flex:1;overflow:hidden;text-overflow:ellipsis\n}\n.notification .notification-details .username{font-weight:bolder;max-width:100%;text-overflow:ellipsis;white-space:nowrap\n}\n.notification .notification-details .timeago{float:right;font-size:12px\n}\n.notification .notification-details .icon-retweet.lit{color:#0fa00f;color:var(--cGreen, #0fa00f)\n}\n.notification .notification-details .icon-user-plus.lit{color:#0095ff;color:var(--cBlue, #0095ff)\n}\n.notification .notification-details .icon-reply.lit{color:#0095ff;color:var(--cBlue, #0095ff)\n}\n.notification .notification-details .icon-star.lit{color:orange;color:orange;color:var(--cOrange, orange)\n}\n.notification .notification-details .status-content{margin:0;max-height:300px\n}\n.notification .notification-details h1{word-break:break-all;margin:0 0 0.3em;padding:0;font-size:1em;line-height:20px\n}\n.notification .notification-details h1 small{font-weight:lighter\n}\n.notification .notification-details p{margin:0;margin-top:0;margin-bottom:0.3em\n}\n.notification:last-child{border-bottom:none;border-radius:0 0 10px 10px;border-radius:0 0 var(--panelRadius, 10px) var(--panelRadius, 10px)\n}\n.notification:last-child .status-el{border-radius:0 0 10px 10px;border-radius:0 0 var(--panelRadius, 10px) var(--panelRadius, 10px)\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/notifications/notifications.scss","\n.status-body{-ms-flex:1;flex:1;min-width:0\n}\n.status-preview.status-el{border-style:solid;border-width:1px;border-color:#222;border-color:var(--border, #222)\n}\n.status-preview-container{position:relative;max-width:100%\n}\n.status-preview{position:absolute;max-width:95%;display:-ms-flexbox;display:flex;background-color:#121a24;background-color:var(--bg, #121a24);border-color:#222;border-color:var(--border, #222);border-style:solid;border-width:1px;border-radius:5px;border-radius:var(--tooltipRadius, 5px);box-shadow:2px 2px 3px rgba(0,0,0,0.5);margin-top:0.25em;margin-left:0.5em;z-index:50\n}\n.status-preview .status{-ms-flex:1;flex:1;border:0;min-width:15em\n}\n.status-preview-loading{display:block;min-width:15em;padding:1em;text-align:center;border-width:1px;border-style:solid\n}\n.status-preview-loading i{font-size:2em\n}\n.status-el{-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto;overflow-wrap:break-word;word-wrap:break-word;word-break:break-word;border-left-width:0px;line-height:18px;min-width:0;border-color:#222;border-color:var(--border, #222);border-left:4px red;border-left:4px var(--cRed, red)\n}\n.status-el_focused{background-color:#151e2a;background-color:var(--lightBg, #151e2a)\n}\n.timeline .status-el{border-bottom-width:1px;border-bottom-style:solid\n}\n.status-el .media-body{-ms-flex:1;flex:1;padding:0;margin:0 0 0.25em 0.8em\n}\n.status-el .usercard{margin-bottom:.7em\n}\n.status-el .media-heading{-ms-flex-wrap:nowrap;flex-wrap:nowrap\n}\n.status-el .media-heading-left{padding:0;vertical-align:bottom;-ms-flex-preferred-size:100%;flex-basis:100%\n}\n.status-el .media-heading-left small{font-weight:lighter\n}\n.status-el .media-heading-left h4{white-space:nowrap;font-size:14px;margin-right:0.25em;overflow:hidden;text-overflow:ellipsis\n}\n.status-el .media-heading-left .name-and-links{padding:0;-ms-flex:1 0;flex:1 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-line-pack:center;align-content:center\n}\n.status-el .media-heading-left .links{display:-ms-flexbox;display:flex;padding-top:1px;margin-left:0.2em;font-size:12px;color:#d8a070;color:var(--link, #d8a070);max-width:100%\n}\n.status-el .media-heading-left .links a{max-width:100%;text-overflow:ellipsis;overflow:hidden;white-space:nowrap\n}\n.status-el .media-heading-left .reply-info{display:-ms-flexbox;display:flex\n}\n.status-el .media-heading-left .replies{line-height:16px\n}\n.status-el .media-heading-left .reply-link{margin-right:0.2em\n}\n.status-el .media-heading-right{-ms-flex-negative:0;flex-shrink:0;display:-ms-flexbox;display:flex;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:1.5em;margin-left:0.25em\n}\n.status-el .media-heading-right .timeago{margin-right:0.2em;font-size:12px;padding-top:1px\n}\n.status-el .media-heading-right i{margin-left:0.2em\n}\n.status-el a{display:inline-block;word-break:break-all\n}\n.status-el .tall-status{position:relative;height:220px;overflow-x:hidden;overflow-y:hidden\n}\n.status-el .tall-status-hider{position:absolute;height:70px;margin-top:150px;width:100%;text-align:center;line-height:110px;background:linear-gradient(to bottom, transparent, #121a24 80%);background:linear-gradient(to bottom, transparent, var(--bg, #121a24) 80%)\n}\n.status-el .tall-status-hider_focused{background:linear-gradient(to bottom, transparent, #151e2a 80%);background:linear-gradient(to bottom, transparent, var(--lightBg, #151e2a) 80%)\n}\n.status-el .tall-status-unhider{width:100%;text-align:center\n}\n.status-el .status-content{margin-right:0.5em\n}\n.status-el .status-content img,.status-el .status-content video{max-width:100%;max-height:400px;vertical-align:middle;object-fit:contain\n}\n.status-el .status-content blockquote{margin:0.2em 0 0.2em 2em;font-style:italic\n}\n.status-el .status-content p{margin:0;margin-top:0.2em;margin-bottom:0.5em\n}\n.status-el .retweet-info{padding:0.4em 0.6em 0 0.6em;margin:0 0 -0.5em 0\n}\n.status-el .retweet-info .avatar{border-radius:10px;border-radius:var(--avatarAltRadius, 10px);margin-left:28px;width:20px;height:20px\n}\n.status-el .retweet-info .media-body{font-size:1em;line-height:22px;display:-ms-flexbox;display:flex;-ms-flex-line-pack:center;align-content:center;-ms-flex-wrap:wrap;flex-wrap:wrap\n}\n.status-el .retweet-info .media-body i{padding:0 0.2em\n}\n.status-el .retweet-info .media-body a{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap\n}\n.status-fadein{animation-duration:0.4s;animation-name:fadein\n}\n@keyframes fadein{\nfrom{opacity:0\n}\nto{opacity:1\n}\n}\n.greentext{color:green\n}\n.status-conversation{border-left-style:solid\n}\n.status-actions{width:100%;display:-ms-flexbox;display:flex\n}\n.status-actions div,.status-actions favorite-button{padding-top:0.25em;max-width:6em;-ms-flex:1;flex:1\n}\n.icon-reply:hover{color:#0095ff;color:var(--cBlue, #0095ff)\n}\n.icon-reply.icon-reply-active{color:#0095ff;color:var(--cBlue, #0095ff)\n}\n.status .avatar-compact{width:32px;height:32px;border-radius:10px;border-radius:var(--avatarAltRadius, 10px)\n}\n.avatar{width:48px;height:48px;border-radius:4px;border-radius:var(--avatarRadius, 4px);overflow:hidden;position:relative\n}\n.avatar img{width:100%;height:100%\n}\n.avatar.animated::before{display:none\n}\n.status:hover .animated.avatar canvas{display:none\n}\n.status:hover .animated.avatar img{visibility:visible\n}\n.status{display:-ms-flexbox;display:flex;padding:0.6em\n}\n.status-conversation:last-child{border-bottom:none\n}\n.muted{padding:0.25em 0.5em\n}\n.muted button{margin-left:auto\n}\n.muted .muteWords{margin-left:10px\n}\na.unmute{display:block;margin-left:auto\n}\n.reply-left{-ms-flex:0;flex:0;min-width:48px\n}\n.reply-body{-ms-flex:1;flex:1\n}\n.timeline>.status-el:last-child{border-bottom-radius:0 0 10px 10px;border-radius:0 0 var(--panelRadius, 10px) var(--panelRadius, 10px)\n}\n@media all and (max-width: 960px){\n.status-el .retweet-info .avatar{margin-left:20px\n}\n.status{max-width:100%\n}\n.status .avatar{width:40px;height:40px\n}\n.status .avatar-compact{width:32px;height:32px\n}\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/status/status.vue","\n.attachments{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-0.7em\n}\n.attachments .attachment.media-upload-container{-ms-flex:0 0 auto;flex:0 0 auto;max-height:300px;max-width:100%\n}\n.attachments .placeholder{margin-right:0.5em\n}\n.attachments .small-attachment{max-height:100px\n}\n.attachments .small-attachment.image,.attachments .small-attachment.video{max-width:35%\n}\n.attachments .attachment{-ms-flex:1 0 30%;flex:1 0 30%;margin:0.5em 0.7em 0.6em 0.0em;-ms-flex-item-align:start;align-self:flex-start;line-height:0;border-style:solid;border-width:1px;border-radius:10px;border-radius:var(--attachmentRadius, 10px);border-color:#222;border-color:var(--border, #222);overflow:hidden\n}\n.attachments .fullwidth{-ms-flex-preferred-size:100%;flex-basis:100%\n}\n.attachments.video{line-height:0\n}\n.attachments.html{-ms-flex-preferred-size:90%;flex-basis:90%;width:100%;display:-ms-flexbox;display:flex\n}\n.attachments.loading{cursor:progress\n}\n.attachments .hider{position:absolute;margin:10px;padding:5px;background:rgba(230,230,230,0.6);font-weight:bold;z-index:4;line-height:1;border-radius:5px;border-radius:var(--tooltipRadius, 5px)\n}\n.attachments .small{max-height:100px\n}\n.attachments video{max-height:500px;height:100%;width:100%;z-index:0\n}\n.attachments audio{width:100%\n}\n.attachments img.media-upload{line-height:0;max-height:300px;max-width:100%\n}\n.attachments .oembed{line-height:1.2em;-ms-flex:1 0 100%;flex:1 0 100%;width:100%;margin-right:15px;display:-ms-flexbox;display:flex\n}\n.attachments .oembed img{width:100%\n}\n.attachments .oembed .image{-ms-flex:1;flex:1\n}\n.attachments .oembed .image img{border:0px;border-radius:5px;height:100%;object-fit:cover\n}\n.attachments .oembed .text{-ms-flex:2;flex:2;margin:8px;word-break:break-all\n}\n.attachments .oembed .text h1{font-size:14px;margin:0px\n}\n.attachments .image-attachment{display:-ms-flexbox;display:flex;-ms-flex:1;flex:1\n}\n.attachments .image-attachment .still-image{width:100%;height:100%\n}\n.attachments .image-attachment .small img{max-height:100px\n}\n.attachments .image-attachment img{object-fit:contain;width:100%;height:100%;max-height:500px;image-orientation:from-image\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/attachment/attachment.vue","\n.fav-active{cursor:pointer;animation-duration:0.6s\n}\n.fav-active:hover{color:orange;color:var(--cOrange, orange)\n}\n.favorite-button.icon-star{color:orange;color:var(--cOrange, orange)\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/favorite_button/favorite_button.vue","\n.rt-active{cursor:pointer;animation-duration:0.6s\n}\n.rt-active:hover{color:#0fa00f;color:var(--cGreen, #0fa00f)\n}\n.icon-retweet.retweeted{color:#0fa00f;color:var(--cGreen, #0fa00f)\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/retweet_button/retweet_button.vue","\n.icon-cancel,.delete-status{cursor:pointer\n}\n.icon-cancel:hover,.delete-status:hover{color:var(--cRed, red);color:red\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/delete_button/delete_button.vue","\n.user-finder-container{height:29px;max-width:100%\n}\n.user-finder-input{max-width:80%;vertical-align:middle\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/user_finder/user_finder.vue","\n.who-to-follow *{vertical-align:middle\n}\n.who-to-follow img{width:32px;height:32px\n}\n.who-to-follow p{line-height:40px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/who_to_follow_panel/who_to_follow_panel.vue","\n.floating-chat{position:fixed;right:0px;bottom:0px;z-index:1000\n}\n.chat-heading{cursor:pointer\n}\n.chat-heading .icon-comment-empty{color:#b9b9ba;color:var(--fg, #b9b9ba)\n}\n.chat-window{width:345px;max-height:40vh;overflow-y:auto;overflow-x:hidden\n}\n.chat-message{display:-ms-flexbox;display:flex;padding:0.2em 0.5em\n}\n.chat-avatar img{height:24px;width:24px;border-radius:4px;border-radius:var(--avatarRadius, 4px);margin-right:0.5em;margin-top:0.25em\n}\n.chat-input{display:-ms-flexbox;display:flex\n}\n.chat-input textarea{-ms-flex:1;flex:1;margin:0.6em;min-height:3.5em;resize:none\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/chat_panel/chat_panel.vue","\n.timeline .timeline-heading{position:relative;display:-ms-flexbox;display:flex\n}\n.timeline .title{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:70%\n}\n.timeline .loadmore-button{position:absolute;right:0.6em;font-size:14px;min-width:6em;height:1.8em;line-height:100%\n}\n.timeline .loadmore-text{position:absolute;right:0.6em;font-size:14px;min-width:6em;font-family:sans-serif;text-align:center;padding:0 0.5em 0 0.5em;opacity:0.8;background-color:transparent;color:rgba(185,185,186,0.5);color:var(--faint, rgba(185,185,186,0.5))\n}\n.timeline .loadmore-error{position:absolute;right:0.6em;font-size:14px;min-width:6em;font-family:sans-serif;text-align:center;padding:0 0.25em 0 0.25em;margin:0;color:#b9b9ba;color:var(--fg, #b9b9ba)\n}\n.new-status-notification{position:relative;margin-top:-1px;font-size:1.1em;border-width:1px 0 0 0;border-style:solid;border-color:var(--border, #222);padding:10px;z-index:1;background-color:#182230;background-color:var(--btn, #182230)\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/timeline/timeline.vue","\n.spacer{height:1em\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/status_or_conversation/status_or_conversation.vue","\n.name-and-screen-name{margin-left:0.7em;margin-top:0.0em;text-align:left;width:100%\n}\n.follows-you{margin-left:2em;float:right\n}\n.card{display:-ms-flexbox;display:flex;-ms-flex:1 0;flex:1 0;padding-top:0.6em;padding-right:1em;padding-bottom:0.6em;padding-left:1em;border-bottom:1px solid;margin:0;border-bottom-color:#222;border-bottom-color:var(--border, #222)\n}\n.card .avatar{margin-top:0.2em;width:32px;height:32px;border-radius:10px;border-radius:var(--avatarAltRadius, 10px)\n}\n.usercard{width:-webkit-fill-available;width:-moz-available;width:fill-available;margin:0.2em 0 0.7em 0;border-radius:10px;border-radius:var(--panelRadius, 10px);border-style:solid;border-color:#222;border-color:var(--border, #222);border-width:1px;overflow:hidden\n}\n.usercard .panel-heading{background:transparent\n}\n.usercard p{margin-bottom:0\n}\n.approval button{width:100%;margin-bottom:0.5em\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/user_card/user_card.vue","\n.user-profile{-ms-flex:2;flex:2;-ms-flex-preferred-size:500px;flex-basis:500px;padding-bottom:10px\n}\n.user-profile .panel-heading{background:transparent\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/user_profile/user_profile.vue","\n.setting-item{border-bottom:2px solid var(--btn, #182230);margin:1em 1em 1.4em;padding-bottom:1.4em\n}\n.setting-item textarea{width:100%;height:100px\n}\n.setting-item .old-avatar{width:128px;border-radius:4px;border-radius:var(--avatarRadius, 4px)\n}\n.setting-item .new-avatar{object-fit:cover;width:128px;height:128px;border-radius:4px;border-radius:var(--avatarRadius, 4px)\n}\n.setting-item .btn{margin-top:1em;min-height:28px;width:10em\n}\n.setting-list{list-style-type:none\n}\n.setting-list li{margin-bottom:0.5em\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/settings/settings.vue","\n.style-switcher{margin-right:1em\n}\n.radius-container,.color-container{display:-ms-flexbox;display:flex\n}\n.radius-container p,.color-container p{margin-top:2em;margin-bottom:.5em\n}\n.radius-container{-ms-flex-direction:column;flex-direction:column\n}\n.color-container{-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:justify;justify-content:space-between\n}\n.radius-item,.color-item{min-width:20em;display:-ms-flexbox;display:flex;-ms-flex:1 1 0px;flex:1 1 0;-ms-flex-align:baseline;align-items:baseline;margin:5px 6px 5px 0\n}\n.radius-item label,.color-item label{color:var(--faint, rgba(185,185,186,0.5))\n}\n.radius-item{-ms-flex-preferred-size:auto;flex-basis:auto\n}\n.theme-radius-rn,.theme-color-cl{border:0;box-shadow:none;background:transparent;color:var(--faint, rgba(185,185,186,0.5));-ms-flex-item-align:stretch;-ms-grid-row-align:stretch;align-self:stretch\n}\n.theme-color-cl,.theme-radius-in,.theme-color-in{margin-left:4px\n}\n.theme-color-in{min-width:4em\n}\n.theme-radius-in{min-width:1em\n}\n.theme-radius-in,.theme-color-in{max-width:7em;-ms-flex:1;flex:1\n}\n.theme-radius-lb,.theme-color-lb{-ms-flex:2;flex:2;min-width:7em\n}\n.theme-radius-lb{max-width:50em\n}\n.theme-color-lb{max-width:10em\n}\n.theme-color-cl{padding:1px;max-width:8em;height:100%;-ms-flex:0;flex:0;min-width:2em;cursor:pointer\n}\n.theme-preview-content{padding:20px\n}\n.dummy .avatar{background:linear-gradient(135deg, #b8e1fc 0%, #a9d2f3 10%, #90bae4 25%, #90bcea 37%, #90bff0 50%, #6ba8e5 51%, #a2daf5 83%, #bdf3fd 100%);color:black;text-align:center;height:48px;line-height:48px;width:48px;float:left;margin-right:1em\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/style_switcher/style_switcher.vue","\n.registration-form{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;margin:0.6em\n}\n.registration-form .container{display:-ms-flexbox;display:flex;-ms-flex-direction:row;flex-direction:row\n}\n.registration-form .terms-of-service{-ms-flex:0 1 50%;flex:0 1 50%;margin:0.8em\n}\n.registration-form .text-fields{margin-top:0.6em;-ms-flex:1 0;flex:1 0;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column\n}\n.registration-form .form-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding:0.3em 0.0em 0.3em;line-height:24px\n}\n.registration-form form textarea{line-height:16px;resize:vertical\n}\n.registration-form .captcha{max-width:350px;margin-bottom:0.4em\n}\n.registration-form .btn{margin-top:0.6em;height:28px\n}\n.registration-form .error{text-align:center\n}\n@media all and (max-width: 959px){\n.registration-form .container{-ms-flex-direction:column-reverse;flex-direction:column-reverse\n}\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/registration/registration.vue","\n.profile-edit .bio{margin:0\n}\n.profile-edit input[type=file]{padding:5px;height:auto\n}\n.profile-edit .banner{max-width:400px\n}\n.profile-edit .uploading{font-size:1.5em;margin:0.25em\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/user_settings/user_settings.vue"],"sourceRoot":""} \ No newline at end of file diff --git a/priv/static/static/css/app.c0e1e1e1fcff94fd1e14fc44bfee9a1e.css b/priv/static/static/css/app.c0e1e1e1fcff94fd1e14fc44bfee9a1e.css deleted file mode 100644 index 3e778b2f0..000000000 Binary files a/priv/static/static/css/app.c0e1e1e1fcff94fd1e14fc44bfee9a1e.css and /dev/null differ diff --git a/priv/static/static/css/app.c0e1e1e1fcff94fd1e14fc44bfee9a1e.css.map b/priv/static/static/css/app.c0e1e1e1fcff94fd1e14fc44bfee9a1e.css.map deleted file mode 100644 index 3e3b0170f..000000000 --- a/priv/static/static/css/app.c0e1e1e1fcff94fd1e14fc44bfee9a1e.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["webpack:///webpack:///src/App.scss","webpack:///webpack:///src/components/user_panel/user_panel.vue","webpack:///webpack:///src/components/login_form/login_form.vue","webpack:///webpack:///src/components/post_status_form/post_status_form.vue","webpack:///webpack:///src/components/media_upload/media_upload.vue","webpack:///webpack:///src/components/user_card_content/user_card_content.vue","webpack:///webpack:///src/components/still-image/still-image.vue","webpack:///webpack:///src/components/nav_panel/nav_panel.vue","webpack:///webpack:///src/components/notifications/notifications.scss","webpack:///webpack:///src/components/status/status.vue","webpack:///webpack:///src/components/attachment/attachment.vue","webpack:///webpack:///src/components/favorite_button/favorite_button.vue","webpack:///webpack:///src/components/retweet_button/retweet_button.vue","webpack:///webpack:///src/components/delete_button/delete_button.vue","webpack:///webpack:///src/components/user_finder/user_finder.vue","webpack:///webpack:///src/components/who_to_follow_panel/who_to_follow_panel.vue","webpack:///webpack:///src/components/chat_panel/chat_panel.vue","webpack:///webpack:///src/components/timeline/timeline.vue","webpack:///webpack:///src/components/status_or_conversation/status_or_conversation.vue","webpack:///webpack:///src/components/user_card/user_card.vue","webpack:///webpack:///src/components/user_profile/user_profile.vue","webpack:///webpack:///src/components/settings/settings.vue","webpack:///webpack:///src/components/style_switcher/style_switcher.vue","webpack:///webpack:///src/components/registration/registration.vue","webpack:///webpack:///src/components/user_settings/user_settings.vue"],"names":[],"mappings":"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","file":"static/css/app.c0e1e1e1fcff94fd1e14fc44bfee9a1e.css","sourcesContent":["\n#app{background-size:cover;background-attachment:fixed;background-repeat:no-repeat;background-position:0 50px;min-height:100vh;max-width:100%;overflow:hidden\n}\ni{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none\n}\nh4{margin:0\n}\n#content{box-sizing:border-box;padding-top:60px;margin:auto;min-height:100vh;max-width:980px;background-color:rgba(0,0,0,0.15);-ms-flex-line-pack:start;align-content:flex-start\n}\n.text-center{text-align:center\n}\nbody{font-family:sans-serif;font-size:14px;margin:0;color:#b9b9ba;color:var(--fg, #b9b9ba);max-width:100vw;overflow-x:hidden\n}\na{text-decoration:none;color:#d8a070;color:var(--link, #d8a070)\n}\nbutton{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;color:#b9b9ba;color:var(--fg, #b9b9ba);background-color:#182230;background-color:var(--btn, #182230);border:none;border-radius:4px;border-radius:var(--btnRadius, 4px);cursor:pointer;border-top:1px solid rgba(255,255,255,0.2);border-bottom:1px solid rgba(0,0,0,0.2);box-shadow:0px 0px 2px black;font-size:14px;font-family:sans-serif\n}\nbutton:hover{box-shadow:0px 0px 4px rgba(255,255,255,0.3)\n}\nbutton:disabled{cursor:not-allowed;opacity:0.5\n}\nbutton.pressed{color:rgba(185,185,186,0.5);color:var(--faint, rgba(185,185,186,0.5));background-color:#121a24;background-color:var(--bg, #121a24)\n}\nlabel.select{padding:0\n}\ninput,textarea,.select{border:none;border-radius:4px;border-radius:var(--inputRadius, 4px);border-bottom:1px solid rgba(255,255,255,0.2);border-top:1px solid rgba(0,0,0,0.2);box-shadow:0px 0px 2px black inset;background-color:#182230;background-color:var(--input, #182230);color:#b9b9ba;color:var(--lightFg, #b9b9ba);font-family:sans-serif;font-size:14px;padding:8px 7px;box-sizing:border-box;display:inline-block;position:relative;height:29px;line-height:16px\n}\ninput .icon-down-open,textarea .icon-down-open,.select .icon-down-open{position:absolute;top:0;bottom:0;right:5px;height:100%;color:#b9b9ba;color:var(--fg, #b9b9ba);line-height:29px;z-index:0;pointer-events:none\n}\ninput select,textarea select,.select select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:none;margin:0;color:#b9b9ba;color:var(--fg, #b9b9ba);padding:4px 2em 3px 3px;width:100%;z-index:1;height:29px;line-height:16px\n}\ninput[type=radio],input[type=checkbox],textarea[type=radio],textarea[type=checkbox],.select[type=radio],.select[type=checkbox]{display:none\n}\ninput[type=radio]:checked+label::before,input[type=checkbox]:checked+label::before,textarea[type=radio]:checked+label::before,textarea[type=checkbox]:checked+label::before,.select[type=radio]:checked+label::before,.select[type=checkbox]:checked+label::before{color:#b9b9ba;color:var(--fg, #b9b9ba)\n}\ninput[type=radio]+label::before,input[type=checkbox]+label::before,textarea[type=radio]+label::before,textarea[type=checkbox]+label::before,.select[type=radio]+label::before,.select[type=checkbox]+label::before{display:inline-block;content:'✔';transition:color 200ms;width:1.1em;height:1.1em;border-radius:2px;border-radius:var(--checkBoxRadius, 2px);border-bottom:1px solid rgba(255,255,255,0.2);border-top:1px solid rgba(0,0,0,0.2);box-shadow:0px 0px 2px black inset;margin-right:.5em;background-color:#182230;background-color:var(--input, #182230);vertical-align:top;text-align:center;line-height:1.1em;font-size:1.1em;box-sizing:border-box;color:transparent;overflow:hidden;box-sizing:border-box\n}\ni[class*=icon-]{color:#666;color:var(--icon, #666)\n}\n.container{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin:0;padding:0 10px 0 10px\n}\n.gaps{margin:-1em 0 0 -1em\n}\n.item{-ms-flex:1;flex:1;line-height:50px;height:50px;overflow:hidden\n}\n.item .nav-icon{font-size:1.1em;margin-left:0.4em\n}\n.gaps>.item{padding:1em 0 0 1em\n}\n.auto-size{-ms-flex:1;flex:1\n}\nnav{width:100%;-ms-flex-align:center;align-items:center;position:fixed;height:50px\n}\nnav .inner-nav{padding-left:20px;padding-right:20px;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-preferred-size:970px;flex-basis:970px;margin:auto;height:50px;background-repeat:no-repeat;background-position:center;background-size:auto 80%\n}\nnav .inner-nav a i{color:#d8a070;color:var(--link, #d8a070)\n}\nmain-router{-ms-flex:1;flex:1\n}\n.status.compact{color:rgba(0,0,0,0.42);font-weight:300\n}\n.status.compact p{margin:0;font-size:0.8em\n}\n.panel{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;margin:0.5em;background-color:#121a24;background-color:var(--bg, #121a24);border-radius:10px;border-radius:var(--panelRadius, 10px);box-shadow:1px 1px 4px rgba(0,0,0,0.6)\n}\n.panel-body:empty::before{content:\"¯\\\\_(ツ)_/¯\";display:block;margin:1em;text-align:center\n}\n.panel-heading{border-radius:10px 10px 0 0;border-radius:var(--panelRadius, 10px) var(--panelRadius, 10px) 0 0;background-size:cover;padding:0.6em 1.0em;text-align:left;font-size:1.3em;line-height:24px;background-color:#182230;background-color:var(--btn, #182230)\n}\n.panel-heading.stub{border-radius:10px;border-radius:var(--panelRadius, 10px)\n}\n.panel-footer{border-radius:0 0 10px 10px;border-radius:0 0 var(--panelRadius, 10px) var(--panelRadius, 10px)\n}\n.panel-body>p{line-height:18px;padding:1em;margin:0\n}\n.container>*{min-width:0px\n}\n.fa{color:grey\n}\nnav{z-index:1000;background-color:#182230;background-color:var(--btn, #182230);color:rgba(185,185,186,0.5);color:var(--faint, rgba(185,185,186,0.5));box-shadow:0px 0px 4px rgba(0,0,0,0.6)\n}\n.fade-enter-active,.fade-leave-active{transition:opacity .2s\n}\n.fade-enter,.fade-leave-active{opacity:0\n}\n.main{-ms-flex-preferred-size:60%;flex-basis:60%;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1\n}\n.sidebar-bounds{-ms-flex:0;flex:0;-ms-flex-preferred-size:35%;flex-basis:35%\n}\n.sidebar-flexer{-ms-flex:1;flex:1;-ms-flex-preferred-size:345px;flex-basis:345px;width:365px\n}\n.mobile-shown{display:none\n}\n.panel-switcher{display:none;width:100%;height:46px\n}\n.panel-switcher button{display:block;-ms-flex:1;flex:1;max-height:32px;margin:0.5em;padding:0.5em\n}\n@media all and (min-width: 960px){\nbody{overflow-y:scroll\n}\n.sidebar-bounds{overflow:hidden;max-height:100vh;width:345px;position:fixed;margin-top:-10px\n}\n.sidebar-bounds .sidebar-scroller{height:96vh;width:365px;padding-top:10px;padding-right:50px;overflow-x:hidden;overflow-y:scroll\n}\n.sidebar-bounds .sidebar{width:345px\n}\n.sidebar-flexer{max-height:96vh;-ms-flex-negative:0;flex-shrink:0;-ms-flex-positive:0;flex-grow:0\n}\n}\n.alert{margin:0.35em;padding:0.25em;border-radius:5px;border-radius:var(--tooltipRadius, 5px);color:rgba(185,185,186,0.5);color:var(--faint, rgba(185,185,186,0.5));min-height:28px;line-height:28px\n}\n.alert.error{background-color:rgba(211,16,20,0.5);background-color:var(--cAlertRed, rgba(211,16,20,0.5))\n}\n.faint{color:rgba(185,185,186,0.5);color:var(--faint, rgba(185,185,186,0.5))\n}\n@media all and (max-width: 959px){\n.mobile-hidden{display:none\n}\n.panel-switcher{display:-ms-flexbox;display:flex\n}\n.container{padding:0 0 0 0\n}\n.panel{margin:0.5em 0 0.5em 0\n}\n}\n.item.right{text-align:right;padding-right:20px\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/App.scss","\n.user-panel .profile-panel-background .panel-heading{background:transparent\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/user_panel/user_panel.vue","\n.login-form .btn{min-height:28px;width:10em\n}\n.login-form .error{text-align:center\n}\n.login-form .register{-ms-flex:1 1;flex:1 1\n}\n.login-form .login-bottom{margin-top:1.0em;display:-ms-flexbox;display:flex;-ms-flex-direction:row;flex-direction:row;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/login_form/login_form.vue","\n.tribute-container ul{padding:0px\n}\n.tribute-container ul li{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center\n}\n.tribute-container img{padding:3px;width:16px;height:16px;border-radius:10px;border-radius:var(--avatarAltRadius, 10px)\n}\n.post-status-form .form-bottom,.login .form-bottom{display:-ms-flexbox;display:flex;padding:0.5em;height:32px\n}\n.post-status-form .form-bottom button,.login .form-bottom button{width:10em\n}\n.post-status-form .form-bottom p,.login .form-bottom p{margin:0.35em;padding:0.35em;display:-ms-flexbox;display:flex\n}\n.post-status-form .error,.login .error{text-align:center\n}\n.post-status-form .attachments,.login .attachments{padding:0 0.5em\n}\n.post-status-form .attachments .attachment,.login .attachments .attachment{position:relative;border:1px solid #222;border:1px solid var(--border, #222);margin:0.5em 0.8em 0.2em 0\n}\n.post-status-form .attachments i,.login .attachments i{position:absolute;margin:10px;padding:5px;background:rgba(230,230,230,0.6);border-radius:10px;border-radius:var(--attachmentRadius, 10px);font-weight:bold\n}\n.post-status-form .btn,.login .btn{cursor:pointer\n}\n.post-status-form .btn[disabled],.login .btn[disabled]{cursor:not-allowed\n}\n.post-status-form form,.login form{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding:0.6em\n}\n.post-status-form .form-group,.login .form-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding:0.3em 0.5em 0.6em;line-height:24px\n}\n.post-status-form form textarea,.login form textarea{line-height:16px;resize:none;overflow:hidden;transition:min-height 200ms 100ms;min-height:1px;box-sizing:content-box\n}\n.post-status-form form textarea:focus,.login form textarea:focus{min-height:48px\n}\n.post-status-form .btn,.login .btn{cursor:pointer\n}\n.post-status-form .btn[disabled],.login .btn[disabled]{cursor:not-allowed\n}\n.post-status-form .icon-cancel,.login .icon-cancel{cursor:pointer;z-index:4\n}\n.post-status-form .autocomplete-panel,.login .autocomplete-panel{margin:0 0.5em 0 0.5em;border-radius:5px;border-radius:var(--tooltipRadius, 5px);position:absolute;z-index:1;box-shadow:1px 2px 4px rgba(0,0,0,0.5);min-width:75%;background:#121a24;background:var(--bg, #121a24);color:#b9b9ba;color:var(--lightFg, #b9b9ba)\n}\n.post-status-form .autocomplete,.login .autocomplete{cursor:pointer;padding:0.2em 0.4em 0.2em 0.4em;border-bottom:1px solid rgba(0,0,0,0.4);display:-ms-flexbox;display:flex\n}\n.post-status-form .autocomplete img,.login .autocomplete img{width:24px;height:24px;border-radius:4px;border-radius:var(--avatarRadius, 4px);object-fit:contain\n}\n.post-status-form .autocomplete span,.login .autocomplete span{line-height:24px;margin:0 0.1em 0 0.2em\n}\n.post-status-form .autocomplete small,.login .autocomplete small{margin-left:.5em;color:rgba(185,185,186,0.5);color:var(--faint, rgba(185,185,186,0.5))\n}\n.post-status-form .autocomplete.highlighted,.login .autocomplete.highlighted{background-color:#182230;background-color:var(--btn, #182230)\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/post_status_form/post_status_form.vue","\n.media-upload {\n font-size: 26px;\n -ms-flex: 1;\n flex: 1;\n}\n.icon-upload {\n cursor: pointer;\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/media_upload/media_upload.vue","\n.profile-panel-background{background-size:cover;border-radius:10px;border-radius:var(--panelRadius, 10px)\n}\n.profile-panel-background .panel-heading{padding:0.6em 0em;text-align:center\n}\n.profile-panel-body{word-wrap:break-word;background:linear-gradient(to bottom, transparent, #121a24 80%);background:linear-gradient(to bottom, transparent, var(--bg, #121a24) 80%)\n}\n.user-info{color:#b9b9ba;color:var(--lightFg, #b9b9ba);padding:0 16px\n}\n.user-info .container{padding:16px 10px 6px 10px;display:-ms-flexbox;display:flex;max-height:56px;overflow:hidden\n}\n.user-info .container .avatar{border-radius:4px;border-radius:var(--avatarRadius, 4px);-ms-flex:1 0 100%;flex:1 0 100%;width:56px;height:56px;box-shadow:0px 1px 8px rgba(0,0,0,0.75);object-fit:cover\n}\n.user-info .container .avatar.animated::before{display:none\n}\n.user-info:hover .animated.avatar canvas{display:none\n}\n.user-info:hover .animated.avatar img{visibility:visible\n}\n.user-info .usersettings{color:#b9b9ba;color:var(--lightFg, #b9b9ba);opacity:.8\n}\n.user-info .name-and-screen-name{display:block;margin-left:0.6em;text-align:left;text-overflow:ellipsis;white-space:nowrap;-ms-flex:1 1 0px;flex:1 1 0\n}\n.user-info .user-name{text-overflow:ellipsis;overflow:hidden\n}\n.user-info .user-screen-name{color:#b9b9ba;color:var(--lightFg, #b9b9ba);display:inline-block;font-weight:light;font-size:15px;padding-right:0.1em\n}\n.user-info .user-interactions{display:-ms-flexbox;display:flex;-ms-flex-flow:row wrap;flex-flow:row wrap;-ms-flex-pack:justify;justify-content:space-between\n}\n.user-info .user-interactions div{-ms-flex:1;flex:1\n}\n.user-info .user-interactions .following{font-size:14px;-ms-flex:0 0 100%;flex:0 0 100%;margin:0 0 .4em 0;padding-left:16px;text-align:left\n}\n.user-info .user-interactions .mute{max-width:220px;min-height:28px\n}\n.user-info .user-interactions .remote-follow{max-width:220px;min-height:28px\n}\n.user-info .user-interactions .follow{max-width:220px;min-height:28px\n}\n.user-info .user-interactions button{width:92%;height:100%\n}\n.user-info .user-interactions .remote-button{height:28px !important;width:92%\n}\n.user-info .user-interactions .pressed{border-bottom-color:rgba(255,255,255,0.2);border-top-color:rgba(0,0,0,0.2)\n}\n.user-counts{display:-ms-flexbox;display:flex;line-height:16px;padding:.5em 1.5em 0em 1.5em;text-align:center;-ms-flex-pack:justify;justify-content:space-between;color:#b9b9ba;color:var(--lightFg, #b9b9ba)\n}\n.user-counts.clickable .user-count{cursor:pointer\n}\n.user-counts.clickable .user-count:hover:not(.selected){transition:border-bottom 100ms;border-bottom:3px solid #d8a070;border-bottom:3px solid var(--link, #d8a070)\n}\n.user-count{-ms-flex:1;flex:1;padding:.5em 0 .5em 0;margin:0 .5em\n}\n.user-count.selected{transition:none;border-bottom:5px solid #d8a070;border-bottom:5px solid var(--link, #d8a070);border-radius:4px;border-radius:var(--btnRadius, 4px)\n}\n.user-count h5{font-size:1em;font-weight:bolder;margin:0 0 0.25em\n}\n.user-count a{text-decoration:none\n}\n.dailyAvg{margin-left:1em;font-size:0.7em;color:#CCC\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/user_card_content/user_card_content.vue","\n.still-image{position:relative;line-height:0;overflow:hidden;width:100%;height:100%\n}\n.still-image:hover canvas{display:none\n}\n.still-image img{width:100%;height:100%\n}\n.still-image.animated:hover::before,.still-image.animated img{visibility:hidden\n}\n.still-image.animated:hover img{visibility:visible\n}\n.still-image.animated::before{content:'gif';position:absolute;line-height:10px;font-size:10px;top:5px;left:5px;background:rgba(127,127,127,0.5);color:#FFF;display:block;padding:2px 4px;border-radius:5px;border-radius:var(--tooltipRadius, 5px);z-index:2\n}\n.still-image canvas{position:absolute;top:0;bottom:0;left:0;right:0;width:100%;height:100%\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/still-image/still-image.vue","\n.nav-panel .panel{overflow:hidden\n}\n.nav-panel ul{list-style:none;margin:0;padding:0\n}\n.nav-panel li{border-bottom:1px solid;border-color:#222;border-color:var(--border, #222);padding:0\n}\n.nav-panel li:first-child a{border-top-right-radius:10px;border-top-right-radius:var(--panelRadius, 10px);border-top-left-radius:10px;border-top-left-radius:var(--panelRadius, 10px)\n}\n.nav-panel li:last-child a{border-bottom-right-radius:10px;border-bottom-right-radius:var(--panelRadius, 10px);border-bottom-left-radius:10px;border-bottom-left-radius:var(--panelRadius, 10px)\n}\n.nav-panel li:last-child{border:none\n}\n.nav-panel a{display:block;padding:0.8em 0.85em\n}\n.nav-panel a:hover{background-color:#151e2a;background-color:var(--lightBg, #151e2a)\n}\n.nav-panel a.router-link-active{font-weight:bolder;background-color:#151e2a;background-color:var(--lightBg, #151e2a)\n}\n.nav-panel a.router-link-active:hover{text-decoration:underline\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/nav_panel/nav_panel.vue","\n.notifications{padding-bottom:15em\n}\n.notifications .panel{background:#121a24;background:var(--bg, #121a24)\n}\n.notifications .panel-body{border-color:#222;border-color:var(--border, #222)\n}\n.notifications .panel-heading{position:relative;background:#182230;background:var(--btn, #182230);color:#b9b9ba;color:var(--fg, #b9b9ba)\n}\n.notifications .panel-heading .read-button{position:absolute;right:0.7em;height:1.8em;line-height:100%\n}\n.notifications .unseen-count{display:inline-block;background-color:red;background-color:var(--cRed, red);text-shadow:0px 0px 3px rgba(0,0,0,0.5);min-width:1.3em;border-radius:1.3em;margin:0 0.2em 0 -0.4em;color:white;font-size:0.9em;text-align:center;line-height:1.3em\n}\n.notifications .unseen{border-left:4px solid red;border-left:4px solid var(--cRed, red);padding-left:0\n}\n.notification{box-sizing:border-box;display:-ms-flexbox;display:flex;border-bottom:1px solid;border-bottom-color:inherit;padding-left:4px\n}\n.notification .avatar-compact{width:32px;height:32px;border-radius:10px;border-radius:var(--avatarAltRadius, 10px);overflow:hidden;line-height:0\n}\n.notification .avatar-compact.animated::before{display:none\n}\n.notification:hover .animated.avatar canvas{display:none\n}\n.notification:hover .animated.avatar img{visibility:visible\n}\n.notification .notification-usercard{margin:0\n}\n.notification .non-mention{display:-ms-flexbox;display:flex;-ms-flex:1;flex:1;-ms-flex-wrap:nowrap;flex-wrap:nowrap;padding:0.6em;min-width:0\n}\n.notification .non-mention .avatar-container{width:32px;height:32px\n}\n.notification .non-mention .status-el{padding:0\n}\n.notification .non-mention .status-el .status{padding:0.25em 0;color:rgba(185,185,186,0.5);color:var(--faint, rgba(185,185,186,0.5))\n}\n.notification .non-mention .status-el .media-body{margin:0\n}\n.notification .follow-text{padding:0.5em 0\n}\n.notification .status-el{-ms-flex:1;flex:1\n}\n.notification time{white-space:nowrap\n}\n.notification .notification-right{-ms-flex:1;flex:1;padding-left:0.8em;min-width:0\n}\n.notification .notification-details{min-width:0px;word-wrap:break-word;line-height:18px;position:relative;overflow:hidden;width:100%;-ms-flex:1 1 0px;flex:1 1 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:nowrap;flex-wrap:nowrap\n}\n.notification .notification-details .name-and-action{-ms-flex:1;flex:1;overflow:hidden;text-overflow:ellipsis\n}\n.notification .notification-details .username{font-weight:bolder;max-width:100%;text-overflow:ellipsis;white-space:nowrap\n}\n.notification .notification-details .timeago{float:right;font-size:12px\n}\n.notification .notification-details .icon-retweet.lit{color:#0fa00f;color:var(--cGreen, #0fa00f)\n}\n.notification .notification-details .icon-user-plus.lit{color:#0095ff;color:var(--cBlue, #0095ff)\n}\n.notification .notification-details .icon-reply.lit{color:#0095ff;color:var(--cBlue, #0095ff)\n}\n.notification .notification-details .icon-star.lit{color:orange;color:orange;color:var(--cOrange, orange)\n}\n.notification .notification-details .status-content{margin:0;max-height:300px\n}\n.notification .notification-details h1{word-break:break-all;margin:0 0 0.3em;padding:0;font-size:1em;line-height:20px\n}\n.notification .notification-details h1 small{font-weight:lighter\n}\n.notification .notification-details p{margin:0;margin-top:0;margin-bottom:0.3em\n}\n.notification:last-child{border-bottom:none;border-radius:0 0 10px 10px;border-radius:0 0 var(--panelRadius, 10px) var(--panelRadius, 10px)\n}\n.notification:last-child .status-el{border-radius:0 0 10px 10px;border-radius:0 0 var(--panelRadius, 10px) var(--panelRadius, 10px)\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/notifications/notifications.scss","\n.status-body{-ms-flex:1;flex:1;min-width:0\n}\n.status-preview.status-el{border-style:solid;border-width:1px;border-color:#222;border-color:var(--border, #222)\n}\n.status-preview-container{position:relative;max-width:100%\n}\n.status-preview{position:absolute;max-width:95%;display:-ms-flexbox;display:flex;background-color:#121a24;background-color:var(--bg, #121a24);border-color:#222;border-color:var(--border, #222);border-style:solid;border-width:1px;border-radius:5px;border-radius:var(--tooltipRadius, 5px);box-shadow:2px 2px 3px rgba(0,0,0,0.5);margin-top:0.25em;margin-left:0.5em;z-index:50\n}\n.status-preview .status{-ms-flex:1;flex:1;border:0;min-width:15em\n}\n.status-preview-loading{display:block;min-width:15em;padding:1em;text-align:center;border-width:1px;border-style:solid\n}\n.status-preview-loading i{font-size:2em\n}\n.status-el{-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto;overflow-wrap:break-word;word-wrap:break-word;word-break:break-word;border-left-width:0px;line-height:18px;min-width:0;border-color:#222;border-color:var(--border, #222);border-left:4px red;border-left:4px var(--cRed, red)\n}\n.status-el_focused{background-color:#151e2a;background-color:var(--lightBg, #151e2a)\n}\n.timeline .status-el{border-bottom-width:1px;border-bottom-style:solid\n}\n.status-el .media-body{-ms-flex:1;flex:1;padding:0;margin:0 0 0.25em 0.8em\n}\n.status-el .usercard{margin-bottom:.7em\n}\n.status-el .media-heading{-ms-flex-wrap:nowrap;flex-wrap:nowrap\n}\n.status-el .media-heading-left{padding:0;vertical-align:bottom;-ms-flex-preferred-size:100%;flex-basis:100%\n}\n.status-el .media-heading-left small{font-weight:lighter\n}\n.status-el .media-heading-left h4{white-space:nowrap;font-size:14px;margin-right:0.25em;overflow:hidden;text-overflow:ellipsis\n}\n.status-el .media-heading-left .name-and-links{padding:0;-ms-flex:1 0;flex:1 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-line-pack:center;align-content:center\n}\n.status-el .media-heading-left .links{display:-ms-flexbox;display:flex;padding-top:1px;margin-left:0.2em;font-size:12px;color:#d8a070;color:var(--link, #d8a070);max-width:100%\n}\n.status-el .media-heading-left .links a{max-width:100%;text-overflow:ellipsis;overflow:hidden;white-space:nowrap\n}\n.status-el .media-heading-left .reply-info{display:-ms-flexbox;display:flex\n}\n.status-el .media-heading-left .replies{line-height:16px\n}\n.status-el .media-heading-left .reply-link{margin-right:0.2em\n}\n.status-el .media-heading-right{-ms-flex-negative:0;flex-shrink:0;display:-ms-flexbox;display:flex;-ms-flex-wrap:nowrap;flex-wrap:nowrap;max-height:1.5em;margin-left:0.25em\n}\n.status-el .media-heading-right .timeago{margin-right:0.2em;font-size:12px;padding-top:1px\n}\n.status-el .media-heading-right i{margin-left:0.2em\n}\n.status-el a{display:inline-block;word-break:break-all\n}\n.status-el .tall-status{position:relative;height:220px;overflow-x:hidden;overflow-y:hidden\n}\n.status-el .tall-status-hider{position:absolute;height:70px;margin-top:150px;width:100%;text-align:center;line-height:110px;background:linear-gradient(to bottom, transparent, #121a24 80%);background:linear-gradient(to bottom, transparent, var(--bg, #121a24) 80%)\n}\n.status-el .tall-status-hider_focused{background:linear-gradient(to bottom, transparent, #151e2a 80%);background:linear-gradient(to bottom, transparent, var(--lightBg, #151e2a) 80%)\n}\n.status-el .tall-status-unhider{width:100%;text-align:center\n}\n.status-el .status-content{margin-right:0.5em\n}\n.status-el .status-content img,.status-el .status-content video{max-width:100%;max-height:400px;vertical-align:middle;object-fit:contain\n}\n.status-el .status-content blockquote{margin:0.2em 0 0.2em 2em;font-style:italic\n}\n.status-el .status-content p{margin:0;margin-top:0.2em;margin-bottom:0.5em\n}\n.status-el .retweet-info{padding:0.4em 0.6em 0 0.6em;margin:0 0 -0.5em 0\n}\n.status-el .retweet-info .avatar{border-radius:10px;border-radius:var(--avatarAltRadius, 10px);margin-left:28px;width:20px;height:20px\n}\n.status-el .retweet-info .media-body{font-size:1em;line-height:22px;display:-ms-flexbox;display:flex;-ms-flex-line-pack:center;align-content:center;-ms-flex-wrap:wrap;flex-wrap:wrap\n}\n.status-el .retweet-info .media-body i{padding:0 0.2em\n}\n.status-el .retweet-info .media-body a{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap\n}\n.status-fadein{animation-duration:0.4s;animation-name:fadein\n}\n@keyframes fadein{\nfrom{opacity:0\n}\nto{opacity:1\n}\n}\n.greentext{color:green\n}\n.status-conversation{border-left-style:solid\n}\n.status-actions{width:100%;display:-ms-flexbox;display:flex\n}\n.status-actions div,.status-actions favorite-button{padding-top:0.25em;max-width:6em;-ms-flex:1;flex:1\n}\n.icon-reply:hover{color:#0095ff;color:var(--cBlue, #0095ff)\n}\n.icon-reply.icon-reply-active{color:#0095ff;color:var(--cBlue, #0095ff)\n}\n.status .avatar-compact{width:32px;height:32px;border-radius:10px;border-radius:var(--avatarAltRadius, 10px)\n}\n.avatar{width:48px;height:48px;border-radius:4px;border-radius:var(--avatarRadius, 4px);overflow:hidden;position:relative\n}\n.avatar img{width:100%;height:100%\n}\n.avatar.animated::before{display:none\n}\n.status:hover .animated.avatar canvas{display:none\n}\n.status:hover .animated.avatar img{visibility:visible\n}\n.status{display:-ms-flexbox;display:flex;padding:0.6em\n}\n.status-conversation:last-child{border-bottom:none\n}\n.muted{padding:0.25em 0.5em\n}\n.muted button{margin-left:auto\n}\n.muted .muteWords{margin-left:10px\n}\na.unmute{display:block;margin-left:auto\n}\n.reply-left{-ms-flex:0;flex:0;min-width:48px\n}\n.reply-body{-ms-flex:1;flex:1\n}\n.timeline>.status-el:last-child{border-bottom-radius:0 0 10px 10px;border-radius:0 0 var(--panelRadius, 10px) var(--panelRadius, 10px)\n}\n@media all and (max-width: 960px){\n.status-el .retweet-info .avatar{margin-left:20px\n}\n.status{max-width:100%\n}\n.status .avatar{width:40px;height:40px\n}\n.status .avatar-compact{width:32px;height:32px\n}\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/status/status.vue","\n.attachments{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-0.7em\n}\n.attachments .attachment.media-upload-container{-ms-flex:0 0 auto;flex:0 0 auto;max-height:300px;max-width:100%\n}\n.attachments .placeholder{margin-right:0.5em\n}\n.attachments .small-attachment{max-height:100px\n}\n.attachments .small-attachment.image,.attachments .small-attachment.video{max-width:35%\n}\n.attachments .attachment{-ms-flex:1 0 30%;flex:1 0 30%;margin:0.5em 0.7em 0.6em 0.0em;-ms-flex-item-align:start;align-self:flex-start;line-height:0;border-style:solid;border-width:1px;border-radius:10px;border-radius:var(--attachmentRadius, 10px);border-color:#222;border-color:var(--border, #222);overflow:hidden\n}\n.attachments .fullwidth{-ms-flex-preferred-size:100%;flex-basis:100%\n}\n.attachments.video{line-height:0\n}\n.attachments.html{-ms-flex-preferred-size:90%;flex-basis:90%;width:100%;display:-ms-flexbox;display:flex\n}\n.attachments.loading{cursor:progress\n}\n.attachments .hider{position:absolute;margin:10px;padding:5px;background:rgba(230,230,230,0.6);font-weight:bold;z-index:4;line-height:1;border-radius:5px;border-radius:var(--tooltipRadius, 5px)\n}\n.attachments .small{max-height:100px\n}\n.attachments video{max-height:500px;height:100%;width:100%;z-index:0\n}\n.attachments audio{width:100%\n}\n.attachments img.media-upload{line-height:0;max-height:300px;max-width:100%\n}\n.attachments .oembed{line-height:1.2em;-ms-flex:1 0 100%;flex:1 0 100%;width:100%;margin-right:15px;display:-ms-flexbox;display:flex\n}\n.attachments .oembed img{width:100%\n}\n.attachments .oembed .image{-ms-flex:1;flex:1\n}\n.attachments .oembed .image img{border:0px;border-radius:5px;height:100%;object-fit:cover\n}\n.attachments .oembed .text{-ms-flex:2;flex:2;margin:8px;word-break:break-all\n}\n.attachments .oembed .text h1{font-size:14px;margin:0px\n}\n.attachments .image-attachment{display:-ms-flexbox;display:flex;-ms-flex:1;flex:1\n}\n.attachments .image-attachment .still-image{width:100%;height:100%\n}\n.attachments .image-attachment .small img{max-height:100px\n}\n.attachments .image-attachment img{object-fit:contain;width:100%;height:100%;max-height:500px;image-orientation:from-image\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/attachment/attachment.vue","\n.fav-active{cursor:pointer;animation-duration:0.6s\n}\n.fav-active:hover{color:orange;color:var(--cOrange, orange)\n}\n.favorite-button.icon-star{color:orange;color:var(--cOrange, orange)\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/favorite_button/favorite_button.vue","\n.rt-active{cursor:pointer;animation-duration:0.6s\n}\n.rt-active:hover{color:#0fa00f;color:var(--cGreen, #0fa00f)\n}\n.icon-retweet.retweeted{color:#0fa00f;color:var(--cGreen, #0fa00f)\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/retweet_button/retweet_button.vue","\n.icon-cancel,.delete-status{cursor:pointer\n}\n.icon-cancel:hover,.delete-status:hover{color:var(--cRed, red);color:red\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/delete_button/delete_button.vue","\n.user-finder-container{height:29px;max-width:100%\n}\n.user-finder-input{max-width:80%;vertical-align:middle\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/user_finder/user_finder.vue","\n.who-to-follow *{vertical-align:middle\n}\n.who-to-follow img{width:32px;height:32px\n}\n.who-to-follow p{line-height:40px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/who_to_follow_panel/who_to_follow_panel.vue","\n.floating-chat{position:fixed;right:0px;bottom:0px;z-index:1000\n}\n.chat-heading{cursor:pointer\n}\n.chat-heading .icon-comment-empty{color:#b9b9ba;color:var(--fg, #b9b9ba)\n}\n.chat-window{width:345px;max-height:40vh;overflow-y:auto;overflow-x:hidden\n}\n.chat-message{display:-ms-flexbox;display:flex;padding:0.2em 0.5em\n}\n.chat-avatar img{height:24px;width:24px;border-radius:4px;border-radius:var(--avatarRadius, 4px);margin-right:0.5em;margin-top:0.25em\n}\n.chat-input{display:-ms-flexbox;display:flex\n}\n.chat-input textarea{-ms-flex:1;flex:1;margin:0.6em;min-height:3.5em;resize:none\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/chat_panel/chat_panel.vue","\n.timeline .timeline-heading{position:relative;display:-ms-flexbox;display:flex\n}\n.timeline .title{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:70%\n}\n.timeline .loadmore-button{position:absolute;right:0.6em;font-size:14px;min-width:6em;height:1.8em;line-height:100%\n}\n.timeline .loadmore-text{position:absolute;right:0.6em;font-size:14px;min-width:6em;font-family:sans-serif;text-align:center;padding:0 0.5em 0 0.5em;opacity:0.8;background-color:transparent;color:rgba(185,185,186,0.5);color:var(--faint, rgba(185,185,186,0.5))\n}\n.timeline .loadmore-error{position:absolute;right:0.6em;font-size:14px;min-width:6em;font-family:sans-serif;text-align:center;padding:0 0.25em 0 0.25em;margin:0;color:#b9b9ba;color:var(--fg, #b9b9ba)\n}\n.new-status-notification{position:relative;margin-top:-1px;font-size:1.1em;border-width:1px 0 0 0;border-style:solid;border-color:var(--border, #222);padding:10px;z-index:1;background-color:#182230;background-color:var(--btn, #182230)\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/timeline/timeline.vue","\n.spacer{height:1em\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/status_or_conversation/status_or_conversation.vue","\n.name-and-screen-name{margin-left:0.7em;margin-top:0.0em;text-align:left;width:100%\n}\n.follows-you{margin-left:2em;float:right\n}\n.card{display:-ms-flexbox;display:flex;-ms-flex:1 0;flex:1 0;padding-top:0.6em;padding-right:1em;padding-bottom:0.6em;padding-left:1em;border-bottom:1px solid;margin:0;border-bottom-color:#222;border-bottom-color:var(--border, #222)\n}\n.card .avatar{margin-top:0.2em;width:32px;height:32px;border-radius:10px;border-radius:var(--avatarAltRadius, 10px)\n}\n.usercard{width:-webkit-fill-available;width:-moz-available;width:fill-available;margin:0.2em 0 0.7em 0;border-radius:10px;border-radius:var(--panelRadius, 10px);border-style:solid;border-color:#222;border-color:var(--border, #222);border-width:1px;overflow:hidden\n}\n.usercard .panel-heading{background:transparent\n}\n.usercard p{margin-bottom:0\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/user_card/user_card.vue","\n.user-profile{-ms-flex:2;flex:2;-ms-flex-preferred-size:500px;flex-basis:500px;padding-bottom:10px\n}\n.user-profile .panel-heading{background:transparent\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/user_profile/user_profile.vue","\n.setting-item{margin:1em 1em 1.4em\n}\n.setting-item textarea{width:100%;height:100px\n}\n.setting-item .old-avatar{width:128px;border-radius:4px;border-radius:var(--avatarRadius, 4px)\n}\n.setting-item .new-avatar{object-fit:cover;width:128px;height:128px;border-radius:4px;border-radius:var(--avatarRadius, 4px)\n}\n.setting-item .btn{margin-top:1em;min-height:28px;width:10em\n}\n.setting-list{list-style-type:none\n}\n.setting-list li{margin-bottom:0.5em\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/settings/settings.vue","\n.style-switcher{margin-right:1em\n}\n.radius-container,.color-container{display:-ms-flexbox;display:flex\n}\n.radius-container p,.color-container p{margin-top:2em;margin-bottom:.5em\n}\n.radius-container{-ms-flex-direction:column;flex-direction:column\n}\n.color-container{-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-pack:justify;justify-content:space-between\n}\n.radius-item,.color-item{min-width:20em;display:-ms-flexbox;display:flex;-ms-flex:1 1 0px;flex:1 1 0;-ms-flex-align:baseline;align-items:baseline;margin:5px 6px 5px 0\n}\n.radius-item label,.color-item label{color:var(--faint, rgba(185,185,186,0.5))\n}\n.radius-item{-ms-flex-preferred-size:auto;flex-basis:auto\n}\n.theme-radius-rn,.theme-color-cl{border:0;box-shadow:none;background:transparent;color:var(--faint, rgba(185,185,186,0.5));-ms-flex-item-align:stretch;-ms-grid-row-align:stretch;align-self:stretch\n}\n.theme-color-cl,.theme-radius-in,.theme-color-in{margin-left:4px\n}\n.theme-color-in{min-width:4em\n}\n.theme-radius-in{min-width:1em\n}\n.theme-radius-in,.theme-color-in{max-width:7em;-ms-flex:1;flex:1\n}\n.theme-radius-lb,.theme-color-lb{-ms-flex:2;flex:2;min-width:7em\n}\n.theme-radius-lb{max-width:50em\n}\n.theme-color-lb{max-width:10em\n}\n.theme-color-cl{padding:1px;max-width:8em;height:100%;-ms-flex:0;flex:0;min-width:2em;cursor:pointer\n}\n.theme-preview-content{padding:20px\n}\n.dummy .avatar{background:linear-gradient(135deg, #b8e1fc 0%, #a9d2f3 10%, #90bae4 25%, #90bcea 37%, #90bff0 50%, #6ba8e5 51%, #a2daf5 83%, #bdf3fd 100%);color:black;text-align:center;height:48px;line-height:48px;width:48px;float:left;margin-right:1em\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/style_switcher/style_switcher.vue","\n.registration-form{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;margin:0.6em\n}\n.registration-form .container{display:-ms-flexbox;display:flex;-ms-flex-direction:row;flex-direction:row\n}\n.registration-form .terms-of-service{-ms-flex:0 1 50%;flex:0 1 50%;margin:0.8em\n}\n.registration-form .text-fields{margin-top:0.6em;-ms-flex:1 0;flex:1 0;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column\n}\n.registration-form .form-group{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;padding:0.3em 0.0em 0.3em;line-height:24px\n}\n.registration-form form textarea{line-height:16px;resize:vertical\n}\n.registration-form .captcha{max-width:350px;margin-bottom:0.4em\n}\n.registration-form .btn{margin-top:0.6em;height:28px\n}\n.registration-form .error{text-align:center\n}\n@media all and (max-width: 959px){\n.registration-form .container{-ms-flex-direction:column-reverse;flex-direction:column-reverse\n}\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/registration/registration.vue","\n.profile-edit .bio{margin:0\n}\n.profile-edit input[type=file]{padding:5px\n}\n.profile-edit .banner{max-width:400px\n}\n.profile-edit .uploading{font-size:1.5em;margin:0.25em\n}\n\n\n\n// WEBPACK FOOTER //\n// webpack:///src/components/user_settings/user_settings.vue"],"sourceRoot":""} \ No newline at end of file diff --git a/priv/static/static/js/app.13c0bda10eb515cdf8ed.js b/priv/static/static/js/app.13c0bda10eb515cdf8ed.js deleted file mode 100644 index 4f78c6e22..000000000 Binary files a/priv/static/static/js/app.13c0bda10eb515cdf8ed.js and /dev/null differ diff --git a/priv/static/static/js/app.13c0bda10eb515cdf8ed.js.map b/priv/static/static/js/app.13c0bda10eb515cdf8ed.js.map deleted file mode 100644 index 04d474c8a..000000000 Binary files a/priv/static/static/js/app.13c0bda10eb515cdf8ed.js.map and /dev/null differ diff --git a/priv/static/static/js/app.de965bb2a0a8bffbeafa.js b/priv/static/static/js/app.de965bb2a0a8bffbeafa.js new file mode 100644 index 000000000..c9bc901d2 Binary files /dev/null and b/priv/static/static/js/app.de965bb2a0a8bffbeafa.js differ diff --git a/priv/static/static/js/app.de965bb2a0a8bffbeafa.js.map b/priv/static/static/js/app.de965bb2a0a8bffbeafa.js.map new file mode 100644 index 000000000..c6af67cc7 Binary files /dev/null and b/priv/static/static/js/app.de965bb2a0a8bffbeafa.js.map differ diff --git a/priv/static/static/js/manifest.16ab7851cdbf730f9cbc.js b/priv/static/static/js/manifest.16ab7851cdbf730f9cbc.js deleted file mode 100644 index e0b409bb5..000000000 Binary files a/priv/static/static/js/manifest.16ab7851cdbf730f9cbc.js and /dev/null differ diff --git a/priv/static/static/js/manifest.f2341edd686e54ee9b4a.js b/priv/static/static/js/manifest.f2341edd686e54ee9b4a.js new file mode 100644 index 000000000..1200d77b5 Binary files /dev/null and b/priv/static/static/js/manifest.f2341edd686e54ee9b4a.js differ diff --git a/priv/static/static/js/manifest.16ab7851cdbf730f9cbc.js.map b/priv/static/static/js/manifest.f2341edd686e54ee9b4a.js.map similarity index 92% rename from priv/static/static/js/manifest.16ab7851cdbf730f9cbc.js.map rename to priv/static/static/js/manifest.f2341edd686e54ee9b4a.js.map index ca7bfc238..df6a9e737 100644 Binary files a/priv/static/static/js/manifest.16ab7851cdbf730f9cbc.js.map and b/priv/static/static/js/manifest.f2341edd686e54ee9b4a.js.map differ diff --git a/priv/static/static/js/vendor.56aa9f8c34786f6af6b7.js.map b/priv/static/static/js/vendor.56aa9f8c34786f6af6b7.js.map deleted file mode 100644 index 6b780e63c..000000000 Binary files a/priv/static/static/js/vendor.56aa9f8c34786f6af6b7.js.map and /dev/null differ diff --git a/priv/static/static/js/vendor.56aa9f8c34786f6af6b7.js b/priv/static/static/js/vendor.a93310d51acbd9480094.js similarity index 90% rename from priv/static/static/js/vendor.56aa9f8c34786f6af6b7.js rename to priv/static/static/js/vendor.a93310d51acbd9480094.js index 480be658d..1882d9b64 100644 Binary files a/priv/static/static/js/vendor.56aa9f8c34786f6af6b7.js and b/priv/static/static/js/vendor.a93310d51acbd9480094.js differ diff --git a/priv/static/static/js/vendor.a93310d51acbd9480094.js.map b/priv/static/static/js/vendor.a93310d51acbd9480094.js.map new file mode 100644 index 000000000..8bcfffd0b Binary files /dev/null and b/priv/static/static/js/vendor.a93310d51acbd9480094.js.map differ diff --git a/test/list_test.exs b/test/list_test.exs index ced012093..da3b88024 100644 --- a/test/list_test.exs +++ b/test/list_test.exs @@ -74,4 +74,20 @@ test "getting all lists by an user" do assert list_two in lists refute list_three in lists end + + test "getting all lists the user is a member of" do + user = insert(:user) + other_user = insert(:user) + {:ok, list_one} = Pleroma.List.create("title", user) + {:ok, list_two} = Pleroma.List.create("other title", user) + {:ok, list_three} = Pleroma.List.create("third title", other_user) + {:ok, list_one} = Pleroma.List.follow(list_one, other_user) + {:ok, list_two} = Pleroma.List.follow(list_two, other_user) + {:ok, list_three} = Pleroma.List.follow(list_three, user) + + lists = Pleroma.List.get_lists_from_activity(%Pleroma.Activity{actor: other_user.ap_id}) + assert list_one in lists + assert list_two in lists + refute list_three in lists + end end diff --git a/test/upload_test.exs b/test/upload_test.exs index d68b3e7ba..09aa5e068 100644 --- a/test/upload_test.exs +++ b/test/upload_test.exs @@ -3,40 +3,58 @@ defmodule Pleroma.UploadTest do use Pleroma.DataCase describe "Storing a file" do - test "copies the file to the configured folder" do + test "copies the file to the configured folder with deduping" do + File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg") + file = %Plug.Upload{ content_type: "image/jpg", - path: Path.absname("test/fixtures/image.jpg"), + path: Path.absname("test/fixtures/image_tmp.jpg"), filename: "an [image.jpg" } - data = Upload.store(file) - assert data["name"] == "an [image.jpg" + data = Upload.store(file, true) - assert List.first(data["url"])["href"] == - "http://localhost:4001/media/#{data["uuid"]}/an%20%5Bimage.jpg" + assert data["name"] == + "e7a6d0cf595bff76f14c9a98b6c199539559e8b844e02e51e5efcfd1f614a2df.jpeg" end - test "fixes an incorrect content type" do + test "copies the file to the configured folder without deduping" do + File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg") + file = %Plug.Upload{ - content_type: "application/octet-stream", - path: Path.absname("test/fixtures/image.jpg"), + content_type: "image/jpg", + path: Path.absname("test/fixtures/image_tmp.jpg"), filename: "an [image.jpg" } - data = Upload.store(file) + data = Upload.store(file, false) + assert data["name"] == "an [image.jpg" + end + + test "fixes incorrect content type" do + File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg") + + file = %Plug.Upload{ + content_type: "application/octet-stream", + path: Path.absname("test/fixtures/image_tmp.jpg"), + filename: "an [image.jpg" + } + + data = Upload.store(file, true) assert hd(data["url"])["mediaType"] == "image/jpeg" end - test "does not modify a valid content type" do + test "adds missing extension" do + File.cp!("test/fixtures/image.jpg", "test/fixtures/image_tmp.jpg") + file = %Plug.Upload{ - content_type: "image/png", - path: Path.absname("test/fixtures/image.jpg"), - filename: "an [image.jpg" + content_type: "image/jpg", + path: Path.absname("test/fixtures/image_tmp.jpg"), + filename: "an [image" } - data = Upload.store(file) - assert hd(data["url"])["mediaType"] == "image/png" + data = Upload.store(file, false) + assert data["name"] == "an [image.jpg" end end end diff --git a/test/user_test.exs b/test/user_test.exs index 8c8cfd673..200352981 100644 --- a/test/user_test.exs +++ b/test/user_test.exs @@ -361,6 +361,27 @@ test "it unblocks users" do end end + describe "domain blocking" do + test "blocks domains" do + user = insert(:user) + collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"}) + + {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com") + + assert User.blocks?(user, collateral_user) + end + + test "unblocks domains" do + user = insert(:user) + collateral_user = insert(:user, %{ap_id: "https://awful-and-rude-instance.com/user/bully"}) + + {:ok, user} = User.block_domain(user, "awful-and-rude-instance.com") + {:ok, user} = User.unblock_domain(user, "awful-and-rude-instance.com") + + refute User.blocks?(user, collateral_user) + end + end + test "get recipients from activity" do actor = insert(:user) user = insert(:user, local: true) diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index 081c202b1..bc33b4dfc 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -318,11 +318,9 @@ test "unannouncing a previously announced object" do {:ok, announce_activity, object} = ActivityPub.announce(user, object) assert object.data["announcement_count"] == 1 - {:ok, unannounce_activity, activity, object} = ActivityPub.unannounce(user, object) + {:ok, unannounce_activity, object} = ActivityPub.unannounce(user, object) assert object.data["announcement_count"] == 0 - assert activity == announce_activity - assert unannounce_activity.data["to"] == [ User.ap_followers(user), announce_activity.data["actor"] diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs index 1291c3693..d1812457d 100644 --- a/test/web/mastodon_api/mastodon_api_controller_test.exs +++ b/test/web/mastodon_api/mastodon_api_controller_test.exs @@ -4,6 +4,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do alias Pleroma.Web.TwitterAPI.TwitterAPI alias Pleroma.{Repo, User, Activity, Notification} alias Pleroma.Web.{OStatus, CommonAPI} + alias Pleroma.Web.ActivityPub.ActivityPub import Pleroma.Factory import ExUnit.CaptureLog @@ -644,6 +645,73 @@ test "returns the relationships for the current user", %{conn: conn} do end end + describe "locked accounts" do + test "/api/v1/follow_requests works" do + user = insert(:user, %{info: %{"locked" => true}}) + other_user = insert(:user) + + {:ok, activity} = ActivityPub.follow(other_user, user) + + user = Repo.get(User, user.id) + other_user = Repo.get(User, other_user.id) + + assert User.following?(other_user, user) == false + + conn = + build_conn() + |> assign(:user, user) + |> get("/api/v1/follow_requests") + + assert [relationship] = json_response(conn, 200) + assert to_string(other_user.id) == relationship["id"] + end + + test "/api/v1/follow_requests/:id/authorize works" do + user = insert(:user, %{info: %{"locked" => true}}) + other_user = insert(:user) + + {:ok, activity} = ActivityPub.follow(other_user, user) + + user = Repo.get(User, user.id) + other_user = Repo.get(User, other_user.id) + + assert User.following?(other_user, user) == false + + conn = + build_conn() + |> assign(:user, user) + |> post("/api/v1/follow_requests/#{other_user.id}/authorize") + + assert relationship = json_response(conn, 200) + assert to_string(other_user.id) == relationship["id"] + + user = Repo.get(User, user.id) + other_user = Repo.get(User, other_user.id) + + assert User.following?(other_user, user) == true + end + + test "/api/v1/follow_requests/:id/reject works" do + user = insert(:user, %{info: %{"locked" => true}}) + other_user = insert(:user) + + {:ok, activity} = ActivityPub.follow(other_user, user) + + conn = + build_conn() + |> assign(:user, user) + |> post("/api/v1/follow_requests/#{other_user.id}/reject") + + assert relationship = json_response(conn, 200) + assert to_string(other_user.id) == relationship["id"] + + user = Repo.get(User, user.id) + other_user = Repo.get(User, other_user.id) + + assert User.following?(other_user, user) == false + end + end + test "account fetching", %{conn: conn} do user = insert(:user) @@ -792,6 +860,46 @@ test "getting a list of blocks", %{conn: conn} do assert [%{"id" => ^other_user_id}] = json_response(conn, 200) end + test "blocking / unblocking a domain", %{conn: conn} do + user = insert(:user) + other_user = insert(:user, %{ap_id: "https://dogwhistle.zone/@pundit"}) + + conn = + conn + |> assign(:user, user) + |> post("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"}) + + assert %{} = json_response(conn, 200) + user = User.get_cached_by_ap_id(user.ap_id) + assert User.blocks?(user, other_user) + + conn = + build_conn() + |> assign(:user, user) + |> delete("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"}) + + assert %{} = json_response(conn, 200) + user = User.get_cached_by_ap_id(user.ap_id) + refute User.blocks?(user, other_user) + end + + test "getting a list of domain blocks" do + user = insert(:user) + + {:ok, user} = User.block_domain(user, "bad.site") + {:ok, user} = User.block_domain(user, "even.worse.site") + + conn = + conn + |> assign(:user, user) + |> get("/api/v1/domain_blocks") + + domain_blocks = json_response(conn, 200) + + assert "bad.site" in domain_blocks + assert "even.worse.site" in domain_blocks + end + test "unimplemented mute endpoints" do user = insert(:user) other_user = insert(:user) diff --git a/test/web/mastodon_api/status_view_test.exs b/test/web/mastodon_api/status_view_test.exs index d9a0a8a95..d28c3cbad 100644 --- a/test/web/mastodon_api/status_view_test.exs +++ b/test/web/mastodon_api/status_view_test.exs @@ -64,11 +64,11 @@ test "a reply" do status = StatusView.render("status.json", %{activity: activity}) - assert status.in_reply_to_id == note.id + assert status.in_reply_to_id == to_string(note.id) [status] = StatusView.render("index.json", %{activities: [activity], as: :activity}) - assert status.in_reply_to_id == note.id + assert status.in_reply_to_id == to_string(note.id) end test "contains mentions" do diff --git a/test/web/twitter_api/twitter_api_controller_test.exs b/test/web/twitter_api/twitter_api_controller_test.exs index 68f4331df..806227110 100644 --- a/test/web/twitter_api/twitter_api_controller_test.exs +++ b/test/web/twitter_api/twitter_api_controller_test.exs @@ -580,6 +580,40 @@ test "with credentials", %{conn: conn, user: current_user} do end end + describe "POST /api/statuses/unretweet/:id" do + setup [:valid_user] + + test "without valid credentials", %{conn: conn} do + note_activity = insert(:note_activity) + conn = post(conn, "/api/statuses/unretweet/#{note_activity.id}.json") + assert json_response(conn, 403) == %{"error" => "Invalid credentials."} + end + + test "with credentials", %{conn: conn, user: current_user} do + note_activity = insert(:note_activity) + + request_path = "/api/statuses/retweet/#{note_activity.id}.json" + + _response = + conn + |> with_credentials(current_user.nickname, "test") + |> post(request_path) + + request_path = String.replace(request_path, "retweet", "unretweet") + + response = + conn + |> with_credentials(current_user.nickname, "test") + |> post(request_path) + + activity = Repo.get(Activity, note_activity.id) + activity_user = Repo.get_by(User, ap_id: note_activity.data["actor"]) + + assert json_response(response, 200) == + ActivityRepresenter.to_map(activity, %{user: activity_user, for: current_user}) + end + end + describe "POST /api/account/register" do test "it creates a new user", %{conn: conn} do data = %{ @@ -762,6 +796,38 @@ test "it updates a user's profile", %{conn: conn} do assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user}) end + + test "it locks an account", %{conn: conn} do + user = insert(:user) + + conn = + conn + |> assign(:user, user) + |> post("/api/account/update_profile.json", %{ + "locked" => "true" + }) + + user = Repo.get!(User, user.id) + assert user.info["locked"] == true + + assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user}) + end + + test "it unlocks an account", %{conn: conn} do + user = insert(:user) + + conn = + conn + |> assign(:user, user) + |> post("/api/account/update_profile.json", %{ + "locked" => "false" + }) + + user = Repo.get!(User, user.id) + assert user.info["locked"] == false + + assert json_response(conn, 200) == UserView.render("user.json", %{user: user, for: user}) + end end defp valid_user(_context) do @@ -926,4 +992,72 @@ test "with credentials and valid password", %{conn: conn, user: current_user} do :timer.sleep(1000) end end + + describe "GET /api/pleroma/friend_requests" do + test "it lists friend requests" do + user = insert(:user, %{info: %{"locked" => true}}) + other_user = insert(:user) + + {:ok, activity} = ActivityPub.follow(other_user, user) + + user = Repo.get(User, user.id) + other_user = Repo.get(User, other_user.id) + + assert User.following?(other_user, user) == false + + conn = + build_conn() + |> assign(:user, user) + |> get("/api/pleroma/friend_requests") + + assert [relationship] = json_response(conn, 200) + assert other_user.id == relationship["id"] + end + end + + describe "POST /api/pleroma/friendships/approve" do + test "it approves a friend request" do + user = insert(:user, %{info: %{"locked" => true}}) + other_user = insert(:user) + + {:ok, activity} = ActivityPub.follow(other_user, user) + + user = Repo.get(User, user.id) + other_user = Repo.get(User, other_user.id) + + assert User.following?(other_user, user) == false + + conn = + build_conn() + |> assign(:user, user) + |> post("/api/pleroma/friendships/approve", %{"user_id" => to_string(other_user.id)}) + + assert relationship = json_response(conn, 200) + assert other_user.id == relationship["id"] + assert relationship["follows_you"] == true + end + end + + describe "POST /api/pleroma/friendships/deny" do + test "it denies a friend request" do + user = insert(:user, %{info: %{"locked" => true}}) + other_user = insert(:user) + + {:ok, activity} = ActivityPub.follow(other_user, user) + + user = Repo.get(User, user.id) + other_user = Repo.get(User, other_user.id) + + assert User.following?(other_user, user) == false + + conn = + build_conn() + |> assign(:user, user) + |> post("/api/pleroma/friendships/deny", %{"user_id" => to_string(other_user.id)}) + + assert relationship = json_response(conn, 200) + assert other_user.id == relationship["id"] + assert relationship["follows_you"] == false + end + end end diff --git a/test/web/twitter_api/twitter_api_test.exs b/test/web/twitter_api/twitter_api_test.exs index edacb312d..06c1ba6ec 100644 --- a/test/web/twitter_api/twitter_api_test.exs +++ b/test/web/twitter_api/twitter_api_test.exs @@ -228,6 +228,17 @@ test "it retweets a status and returns the retweet" do assert status == updated_activity end + test "it unretweets an already retweeted status" do + user = insert(:user) + note_activity = insert(:note_activity) + + {:ok, _status} = TwitterAPI.repeat(user, note_activity.id) + {:ok, status} = TwitterAPI.unrepeat(user, note_activity.id) + updated_activity = Activity.get_by_ap_id(note_activity.data["id"]) + + assert status == updated_activity + end + test "it registers a new user and returns the user." do data = %{ "nickname" => "lain", diff --git a/test/web/twitter_api/views/user_view_test.exs b/test/web/twitter_api/views/user_view_test.exs index 9f8bf4cdc..eea743b32 100644 --- a/test/web/twitter_api/views/user_view_test.exs +++ b/test/web/twitter_api/views/user_view_test.exs @@ -59,7 +59,8 @@ test "A user" do "statusnet_profile_url" => user.ap_id, "cover_photo" => banner, "background_image" => nil, - "is_local" => true + "is_local" => true, + "locked" => false } assert represented == UserView.render("show.json", %{user: user}) @@ -94,7 +95,8 @@ test "A user for a given other follower", %{user: user} do "statusnet_profile_url" => user.ap_id, "cover_photo" => banner, "background_image" => nil, - "is_local" => true + "is_local" => true, + "locked" => false } assert represented == UserView.render("show.json", %{user: user, for: follower}) @@ -130,7 +132,8 @@ test "A user that follows you", %{user: user} do "statusnet_profile_url" => follower.ap_id, "cover_photo" => banner, "background_image" => nil, - "is_local" => true + "is_local" => true, + "locked" => false } assert represented == UserView.render("show.json", %{user: follower, for: user}) @@ -173,7 +176,8 @@ test "A blocked user for the blocker" do "statusnet_profile_url" => user.ap_id, "cover_photo" => banner, "background_image" => nil, - "is_local" => true + "is_local" => true, + "locked" => false } blocker = Repo.get(User, blocker.id)