chore: refactor sydication

This commit is contained in:
sloane 2025-05-04 15:32:17 -04:00
parent fce42316e8
commit bec40bed01
Signed by: sloanelybutsurely
SSH key fingerprint: SHA256:8SBnwhl+RY3oEyQxy1a9wByPzxWM0x+/Ejc+sIlY5qQ
7 changed files with 155 additions and 40 deletions

View file

@ -1,10 +1,22 @@
defmodule Core.Posts do
@moduledoc false
alias Core.Syndication
alias Core.Posts.Post
def get!(id) do
Core.Repo.get!(Schema.Post, id)
Post.Query.base()
|> Core.Repo.get!(id)
end
def get(id) do
Post.Query.base()
|> Core.Repo.get(id)
end
def get_published_post(id) do
Post.Query.published()
|> Core.Repo.get(id)
end
def get_published_blog!(%Date{} = publish_date, slug) when is_binary(slug) do
@ -70,29 +82,28 @@ defmodule Core.Posts do
attrs
|> change_post()
|> Core.Repo.insert()
|> do_syndication()
end
def update_post(%Schema.Post{} = post, attrs) do
post
|> change_post(attrs)
|> Core.Repo.update()
|> do_syndication()
end
def create_or_update_post(%Schema.Post{} = post, attrs) do
post
|> change_post(attrs)
|> Core.Repo.insert_or_update()
|> do_syndication()
end
def publish_post(%Schema.Post{} = post, published_at \\ DateTime.utc_now()) do
with {:ok, post} <-
post
|> Post.publish_changeset(published_at)
|> Core.Repo.update(),
{:ok, post} <- Core.Syndication.syndicate_to_mastodon(post),
{:ok, post} <- Core.Syndication.syndicate_to_bluesky(post) do
{:ok, post}
end
post
|> Post.publish_changeset(published_at)
|> Core.Repo.update()
|> do_syndication()
end
def delete_post(%Schema.Post{} = post, deleted_at \\ DateTime.utc_now()) do
@ -105,11 +116,29 @@ defmodule Core.Posts do
post
|> Post.unpublish_changeset()
|> Core.Repo.update()
|> do_syndication()
end
def undelete_post(%Schema.Post{} = post) do
post
|> Post.undelete_changeset()
|> Core.Repo.update()
|> do_syndication()
end
defp do_syndication(%Schema.Post{} = post) do
%{"post_id" => post.id}
|> Syndication.SyndicatePostWorker.new()
|> Oban.insert()
post
end
defp do_syndication({:ok, %Schema.Post{} = post}) do
do_syndication(post)
{:ok, post}
end
defp do_syndication(other), do: other
end

View file

@ -20,25 +20,19 @@ defmodule Core.Syndication do
end
def syndicate_to_mastodon(%Schema.Post{} = post) do
post = Core.Repo.preload(post, [:mastodon_post])
conn = build_mastodon_client_conn()
if post.syndicate_to_mastodon and is_nil(post.mastodon_post) do
conn = build_mastodon_client_conn()
{:ok, resp} = MastodonClient.post(conn, "/api/v1/statuses", %{status: post.body})
{:ok, resp} = MastodonClient.post(conn, "/api/v1/statuses", %{status: post.body})
post
|> Ecto.build_assoc(:mastodon_post)
|> Syndication.MastodonPost.changeset(%{
status_id: resp.body["id"],
url: resp.body["url"]
})
|> Core.Repo.insert()
post
|> Ecto.build_assoc(:mastodon_post)
|> Syndication.MastodonPost.changeset(%{
status_id: resp.body["id"],
url: resp.body["url"]
})
|> Core.Repo.insert()
{:ok, post}
else
{:ok, post}
end
{:ok, post}
end
defp get_mastodon_access_token! do
@ -94,20 +88,14 @@ defmodule Core.Syndication do
end
def syndicate_to_bluesky(%Schema.Post{} = post) do
post = Core.Repo.preload(post, [:bluesky_post])
{:ok, bluesky_account} = get_bluesky_account!() |> refresh_bluesky_account()
if post.syndicate_to_bluesky && is_nil(post.bluesky_post) do
{:ok, bluesky_account} = get_bluesky_account!() |> refresh_bluesky_account()
with {:ok, resp} <- Syndication.BlueskyClient.post_status(bluesky_account, post.body) do
post
|> Ecto.build_assoc(:bluesky_post)
|> Syndication.BlueskyPost.changeset(resp.body)
|> Core.Repo.insert()
with {:ok, resp} <- Syndication.BlueskyClient.post_status(bluesky_account, post.body) do
post
|> Ecto.build_assoc(:bluesky_post)
|> Syndication.BlueskyPost.changeset(resp.body)
|> Core.Repo.insert()
{:ok, post}
end
else
{:ok, post}
end
end

