mirror of
https://framagit.org/veretcle/oolatoocs.git
synced 2025-07-20 12:31:18 +02:00
feat: threads
This commit is contained in:
13
src/lib.rs
13
src/lib.rs
@@ -44,6 +44,7 @@ pub async fn run(config: &Config) {
|
||||
|
||||
// if we wanted to cut toot in half, now would be the right time to do so
|
||||
|
||||
// treats media
|
||||
for media in toot.media_attachments {
|
||||
let id = match media.r#type {
|
||||
AttachmentType::Image => {
|
||||
@@ -77,12 +78,20 @@ pub async fn run(config: &Config) {
|
||||
medias.push(id);
|
||||
}
|
||||
|
||||
println!("{:?}", medias);
|
||||
// threads if necessary
|
||||
let reply_to = toot.in_reply_to_id.and_then(|t| {
|
||||
read_state(&conn, Some(t.parse::<u64>().unwrap()))
|
||||
.ok()
|
||||
.flatten()
|
||||
.map(|s| s.tweet_id)
|
||||
});
|
||||
|
||||
let tweet_id = post_tweet(&config.twitter, &tweet_content, &medias)
|
||||
// posts corresponding tweet
|
||||
let tweet_id = post_tweet(&config.twitter, &tweet_content, &medias, &reply_to)
|
||||
.await
|
||||
.unwrap_or_else(|e| panic!("Cannot Tweet {}: {}", toot.id, e));
|
||||
|
||||
// writes the current state of the tweet
|
||||
write_state(
|
||||
&conn,
|
||||
TweetToToot {
|
||||
|
@@ -7,7 +7,7 @@ use reqwest::{
|
||||
Body, Client,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::error::Error;
|
||||
use std::{error::Error, ops::Not};
|
||||
use tokio::time::{sleep, Duration};
|
||||
|
||||
const TWITTER_API_TWEET_URL: &str = "https://api.twitter.com/2/tweets";
|
||||
@@ -20,24 +20,32 @@ const TWITTER_METADATA_MEDIA_URL: &str =
|
||||
struct EmptyRequest {}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct Tweet {
|
||||
pub text: String,
|
||||
pub media: TweetMediasIds,
|
||||
struct Tweet {
|
||||
text: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
media: Option<TweetMediasIds>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
reply: Option<TweetReply>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct TweetMediasIds {
|
||||
pub media_ids: Vec<String>,
|
||||
struct TweetMediasIds {
|
||||
media_ids: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
struct TweetReply {
|
||||
in_reply_to_tweet_id: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct TweetResponse {
|
||||
pub data: TweetResponseData,
|
||||
struct TweetResponse {
|
||||
data: TweetResponseData,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct TweetResponseData {
|
||||
pub id: String,
|
||||
struct TweetResponseData {
|
||||
id: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
@@ -112,7 +120,7 @@ pub async fn upload_simple_media(
|
||||
|
||||
// upload the media
|
||||
let client = Client::new();
|
||||
let res: UploadMediaResponse = client
|
||||
let res = client
|
||||
.post(TWITTER_UPLOAD_MEDIA_URL)
|
||||
.header(
|
||||
"Authorization",
|
||||
@@ -129,7 +137,7 @@ pub async fn upload_simple_media(
|
||||
))
|
||||
.send()
|
||||
.await?
|
||||
.json()
|
||||
.json::<UploadMediaResponse>()
|
||||
.await?;
|
||||
|
||||
debug!("Media ID: {}", res.media_id);
|
||||
@@ -201,7 +209,7 @@ pub async fn upload_chunk_media(
|
||||
debug!("Init the slot for uploading media: {}", u);
|
||||
// init the slot for uploading
|
||||
let client = Client::new();
|
||||
let orig_media_id: UploadMediaResponse = client
|
||||
let orig_media_id = client
|
||||
.post(TWITTER_UPLOAD_MEDIA_URL)
|
||||
.header(
|
||||
"Authorization",
|
||||
@@ -221,7 +229,7 @@ pub async fn upload_chunk_media(
|
||||
)
|
||||
.send()
|
||||
.await?
|
||||
.json()
|
||||
.json::<UploadMediaResponse>()
|
||||
.await?;
|
||||
|
||||
debug!("Slot initiated with ID: {}", orig_media_id.media_id);
|
||||
@@ -267,7 +275,7 @@ pub async fn upload_chunk_media(
|
||||
|
||||
debug!("Finalize media ID: {}", orig_media_id.media_id);
|
||||
// Finalizing task
|
||||
let fin: UploadMediaResponse = client
|
||||
let fin = client
|
||||
.post(TWITTER_UPLOAD_MEDIA_URL)
|
||||
.header(
|
||||
"Authorization",
|
||||
@@ -285,7 +293,7 @@ pub async fn upload_chunk_media(
|
||||
)
|
||||
.send()
|
||||
.await?
|
||||
.json()
|
||||
.json::<UploadMediaResponse>()
|
||||
.await?;
|
||||
|
||||
if let Some(p_info) = fin.processing_info {
|
||||
@@ -310,7 +318,7 @@ pub async fn upload_chunk_media(
|
||||
orig_media_id.media_id, wait_sec
|
||||
);
|
||||
|
||||
let status: UploadMediaResponse = client
|
||||
let status = client
|
||||
.get(TWITTER_UPLOAD_MEDIA_URL)
|
||||
.header(
|
||||
"Authorization",
|
||||
@@ -324,7 +332,7 @@ pub async fn upload_chunk_media(
|
||||
.query(&command)
|
||||
.send()
|
||||
.await?
|
||||
.json()
|
||||
.json::<UploadMediaResponse>()
|
||||
.await?;
|
||||
|
||||
let p_status = status.processing_info.unwrap(); // shouldn’t be None at this point
|
||||
@@ -347,7 +355,8 @@ pub async fn upload_chunk_media(
|
||||
"Processing still pending, waiting {} secs more…",
|
||||
p_status.check_after_secs.unwrap() // unwrap is safe here,
|
||||
// check_after_secs is only present
|
||||
// when status is pending
|
||||
// when status is pending or in
|
||||
// progress
|
||||
);
|
||||
sleep(Duration::from_secs(p_status.check_after_secs.unwrap())).await;
|
||||
continue;
|
||||
@@ -365,15 +374,19 @@ pub async fn post_tweet(
|
||||
config: &TwitterConfig,
|
||||
content: &str,
|
||||
medias: &[u64],
|
||||
reply_to: &Option<u64>,
|
||||
) -> Result<u64, Box<dyn Error>> {
|
||||
let empty_request = EmptyRequest {}; // Why? Because fuck you, that’s why!
|
||||
let token = get_token(config);
|
||||
|
||||
let tweet = Tweet {
|
||||
text: content.to_string(),
|
||||
media: TweetMediasIds {
|
||||
media: medias.is_empty().not().then(|| TweetMediasIds {
|
||||
media_ids: medias.iter().map(|m| m.to_string()).collect(),
|
||||
},
|
||||
}),
|
||||
reply: reply_to.map(|s| TweetReply {
|
||||
in_reply_to_tweet_id: s.to_string(),
|
||||
}),
|
||||
};
|
||||
|
||||
let client = Client::new();
|
||||
|
Reference in New Issue
Block a user