implement posts with images

This commit is contained in:
Denis-Cosmin NUTIU 2024-12-31 12:11:46 +02:00
parent 0997ab8c20
commit 97cdfbb7ef
3 changed files with 51 additions and 5 deletions

View file

@ -3,9 +3,9 @@ mod token;
use crate::bluesky::atproto::{ATProtoServerCreateSession, BlobResponse};
use anyhow::anyhow;
use base64::prelude::BASE64_STANDARD;
use base64::Engine;
use reqwest::Body;
use std::io::Write;
use token::Token;
/// The BlueSky client used to interact with the platform.
@ -85,17 +85,28 @@ impl BlueSkyClient {
}
/// Uploads an image.
async fn upload_image(&mut self, payload: Vec<u8>) -> Result<BlobResponse, anyhow::Error> {
let base64_data = BASE64_STANDARD.encode(payload);
pub async fn upload_image_by_url(
&mut self,
image_url: &str,
) -> Result<BlobResponse, anyhow::Error> {
let data: Vec<u8> = self
.client
.get(image_url)
.send()
.await?
.bytes()
.await?
.to_vec();
Ok(self
.client
.post("https://bsky.social/xrpc/com.atproto.repo.uploadBlob")
.header("Content-Type", "image/png")
.header("Content-Type", "image/jpeg")
.header(
"Authorization",
format!("Bearer {}", self.auth_token.access_jwt),
)
.body(base64_data)
.body(data)
.send()
.await?
.json()

View file

@ -20,6 +20,7 @@ pub struct Blob {
}
impl Blob {
#![allow(dead_code)]
pub fn new(link: &str, mime_type: &str, size: i64) -> Self {
Blob {
_type: "blob".to_string(),
@ -235,4 +236,18 @@ mod tests {
Ok(())
}
#[test]
fn test_blob_new_serialization() -> Result<(), anyhow::Error> {
let blob = Blob::new("asa", "image/jpeg", 1);
let json = serde_json::to_string(&blob)?;
assert_eq!(
json,
r#"{"$type":"blob","ref":{"$link":"asa"},"mimeType":"image/jpeg","size":1}"#
);
Ok(())
}
}

View file

@ -32,6 +32,18 @@ fn setup_graceful_shutdown(running: &Arc<AtomicBool>) {
});
}
/// Embeds an image to a post.
async fn add_image_to_post(
client: &mut BlueSkyClient,
image_url: &str,
record: &mut bluesky::atproto::ATProtoRepoCreateRecord,
) -> Result<(), anyhow::Error> {
let thumb = client.upload_image_by_url(image_url).await?;
record.record.embed.as_mut().unwrap().external.thumb = Some(thumb.blob);
Ok(())
}
#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
env_logger::init();
@ -70,6 +82,14 @@ async fn main() -> Result<(), anyhow::Error> {
Ok(post) => {
let mut data: bluesky::atproto::ATProtoRepoCreateRecord = post.clone().into();
data.repo = args.bluesky_handle.clone();
if let Some(image_link) = post.image.clone() {
let result =
add_image_to_post(&mut bluesky_client, &image_link, &mut data).await;
if let Err(err) = result {
warn!("Failed to upload image: {err}")
}
}
let json = serde_json::to_string(&data);
match json {
Ok(json) => {