initial commit

This commit is contained in:
Marc Planard 2023-11-30 21:03:52 +01:00
commit bd92493910
3 changed files with 2274 additions and 0 deletions

2129
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

14
Cargo.toml Normal file
View File

@ -0,0 +1,14 @@
[package]
name = "mastui"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
chrono = "0.4.31"
env_logger = "0.10.1"
megalodon = "0.11.6"
scraper = "0.18.1"
serde_json = "1.0.108"
tokio = "1.34.0"

131
src/main.rs Normal file
View File

@ -0,0 +1,131 @@
use megalodon::{generator, streaming::Message};
use std::env;
use scraper::{Html,Selector};
use megalodon::entities::Status;
use megalodon::entities::notification::NotificationType;
#[tokio::main]
async fn main() {
env_logger::init();
let url = env::var("MASTODON_STREAMING_URL").unwrap_or_else(|_| {
String::from("https://mamot.fr/")
});
let Ok(token) = env::var("MASTODON_ACCESS_TOKEN") else {
println!("Specify MASTODON_ACCESS_TOKEN!!");
return
};
let client = megalodon::generator(
megalodon::SNS::Mastodon,
url.clone(),
Some(token.clone()),
None,
);
let res = client.verify_account_credentials().await.unwrap();
println!("Creds: {:#?}", res.json());
let res = client.get_instance().await.unwrap();
//println!("Instance: {:#?}", res.json());
let mut res2 = client.get_home_timeline(None).await.unwrap().json();
res2.reverse();
for status in &res2 {
print_status(status);
}
let url_ws = res.json().urls.unwrap().streaming_api;
streaming(url_ws.as_str(), token).await;
}
fn print_status(status: &Status) {
let now = chrono::offset::Utc::now();
let date_diff = duration_to_string(&(now - status.created_at));
if let Some(retoot) = &status.reblog {
println!("From: {}, {date_diff} ago [retoot by: {}]",
retoot.account.acct,
status.account.acct);
print_content(&retoot.content);
} else {
println!("From: {}, {date_diff} ago", status.account.acct);
print_content(&status.content);
}
println!();
}
fn duration_to_string(d: &chrono::Duration) -> String {
match d.num_seconds() {
s if s < 60 => format!("{} secs.", s),
s if s < 60*60 => format!("{} mins.", s/60),
s if s < 60*60*24 => format!("{} hours.", s/(60*60)),
s => format!("{}days", s/(60*60*24))
}
}
fn print_content(content: &str) {
let fragment = Html::parse_fragment(content);
let sel = Selector::parse("p").unwrap();
if let Some(p) = fragment.select(&sel).next() {
let text = p.text().collect::<Vec<_>>();
let text2 = text.join(" ");
println!("Content: {}", text2);
} else {
println!("Content: {:?}", content);
}
}
async fn streaming(url: &str, access_token: String) {
let client = generator(
megalodon::SNS::Mastodon,
url.to_string(),
Some(access_token),
None,
);
let streaming = client.user_streaming(url.to_string());
streaming
.listen(Box::new(|message| match message {
Message::Update(status) => print_status(&status),
Message::Notification(mes) => {
let from = mes.account.map(| u | u.acct)
.unwrap_or_else(|| String::from("(unknown)"));
match mes.r#type {
NotificationType::Favourite => {
println!("*** {from} favorited one of your toots.");
},
NotificationType::Reblog => {
println!("*** {from} boosted one of your toots.");
},
NotificationType::Follow => {
println!("*** {from} follows you.");
},
NotificationType::FollowRequest => {
println!("*** {from} sent you a follow request.");
},
_ => {
println!("Notification: {:?}", mes.r#type);
}
}
},
Message::Conversation(mes) => {
println!("Conversation: {:#?}", mes);
}
Message::Delete(mes) => {
println!("message is deleted: {}", mes);
}
Message::StatusUpdate(mes) => {
println!("updated: {:#?}", mes)
}
Message::Heartbeat() => {
//println!("heartbeat");
}
}))
.await;
}