Browse Source

fix for scheduled post with poll

youtube-fix
Alexander Strizhakov 3 years ago
parent
commit
0dc68c157f
No known key found for this signature in database GPG Key ID: 22896A53AEF1381
6 changed files with 119 additions and 61 deletions
  1. +1
    -0
      CHANGELOG.md
  2. +32
    -28
      lib/pleroma/web/api_spec/operations/status_operation.ex
  3. +2
    -2
      lib/pleroma/web/api_spec/schemas/scheduled_status.ex
  4. +33
    -21
      lib/pleroma/workers/scheduled_activity_worker.ex
  5. +39
    -1
      test/pleroma/web/mastodon_api/controllers/status_controller_test.exs
  6. +12
    -9
      test/pleroma/workers/scheduled_activity_worker_test.exs

+ 1
- 0
CHANGELOG.md View File

@@ -65,6 +65,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Mastodon API: Fixed last_status.account being not filled with account data.
- Mastodon API: Fix not being able to add or remove multiple users at once in lists.
- Mastodon API: Fixed own_votes being not returned with poll data.
- Mastodon API: Fixed creation of scheduled posts with polls.
</details>

## Unreleased (Patch)


+ 32
- 28
lib/pleroma/web/api_spec/operations/status_operation.ex View File

@@ -413,34 +413,7 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
items: %Schema{type: :string},
description: "Array of Attachment ids to be attached as media."
},
poll: %Schema{
nullable: true,
type: :object,
required: [:options],
properties: %{
options: %Schema{
type: :array,
items: %Schema{type: :string},
description: "Array of possible answers. Must be provided with `poll[expires_in]`."
},
expires_in: %Schema{
type: :integer,
nullable: true,
description:
"Duration the poll should be open, in seconds. Must be provided with `poll[options]`"
},
multiple: %Schema{
allOf: [BooleanLike],
nullable: true,
description: "Allow multiple choices?"
},
hide_totals: %Schema{
allOf: [BooleanLike],
nullable: true,
description: "Hide vote counts until the poll ends?"
}
}
},
poll: poll_params(),
in_reply_to_id: %Schema{
nullable: true,
allOf: [FlakeID],
@@ -522,6 +495,37 @@ defmodule Pleroma.Web.ApiSpec.StatusOperation do
}
end

def poll_params do
%Schema{
nullable: true,
type: :object,
required: [:options, :expires_in],
properties: %{
options: %Schema{
type: :array,
items: %Schema{type: :string},
description: "Array of possible answers. Must be provided with `poll[expires_in]`."
},
expires_in: %Schema{
type: :integer,
nullable: true,
description:
"Duration the poll should be open, in seconds. Must be provided with `poll[options]`"
},
multiple: %Schema{
allOf: [BooleanLike],
nullable: true,
description: "Allow multiple choices?"
},
hide_totals: %Schema{
allOf: [BooleanLike],
nullable: true,
description: "Hide vote counts until the poll ends?"
}
}
}
end

def id_param do
Operation.parameter(:id, :path, FlakeID, "Status ID",
example: "9umDrYheeY451cQnEe",


+ 2
- 2
lib/pleroma/web/api_spec/schemas/scheduled_status.ex View File

@@ -5,8 +5,8 @@
defmodule Pleroma.Web.ApiSpec.Schemas.ScheduledStatus do
alias OpenApiSpex.Schema
alias Pleroma.Web.ApiSpec.Schemas.Attachment
alias Pleroma.Web.ApiSpec.Schemas.Poll
alias Pleroma.Web.ApiSpec.Schemas.VisibilityScope
alias Pleroma.Web.ApiSpec.StatusOperation

require OpenApiSpex

@@ -29,7 +29,7 @@ defmodule Pleroma.Web.ApiSpec.Schemas.ScheduledStatus do
spoiler_text: %Schema{type: :string, nullable: true},
visibility: %Schema{allOf: [VisibilityScope], nullable: true},
scheduled_at: %Schema{type: :string, format: :"date-time", nullable: true},
poll: %Schema{allOf: [Poll], nullable: true},
poll: StatusOperation.poll_params(),
in_reply_to_id: %Schema{type: :string, nullable: true}
}
}


+ 33
- 21
lib/pleroma/workers/scheduled_activity_worker.ex View File

@@ -9,38 +9,50 @@ defmodule Pleroma.Workers.ScheduledActivityWorker do

use Pleroma.Workers.WorkerHelper, queue: "scheduled_activities"

alias Pleroma.Config
alias Pleroma.Repo
alias Pleroma.ScheduledActivity
alias Pleroma.User
alias Pleroma.Web.CommonAPI

require Logger

@impl Oban.Worker
def perform(%Job{args: %{"activity_id" => activity_id}}) do
if Config.get([ScheduledActivity, :enabled]) do
case Pleroma.Repo.get(ScheduledActivity, activity_id) do
%ScheduledActivity{} = scheduled_activity ->
post_activity(scheduled_activity)

_ ->
Logger.error("#{__MODULE__} Couldn't find scheduled activity: #{activity_id}")
end
with %ScheduledActivity{} = scheduled_activity <- find_scheduled_activity(activity_id),
%User{} = user <- find_user(scheduled_activity.user_id) do
params = atomize_keys(scheduled_activity.params)

