forked from YokaiRick/akkoma
Add scheduled activities
This commit is contained in:
parent
876965a7e7
commit
7bf622ce73
8 changed files with 284 additions and 0 deletions
74
lib/pleroma/scheduled_activity.ex
Normal file
74
lib/pleroma/scheduled_activity.ex
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.ScheduledActivity do
|
||||||
|
use Ecto.Schema
|
||||||
|
|
||||||
|
alias Pleroma.Repo
|
||||||
|
alias Pleroma.ScheduledActivity
|
||||||
|
alias Pleroma.User
|
||||||
|
|
||||||
|
import Ecto.Query
|
||||||
|
import Ecto.Changeset
|
||||||
|
|
||||||
|
schema "scheduled_activities" do
|
||||||
|
belongs_to(:user, User, type: Pleroma.FlakeId)
|
||||||
|
field(:scheduled_at, :naive_datetime)
|
||||||
|
field(:params, :map)
|
||||||
|
|
||||||
|
timestamps()
|
||||||
|
end
|
||||||
|
|
||||||
|
def changeset(%ScheduledActivity{} = scheduled_activity, attrs) do
|
||||||
|
scheduled_activity
|
||||||
|
|> cast(attrs, [:scheduled_at, :params])
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_changeset(%ScheduledActivity{} = scheduled_activity, attrs) do
|
||||||
|
scheduled_activity
|
||||||
|
|> cast(attrs, [:scheduled_at])
|
||||||
|
end
|
||||||
|
|
||||||
|
def new(%User{} = user, attrs) do
|
||||||
|
%ScheduledActivity{user_id: user.id}
|
||||||
|
|> changeset(attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create(%User{} = user, attrs) do
|
||||||
|
user
|
||||||
|
|> new(attrs)
|
||||||
|
|> Repo.insert()
|
||||||
|
end
|
||||||
|
|
||||||
|
def get(%User{} = user, scheduled_activity_id) do
|
||||||
|
ScheduledActivity
|
||||||
|
|> where(user_id: ^user.id)
|
||||||
|
|> where(id: ^scheduled_activity_id)
|
||||||
|
|> Repo.one()
|
||||||
|
end
|
||||||
|
|
||||||
|
def update(%User{} = user, scheduled_activity_id, attrs) do
|
||||||
|
with %ScheduledActivity{} = scheduled_activity <- get(user, scheduled_activity_id) do
|
||||||
|
scheduled_activity
|
||||||
|
|> update_changeset(attrs)
|
||||||
|
|> Repo.update()
|
||||||
|
else
|
||||||
|
nil -> {:error, :not_found}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete(%User{} = user, scheduled_activity_id) do
|
||||||
|
with %ScheduledActivity{} = scheduled_activity <- get(user, scheduled_activity_id) do
|
||||||
|
scheduled_activity
|
||||||
|
|> Repo.delete()
|
||||||
|
else
|
||||||
|
nil -> {:error, :not_found}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def for_user_query(%User{} = user) do
|
||||||
|
ScheduledActivity
|
||||||
|
|> where(user_id: ^user.id)
|
||||||
|
end
|
||||||
|
end
|
|
@ -5,6 +5,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPI do
|
||||||
alias Pleroma.Activity
|
alias Pleroma.Activity
|
||||||
alias Pleroma.Notification
|
alias Pleroma.Notification
|
||||||
alias Pleroma.Pagination
|
alias Pleroma.Pagination
|
||||||
|
alias Pleroma.ScheduledActivity
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
|
||||||
def get_followers(user, params \\ %{}) do
|
def get_followers(user, params \\ %{}) do
|
||||||
|
@ -28,6 +29,12 @@ def get_notifications(user, params \\ %{}) do
|
||||||
|> Pagination.fetch_paginated(params)
|
|> Pagination.fetch_paginated(params)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get_scheduled_activities(user, params \\ %{}) do
|
||||||
|
user
|
||||||
|
|> ScheduledActivity.for_user_query()
|
||||||
|
|> Pagination.fetch_paginated(params)
|
||||||
|
end
|
||||||
|
|
||||||
defp cast_params(params) do
|
defp cast_params(params) do
|
||||||
param_types = %{
|
param_types = %{
|
||||||
exclude_types: {:array, :string}
|
exclude_types: {:array, :string}
|
||||||
|
|
|
@ -11,6 +11,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
||||||
alias Pleroma.Notification
|
alias Pleroma.Notification
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
|
alias Pleroma.ScheduledActivity
|
||||||
alias Pleroma.Stats
|
alias Pleroma.Stats
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web
|
alias Pleroma.Web
|
||||||
|
@ -25,6 +26,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
|
||||||
alias Pleroma.Web.MastodonAPI.MastodonView
|
alias Pleroma.Web.MastodonAPI.MastodonView
|
||||||
alias Pleroma.Web.MastodonAPI.NotificationView
|
alias Pleroma.Web.MastodonAPI.NotificationView
|
||||||
alias Pleroma.Web.MastodonAPI.ReportView
|
alias Pleroma.Web.MastodonAPI.ReportView
|
||||||
|
alias Pleroma.Web.MastodonAPI.ScheduledActivityView
|
||||||
alias Pleroma.Web.MastodonAPI.StatusView
|
alias Pleroma.Web.MastodonAPI.StatusView
|
||||||
alias Pleroma.Web.MediaProxy
|
alias Pleroma.Web.MediaProxy
|
||||||
alias Pleroma.Web.OAuth.App
|
alias Pleroma.Web.OAuth.App
|
||||||
|
@ -364,6 +366,45 @@ def get_context(%{assigns: %{user: user}} = conn, %{"id" => id}) do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def scheduled_statuses(%{assigns: %{user: user}} = conn, params) do
|
||||||
|
with scheduled_activities <- MastodonAPI.get_scheduled_activities(user, params) do
|
||||||
|
conn
|
||||||
|
|> add_link_headers(:scheduled_statuses, scheduled_activities)
|
||||||
|
|> put_view(ScheduledActivityView)
|
||||||
|
|> render("index.json", %{scheduled_activities: scheduled_activities})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def show_scheduled_status(%{assigns: %{user: user}} = conn, %{"id" => scheduled_activity_id}) do
|
||||||
|
with %ScheduledActivity{} = scheduled_activity <-
|
||||||
|
ScheduledActivity.get(user, scheduled_activity_id) do
|
||||||
|
conn
|
||||||
|
|> put_view(ScheduledActivityView)
|
||||||
|
|> render("show.json", %{scheduled_activity: scheduled_activity})
|
||||||
|
else
|
||||||
|
_ -> {:error, :not_found}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_scheduled_status(
|
||||||
|
%{assigns: %{user: user}} = conn,
|
||||||
|
%{"id" => scheduled_activity_id} = params
|
||||||
|
) do
|
||||||
|
with {:ok, scheduled_activity} <-
|
||||||
|
ScheduledActivity.update(user, scheduled_activity_id, params) do
|
||||||
|
conn
|
||||||
|
|> put_view(ScheduledActivityView)
|
||||||
|
|> render("show.json", %{scheduled_activity: scheduled_activity})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete_scheduled_status(%{assigns: %{user: user}} = conn, %{"id" => scheduled_activity_id}) do
|
||||||
|
with {:ok, %ScheduledActivity{}} <- ScheduledActivity.delete(user, scheduled_activity_id) do
|
||||||
|
conn
|
||||||
|
|> json(%{})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def post_status(conn, %{"status" => "", "media_ids" => media_ids} = params)
|
def post_status(conn, %{"status" => "", "media_ids" => media_ids} = params)
|
||||||
when length(media_ids) > 0 do
|
when length(media_ids) > 0 do
|
||||||
params =
|
params =
|
||||||
|
@ -1406,6 +1447,12 @@ def delete_filter(%{assigns: %{user: user}} = conn, %{"id" => filter_id}) do
|
||||||
|
|
||||||
# fallback action
|
# fallback action
|
||||||
#
|
#
|
||||||
|
def errors(conn, {:error, :not_found}) do
|
||||||
|
conn
|
||||||
|
|> put_status(404)
|
||||||
|
|> json(%{error: "Record not found"})
|
||||||
|
end
|
||||||
|
|
||||||
def errors(conn, _) do
|
def errors(conn, _) do
|
||||||
conn
|
conn
|
||||||
|> put_status(500)
|
|> put_status(500)
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.MastodonAPI.ScheduledActivityView do
|
||||||
|
use Pleroma.Web, :view
|
||||||
|
|
||||||
|
alias Pleroma.ScheduledActivity
|
||||||
|
alias Pleroma.Web.CommonAPI
|
||||||
|
alias Pleroma.Web.MastodonAPI.ScheduledActivityView
|
||||||
|
|
||||||
|
def render("index.json", %{scheduled_activities: scheduled_activities}) do
|
||||||
|
render_many(scheduled_activities, ScheduledActivityView, "show.json")
|
||||||
|
end
|
||||||
|
|
||||||
|
def render("show.json", %{scheduled_activity: %ScheduledActivity{} = scheduled_activity}) do
|
||||||
|
%{
|
||||||
|
id: scheduled_activity.id |> to_string,
|
||||||
|
scheduled_at: scheduled_activity.scheduled_at |> CommonAPI.Utils.to_masto_date(),
|
||||||
|
params: scheduled_activity.params
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
|
@ -244,6 +244,9 @@ defmodule Pleroma.Web.Router do
|
||||||
get("/notifications", MastodonAPIController, :notifications)
|
get("/notifications", MastodonAPIController, :notifications)
|
||||||
get("/notifications/:id", MastodonAPIController, :get_notification)
|
get("/notifications/:id", MastodonAPIController, :get_notification)
|
||||||
|
|
||||||
|
get("/scheduled_statuses", MastodonAPIController, :scheduled_statuses)
|
||||||
|
get("/scheduled_statuses/:id", MastodonAPIController, :show_scheduled_status)
|
||||||
|
|
||||||
get("/lists", MastodonAPIController, :get_lists)
|
get("/lists", MastodonAPIController, :get_lists)
|
||||||
get("/lists/:id", MastodonAPIController, :get_list)
|
get("/lists/:id", MastodonAPIController, :get_list)
|
||||||
get("/lists/:id/accounts", MastodonAPIController, :list_accounts)
|
get("/lists/:id/accounts", MastodonAPIController, :list_accounts)
|
||||||
|
@ -278,6 +281,9 @@ defmodule Pleroma.Web.Router do
|
||||||
post("/statuses/:id/mute", MastodonAPIController, :mute_conversation)
|
post("/statuses/:id/mute", MastodonAPIController, :mute_conversation)
|
||||||
post("/statuses/:id/unmute", MastodonAPIController, :unmute_conversation)
|
post("/statuses/:id/unmute", MastodonAPIController, :unmute_conversation)
|
||||||
|
|
||||||
|
put("/scheduled_statuses/:id", MastodonAPIController, :update_scheduled_status)
|
||||||
|
delete("/scheduled_statuses/:id", MastodonAPIController, :delete_scheduled_status)
|
||||||
|
|
||||||
post("/media", MastodonAPIController, :upload)
|
post("/media", MastodonAPIController, :upload)
|
||||||
put("/media/:id", MastodonAPIController, :update_media)
|
put("/media/:id", MastodonAPIController, :update_media)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
defmodule Pleroma.Repo.Migrations.CreateScheduledActivities do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
create table(:scheduled_activities) do
|
||||||
|
add(:user_id, references(:users, type: :uuid, on_delete: :delete_all))
|
||||||
|
add(:scheduled_at, :naive_datetime, null: false)
|
||||||
|
add(:params, :map, null: false)
|
||||||
|
|
||||||
|
timestamps()
|
||||||
|
end
|
||||||
|
|
||||||
|
create(index(:scheduled_activities, [:scheduled_at]))
|
||||||
|
end
|
||||||
|
end
|
|
@ -23,6 +23,14 @@ def user_factory do
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def scheduled_activity_factory do
|
||||||
|
%Pleroma.ScheduledActivity{
|
||||||
|
user: build(:user),
|
||||||
|
scheduled_at: NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(60), :millisecond),
|
||||||
|
params: build(:note) |> Map.from_struct() |> Map.get(:data)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
def note_factory(attrs \\ %{}) do
|
def note_factory(attrs \\ %{}) do
|
||||||
text = sequence(:text, &"This is :moominmamma: note #{&1}")
|
text = sequence(:text, &"This is :moominmamma: note #{&1}")
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
|
||||||
alias Pleroma.Notification
|
alias Pleroma.Notification
|
||||||
alias Pleroma.Object
|
alias Pleroma.Object
|
||||||
alias Pleroma.Repo
|
alias Pleroma.Repo
|
||||||
|
alias Pleroma.ScheduledActivity
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
alias Pleroma.Web.CommonAPI
|
alias Pleroma.Web.CommonAPI
|
||||||
|
@ -2407,4 +2408,107 @@ test "redirects to the getting-started page when referer is not present", %{conn
|
||||||
assert redirected_to(conn) == "/web/getting-started"
|
assert redirected_to(conn) == "/web/getting-started"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "scheduled activities" do
|
||||||
|
test "shows scheduled activities", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
scheduled_activity_id1 = insert(:scheduled_activity, user: user).id |> to_string()
|
||||||
|
scheduled_activity_id2 = insert(:scheduled_activity, user: user).id |> to_string()
|
||||||
|
scheduled_activity_id3 = insert(:scheduled_activity, user: user).id |> to_string()
|
||||||
|
scheduled_activity_id4 = insert(:scheduled_activity, user: user).id |> to_string()
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|
||||||
|
# min_id
|
||||||
|
conn_res =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/scheduled_statuses?limit=2&min_id=#{scheduled_activity_id1}")
|
||||||
|
|
||||||
|
result = json_response(conn_res, 200)
|
||||||
|
assert [%{"id" => ^scheduled_activity_id3}, %{"id" => ^scheduled_activity_id2}] = result
|
||||||
|
|
||||||
|
# since_id
|
||||||
|
conn_res =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/scheduled_statuses?limit=2&since_id=#{scheduled_activity_id1}")
|
||||||
|
|
||||||
|
result = json_response(conn_res, 200)
|
||||||
|
assert [%{"id" => ^scheduled_activity_id4}, %{"id" => ^scheduled_activity_id3}] = result
|
||||||
|
|
||||||
|
# max_id
|
||||||
|
conn_res =
|
||||||
|
conn
|
||||||
|
|> get("/api/v1/scheduled_statuses?limit=2&max_id=#{scheduled_activity_id4}")
|
||||||
|
|
||||||
|
result = json_response(conn_res, 200)
|
||||||
|
assert [%{"id" => ^scheduled_activity_id3}, %{"id" => ^scheduled_activity_id2}] = result
|
||||||
|
end
|
||||||
|
|
||||||
|
test "shows a scheduled activity", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
scheduled_activity = insert(:scheduled_activity, user: user)
|
||||||
|
|
||||||
|
res_conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
|
||||||
|
|
||||||
|
assert %{"id" => scheduled_activity_id} = json_response(res_conn, 200)
|
||||||
|
assert scheduled_activity_id == scheduled_activity.id |> to_string()
|
||||||
|
|
||||||
|
res_conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/api/v1/scheduled_statuses/404")
|
||||||
|
|
||||||
|
assert %{"error" => "Record not found"} = json_response(res_conn, 404)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "updates a scheduled activity", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
scheduled_activity = insert(:scheduled_activity, user: user)
|
||||||
|
|
||||||
|
new_scheduled_at =
|
||||||
|
NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
|
||||||
|
|
||||||
|
res_conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> put("/api/v1/scheduled_statuses/#{scheduled_activity.id}", %{
|
||||||
|
scheduled_at: new_scheduled_at
|
||||||
|
})
|
||||||
|
|
||||||
|
assert %{"scheduled_at" => expected_scheduled_at} = json_response(res_conn, 200)
|
||||||
|
assert expected_scheduled_at == Pleroma.Web.CommonAPI.Utils.to_masto_date(new_scheduled_at)
|
||||||
|
|
||||||
|
res_conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> put("/api/v1/scheduled_statuses/404", %{scheduled_at: new_scheduled_at})
|
||||||
|
|
||||||
|
assert %{"error" => "Record not found"} = json_response(res_conn, 404)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "deletes a scheduled activity", %{conn: conn} do
|
||||||
|
user = insert(:user)
|
||||||
|
scheduled_activity = insert(:scheduled_activity, user: user)
|
||||||
|
|
||||||
|
res_conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> delete("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
|
||||||
|
|
||||||
|
assert %{} = json_response(res_conn, 200)
|
||||||
|
assert nil == Repo.get(ScheduledActivity, scheduled_activity.id)
|
||||||
|
|
||||||
|
res_conn =
|
||||||
|
conn
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> delete("/api/v1/scheduled_statuses/#{scheduled_activity.id}")
|
||||||
|
|
||||||
|
assert %{"error" => "Record not found"} = json_response(res_conn, 404)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue