implement posts with images
This commit is contained in:
parent
0997ab8c20
commit
97cdfbb7ef
3 changed files with 51 additions and 5 deletions
|
@ -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()
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) => {
|
||||
|
|
Loading…
Reference in a new issue