implement almost everything
commit
7d0a809bd6
|
@ -0,0 +1,3 @@
|
|||
/target
|
||||
.DS_Store
|
||||
mastodon-data.toml
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "tootre"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
clap = "2.33.3"
|
||||
elefren = { version = "0.22.0", features = ["toml"] }
|
||||
home = "0.5.3"
|
||||
regex = "1.5.4"
|
|
@ -0,0 +1,174 @@
|
|||
use std::error::Error;
|
||||
|
||||
use elefren::entities::status::Status;
|
||||
use elefren::helpers::cli;
|
||||
use elefren::helpers::toml;
|
||||
use elefren::prelude::*;
|
||||
|
||||
use clap::{App, Arg};
|
||||
use regex::Regex;
|
||||
|
||||
// TODO Put data.toml file path in an env var
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let matches = App::new("tootre")
|
||||
.version("0.1")
|
||||
.author("annieversary")
|
||||
.about("grep through own toots")
|
||||
.arg(
|
||||
Arg::with_name("regex")
|
||||
.short("r")
|
||||
.long("regex")
|
||||
.value_name("REGEX")
|
||||
.required(true)
|
||||
.help("Regex to use for matching toots"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("max")
|
||||
.short("m")
|
||||
.long("max")
|
||||
.value_name("MAX")
|
||||
.help("Max number of toots to find"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("boosts")
|
||||
.short("b")
|
||||
.long("boosts")
|
||||
.help("Includes boosts in the search"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("v")
|
||||
.short("v")
|
||||
.long("verbose")
|
||||
.help("Sets the level of verbosity"),
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
let max = matches
|
||||
.value_of("max")
|
||||
.map(|val| val.parse::<usize>().ok())
|
||||
.flatten();
|
||||
let verbose = matches.is_present("v");
|
||||
let include_retoots = matches.is_present("boosts");
|
||||
|
||||
if let Some(regex) = matches.value_of("regex") {
|
||||
run(regex, max, verbose, include_retoots)
|
||||
} else {
|
||||
panic!("Regex was not provided");
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns path for config
|
||||
fn get_path() -> std::path::PathBuf {
|
||||
if let Some(mut home) = home::home_dir() {
|
||||
home.push(".tootre.toml");
|
||||
home
|
||||
} else {
|
||||
".tootre.toml".into()
|
||||
}
|
||||
}
|
||||
|
||||
fn run(
|
||||
regex: &str,
|
||||
max_statuses: Option<usize>,
|
||||
verbose: bool,
|
||||
include_retoots: bool,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
let client = if let Ok(data) = toml::from_file(get_path()) {
|
||||
Mastodon::from(data)
|
||||
} else {
|
||||
register()?
|
||||
};
|
||||
|
||||
if verbose {
|
||||
println!("Getting statuses...");
|
||||
}
|
||||
|
||||
// Get statuses for own account
|
||||
let acc = client.verify_credentials()?;
|
||||
let statuses = client.statuses(&acc.id, None)?;
|
||||
|
||||
let regex = Regex::new(regex).unwrap();
|
||||
let mut results = Vec::new();
|
||||
|
||||
if verbose {
|
||||
println!("Searching...");
|
||||
}
|
||||
|
||||
// Search through statuses
|
||||
for status in statuses.items_iter() {
|
||||
// Add it to results if it matches and it isn't a retoot
|
||||
// or if it matches and isn't a retoot
|
||||
if status_matches(&status, ®ex) && (include_retoots || status.reblog.is_none()) {
|
||||
results.push(status);
|
||||
}
|
||||
|
||||
// If there's a limit of results, check it and exit
|
||||
if let Some(max) = max_statuses {
|
||||
if results.len() >= max {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("\n\nResults:\n");
|
||||
|
||||
// Print results
|
||||
for status in &results {
|
||||
if !status.spoiler_text.is_empty() {
|
||||
println!("CW: {}", status.spoiler_text);
|
||||
}
|
||||
println!("Content: {}", status.content);
|
||||
// Print actual url if it's a retoot
|
||||
if let Some(retoot) = &status.reblog {
|
||||
if let Some(url) = &retoot.url {
|
||||
println!("Url: {}", url);
|
||||
}
|
||||
} else if let Some(url) = &status.url {
|
||||
println!("Url: {}", url);
|
||||
}
|
||||
|
||||
// Print some extra info
|
||||
if verbose {
|
||||
println!("Created at: {}", status.created_at);
|
||||
if let Some(retoot) = &status.reblog {
|
||||
println!("Is retoot: yes ({})", retoot.account.acct);
|
||||
} else {
|
||||
// We don't want to print these if it's a retoot
|
||||
println!("Favs: {}", status.favourites_count);
|
||||
println!("Retoots: {}", status.reblogs_count);
|
||||
}
|
||||
}
|
||||
|
||||
println!();
|
||||
}
|
||||
|
||||
println!("Found {} results", results.len());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn status_matches(status: &Status, regex: &Regex) -> bool {
|
||||
regex.is_match(&status.content) || regex.is_match(&status.spoiler_text)
|
||||
}
|
||||
|
||||
fn register() -> Result<Mastodon, Box<dyn Error>> {
|
||||
println!("You are not registered, registering...");
|
||||
let url = read_line("Enter instance url (eg: https://mastodon.social):")?;
|
||||
let registration = Registration::new(url).client_name("tootre").build()?;
|
||||
let mastodon = cli::authenticate(registration)?;
|
||||
|
||||
// Save app data for using on the next run.
|
||||
toml::to_file(&mastodon, get_path())?;
|
||||
|
||||
Ok(mastodon)
|
||||
}
|
||||
|
||||
pub fn read_line(message: &str) -> Result<String, Box<dyn Error>> {
|
||||
println!("{}", message);
|
||||
|
||||
let mut input = String::new();
|
||||
std::io::stdin().read_line(&mut input)?;
|
||||
|
||||
Ok(input.trim().to_string())
|
||||
}
|
Loading…
Reference in New Issue