forked from xenua/fedi-frq-friend
xenua
2 years ago
commit
0de46b3ce3
5 changed files with 2013 additions and 0 deletions
@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
|
||||
/target |
||||
fedi-data.toml |
||||
config.kdl |
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
[package] |
||||
name = "fedi-frq-friend" |
||||
version = "0.1.0" |
||||
edition = "2021" |
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html |
||||
|
||||
[dependencies] |
||||
futures-util = "0.3.28" |
||||
knuffel = "3.0.0" |
||||
mastodon-async = { version = "1.2.1", features = ["toml", "mt"] } |
||||
tokio = { version = "1.27.0", features = ["full"] } |
||||
|
||||
|
||||
[[bin]] |
||||
name = "f3" |
||||
path = "src/main.rs" |
@ -0,0 +1,2 @@
@@ -0,0 +1,2 @@
|
||||
status-text "this is the automated follow request message from fedi-frq-friend. i haven't set the message in the config yet!" |
||||
with-cw "automated follow request pm" // optional |
@ -0,0 +1,110 @@
@@ -0,0 +1,110 @@
|
||||
use futures_util::TryStreamExt; |
||||
use mastodon_async::entities::notification::NotificationType; |
||||
use mastodon_async::helpers::cli::authenticate; |
||||
use mastodon_async::helpers::toml; |
||||
use mastodon_async::prelude::*; |
||||
use mastodon_async::Result as MResult; |
||||
|
||||
use std::fs::File; |
||||
use std::io::{self, Write}; |
||||
|
||||
const DEFAULT_CONFIG: &'static str = include_str!("default_config.kdl"); |
||||
|
||||
#[derive(knuffel::Decode, Debug, Clone)] |
||||
struct Config { |
||||
#[knuffel(child, unwrap(argument))] |
||||
status_text: String, |
||||
#[knuffel(child, unwrap(argument))] |
||||
with_cw: Option<String>, |
||||
} |
||||
|
||||
async fn get_mastodon() -> MResult<Mastodon> { |
||||
if let Ok(data) = toml::from_file("fedi-data.toml") { |
||||
Ok(Mastodon::from(data)) |
||||
} else { |
||||
log_in().await |
||||
} |
||||
} |
||||
|
||||
async fn log_in() -> MResult<Mastodon> { |
||||
println!("fedi-data.toml is missing, doing initial setup:"); |
||||
print!("Enter your instance url (e.g. botsin.space): "); |
||||
io::stdout().flush()?; |
||||
|
||||
let mut instance = String::new(); |
||||
io::stdin().read_line(&mut instance)?; |
||||
|
||||
if !(instance.starts_with("http://") || instance.starts_with("https://")) { |
||||
instance = format!("https://{instance}"); |
||||
} |
||||
|
||||
let registration = Registration::new(instance.trim()) |
||||
.client_name("frq-friend") |
||||
.scopes(Scopes::all()) |
||||
.build() |
||||
.await?; |
||||
let mastodon = authenticate(registration).await?; |
||||
|
||||
toml::to_file(&mastodon.data, "fedi-data.toml")?; |
||||
|
||||
Ok(mastodon) |
||||
} |
||||
|
||||
async fn do_the_thing() -> MResult<()> { |
||||
let config_string = std::fs::read_to_string("config.kdl").unwrap_or_else(|_| { |
||||
File::create("config.kdl") |
||||
.and_then(|mut v| v.write_all(DEFAULT_CONFIG.as_bytes())) |
||||
.expect("Unable to write default to config.kdl; is the working dir writable?"); |
||||
println!("created example config.kdl. you probably want to change the text in there"); |
||||
DEFAULT_CONFIG.to_string() |
||||
}); |
||||
let config: Config = |
||||
knuffel::parse("config.kdl", &config_string).expect("Error parsing config.kdl"); |
||||
|
||||
let mastodon = get_mastodon().await?; |
||||
let stream = mastodon.stream_notifications().await?; |
||||
println!("listening for events\n--------------------"); |
||||
stream |
||||
.try_for_each(|(event, client)| { |
||||
let cfg = config.clone(); |
||||
async move { |
||||
match event { |
||||
Event::Notification { |
||||
0: |
||||
Notification { |
||||
notification_type: NotificationType::FollowRequest, |
||||
account, |
||||
.. |
||||
}, |
||||
} => { |
||||
println!( |
||||
"got a follow request from {} (@{})", |
||||
account.display_name, account.acct |
||||
); |
||||
|
||||
let mut builder = StatusBuilder::new(); |
||||
builder |
||||
.status(format!("@{}\n{}", account.acct, cfg.status_text)) |
||||
.visibility(Visibility::Direct); |
||||
|
||||
if let Some(cw) = cfg.with_cw { |
||||
builder.sensitive(true).spoiler_text(cw); |
||||
} |
||||
|
||||
let status = builder.build()?; |
||||
|
||||
client.new_status(status).await?; |
||||
} |
||||
_ => (), |
||||
} |
||||
Ok(()) |
||||
} |
||||
}) |
||||
.await?; |
||||
Ok(()) |
||||
} |
||||
|
||||
#[tokio::main] |
||||
async fn main() -> MResult<()> { |
||||
do_the_thing().await |
||||
} |
Loading…
Reference in new issue