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