mirror of
https://framagit.org/veretcle/oolatoocs.git
synced 2025-07-20 20:41:17 +02:00
123 lines
3.6 KiB
Rust
123 lines
3.6 KiB
Rust
use crate::config::MastodonConfig;
|
||
use chrono::{DateTime, Utc};
|
||
use megalodon::{
|
||
entities::{Status, StatusVisibility},
|
||
generator,
|
||
mastodon::mastodon::Mastodon,
|
||
megalodon::AppInputOptions,
|
||
megalodon::GetHomeTimelineInputOptions,
|
||
Megalodon,
|
||
};
|
||
use std::error::Error;
|
||
use std::io::stdin;
|
||
|
||
/// Get Mastodon Object instance
|
||
pub fn get_mastodon_instance(config: &MastodonConfig) -> Result<Mastodon, Box<dyn Error>> {
|
||
Ok(Mastodon::new(
|
||
config.base.to_string(),
|
||
Some(config.token.to_string()),
|
||
None,
|
||
)?)
|
||
}
|
||
|
||
/// Get the edited_at field from the specified toot
|
||
pub async fn get_status_edited_at(mastodon: &Mastodon, t: u64) -> Option<DateTime<Utc>> {
|
||
mastodon
|
||
.get_status(t.to_string())
|
||
.await
|
||
.ok()
|
||
.and_then(|t| t.json.edited_at)
|
||
}
|
||
|
||
/// Get the home timeline since the last toot
|
||
pub async fn get_mastodon_timeline_since(
|
||
mastodon: &Mastodon,
|
||
id: Option<u64>,
|
||
) -> Result<Vec<Status>, Box<dyn Error>> {
|
||
let input_options = GetHomeTimelineInputOptions {
|
||
only_media: Some(false),
|
||
limit: None,
|
||
max_id: None,
|
||
since_id: id.map(|i| i.to_string()),
|
||
min_id: None,
|
||
local: Some(true),
|
||
};
|
||
|
||
let mut timeline: Vec<Status> = mastodon
|
||
.get_home_timeline(Some(&input_options))
|
||
.await?
|
||
.json()
|
||
.iter()
|
||
.filter(|t| {
|
||
// this excludes the reply to other users
|
||
t.in_reply_to_account_id.is_none()
|
||
|| t.in_reply_to_account_id
|
||
.clone()
|
||
.is_some_and(|r| r == t.account.id)
|
||
})
|
||
.filter(|t| t.visibility == StatusVisibility::Public) // excludes everything that isn’t
|
||
// public
|
||
.filter(|t| t.reblog.is_none()) // excludes reblogs
|
||
.cloned()
|
||
.collect();
|
||
|
||
timeline.reverse();
|
||
|
||
Ok(timeline)
|
||
}
|
||
|
||
/// Generic register function
|
||
/// As this function is supposed to be run only once, it will panic for every error it encounters
|
||
/// Most of this function is a direct copy/paste of the official `elefren` crate
|
||
#[tokio::main]
|
||
pub async fn register(host: &str) {
|
||
let mastodon = generator(megalodon::SNS::Mastodon, host.to_string(), None, None)
|
||
.expect("Cannot build Mastodon generator object");
|
||
|
||
let options = AppInputOptions {
|
||
redirect_uris: None,
|
||
scopes: Some(["read:statuses".to_string()].to_vec()),
|
||
website: Some("https://framagit.org/veretcle/oolatoocs".to_string()),
|
||
};
|
||
|
||
let app_data = mastodon
|
||
.register_app(env!("CARGO_PKG_NAME").to_string(), &options)
|
||
.await
|
||
.expect("Cannot build registration object!");
|
||
|
||
let url = app_data.url.expect("Cannot generate registration URI!");
|
||
|
||
println!("Click this link to authorize on Mastodon: {url}");
|
||
println!("Paste the returned authorization code: ");
|
||
|
||
let mut input = String::new();
|
||
stdin()
|
||
.read_line(&mut input)
|
||
.expect("Unable to read back registration code!");
|
||
|
||
let token_data = mastodon
|
||
.fetch_access_token(
|
||
app_data.client_id.to_owned(),
|
||
app_data.client_secret.to_owned(),
|
||
input.trim().to_string(),
|
||
megalodon::default::NO_REDIRECT.to_string(),
|
||
)
|
||
.await
|
||
.expect("Unable to create access token!");
|
||
|
||
println!(
|
||
r#"Please insert the following block at the end of your configuration file:
|
||
[mastodon]
|
||
base = "{}"
|
||
client_id = "{}"
|
||
client_secret = "{}"
|
||
redirect = "{}"
|
||
token = "{}""#,
|
||
host,
|
||
app_data.client_id,
|
||
app_data.client_secret,
|
||
app_data.redirect_uri.as_ref().unwrap(),
|
||
token_data.access_token,
|
||
);
|
||
}
|