Merge branch 'develop' of https://git.pleroma.social/pleroma/pleroma into feature/unrepeats

This commit is contained in:
Francis Dinh 2018-04-20 16:47:44 -04:00
commit c5dc7e6e31
43 changed files with 405 additions and 74 deletions

6
.gitignore vendored
View file

@ -6,6 +6,9 @@
/uploads
/test/uploads
# Prevent committing custom emojis
/priv/static/emoji/custom/*
# Generated on crash by the VM
erl_crash.dump
@ -16,3 +19,6 @@ erl_crash.dump
# secrets files as long as you replace their contents by environment
# variables.
/config/*.secret.exs
# Database setup file, some may forget to delete it
/config/setup_db.psql

View file

@ -9,6 +9,7 @@ variables:
POSTGRES_PASSWORD: postgres
stages:
- lint
- test
before_script:
@ -18,6 +19,11 @@ before_script:
- MIX_ENV=test mix ecto.create
- MIX_ENV=test mix ecto.migrate
lint:
stage: lint
script:
- MIX_ENV=test mix format --check-formatted
unit-testing:
stage: test
script:

View file

@ -9,20 +9,6 @@ defmodule Mix.Tasks.GenerateConfig do
name = IO.gets("What is the name of your instance? (e.g. Pleroma/Soykaf): ") |> String.trim()
email = IO.gets("What's your admin email address: ") |> String.trim()
mediaproxy =
IO.gets("Do you want to activate the mediaproxy? (y/N): ")
|> String.trim()
|> String.downcase()
|> String.starts_with?("y")
proxy_url =
if mediaproxy do
IO.gets("What is the mediaproxy's URL? (e.g. https://cache.example.com): ")
|> String.trim()
else
"https://cache.example.com"
end
secret = :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64)
dbpass = :crypto.strong_rand_bytes(64) |> Base.encode64() |> binary_part(0, 64)
@ -35,8 +21,6 @@ defmodule Mix.Tasks.GenerateConfig do
email: email,
name: name,
secret: secret,
mediaproxy: mediaproxy,
proxy_url: proxy_url,
dbpass: dbpass
)

View file

@ -1,14 +1,14 @@
defmodule Mix.Tasks.RmUser do
use Mix.Task
import Mix.Ecto
alias Pleroma.User
alias Pleroma.{User, Repo}
@shortdoc "Permanently delete a user"
def run([nickname]) do
ensure_started(Repo, [])
Mix.Task.run("app.start")
with %User{local: true} = user <- User.get_by_nickname(nickname) do
user.delete()
User.delete(user)
end
end
end

View file

@ -11,9 +11,9 @@ config :pleroma, :instance,
registrations_open: true
config :pleroma, :media_proxy,
enabled: <%= mediaproxy %>,
redirect_on_failure: true,
base_url: "<%= proxy_url %>"
enabled: false,
redirect_on_failure: true
#base_url: "https://cache.pleroma.social"
# Configure your database
config :pleroma, Pleroma.Repo,

View file

@ -250,6 +250,13 @@ defmodule Pleroma.User do
Repo.get_by(User, nickname: nickname)
end
def get_by_nickname_or_email(nickname_or_email) do
case user = Repo.get_by(User, nickname: nickname_or_email) do
%User{} -> user
nil -> Repo.get_by(User, email: nickname_or_email)
end
end
def get_cached_user_info(user) do
key = "user_info:#{user.id}"
Cachex.get!(:user_cache, key, fallback: fn _ -> user_info(user) end)

View file

@ -61,6 +61,7 @@ defmodule Pleroma.Web.CommonAPI.Utils do
def make_content_html(status, mentions, attachments, tags, no_attachment_links \\ false) do
status
|> String.replace("\r", "")
|> format_input(mentions, tags)
|> maybe_add_attachments(attachments, no_attachment_links)
end

View file

@ -217,8 +217,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
activities = []
else
activities =
ActivityPub.fetch_public_activities(params)
|> Enum.reverse()
ActivityPub.fetch_public_activities(params)
|> Enum.reverse()
end
conn
@ -700,7 +700,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
end
def login_post(conn, %{"authorization" => %{"name" => name, "password" => password}}) do
with %User{} = user <- User.get_cached_by_nickname(name),
with %User{} = user <- User.get_by_nickname_or_email(name),
true <- Pbkdf2.checkpw(password, user.password_hash),
{:ok, app} <- get_or_make_app(),
{:ok, auth} <- Authorization.create_authorization(app, user),

View file

@ -29,7 +29,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do
"redirect_uri" => redirect_uri
} = params
}) do
with %User{} = user <- User.get_cached_by_nickname(name),
with %User{} = user <- User.get_by_nickname_or_email(name),
true <- Pbkdf2.checkpw(password, user.password_hash),
%App{} = app <- Repo.get_by(App, client_id: client_id),
{:ok, auth} <- Authorization.create_authorization(app, user) do

View file

@ -213,6 +213,7 @@ defmodule Pleroma.Web.Router do
get("/statuses/friends_timeline", TwitterAPI.Controller, :friends_timeline)
get("/statuses/mentions", TwitterAPI.Controller, :mentions_timeline)
get("/statuses/mentions_timeline", TwitterAPI.Controller, :mentions_timeline)
get("/qvitter/statuses/notifications", TwitterAPI.Controller, :notifications)
post("/statuses/update", TwitterAPI.Controller, :status_update)
post("/statuses/retweet/:id", TwitterAPI.Controller, :retweet)

View file

@ -3,7 +3,7 @@
<h2><%= @error %></h2>
<% end %>
<%= form_for @conn, mastodon_api_path(@conn, :login), [as: "authorization"], fn f -> %>
<%= text_input f, :name, placeholder: "Username" %>
<%= text_input f, :name, placeholder: "Username or email" %>
<br>
<%= password_input f, :password, placeholder: "Password" %>
<br>

View file

@ -2,7 +2,7 @@
<p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
<h2>OAuth Authorization</h2>
<%= form_for @conn, o_auth_path(@conn, :authorize), [as: "authorization"], fn f -> %>
<%= label f, :name, "Name" %>
<%= label f, :name, "Name or email" %>
<%= text_input f, :name %>
<br>
<%= label f, :password, "Password" %>

View file

@ -1,8 +1,8 @@
defmodule Pleroma.Web.TwitterAPI.Controller do
use Pleroma.Web, :controller
alias Pleroma.Web.TwitterAPI.{TwitterAPI, UserView, ActivityView}
alias Pleroma.Web.TwitterAPI.{TwitterAPI, UserView, ActivityView, NotificationView}
alias Pleroma.Web.CommonAPI
alias Pleroma.{Repo, Activity, User}
alias Pleroma.{Repo, Activity, User, Notification}
alias Pleroma.Web.ActivityPub.ActivityPub
alias Ecto.Changeset
@ -119,6 +119,13 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
|> render(ActivityView, "index.json", %{activities: activities, for: user})
end
def notifications(%{assigns: %{user: user}} = conn, params) do
notifications = Notification.for_user(user, params)
conn
|> render(NotificationView, "notification.json", %{notifications: notifications, for: user})
end
def follow(%{assigns: %{user: user}} = conn, params) do
case TwitterAPI.follow(user, params) do
{:ok, user, followed, _activity} ->

View file

@ -0,0 +1,65 @@
defmodule Pleroma.Web.TwitterAPI.NotificationView do
use Pleroma.Web, :view
alias Pleroma.{Notification, User}
alias Pleroma.Web.CommonAPI.Utils
alias Pleroma.Web.MediaProxy
alias Pleroma.Web.TwitterAPI.UserView
alias Pleroma.Web.TwitterAPI.ActivityView
defp get_user(ap_id, opts) do
cond do
user = opts[:users][ap_id] ->
user
String.ends_with?(ap_id, "/followers") ->
nil
ap_id == "https://www.w3.org/ns/activitystreams#Public" ->
nil
true ->
User.get_cached_by_ap_id(ap_id)
end
end
def render("notification.json", %{notifications: notifications, for: user}) do
render_many(
notifications,
Pleroma.Web.TwitterAPI.NotificationView,
"notification.json",
for: user
)
end
def render(
"notification.json",
%{
notification: %Notification{
id: id,
seen: seen,
activity: activity,
inserted_at: created_at
},
for: user
} = opts
) do
ntype =
case activity.data["type"] do
"Create" -> "mention"
"Like" -> "like"
"Announce" -> "repeat"
"Follow" -> "follow"
end
from = get_user(activity.data["actor"], opts)
%{
"id" => id,
"ntype" => ntype,
"notice" => ActivityView.render("activity.json", %{activity: activity, for: user}),
"from_profile" => UserView.render("show.json", %{user: from, for: user}),
"is_seen" => if(seen, do: 1, else: 0),
"created_at" => created_at |> Utils.format_naive_asctime()
}
end
end

View file

@ -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=stylesheet href=/static/font/css/fontello.css><link rel=stylesheet href=/static/font/css/animation.css><link href=/static/css/app.b96f1ae65bf0fc0f0564dbc7f12febfd.css rel=stylesheet></head><body style="display: none"><div id=app></div><script type=text/javascript src=/static/js/manifest.c0906490430c3def2aa2.js></script><script type=text/javascript src=/static/js/vendor.07fdc75424ae7c00c949.js></script><script type=text/javascript src=/static/js/app.be2883b7ed550f51c41d.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=stylesheet href=/static/font/css/fontello.css><link rel=stylesheet href=/static/font/css/animation.css><link href=/static/css/app.6c8da1b0ace79ad8881a0e5e716ec818.css rel=stylesheet></head><body style="display: none"><div id=app></div><script type=text/javascript src=/static/js/manifest.f80ee14f782f05d77e39.js></script><script type=text/javascript src=/static/js/vendor.ef2aee0b2db579c3a86a.js></script><script type=text/javascript src=/static/js/app.64c4246ae54f6439cb69.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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -107,6 +107,54 @@
"css": "attach",
"code": 59402,
"src": "entypo"
},
{
"uid": "e15f0d620a7897e2035c18c80142f6d9",
"css": "link-ext",
"code": 61582,
"src": "fontawesome"
},
{
"uid": "381da2c2f7fd51f8de877c044d7f439d",
"css": "picture",
"code": 59403,
"src": "fontawesome"
},
{
"uid": "872d9516df93eb6b776cc4d94bd97dac",
"css": "video",
"code": 59404,
"src": "fontawesome"
},
{
"uid": "399ef63b1e23ab1b761dfbb5591fa4da",
"css": "right-open",
"code": 59405,
"src": "fontawesome"
},
{
"uid": "d870630ff8f81e6de3958ecaeac532f2",
"css": "left-open",
"code": 59406,
"src": "fontawesome"
},
{
"uid": "fe6697b391355dec12f3d86d6d490397",
"css": "up-open",
"code": 59407,
"src": "fontawesome"
},
{
"uid": "9c1376672bb4f1ed616fdd78a23667e9",
"css": "comment-empty",
"code": 61669,
"src": "fontawesome"
},
{
"uid": "cd21cbfb28ad4d903cede582157f65dc",
"css": "bell",
"code": 59408,
"src": "fontawesome"
}
]
}

View file

@ -10,9 +10,17 @@
.icon-logout:before { content: '\e808'; } /* '' */
.icon-down-open:before { content: '\e809'; } /* '' */
.icon-attach:before { content: '\e80a'; } /* '' */
.icon-picture:before { content: '\e80b'; } /* '' */
.icon-video:before { content: '\e80c'; } /* '' */
.icon-right-open:before { content: '\e80d'; } /* '' */
.icon-left-open:before { content: '\e80e'; } /* '' */
.icon-up-open:before { content: '\e80f'; } /* '' */
.icon-bell:before { content: '\e810'; } /* '' */
.icon-spin3:before { content: '\e832'; } /* '' */
.icon-spin4:before { content: '\e834'; } /* '' */
.icon-link-ext:before { content: '\f08e'; } /* '' */
.icon-menu:before { content: '\f0c9'; } /* '' */
.icon-comment-empty:before { content: '\f0e5'; } /* '' */
.icon-reply:before { content: '\f112'; } /* '' */
.icon-binoculars:before { content: '\f1e5'; } /* '' */
.icon-user-plus:before { content: '\f234'; } /* '' */

