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 crate::bluesky::atproto::{ATProtoServerCreateSession, BlobResponse};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use base64::prelude::BASE64_STANDARD;
|
|
||||||
use base64::Engine;
|
use base64::Engine;
|
||||||
use reqwest::Body;
|
use reqwest::Body;
|
||||||
|
use std::io::Write;
|
||||||
use token::Token;
|
use token::Token;
|
||||||
|
|
||||||
/// The BlueSky client used to interact with the platform.
|
/// The BlueSky client used to interact with the platform.
|
||||||
|
@ -85,17 +85,28 @@ impl BlueSkyClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Uploads an image.
|
/// Uploads an image.
|
||||||
async fn upload_image(&mut self, payload: Vec<u8>) -> Result<BlobResponse, anyhow::Error> {
|
pub async fn upload_image_by_url(
|
||||||
let base64_data = BASE64_STANDARD.encode(payload);
|
&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
|
Ok(self
|
||||||
.client
|
.client
|
||||||
.post("https://bsky.social/xrpc/com.atproto.repo.uploadBlob")
|
.post("https://bsky.social/xrpc/com.atproto.repo.uploadBlob")
|
||||||
.header("Content-Type", "image/png")
|
.header("Content-Type", "image/jpeg")
|
||||||
.header(
|
.header(
|
||||||
"Authorization",
|
"Authorization",
|
||||||
format!("Bearer {}", self.auth_token.access_jwt),
|
format!("Bearer {}", self.auth_token.access_jwt),
|
||||||
)
|
)
|
||||||
.body(base64_data)
|
.body(data)
|
||||||
.send()
|
.send()
|
||||||
.await?
|
.await?
|
||||||
.json()
|
.json()
|
||||||
|
|
|
@ -20,6 +20,7 @@ pub struct Blob {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Blob {
|
impl Blob {
|
||||||
|
#![allow(dead_code)]
|
||||||
pub fn new(link: &str, mime_type: &str, size: i64) -> Self {
|
pub fn new(link: &str, mime_type: &str, size: i64) -> Self {
|
||||||
Blob {
|
Blob {
|
||||||
_type: "blob".to_string(),
|
_type: "blob".to_string(),
|
||||||
|
@ -235,4 +236,18 @@ mod tests {
|
||||||
|
|
||||||
Ok(())
|
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]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), anyhow::Error> {
|
async fn main() -> Result<(), anyhow::Error> {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
|
@ -70,6 +82,14 @@ async fn main() -> Result<(), anyhow::Error> {
|
||||||
Ok(post) => {
|
Ok(post) => {
|
||||||
let mut data: bluesky::atproto::ATProtoRepoCreateRecord = post.clone().into();
|
let mut data: bluesky::atproto::ATProtoRepoCreateRecord = post.clone().into();
|
||||||
data.repo = args.bluesky_handle.clone();
|
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);
|
let json = serde_json::to_string(&data);
|
||||||
match json {
|
match json {
|
||||||
Ok(json) => {
|
Ok(json) => {
|
||||||
|
|
Loading…
Reference in a new issue