Merge branch 'feld/pleroma-feld-mastodon-usersearch' into develop

This commit is contained in:
Roger Braun 2017-10-30 19:25:32 +01:00
commit f23edd2d6b
19 changed files with 104 additions and 31 deletions

View file

@ -24,7 +24,7 @@ def change(struct, params \\ %{}) do
def get_by_ap_id(nil), do: nil
def get_by_ap_id(ap_id) do
Repo.one(from object in Object,
where: fragment("? @> ?", object.data, ^%{id: ap_id}))
where: fragment("(?)->>'id' = ?", object.data, ^ap_id))
end
def get_cached_by_ap_id(ap_id) do

View file

@ -241,7 +241,7 @@ def get_friends(%User{id: id, following: following}) do
def update_note_count(%User{} = user) do
note_count_query = from a in Object,
where: fragment("? @> ?", a.data, ^%{actor: user.ap_id, type: "Note"}),
where: fragment("?->>'actor' = ? and ?->>'type' = 'Note'", a.data, ^user.ap_id, a.data),
select: count(a.id)
note_count = Repo.one(note_count_query)
@ -274,4 +274,14 @@ def get_notified_from_activity(%Activity{data: %{"to" => to}} = activity) do
Repo.all(query)
end
def search(query, resolve) do
if resolve do
User.get_or_fetch_by_nickname(query)
end
q = from u in User,
where: fragment("(to_tsvector('english', ?) || to_tsvector('english', ?)) @@ plainto_tsquery('english', ?)", u.nickname, u.name, ^query),
limit: 20
Repo.all(q)
end
end

View file