File diff suppressed because one or more lines are too long

View file

@ -10,9 +10,17 @@
.icon-logout { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe808;&nbsp;'); }
.icon-down-open { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe809;&nbsp;'); }
.icon-attach { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80a;&nbsp;'); }
.icon-picture { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80b;&nbsp;'); }
.icon-video { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80c;&nbsp;'); }
.icon-right-open { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80d;&nbsp;'); }
.icon-left-open { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80e;&nbsp;'); }
.icon-up-open { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80f;&nbsp;'); }
.icon-bell { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe810;&nbsp;'); }
.icon-spin3 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe832;&nbsp;'); }
.icon-spin4 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe834;&nbsp;'); }
.icon-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf08e;&nbsp;'); }
.icon-menu { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c9;&nbsp;'); }
.icon-comment-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e5;&nbsp;'); }
.icon-reply { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf112;&nbsp;'); }
.icon-binoculars { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf1e5;&nbsp;'); }
.icon-user-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf234;&nbsp;'); }

View file

@ -21,9 +21,17 @@
.icon-logout { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe808;&nbsp;'); }
.icon-down-open { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe809;&nbsp;'); }
.icon-attach { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80a;&nbsp;'); }
.icon-picture { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80b;&nbsp;'); }
.icon-video { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80c;&nbsp;'); }
.icon-right-open { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80d;&nbsp;'); }
.icon-left-open { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80e;&nbsp;'); }
.icon-up-open { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe80f;&nbsp;'); }
.icon-bell { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe810;&nbsp;'); }
.icon-spin3 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe832;&nbsp;'); }
.icon-spin4 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe834;&nbsp;'); }
.icon-link-ext { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf08e;&nbsp;'); }
.icon-menu { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c9;&nbsp;'); }
.icon-comment-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e5;&nbsp;'); }
.icon-reply { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf112;&nbsp;'); }
.icon-binoculars { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf1e5;&nbsp;'); }
.icon-user-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf234;&nbsp;'); }

View file

@ -1,11 +1,11 @@
@font-face {
font-family: 'fontello';
src: url('../font/fontello.eot?73580499');
src: url('../font/fontello.eot?73580499#iefix') format('embedded-opentype'),
url('../font/fontello.woff2?73580499') format('woff2'),
url('../font/fontello.woff?73580499') format('woff'),
url('../font/fontello.ttf?73580499') format('truetype'),
url('../font/fontello.svg?73580499#fontello') format('svg');
src: url('../font/fontello.eot?47566415');
src: url('../font/fontello.eot?47566415#iefix') format('embedded-opentype'),
url('../font/fontello.woff2?47566415') format('woff2'),
url('../font/fontello.woff?47566415') format('woff'),
url('../font/fontello.ttf?47566415') format('truetype'),
url('../font/fontello.svg?47566415#fontello') format('svg');
font-weight: normal;
font-style: normal;
}
@ -15,7 +15,7 @@
@media screen and (-webkit-min-device-pixel-ratio:0) {
@font-face {
font-family: 'fontello';
src: url('../font/fontello.svg?73580499#fontello') format('svg');
src: url('../font/fontello.svg?47566415#fontello') format('svg');
}
}
*/
@ -66,9 +66,17 @@
.icon-logout:before { content: '\e808'; } /* '' */
.icon-down-open:before { content: '\e809'; } /* '' */
.icon-attach:before { content: '\e80a'; } /* '' */
.icon-picture:before { content: '\e80b'; } /* '' */
.icon-video:before { content: '\e80c'; } /* '' */
.icon-right-open:before { content: '\e80d'; } /* '' */
.icon-left-open:before { content: '\e80e'; } /* '' */
.icon-up-open:before { content: '\e80f'; } /* '' */
.icon-bell:before { content: '\e810'; } /* '' */
.icon-spin3:before { content: '\e832'; } /* '' */
.icon-spin4:before { content: '\e834'; } /* '' */
.icon-link-ext:before { content: '\f08e'; } /* '' */
.icon-menu:before { content: '\f0c9'; } /* '' */
.icon-comment-empty:before { content: '\f0e5'; } /* '' */
.icon-reply:before { content: '\f112'; } /* '' */
.icon-binoculars:before { content: '\f1e5'; } /* '' */
.icon-user-plus:before { content: '\f234'; } /* '' */

View file

@ -229,11 +229,11 @@ body {
}
@font-face {
font-family: 'fontello';
src: url('./font/fontello.eot?97388161');
src: url('./font/fontello.eot?97388161#iefix') format('embedded-opentype'),
url('./font/fontello.woff?97388161') format('woff'),
url('./font/fontello.ttf?97388161') format('truetype'),
url('./font/fontello.svg?97388161#fontello') format('svg');
src: url('./font/fontello.eot?34497073');
src: url('./font/fontello.eot?34497073#iefix') format('embedded-opentype'),
url('./font/fontello.woff?34497073') format('woff'),
url('./font/fontello.ttf?34497073') format('truetype'),
url('./font/fontello.svg?34497073#fontello') format('svg');
font-weight: normal;
font-style: normal;
}
@ -313,11 +313,23 @@ body {
<div class="the-icons span3" title="Code: 0xe808"><i class="demo-icon icon-logout">&#xe808;</i> <span class="i-name">icon-logout</span><span class="i-code">0xe808</span></div>
<div class="the-icons span3" title="Code: 0xe809"><i class="demo-icon icon-down-open">&#xe809;</i> <span class="i-name">icon-down-open</span><span class="i-code">0xe809</span></div>
<div class="the-icons span3" title="Code: 0xe80a"><i class="demo-icon icon-attach">&#xe80a;</i> <span class="i-name">icon-attach</span><span class="i-code">0xe80a</span></div>
<div class="the-icons span3" title="Code: 0xe832"><i class="demo-icon icon-spin3 animate-spin">&#xe832;</i> <span class="i-name">icon-spin3</span><span class="i-code">0xe832</span></div>
<div class="the-icons span3" title="Code: 0xe80b"><i class="demo-icon icon-picture">&#xe80b;</i> <span class="i-name">icon-picture</span><span class="i-code">0xe80b</span></div>
</div>
<div class="row">
<div class="the-icons span3" title="Code: 0xe80c"><i class="demo-icon icon-video">&#xe80c;</i> <span class="i-name">icon-video</span><span class="i-code">0xe80c</span></div>
<div class="the-icons span3" title="Code: 0xe80d"><i class="demo-icon icon-right-open">&#xe80d;</i> <span class="i-name">icon-right-open</span><span class="i-code">0xe80d</span></div>
<div class="the-icons span3" title="Code: 0xe80e"><i class="demo-icon icon-left-open">&#xe80e;</i> <span class="i-name">icon-left-open</span><span class="i-code">0xe80e</span></div>
<div class="the-icons span3" title="Code: 0xe80f"><i class="demo-icon icon-up-open">&#xe80f;</i> <span class="i-name">icon-up-open</span><span class="i-code">0xe80f</span></div>
</div>
<div class="row">
<div class="the-icons span3" title="Code: 0xe810"><i class="demo-icon icon-bell">&#xe810;</i> <span class="i-name">icon-bell</span><span class="i-code">0xe810</span></div>
<div class="the-icons span3" title="Code: 0xe832"><i class="demo-icon icon-spin3 animate-spin">&#xe832;</i> <span class="i-name">icon-spin3</span><span class="i-code">0xe832</span></div>
<div class="the-icons span3" title="Code: 0xe834"><i class="demo-icon icon-spin4 animate-spin">&#xe834;</i> <span class="i-name">icon-spin4</span><span class="i-code">0xe834</span></div>
<div class="the-icons span3" title="Code: 0xf08e"><i class="demo-icon icon-link-ext">&#xf08e;</i> <span class="i-name">icon-link-ext</span><span class="i-code">0xf08e</span></div>
</div>
<div class="row">
<div class="the-icons span3" title="Code: 0xf0c9"><i class="demo-icon icon-menu">&#xf0c9;</i> <span class="i-name">icon-menu</span><span class="i-code">0xf0c9</span></div>
<div class="the-icons span3" title="Code: 0xf0e5"><i class="demo-icon icon-comment-empty">&#xf0e5;</i> <span class="i-name">icon-comment-empty</span><span class="i-code">0xf0e5</span></div>
<div class="the-icons span3" title="Code: 0xf112"><i class="demo-icon icon-reply">&#xf112;</i> <span class="i-name">icon-reply</span><span class="i-code">0xf112</span></div>
<div class="the-icons span3" title="Code: 0xf1e5"><i class="demo-icon icon-binoculars">&#xf1e5;</i> <span class="i-name">icon-binoculars</span><span class="i-code">0xf1e5</span></div>
</div>

View file

@ -28,12 +28,28 @@
<glyph glyph-name="attach" unicode="&#xe80a;" d="M244-140q-102 0-170 72-72 70-74 166t84 190l496 496q80 80 174 54 44-12 79-47t47-79q26-96-54-176l-474-474q-40-40-88-46-48-4-80 28-30 24-27 74t47 92l332 334q24 26 50 0t0-50l-332-332q-44-44-20-70 12-8 24-6 24 4 46 26l474 474q50 50 34 108-16 60-76 76-54 14-108-36l-494-494q-66-76-64-143t52-117q50-48 117-50t141 62l496 494q24 24 50 0 26-22 0-48l-496-496q-82-82-186-82z" horiz-adv-x="939" />
<glyph glyph-name="picture" unicode="&#xe80b;" d="M357 529q0-45-31-76t-76-32-76 32-31 76 31 76 76 31 76-31 31-76z m572-215v-250h-786v107l178 179 90-89 285 285z m53 393h-893q-7 0-12-5t-6-13v-678q0-7 6-13t12-5h893q7 0 13 5t5 13v678q0 8-5 13t-13 5z m89-18v-678q0-37-26-63t-63-27h-893q-36 0-63 27t-26 63v678q0 37 26 63t63 27h893q37 0 63-27t26-63z" horiz-adv-x="1071.4" />
<glyph glyph-name="video" unicode="&#xe80c;" d="M214-43v72q0 14-10 25t-25 10h-72q-14 0-25-10t-11-25v-72q0-14 11-25t25-11h72q14 0 25 11t10 25z m0 214v72q0 14-10 25t-25 11h-72q-14 0-25-11t-11-25v-72q0-14 11-25t25-10h72q14 0 25 10t10 25z m0 215v71q0 15-10 25t-25 11h-72q-14 0-25-11t-11-25v-71q0-15 11-25t25-11h72q14 0 25 11t10 25z m572-429v286q0 14-11 25t-25 11h-429q-14 0-25-11t-10-25v-286q0-14 10-25t25-11h429q15 0 25 11t11 25z m-572 643v71q0 15-10 26t-25 10h-72q-14 0-25-10t-11-26v-71q0-14 11-25t25-11h72q14 0 25 11t10 25z m786-643v72q0 14-11 25t-25 10h-71q-15 0-25-10t-11-25v-72q0-14 11-25t25-11h71q15 0 25 11t11 25z m-214 429v285q0 15-11 26t-25 10h-429q-14 0-25-10t-10-26v-285q0-15 10-25t25-11h429q15 0 25 11t11 25z m214-215v72q0 14-11 25t-25 11h-71q-15 0-25-11t-11-25v-72q0-14 11-25t25-10h71q15 0 25 10t11 25z m0 215v71q0 15-11 25t-25 11h-71q-15 0-25-11t-11-25v-71q0-15 11-25t25-11h71q15 0 25 11t11 25z m0 214v71q0 15-11 26t-25 10h-71q-15 0-25-10t-11-26v-71q0-14 11-25t25-11h71q15 0 25 11t11 25z m71 89v-750q0-37-26-63t-63-26h-893q-36 0-63 26t-26 63v750q0 37 26 63t63 27h893q37 0 63-27t26-63z" horiz-adv-x="1071.4" />
<glyph glyph-name="right-open" unicode="&#xe80d;" d="M618 361l-414-415q-11-10-25-10t-25 10l-93 93q-11 11-11 25t11 25l296 297-296 296q-11 11-11 25t11 25l93 93q10 11 25 11t25-11l414-414q10-11 10-25t-10-25z" horiz-adv-x="714.3" />
<glyph glyph-name="left-open" unicode="&#xe80e;" d="M654 682l-297-296 297-297q10-10 10-25t-10-25l-93-93q-11-10-25-10t-25 10l-414 415q-11 10-11 25t11 25l414 414q10 11 25 11t25-11l93-93q10-10 10-25t-10-25z" horiz-adv-x="714.3" />
<glyph glyph-name="up-open" unicode="&#xe80f;" d="M939 107l-92-92q-11-10-26-10t-25 10l-296 297-296-297q-11-10-25-10t-25 10l-93 92q-11 11-11 26t11 25l414 414q11 10 25 10t25-10l414-414q11-11 11-25t-11-26z" horiz-adv-x="1000" />
<glyph glyph-name="bell" unicode="&#xe810;" d="M509-96q0 8-9 8-33 0-57 24t-23 57q0 9-9 9t-9-9q0-41 29-70t69-28q9 0 9 9z m-372 160h726q-149 168-149 465 0 28-13 58t-39 58-67 45-95 17-95-17-67-45-39-58-13-58q0-297-149-465z m827 0q0-29-21-50t-50-21h-250q0-59-42-101t-101-42-101 42-42 101h-250q-29 0-50 21t-21 50q28 24 51 49t47 67 42 89 27 115 11 145q0 84 66 157t171 89q-5 10-5 21 0 23 16 38t38 16 38-16 16-38q0-11-5-21 106-16 171-89t66-157q0-78 11-145t28-115 41-89 48-67 50-49z" horiz-adv-x="1000" />
<glyph glyph-name="spin3" unicode="&#xe832;" d="M494 850c-266 0-483-210-494-472-1-19 13-20 13-20l84 0c16 0 19 10 19 18 10 199 176 358 378 358 107 0 205-45 273-118l-58-57c-11-12-11-27 5-31l247-50c21-5 46 11 37 44l-58 227c-2 9-16 22-29 13l-65-60c-89 91-214 148-352 148z m409-508c-16 0-19-10-19-18-10-199-176-358-377-358-108 0-205 45-274 118l59 57c10 12 10 27-5 31l-248 50c-21 5-46-11-37-44l58-227c2-9 16-22 30-13l64 60c89-91 214-148 353-148 265 0 482 210 493 473 1 18-13 19-13 19l-84 0z" horiz-adv-x="1000" />
<glyph glyph-name="spin4" unicode="&#xe834;" d="M498 850c-114 0-228-39-320-116l0 0c173 140 428 130 588-31 134-134 164-332 89-495-10-29-5-50 12-68 21-20 61-23 84 0 3 3 12 15 15 24 71 180 33 393-112 539-99 98-228 147-356 147z m-409-274c-14 0-29-5-39-16-3-3-13-15-15-24-71-180-34-393 112-539 185-185 479-195 676-31l0 0c-173-140-428-130-589 31-134 134-163 333-89 495 11 29 6 50-12 68-11 11-27 17-44 16z" horiz-adv-x="1001" />
<glyph glyph-name="link-ext" unicode="&#xf08e;" d="M786 332v-178q0-67-47-114t-114-47h-464q-67 0-114 47t-47 114v464q0 66 47 113t114 48h393q7 0 12-5t5-13v-36q0-8-5-13t-12-5h-393q-37 0-63-26t-27-63v-464q0-37 27-63t63-27h464q37 0 63 27t26 63v178q0 8 5 13t13 5h36q8 0 13-5t5-13z m214 482v-285q0-15-11-25t-25-11-25 11l-98 98-364-364q-5-6-13-6t-12 6l-64 64q-6 5-6 12t6 13l364 364-98 98q-11 11-11 25t11 25 25 11h285q15 0 25-11t11-25z" horiz-adv-x="1000" />
<glyph glyph-name="menu" unicode="&#xf0c9;" d="M857 100v-71q0-15-10-25t-26-11h-785q-15 0-25 11t-11 25v71q0 15 11 25t25 11h785q15 0 26-11t10-25z m0 286v-72q0-14-10-25t-26-10h-785q-15 0-25 10t-11 25v72q0 14 11 25t25 10h785q15 0 26-10t10-25z m0 285v-71q0-14-10-25t-26-11h-785q-15 0-25 11t-11 25v71q0 15 11 26t25 10h785q15 0 26-10t10-26z" horiz-adv-x="857.1" />
<glyph glyph-name="comment-empty" unicode="&#xf0e5;" d="M500 636q-114 0-213-39t-157-105-59-142q0-62 40-119t113-98l48-28-15-53q-13-51-39-97 85 36 154 96l24 21 32-3q38-5 72-5 114 0 213 39t157 105 59 142-59 142-157 105-213 39z m500-286q0-97-67-179t-182-130-251-48q-39 0-81 4-110-97-257-135-27-8-63-12h-3q-8 0-15 6t-9 15v1q-2 2 0 6t1 6 2 5l4 5t4 5 4 5q4 5 17 19t20 22 17 22 18 28 15 33 15 42q-88 50-138 123t-51 157q0 97 67 179t182 130 251 48 251-48 182-130 67-179z" horiz-adv-x="1000" />
<glyph glyph-name="reply" unicode="&#xf112;" d="M1000 225q0-93-71-252-1-4-6-13t-7-17-7-12q-7-10-16-10-8 0-13 6t-5 14q0 5 1 15t2 13q3 38 3 69 0 56-10 101t-27 77-45 56-59 39-74 24-86 12-98 3h-125v-143q0-14-10-25t-26-11-25 11l-285 286q-11 10-11 25t11 25l285 286q11 10 25 10t26-10 10-25v-143h125q398 0 488-225 30-75 30-186z" horiz-adv-x="1000" />
<glyph glyph-name="binoculars" unicode="&#xf1e5;" d="M393 671v-428q0-15-11-25t-25-11v-321q0-15-10-25t-26-11h-285q-15 0-25 11t-11 25v285l139 488q4 12 17 12h237z m178 0v-392h-142v392h142z m429-500v-285q0-15-11-25t-25-11h-285q-15 0-25 11t-11 25v321q-15 0-25 11t-11 25v428h237q13 0 17-12z m-589 661v-125h-197v125q0 8 5 13t13 5h161q8 0 13-5t5-13z m375 0v-125h-197v125q0 8 5 13t13 5h161q8 0 13-5t5-13z" horiz-adv-x="1000" />

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 11 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

View file

@ -1,2 +0,0 @@
!function(e){function t(r){if(n[r])return n[r].exports;var a=n[r]={exports:{},id:r,loaded:!1};return e[r].call(a.exports,a,a.exports,t),a.loaded=!0,a.exports}var r=window.webpackJsonp;window.webpackJsonp=function(c,o){for(var p,l,s=0,i=[];s<c.length;s++)l=c[s],a[l]&&i.push.apply(i,a[l]),a[l]=0;for(p in o)Object.prototype.hasOwnProperty.call(o,p)&&(e[p]=o[p]);for(r&&r(c,o);i.length;)i.shift().call(null,t);if(o[0])return n[0]=0,t(0)};var n={},a={0:0};t.e=function(e,r){if(0===a[e])return r.call(null,t);if(void 0!==a[e])a[e].push(r);else{a[e]=[r];var n=document.getElementsByTagName("head")[0],c=document.createElement("script");c.type="text/javascript",c.charset="utf-8",c.async=!0,c.src=t.p+"static/js/"+e+"."+{1:"07fdc75424ae7c00c949",2:"be2883b7ed550f51c41d"}[e]+".js",n.appendChild(c)}},t.m=e,t.c=n,t.p="/"}([]);
//# sourceMappingURL=manifest.c0906490430c3def2aa2.js.map

View file

@ -0,0 +1,2 @@
!function(e){function t(a){if(r[a])return r[a].exports;var n=r[a]={exports:{},id:a,loaded:!1};return e[a].call(n.exports,n,n.exports,t),n.loaded=!0,n.exports}var a=window.webpackJsonp;window.webpackJsonp=function(c,o){for(var p,l,s=0,i=[];s<c.length;s++)l=c[s],n[l]&&i.push.apply(i,n[l]),n[l]=0;for(p in o)Object.prototype.hasOwnProperty.call(o,p)&&(e[p]=o[p]);for(a&&a(c,o);i.length;)i.shift().call(null,t);if(o[0])return r[0]=0,t(0)};var r={},n={0:0};t.e=function(e,a){if(0===n[e])return a.call(null,t);if(void 0!==n[e])n[e].push(a);else{n[e]=[a];var r=document.getElementsByTagName("head")[0],c=document.createElement("script");c.type="text/javascript",c.charset="utf-8",c.async=!0,c.src=t.p+"static/js/"+e+"."+{1:"ef2aee0b2db579c3a86a",2:"64c4246ae54f6439cb69"}[e]+".js",r.appendChild(c)}},t.m=e,t.c=r,t.p="/"}([]);
//# sourceMappingURL=manifest.f80ee14f782f05d77e39.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -2,9 +2,10 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
use Pleroma.Web.ConnCase
alias Pleroma.Web.TwitterAPI.Representers.ActivityRepresenter
alias Pleroma.Builders.{ActivityBuilder, UserBuilder}
alias Pleroma.{Repo, Activity, User, Object}
alias Pleroma.{Repo, Activity, User, Object, Notification}
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.TwitterAPI.UserView
alias Pleroma.Web.TwitterAPI.NotificationView
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.TwitterAPI.TwitterAPI
@ -247,6 +248,35 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
end
end
describe "GET /api/qvitter/statuses/notifications.json" do
setup [:valid_user]
test "without valid credentials", %{conn: conn} do
conn = get(conn, "/api/qvitter/statuses/notifications.json")
assert json_response(conn, 403) == %{"error" => "Invalid credentials."}
end
test "with credentials", %{conn: conn, user: current_user} do
{:ok, activity} =
ActivityBuilder.insert(%{"to" => [current_user.ap_id]}, %{user: current_user})
conn =
conn
|> with_credentials(current_user.nickname, "test")
|> get("/api/qvitter/statuses/notifications.json")
response = json_response(conn, 200)
assert length(response) == 1
assert response ==
NotificationView.render("notification.json", %{
notifications: Notification.for_user(current_user),
for: current_user
})
end
end
describe "GET /statuses/user_timeline.json" do
setup [:valid_user]

View file

@ -0,0 +1,108 @@
defmodule Pleroma.Web.TwitterAPI.NotificationViewTest do
use Pleroma.DataCase
alias Pleroma.{User, Notification}
alias Pleroma.Web.TwitterAPI.TwitterAPI
alias Pleroma.Web.TwitterAPI.NotificationView
alias Pleroma.Web.TwitterAPI.UserView
alias Pleroma.Web.TwitterAPI.ActivityView
alias Pleroma.Web.CommonAPI.Utils
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Builders.UserBuilder
import Pleroma.Factory
setup do
user = insert(:user, bio: "<span>Here's some html</span>")
[user: user]
end
test "A follow notification" do
note_activity = insert(:note_activity)
user = User.get_cached_by_ap_id(note_activity.data["actor"])
follower = insert(:user)
{:ok, follower} = User.follow(follower, user)
{:ok, activity} = ActivityPub.follow(follower, user)
Cachex.set(:user_cache, "user_info:#{user.id}", User.user_info(Repo.get!(User, user.id)))
[follow_notif] = Notification.for_user(user)
represented = %{
"created_at" => follow_notif.inserted_at |> Utils.format_naive_asctime(),
"from_profile" => UserView.render("show.json", %{user: follower, for: user}),
"id" => follow_notif.id,
"is_seen" => 0,
"notice" => ActivityView.render("activity.json", %{activity: activity, for: user}),
"ntype" => "follow"
}
assert represented ==
NotificationView.render("notification.json", %{notification: follow_notif, for: user})
end
test "A mention notification" do
user = insert(:user)
other_user = insert(:user)
{:ok, activity} =
TwitterAPI.create_status(other_user, %{"status" => "Päivää, @#{user.nickname}"})
[notification] = Notification.for_user(user)
represented = %{
"created_at" => notification.inserted_at |> Utils.format_naive_asctime(),
"from_profile" => UserView.render("show.json", %{user: other_user, for: user}),
"id" => notification.id,
"is_seen" => 0,
"notice" => ActivityView.render("activity.json", %{activity: activity, for: user}),
"ntype" => "mention"
}
assert represented ==
NotificationView.render("notification.json", %{notification: notification, for: user})
end
test "A retweet notification" do
note_activity = insert(:note_activity)
user = User.get_cached_by_ap_id(note_activity.data["actor"])
repeater = insert(:user)
{:ok, activity} = TwitterAPI.repeat(repeater, note_activity.id)
[notification] = Notification.for_user(user)
represented = %{
"created_at" => notification.inserted_at |> Utils.format_naive_asctime(),
"from_profile" => UserView.render("show.json", %{user: repeater, for: user}),
"id" => notification.id,
"is_seen" => 0,
"notice" =>
ActivityView.render("activity.json", %{activity: notification.activity, for: user}),
"ntype" => "repeat"
}
assert represented ==
NotificationView.render("notification.json", %{notification: notification, for: user})
end
test "A like notification" do
note_activity = insert(:note_activity)
user = User.get_cached_by_ap_id(note_activity.data["actor"])
liker = insert(:user)
{:ok, activity} = TwitterAPI.fav(liker, note_activity.id)
[notification] = Notification.for_user(user)
represented = %{
"created_at" => notification.inserted_at |> Utils.format_naive_asctime(),
"from_profile" => UserView.render("show.json", %{user: liker, for: user}),
"id" => notification.id,
"is_seen" => 0,
"notice" =>
ActivityView.render("activity.json", %{activity: notification.activity, for: user}),
"ntype" => "like"
}
assert represented ==
NotificationView.render("notification.json", %{notification: notification, for: user})
end
end