mirror of
https://akkoma.dev/AkkomaGang/akkoma.git
synced 2024-11-09 09:52:13 +00:00
Merge branch 'develop' into 'patch-2'
# Conflicts: # mix.exs
This commit is contained in:
commit
f2fa09c50f
|
@ -13,6 +13,21 @@ 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`
|
||||
|
||||
## Uploads configuration
|
||||
|
||||
To configure where to upload files, and wether or not
|
||||
you want to remove automatically EXIF data from pictures
|
||||
being uploaded.
|
||||
|
||||
config :pleroma, Pleroma.Upload,
|
||||
uploads: "uploads",
|
||||
strip_exif: false
|
||||
|
||||
* `uploads`: where to put the uploaded files, relative to pleroma's main directory.
|
||||
* `strip_exif`: whether or not to remove EXIF data from uploaded pics automatically.
|
||||
This needs Imagemagick installed on the system ( apt install imagemagick ).
|
||||
|
||||
|
||||
## Block functionality
|
||||
|
||||
config :pleroma, :activitypub,
|
||||
|
|
|
@ -10,7 +10,11 @@ config :pleroma, ecto_repos: [Pleroma.Repo]
|
|||
|
||||
config :pleroma, Pleroma.Repo, types: Pleroma.PostgresTypes
|
||||
|
||||
config :pleroma, Pleroma.Upload, uploads: "uploads"
|
||||
config :pleroma, Pleroma.Upload,
|
||||
uploads: "uploads",
|
||||
strip_exif: false
|
||||
|
||||
config :pleroma, :emoji, shortcode_globs: ["/emoji/custom/**/*.png"]
|
||||
|
||||
# Configures the endpoint
|
||||
config :pleroma, Pleroma.Web.Endpoint,
|
||||
|
@ -50,6 +54,7 @@ config :pleroma, :instance,
|
|||
version: version,
|
||||
name: "Pleroma",
|
||||
email: "example@example.com",
|
||||
description: "A Pleroma instance, an alternative fediverse server",
|
||||
limit: 5000,
|
||||
upload_limit: 16_000_000,
|
||||
registrations_open: true,
|
||||
|
@ -58,6 +63,19 @@ config :pleroma, :instance,
|
|||
public: true,
|
||||
quarantined_instances: []
|
||||
|
||||
config :pleroma, :fe,
|
||||
theme: "pleroma-dark",
|
||||
logo: "/static/logo.png",
|
||||
background: "/static/aurora_borealis.jpg",
|
||||
redirect_root_no_login: "/main/all",
|
||||
redirect_root_login: "/main/friends",
|
||||
show_instance_panel: true,
|
||||
show_who_to_follow_panel: false,
|
||||
who_to_follow_provider:
|
||||
"https://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-osa-api.cgi?{{host}}+{{user}}",
|
||||
who_to_follow_link: "https://vinayaka.distsn.org/?{{host}}+{{user}}",
|
||||
scope_options_enabled: false
|
||||
|
||||
config :pleroma, :activitypub,
|
||||
accept_blocks: true,
|
||||
unfollow_blocked: true,
|
||||
|
@ -93,6 +111,13 @@ config :pleroma, :gopher,
|
|||
ip: {0, 0, 0, 0},
|
||||
port: 9999
|
||||
|
||||
config :pleroma, :suggestions,
|
||||
enabled: false,
|
||||
third_party_engine:
|
||||
"http://vinayaka.distsn.org/cgi-bin/vinayaka-user-match-suggestions-api.cgi?{{host}}+{{user}}",
|
||||
timeout: 300_000,
|
||||
web: "https://vinayaka.distsn.org/?{{host}}+{{user}}"
|
||||
|
||||
# Import environment specific config. This must remain at the bottom
|
||||
# of this file so it overrides the configuration defined above.
|
||||
import_config "#{Mix.env()}.exs"
|
||||
|
|
25
lib/mix/tasks/generate_invite_token.ex
Normal file
25
lib/mix/tasks/generate_invite_token.ex
Normal file
|
@ -0,0 +1,25 @@
|
|||
defmodule Mix.Tasks.GenerateInviteToken do
|
||||
use Mix.Task
|
||||
|
||||
@shortdoc "Generate invite token for user"
|
||||
def run([]) do
|
||||
Mix.Task.run("app.start")
|
||||
|
||||
with {:ok, token} <- Pleroma.UserInviteToken.create_token() do
|
||||
IO.puts("Generated user invite token")
|
||||
|
||||
IO.puts(
|
||||
"Url: #{
|
||||
Pleroma.Web.Router.Helpers.redirect_url(
|
||||
Pleroma.Web.Endpoint,
|
||||
:registration_page,
|
||||
token.token
|
||||
)
|
||||
}"
|
||||
)
|
||||
else
|
||||
_ ->
|
||||
IO.puts("Error creating token")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -78,4 +78,8 @@ defmodule Pleroma.Activity do
|
|||
end
|
||||
|
||||
def get_create_activity_by_object_ap_id(_), do: nil
|
||||
|
||||
def normalize(obj) when is_map(obj), do: Activity.get_by_ap_id(obj["id"])
|
||||
def normalize(ap_id) when is_binary(ap_id), do: Activity.get_by_ap_id(ap_id)
|
||||
def normalize(_), do: nil
|
||||
end
|
||||
|
|
|
@ -116,7 +116,28 @@ defmodule Pleroma.Formatter do
|
|||
_ -> []
|
||||
end)
|
||||
|
||||
@emoji @finmoji_with_filenames ++ @emoji_from_file
|
||||
@emoji_from_globs (
|
||||
static_path = Path.join(:code.priv_dir(:pleroma), "static")
|
||||
|
||||
globs =
|
||||
Application.get_env(:pleroma, :emoji, [])
|
||||
|> Keyword.get(:shortcode_globs, [])
|
||||
|
||||
paths =
|
||||
Enum.map(globs, fn glob ->
|
||||
Path.join(static_path, glob)
|
||||
|> Path.wildcard()
|
||||
end)
|
||||
|> Enum.concat()
|
||||
|
||||
Enum.map(paths, fn path ->
|
||||
shortcode = Path.basename(path, Path.extname(path))
|
||||
external_path = Path.join("/", Path.relative_to(path, static_path))
|
||||
{shortcode, external_path}
|
||||
end)
|
||||
)
|
||||
|
||||
@emoji @finmoji_with_filenames ++ @emoji_from_globs ++ @emoji_from_file
|
||||
|
||||
def emojify(text, emoji \\ @emoji)
|
||||
def emojify(text, nil), do: text
|
||||
|
@ -223,8 +244,8 @@ defmodule Pleroma.Formatter do
|
|||
|
||||
subs =
|
||||
subs ++
|
||||
Enum.map(tags, fn {_, tag, uuid} ->
|
||||
url = "<a href='#{Pleroma.Web.base_url()}/tag/#{tag}' rel='tag'>##{tag}</a>"
|
||||
Enum.map(tags, fn {tag_text, tag, uuid} ->
|
||||
url = "<a href='#{Pleroma.Web.base_url()}/tag/#{tag}' rel='tag'>#{tag_text}</a>"
|
||||
{uuid, url}
|
||||
end)
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ defmodule Pleroma.Gopher.Server.ProtocolHandler do
|
|||
|
||||
String.split(text, "\r")
|
||||
|> Enum.map(fn text ->
|
||||
"i#{text}\tfake\(NULL)\t0\r\n"
|
||||
"i#{text}\tfake\t(NULL)\t0\r\n"
|
||||
end)
|
||||
|> Enum.join("")
|
||||
end
|
||||
|
@ -77,14 +77,14 @@ defmodule Pleroma.Gopher.Server.ProtocolHandler do
|
|||
|
||||
link("Post ##{activity.id} by #{user.nickname}", "/notices/#{activity.id}") <>
|
||||
info("#{like_count} likes, #{announcement_count} repeats") <>
|
||||
"\r\n" <>
|
||||
"i\tfake\t(NULL)\t0\r\n" <>
|
||||
info(
|
||||
HtmlSanitizeEx.strip_tags(
|
||||
String.replace(activity.data["object"]["content"], "<br>", "\r")
|
||||
)
|
||||
)
|
||||
end)
|
||||
|> Enum.join("\r\n")
|
||||
|> Enum.join("i\tfake\t(NULL)\t0\r\n")
|
||||
end
|
||||
|
||||
def response("") do
|
||||
|
|
|
@ -27,6 +27,10 @@ defmodule Pleroma.Object do
|
|||
Repo.one(from(object in Object, where: fragment("(?)->>'id' = ?", object.data, ^ap_id)))
|
||||
end
|
||||
|
||||
def normalize(obj) when is_map(obj), do: Object.get_by_ap_id(obj["id"])
|
||||
def normalize(ap_id) when is_binary(ap_id), do: Object.get_by_ap_id(ap_id)
|
||||
def normalize(_), do: nil
|
||||
|
||||
def get_cached_by_ap_id(ap_id) do
|
||||
if Mix.env() == :test do
|
||||
get_by_ap_id(ap_id)
|
||||
|
|
10
lib/pleroma/plugs/digest.ex
Normal file
10
lib/pleroma/plugs/digest.ex
Normal file
|
@ -0,0 +1,10 @@
|
|||
defmodule Pleroma.Web.Plugs.DigestPlug do
|
||||
alias Plug.Conn
|
||||
require Logger
|
||||
|
||||
def read_body(conn, opts) do
|
||||
{:ok, body, conn} = Conn.read_body(conn, opts)
|
||||
digest = "SHA-256=" <> (:crypto.hash(:sha256, body) |> Base.encode64())
|
||||
{:ok, body, Conn.assign(conn, :digest, digest)}
|
||||
end
|
||||
end
|
|
@ -19,6 +19,8 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do
|
|||
|
||||
cond do
|
||||
signature && String.contains?(signature, user) ->
|
||||
# set (request-target) header to the appropriate value
|
||||
# we also replace the digest header with the one we computed
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header(
|
||||
|
@ -26,6 +28,14 @@ defmodule Pleroma.Web.Plugs.HTTPSignaturePlug do
|
|||
String.downcase("#{conn.method}") <> " #{conn.request_path}"
|
||||
)
|
||||
|
||||
conn =
|
||||
if conn.assigns[:digest] do
|
||||
conn
|
||||
|> put_req_header("digest", conn.assigns[:digest])
|
||||
else
|
||||
conn
|
||||
end
|
||||
|
||||
assign(conn, :valid_signature, HTTPSignatures.validate_conn(conn))
|
||||
|
||||
signature ->
|
||||
|
|
|
@ -18,8 +18,10 @@ defmodule Pleroma.Upload do
|
|||
File.cp!(file.path, result_file)
|
||||
end
|
||||
|
||||
strip_exif_data(content_type, result_file)
|
||||
|
||||
%{
|
||||
"type" => "Image",
|
||||
"type" => "Document",
|
||||
"url" => [
|
||||
%{
|
||||
"type" => "Link",
|
||||
|
@ -67,6 +69,8 @@ defmodule Pleroma.Upload do
|
|||
File.rename(uuidpath, result_file)
|
||||
end
|
||||
|
||||
strip_exif_data(content_type, result_file)
|
||||
|
||||
%{
|
||||
"type" => "Image",
|
||||
"url" => [
|
||||
|
@ -80,6 +84,16 @@ defmodule Pleroma.Upload do
|
|||
}
|
||||
end
|
||||
|
||||
def strip_exif_data(content_type, file) do
|
||||
settings = Application.get_env(:pleroma, Pleroma.Upload)
|
||||
do_strip = Keyword.fetch!(settings, :strip_exif)
|
||||
[filetype, ext] = String.split(content_type, "/")
|
||||
|
||||
if filetype == "image" and do_strip == true do
|
||||
Mogrify.open(file) |> Mogrify.custom("strip") |> Mogrify.save(in_place: true)
|
||||
end
|
||||
end
|
||||
|
||||
def upload_path do
|
||||
settings = Application.get_env(:pleroma, Pleroma.Upload)
|
||||
Keyword.fetch!(settings, :uploads)
|
||||
|
@ -110,20 +124,20 @@ defmodule Pleroma.Upload 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
|
||||
parts = String.split(file.filename, ".")
|
||||
|
||||
new_filename =
|
||||
if length(parts) > 1 do
|
||||
Enum.drop(parts, -1) |> Enum.join(".")
|
||||
else
|
||||
Enum.join(parts)
|
||||
end
|
||||
else
|
||||
file.filename
|
||||
|
||||
case type do
|
||||
"application/octet-stream" -> file.filename
|
||||
"audio/mpeg" -> new_filename <> ".mp3"
|
||||
"image/jpeg" -> new_filename <> ".jpg"
|
||||
_ -> Enum.join([new_filename, String.split(type, "/") |> List.last()], ".")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -398,6 +398,7 @@ defmodule Pleroma.User do
|
|||
Enum.map(reqs, fn req -> req.actor end)
|
||||
|> Enum.uniq()
|
||||
|> Enum.map(fn ap_id -> get_by_ap_id(ap_id) end)
|
||||
|> Enum.filter(fn u -> !following?(u, user) end)
|
||||
|
||||
{:ok, users}
|
||||
end
|
||||
|
@ -607,7 +608,7 @@ defmodule Pleroma.User do
|
|||
|> Enum.each(fn activity ->
|
||||
case activity.data["type"] do
|
||||
"Create" ->
|
||||
ActivityPub.delete(Object.get_by_ap_id(activity.data["object"]["id"]))
|
||||
ActivityPub.delete(Object.normalize(activity.data["object"]))
|
||||
|
||||
# TODO: Do something with likes, follows, repeats.
|
||||
_ ->
|
||||
|
|
40
lib/pleroma/user_invite_token.ex
Normal file
40
lib/pleroma/user_invite_token.ex
Normal file
|
@ -0,0 +1,40 @@
|
|||
defmodule Pleroma.UserInviteToken do
|
||||
use Ecto.Schema
|
||||
|
||||
import Ecto.Changeset
|
||||
|
||||
alias Pleroma.{User, UserInviteToken, Repo}
|
||||
|
||||
schema "user_invite_tokens" do
|
||||
field(:token, :string)
|
||||
field(:used, :boolean, default: false)
|
||||
|
||||
timestamps()
|
||||
end
|
||||
|
||||
def create_token do
|
||||
token = :crypto.strong_rand_bytes(32) |> Base.url_encode64()
|
||||
|
||||
token = %UserInviteToken{
|
||||
used: false,
|
||||
token: token
|
||||
}
|
||||
|
||||
Repo.insert(token)
|
||||
end
|
||||
|
||||
def used_changeset(struct) do
|
||||
struct
|
||||
|> cast(%{}, [])
|
||||
|> put_change(:used, true)
|
||||
end
|
||||
|
||||
def mark_as_used(token) do
|
||||
with %{used: false} = token <- Repo.get_by(UserInviteToken, %{token: token}),
|
||||
{:ok, token} <- Repo.update(used_changeset(token)) do
|
||||
{:ok, token}
|
||||
else
|
||||
_e -> {:error, token}
|
||||
end
|
||||
end
|
||||
end
|
|
@ -30,7 +30,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
end
|
||||
|
||||
def insert(map, local \\ true) when is_map(map) do
|
||||
with nil <- Activity.get_by_ap_id(map["id"]),
|
||||
with nil <- Activity.normalize(map),
|
||||
map <- lazy_put_activity_defaults(map),
|
||||
:ok <- check_actor_is_active(map["actor"]),
|
||||
{:ok, map} <- MRF.filter(map),
|
||||
|
@ -641,13 +641,23 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
Logger.info("Federating #{id} to #{inbox}")
|
||||
host = URI.parse(inbox).host
|
||||
|
||||
digest = "SHA-256=" <> (:crypto.hash(:sha256, json) |> Base.encode64())
|
||||
|
||||
signature =
|
||||
Pleroma.Web.HTTPSignatures.sign(actor, %{host: host, "content-length": byte_size(json)})
|
||||
Pleroma.Web.HTTPSignatures.sign(actor, %{
|
||||
host: host,
|
||||
"content-length": byte_size(json),
|
||||
digest: digest
|
||||
})
|
||||
|
||||
@httpoison.post(
|
||||
inbox,
|
||||
json,
|
||||
[{"Content-Type", "application/activity+json"}, {"signature", signature}],
|
||||
[
|
||||
{"Content-Type", "application/activity+json"},
|
||||
{"signature", signature},
|
||||
{"digest", digest}
|
||||
],
|
||||
hackney: [pool: :default]
|
||||
)
|
||||
end
|
||||
|
@ -670,7 +680,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
recv_timeout: 20000
|
||||
),
|
||||
{:ok, data} <- Jason.decode(body),
|
||||
nil <- Object.get_by_ap_id(data["id"]),
|
||||
nil <- Object.normalize(data),
|
||||
params <- %{
|
||||
"type" => "Create",
|
||||
"to" => data["to"],
|
||||
|
@ -679,7 +689,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
"object" => data
|
||||
},
|
||||
{:ok, activity} <- Transmogrifier.handle_incoming(params) do
|
||||
{:ok, Object.get_by_ap_id(activity.data["object"]["id"])}
|
||||
{:ok, Object.normalize(activity.data["object"])}
|
||||
else
|
||||
object = %Object{} ->
|
||||
{:ok, object}
|
||||
|
@ -688,7 +698,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||
Logger.info("Couldn't get object via AP, trying out OStatus fetching...")
|
||||
|
||||
case OStatus.fetch_activity_from_url(id) do
|
||||
{:ok, [activity | _]} -> {:ok, Object.get_by_ap_id(activity.data["object"]["id"])}
|
||||
{:ok, [activity | _]} -> {:ok, Object.normalize(activity.data["object"])}
|
||||
e -> e
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,18 +13,58 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
|
||||
require Logger
|
||||
|
||||
def get_actor(%{"actor" => actor}) when is_binary(actor) do
|
||||
actor
|
||||
end
|
||||
|
||||
def get_actor(%{"actor" => actor}) when is_list(actor) do
|
||||
Enum.at(actor, 0)
|
||||
end
|
||||
|
||||
def get_actor(%{"actor" => actor}) when is_map(actor) do
|
||||
actor["id"]
|
||||
end
|
||||
|
||||
def get_actor(%{"actor" => actor_list}) do
|
||||
Enum.find(actor_list, fn %{"type" => type} -> type == "Person" end)
|
||||
|> Map.get("id")
|
||||
end
|
||||
|
||||
@doc """
|
||||
Modifies an incoming AP object (mastodon format) to our internal format.
|
||||
"""
|
||||
def fix_object(object) do
|
||||
object
|
||||
|> Map.put("actor", object["attributedTo"])
|
||||
|> fix_actor
|
||||
|> fix_attachments
|
||||
|> fix_context
|
||||
|> fix_in_reply_to
|
||||
|> fix_emoji
|
||||
|> fix_tag
|
||||
|> fix_content_map
|
||||
|> fix_addressing
|
||||
end
|
||||
|
||||
def fix_addressing_list(map, field) do
|
||||
if is_binary(map[field]) do
|
||||
map
|
||||
|> Map.put(field, [map[field]])
|
||||
else
|
||||
map
|
||||
end
|
||||
end
|
||||
|
||||
def fix_addressing(map) do
|
||||
map
|
||||
|> fix_addressing_list("to")
|
||||
|> fix_addressing_list("cc")
|
||||
|> fix_addressing_list("bto")
|
||||
|> fix_addressing_list("bcc")
|
||||
end
|
||||
|
||||
def fix_actor(%{"attributedTo" => actor} = object) do
|
||||
object
|
||||
|> Map.put("actor", get_actor(%{"actor" => actor}))
|
||||
end
|
||||
|
||||
def fix_in_reply_to(%{"inReplyTo" => in_reply_to_id} = object)
|
||||
|
@ -122,7 +162,14 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
# TODO: validate those with a Ecto scheme
|
||||
# - tags
|
||||
# - emoji
|
||||
def handle_incoming(%{"type" => "Create", "object" => %{"type" => "Note"} = object} = data) do
|
||||
def handle_incoming(%{"type" => "Create", "object" => %{"type" => objtype} = object} = data)
|
||||
when objtype in ["Article", "Note"] do
|
||||
actor = get_actor(data)
|
||||
|
||||
data =
|
||||
Map.put(data, "actor", actor)
|
||||
|> fix_addressing
|
||||
|
||||
with nil <- Activity.get_create_activity_by_object_ap_id(object["id"]),
|
||||
%User{} = user <- User.get_or_fetch_by_ap_id(data["actor"]) do
|
||||
object = fix_object(data["object"])
|
||||
|
@ -412,7 +459,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
def handle_incoming(_), do: :error
|
||||
|
||||
def get_obj_helper(id) do
|
||||
if object = Object.get_by_ap_id(id), do: {:ok, object}, else: nil
|
||||
if object = Object.normalize(id), do: {:ok, object}, else: nil
|
||||
end
|
||||
|
||||
def set_reply_to_uri(%{"inReplyTo" => inReplyTo} = object) do
|
||||
|
@ -460,14 +507,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
# 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
|
||||
with follow_activity <- Activity.normalize(data["object"]) do
|
||||
object = %{
|
||||
"actor" => follow_activity.actor,
|
||||
"object" => follow_activity.data["object"],
|
||||
|
@ -485,14 +525,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||
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
|
||||
with follow_activity <- Activity.normalize(data["object"]) do
|
||||
object = %{
|
||||
"actor" => follow_activity.actor,
|
||||
"object" => follow_activity.data["object"],
|
||||
|
|
|
@ -128,7 +128,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
|||
Inserts a full object if it is contained in an activity.
|
||||
"""
|
||||
def insert_full_object(%{"object" => %{"type" => type} = object_data})
|
||||
when is_map(object_data) and type in ["Note"] do
|
||||
when is_map(object_data) and type in ["Article", "Note"] do
|
||||
with {:ok, _} <- Object.create(object_data) do
|
||||
:ok
|
||||
end
|
||||
|
|
|
@ -12,7 +12,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
|||
def render("user.json", %{user: user}) do
|
||||
{:ok, user} = WebFinger.ensure_keys_present(user)
|
||||
{:ok, _, public_key} = Salmon.keys_from_pem(user.info["keys"])
|
||||
public_key = :public_key.pem_entry_encode(:RSAPublicKey, public_key)
|
||||
public_key = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, public_key)
|
||||
public_key = :public_key.pem_encode([public_key])
|
||||
|
||||
%{
|
||||
|
@ -98,9 +98,6 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
|||
info = User.user_info(user)
|
||||
|
||||
params = %{
|
||||
"type" => ["Create", "Announce"],
|
||||
"actor_id" => user.ap_id,
|
||||
"whole_db" => true,
|
||||
"limit" => "10"
|
||||
}
|
||||
|
||||
|
@ -111,10 +108,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
|||
params
|
||||
end
|
||||
|
||||
activities = ActivityPub.fetch_public_activities(params)
|
||||
min_id = Enum.at(activities, 0).id
|
||||
|
||||
activities = Enum.reverse(activities)
|
||||
activities = ActivityPub.fetch_user_activities(user, nil, params)
|
||||
min_id = Enum.at(Enum.reverse(activities), 0).id
|
||||
max_id = Enum.at(activities, 0).id
|
||||
|
||||
collection =
|
||||
|
|
|
@ -7,7 +7,7 @@ defmodule Pleroma.Web.CommonAPI do
|
|||
|
||||
def delete(activity_id, user) do
|
||||
with %Activity{data: %{"object" => %{"id" => object_id}}} <- Repo.get(Activity, activity_id),
|
||||
%Object{} = object <- Object.get_by_ap_id(object_id),
|
||||
%Object{} = object <- Object.normalize(object_id),
|
||||
true <- user.info["is_moderator"] || user.ap_id == object.data["actor"],
|
||||
{:ok, delete} <- ActivityPub.delete(object) do
|
||||
{:ok, delete}
|
||||
|
@ -16,7 +16,7 @@ defmodule Pleroma.Web.CommonAPI do
|
|||
|
||||
def repeat(id_or_ap_id, user) do
|
||||
with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id),
|
||||
object <- Object.get_by_ap_id(activity.data["object"]["id"]) do
|
||||
object <- Object.normalize(activity.data["object"]["id"]) do
|
||||
ActivityPub.announce(user, object)
|
||||
else
|
||||
_ ->
|
||||
|
@ -26,7 +26,7 @@ defmodule Pleroma.Web.CommonAPI do
|
|||
|
||||
def unrepeat(id_or_ap_id, user) do
|
||||
with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id),
|
||||
object <- Object.get_by_ap_id(activity.data["object"]["id"]) do
|
||||
object <- Object.normalize(activity.data["object"]["id"]) do
|
||||
ActivityPub.unannounce(user, object)
|
||||
else
|
||||
_ ->
|
||||
|
@ -37,7 +37,7 @@ defmodule Pleroma.Web.CommonAPI do
|
|||
def favorite(id_or_ap_id, user) do
|
||||
with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id),
|
||||
false <- activity.data["actor"] == user.ap_id,
|
||||
object <- Object.get_by_ap_id(activity.data["object"]["id"]) do
|
||||
object <- Object.normalize(activity.data["object"]["id"]) do
|
||||
ActivityPub.like(user, object)
|
||||
else
|
||||
_ ->
|
||||
|
@ -48,7 +48,7 @@ defmodule Pleroma.Web.CommonAPI do
|
|||
def unfavorite(id_or_ap_id, user) do
|
||||
with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id),
|
||||
false <- activity.data["actor"] == user.ap_id,
|
||||
object <- Object.get_by_ap_id(activity.data["object"]["id"]) do
|
||||
object <- Object.normalize(activity.data["object"]["id"]) do
|
||||
ActivityPub.unlike(user, object)
|
||||
else
|
||||
_ ->
|
||||
|
|
|
@ -35,7 +35,8 @@ defmodule Pleroma.Web.Endpoint do
|
|||
parsers: [:urlencoded, :multipart, :json],
|
||||
pass: ["*/*"],
|
||||
json_decoder: Jason,
|
||||
length: Application.get_env(:pleroma, :instance) |> Keyword.get(:upload_limit)
|
||||
length: Application.get_env(:pleroma, :instance) |> Keyword.get(:upload_limit),
|
||||
body_reader: {Pleroma.Web.Plugs.DigestPlug, :read_body, []}
|
||||
)
|
||||
|
||||
plug(Plug.MethodOverride)
|
||||
|
|
|
@ -95,7 +95,7 @@ defmodule Pleroma.Web.Federator do
|
|||
params = Utils.normalize_params(params)
|
||||
|
||||
with {:ok, _user} <- ap_enabled_actor(params["actor"]),
|
||||
nil <- Activity.get_by_ap_id(params["id"]),
|
||||
nil <- Activity.normalize(params["id"]),
|
||||
{:ok, _activity} <- Transmogrifier.handle_incoming(params) do
|
||||
else
|
||||
%Activity{} ->
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
||||
use Pleroma.Web, :controller
|
||||
alias Pleroma.{Repo, Activity, User, Notification, Stats}
|
||||
alias Pleroma.{Repo, Object, Activity, User, Notification, Stats}
|
||||
alias Pleroma.Web
|
||||
alias Pleroma.Web.MastodonAPI.{StatusView, AccountView, MastodonView, ListView}
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
|
@ -11,6 +11,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
import Ecto.Query
|
||||
require Logger
|
||||
|
||||
@httpoison Application.get_env(:pleroma, :httpoison)
|
||||
|
||||
action_fallback(:errors)
|
||||
|
||||
def create_app(conn, params) do
|
||||
|
@ -125,7 +127,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
response = %{
|
||||
uri: Web.base_url(),
|
||||
title: Keyword.get(@instance, :name),
|
||||
description: "A Pleroma instance, an alternative fediverse server",
|
||||
description: Keyword.get(@instance, :description),
|
||||
version: "#{@mastodon_api_level} (compatible; #{Keyword.get(@instance, :version)})",
|
||||
email: Keyword.get(@instance, :email),
|
||||
urls: %{
|
||||
|
@ -428,16 +430,43 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
render(conn, AccountView, "relationships.json", %{user: user, targets: targets})
|
||||
end
|
||||
|
||||
def upload(%{assigns: %{user: _}} = conn, %{"file" => file}) do
|
||||
with {:ok, object} <- ActivityPub.upload(file) do
|
||||
def update_media(%{assigns: %{user: _}} = conn, data) do
|
||||
with %Object{} = object <- Repo.get(Object, data["id"]),
|
||||
true <- is_binary(data["description"]),
|
||||
description <- data["description"] do
|
||||
new_data = %{object.data | "name" => description}
|
||||
|
||||
change = Object.change(object, %{data: new_data})
|
||||
{:ok, media_obj} = Repo.update(change)
|
||||
|
||||
data =
|
||||
object.data
|
||||
new_data
|
||||
|> Map.put("id", object.id)
|
||||
|
||||
render(conn, StatusView, "attachment.json", %{attachment: data})
|
||||
end
|
||||
end
|
||||
|
||||
def upload(%{assigns: %{user: _}} = conn, %{"file" => file} = data) do
|
||||
with {:ok, object} <- ActivityPub.upload(file) do
|
||||
objdata =
|
||||
if Map.has_key?(data, "description") do
|
||||
Map.put(object.data, "name", data["description"])
|
||||
else
|
||||
object.data
|
||||
end
|
||||
|
||||
change = Object.change(object, %{data: objdata})
|
||||
{:ok, object} = Repo.update(change)
|
||||
|
||||
objdata =
|
||||
objdata
|
||||
|> Map.put("id", object.id)
|
||||
|
||||
render(conn, StatusView, "attachment.json", %{attachment: objdata})
|
||||
end
|
||||
end
|
||||
|
||||
def favourited_by(conn, %{"id" => id}) do
|
||||
with %Activity{data: %{"object" => %{"likes" => likes}}} <- Repo.get(Activity, id) do
|
||||
q = from(u in User, where: u.ap_id in ^likes)
|
||||
|
@ -873,7 +902,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
},
|
||||
compose: %{
|
||||
me: "#{user.id}",
|
||||
default_privacy: "public",
|
||||
default_privacy: user.info["default_scope"] || "public",
|
||||
default_sensitive: false
|
||||
},
|
||||
media_attachments: %{
|
||||
|
@ -1070,4 +1099,38 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||
|> put_status(500)
|
||||
|> json("Something went wrong")
|
||||
end
|
||||
|
||||
@suggestions Application.get_env(:pleroma, :suggestions)
|
||||
|
||||
def suggestions(%{assigns: %{user: user}} = conn, _) do
|
||||
if Keyword.get(@suggestions, :enabled, false) do
|
||||
api = Keyword.get(@suggestions, :third_party_engine, "")
|
||||
timeout = Keyword.get(@suggestions, :timeout, 5000)
|
||||
|
||||
host =
|
||||
Application.get_env(:pleroma, Pleroma.Web.Endpoint)
|
||||
|> Keyword.get(:url)
|
||||
|> Keyword.get(:host)
|
||||
|
||||
user = user.nickname
|
||||
url = String.replace(api, "{{host}}", host) |> String.replace("{{user}}", user)
|
||||
|
||||
with {:ok, %{status_code: 200, body: body}} <-
|
||||
@httpoison.get(url, [], timeout: timeout, recv_timeout: timeout),
|
||||
{:ok, data} <- Jason.decode(body) do
|
||||
data2 =
|
||||
Enum.slice(data, 0, 40)
|
||||
|> Enum.map(fn x ->
|
||||
Map.put(x, "id", User.get_or_fetch(x["acct"]).id)
|
||||
end)
|
||||
|
||||
conn
|
||||
|> json(data2)
|
||||
else
|
||||
e -> Logger.error("Could not retrieve suggestions at fetch #{url}, #{inspect(e)}")
|
||||
end
|
||||
else
|
||||
json(conn, [])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -14,6 +14,18 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
|||
header = User.banner_url(user) |> MediaProxy.url()
|
||||
user_info = User.user_info(user)
|
||||
|
||||
emojis =
|
||||
(user.info["source_data"]["tag"] || [])
|
||||
|> Enum.filter(fn %{"type" => t} -> t == "Emoji" end)
|
||||
|> Enum.map(fn %{"icon" => %{"url" => url}, "name" => name} ->
|
||||
%{
|
||||
"shortcode" => String.trim(name, ":"),
|
||||
"url" => MediaProxy.url(url),
|
||||
"static_url" => MediaProxy.url(url),
|
||||
"visible_in_picker" => false
|
||||
}
|
||||
end)
|
||||
|
||||
%{
|
||||
id: to_string(user.id),
|
||||
username: hd(String.split(user.nickname, "@")),
|
||||
|
@ -30,7 +42,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
|||
avatar_static: image,
|
||||
header: header,
|
||||
header_static: header,
|
||||
emojis: [],
|
||||
emojis: emojis,
|
||||
fields: [],
|
||||
source: %{
|
||||
note: "",
|
||||
|
|
|
@ -54,8 +54,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||
%{
|
||||
id: to_string(activity.id),
|
||||
uri: object,
|
||||
# TODO: This might be wrong, check with mastodon.
|
||||
url: nil,
|
||||
url: object,
|
||||
account: AccountView.render("account.json", %{user: user}),
|
||||
in_reply_to_id: nil,
|
||||
in_reply_to_account_id: nil,
|
||||
|
@ -128,7 +127,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||
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"]),
|
||||
content: render_content(object),
|
||||
created_at: created_at,
|
||||
reblogs_count: announcement_count,
|
||||
favourites_count: like_count,
|
||||
|
@ -170,7 +169,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||
remote_url: href,
|
||||
preview_url: MediaProxy.url(href),
|
||||
text_url: href,
|
||||
type: type
|
||||
type: type,
|
||||
description: attachment["name"]
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -207,4 +207,21 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||
"direct"
|
||||
end
|
||||
end
|
||||
|
||||
def render_content(%{"type" => "Article"} = object) do
|
||||
summary = object["name"]
|
||||
|
||||
content =
|
||||
if !!summary and summary != "" do
|
||||
"<p><a href=\"#{object["url"]}\">#{summary}</a></p>#{object["content"]}"
|
||||
else
|
||||
object["content"]
|
||||
end
|
||||
|
||||
HtmlSanitizeEx.basic_html(content)
|
||||
end
|
||||
|
||||
def render_content(object) do
|
||||
HtmlSanitizeEx.basic_html(object["content"])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,8 +4,6 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
|
|||
alias Pleroma.Stats
|
||||
alias Pleroma.Web
|
||||
|
||||
@instance Application.get_env(:pleroma, :instance)
|
||||
|
||||
def schemas(conn, _params) do
|
||||
response = %{
|
||||
links: [
|
||||
|
@ -21,20 +19,23 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
|
|||
|
||||
# Schema definition: https://github.com/jhass/nodeinfo/blob/master/schemas/2.0/schema.json
|
||||
def nodeinfo(conn, %{"version" => "2.0"}) do
|
||||
instance = Application.get_env(:pleroma, :instance)
|
||||
media_proxy = Application.get_env(:pleroma, :media_proxy)
|
||||
suggestions = Application.get_env(:pleroma, :suggestions)
|
||||
stats = Stats.get_stats()
|
||||
|
||||
response = %{
|
||||
version: "2.0",
|
||||
software: %{
|
||||
name: "pleroma",
|
||||
version: Keyword.get(@instance, :version)
|
||||
version: Keyword.get(instance, :version)
|
||||
},
|
||||
protocols: ["ostatus", "activitypub"],
|
||||
services: %{
|
||||
inbound: [],
|
||||
outbound: []
|
||||
},
|
||||
openRegistrations: Keyword.get(@instance, :registrations_open),
|
||||
openRegistrations: Keyword.get(instance, :registrations_open),
|
||||
usage: %{
|
||||
users: %{
|
||||
total: stats.user_count || 0
|
||||
|
@ -42,7 +43,16 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
|
|||
localPosts: stats.status_count || 0
|
||||
},
|
||||
metadata: %{
|
||||
nodeName: Keyword.get(@instance, :name)
|
||||
nodeName: Keyword.get(instance, :name),
|
||||
nodeDescription: Keyword.get(instance, :description),
|
||||
mediaProxy: Keyword.get(media_proxy, :enabled),
|
||||
private: !Keyword.get(instance, :public, true),
|
||||
suggestions: %{
|
||||
enabled: Keyword.get(suggestions, :enabled, false),
|
||||
thirdPartyEngine: Keyword.get(suggestions, :third_party_engine, ""),
|
||||
timeout: Keyword.get(suggestions, :timeout, 5000),
|
||||
web: Keyword.get(suggestions, :web, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -246,7 +246,7 @@ defmodule Pleroma.Web.OStatus.ActivityRepresenter do
|
|||
author = if with_author, do: [{:author, UserRepresenter.to_simple_form(user)}], else: []
|
||||
|
||||
mentions = (activity.recipients || []) |> get_mentions
|
||||
follow_activity = Activity.get_by_ap_id(follow_activity["id"])
|
||||
follow_activity = Activity.normalize(follow_activity)
|
||||
|
||||
[
|
||||
{:"activity:object-type", ['http://activitystrea.ms/schema/1.0/activity']},
|
||||
|
|
|
@ -6,7 +6,7 @@ defmodule Pleroma.Web.OStatus.DeleteHandler do
|
|||
|
||||
def handle_delete(entry, _doc \\ nil) do
|
||||
with id <- XML.string_from_xpath("//id", entry),
|
||||
object when not is_nil(object) <- Object.get_by_ap_id(id),
|
||||
%Object{} = object <- Object.normalize(id),
|
||||
{:ok, delete} <- ActivityPub.delete(object, false) do
|
||||
delete
|
||||
end
|
||||
|
|
|
@ -89,7 +89,7 @@ defmodule Pleroma.Web.OStatus do
|
|||
|
||||
def make_share(entry, doc, retweeted_activity) do
|
||||
with {:ok, actor} <- find_make_or_update_user(doc),
|
||||
%Object{} = object <- Object.get_by_ap_id(retweeted_activity.data["object"]["id"]),
|
||||
%Object{} = object <- Object.normalize(retweeted_activity.data["object"]),
|
||||
id when not is_nil(id) <- string_from_xpath("/entry/id", entry),
|
||||
{:ok, activity, _object} = ActivityPub.announce(actor, object, id, false) do
|
||||
{:ok, activity}
|
||||
|
@ -107,7 +107,7 @@ defmodule Pleroma.Web.OStatus do
|
|||
|
||||
def make_favorite(entry, doc, favorited_activity) do
|
||||
with {:ok, actor} <- find_make_or_update_user(doc),
|
||||
%Object{} = object <- Object.get_by_ap_id(favorited_activity.data["object"]["id"]),
|
||||
%Object{} = object <- Object.normalize(favorited_activity.data["object"]),
|
||||
id when not is_nil(id) <- string_from_xpath("/entry/id", entry),
|
||||
{:ok, activity, _object} = ActivityPub.like(actor, object, id, false) do
|
||||
{:ok, activity}
|
||||
|
|
|
@ -6,6 +6,7 @@ defmodule Pleroma.Web.OStatus.OStatusController do
|
|||
alias Pleroma.Repo
|
||||
alias Pleroma.Web.{OStatus, Federator}
|
||||
alias Pleroma.Web.XML
|
||||
alias Pleroma.Web.ActivityPub.ObjectView
|
||||
alias Pleroma.Web.ActivityPub.ActivityPubController
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
|
||||
|
@ -90,7 +91,7 @@ defmodule Pleroma.Web.OStatus.OStatusController do
|
|||
%User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
|
||||
case get_format(conn) do
|
||||
"html" -> redirect(conn, to: "/notice/#{activity.id}")
|
||||
_ -> represent_activity(conn, activity, user)
|
||||
_ -> represent_activity(conn, nil, activity, user)
|
||||
end
|
||||
else
|
||||
{:public?, false} ->
|
||||
|
@ -107,12 +108,12 @@ defmodule Pleroma.Web.OStatus.OStatusController do
|
|||
|
||||
def activity(conn, %{"uuid" => uuid}) do
|
||||
with id <- o_status_url(conn, :activity, uuid),
|
||||
{_, %Activity{} = activity} <- {:activity, Activity.get_by_ap_id(id)},
|
||||
{_, %Activity{} = activity} <- {:activity, Activity.normalize(id)},
|
||||
{_, true} <- {:public?, ActivityPub.is_public?(activity)},
|
||||
%User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
|
||||
case get_format(conn) do
|
||||
case format = get_format(conn) do
|
||||
"html" -> redirect(conn, to: "/notice/#{activity.id}")
|
||||
_ -> represent_activity(conn, activity, user)
|
||||
_ -> represent_activity(conn, format, activity, user)
|
||||
end
|
||||
else
|
||||
{:public?, false} ->
|
||||
|
@ -130,14 +131,14 @@ defmodule Pleroma.Web.OStatus.OStatusController do
|
|||
with {_, %Activity{} = activity} <- {:activity, Repo.get(Activity, id)},
|
||||
{_, true} <- {:public?, ActivityPub.is_public?(activity)},
|
||||
%User{} = user <- User.get_cached_by_ap_id(activity.data["actor"]) do
|
||||
case get_format(conn) do
|
||||
case format = get_format(conn) do
|
||||
"html" ->
|
||||
conn
|
||||
|> put_resp_content_type("text/html")
|
||||
|> send_file(200, "priv/static/index.html")
|
||||
|
||||
_ ->
|
||||
represent_activity(conn, activity, user)
|
||||
represent_activity(conn, format, activity, user)
|
||||
end
|
||||
else
|
||||
{:public?, false} ->
|
||||
|
@ -151,7 +152,13 @@ defmodule Pleroma.Web.OStatus.OStatusController do
|
|||
end
|
||||
end
|
||||
|
||||
defp represent_activity(conn, activity, user) do
|
||||
defp represent_activity(conn, "activity+json", activity, user) do
|
||||
conn
|
||||
|> put_resp_header("content-type", "application/activity+json")
|
||||
|> json(ObjectView.render("object.json", %{object: activity}))
|
||||
end
|
||||
|
||||
defp represent_activity(conn, _, activity, user) do
|
||||
response =
|
||||
activity
|
||||
|> ActivityRepresenter.to_simple_form(user, true)
|
||||
|
|
|
@ -127,6 +127,7 @@ defmodule Pleroma.Web.Router do
|
|||
get("/notifications/:id", MastodonAPIController, :get_notification)
|
||||
|
||||
post("/media", MastodonAPIController, :upload)
|
||||
put("/media/:id", MastodonAPIController, :update_media)
|
||||
|
||||
get("/lists", MastodonAPIController, :get_lists)
|
||||
get("/lists/:id", MastodonAPIController, :get_list)
|
||||
|
@ -140,6 +141,8 @@ defmodule Pleroma.Web.Router do
|
|||
get("/domain_blocks", MastodonAPIController, :domain_blocks)
|
||||
post("/domain_blocks", MastodonAPIController, :block_domain)
|
||||
delete("/domain_blocks", MastodonAPIController, :unblock_domain)
|
||||
|
||||
get("/suggestions", MastodonAPIController, :suggestions)
|
||||
end
|
||||
|
||||
scope "/api/web", Pleroma.Web.MastodonAPI do
|
||||
|
@ -201,9 +204,7 @@ defmodule Pleroma.Web.Router do
|
|||
get("/statuses/show/:id", TwitterAPI.Controller, :fetch_status)
|
||||
get("/statusnet/conversation/:id", TwitterAPI.Controller, :fetch_conversation)
|
||||
|
||||
if @registrations_open do
|
||||
post("/account/register", TwitterAPI.Controller, :register)
|
||||
end
|
||||
post("/account/register", TwitterAPI.Controller, :register)
|
||||
|
||||
get("/search", TwitterAPI.Controller, :search)
|
||||
get("/statusnet/tags/timeline/:tag", TwitterAPI.Controller, :public_and_external_timeline)
|
||||
|
@ -355,6 +356,7 @@ defmodule Pleroma.Web.Router do
|
|||
end
|
||||
|
||||
scope "/", Fallback do
|
||||
get("/registration/:token", RedirectController, :registration_page)
|
||||
get("/*path", RedirectController, :redirector)
|
||||
end
|
||||
end
|
||||
|
@ -369,4 +371,8 @@ defmodule Fallback.RedirectController do
|
|||
|> send_file(200, "priv/static/index.html")
|
||||
end
|
||||
end
|
||||
|
||||
def registration_page(conn, params) do
|
||||
redirector(conn, params)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -158,7 +158,7 @@ defmodule Pleroma.Web.Streamer do
|
|||
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"])
|
||||
parent = Object.normalize(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)})
|
||||
|
|
|
@ -99,6 +99,10 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
|
|||
conn
|
||||
|> render("followed.html", %{error: false})
|
||||
else
|
||||
# Was already following user
|
||||
{:error, "Could not follow user:" <> _rest} ->
|
||||
render(conn, "followed.html", %{error: false})
|
||||
|
||||
_e ->
|
||||
conn
|
||||
|> render("follow_login.html", %{
|
||||
|
@ -117,6 +121,11 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
|
|||
conn
|
||||
|> render("followed.html", %{error: false})
|
||||
else
|
||||
# Was already following user
|
||||
{:error, "Could not follow user:" <> _rest} ->
|
||||
conn
|
||||
|> render("followed.html", %{error: false})
|
||||
|
||||
e ->
|
||||
Logger.debug("Remote follow failed with error #{inspect(e)}")
|
||||
|
||||
|
@ -126,6 +135,8 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
|
|||
end
|
||||
|
||||
@instance Application.get_env(:pleroma, :instance)
|
||||
@instance_fe Application.get_env(:pleroma, :fe)
|
||||
@instance_chat Application.get_env(:pleroma, :chat)
|
||||
def config(conn, _params) do
|
||||
case get_format(conn) do
|
||||
"xml" ->
|
||||
|
@ -148,9 +159,24 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
|
|||
json(conn, %{
|
||||
site: %{
|
||||
name: Keyword.get(@instance, :name),
|
||||
description: Keyword.get(@instance, :description),
|
||||
server: Web.base_url(),
|
||||
textlimit: to_string(Keyword.get(@instance, :limit)),
|
||||
closed: if(Keyword.get(@instance, :registrations_open), do: "0", else: "1")
|
||||
closed: if(Keyword.get(@instance, :registrations_open), do: "0", else: "1"),
|
||||
private: if(Keyword.get(@instance, :public, true), do: "0", else: "1"),
|
||||
pleromafe: %{
|
||||
theme: Keyword.get(@instance_fe, :theme),
|
||||
background: Keyword.get(@instance_fe, :background),
|
||||
logo: Keyword.get(@instance_fe, :logo),
|
||||
redirectRootNoLogin: Keyword.get(@instance_fe, :redirect_root_no_login),
|
||||
redirectRootLogin: Keyword.get(@instance_fe, :redirect_root_login),
|
||||
chatDisabled: !Keyword.get(@instance_chat, :enabled),
|
||||
showInstanceSpecificPanel: Keyword.get(@instance_fe, :show_instance_panel),
|
||||
showWhoToFollowPanel: Keyword.get(@instance_fe, :show_who_to_follow_panel),
|
||||
scopeOptionsEnabled: Keyword.get(@instance_fe, :scope_options_enabled),
|
||||
whoToFollowProvider: Keyword.get(@instance_fe, :who_to_follow_provider),
|
||||
whoToFollowLink: Keyword.get(@instance_fe, :who_to_follow_link)
|
||||
}
|
||||
}
|
||||
})
|
||||
end
|
||||
|
|
|
@ -4,7 +4,7 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do
|
|||
use Pleroma.Web.TwitterAPI.Representers.BaseRepresenter
|
||||
alias Pleroma.Web.TwitterAPI.Representers.ObjectRepresenter
|
||||
alias Pleroma.{Activity, User}
|
||||
alias Pleroma.Web.TwitterAPI.{TwitterAPI, UserView}
|
||||
alias Pleroma.Web.TwitterAPI.{TwitterAPI, UserView, ActivityView}
|
||||
alias Pleroma.Web.CommonAPI.Utils
|
||||
alias Pleroma.Formatter
|
||||
|
||||
|
@ -164,14 +164,7 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do
|
|||
|
||||
tags = if possibly_sensitive, do: Enum.uniq(["nsfw" | tags]), else: tags
|
||||
|
||||
summary = activity.data["object"]["summary"]
|
||||
|
||||
content =
|
||||
if !!summary and summary != "" do
|
||||
"<span>#{activity.data["object"]["summary"]}</span><br />#{content}</span>"
|
||||
else
|
||||
content
|
||||
end
|
||||
{summary, content} = ActivityView.render_content(object)
|
||||
|
||||
html =
|
||||
HtmlSanitizeEx.basic_html(content)
|
||||
|
@ -198,7 +191,8 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do
|
|||
"tags" => tags,
|
||||
"activity_type" => "post",
|
||||
"possibly_sensitive" => possibly_sensitive,
|
||||
"visibility" => Pleroma.Web.MastodonAPI.StatusView.get_visibility(object)
|
||||
"visibility" => Pleroma.Web.MastodonAPI.StatusView.get_visibility(object),
|
||||
"summary" => object["summary"]
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
|
||||
alias Pleroma.{User, Activity, Repo, Object}
|
||||
alias Pleroma.{UserInviteToken, User, Activity, Repo, Object}
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
alias Pleroma.Web.TwitterAPI.UserView
|
||||
alias Pleroma.Web.{OStatus, CommonAPI}
|
||||
import Ecto.Query
|
||||
|
||||
@instance Application.get_env(:pleroma, :instance)
|
||||
@httpoison Application.get_env(:pleroma, :httpoison)
|
||||
@registrations_open Keyword.get(@instance, :registrations_open)
|
||||
|
||||
def create_status(%User{} = user, %{"status" => _} = data) do
|
||||
CommonAPI.post(user, data)
|
||||
|
@ -120,6 +122,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
|
|||
end
|
||||
|
||||
def register_user(params) do
|
||||
tokenString = params["token"]
|
||||
|
||||
params = %{
|
||||
nickname: params["nickname"],
|
||||
name: params["fullname"],
|
||||
|
@ -129,17 +133,33 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
|
|||
password_confirmation: params["confirm"]
|
||||
}
|
||||
|
||||
changeset = User.register_changeset(%User{}, params)
|
||||
# no need to query DB if registration is open
|
||||
token =
|
||||
unless @registrations_open || is_nil(tokenString) do
|
||||
Repo.get_by(UserInviteToken, %{token: tokenString})
|
||||
end
|
||||
|
||||
with {:ok, user} <- Repo.insert(changeset) do
|
||||
{:ok, user}
|
||||
else
|
||||
{:error, changeset} ->
|
||||
errors =
|
||||
Ecto.Changeset.traverse_errors(changeset, fn {msg, _opts} -> msg end)
|
||||
|> Jason.encode!()
|
||||
cond do
|
||||
@registrations_open || (!is_nil(token) && !token.used) ->
|
||||
changeset = User.register_changeset(%User{}, params)
|
||||
|
||||
{:error, %{error: errors}}
|
||||
with {:ok, user} <- Repo.insert(changeset) do
|
||||
!@registrations_open && UserInviteToken.mark_as_used(token.token)
|
||||
{:ok, user}
|
||||
else
|
||||
{:error, changeset} ->
|
||||
errors =
|
||||
Ecto.Changeset.traverse_errors(changeset, fn {msg, _opts} -> msg end)
|
||||
|> Jason.encode!()
|
||||
|
||||
{:error, %{error: errors}}
|
||||
end
|
||||
|
||||
!@registrations_open && is_nil(token) ->
|
||||
{:error, "Invalid token"}
|
||||
|
||||
!@registrations_open && token.used ->
|
||||
{:error, "Expired token"}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -431,6 +431,19 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
|
|||
user
|
||||
end
|
||||
|
||||
user =
|
||||
if default_scope = params["default_scope"] do
|
||||
with new_info <- Map.put(user.info, "default_scope", default_scope),
|
||||
change <- User.info_changeset(user, %{info: new_info}),
|
||||
{:ok, user} <- User.update_and_set_cache(change) do
|
||||
user
|
||||
else
|
||||
_e -> user
|
||||
end
|
||||
else
|
||||
user
|
||||
end
|
||||
|
||||
with changeset <- User.update_changeset(user, params),
|
||||
{:ok, user} <- User.update_and_set_cache(changeset) do
|
||||
CommonAPI.update(user)
|
||||
|
|
|
@ -228,15 +228,7 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do
|
|||
|
||||
tags = if possibly_sensitive, do: Enum.uniq(["nsfw" | tags]), else: tags
|
||||
|
||||
summary = activity.data["object"]["summary"]
|
||||
content = object["content"]
|
||||
|
||||
content =
|
||||
if !!summary and summary != "" do
|
||||
"<span>#{activity.data["object"]["summary"]}</span><br />#{content}</span>"
|
||||
else
|
||||
content
|
||||
end
|
||||
{summary, content} = render_content(object)
|
||||
|
||||
html =
|
||||
HtmlSanitizeEx.basic_html(content)
|
||||
|
@ -263,7 +255,41 @@ defmodule Pleroma.Web.TwitterAPI.ActivityView do
|
|||
"tags" => tags,
|
||||
"activity_type" => "post",
|
||||
"possibly_sensitive" => possibly_sensitive,
|
||||
"visibility" => Pleroma.Web.MastodonAPI.StatusView.get_visibility(object)
|
||||
"visibility" => Pleroma.Web.MastodonAPI.StatusView.get_visibility(object),
|
||||
"summary" => summary
|
||||
}
|
||||
end
|
||||
|
||||
def render_content(%{"type" => "Note"} = object) do
|
||||
summary = object["summary"]
|
||||
|
||||
content =
|
||||
if !!summary and summary != "" do
|
||||
"<p>#{summary}</p>#{object["content"]}"
|
||||
else
|
||||
object["content"]
|
||||
end
|
||||
|
||||
{summary, content}
|
||||
end
|
||||
|
||||
def render_content(%{"type" => "Article"} = object) do
|
||||
summary = object["name"] || object["summary"]
|
||||
|
||||
content =
|
||||
if !!summary and summary != "" do
|
||||
"<p><a href=\"#{object["url"]}\">#{summary}</a></p>#{object["content"]}"
|
||||
else
|
||||
object["content"]
|
||||
end
|
||||
|
||||
{summary, content}
|
||||
end
|
||||
|
||||
def render_content(object) do
|
||||
summary = object["summary"] || "Unhandled activity type: #{object["type"]}"
|
||||
content = "<p>#{summary}</p>#{object["content"]}"
|
||||
|
||||
{summary, content}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
defmodule Pleroma.Web.TwitterAPI.UserView do
|
||||
use Pleroma.Web, :view
|
||||
alias Pleroma.User
|
||||
alias Pleroma.Formatter
|
||||
alias Pleroma.Web.CommonAPI.Utils
|
||||
alias Pleroma.Web.MediaProxy
|
||||
|
||||
|
@ -28,9 +29,19 @@ defmodule Pleroma.Web.TwitterAPI.UserView do
|
|||
|
||||
user_info = User.get_cached_user_info(user)
|
||||
|
||||
emoji =
|
||||
(user.info["source_data"]["tag"] || [])
|
||||
|> Enum.filter(fn %{"type" => t} -> t == "Emoji" end)
|
||||
|> Enum.map(fn %{"icon" => %{"url" => url}, "name" => name} ->
|
||||
{String.trim(name, ":"), url}
|
||||
end)
|
||||
|
||||
bio = HtmlSanitizeEx.strip_tags(user.bio)
|
||||
|
||||
data = %{
|
||||
"created_at" => user.inserted_at |> Utils.format_naive_asctime(),
|
||||
"description" => HtmlSanitizeEx.strip_tags(user.bio),
|
||||
"description" => bio,
|
||||
"description_html" => bio |> Formatter.emojify(emoji),
|
||||
"favourites_count" => 0,
|
||||
"followers_count" => user_info[:follower_count],
|
||||
"following" => following,
|
||||
|
@ -39,6 +50,7 @@ defmodule Pleroma.Web.TwitterAPI.UserView do
|
|||
"friends_count" => user_info[:following_count],
|
||||
"id" => user.id,
|
||||
"name" => user.name,
|
||||
"name_html" => HtmlSanitizeEx.strip_tags(user.name) |> Formatter.emojify(emoji),
|
||||
"profile_image_url" => image,
|
||||
"profile_image_url_https" => image,
|
||||
"profile_image_url_profile_size" => image,
|
||||
|
@ -52,7 +64,8 @@ defmodule Pleroma.Web.TwitterAPI.UserView do
|
|||
"cover_photo" => User.banner_url(user) |> MediaProxy.url(),
|
||||
"background_image" => image_url(user.info["background"]) |> MediaProxy.url(),
|
||||
"is_local" => user.local,
|
||||
"locked" => !!user.info["locked"]
|
||||
"locked" => !!user.info["locked"],
|
||||
"default_scope" => user.info["default_scope"] || "public"
|
||||
}
|
||||
|
||||
if assigns[:token] do
|
||||
|
|
1
mix.exs
1
mix.exs
|
@ -45,6 +45,7 @@ defmodule Pleroma.Mixfile do
|
|||
{:cachex, "~> 3.0.2"},
|
||||
{:httpoison, "~> 1.2.0"},
|
||||
{:jason, "~> 1.0"},
|
||||
{:mogrify, "~> 0.6.1"}
|
||||
{:ex_machina, "~> 2.2", only: :test},
|
||||
{:credo, "~> 0.9.3", only: [:dev, :test]},
|
||||
{:mock, "~> 0.3.1", only: :test}
|
||||
|
|
1
mix.lock
1
mix.lock
|
@ -25,6 +25,7 @@
|
|||
"mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"},
|
||||
"mochiweb": {:hex, :mochiweb, "2.15.0", "e1daac474df07651e5d17cc1e642c4069c7850dc4508d3db7263a0651330aacc", [:rebar3], [], "hexpm"},
|
||||
"mock": {:hex, :mock, "0.3.1", "994f00150f79a0ea50dc9d86134cd9ebd0d177ad60bd04d1e46336cdfdb98ff9", [:mix], [{:meck, "~> 0.8.8", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
"mogrify": {:hex, :mogrify, "0.6.1", "de1b527514f2d95a7bbe9642eb556061afb337e220cf97adbf3a4e6438ed70af", [:mix], [], "hexpm"},
|
||||
"parse_trans": {:hex, :parse_trans, "3.2.0", "2adfa4daf80c14dc36f522cf190eb5c4ee3e28008fc6394397c16f62a26258c2", [:rebar3], [], "hexpm"},
|
||||
"pbkdf2_elixir": {:hex, :pbkdf2_elixir, "0.12.3", "6706a148809a29c306062862c803406e88f048277f6e85b68faf73291e820b84", [:mix], [], "hexpm"},
|
||||
"phoenix": {:hex, :phoenix, "1.3.2", "2a00d751f51670ea6bc3f2ba4e6eb27ecb8a2c71e7978d9cd3e5de5ccf7378bd", [:mix], [{:cowboy, "~> 1.0", [hex: :cowboy, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.3.3 or ~> 1.4", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
defmodule Pleroma.Repo.Migrations.CreateUserInviteTokens do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
create table(:user_invite_tokens) do
|
||||
add :token, :string
|
||||
add :used, :boolean, default: false
|
||||
|
||||
timestamps()
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1 +1 @@
|
|||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>Pleroma</title><link rel=icon type=image/png href=/favicon.png><link rel=stylesheet href=/static/font/css/fontello.css><link rel=stylesheet href=/static/font/css/animation.css><link href=/static/css/app.5d0189b6f119febde070b703869bbd06.css rel=stylesheet></head><body style="display: none"><div id=app></div><script type=text/javascript src=/static/js/manifest.f2341edd686e54ee9b4a.js></script><script type=text/javascript src=/static/js/vendor.a93310d51acbd9480094.js></script><script type=text/javascript src=/static/js/app.de965bb2a0a8bffbeafa.js></script></body></html>
|
||||
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>Pleroma</title><link rel=icon type=image/png href=/favicon.png><link rel=stylesheet href=/static/font/css/fontello.css><link rel=stylesheet href=/static/font/css/animation.css><link href=/static/css/app.4e316dc76ab907cb78bb88b978ce04e2.css rel=stylesheet></head><body style="display: none"><div id=app></div><script type=text/javascript src=/static/js/manifest.212bbb8f66cdc9a7eebf.js></script><script type=text/javascript src=/static/js/vendor.da712c56a19114013b34.js></script><script type=text/javascript src=/static/js/app.9d52d5cd0ef719b7db59.js></script></body></html>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,2 +1,2 @@
|
|||
webpackJsonp([69],{658:function(e,c,t){"use strict";function o(e){var c=e.detail,t=c[0],o=document.querySelector('[data-id="'+t.id+'"]');o&&o.parentNode.removeChild(o)}Object.defineProperty(c,"__esModule",{value:!0});var n=t(144);t.n(n);[].forEach.call(document.querySelectorAll(".trash-button"),function(e){e.addEventListener("ajax:success",o)});Object(n.delegate)(document,"#batch_checkbox_all","change",function(e){var c=e.target;[].forEach.call(document.querySelectorAll('.batch-checkbox input[type="checkbox"]'),function(e){e.checked=c.checked})}),Object(n.delegate)(document,'.batch-checkbox input[type="checkbox"]',"change",function(){var e=document.querySelector("#batch_checkbox_all");e&&(e.checked=[].every.call(document.querySelectorAll('.batch-checkbox input[type="checkbox"]'),function(e){return e.checked}))}),Object(n.delegate)(document,".media-spoiler-show-button","click",function(){[].forEach.call(document.querySelectorAll("button.media-spoiler"),function(e){e.click()})}),Object(n.delegate)(document,".media-spoiler-hide-button","click",function(){[].forEach.call(document.querySelectorAll(".spoiler-button.spoiler-button--visible button"),function(e){e.click()})})}},[658]);
|
||||
webpackJsonp([85],{661:function(e,c,t){"use strict";function o(e){var c=e.detail,t=c[0],o=document.querySelector('[data-id="'+t.id+'"]');o&&o.parentNode.removeChild(o)}Object.defineProperty(c,"__esModule",{value:!0});var n=t(152);t.n(n);[].forEach.call(document.querySelectorAll(".trash-button"),function(e){e.addEventListener("ajax:success",o)});var l='.batch-checkbox input[type="checkbox"]';Object(n.delegate)(document,"#batch_checkbox_all","change",function(e){var c=e.target;[].forEach.call(document.querySelectorAll(l),function(e){e.checked=c.checked})}),Object(n.delegate)(document,l,"change",function(){var e=document.querySelector("#batch_checkbox_all");e&&(e.checked=[].every.call(document.querySelectorAll(l),function(e){return e.checked}),e.indeterminate=!e.checked&&[].some.call(document.querySelectorAll(l),function(e){return e.checked}))}),Object(n.delegate)(document,".media-spoiler-show-button","click",function(){[].forEach.call(document.querySelectorAll("button.media-spoiler"),function(e){e.click()})}),Object(n.delegate)(document,".media-spoiler-hide-button","click",function(){[].forEach.call(document.querySelectorAll(".spoiler-button.spoiler-button--visible button"),function(e){e.click()})})}},[661]);
|
||||
//# sourceMappingURL=admin.js.map
|
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,5 @@
|
|||
CACHE MANIFEST
|
||||
#ver:2018-4-9 21:57:37
|
||||
#ver:2018-8-12 18:01:32
|
||||
#plugin:4.8.4
|
||||
|
||||
CACHE:
|
||||
|
@ -13,33 +13,46 @@ CACHE:
|
|||
/packs/features/home_timeline.js
|
||||
/packs/features/public_timeline.js
|
||||
/packs/features/community_timeline.js
|
||||
/packs/features/favourited_statuses.js
|
||||
/packs/features/list_timeline.js
|
||||
/packs/features/direct_timeline.js
|
||||
/packs/features/pinned_statuses.js
|
||||
/packs/features/domain_blocks.js
|
||||
/packs/features/following.js
|
||||
/packs/features/followers.js
|
||||
/packs/features/favourited_statuses.js
|
||||
/packs/features/list_timeline.js
|
||||
/packs/features/account_gallery.js
|
||||
/packs/features/hashtag_timeline.js
|
||||
/packs/features/status.js
|
||||
/packs/features/account_gallery.js
|
||||
/packs/features/blocks.js
|
||||
/packs/features/lists.js
|
||||
/packs/modals/report_modal.js
|
||||
/packs/features/getting_started.js
|
||||
/packs/features/follow_requests.js
|
||||
/packs/features/mutes.js
|
||||
/packs/features/blocks.js
|
||||
/packs/features/reblogs.js
|
||||
/packs/features/favourites.js
|
||||
/packs/features/getting_started.js
|
||||
/packs/features/keyboard_shortcuts.js
|
||||
/packs/modals/mute_modal.js
|
||||
/packs/features/generic_not_found.js
|
||||
/packs/features/list_editor.js
|
||||
/packs/modals/embed_modal.js
|
||||
/packs/status/media_gallery.js
|
||||
/packs/containers/media_container.js
|
||||
/packs/share.js
|
||||
/packs/application.js
|
||||
/packs/about.js
|
||||
/packs/public.js
|
||||
/packs/mailer.js
|
||||
/packs/mastodon-light.js
|
||||
/packs/contrast.js
|
||||
/packs/default.js
|
||||
/packs/public.js
|
||||
/packs/admin.js
|
||||
/packs/common.js
|
||||
/packs/common.css
|
||||
/packs/mailer.css
|
||||
/packs/default.css
|
||||
/packs/contrast.css
|
||||
/packs/mastodon-light.css
|
||||
/packs/manifest.json
|
||||
|
||||
NETWORK:
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
priv/static/packs/containers/media_container.js
Normal file
2
priv/static/packs/containers/media_container.js
Normal file
File diff suppressed because one or more lines are too long
1
priv/static/packs/containers/media_container.js.map
Normal file
1
priv/static/packs/containers/media_container.js.map
Normal file
File diff suppressed because one or more lines are too long
2
priv/static/packs/contrast.css
Normal file
2
priv/static/packs/contrast.css
Normal file
File diff suppressed because one or more lines are too long
1
priv/static/packs/contrast.css.map
Normal file
1
priv/static/packs/contrast.css.map
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":[],"names":[],"mappings":"","file":"contrast.css","sourceRoot":""}
|
2
priv/static/packs/contrast.js
Normal file
2
priv/static/packs/contrast.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
webpackJsonp([82],{803:function(n,c){}},[803]);
|
||||
//# sourceMappingURL=contrast.js.map
|
1
priv/static/packs/contrast.js.map
Normal file
1
priv/static/packs/contrast.js.map
Normal file
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["webpack:///contrast.js"],"names":["webpackJsonp","803","module","exports"],"mappings":"AAAAA,cAAc,KAERC,IACA,SAAUC,EAAQC,OAMrB","file":"contrast.js","sourcesContent":["webpackJsonp([82],{\n\n/***/ 803:\n/***/ (function(module, exports) {\n\n// removed by extract-text-webpack-plugin\n\n/***/ })\n\n},[803]);\n\n\n// WEBPACK FOOTER //\n// contrast.js"],"sourceRoot":""}
|
File diff suppressed because one or more lines are too long
|
@ -1,2 +1,2 @@
|
|||
webpackJsonp([68],{799:function(n,c){}},[799]);
|
||||
webpackJsonp([83],{802:function(n,c){}},[802]);
|
||||
//# sourceMappingURL=default.js.map
|
|
@ -1 +1 @@
|
|||
{"version":3,"sources":["webpack:///default.js"],"names":["webpackJsonp","799","module","exports"],"mappings":"AAAAA,cAAc,KAERC,IACA,SAAUC,EAAQC,OAMrB","file":"default.js","sourcesContent":["webpackJsonp([68],{\n\n/***/ 799:\n/***/ (function(module, exports) {\n\n// removed by extract-text-webpack-plugin\n\n/***/ })\n\n},[799]);\n\n\n// WEBPACK FOOTER //\n// default.js"],"sourceRoot":""}
|
||||
{"version":3,"sources":["webpack:///default.js"],"names":["webpackJsonp","802","module","exports"],"mappings":"AAAAA,cAAc,KAERC,IACA,SAAUC,EAAQC,OAMrB","file":"default.js","sourcesContent":["webpackJsonp([83],{\n\n/***/ 802:\n/***/ (function(module, exports) {\n\n// removed by extract-text-webpack-plugin\n\n/***/ })\n\n},[802]);\n\n\n// WEBPACK FOOTER //\n// default.js"],"sourceRoot":""}
|
Binary file not shown.
Before Width: | Height: | Size: 40 KiB |
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 11 KiB |
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 17 KiB |
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 11 KiB |
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 8.3 KiB |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
priv/static/packs/features/direct_timeline.js
Normal file
2
priv/static/packs/features/direct_timeline.js
Normal file
File diff suppressed because one or more lines are too long
1
priv/static/packs/features/direct_timeline.js.map
Normal file
1
priv/static/packs/features/direct_timeline.js.map
Normal file
File diff suppressed because one or more lines are too long
2
priv/static/packs/features/domain_blocks.js
Normal file
2
priv/static/packs/features/domain_blocks.js
Normal file
File diff suppressed because one or more lines are too long
1
priv/static/packs/features/domain_blocks.js.map
Normal file
1
priv/static/packs/features/domain_blocks.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,2 +1,2 @@
|
|||
webpackJsonp([23],{150:function(n,e,i){"use strict";i.d(e,"a",function(){return v});var t=i(2),r=i.n(t),o=i(1),a=i.n(o),c=i(3),l=i.n(c),u=i(4),s=i.n(u),d=i(0),f=i.n(d),h=i(10),p=i.n(h),v=function(n){function e(){var i,t,r;a()(this,e);for(var o=arguments.length,c=Array(o),u=0;u<o;u++)c[u]=arguments[u];return i=t=l()(this,n.call.apply(n,[this].concat(c))),t.handleClick=function(){t.props.onClick()},r=i,l()(t,r)}return s()(e,n),e.prototype.render=function(){var n=this.props,e=n.icon,i=n.type,t=n.active,o=n.columnHeaderId,a="";return e&&(a=r()("i",{className:"fa fa-fw fa-"+e+" column-header__icon"})),r()("h1",{className:p()("column-header",{active:t}),id:o||null},void 0,r()("button",{onClick:this.handleClick},void 0,a,i))},e}(f.a.PureComponent)},284:function(n,e,i){"use strict";i.d(e,"a",function(){return g});var t=i(2),r=i.n(t),o=i(1),a=i.n(o),c=i(3),l=i.n(c),u=i(4),s=i.n(u),d=i(34),f=i.n(d),h=i(0),p=i.n(h),v=i(150),b=i(91),m=i(35),g=function(n){function e(){var i,t,r;a()(this,e);for(var o=arguments.length,c=Array(o),u=0;u<o;u++)c[u]=arguments[u];return i=t=l()(this,n.call.apply(n,[this].concat(c))),t.handleHeaderClick=function(){var n=t.node.querySelector(".scrollable");n&&(t._interruptScrollAnimation=Object(b.b)(n))},t.handleScroll=f()(function(){void 0!==t._interruptScrollAnimation&&t._interruptScrollAnimation()},200),t.setRef=function(n){t.node=n},r=i,l()(t,r)}return s()(e,n),e.prototype.scrollTop=function(){var n=this.node.querySelector(".scrollable");n&&(this._interruptScrollAnimation=Object(b.b)(n))},e.prototype.render=function(){var n=this.props,e=n.heading,i=n.icon,t=n.children,o=n.active,a=n.hideHeadingOnMobile,c=e&&(!a||a&&!Object(m.b)(window.innerWidth)),l=c&&e.replace(/ /g,"-"),u=c&&r()(v.a,{icon:i,active:o,type:e,onClick:this.handleHeaderClick,columnHeaderId:l});return p.a.createElement("div",{ref:this.setRef,role:"region","aria-labelledby":l,className:"column",onScroll:this.handleScroll},u,t)},e}(p.a.PureComponent)},820:function(n,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var t=i(2),r=i.n(t),o=i(0),a=(i.n(o),i(284)),c=i(843),l=function(){return r()(a.a,{},void 0,r()(c.a,{}))};e.default=l},843:function(n,e,i){"use strict";var t=i(2),r=i.n(t),o=i(0),a=(i.n(o),i(6)),c=function(){return r()("div",{className:"regeneration-indicator missing-indicator"},void 0,r()("div",{},void 0,r()("div",{className:"regeneration-indicator__label"},void 0,r()(a.b,{id:"missing_indicator.label",tagName:"strong",defaultMessage:"Not found"}),r()(a.b,{id:"missing_indicator.sublabel",defaultMessage:"This resource could not be found"}))))};e.a=c}});
|
||||
webpackJsonp([30],{155:function(n,e,i){"use strict";i.d(e,"a",function(){return v});var t=i(2),r=i.n(t),o=i(1),a=i.n(o),c=i(3),l=i.n(c),u=i(4),s=i.n(u),d=i(0),f=i.n(d),h=i(10),p=i.n(h),v=function(n){function e(){var i,t,r;a()(this,e);for(var o=arguments.length,c=Array(o),u=0;u<o;u++)c[u]=arguments[u];return i=t=l()(this,n.call.apply(n,[this].concat(c))),t.handleClick=function(){t.props.onClick()},r=i,l()(t,r)}return s()(e,n),e.prototype.render=function(){var n=this.props,e=n.icon,i=n.type,t=n.active,o=n.columnHeaderId,a="";return e&&(a=r()("i",{className:"fa fa-fw fa-"+e+" column-header__icon"})),r()("h1",{className:p()("column-header",{active:t}),id:o||null},void 0,r()("button",{onClick:this.handleClick},void 0,a,i))},e}(f.a.PureComponent)},274:function(n,e,i){"use strict";i.d(e,"a",function(){return g});var t=i(2),r=i.n(t),o=i(1),a=i.n(o),c=i(3),l=i.n(c),u=i(4),s=i.n(u),d=i(32),f=i.n(d),h=i(0),p=i.n(h),v=i(155),m=i(91),b=i(43),g=function(n){function e(){var i,t,r;a()(this,e);for(var o=arguments.length,c=Array(o),u=0;u<o;u++)c[u]=arguments[u];return i=t=l()(this,n.call.apply(n,[this].concat(c))),t.handleHeaderClick=function(){var n=t.node.querySelector(".scrollable");n&&(t._interruptScrollAnimation=Object(m.b)(n))},t.handleScroll=f()(function(){void 0!==t._interruptScrollAnimation&&t._interruptScrollAnimation()},200),t.setRef=function(n){t.node=n},r=i,l()(t,r)}return s()(e,n),e.prototype.scrollTop=function(){var n=this.node.querySelector(".scrollable");n&&(this._interruptScrollAnimation=Object(m.b)(n))},e.prototype.render=function(){var n=this.props,e=n.heading,i=n.icon,t=n.children,o=n.active,a=n.hideHeadingOnMobile,c=e&&(!a||a&&!Object(b.b)(window.innerWidth)),l=c&&e.replace(/ /g,"-"),u=c&&r()(v.a,{icon:i,active:o,type:e,onClick:this.handleHeaderClick,columnHeaderId:l});return p.a.createElement("div",{ref:this.setRef,role:"region","aria-labelledby":l,className:"column",onScroll:this.handleScroll},u,t)},e}(p.a.PureComponent)},829:function(n,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var t=i(2),r=i.n(t),o=i(0),a=(i.n(o),i(274)),c=i(866),l=function(){return r()(a.a,{},void 0,r()(c.a,{}))};e.default=l},866:function(n,e,i){"use strict";var t=i(2),r=i.n(t),o=i(0),a=(i.n(o),i(7)),c=function(){return r()("div",{className:"regeneration-indicator missing-indicator"},void 0,r()("div",{},void 0,r()("div",{className:"regeneration-indicator__figure"}),r()("div",{className:"regeneration-indicator__label"},void 0,r()(a.b,{id:"missing_indicator.label",tagName:"strong",defaultMessage:"Not found"}),r()(a.b,{id:"missing_indicator.sublabel",defaultMessage:"This resource could not be found"}))))};e.a=c}});
|
||||
//# sourceMappingURL=generic_not_found.js.map
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue