Add basic mastodon notification support.
This commit is contained in:
parent
7616b202ea
commit
61adf676d5
|
@ -1,11 +1,12 @@
|
|||
defmodule Pleroma.Activity do
|
||||
use Ecto.Schema
|
||||
alias Pleroma.{Repo, Activity}
|
||||
alias Pleroma.{Repo, Activity, Notification}
|
||||
import Ecto.Query
|
||||
|
||||
schema "activities" do
|
||||
field :data, :map
|
||||
field :local, :boolean, default: true
|
||||
has_many :notifications, Notification
|
||||
|
||||
timestamps()
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
||||
import Ecto.{Changeset, Query}
|
||||
alias Pleroma.{Repo, User, Object, Web}
|
||||
alias Pleroma.{Repo, User, Object, Web, Activity, Notification}
|
||||
alias Comeonin.Pbkdf2
|
||||
alias Pleroma.Web.{OStatus, Websub}
|
||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||
|
@ -22,6 +22,7 @@ defmodule Pleroma.User do
|
|||
field :local, :boolean, default: true
|
||||
field :info, :map, default: %{}
|
||||
field :follower_address, :string
|
||||
has_many :notifications, Notification
|
||||
|
||||
timestamps()
|
||||
end
|
||||
|
@ -239,4 +240,12 @@ def update_follower_count(%User{} = user) do
|
|||
|
||||
Repo.update(cs)
|
||||
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
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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}
|
||||
import Ecto.Query
|
||||
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"]),
|
||||
map <- lazy_put_activity_defaults(map),
|
||||
: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
|
||||
%Activity{} = activity -> {:ok, activity}
|
||||
error -> {:error, error}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
||||
use Pleroma.Web, :controller
|
||||
alias Pleroma.{Repo, Activity, User}
|
||||
alias Pleroma.{Repo, Activity, User, Notification}
|
||||
alias Pleroma.Web.OAuth.App
|
||||
alias Pleroma.Web
|
||||
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
|
||||
|
||||
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
|
||||
Logger.debug("Unimplemented, returning an empty array")
|
||||
json(conn, [])
|
||||
|
|
|
@ -65,7 +65,7 @@ def user_fetcher(username) do
|
|||
post "/statuses/:id/favourite", MastodonAPIController, :fav_status
|
||||
post "/statuses/:id/unfavourite", MastodonAPIController, :unfav_status
|
||||
|
||||
get "/notifications", MastodonAPIController, :empty_array
|
||||
get "/notifications", MastodonAPIController, :notifications
|
||||
end
|
||||
|
||||
scope "/api", Pleroma.Web do
|
||||
|
|
|
@ -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
|
|
@ -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 New Issue