Add basic mastodon notification support.
This commit is contained in:
parent
7616b202ea
commit
61adf676d5
8 changed files with 108 additions and 6 deletions
|
@ -1,11 +1,12 @@
|
||||||
defmodule Pleroma.Activity do
|
defmodule Pleroma.Activity do
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
alias Pleroma.{Repo, Activity}
|
alias Pleroma.{Repo, Activity, Notification}
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
|
|
||||||
schema "activities" do
|
schema "activities" do
|
||||||
field :data, :map
|
field :data, :map
|
||||||
field :local, :boolean, default: true
|
field :local, :boolean, default: true
|
||||||
|
has_many :notifications, Notification
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
38
lib/pleroma/notification.ex
Normal file
38
lib/pleroma/notification.ex
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
defmodule Pleroma.Notification do
|
||||||
|
use Ecto.Schema
|
||||||
|
alias Pleroma.{User, Activity, Notification, Repo}
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
|
schema "notifications" do
|
||||||
|
field :seen, :boolean, default: false
|
||||||
|
belongs_to :user, Pleroma.User
|
||||||
|
belongs_to :activity, Pleroma.Activity
|
||||||
|
|
||||||
|
timestamps()
|
||||||
|
end
|
||||||
|
|
||||||
|
def for_user(user, opts \\ %{}) do
|
||||||
|
query = from n in Notification,
|
||||||
|
where: n.user_id == ^user.id,
|
||||||
|
order_by: [desc: n.id],
|
||||||
|
preload: [:activity],
|
||||||
|
limit: 20
|
||||||
|
Repo.all(query)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_notifications(%Activity{id: id, data: %{"to" => to, "type" => type}} = activity) when type in ["Create"] do
|
||||||
|
users = User.get_notified_from_activity(activity)
|
||||||
|
|
||||||
|
notifications = Enum.map(users, fn (user) -> create_notification(activity, user) end)
|
||||||
|
{:ok, notifications}
|
||||||
|
end
|
||||||
|
def create_notifications(_), do: {:ok, []}
|
||||||
|
|
||||||
|
# TODO move to sql, too.
|
||||||
|
def create_notification(%Activity{} = activity, %User{} = user) do
|
||||||
|
notification = %Notification{user_id: user.id, activity_id: activity.id}
|
||||||
|
{:ok, notification} = Repo.insert(notification)
|
||||||
|
notification
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -2,7 +2,7 @@ defmodule Pleroma.User do
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
|
|
||||||
import Ecto.{Changeset, Query}
|
import Ecto.{Changeset, Query}
|
||||||
alias Pleroma.{Repo, User, Object, Web}
|
alias Pleroma.{Repo, User, Object, Web, Activity, Notification}
|
||||||
alias Comeonin.Pbkdf2
|
alias Comeonin.Pbkdf2
|
||||||
alias Pleroma.Web.{OStatus, Websub}
|
alias Pleroma.Web.{OStatus, Websub}
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
|
@ -22,6 +22,7 @@ defmodule Pleroma.User do
|
||||||
field :local, :boolean, default: true
|
field :local, :boolean, default: true
|
||||||
field :info, :map, default: %{}
|
field :info, :map, default: %{}
|
||||||
field :follower_address, :string
|
field :follower_address, :string
|
||||||
|
has_many :notifications, Notification
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
@ -239,4 +240,12 @@ def update_follower_count(%User{} = user) do
|
||||||
|
|
||||||
Repo.update(cs)
|
Repo.update(cs)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get_notified_from_activity(%Activity{data: %{"to" => to}} = activity) do
|
||||||
|
query = from u in User,
|
||||||
|
where: u.ap_id in ^to,
|
||||||
|
where: u.local == true
|
||||||
|
|
||||||
|
Repo.all(query)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
defmodule Pleroma.Web.ActivityPub.ActivityPub do
|
||||||
alias Pleroma.{Activity, Repo, Object, Upload, User, Web}
|
alias Pleroma.{Activity, Repo, Object, Upload, User, Web, Notification}
|
||||||
alias Ecto.{Changeset, UUID}
|
alias Ecto.{Changeset, UUID}
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
import Pleroma.Web.ActivityPub.Utils
|
import Pleroma.Web.ActivityPub.Utils
|
||||||
|
@ -9,7 +9,9 @@ def insert(map, local \\ true) when is_map(map) do
|
||||||
with nil <- Activity.get_by_ap_id(map["id"]),
|
with nil <- Activity.get_by_ap_id(map["id"]),
|
||||||
map <- lazy_put_activity_defaults(map),
|
map <- lazy_put_activity_defaults(map),
|
||||||
:ok <- insert_full_object(map) do
|
:ok <- insert_full_object(map) do
|
||||||
Repo.insert(%Activity{data: map, local: local})
|
{:ok, activity} = Repo.insert(%Activity{data: map, local: local})
|
||||||
|
Notification.create_notifications(activity)
|
||||||
|
{:ok, activity}
|
||||||
else
|
else
|
||||||
%Activity{} = activity -> {:ok, activity}
|
%Activity{} = activity -> {:ok, activity}
|
||||||
error -> {:error, error}
|
error -> {:error, error}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
alias Pleroma.{Repo, Activity, User}
|
alias Pleroma.{Repo, Activity, User, Notification}
|
||||||
alias Pleroma.Web.OAuth.App
|
alias Pleroma.Web.OAuth.App
|
||||||
alias Pleroma.Web
|
alias Pleroma.Web
|
||||||
alias Pleroma.Web.MastodonAPI.{StatusView, AccountView}
|
alias Pleroma.Web.MastodonAPI.{StatusView, AccountView}
|
||||||
|
@ -132,6 +132,20 @@ def unfav_status(%{assigns: %{user: user}} = conn, %{"id" => ap_id_or_id}) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def notifications(%{assigns: %{user: user}} = conn, params) do
|
||||||
|
notifications = Notification.for_user(user, params)
|
||||||
|
result = Enum.map(notifications, fn (%{id: id, activity: activity, inserted_at: created_at}) ->
|
||||||
|
actor = User.get_cached_by_ap_id(activity.data["actor"])
|
||||||
|
case activity.data["type"] do
|
||||||
|
"Create" -> %{ id: id, type: "mention", created_at: created_at, account: AccountView.render("account.json", %{user: actor}), status: StatusView.render("status.json", %{activity: activity})}
|
||||||
|
_ -> nil
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|> Enum.filter(&(&1))
|
||||||
|
|
||||||
|
json(conn, result)
|
||||||
|
end
|
||||||
|
|
||||||
def empty_array(conn, _) do
|
def empty_array(conn, _) do
|
||||||
Logger.debug("Unimplemented, returning an empty array")
|
Logger.debug("Unimplemented, returning an empty array")
|
||||||
json(conn, [])
|
json(conn, [])
|
||||||
|
|
|
@ -65,7 +65,7 @@ def user_fetcher(username) do
|
||||||
post "/statuses/:id/favourite", MastodonAPIController, :fav_status
|
post "/statuses/:id/favourite", MastodonAPIController, :fav_status
|
||||||
post "/statuses/:id/unfavourite", MastodonAPIController, :unfav_status
|
post "/statuses/:id/unfavourite", MastodonAPIController, :unfav_status
|
||||||
|
|
||||||
get "/notifications", MastodonAPIController, :empty_array
|
get "/notifications", MastodonAPIController, :notifications
|
||||||
end
|
end
|
||||||
|
|
||||||
scope "/api", Pleroma.Web do
|
scope "/api", Pleroma.Web do
|
||||||
|
|
15
priv/repo/migrations/20170911123607_create_notifications.exs
Normal file
15
priv/repo/migrations/20170911123607_create_notifications.exs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
defmodule Pleroma.Repo.Migrations.CreateNotifications do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
create table(:notifications) do
|
||||||
|
add :user_id, references(:users, on_delete: :delete_all)
|
||||||
|
add :activity_id, references(:activities, on_delete: :delete_all)
|
||||||
|
add :seen, :boolean, default: false
|
||||||
|
|
||||||
|
timestamps()
|
||||||
|
end
|
||||||
|
|
||||||
|
create index(:notifications, [:user_id])
|
||||||
|
end
|
||||||
|
end
|
23
test/notification_test.exs
Normal file
23
test/notification_test.exs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
defmodule Pleroma.NotificationTest do
|
||||||
|
use Pleroma.DataCase
|
||||||
|
alias Pleroma.Web.TwitterAPI.TwitterAPI
|
||||||
|
alias Pleroma.{User, Notification}
|
||||||
|
import Pleroma.Factory
|
||||||
|
|
||||||
|
describe "create_notifications" do
|
||||||
|
test "notifies someone when they are directly addressed" do
|
||||||
|
user = insert(:user)
|
||||||
|
other_user = insert(:user)
|
||||||
|
third_user = insert(:user)
|
||||||
|
|
||||||
|
{:ok, activity} = TwitterAPI.create_status(user, %{"status" => "hey @#{other_user.nickname} and @#{third_user.nickname}"})
|
||||||
|
|
||||||
|
{:ok, [notification, other_notification]} = Notification.create_notifications(activity)
|
||||||
|
|
||||||
|
assert notification.user_id == other_user.id
|
||||||
|
assert notification.activity_id == activity.id
|
||||||
|
assert other_notification.user_id == third_user.id
|
||||||
|
assert other_notification.activity_id == activity.id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue