151 lines
4.1 KiB
Ruby
151 lines
4.1 KiB
Ruby
# typed: strict
|
|
# frozen_string_literal: true
|
|
#
|
|
class Bluesky::ProcessPostHelper
|
|
extend T::Sig
|
|
include HasColorLogger
|
|
IMAGE_OR_VIDEO =
|
|
T.let(%w[app.bsky.embed.images app.bsky.embed.video], T::Array[String])
|
|
|
|
sig { params(deferred_job_sink: DeferredJobSink).void }
|
|
def initialize(deferred_job_sink)
|
|
@deferred_job_sink = deferred_job_sink
|
|
end
|
|
|
|
sig { params(did: String, cid: String).returns(String) }
|
|
def self.construct_blob_url(did, cid)
|
|
"https://bsky.social/xrpc/com.atproto.sync.getBlob?did=#{did}&cid=#{cid}"
|
|
end
|
|
|
|
sig { params(embed_data: T::Hash[String, T.untyped]).returns(T::Boolean) }
|
|
def should_process_post?(embed_data)
|
|
type = embed_data["$type"]
|
|
if IMAGE_OR_VIDEO.include?(type)
|
|
true
|
|
elsif type == "app.bsky.embed.recordWithMedia"
|
|
embed_type = embed_data.dig("media", "$type")
|
|
IMAGE_OR_VIDEO.include?(embed_type)
|
|
else
|
|
false
|
|
end
|
|
end
|
|
|
|
sig do
|
|
params(
|
|
post: Domain::Post::BlueskyPost,
|
|
embed_data: T::Hash[String, T.untyped],
|
|
did: String,
|
|
).void
|
|
end
|
|
def process_post_media(post, embed_data, did)
|
|
case embed_data["$type"]
|
|
when "app.bsky.embed.images"
|
|
process_post_images(post, embed_data, did)
|
|
when "app.bsky.embed.video"
|
|
process_post_video(post, embed_data, did)
|
|
when "app.bsky.embed.recordWithMedia"
|
|
embed_type = embed_data.dig("media", "$type")
|
|
if embed_type == "app.bsky.embed.images"
|
|
process_post_images(post, embed_data["media"], did)
|
|
elsif embed_type == "app.bsky.embed.video"
|
|
process_post_video(post, embed_data["media"], did)
|
|
end
|
|
end
|
|
end
|
|
|
|
sig do
|
|
params(
|
|
post: Domain::Post::BlueskyPost,
|
|
embed_data: T::Hash[String, T.untyped],
|
|
did: String,
|
|
).void
|
|
end
|
|
def process_post_images(post, embed_data, did)
|
|
images = embed_data.dig("images") || []
|
|
images.each_with_index do |image_data, index|
|
|
post_file = post.files.build(file_order: index)
|
|
set_blob_ref_and_url(post_file, image_data["image"], did)
|
|
set_aspect_ratio(post_file, image_data["aspectRatio"])
|
|
set_alt_text(post_file, image_data["alt"])
|
|
|
|
post_file.save!
|
|
@deferred_job_sink.defer_job(
|
|
Domain::StaticFileJob,
|
|
{ post_file: },
|
|
{ queue: "bluesky" },
|
|
)
|
|
|
|
logger.debug(
|
|
format_tags(
|
|
"created image for post",
|
|
make_tags(at_uri: post.at_uri, post_file_id: post_file.id),
|
|
),
|
|
)
|
|
end
|
|
end
|
|
|
|
sig do
|
|
params(
|
|
post: Domain::Post::BlueskyPost,
|
|
embed_data: T::Hash[String, T.untyped],
|
|
did: String,
|
|
).void
|
|
end
|
|
def process_post_video(post, embed_data, did)
|
|
post_file = post.files.build(file_order: 0)
|
|
set_blob_ref_and_url(post_file, embed_data["video"], did)
|
|
set_aspect_ratio(post_file, embed_data["aspectRatio"])
|
|
set_alt_text(post_file, embed_data["alt"])
|
|
post_file.save!
|
|
@deferred_job_sink.defer_job(
|
|
Domain::StaticFileJob,
|
|
{ post_file: },
|
|
{ queue: "bluesky" },
|
|
)
|
|
|
|
logger.debug(
|
|
format_tags(
|
|
"created video for post",
|
|
make_tags(at_uri: post.at_uri, post_file_id: post_file.id),
|
|
),
|
|
)
|
|
end
|
|
|
|
sig do
|
|
params(
|
|
post_file: Domain::PostFile::BlueskyPostFile,
|
|
file_data: T::Hash[String, T.untyped],
|
|
did: String,
|
|
).void
|
|
end
|
|
def set_blob_ref_and_url(post_file, file_data, did)
|
|
return unless file_data.dig("$type") == "blob"
|
|
blob_ref = file_data.dig("ref", "$link")
|
|
return unless blob_ref
|
|
post_file.blob_ref = blob_ref
|
|
post_file.url_str = self.class.construct_blob_url(did, blob_ref)
|
|
end
|
|
|
|
sig do
|
|
params(
|
|
post_file: Domain::PostFile::BlueskyPostFile,
|
|
aspect_ratio: T.nilable(T::Hash[String, T.untyped]),
|
|
).void
|
|
end
|
|
def set_aspect_ratio(post_file, aspect_ratio)
|
|
return unless aspect_ratio
|
|
post_file.aspect_ratio_width = aspect_ratio.dig("width")
|
|
post_file.aspect_ratio_height = aspect_ratio.dig("height")
|
|
end
|
|
|
|
sig do
|
|
params(
|
|
post_file: Domain::PostFile::BlueskyPostFile,
|
|
alt_text: T.nilable(String),
|
|
).void
|
|
end
|
|
def set_alt_text(post_file, alt_text)
|
|
post_file.alt_text = alt_text if alt_text
|
|
end
|
|
end
|