View file

@ -1,5 +1,5 @@
defmodule Core.Syndication.BlueskyRefreshWorker do
use Oban.Worker
use Oban.Worker, unique: true, replace: [scheduled: [:scheduled_at]]
@impl true
def perform(%Oban.Job{args: %{"bluesky_account_id" => id}}) do

View file

@ -0,0 +1,36 @@
defmodule Core.Syndication.SyndicatePostWorker do
use Oban.Worker, unique: true
alias Core.Posts
alias Core.Syndication.SyndicateToBlueskyWorker
alias Core.Syndication.SyndicateToMastodonWorker
def perform(%Oban.Job{args: %{"post_id" => post_id}}) do
with {:ok, %Schema.Post{} = post} <- get_post(post_id) do
syndicate_worker_args = %{"post_id" => post_id}
subjobs =
[
if(post.syndicate_to_bluesky, do: SyndicateToBlueskyWorker.new(syndicate_worker_args)),
if(post.syndicate_to_mastodon, do: SyndicateToMastodonWorker.new(syndicate_worker_args))
]
|> Enum.reject(&is_nil/1)
|> Oban.insert_all()
case subjobs do
[] -> {:cancel, "post not set to syndicate"}
_ -> :ok
end
end
end
defp get_post(post_id) do
case Posts.get_published_post(post_id) do
%Schema.Post{} = post ->
{:ok, post}
_ ->
{:cancel, "post does not exist or is not published"}
end
end
end

View file

@ -0,0 +1,34 @@
defmodule Core.Syndication.SyndicateToBlueskyWorker do
alias Core.Syndication
use Oban.Worker, unique: true
alias Core.Posts
def perform(%Oban.Job{args: %{"post_id" => post_id}}) do
with {:ok, post} <- get_post(post_id),
{:ok, _bluesky_post} <- Syndication.syndicate_to_bluesky(post) do
:ok
end
end
defp get_post(post_id) do
case Posts.get_published_post(post_id) do
%Schema.Post{} = post ->
post = Core.Repo.preload(post, [:bluesky_post])
cond do
not post.syndicate_to_bluesky ->
{:cancel, "post is not marked for syndication to bluesky"}
not is_nil(post.bluesky_post) ->
{:cancel, "post already syndicated to bluesky"}
true ->
{:ok, post}
end
_ ->
{:cancel, "post does not exist or is not published"}
end
end
end

View file

@ -0,0 +1,28 @@
defmodule Core.Syndication.SyndicateToMastodonWorker do
alias Core.Syndication
use Oban.Worker, unique: true
alias Core.Posts
alias Core.Syndication
def perform(%Oban.Job{args: %{"post_id" => post_id}}) do
with {:ok, post} <- get_post(post_id),
{:ok, _mastodon_post} <- Syndication.syndicate_to_mastodon(post) do
:ok
end
end
defp get_post(post_id) do
case Posts.get(post_id) do
%Schema.Post{} = post ->
cond do
not post.syndicate_to_mastodon -> {:cancel, "post not set to syndicate to mastodon"}
not is_nil(post.mastodon_post) -> {:cancel, "post already syndicated to mastodon"}
true -> {:ok, post}
end
_ ->
{:cancel, "post not found"}
end
end
end

View file

@ -28,8 +28,8 @@ defmodule Schema.Post do
field :published_at, :utc_datetime_usec
field :deleted_at, :utc_datetime_usec
field :syndicate_to_mastodon, :boolean
field :syndicate_to_bluesky, :boolean
field :syndicate_to_mastodon, :boolean, default: true
field :syndicate_to_bluesky, :boolean, default: true
has_one :mastodon_post, Schema.MastodonPost
has_one :bluesky_post, Schema.BlueskyPost