@ -90,7 +90,11 @@ def update_object_in_activities(%{data: %{"id" => id}} = object) do
"""
def get_existing_like(actor, %{data: %{"id" => id}} = object) do
query = from activity in Activity,
where: fragment("? @> ?", activity.data, ^%{actor: actor, object: id, type: "Like"})
where: fragment("(?)->>'actor' = ?", activity.data, ^actor),
# this is to use the index
where: fragment("coalesce((?)->'object'->>'id', (?)->>'object') = ?", activity.data, activity.data, ^id),
where: fragment("(?)->>'type' = 'Like'", activity.data)
Repo.one(query)
end

View file

@ -271,9 +271,27 @@ def following(conn, %{"id" => id}) do
def follow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do
with %User{} = followed <- Repo.get(User, id),
{:ok, follower} <- User.follow(follower, followed),
{:ok, activity} <- ActivityPub.follow(follower, followed) do
{:ok, follower} <- User.follow(follower, followed),
{:ok, activity} <- ActivityPub.follow(follower, followed) do
render conn, AccountView, "relationship.json", %{user: follower, target: followed}
else
{:error, message} = err ->
conn
|> put_resp_content_type("application/json")
|> send_resp(403, Poison.encode!(%{"error" => message}))
end
end
def follow(%{assigns: %{user: follower}} = conn, %{"uri" => uri}) do
with %User{} = followed <- Repo.get_by(User, nickname: uri),
{:ok, follower} <- User.follow(follower, followed),
{:ok, activity} <- ActivityPub.follow(follower, followed) do
render conn, AccountView, "account.json", %{user: followed}
else
{:error, message} = err ->
conn
|> put_resp_content_type("application/json")
|> send_resp(403, Poison.encode!(%{"error" => message}))
end
end
@ -291,14 +309,7 @@ def unfollow(%{assigns: %{user: follower}} = conn, %{"id" => id}) do
end
def search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do
if params["resolve"] == "true" do
User.get_or_fetch_by_nickname(query)
end
q = from u in User,
where: fragment("(to_tsvector('english', ?) || to_tsvector('english', ?)) @@ plainto_tsquery('english', ?)", u.nickname, u.name, ^query),
limit: 20
accounts = Repo.all(q)
accounts = User.search(query, params["resolve"] == "true")
q = from a in Activity,
where: fragment("?->>'type' = 'Create'", a.data),
@ -315,6 +326,14 @@ def search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do
json(conn, res)
end
def account_search(%{assigns: %{user: user}} = conn, %{"q" => query} = params) do
accounts = User.search(query, params["resolve"] == "true")
res = AccountView.render("accounts.json", users: accounts, for: user, as: :user)
json(conn, res)
end
def favourites(%{assigns: %{user: user}} = conn, params) do
params = conn
|> Map.put("type", "Create")

View file

@ -55,6 +55,7 @@ def user_fetcher(username) do
get "/accounts/verify_credentials", MastodonAPIController, :verify_credentials
get "/accounts/relationships", MastodonAPIController, :relationships
get "/accounts/search", MastodonAPIController, :account_search
post "/accounts/:id/follow", MastodonAPIController, :follow
post "/accounts/:id/unfollow", MastodonAPIController, :unfollow
post "/accounts/:id/block", MastodonAPIController, :relationship_noop
@ -62,6 +63,8 @@ def user_fetcher(username) do
post "/accounts/:id/mute", MastodonAPIController, :relationship_noop
post "/accounts/:id/unmute", MastodonAPIController, :relationship_noop
post "/follows", MastodonAPIController, :follow
get "/blocks", MastodonAPIController, :empty_array
get "/domain_blocks", MastodonAPIController, :empty_array
get "/follow_requests", MastodonAPIController, :empty_array

View file

@ -0,0 +1,7 @@
defmodule Pleroma.Repo.Migrations.DropObjectIndex do
use Ecto.Migration
def change do
drop_if_exists index(:objects, [:data], using: :gin)
end
end

View file

@ -0,0 +1,9 @@
defmodule Pleroma.Repo.Migrations.AddObjectActorIndex do
use Ecto.Migration
@disable_ddl_transaction true
def change do
create index(:objects, ["(data->>'actor')", "(data->>'type')"], concurrently: true, name: :objects_actor_type)
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.9cfa0ec1ee2d157fc360f5a3f1ee687c.css rel=stylesheet></head><body style="display: none"><div id=app></div><script type=text/javascript src=/static/js/manifest.13905a962b52e27fb039.js></script><script type=text/javascript src=/static/js/vendor.5ae36edd0f238a1334af.js></script><script type=text/javascript src=/static/js/app.437f43ecaf6ade101b9a.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.9cfa0ec1ee2d157fc360f5a3f1ee687c.css rel=stylesheet></head><body style="display: none"><div id=app></div><script type=text/javascript src=/static/js/manifest.5e2e6cbffed3dea6be7c.js></script><script type=text/javascript src=/static/js/vendor.a940853cbf3c748efda4.js></script><script type=text/javascript src=/static/js/app.37dc091547e5c8fb0a0e.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

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

View file

@ -0,0 +1,2 @@
!function(e){function t(n){if(a[n])return a[n].exports;var r=a[n]={exports:{},id:n,loaded:!1};return e[n].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var n=window.webpackJsonp;window.webpackJsonp=function(c,o){for(var p,s,l=0,i=[];l<c.length;l++)s=c[l],r[s]&&i.push.apply(i,r[s]),r[s]=0;for(p in o)e[p]=o[p];for(n&&n(c,o);i.length;)i.shift().call(null,t);if(o[0])return a[0]=0,t(0)};var a={},r={0:0};t.e=function(e,n){if(0===r[e])return n.call(null,t);if(void 0!==r[e])r[e].push(n);else{r[e]=[n];var a=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:"a940853cbf3c748efda4",2:"37dc091547e5c8fb0a0e"}[e]+".js",a.appendChild(c)}},t.m=e,t.c=a,t.p="/"}([]);
//# sourceMappingURL=manifest.5e2e6cbffed3dea6be7c.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

@ -281,6 +281,14 @@ test "following / unfollowing a user", %{conn: conn} do
|> post("/api/v1/accounts/#{other_user.id}/unfollow")
assert %{"id" => id, "following" => false} = json_response(conn, 200)
user = Repo.get(User, user.id)
conn = build_conn()
|> assign(:user, user)
|> post("/api/v1/follows", %{"uri" => other_user.nickname})
assert %{"id" => id} = json_response(conn, 200)
assert id == other_user.id
end
test "unimplemented block/mute endpoints" do
@ -311,6 +319,19 @@ test "unimplemented mutes, follow_requests, blocks, domain blocks" do
end)
end
test "account seach", %{conn: conn} do
user = insert(:user)
user_two = insert(:user, %{nickname: "shp@shitposter.club"})
user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"})
conn = conn
|> assign(:user, user)
|> get("/api/v1/accounts/search", %{"q" => "2hu"})
assert [account] = json_response(conn, 200)
assert account["id"] == user_three.id
end
test "search", %{conn: conn} do
user = insert(:user)
user_two = insert(:user, %{nickname: "shp@shitposter.club"})