mirror of
https://framagit.org/veretcle/oolatoocs.git
synced 2025-12-06 06:43:15 +01:00
♻️: better handle of quotes and media embedded into quotes
This commit is contained in:
60
src/bsky.rs
60
src/bsky.rs
@@ -1,4 +1,4 @@
|
||||
use crate::config::BlueskyConfig;
|
||||
use crate::{config::BlueskyConfig, OolatoocsError};
|
||||
use atrium_api::{
|
||||
app::bsky::feed::post::RecordData, com::atproto::repo::upload_blob::Output,
|
||||
types::string::Datetime, types::string::Language, types::string::RecordKey,
|
||||
@@ -148,18 +148,16 @@ async fn get_record(
|
||||
Ok(record)
|
||||
}
|
||||
|
||||
/// Generate an quote embed record into Bsky
|
||||
/// Generate an quote embed record
|
||||
/// it is encapsulated in Option to prevent this function from failing
|
||||
pub async fn generate_quote_records(
|
||||
config: &BlueskyConfig,
|
||||
quote_id: &str,
|
||||
) -> Option<atrium_api::types::Union<atrium_api::app::bsky::feed::post::RecordEmbedRefs>> {
|
||||
) -> Result<atrium_api::app::bsky::feed::post::RecordEmbedRefs, Box<dyn Error>> {
|
||||
// if we can’t match the quote_id, simply return None
|
||||
let quote_record = match get_record(&config.handle, &rkey(quote_id)).await {
|
||||
Ok(a) => a,
|
||||
Err(_) => return None,
|
||||
};
|
||||
let quote_record = get_record(&config.handle, &rkey(quote_id)).await?;
|
||||
|
||||
Some(atrium_api::types::Union::Refs(
|
||||
Ok(
|
||||
atrium_api::app::bsky::feed::post::RecordEmbedRefs::AppBskyEmbedRecordMain(Box::new(
|
||||
atrium_api::app::bsky::embed::record::MainData {
|
||||
record: atrium_api::com::atproto::repo::strong_ref::MainData {
|
||||
@@ -170,24 +168,18 @@ pub async fn generate_quote_records(
|
||||
}
|
||||
.into(),
|
||||
)),
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
/// Generate an embed card record into Bsky
|
||||
/// Generate an embed webcard record into Bsky
|
||||
/// If the preview image does not exist or fails to upload, it is simply ignored
|
||||
pub async fn generate_embed_records(
|
||||
pub async fn generate_webcard_records(
|
||||
bsky: &BskyAgent,
|
||||
card: &Card,
|
||||
) -> Option<atrium_api::types::Union<atrium_api::app::bsky::feed::post::RecordEmbedRefs>> {
|
||||
// uploads the image card, if it fails, simply ignore everything
|
||||
let blob = if let Some(url) = &card.image {
|
||||
if let Ok(image_blob) = upload_media(true, bsky, url).await {
|
||||
Some(image_blob.blob.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
) -> Result<atrium_api::app::bsky::feed::post::RecordEmbedRefs, Box<dyn Error + Send + Sync>> {
|
||||
let blob = match &card.image {
|
||||
Some(url) => upload_media(true, bsky, url).await?.blob.clone().into(),
|
||||
None => None,
|
||||
};
|
||||
|
||||
let record_card = atrium_api::app::bsky::embed::external::ExternalData {
|
||||
@@ -197,14 +189,14 @@ pub async fn generate_embed_records(
|
||||
uri: card.url.clone(),
|
||||
};
|
||||
|
||||
Some(atrium_api::types::Union::Refs(
|
||||
Ok(
|
||||
atrium_api::app::bsky::feed::post::RecordEmbedRefs::AppBskyEmbedExternalMain(Box::new(
|
||||
atrium_api::app::bsky::embed::external::MainData {
|
||||
external: record_card.into(),
|
||||
}
|
||||
.into(),
|
||||
)),
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
/// Generate an array of Bsky media records
|
||||
@@ -213,11 +205,7 @@ pub async fn generate_embed_records(
|
||||
pub async fn generate_media_records(
|
||||
bsky: &BskyAgent,
|
||||
media_attach: &[Attachment],
|
||||
) -> Option<atrium_api::types::Union<atrium_api::app::bsky::feed::post::RecordEmbedRefs>> {
|
||||
let mut embed: Option<
|
||||
atrium_api::types::Union<atrium_api::app::bsky::feed::post::RecordEmbedRefs>,
|
||||
> = None;
|
||||
|
||||
) -> Result<atrium_api::app::bsky::feed::post::RecordEmbedRefs, Box<dyn Error + Send + Sync>> {
|
||||
let image_media_attach: Vec<_> = media_attach
|
||||
.iter()
|
||||
.filter(|x| x.r#type == AttachmentType::Image)
|
||||
@@ -233,9 +221,9 @@ pub async fn generate_media_records(
|
||||
if !video_media_attach.is_empty() {
|
||||
// treat only the very first video, ignore the rest
|
||||
let media = &video_media_attach[0];
|
||||
let blob = upload_media(false, bsky, &media.url).await.unwrap();
|
||||
let blob = upload_media(false, bsky, &media.url).await?;
|
||||
|
||||
embed = Some(atrium_api::types::Union::Refs(
|
||||
return Ok(
|
||||
atrium_api::app::bsky::feed::post::RecordEmbedRefs::AppBskyEmbedVideoMain(Box::new(
|
||||
atrium_api::app::bsky::embed::video::MainData {
|
||||
alt: media.description.clone(),
|
||||
@@ -245,12 +233,10 @@ pub async fn generate_media_records(
|
||||
}
|
||||
.into(),
|
||||
)),
|
||||
));
|
||||
|
||||
// returns immediately, we don’t want to treat the other medias
|
||||
return embed;
|
||||
);
|
||||
}
|
||||
|
||||
// It wasn’t a video, then it’s an image or a gallery of 4 images
|
||||
let mut stream = stream::iter(image_media_attach)
|
||||
.map(|media| {
|
||||
let bsky = bsky.clone();
|
||||
@@ -281,14 +267,14 @@ pub async fn generate_media_records(
|
||||
}
|
||||
|
||||
if !images.is_empty() {
|
||||
embed = Some(atrium_api::types::Union::Refs(
|
||||
return Ok(
|
||||
atrium_api::app::bsky::feed::post::RecordEmbedRefs::AppBskyEmbedImagesMain(Box::new(
|
||||
atrium_api::app::bsky::embed::images::MainData { images }.into(),
|
||||
)),
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
embed
|
||||
Err(OolatoocsError::new("Cannot embed media").into())
|
||||
}
|
||||
|
||||
async fn upload_media(
|
||||
|
||||
76
src/lib.rs
76
src/lib.rs
@@ -19,7 +19,7 @@ use utils::{generate_multi_tweets, strip_everything};
|
||||
|
||||
mod bsky;
|
||||
use bsky::{
|
||||
build_post_record, generate_embed_records, generate_media_records, generate_quote_records,
|
||||
build_post_record, generate_media_records, generate_quote_records, generate_webcard_records,
|
||||
get_session, BskyReply,
|
||||
};
|
||||
|
||||
@@ -161,22 +161,66 @@ pub async fn run(config: &Config) {
|
||||
});
|
||||
};
|
||||
|
||||
// Don’t know how to union things so…
|
||||
// cards have the least priority (you cannot embed card and images anyway)
|
||||
// images have a higher priority
|
||||
// quotes have the highest priority
|
||||
|
||||
let record_embed = if toot.reblog.is_some() {
|
||||
let quote_record =
|
||||
read_state(&conn, Some(toot.reblog.unwrap().id.parse::<u64>().unwrap()));
|
||||
match quote_record {
|
||||
Ok(Some(q)) => generate_quote_records(&config.bluesky, &q.record_uri).await,
|
||||
_ => None,
|
||||
// handle quote if any
|
||||
let quote_embed = match toot.reblog {
|
||||
Some(r) => {
|
||||
let quote_record = read_state(&conn, Some(r.id.parse::<u64>().unwrap()));
|
||||
match quote_record {
|
||||
Ok(Some(q)) => generate_quote_records(&config.bluesky, &q.record_uri)
|
||||
.await
|
||||
.ok(),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
} else if toot.media_attachments.len() > usize::from(0u8) {
|
||||
generate_media_records(&bluesky, &toot.media_attachments).await
|
||||
} else if toot.card.is_some() {
|
||||
generate_embed_records(&bluesky, &toot.card.unwrap()).await
|
||||
None => None,
|
||||
};
|
||||
|
||||
// handle medias if any
|
||||
let media_embed = if toot.media_attachments.len() > usize::from(0u8) {
|
||||
generate_media_records(&bluesky, &toot.media_attachments)
|
||||
.await
|
||||
.ok()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// handle webcard if any
|
||||
let webcard_embed = match toot.card {
|
||||
Some(t) => generate_webcard_records(&bluesky, &t).await.ok(),
|
||||
None => None,
|
||||
};
|
||||
|
||||
let record_embed = if quote_embed.is_some() {
|
||||
if media_embed.is_some() {
|
||||
let medias_mapped = match media_embed.unwrap() {
|
||||
atrium_api::app::bsky::feed::post::RecordEmbedRefs::AppBskyEmbedImagesMain(a) => atrium_api::app::bsky::embed::record_with_media::MainMediaRefs::AppBskyEmbedImagesMain(a),
|
||||
atrium_api::app::bsky::feed::post::RecordEmbedRefs::AppBskyEmbedVideoMain(a) => atrium_api::app::bsky::embed::record_with_media::MainMediaRefs::AppBskyEmbedVideoMain(a),
|
||||
_ => continue, // this should NEVER happen as Media are either Video or
|
||||
// Images at this point
|
||||
};
|
||||
let quote_mapped = match quote_embed.unwrap() {
|
||||
atrium_api::app::bsky::feed::post::RecordEmbedRefs::AppBskyEmbedRecordMain(
|
||||
a,
|
||||
) => a,
|
||||
_ => continue, // again, this should NEVER happen
|
||||
};
|
||||
Some(atrium_api::types::Union::Refs(
|
||||
atrium_api::app::bsky::feed::post::RecordEmbedRefs::AppBskyEmbedRecordWithMediaMain(
|
||||
Box::new(
|
||||
atrium_api::app::bsky::embed::record_with_media::MainData {
|
||||
media: atrium_api::types::Union::Refs(medias_mapped),
|
||||
record: (*quote_mapped),
|
||||
}.into()
|
||||
)
|
||||
)
|
||||
))
|
||||
} else {
|
||||
quote_embed.map(atrium_api::types::Union::Refs)
|
||||
}
|
||||
} else if media_embed.is_some() {
|
||||
media_embed.map(atrium_api::types::Union::Refs)
|
||||
} else if webcard_embed.is_some() {
|
||||
webcard_embed.map(atrium_api::types::Union::Refs)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user