Compare commits

2 Commits
Author SHA1 Message Date
pyro b356720e77 added a url option to search for. 2026-09-25 12:16:07 -05:00
pyro 5a37beb434 updated install script to actually work. 2026-09-01 16:35:20 -05:00
3 changed files with 76 additions and 38 deletions

No files matched your search

+1
View File
@@ -7,6 +7,7 @@ edition = "2024"
calamine = "0.36.0" calamine = "0.36.0"
clap = { version = "4.6.1", features = ["derive"] } clap = { version = "4.6.1", features = ["derive"] }
docx-rust = "0.1.11" docx-rust = "0.1.11"
indicatif = "0.18.6"
lopdf = "0.44.0" lopdf = "0.44.0"
rayon = "1.12.0" rayon = "1.12.0"
reqwest = { version = "0.13.3", features = ["blocking"] } reqwest = { version = "0.13.3", features = ["blocking"] }
-10
View File
@@ -3,16 +3,6 @@
echo "compiling ferrisfind..." echo "compiling ferrisfind..."
if cargo build --release; then if cargo build --release; then
echo "ferrisfind compiled successfully!" echo "ferrisfind compiled successfully!"
if ldd ./target/release/ferrisfind | grep libtika | grep "not found"; then
echo "libtika not found in current sytem, copying from the build directory."
echo "this will need sudo privileges..."
if sudo cp ./target/release/build/extractous-*/out/libs/libtika_native.so /usr/lib64/; then
echo "library copied successfully!"
else
echo "error copying libary!"
exit
fi
fi
echo "copying binary to your path..." echo "copying binary to your path..."
echo "this will require sudo privileges" echo "this will require sudo privileges"
if sudo cp ./target/release/ferrisfind /usr/bin; then if sudo cp ./target/release/ferrisfind /usr/bin; then
+75 -28
View File
@@ -1,6 +1,7 @@
use calamine::{Reader, Xlsx}; use calamine::{Reader, Xlsx};
use clap::Parser; use clap::Parser;
use docx_rust::DocxFile; use docx_rust::DocxFile;
use indicatif::ProgressBar;
use lopdf::{Document, Object}; use lopdf::{Document, Object};
use rayon::iter::IntoParallelRefMutIterator; use rayon::iter::IntoParallelRefMutIterator;
use rayon::{ThreadPoolBuilder, iter::ParallelIterator}; use rayon::{ThreadPoolBuilder, iter::ParallelIterator};
@@ -24,7 +25,11 @@ use urlencoding::decode;
struct Args { struct Args {
///company name ///company name
#[arg(short, long)] #[arg(short, long)]
name: String, name: Option<String>,
///url to search files on
#[arg(short, long)]
url: Option<String>,
///serpapi key ///serpapi key
#[arg(short, long)] #[arg(short, long)]
@@ -69,16 +74,13 @@ struct FoundFile {
impl FoundFile { impl FoundFile {
fn download(&mut self) { fn download(&mut self) {
println!("downloading {}...", self.filename);
if let Ok(res) = get(&self.url) { if let Ok(res) = get(&self.url) {
if res.status().is_success() { if res.status().is_success() {
if let Ok(data) = res.bytes() { if let Ok(data) = res.bytes() {
if let Ok(mut local_file) = File::create(&self.filepath) { if let Ok(mut local_file) = File::create(&self.filepath) {
if let Err(e) = local_file.write(&data) { if let Err(e) = local_file.write(&data) {
eprintln!("Error downloading file! {e}");
} else { } else {
self.downloaded = Some(true); self.downloaded = Some(true);
println!("{} Downloaded!", self.filename);
return; return;
} }
} }
@@ -89,7 +91,6 @@ impl FoundFile {
} }
fn parse(&mut self) -> Result<(), Box<dyn Error>> { fn parse(&mut self) -> Result<(), Box<dyn Error>> {
println!("parsing {}", self.filename);
match self.filetype { match self.filetype {
FileType::Pdf => { FileType::Pdf => {
let doc = Document::load(&self.filepath)?; let doc = Document::load(&self.filepath)?;
@@ -109,7 +110,6 @@ impl FoundFile {
FileType::Xlsx => {} FileType::Xlsx => {}
} }
self.parsed = Some(true); self.parsed = Some(true);
println!("{} parsed!", self.filename);
return Ok(()); return Ok(());
} }
} }
@@ -146,48 +146,95 @@ async fn main() {
settings.insert("engine".to_string(), "google".to_string()); settings.insert("engine".to_string(), "google".to_string());
let client = Client::new(settings).unwrap(); let client = Client::new(settings).unwrap();
let mut params = HashMap::new(); let mut params = HashMap::new();
params.insert("q".to_string(), format!("Filetype: PDF \"{}\"", args.name)); match &args.url {
None => {
if let Some(name) = args.name {
params.insert("q".to_string(), format!("Filetype: PDF \"{}\"", name));
} else {
eprintln!("error no url or name given!");
}
}
Some(url) => {
params.insert("q".to_string(), format!("Site: {} Filetype: PDF", url));
}
}
params.insert("h1".to_string(), "en".to_string()); params.insert("h1".to_string(), "en".to_string());
params.insert("g1".to_string(), "us".to_string()); params.insert("g1".to_string(), "us".to_string());
params.insert("google_domain".to_string(), "google.com".to_string()); params.insert("google_domain".to_string(), "google.com".to_string());
params.insert("start".to_string(), "0".to_string()); params.insert("start".to_string(), "0".to_string());
let mut files = Vec::new(); let mut files = Vec::new();
println!("beginning search"); let search_pb = ProgressBar::new(pages.len() as u64);
search_pb.println("starting search...");
for page in pages { for page in pages {
params.insert("start".to_string(), page.to_string()); params.insert("start".to_string(), page.to_string());
if let Ok(results) = client.search(params.clone()).await { if let Ok(results) = client.search(params.clone()).await {
search_pb.inc(1);
if let Some(arr) = results["organic_results"].as_array() { if let Some(arr) = results["organic_results"].as_array() {
for item in arr { for item in arr {
if let Some(link) = item["link"].as_str() { if let Some(link) = item["link"].as_str() {
if link.contains(".pdf") { match &args.url {
let link_vec: Vec<&str> = link.split("/").collect(); None => {
let link = link.to_string(); if link.contains(".pdf") {
if let Some(filename) = link_vec.last() { let link_vec: Vec<&str> = link.split("/").collect();
let encoded_filename = filename.to_string(); let link = link.to_string();
let filename = decode(&encoded_filename).unwrap().to_string(); if let Some(filename) = link_vec.last() {
let mut filepath = download_path.clone(); let encoded_filename = filename.to_string();
filepath.push(&filename); let filename =
let new_file = FoundFile { decode(&encoded_filename).unwrap().to_string();
filename: filename, let mut filepath = download_path.clone();
filepath, filepath.push(&filename);
url: link, let new_file = FoundFile {
downloaded: None, filename: filename,
parsed: None, filepath,
metadata: HashMap::new(), url: link,
filetype: FileType::Pdf, downloaded: None,
}; parsed: None,
files.push(new_file); metadata: HashMap::new(),
filetype: FileType::Pdf,
};
files.push(new_file);
}
}
}
Some(url) => {
if link.contains(url) {
if link.contains(".pdf") {
let link_vec: Vec<&str> = link.split("/").collect();
let link = link.to_string();
if let Some(filename) = link_vec.last() {
let encoded_filename = filename.to_string();
let filename =
decode(&encoded_filename).unwrap().to_string();
let mut filepath = download_path.clone();
filepath.push(&filename);
let new_file = FoundFile {
filename: filename,
filepath,
url: link,
downloaded: None,
parsed: None,
metadata: HashMap::new(),
filetype: FileType::Pdf,
};
files.push(new_file);
}
}
}
} }
} }
} }
} }
} }
} else {
break;
} }
} }
println!("Search finished!"); search_pb.finish_and_clear();
println!("downloding files..."); let download_pb = ProgressBar::new(files.len() as u64);
download_pb.println("downloading files...");
files.par_iter_mut().for_each(|file| { files.par_iter_mut().for_each(|file| {
file.download(); file.download();
download_pb.inc(1);
if file.downloaded == Some(true) { if file.downloaded == Some(true) {
match file.parse() { match file.parse() {
Ok(_) => {} Ok(_) => {}