Repo.transaction(fn ->
{:ok, activity} = Pleroma.Web.CommonAPI.post(user, params)
{:ok, _} = ScheduledActivity.delete(scheduled_activity)
activity
end)
else
{:error, :scheduled_activity_not_found} = error ->
Logger.error("#{__MODULE__} Couldn't find scheduled activity: #{activity_id}")
error

{:error, :user_not_found} = error ->
Logger.error("#{__MODULE__} Couldn't find user for scheduled activity: #{activity_id}")
error
end
end

defp post_activity(%ScheduledActivity{user_id: user_id, params: params} = scheduled_activity) do
params = Map.new(params, fn {key, value} -> {String.to_existing_atom(key), value} end)
defp find_scheduled_activity(id) do
with nil <- Repo.get(ScheduledActivity, id) do
{:error, :scheduled_activity_not_found}
end
end

with {:delete, {:ok, _}} <- {:delete, ScheduledActivity.delete(scheduled_activity)},
{:user, %User{} = user} <- {:user, User.get_cached_by_id(user_id)},
{:post, {:ok, _}} <- {:post, CommonAPI.post(user, params)} do
:ok
else
error ->
Logger.error(
"#{__MODULE__} Couldn't create a status from the scheduled activity: #{inspect(error)}"
)
defp find_user(id) do
with nil <- User.get_cached_by_id(id) do
{:error, :user_not_found}
end
end

defp atomize_keys(map) do
Map.new(map, fn
{key, value} when is_map(value) -> {String.to_existing_atom(key), atomize_keys(value)}
{key, value} -> {String.to_existing_atom(key), value}
end)
end
end

+ 39
- 1
test/pleroma/web/mastodon_api/controllers/status_controller_test.exs View File

@@ -515,7 +515,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
end)

assert NaiveDateTime.diff(NaiveDateTime.from_iso8601!(response["poll"]["expires_at"]), time) in 420..430
refute response["poll"]["expred"]
assert response["poll"]["expired"] == false

question = Object.get_by_id(response["poll"]["id"])

@@ -591,6 +591,44 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
%{"error" => error} = json_response_and_validate_schema(conn, 422)
assert error == "Expiration date is too far in the future"
end

test "scheduled poll", %{conn: conn} do
clear_config([ScheduledActivity, :enabled], true)

scheduled_at =
NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(6), :millisecond)
|> NaiveDateTime.to_iso8601()
|> Kernel.<>("Z")

%{"id" => scheduled_id} =
conn
|> put_req_header("content-type", "application/json")
|> post("/api/v1/statuses", %{
"status" => "very cool poll",
"poll" => %{
"options" => ~w(a b c),
"expires_in" => 420
},
"scheduled_at" => scheduled_at
})
|> json_response_and_validate_schema(200)

assert {:ok, %{id: activity_id}} =
perform_job(Pleroma.Workers.ScheduledActivityWorker, %{
activity_id: scheduled_id
})

assert Repo.all(Oban.Job) == []

object =
Activity
|> Repo.get(activity_id)
|> Object.normalize()

assert object.data["content"] == "very cool poll"
assert object.data["type"] == "Question"
assert length(object.data["oneOf"]) == 3
end
end

test "get a status" do


+ 12
- 9
test/pleroma/workers/scheduled_activity_worker_test.exs View File

@@ -11,10 +11,9 @@ defmodule Pleroma.Workers.ScheduledActivityWorkerTest do
import Pleroma.Factory
import ExUnit.CaptureLog

setup do: clear_config([ScheduledActivity, :enabled])
setup do: clear_config([ScheduledActivity, :enabled], true)

test "creates a status from the scheduled activity" do
clear_config([ScheduledActivity, :enabled], true)
user = insert(:user)

naive_datetime =
@@ -32,18 +31,22 @@ defmodule Pleroma.Workers.ScheduledActivityWorkerTest do
params: %{status: "hi"}
)

ScheduledActivityWorker.perform(%Oban.Job{args: %{"activity_id" => scheduled_activity.id}})
{:ok, %{id: activity_id}} =
ScheduledActivityWorker.perform(%Oban.Job{args: %{"activity_id" => scheduled_activity.id}})

refute Repo.get(ScheduledActivity, scheduled_activity.id)
activity = Repo.all(Pleroma.Activity) |> Enum.find(&(&1.actor == user.ap_id))
assert Pleroma.Object.normalize(activity, fetch: false).data["content"] == "hi"
end

test "adds log message if ScheduledActivity isn't find" do
clear_config([ScheduledActivity, :enabled], true)
object =
Pleroma.Activity
|> Repo.get(activity_id)
|> Pleroma.Object.normalize()

assert object.data["content"] == "hi"
end

test "error message for non-existent scheduled activity" do
assert capture_log([level: :error], fn ->
ScheduledActivityWorker.perform(%Oban.Job{args: %{"activity_id" => 42}})
end) =~ "Couldn't find scheduled activity"
end) =~ "Couldn't find scheduled activity: 42"
end
end

Loading…
Cancel
Save