Merge branch 'develop' into 'feature/relay'
# Conflicts: # lib/pleroma/web/activity_pub/utils.ex
This commit is contained in:
commit
0f5bff8c66
@ -16,6 +16,8 @@ config :pleroma, Pleroma.Upload,
|
|||||||
|
|
||||||
config :pleroma, :emoji, shortcode_globs: ["/emoji/custom/**/*.png"]
|
config :pleroma, :emoji, shortcode_globs: ["/emoji/custom/**/*.png"]
|
||||||
|
|
||||||
|
config :pleroma, :uri_schemes, additionnal_schemes: []
|
||||||
|
|
||||||
# Configures the endpoint
|
# Configures the endpoint
|
||||||
config :pleroma, Pleroma.Web.Endpoint,
|
config :pleroma, Pleroma.Web.Endpoint,
|
||||||
url: [host: "localhost"],
|
url: [host: "localhost"],
|
||||||
@ -71,11 +73,8 @@ config :pleroma, :fe,
|
|||||||
redirect_root_no_login: "/main/all",
|
redirect_root_no_login: "/main/all",
|
||||||
redirect_root_login: "/main/friends",
|
redirect_root_login: "/main/friends",
|
||||||
show_instance_panel: true,
|
show_instance_panel: true,
|
||||||
show_who_to_follow_panel: false,
|
scope_options_enabled: false,
|
||||||
who_to_follow_provider:
|
collapse_message_with_subject: false
|
||||||
"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,
|
config :pleroma, :activitypub,
|
||||||
accept_blocks: true,
|
accept_blocks: true,
|
||||||
@ -112,6 +111,13 @@ config :pleroma, :gopher,
|
|||||||
ip: {0, 0, 0, 0},
|
ip: {0, 0, 0, 0},
|
||||||
port: 9999
|
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
|
# Import environment specific config. This must remain at the bottom
|
||||||
# of this file so it overrides the configuration defined above.
|
# of this file so it overrides the configuration defined above.
|
||||||
import_config "#{Mix.env()}.exs"
|
import_config "#{Mix.env()}.exs"
|
||||||
|
@ -1,8 +1,32 @@
|
|||||||
social.domain.tld {
|
social.domain.tld {
|
||||||
tls user@domain.tld
|
log /var/log/caddy/pleroma_access.log
|
||||||
|
errors /var/log/caddy/pleroma_error.log
|
||||||
|
|
||||||
log /var/log/caddy/pleroma.log
|
gzip
|
||||||
|
|
||||||
|
proxy / localhost:4000 {
|
||||||
|
websocket
|
||||||
|
transparent
|
||||||
|
}
|
||||||
|
|
||||||
|
tls user@domain.tld {
|
||||||
|
# Remove the rest of the lines in here, if you want to support older devices
|
||||||
|
key_type p256
|
||||||
|
ciphers ECDHE-ECDSA-WITH-CHACHA20-POLY1305 ECDHE-RSA-WITH-CHACHA20-POLY1305 ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-RSA-AES256-GCM-SHA384 ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-RSA-AES128-GCM-SHA256
|
||||||
|
}
|
||||||
|
|
||||||
|
header / {
|
||||||
|
X-XSS-Protection "1; mode=block"
|
||||||
|
X-Frame-Options "DENY"
|
||||||
|
X-Content-Type-Options "nosniff"
|
||||||
|
Referrer-Policy "same-origin"
|
||||||
|
Strict-Transport-Security "max-age=31536000; includeSubDomains;"
|
||||||
|
Expect-CT "enforce, max-age=2592000"
|
||||||
|
}
|
||||||
|
|
||||||
|
# If you do not want remote frontends to be able to access your Pleroma backend server, remove these lines.
|
||||||
|
# If you want to allow all origins access, remove the origin lines.
|
||||||
|
# To use this directive, you need the http.cors plugin for Caddy.
|
||||||
cors / {
|
cors / {
|
||||||
origin https://halcyon.domain.tld
|
origin https://halcyon.domain.tld
|
||||||
origin https://pinafore.domain.tld
|
origin https://pinafore.domain.tld
|
||||||
@ -10,9 +34,13 @@ social.domain.tld {
|
|||||||
allowed_headers Authorization,Content-Type,Idempotency-Key
|
allowed_headers Authorization,Content-Type,Idempotency-Key
|
||||||
exposed_headers Link,X-RateLimit-Reset,X-RateLimit-Limit,X-RateLimit-Remaining,X-Request-Id
|
exposed_headers Link,X-RateLimit-Reset,X-RateLimit-Limit,X-RateLimit-Remaining,X-Request-Id
|
||||||
}
|
}
|
||||||
|
# Stop removing lines here.
|
||||||
|
|
||||||
proxy / localhost:4000 {
|
# If you do not want to use the mediaproxy function, remove these lines.
|
||||||
websocket
|
# To use this directive, you need the http.cache plugin for Caddy.
|
||||||
transparent
|
cache {
|
||||||
|
match_path /proxy
|
||||||
|
default_max_age 720m
|
||||||
}
|
}
|
||||||
|
# Stop removing lines here.
|
||||||
}
|
}
|
||||||
|
21
installation/init.d/pleroma
Executable file
21
installation/init.d/pleroma
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
#!/sbin/openrc-run
|
||||||
|
|
||||||
|
# Requires OpenRC >= 0.35
|
||||||
|
directory=~pleroma/pleroma
|
||||||
|
|
||||||
|
command=/usr/bin/mix
|
||||||
|
command_args="phx.server"
|
||||||
|
command_user=pleroma:pleroma
|
||||||
|
command_background=1
|
||||||
|
|
||||||
|
export PORT=4000
|
||||||
|
export MIX_ENV=prod
|
||||||
|
|
||||||
|
# Ask process to terminate within 30 seconds, otherwise kill it
|
||||||
|
retry="SIGTERM/30 SIGKILL/5"
|
||||||
|
|
||||||
|
pidfile="/var/run/pleroma.pid"
|
||||||
|
|
||||||
|
depend() {
|
||||||
|
need nginx postgresql
|
||||||
|
}
|
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
|
@ -16,7 +16,7 @@ defmodule Pleroma.Formatter do
|
|||||||
def parse_mentions(text) do
|
def parse_mentions(text) do
|
||||||
# Modified from https://www.w3.org/TR/html5/forms.html#valid-e-mail-address
|
# Modified from https://www.w3.org/TR/html5/forms.html#valid-e-mail-address
|
||||||
regex =
|
regex =
|
||||||
~r/@[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@?[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*/u
|
~r/@[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]*@?[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*/u
|
||||||
|
|
||||||
Regex.scan(regex, text)
|
Regex.scan(regex, text)
|
||||||
|> List.flatten()
|
|> List.flatten()
|
||||||
@ -165,8 +165,29 @@ defmodule Pleroma.Formatter do
|
|||||||
@emoji
|
@emoji
|
||||||
end
|
end
|
||||||
|
|
||||||
@link_regex ~r/https?:\/\/[\w\.\/?=\-#\+%&@~'\(\):]+[\w\/]/u
|
@link_regex ~r/[0-9a-z+\-\.]+:[0-9a-z$-_.+!*'(),]+/ui
|
||||||
|
|
||||||
|
# IANA got a list https://www.iana.org/assignments/uri-schemes/ but
|
||||||
|
# Stuff like ipfs isn’t in it
|
||||||
|
# There is very niche stuff
|
||||||
|
@uri_schemes [
|
||||||
|
"https://",
|
||||||
|
"http://",
|
||||||
|
"dat://",
|
||||||
|
"dweb://",
|
||||||
|
"gopher://",
|
||||||
|
"ipfs://",
|
||||||
|
"ipns://",
|
||||||
|
"irc:",
|
||||||
|
"ircs:",
|
||||||
|
"magnet:",
|
||||||
|
"mailto:",
|
||||||
|
"mumble:",
|
||||||
|
"ssb://",
|
||||||
|
"xmpp:"
|
||||||
|
]
|
||||||
|
|
||||||
|
# TODO: make it use something other than @link_regex
|
||||||
def html_escape(text) do
|
def html_escape(text) do
|
||||||
Regex.split(@link_regex, text, include_captures: true)
|
Regex.split(@link_regex, text, include_captures: true)
|
||||||
|> Enum.map_every(2, fn chunk ->
|
|> Enum.map_every(2, fn chunk ->
|
||||||
@ -176,11 +197,18 @@ defmodule Pleroma.Formatter do
|
|||||||
|> Enum.join("")
|
|> Enum.join("")
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc "changes http:... links to html links"
|
@doc "changes scheme:... urls to html links"
|
||||||
def add_links({subs, text}) do
|
def add_links({subs, text}) do
|
||||||
|
additionnal_schemes =
|
||||||
|
Application.get_env(:pleroma, :uri_schemes, [])
|
||||||
|
|> Keyword.get(:additionnal_schemes, [])
|
||||||
|
|
||||||
links =
|
links =
|
||||||
Regex.scan(@link_regex, text)
|
text
|
||||||
|> Enum.map(fn [url] -> {Ecto.UUID.generate(), url} end)
|
|> String.split([" ", "\t", "<br>"])
|
||||||
|
|> Enum.filter(fn word -> String.starts_with?(word, @uri_schemes ++ additionnal_schemes) end)
|
||||||
|
|> Enum.filter(fn word -> Regex.match?(@link_regex, word) end)
|
||||||
|
|> Enum.map(fn url -> {Ecto.UUID.generate(), url} end)
|
||||||
|> Enum.sort_by(fn {_, url} -> -String.length(url) end)
|
|> Enum.sort_by(fn {_, url} -> -String.length(url) end)
|
||||||
|
|
||||||
uuid_text =
|
uuid_text =
|
||||||
@ -244,8 +272,8 @@ defmodule Pleroma.Formatter do
|
|||||||
|
|
||||||
subs =
|
subs =
|
||||||
subs ++
|
subs ++
|
||||||
Enum.map(tags, fn {_, tag, uuid} ->
|
Enum.map(tags, fn {tag_text, tag, uuid} ->
|
||||||
url = "<a href='#{Pleroma.Web.base_url()}/tag/#{tag}' rel='tag'>##{tag}</a>"
|
url = "<a href='#{Pleroma.Web.base_url()}/tag/#{tag}' rel='tag'>#{tag_text}</a>"
|
||||||
{uuid, url}
|
{uuid, url}
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ defmodule Pleroma.Gopher.Server.ProtocolHandler do
|
|||||||
|
|
||||||
String.split(text, "\r")
|
String.split(text, "\r")
|
||||||
|> Enum.map(fn text ->
|
|> Enum.map(fn text ->
|
||||||
"i#{text}\tfake\(NULL)\t0\r\n"
|
"i#{text}\tfake\t(NULL)\t0\r\n"
|
||||||
end)
|
end)
|
||||||
|> Enum.join("")
|
|> Enum.join("")
|
||||||
end
|
end
|
||||||
@ -77,14 +77,14 @@ defmodule Pleroma.Gopher.Server.ProtocolHandler do
|
|||||||
|
|
||||||
link("Post ##{activity.id} by #{user.nickname}", "/notices/#{activity.id}") <>
|
link("Post ##{activity.id} by #{user.nickname}", "/notices/#{activity.id}") <>
|
||||||
info("#{like_count} likes, #{announcement_count} repeats") <>
|
info("#{like_count} likes, #{announcement_count} repeats") <>
|
||||||
"\r\n" <>
|
"i\tfake\t(NULL)\t0\r\n" <>
|
||||||
info(
|
info(
|
||||||
HtmlSanitizeEx.strip_tags(
|
HtmlSanitizeEx.strip_tags(
|
||||||
String.replace(activity.data["object"]["content"], "<br>", "\r")
|
String.replace(activity.data["object"]["content"], "<br>", "\r")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
end)
|
end)
|
||||||
|> Enum.join("\r\n")
|
|> Enum.join("i\tfake\t(NULL)\t0\r\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
def response("") do
|
def response("") do
|
||||||
|
@ -1,5 +1,23 @@
|
|||||||
defmodule Pleroma.HTTP do
|
defmodule Pleroma.HTTP do
|
||||||
use HTTPoison.Base
|
require HTTPoison
|
||||||
|
|
||||||
|
def request(method, url, body \\ "", headers \\ [], options \\ []) do
|
||||||
|
options =
|
||||||
|
process_request_options(options)
|
||||||
|
|> process_sni_options(url)
|
||||||
|
|
||||||
|
HTTPoison.request(method, url, body, headers, options)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp process_sni_options(options, url) do
|
||||||
|
uri = URI.parse(url)
|
||||||
|
host = uri.host |> to_charlist()
|
||||||
|
|
||||||
|
case uri.scheme do
|
||||||
|
"https" -> options ++ [ssl: [server_name_indication: host]]
|
||||||
|
_ -> options
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def process_request_options(options) do
|
def process_request_options(options) do
|
||||||
config = Application.get_env(:pleroma, :http, [])
|
config = Application.get_env(:pleroma, :http, [])
|
||||||
@ -10,4 +28,9 @@ defmodule Pleroma.HTTP do
|
|||||||
_ -> options ++ [proxy: proxy]
|
_ -> options ++ [proxy: proxy]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get(url, headers \\ [], options \\ []), do: request(:get, url, "", headers, options)
|
||||||
|
|
||||||
|
def post(url, body, headers \\ [], options \\ []),
|
||||||
|
do: request(:post, url, body, headers, options)
|
||||||
end
|
end
|
||||||
|
@ -124,20 +124,20 @@ defmodule Pleroma.Upload do
|
|||||||
if should_dedupe do
|
if should_dedupe do
|
||||||
create_name(uuid, List.last(String.split(file.filename, ".")), type)
|
create_name(uuid, List.last(String.split(file.filename, ".")), type)
|
||||||
else
|
else
|
||||||
unless String.contains?(file.filename, ".") do
|
parts = String.split(file.filename, ".")
|
||||||
case type do
|
|
||||||
"image/png" -> file.filename <> ".png"
|
new_filename =
|
||||||
"image/jpeg" -> file.filename <> ".jpg"
|
if length(parts) > 1 do
|
||||||
"image/gif" -> file.filename <> ".gif"
|
Enum.drop(parts, -1) |> Enum.join(".")
|
||||||
"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
|
else
|
||||||
file.filename
|
Enum.join(parts)
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
end
|
||||||
end
|
end
|
||||||
|
@ -398,6 +398,7 @@ defmodule Pleroma.User do
|
|||||||
Enum.map(reqs, fn req -> req.actor end)
|
Enum.map(reqs, fn req -> req.actor end)
|
||||||
|> Enum.uniq()
|
|> Enum.uniq()
|
||||||
|> Enum.map(fn ap_id -> get_by_ap_id(ap_id) end)
|
|> Enum.map(fn ap_id -> get_by_ap_id(ap_id) end)
|
||||||
|
|> Enum.filter(fn u -> !following?(u, user) end)
|
||||||
|
|
||||||
{:ok, users}
|
{:ok, users}
|
||||||
end
|
end
|
||||||
|
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
|
@ -576,7 +576,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
|||||||
|
|
||||||
def fetch_and_prepare_user_from_ap_id(ap_id) do
|
def fetch_and_prepare_user_from_ap_id(ap_id) do
|
||||||
with {:ok, %{status_code: 200, body: body}} <-
|
with {:ok, %{status_code: 200, body: body}} <-
|
||||||
@httpoison.get(ap_id, Accept: "application/activity+json"),
|
@httpoison.get(ap_id, [Accept: "application/activity+json"], follow_redirect: true),
|
||||||
{:ok, data} <- Jason.decode(body) do
|
{:ok, data} <- Jason.decode(body) do
|
||||||
user_data_from_user_object(data)
|
user_data_from_user_object(data)
|
||||||
else
|
else
|
||||||
|
@ -18,12 +18,16 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def get_actor(%{"actor" => actor}) when is_list(actor) do
|
def get_actor(%{"actor" => actor}) when is_list(actor) do
|
||||||
|
if is_binary(Enum.at(actor, 0)) do
|
||||||
Enum.at(actor, 0)
|
Enum.at(actor, 0)
|
||||||
|
else
|
||||||
|
Enum.find(actor, fn %{"type" => type} -> type == "Person" end)
|
||||||
|
|> Map.get("id")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_actor(%{"actor" => actor_list}) do
|
def get_actor(%{"actor" => actor}) when is_map(actor) do
|
||||||
Enum.find(actor_list, fn %{"type" => type} -> type == "Person" end)
|
actor["id"]
|
||||||
|> Map.get("id")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
@ -38,6 +42,25 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||||||
|> fix_emoji
|
|> fix_emoji
|
||||||
|> fix_tag
|
|> fix_tag
|
||||||
|> fix_content_map
|
|> fix_content_map
|
||||||
|
|> fix_likes
|
||||||
|
|> 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
|
end
|
||||||
|
|
||||||
def fix_actor(%{"attributedTo" => actor} = object) do
|
def fix_actor(%{"attributedTo" => actor} = object) do
|
||||||
@ -45,6 +68,20 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||||||
|> Map.put("actor", get_actor(%{"actor" => actor}))
|
|> Map.put("actor", get_actor(%{"actor" => actor}))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def fix_likes(%{"likes" => likes} = object)
|
||||||
|
when is_bitstring(likes) do
|
||||||
|
# Check for standardisation
|
||||||
|
# This is what Peertube does
|
||||||
|
# curl -H 'Accept: application/activity+json' $likes | jq .totalItems
|
||||||
|
object
|
||||||
|
|> Map.put("likes", [])
|
||||||
|
|> Map.put("like_count", 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
def fix_likes(object) do
|
||||||
|
object
|
||||||
|
end
|
||||||
|
|
||||||
def fix_in_reply_to(%{"inReplyTo" => in_reply_to_id} = object)
|
def fix_in_reply_to(%{"inReplyTo" => in_reply_to_id} = object)
|
||||||
when not is_nil(in_reply_to_id) do
|
when not is_nil(in_reply_to_id) do
|
||||||
case ActivityPub.fetch_object_from_id(in_reply_to_id) do
|
case ActivityPub.fetch_object_from_id(in_reply_to_id) do
|
||||||
@ -72,8 +109,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||||||
def fix_in_reply_to(object), do: object
|
def fix_in_reply_to(object), do: object
|
||||||
|
|
||||||
def fix_context(object) do
|
def fix_context(object) do
|
||||||
|
context = object["context"] || object["conversation"] || Utils.generate_context_id()
|
||||||
|
|
||||||
object
|
object
|
||||||
|> Map.put("context", object["conversation"])
|
|> Map.put("context", context)
|
||||||
|
|> Map.put("conversation", context)
|
||||||
end
|
end
|
||||||
|
|
||||||
def fix_attachments(object) do
|
def fix_attachments(object) do
|
||||||
@ -137,13 +177,22 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|
|||||||
|
|
||||||
def fix_content_map(object), do: object
|
def fix_content_map(object), do: object
|
||||||
|
|
||||||
|
# disallow objects with bogus IDs
|
||||||
|
def handle_incoming(%{"id" => nil}), do: :error
|
||||||
|
def handle_incoming(%{"id" => ""}), do: :error
|
||||||
|
# length of https:// = 8, should validate better, but good enough for now.
|
||||||
|
def handle_incoming(%{"id" => id}) when not (is_binary(id) and length(id) > 8), do: :error
|
||||||
|
|
||||||
# TODO: validate those with a Ecto scheme
|
# TODO: validate those with a Ecto scheme
|
||||||
# - tags
|
# - tags
|
||||||
# - emoji
|
# - emoji
|
||||||
def handle_incoming(%{"type" => "Create", "object" => %{"type" => objtype} = object} = data)
|
def handle_incoming(%{"type" => "Create", "object" => %{"type" => objtype} = object} = data)
|
||||||
when objtype in ["Article", "Note"] do
|
when objtype in ["Article", "Note", "Video"] do
|
||||||
actor = get_actor(data)
|
actor = get_actor(data)
|
||||||
data = Map.put(data, "actor", actor)
|
|
||||||
|
data =
|
||||||
|
Map.put(data, "actor", actor)
|
||||||
|
|> fix_addressing
|
||||||
|
|
||||||
with nil <- Activity.get_create_activity_by_object_ap_id(object["id"]),
|
with nil <- Activity.get_create_activity_by_object_ap_id(object["id"]),
|
||||||
%User{} = user <- User.get_or_fetch_by_ap_id(data["actor"]) do
|
%User{} = user <- User.get_or_fetch_by_ap_id(data["actor"]) do
|
||||||
|
@ -128,7 +128,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
|||||||
Inserts a full object if it is contained in an activity.
|
Inserts a full object if it is contained in an activity.
|
||||||
"""
|
"""
|
||||||
def insert_full_object(%{"object" => %{"type" => type} = object_data})
|
def insert_full_object(%{"object" => %{"type" => type} = object_data})
|
||||||
when is_map(object_data) and type in ["Article", "Note"] do
|
when is_map(object_data) and type in ["Article", "Note", "Video"] do
|
||||||
with {:ok, _} <- Object.create(object_data) do
|
with {:ok, _} <- Object.create(object_data) do
|
||||||
:ok
|
:ok
|
||||||
end
|
end
|
||||||
@ -204,13 +204,17 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def add_like_to_object(%Activity{data: %{"actor" => actor}}, object) do
|
def add_like_to_object(%Activity{data: %{"actor" => actor}}, object) do
|
||||||
with likes <- [actor | object.data["likes"] || []] |> Enum.uniq() do
|
likes = if is_list(object.data["likes"]), do: object.data["likes"], else: []
|
||||||
|
|
||||||
|
with likes <- [actor | likes] |> Enum.uniq() do
|
||||||
update_likes_in_object(likes, object)
|
update_likes_in_object(likes, object)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove_like_from_object(%Activity{data: %{"actor" => actor}}, object) do
|
def remove_like_from_object(%Activity{data: %{"actor" => actor}}, object) do
|
||||||
with likes <- (object.data["likes"] || []) |> List.delete(actor) do
|
likes = if is_list(object.data["likes"]), do: object.data["likes"], else: []
|
||||||
|
|
||||||
|
with likes <- likes |> List.delete(actor) do
|
||||||
update_likes_in_object(likes, object)
|
update_likes_in_object(likes, object)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -380,7 +384,10 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
|||||||
},
|
},
|
||||||
object
|
object
|
||||||
) do
|
) do
|
||||||
with announcements <- [actor | object.data["announcements"] || []] |> Enum.uniq() do
|
announcements =
|
||||||
|
if is_list(object.data["announcements"]), do: object.data["announcements"], else: []
|
||||||
|
|
||||||
|
with announcements <- [actor | announcements] |> Enum.uniq() do
|
||||||
update_element_in_object("announcement", announcements, object)
|
update_element_in_object("announcement", announcements, object)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -388,7 +395,10 @@ defmodule Pleroma.Web.ActivityPub.Utils do
|
|||||||
def add_announce_to_object(_, object), do: {:ok, object}
|
def add_announce_to_object(_, object), do: {:ok, object}
|
||||||
|
|
||||||
def remove_announce_from_object(%Activity{data: %{"actor" => actor}}, object) do
|
def remove_announce_from_object(%Activity{data: %{"actor" => actor}}, object) do
|
||||||
with announcements <- (object.data["announcements"] || []) |> List.delete(actor) do
|
announcements =
|
||||||
|
if is_list(object.data["announcements"]), do: object.data["announcements"], else: []
|
||||||
|
|
||||||
|
with announcements <- announcements |> List.delete(actor) do
|
||||||
update_element_in_object("announcement", announcements, object)
|
update_element_in_object("announcement", announcements, object)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -127,9 +127,6 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
|||||||
info = User.user_info(user)
|
info = User.user_info(user)
|
||||||
|
|
||||||
params = %{
|
params = %{
|
||||||
"type" => ["Create", "Announce"],
|
|
||||||
"actor_id" => user.ap_id,
|
|
||||||
"whole_db" => true,
|
|
||||||
"limit" => "10"
|
"limit" => "10"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,10 +137,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do
|
|||||||
params
|
params
|
||||||
end
|
end
|
||||||
|
|
||||||
activities = ActivityPub.fetch_public_activities(params)
|
activities = ActivityPub.fetch_user_activities(user, nil, params)
|
||||||
min_id = Enum.at(activities, 0).id
|
min_id = Enum.at(Enum.reverse(activities), 0).id
|
||||||
|
|
||||||
activities = Enum.reverse(activities)
|
|
||||||
max_id = Enum.at(activities, 0).id
|
max_id = Enum.at(activities, 0).id
|
||||||
|
|
||||||
collection =
|
collection =
|
||||||
|
@ -64,7 +64,6 @@ defmodule Pleroma.Web.CommonAPI.Utils do
|
|||||||
|
|
||||||
def make_content_html(status, mentions, attachments, tags, no_attachment_links \\ false) do
|
def make_content_html(status, mentions, attachments, tags, no_attachment_links \\ false) do
|
||||||
status
|
status
|
||||||
|> String.replace("\r", "")
|
|
||||||
|> format_input(mentions, tags)
|
|> format_input(mentions, tags)
|
||||||
|> maybe_add_attachments(attachments, no_attachment_links)
|
|> maybe_add_attachments(attachments, no_attachment_links)
|
||||||
end
|
end
|
||||||
@ -95,7 +94,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do
|
|||||||
def format_input(text, mentions, tags) do
|
def format_input(text, mentions, tags) do
|
||||||
text
|
text
|
||||||
|> Formatter.html_escape()
|
|> Formatter.html_escape()
|
||||||
|> String.replace("\n", "<br>")
|
|> String.replace(~r/\r?\n/, "<br>")
|
||||||
|> (&{[], &1}).()
|
|> (&{[], &1}).()
|
||||||
|> Formatter.add_links()
|
|> Formatter.add_links()
|
||||||
|> Formatter.add_user_links(mentions)
|
|> Formatter.add_user_links(mentions)
|
||||||
@ -109,7 +108,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do
|
|||||||
|> Enum.sort_by(fn {tag, _} -> -String.length(tag) end)
|
|> Enum.sort_by(fn {tag, _} -> -String.length(tag) end)
|
||||||
|
|
||||||
Enum.reduce(tags, text, fn {full, tag}, text ->
|
Enum.reduce(tags, text, fn {full, tag}, text ->
|
||||||
url = "#<a href='#{Pleroma.Web.base_url()}/tag/#{tag}' rel='tag'>#{tag}</a>"
|
url = "<a href='#{Pleroma.Web.base_url()}/tag/#{tag}' rel='tag'>##{tag}</a>"
|
||||||
String.replace(text, full, url)
|
String.replace(text, full, url)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
@ -5,21 +5,26 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||||||
alias Pleroma.Web.MastodonAPI.{StatusView, AccountView, MastodonView, ListView}
|
alias Pleroma.Web.MastodonAPI.{StatusView, AccountView, MastodonView, ListView}
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.ActivityPub.Utils
|
alias Pleroma.Web.ActivityPub.Utils
|
||||||
alias Pleroma.Web.{CommonAPI, OStatus}
|
alias Pleroma.Web.CommonAPI
|
||||||
alias Pleroma.Web.OAuth.{Authorization, Token, App}
|
alias Pleroma.Web.OAuth.{Authorization, Token, App}
|
||||||
alias Comeonin.Pbkdf2
|
alias Comeonin.Pbkdf2
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
require Logger
|
require Logger
|
||||||
|
|
||||||
|
@httpoison Application.get_env(:pleroma, :httpoison)
|
||||||
|
|
||||||
action_fallback(:errors)
|
action_fallback(:errors)
|
||||||
|
|
||||||
def create_app(conn, params) do
|
def create_app(conn, params) do
|
||||||
with cs <- App.register_changeset(%App{}, params) |> IO.inspect(),
|
with cs <- App.register_changeset(%App{}, params) |> IO.inspect(),
|
||||||
{:ok, app} <- Repo.insert(cs) |> IO.inspect() do
|
{:ok, app} <- Repo.insert(cs) |> IO.inspect() do
|
||||||
res = %{
|
res = %{
|
||||||
id: app.id,
|
id: app.id |> to_string,
|
||||||
|
name: app.client_name,
|
||||||
client_id: app.client_id,
|
client_id: app.client_id,
|
||||||
client_secret: app.client_secret
|
client_secret: app.client_secret,
|
||||||
|
redirect_uri: app.redirect_uris,
|
||||||
|
website: app.website
|
||||||
}
|
}
|
||||||
|
|
||||||
json(conn, res)
|
json(conn, res)
|
||||||
@ -653,12 +658,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||||||
|
|
||||||
fetched =
|
fetched =
|
||||||
if Regex.match?(~r/https?:/, query) do
|
if Regex.match?(~r/https?:/, query) do
|
||||||
with {:ok, activities} <- OStatus.fetch_activity_from_url(query) do
|
with {:ok, object} <- ActivityPub.fetch_object_from_id(query) do
|
||||||
activities
|
[Activity.get_create_activity_by_object_ap_id(object.data["id"])]
|
||||||
|> Enum.filter(fn
|
|
||||||
%{data: %{"type" => "Create"}} -> true
|
|
||||||
_ -> false
|
|
||||||
end)
|
|
||||||
else
|
else
|
||||||
_e -> []
|
_e -> []
|
||||||
end
|
end
|
||||||
@ -705,12 +706,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||||||
|
|
||||||
fetched =
|
fetched =
|
||||||
if Regex.match?(~r/https?:/, query) do
|
if Regex.match?(~r/https?:/, query) do
|
||||||
with {:ok, activities} <- OStatus.fetch_activity_from_url(query) do
|
with {:ok, object} <- ActivityPub.fetch_object_from_id(query) do
|
||||||
activities
|
[Activity.get_create_activity_by_object_ap_id(object.data["id"])]
|
||||||
|> Enum.filter(fn
|
|
||||||
%{data: %{"type" => "Create"}} -> true
|
|
||||||
_ -> false
|
|
||||||
end)
|
|
||||||
else
|
else
|
||||||
_e -> []
|
_e -> []
|
||||||
end
|
end
|
||||||
@ -1097,4 +1094,45 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
|||||||
|> put_status(500)
|
|> put_status(500)
|
||||||
|> json("Something went wrong")
|
|> json("Something went wrong")
|
||||||
end
|
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",
|
||||||
|
case User.get_or_fetch(x["acct"]) do
|
||||||
|
%{id: id} -> id
|
||||||
|
_ -> 0
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> json(data2)
|
||||||
|
else
|
||||||
|
e -> Logger.error("Could not retrieve suggestions at fetch #{url}, #{inspect(e)}")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
json(conn, [])
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -14,6 +14,18 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
|||||||
header = User.banner_url(user) |> MediaProxy.url()
|
header = User.banner_url(user) |> MediaProxy.url()
|
||||||
user_info = User.user_info(user)
|
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),
|
id: to_string(user.id),
|
||||||
username: hd(String.split(user.nickname, "@")),
|
username: hd(String.split(user.nickname, "@")),
|
||||||
@ -24,13 +36,13 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do
|
|||||||
followers_count: user_info.follower_count,
|
followers_count: user_info.follower_count,
|
||||||
following_count: user_info.following_count,
|
following_count: user_info.following_count,
|
||||||
statuses_count: user_info.note_count,
|
statuses_count: user_info.note_count,
|
||||||
note: user.bio || "",
|
note: HtmlSanitizeEx.basic_html(user.bio) || "",
|
||||||
url: user.ap_id,
|
url: user.ap_id,
|
||||||
avatar: image,
|
avatar: image,
|
||||||
avatar_static: image,
|
avatar_static: image,
|
||||||
header: header,
|
header: header,
|
||||||
header_static: header,
|
header_static: header,
|
||||||
emojis: [],
|
emojis: emojis,
|
||||||
fields: [],
|
fields: [],
|
||||||
source: %{
|
source: %{
|
||||||
note: "",
|
note: "",
|
||||||
|
@ -99,8 +99,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||||||
repeated = opts[:for] && opts[:for].ap_id in (object["announcements"] || [])
|
repeated = opts[:for] && opts[:for].ap_id in (object["announcements"] || [])
|
||||||
favorited = opts[:for] && opts[:for].ap_id in (object["likes"] || [])
|
favorited = opts[:for] && opts[:for].ap_id in (object["likes"] || [])
|
||||||
|
|
||||||
attachments =
|
attachment_data = object["attachment"] || []
|
||||||
render_many(object["attachment"] || [], StatusView, "attachment.json", as: :attachment)
|
attachment_data = attachment_data ++ if object["type"] == "Video", do: [object], else: []
|
||||||
|
attachments = render_many(attachment_data, StatusView, "attachment.json", as: :attachment)
|
||||||
|
|
||||||
created_at = Utils.to_masto_date(object["published"])
|
created_at = Utils.to_masto_date(object["published"])
|
||||||
|
|
||||||
@ -151,7 +152,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def render("attachment.json", %{attachment: attachment}) do
|
def render("attachment.json", %{attachment: attachment}) do
|
||||||
[%{"mediaType" => media_type, "href" => href} | _] = attachment["url"]
|
[attachment_url | _] = attachment["url"]
|
||||||
|
media_type = attachment_url["mediaType"] || attachment_url["mimeType"]
|
||||||
|
href = attachment_url["href"]
|
||||||
|
|
||||||
type =
|
type =
|
||||||
cond do
|
cond do
|
||||||
@ -208,6 +211,19 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def render_content(%{"type" => "Video"} = object) do
|
||||||
|
name = object["name"]
|
||||||
|
|
||||||
|
content =
|
||||||
|
if !!name and name != "" do
|
||||||
|
"<p><a href=\"#{object["id"]}\">#{name}</a></p>#{object["content"]}"
|
||||||
|
else
|
||||||
|
object["content"]
|
||||||
|
end
|
||||||
|
|
||||||
|
HtmlSanitizeEx.basic_html(content)
|
||||||
|
end
|
||||||
|
|
||||||
def render_content(%{"type" => "Article"} = object) do
|
def render_content(%{"type" => "Article"} = object) do
|
||||||
summary = object["name"]
|
summary = object["name"]
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
|
|||||||
def nodeinfo(conn, %{"version" => "2.0"}) do
|
def nodeinfo(conn, %{"version" => "2.0"}) do
|
||||||
instance = Application.get_env(:pleroma, :instance)
|
instance = Application.get_env(:pleroma, :instance)
|
||||||
media_proxy = Application.get_env(:pleroma, :media_proxy)
|
media_proxy = Application.get_env(:pleroma, :media_proxy)
|
||||||
|
suggestions = Application.get_env(:pleroma, :suggestions)
|
||||||
stats = Stats.get_stats()
|
stats = Stats.get_stats()
|
||||||
|
|
||||||
response = %{
|
response = %{
|
||||||
@ -45,7 +46,13 @@ defmodule Pleroma.Web.Nodeinfo.NodeinfoController do
|
|||||||
nodeName: Keyword.get(instance, :name),
|
nodeName: Keyword.get(instance, :name),
|
||||||
nodeDescription: Keyword.get(instance, :description),
|
nodeDescription: Keyword.get(instance, :description),
|
||||||
mediaProxy: Keyword.get(media_proxy, :enabled),
|
mediaProxy: Keyword.get(media_proxy, :enabled),
|
||||||
private: !Keyword.get(instance, :public, true)
|
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, "")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,6 +142,8 @@ defmodule Pleroma.Web.Router do
|
|||||||
get("/domain_blocks", MastodonAPIController, :domain_blocks)
|
get("/domain_blocks", MastodonAPIController, :domain_blocks)
|
||||||
post("/domain_blocks", MastodonAPIController, :block_domain)
|
post("/domain_blocks", MastodonAPIController, :block_domain)
|
||||||
delete("/domain_blocks", MastodonAPIController, :unblock_domain)
|
delete("/domain_blocks", MastodonAPIController, :unblock_domain)
|
||||||
|
|
||||||
|
get("/suggestions", MastodonAPIController, :suggestions)
|
||||||
end
|
end
|
||||||
|
|
||||||
scope "/api/web", Pleroma.Web.MastodonAPI do
|
scope "/api/web", Pleroma.Web.MastodonAPI do
|
||||||
@ -203,9 +205,7 @@ defmodule Pleroma.Web.Router do
|
|||||||
get("/statuses/show/:id", TwitterAPI.Controller, :fetch_status)
|
get("/statuses/show/:id", TwitterAPI.Controller, :fetch_status)
|
||||||
get("/statusnet/conversation/:id", TwitterAPI.Controller, :fetch_conversation)
|
get("/statusnet/conversation/:id", TwitterAPI.Controller, :fetch_conversation)
|
||||||
|
|
||||||
if @registrations_open do
|
|
||||||
post("/account/register", TwitterAPI.Controller, :register)
|
post("/account/register", TwitterAPI.Controller, :register)
|
||||||
end
|
|
||||||
|
|
||||||
get("/search", TwitterAPI.Controller, :search)
|
get("/search", TwitterAPI.Controller, :search)
|
||||||
get("/statusnet/tags/timeline/:tag", TwitterAPI.Controller, :public_and_external_timeline)
|
get("/statusnet/tags/timeline/:tag", TwitterAPI.Controller, :public_and_external_timeline)
|
||||||
@ -368,6 +368,7 @@ defmodule Pleroma.Web.Router do
|
|||||||
end
|
end
|
||||||
|
|
||||||
scope "/", Fallback do
|
scope "/", Fallback do
|
||||||
|
get("/registration/:token", RedirectController, :registration_page)
|
||||||
get("/*path", RedirectController, :redirector)
|
get("/*path", RedirectController, :redirector)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -382,4 +383,8 @@ defmodule Fallback.RedirectController do
|
|||||||
|> send_file(200, "priv/static/index.html")
|
|> send_file(200, "priv/static/index.html")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def registration_page(conn, params) do
|
||||||
|
redirector(conn, params)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
<script id='initial-state' type='application/json'><%= raw @initial_state %></script>
|
<script id='initial-state' type='application/json'><%= raw @initial_state %></script>
|
||||||
<script src="/packs/application.js"></script>
|
<script src="/packs/application.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body class='app-body no-reduce-motion'>
|
<body class='app-body no-reduce-motion system-font'>
|
||||||
<div class='app-holder' data-props='{"locale":"en"}' id='mastodon'>
|
<div class='app-holder' data-props='{"locale":"en"}' id='mastodon'>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@ -99,6 +99,10 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
|
|||||||
conn
|
conn
|
||||||
|> render("followed.html", %{error: false})
|
|> render("followed.html", %{error: false})
|
||||||
else
|
else
|
||||||
|
# Was already following user
|
||||||
|
{:error, "Could not follow user:" <> _rest} ->
|
||||||
|
render(conn, "followed.html", %{error: false})
|
||||||
|
|
||||||
_e ->
|
_e ->
|
||||||
conn
|
conn
|
||||||
|> render("follow_login.html", %{
|
|> render("follow_login.html", %{
|
||||||
@ -117,6 +121,11 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
|
|||||||
conn
|
conn
|
||||||
|> render("followed.html", %{error: false})
|
|> render("followed.html", %{error: false})
|
||||||
else
|
else
|
||||||
|
# Was already following user
|
||||||
|
{:error, "Could not follow user:" <> _rest} ->
|
||||||
|
conn
|
||||||
|
|> render("followed.html", %{error: false})
|
||||||
|
|
||||||
e ->
|
e ->
|
||||||
Logger.debug("Remote follow failed with error #{inspect(e)}")
|
Logger.debug("Remote follow failed with error #{inspect(e)}")
|
||||||
|
|
||||||
@ -163,10 +172,9 @@ defmodule Pleroma.Web.TwitterAPI.UtilController do
|
|||||||
redirectRootLogin: Keyword.get(@instance_fe, :redirect_root_login),
|
redirectRootLogin: Keyword.get(@instance_fe, :redirect_root_login),
|
||||||
chatDisabled: !Keyword.get(@instance_chat, :enabled),
|
chatDisabled: !Keyword.get(@instance_chat, :enabled),
|
||||||
showInstanceSpecificPanel: Keyword.get(@instance_fe, :show_instance_panel),
|
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),
|
scopeOptionsEnabled: Keyword.get(@instance_fe, :scope_options_enabled),
|
||||||
whoToFollowProvider: Keyword.get(@instance_fe, :who_to_follow_provider),
|
collapseMessageWithSubject:
|
||||||
whoToFollowLink: Keyword.get(@instance_fe, :who_to_follow_link)
|
Keyword.get(@instance_fe, :collapse_message_with_subject)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -170,6 +170,15 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do
|
|||||||
HtmlSanitizeEx.basic_html(content)
|
HtmlSanitizeEx.basic_html(content)
|
||||||
|> Formatter.emojify(object["emoji"])
|
|> Formatter.emojify(object["emoji"])
|
||||||
|
|
||||||
|
video =
|
||||||
|
if object["type"] == "Video" do
|
||||||
|
vid = [object]
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
|
||||||
|
attachments = (object["attachment"] || []) ++ video
|
||||||
|
|
||||||
%{
|
%{
|
||||||
"id" => activity.id,
|
"id" => activity.id,
|
||||||
"uri" => activity.data["object"]["id"],
|
"uri" => activity.data["object"]["id"],
|
||||||
@ -181,7 +190,7 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter do
|
|||||||
"created_at" => created_at,
|
"created_at" => created_at,
|
||||||
"in_reply_to_status_id" => object["inReplyToStatusId"],
|
"in_reply_to_status_id" => object["inReplyToStatusId"],
|
||||||
"statusnet_conversation_id" => conversation_id,
|
"statusnet_conversation_id" => conversation_id,
|
||||||
"attachments" => (object["attachment"] || []) |> ObjectRepresenter.enum_to_list(opts),
|
"attachments" => attachments |> ObjectRepresenter.enum_to_list(opts),
|
||||||
"attentions" => attentions,
|
"attentions" => attentions,
|
||||||
"fave_num" => like_count,
|
"fave_num" => like_count,
|
||||||
"repeat_num" => announcement_count,
|
"repeat_num" => announcement_count,
|
||||||
|
@ -7,18 +7,20 @@ defmodule Pleroma.Web.TwitterAPI.Representers.ObjectRepresenter do
|
|||||||
|
|
||||||
%{
|
%{
|
||||||
url: url["href"] |> Pleroma.Web.MediaProxy.url(),
|
url: url["href"] |> Pleroma.Web.MediaProxy.url(),
|
||||||
mimetype: url["mediaType"],
|
mimetype: url["mediaType"] || url["mimeType"],
|
||||||
id: data["uuid"],
|
id: data["uuid"],
|
||||||
oembed: false
|
oembed: false,
|
||||||
|
description: data["name"]
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_map(%Object{data: %{"url" => url} = data}, _opts) when is_binary(url) do
|
def to_map(%Object{data: %{"url" => url} = data}, _opts) when is_binary(url) do
|
||||||
%{
|
%{
|
||||||
url: url |> Pleroma.Web.MediaProxy.url(),
|
url: url |> Pleroma.Web.MediaProxy.url(),
|
||||||
mimetype: data["mediaType"],
|
mimetype: data["mediaType"] || url["mimeType"],
|
||||||
id: data["uuid"],
|
id: data["uuid"],
|
||||||
oembed: false
|
oembed: false,
|
||||||
|
description: data["name"]
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
|
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.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.TwitterAPI.UserView
|
alias Pleroma.Web.TwitterAPI.UserView
|
||||||
alias Pleroma.Web.{OStatus, CommonAPI}
|
alias Pleroma.Web.{OStatus, CommonAPI}
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
|
|
||||||
|
@instance Application.get_env(:pleroma, :instance)
|
||||||
@httpoison Application.get_env(:pleroma, :httpoison)
|
@httpoison Application.get_env(:pleroma, :httpoison)
|
||||||
|
@registrations_open Keyword.get(@instance, :registrations_open)
|
||||||
|
|
||||||
def create_status(%User{} = user, %{"status" => _} = data) do
|
def create_status(%User{} = user, %{"status" => _} = data) do
|
||||||
CommonAPI.post(user, data)
|
CommonAPI.post(user, data)
|
||||||
@ -120,6 +122,8 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def register_user(params) do
|
def register_user(params) do
|
||||||
|
tokenString = params["token"]
|
||||||
|
|
||||||
params = %{
|
params = %{
|
||||||
nickname: params["nickname"],
|
nickname: params["nickname"],
|
||||||
name: params["fullname"],
|
name: params["fullname"],
|
||||||
@ -129,9 +133,18 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
|
|||||||
password_confirmation: params["confirm"]
|
password_confirmation: params["confirm"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# no need to query DB if registration is open
|
||||||
|
token =
|
||||||
|
unless @registrations_open || is_nil(tokenString) do
|
||||||
|
Repo.get_by(UserInviteToken, %{token: tokenString})
|
||||||
|
end
|
||||||
|
|
||||||
|
cond do
|
||||||
|
@registrations_open || (!is_nil(token) && !token.used) ->
|
||||||
changeset = User.register_changeset(%User{}, params)
|
changeset = User.register_changeset(%User{}, params)
|
||||||
|
|
||||||
with {:ok, user} <- Repo.insert(changeset) do
|
with {:ok, user} <- Repo.insert(changeset) do
|
||||||
|
!@registrations_open && UserInviteToken.mark_as_used(token.token)
|
||||||
{:ok, user}
|
{:ok, user}
|
||||||
else
|
else
|
||||||
{:error, changeset} ->
|
{:error, changeset} ->
|
||||||
@ -141,6 +154,13 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do
|
|||||||
|
|
||||||
{:error, %{error: errors}}
|
{:error, %{error: errors}}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
!@registrations_open && is_nil(token) ->
|
||||||
|
{:error, "Invalid token"}
|
||||||
|
|
||||||
|
!@registrations_open && token.used ->
|
||||||
|
{:error, "Expired token"}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_by_id_or_nickname(id_or_nickname) do
|
def get_by_id_or_nickname(id_or_nickname) do
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
defmodule Pleroma.Web.TwitterAPI.Controller do
|
defmodule Pleroma.Web.TwitterAPI.Controller do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
alias Pleroma.Formatter
|
||||||
alias Pleroma.Web.TwitterAPI.{TwitterAPI, UserView, ActivityView, NotificationView}
|
alias Pleroma.Web.TwitterAPI.{TwitterAPI, UserView, ActivityView, NotificationView}
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
alias Pleroma.Web.CommonAPI.Utils, as: CommonUtils
|
||||||
alias Pleroma.{Repo, Activity, User, Notification}
|
alias Pleroma.{Repo, Activity, User, Notification}
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.ActivityPub.Utils
|
alias Pleroma.Web.ActivityPub.Utils
|
||||||
@ -411,8 +413,18 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
|
|||||||
def update_profile(%{assigns: %{user: user}} = conn, params) do
|
def update_profile(%{assigns: %{user: user}} = conn, params) do
|
||||||
params =
|
params =
|
||||||
if bio = params["description"] do
|
if bio = params["description"] do
|
||||||
bio_brs = Regex.replace(~r/\r?\n/, bio, "<br>")
|
mentions = Formatter.parse_mentions(bio)
|
||||||
Map.put(params, "bio", bio_brs)
|
tags = Formatter.parse_tags(bio)
|
||||||
|
|
||||||
|
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_html = CommonUtils.format_input(bio, mentions, tags)
|
||||||
|
Map.put(params, "bio", bio_html |> Formatter.emojify(emoji))
|
||||||
else
|
else
|
||||||
params
|
params
|
||||||
end
|
end
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
defmodule Pleroma.Web.TwitterAPI.UserView do
|
defmodule Pleroma.Web.TwitterAPI.UserView do
|
||||||
use Pleroma.Web, :view
|
use Pleroma.Web, :view
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
alias Pleroma.Formatter
|
||||||
alias Pleroma.Web.CommonAPI.Utils
|
alias Pleroma.Web.CommonAPI.Utils
|
||||||
alias Pleroma.Web.MediaProxy
|
alias Pleroma.Web.MediaProxy
|
||||||
|
|
||||||
@ -28,9 +29,18 @@ defmodule Pleroma.Web.TwitterAPI.UserView do
|
|||||||
|
|
||||||
user_info = User.get_cached_user_info(user)
|
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)
|
||||||
|
|
||||||
data = %{
|
data = %{
|
||||||
"created_at" => user.inserted_at |> Utils.format_naive_asctime(),
|
"created_at" => user.inserted_at |> Utils.format_naive_asctime(),
|
||||||
"description" => HtmlSanitizeEx.strip_tags(user.bio),
|
"description" =>
|
||||||
|
HtmlSanitizeEx.strip_tags((user.bio || "") |> String.replace("<br>", "\n")),
|
||||||
|
"description_html" => HtmlSanitizeEx.basic_html(user.bio),
|
||||||
"favourites_count" => 0,
|
"favourites_count" => 0,
|
||||||
"followers_count" => user_info[:follower_count],
|
"followers_count" => user_info[:follower_count],
|
||||||
"following" => following,
|
"following" => following,
|
||||||
@ -39,6 +49,7 @@ defmodule Pleroma.Web.TwitterAPI.UserView do
|
|||||||
"friends_count" => user_info[:following_count],
|
"friends_count" => user_info[:following_count],
|
||||||
"id" => user.id,
|
"id" => user.id,
|
||||||
"name" => user.name,
|
"name" => user.name,
|
||||||
|
"name_html" => HtmlSanitizeEx.strip_tags(user.name) |> Formatter.emojify(emoji),
|
||||||
"profile_image_url" => image,
|
"profile_image_url" => image,
|
||||||
"profile_image_url_https" => image,
|
"profile_image_url_https" => image,
|
||||||
"profile_image_url_profile_size" => image,
|
"profile_image_url_profile_size" => image,
|
||||||
|
34
mix.exs
34
mix.exs
@ -30,25 +30,25 @@ defmodule Pleroma.Mixfile do
|
|||||||
# Type `mix help deps` for examples and options.
|
# Type `mix help deps` for examples and options.
|
||||||
defp deps do
|
defp deps do
|
||||||
[
|
[
|
||||||
{:phoenix, "~> 1.3.0"},
|
{:phoenix, "~> 1.3.3"},
|
||||||
{:phoenix_pubsub, "~> 1.0"},
|
{:phoenix_pubsub, "~> 1.0.2"},
|
||||||
{:phoenix_ecto, "~> 3.2"},
|
{:phoenix_ecto, "~> 3.3"},
|
||||||
{:postgrex, ">= 0.0.0"},
|
{:postgrex, ">= 0.13.5"},
|
||||||
{:gettext, "~> 0.11"},
|
{:gettext, "~> 0.15"},
|
||||||
{:cowboy, "~> 1.0", override: true},
|
{:cowboy, "~> 1.1.2", override: true},
|
||||||
{:comeonin, "~> 4.0"},
|
{:comeonin, "~> 4.1.1"},
|
||||||
{:pbkdf2_elixir, "~> 0.12"},
|
{:pbkdf2_elixir, "~> 0.12.3"},
|
||||||
{:trailing_format_plug, "~> 0.0.5"},
|
{:trailing_format_plug, "~> 0.0.7"},
|
||||||
{:html_sanitize_ex, "~> 1.3.0-rc1"},
|
{:html_sanitize_ex, "~> 1.3.0"},
|
||||||
{:phoenix_html, "~> 2.10"},
|
{:phoenix_html, "~> 2.10"},
|
||||||
{:calendar, "~> 0.16.1"},
|
{:calendar, "~> 0.17.4"},
|
||||||
{:cachex, "~> 3.0"},
|
{:cachex, "~> 3.0.2"},
|
||||||
{:httpoison, "~> 1.1.0"},
|
{:httpoison, "~> 1.2.0"},
|
||||||
{:jason, "~> 1.0"},
|
{:jason, "~> 1.0"},
|
||||||
{:ex_machina, "~> 2.0", only: :test},
|
{:mogrify, "~> 0.6.1"},
|
||||||
{:credo, "~> 0.7", only: [:dev, :test]},
|
{:ex_machina, "~> 2.2", only: :test},
|
||||||
{:mock, "~> 0.3.0", only: :test},
|
{:credo, "~> 0.9.3", only: [:dev, :test]},
|
||||||
{:mogrify, "~> 0.6.1"}
|
{:mock, "~> 0.3.1", only: :test}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
18
mix.lock
18
mix.lock
@ -1,45 +1,45 @@
|
|||||||
%{
|
%{
|
||||||
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"},
|
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"},
|
||||||
"cachex": {:hex, :cachex, "3.0.2", "1351caa4e26e29f7d7ec1d29b53d6013f0447630bbf382b4fb5d5bad0209f203", [:mix], [{:eternal, "~> 1.2", [hex: :eternal, repo: "hexpm", optional: false]}, {:unsafe, "~> 1.0", [hex: :unsafe, repo: "hexpm", optional: false]}], "hexpm"},
|
"cachex": {:hex, :cachex, "3.0.2", "1351caa4e26e29f7d7ec1d29b53d6013f0447630bbf382b4fb5d5bad0209f203", [:mix], [{:eternal, "~> 1.2", [hex: :eternal, repo: "hexpm", optional: false]}, {:unsafe, "~> 1.0", [hex: :unsafe, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"calendar": {:hex, :calendar, "0.16.1", "782327ad8bae7c797b887840dc4ddb933f05ce6e333e5b04964d7a5d5f79bde3", [:mix], [{:tzdata, "~> 0.5.8 or ~> 0.1.201603", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm"},
|
"calendar": {:hex, :calendar, "0.17.4", "22c5e8d98a4db9494396e5727108dffb820ee0d18fed4b0aa8ab76e4f5bc32f1", [:mix], [{:tzdata, "~> 0.5.8 or ~> 0.1.201603", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"certifi": {:hex, :certifi, "2.3.1", "d0f424232390bf47d82da8478022301c561cf6445b5b5fb6a84d49a9e76d2639", [:rebar3], [{:parse_trans, "3.2.0", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
|
"certifi": {:hex, :certifi, "2.3.1", "d0f424232390bf47d82da8478022301c561cf6445b5b5fb6a84d49a9e76d2639", [:rebar3], [{:parse_trans, "3.2.0", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"comeonin": {:hex, :comeonin, "4.1.1", "c7304fc29b45b897b34142a91122bc72757bc0c295e9e824999d5179ffc08416", [:mix], [{:argon2_elixir, "~> 1.2", [hex: :argon2_elixir, repo: "hexpm", optional: true]}, {:bcrypt_elixir, "~> 0.12.1 or ~> 1.0", [hex: :bcrypt_elixir, repo: "hexpm", optional: true]}, {:pbkdf2_elixir, "~> 0.12", [hex: :pbkdf2_elixir, repo: "hexpm", optional: true]}], "hexpm"},
|
"comeonin": {:hex, :comeonin, "4.1.1", "c7304fc29b45b897b34142a91122bc72757bc0c295e9e824999d5179ffc08416", [:mix], [{:argon2_elixir, "~> 1.2", [hex: :argon2_elixir, repo: "hexpm", optional: true]}, {:bcrypt_elixir, "~> 0.12.1 or ~> 1.0", [hex: :bcrypt_elixir, repo: "hexpm", optional: true]}, {:pbkdf2_elixir, "~> 0.12", [hex: :pbkdf2_elixir, repo: "hexpm", optional: true]}], "hexpm"},
|
||||||
"connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm"},
|
"connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm"},
|
||||||
"cowboy": {:hex, :cowboy, "1.1.2", "61ac29ea970389a88eca5a65601460162d370a70018afe6f949a29dca91f3bb0", [:rebar3], [{:cowlib, "~> 1.0.2", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.3.2", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
|
"cowboy": {:hex, :cowboy, "1.1.2", "61ac29ea970389a88eca5a65601460162d370a70018afe6f949a29dca91f3bb0", [:rebar3], [{:cowlib, "~> 1.0.2", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.3.2", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], [], "hexpm"},
|
"cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], [], "hexpm"},
|
||||||
"credo": {:hex, :credo, "0.9.2", "841d316612f568beb22ba310d816353dddf31c2d94aa488ae5a27bb53760d0bf", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:poison, ">= 0.0.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
|
"credo": {:hex, :credo, "0.9.3", "76fa3e9e497ab282e0cf64b98a624aa11da702854c52c82db1bf24e54ab7c97a", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:poison, ">= 0.0.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"db_connection": {:hex, :db_connection, "1.1.3", "89b30ca1ef0a3b469b1c779579590688561d586694a3ce8792985d4d7e575a61", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm"},
|
"db_connection": {:hex, :db_connection, "1.1.3", "89b30ca1ef0a3b469b1c779579590688561d586694a3ce8792985d4d7e575a61", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm"},
|
||||||
"decimal": {:hex, :decimal, "1.5.0", "b0433a36d0e2430e3d50291b1c65f53c37d56f83665b43d79963684865beab68", [:mix], [], "hexpm"},
|
"decimal": {:hex, :decimal, "1.5.0", "b0433a36d0e2430e3d50291b1c65f53c37d56f83665b43d79963684865beab68", [:mix], [], "hexpm"},
|
||||||
"ecto": {:hex, :ecto, "2.2.10", "e7366dc82f48f8dd78fcbf3ab50985ceeb11cb3dc93435147c6e13f2cda0992e", [:mix], [{:db_connection, "~> 1.1", [hex: :db_connection, repo: "hexpm", optional: true]}, {:decimal, "~> 1.2", [hex: :decimal, repo: "hexpm", optional: false]}, {:mariaex, "~> 0.8.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: true]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.13.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm"},
|
"ecto": {:hex, :ecto, "2.2.10", "e7366dc82f48f8dd78fcbf3ab50985ceeb11cb3dc93435147c6e13f2cda0992e", [:mix], [{:db_connection, "~> 1.1", [hex: :db_connection, repo: "hexpm", optional: true]}, {:decimal, "~> 1.2", [hex: :decimal, repo: "hexpm", optional: false]}, {:mariaex, "~> 0.8.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: true]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.13.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm"},
|
||||||
"eternal": {:hex, :eternal, "1.2.0", "e2a6b6ce3b8c248f7dc31451aefca57e3bdf0e48d73ae5043229380a67614c41", [:mix], [], "hexpm"},
|
"eternal": {:hex, :eternal, "1.2.0", "e2a6b6ce3b8c248f7dc31451aefca57e3bdf0e48d73ae5043229380a67614c41", [:mix], [], "hexpm"},
|
||||||
"ex_machina": {:hex, :ex_machina, "2.2.0", "fec496331e04fc2db2a1a24fe317c12c0c4a50d2beb8ebb3531ed1f0d84be0ed", [:mix], [{:ecto, "~> 2.1", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"},
|
"ex_machina": {:hex, :ex_machina, "2.2.0", "fec496331e04fc2db2a1a24fe317c12c0c4a50d2beb8ebb3531ed1f0d84be0ed", [:mix], [{:ecto, "~> 2.1", [hex: :ecto, repo: "hexpm", optional: true]}], "hexpm"},
|
||||||
"gettext": {:hex, :gettext, "0.15.0", "40a2b8ce33a80ced7727e36768499fc9286881c43ebafccae6bab731e2b2b8ce", [:mix], [], "hexpm"},
|
"gettext": {:hex, :gettext, "0.15.0", "40a2b8ce33a80ced7727e36768499fc9286881c43ebafccae6bab731e2b2b8ce", [:mix], [], "hexpm"},
|
||||||
"hackney": {:hex, :hackney, "1.12.1", "8bf2d0e11e722e533903fe126e14d6e7e94d9b7983ced595b75f532e04b7fdc7", [:rebar3], [{:certifi, "2.3.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.1", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
|
"hackney": {:hex, :hackney, "1.13.0", "24edc8cd2b28e1c652593833862435c80661834f6c9344e84b6a2255e7aeef03", [:rebar3], [{:certifi, "2.3.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.2", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"html_sanitize_ex": {:hex, :html_sanitize_ex, "1.3.0", "f005ad692b717691203f940c686208aa3d8ffd9dd4bb3699240096a51fa9564e", [:mix], [{:mochiweb, "~> 2.15", [hex: :mochiweb, repo: "hexpm", optional: false]}], "hexpm"},
|
"html_sanitize_ex": {:hex, :html_sanitize_ex, "1.3.0", "f005ad692b717691203f940c686208aa3d8ffd9dd4bb3699240096a51fa9564e", [:mix], [{:mochiweb, "~> 2.15", [hex: :mochiweb, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"httpoison": {:hex, :httpoison, "1.1.1", "96ed7ab79f78a31081bb523eefec205fd2900a02cda6dbc2300e7a1226219566", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
|
"httpoison": {:hex, :httpoison, "1.2.0", "2702ed3da5fd7a8130fc34b11965c8cfa21ade2f232c00b42d96d4967c39a3a3", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"idna": {:hex, :idna, "5.1.1", "cbc3b2fa1645113267cc59c760bafa64b2ea0334635ef06dbac8801e42f7279c", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
|
"idna": {:hex, :idna, "5.1.2", "e21cb58a09f0228a9e0b95eaa1217f1bcfc31a1aaa6e1fdf2f53a33f7dbd9494", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"jason": {:hex, :jason, "1.0.0", "0f7cfa9bdb23fed721ec05419bcee2b2c21a77e926bce0deda029b5adc716fe2", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
|
"jason": {:hex, :jason, "1.0.0", "0f7cfa9bdb23fed721ec05419bcee2b2c21a77e926bce0deda029b5adc716fe2", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
|
||||||
"meck": {:hex, :meck, "0.8.9", "64c5c0bd8bcca3a180b44196265c8ed7594e16bcc845d0698ec6b4e577f48188", [:rebar3], [], "hexpm"},
|
"meck": {:hex, :meck, "0.8.9", "64c5c0bd8bcca3a180b44196265c8ed7594e16bcc845d0698ec6b4e577f48188", [:rebar3], [], "hexpm"},
|
||||||
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"},
|
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"},
|
||||||
"mime": {:hex, :mime, "1.2.0", "78adaa84832b3680de06f88f0997e3ead3b451a440d183d688085be2d709b534", [:mix], [], "hexpm"},
|
"mime": {:hex, :mime, "1.3.0", "5e8d45a39e95c650900d03f897fbf99ae04f60ab1daa4a34c7a20a5151b7a5fe", [:mix], [], "hexpm"},
|
||||||
"mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"},
|
"mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"},
|
||||||
"mochiweb": {:hex, :mochiweb, "2.15.0", "e1daac474df07651e5d17cc1e642c4069c7850dc4508d3db7263a0651330aacc", [: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"},
|
"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"},
|
"mogrify": {:hex, :mogrify, "0.6.1", "de1b527514f2d95a7bbe9642eb556061afb337e220cf97adbf3a4e6438ed70af", [:mix], [], "hexpm"},
|
||||||
"parse_trans": {:hex, :parse_trans, "3.2.0", "2adfa4daf80c14dc36f522cf190eb5c4ee3e28008fc6394397c16f62a26258c2", [:rebar3], [], "hexpm"},
|
"parse_trans": {:hex, :parse_trans, "3.2.0", "2adfa4daf80c14dc36f522cf190eb5c4ee3e28008fc6394397c16f62a26258c2", [:rebar3], [], "hexpm"},
|
||||||
"pbkdf2_elixir": {:hex, :pbkdf2_elixir, "0.12.3", "6706a148809a29c306062862c803406e88f048277f6e85b68faf73291e820b84", [:mix], [], "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"},
|
"phoenix": {:hex, :phoenix, "1.3.4", "aaa1b55e5523083a877bcbe9886d9ee180bf2c8754905323493c2ac325903dc5", [: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"},
|
||||||
"phoenix_ecto": {:hex, :phoenix_ecto, "3.3.0", "702f6e164512853d29f9d20763493f2b3bcfcb44f118af2bc37bb95d0801b480", [:mix], [{:ecto, "~> 2.1", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
"phoenix_ecto": {:hex, :phoenix_ecto, "3.3.0", "702f6e164512853d29f9d20763493f2b3bcfcb44f118af2bc37bb95d0801b480", [:mix], [{:ecto, "~> 2.1", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"phoenix_html": {:hex, :phoenix_html, "2.11.2", "86ebd768258ba60a27f5578bec83095bdb93485d646fc4111db8844c316602d6", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
"phoenix_html": {:hex, :phoenix_html, "2.11.2", "86ebd768258ba60a27f5578bec83095bdb93485d646fc4111db8844c316602d6", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"phoenix_pubsub": {:hex, :phoenix_pubsub, "1.0.2", "bfa7fd52788b5eaa09cb51ff9fcad1d9edfeb68251add458523f839392f034c1", [:mix], [], "hexpm"},
|
"phoenix_pubsub": {:hex, :phoenix_pubsub, "1.0.2", "bfa7fd52788b5eaa09cb51ff9fcad1d9edfeb68251add458523f839392f034c1", [:mix], [], "hexpm"},
|
||||||
"plug": {:hex, :plug, "1.5.1", "1ff35bdecfb616f1a2b1c935ab5e4c47303f866cb929d2a76f0541e553a58165", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1 or ~> 2.3", [hex: :cowboy, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}], "hexpm"},
|
"plug": {:hex, :plug, "1.6.2", "e06a7bd2bb6de5145da0dd950070110dce88045351224bd98e84edfdaaf5ffee", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"},
|
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"},
|
||||||
"poolboy": {:hex, :poolboy, "1.5.1", "6b46163901cfd0a1b43d692657ed9d7e599853b3b21b95ae5ae0a777cf9b6ca8", [:rebar], [], "hexpm"},
|
"poolboy": {:hex, :poolboy, "1.5.1", "6b46163901cfd0a1b43d692657ed9d7e599853b3b21b95ae5ae0a777cf9b6ca8", [:rebar], [], "hexpm"},
|
||||||
"postgrex": {:hex, :postgrex, "0.13.5", "3d931aba29363e1443da167a4b12f06dcd171103c424de15e5f3fc2ba3e6d9c5", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 1.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm"},
|
"postgrex": {:hex, :postgrex, "0.13.5", "3d931aba29363e1443da167a4b12f06dcd171103c424de15e5f3fc2ba3e6d9c5", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 1.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"ranch": {:hex, :ranch, "1.3.2", "e4965a144dc9fbe70e5c077c65e73c57165416a901bd02ea899cfd95aa890986", [:rebar3], [], "hexpm"},
|
"ranch": {:hex, :ranch, "1.3.2", "e4965a144dc9fbe70e5c077c65e73c57165416a901bd02ea899cfd95aa890986", [:rebar3], [], "hexpm"},
|
||||||
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"},
|
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"},
|
||||||
"trailing_format_plug": {:hex, :trailing_format_plug, "0.0.7", "64b877f912cf7273bed03379936df39894149e35137ac9509117e59866e10e45", [:mix], [{:plug, "> 0.12.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
"trailing_format_plug": {:hex, :trailing_format_plug, "0.0.7", "64b877f912cf7273bed03379936df39894149e35137ac9509117e59866e10e45", [:mix], [{:plug, "> 0.12.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"tzdata": {:hex, :tzdata, "0.5.16", "13424d3afc76c68ff607f2df966c0ab4f3258859bbe3c979c9ed1606135e7352", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
|
"tzdata": {:hex, :tzdata, "0.5.17", "50793e3d85af49736701da1a040c415c97dc1caf6464112fd9bd18f425d3053b", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
|
||||||
"unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm"},
|
"unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm"},
|
||||||
"unsafe": {:hex, :unsafe, "1.0.0", "7c21742cd05380c7875546b023481d3a26f52df8e5dfedcb9f958f322baae305", [:mix], [], "hexpm"},
|
"unsafe": {:hex, :unsafe, "1.0.0", "7c21742cd05380c7875546b023481d3a26f52df8e5dfedcb9f958f322baae305", [:mix], [], "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.b76dcba564bc8d13e27c546e95fbb72e.css rel=stylesheet></head><body style="display: none"><div id=app></div><script type=text/javascript src=/static/js/manifest.004e63f0a7e5719fbbe8.js></script><script type=text/javascript src=/static/js/vendor.48cf760f1485c83eb636.js></script><script type=text/javascript src=/static/js/app.d3eba781c5f30aabbb47.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
|
//# sourceMappingURL=admin.js.map
|
File diff suppressed because one or more lines are too long
@ -1,5 +1,5 @@
|
|||||||
CACHE MANIFEST
|
CACHE MANIFEST
|
||||||
#ver:2018-4-9 21:57:37
|
#ver:2018-8-12 18:01:32
|
||||||
#plugin:4.8.4
|
#plugin:4.8.4
|
||||||
|
|
||||||
CACHE:
|
CACHE:
|
||||||
@ -13,33 +13,46 @@ CACHE:
|
|||||||
/packs/features/home_timeline.js
|
/packs/features/home_timeline.js
|
||||||
/packs/features/public_timeline.js
|
/packs/features/public_timeline.js
|
||||||
/packs/features/community_timeline.js
|
/packs/features/community_timeline.js
|
||||||
/packs/features/favourited_statuses.js
|
/packs/features/direct_timeline.js
|
||||||
/packs/features/list_timeline.js
|
/packs/features/pinned_statuses.js
|
||||||
|
/packs/features/domain_blocks.js
|
||||||
/packs/features/following.js
|
/packs/features/following.js
|
||||||
/packs/features/followers.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/hashtag_timeline.js
|
||||||
/packs/features/status.js
|
/packs/features/status.js
|
||||||
/packs/features/account_gallery.js
|
/packs/features/lists.js
|
||||||
/packs/features/blocks.js
|
/packs/modals/report_modal.js
|
||||||
|
/packs/features/getting_started.js
|
||||||
/packs/features/follow_requests.js
|
/packs/features/follow_requests.js
|
||||||
|
/packs/features/mutes.js
|
||||||
|
/packs/features/blocks.js
|
||||||
/packs/features/reblogs.js
|
/packs/features/reblogs.js
|
||||||
/packs/features/favourites.js
|
/packs/features/favourites.js
|
||||||
/packs/features/getting_started.js
|
|
||||||
/packs/features/keyboard_shortcuts.js
|
/packs/features/keyboard_shortcuts.js
|
||||||
|
/packs/modals/mute_modal.js
|
||||||
/packs/features/generic_not_found.js
|
/packs/features/generic_not_found.js
|
||||||
/packs/features/list_editor.js
|
/packs/features/list_editor.js
|
||||||
|
/packs/modals/embed_modal.js
|
||||||
/packs/status/media_gallery.js
|
/packs/status/media_gallery.js
|
||||||
|
/packs/containers/media_container.js
|
||||||
/packs/share.js
|
/packs/share.js
|
||||||
/packs/application.js
|
/packs/application.js
|
||||||
/packs/about.js
|
/packs/about.js
|
||||||
/packs/public.js
|
|
||||||
/packs/mailer.js
|
/packs/mailer.js
|
||||||
|
/packs/mastodon-light.js
|
||||||
|
/packs/contrast.js
|
||||||
/packs/default.js
|
/packs/default.js
|
||||||
|
/packs/public.js
|
||||||
/packs/admin.js
|
/packs/admin.js
|
||||||
/packs/common.js
|
/packs/common.js
|
||||||
/packs/common.css
|
/packs/common.css
|
||||||
/packs/mailer.css
|
/packs/mailer.css
|
||||||
/packs/default.css
|
/packs/default.css
|
||||||
|
/packs/contrast.css
|
||||||
|
/packs/mastodon-light.css
|
||||||
/packs/manifest.json
|
/packs/manifest.json
|
||||||
|
|
||||||
NETWORK:
|
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
|
//# 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
|
//# 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
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/lists.js
Normal file
2
priv/static/packs/features/lists.js
Normal file
File diff suppressed because one or more lines are too long
1
priv/static/packs/features/lists.js.map
Normal file
1
priv/static/packs/features/lists.js.map
Normal file
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 New Issue
Block a user