Help me, I have some errors

error[E0432]: unresolved import `reqwest::blocking::multipart`
 --> src\main.rs:7:5
  |
7 | use reqwest::blocking::multipart;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `multipart` in `blocking`

error[E0432]: unresolved import `reqwest::multipart`
  --> src\main.rs:10:5
   |
10 | use reqwest::multipart;
   |     ^^^^^^^^^^^^^^^^^^ no `multipart` in the root

error[E0599]: no method named `multipart` found for struct `reqwest::blocking::RequestBuilder` in the current scope
   --> src\main.rs:104:38
    |
104 |     let response = client.post(&url).multipart(form).send().await?;
    |                                      ^^^^^^^^^ method not found in `RequestBuilder`

How to fix it? Can anyone help me?

Code:

use std::fs;
use std::io::{BufRead, BufReader, Write};
use std::path::Path;
use std::process::Command;
use chrono::Local;
use serde::{Deserialize, Serialize};
use reqwest::blocking::multipart;
use tokio::runtime::Runtime;
use reqwest::blocking::RequestBuilder;
use reqwest::multipart;

const CONFIG_FILE: &str = "config.json";

#[derive(Debug, Serialize, Deserialize)]
struct Config {
    telegram_token: String,
    chat_id: String,
}

#[derive(Debug)]
struct Query {
    name: String,
    domain: String,
}

impl Query {
    fn new(name: String, domain: String) -> Self {
        Query { name, domain }
    }
}

fn load_config() -> Result<Config, Box<dyn std::error::Error>> {
    if !Path::new(CONFIG_FILE).exists() {
        let config_data = Config {
            telegram_token: String::from("TOKEN_TELEGRAM_BOT"),
            chat_id: String::from("CHAT_ID"),
        };
        let config_data_json = serde_json::to_string_pretty(&config_data)?;
        fs::write(CONFIG_FILE, config_data_json)?;
        println!("Config file created. Please fill it and run the program again.");
        return Err("Config file not found.".into());
    } else {
        let config_data = fs::read_to_string(CONFIG_FILE)?;
        let config: Config = serde_json::from_str(&config_data)?;
        println!("Config loaded successfully.");
        return Ok(config);
    }
}

async fn parse_file(filename: &str, queries: &[Query], result_folder: &str) -> Result<(u64, u64, u64), Box<dyn std::error::Error>> {
    let mut found_queries = 0;
    let mut not_found_queries = 0;
    let mut total_lines = 0;

    let file = fs::File::open(filename)?;
    let reader = BufReader::new(file);

    for line_result in reader.lines() {
        let line = line_result?;
        total_lines += 1;

        for query in queries {
            if line.to_lowercase().contains(&query.domain) {
                found_queries += 1;
                let folder_name = query.name.replace('/', "_").replace(':', "_");
                let folder_path = format!("{}/{}", result_folder, folder_name);
                fs::create_dir_all(&folder_path)?;

                let file_name = format!("{}/{}.txt", folder_path, query.name.replace('/', "_").replace(':', "_"));
                let mut file = fs::OpenOptions::new().create(true).append(true).open(&file_name)?;

                writeln!(file, "{}", line)?;
            } else {
                not_found_queries += 1;
            }
        }
    }

    Ok((found_queries, not_found_queries, total_lines))
}

async fn archive_results(result_folder: &str) -> Result<String, Box<dyn std::error::Error>> {
    let zip_file_name = format!("{}.zip", result_folder);
    let output = Command::new("zip")
        .arg("-r")
        .arg(&zip_file_name)
        .arg(result_folder)
        .output()?;
    if !output.status.success() {
        return Err(format!("Failed to create zip archive: {:?}", output).into());
    }

    println!("Results successfully archived: {}", zip_file_name);
    Ok(zip_file_name)
}

async fn send_to_telegram(token: &str, chat_id: &str, file_path: &str) -> Result<(), Box<dyn std::error::Error>> {
    let url = format!("https://api.telegram.org/bot{}/sendDocument", token);
    let form = multipart::Form::new()
        .text("chat_id", chat_id)
        .file("document", file_path)?;
    
    let client = reqwest::blocking::Client::new();
    let response = client.post(&url).multipart(form).send().await?;
    
    if response.status().is_success() {
        println!("Results successfully sent to Telegram bot.");
    } else {
        println!("Failed to send results to Telegram: {:?}", response.text().await?);
    }
    
    Ok(())
}


fn read_queries_from_file(filename: &str) -> Result<Vec<Query>, Box<dyn std::error::Error>> {
    let file = fs::File::open(filename)?;
    let reader = BufReader::new(file);

    let mut queries = Vec::new();

    for line_result in reader.lines() {
        let line = line_result?;
        let line = line.trim();
        if !line.is_empty() {
            let query = Query::new(line.to_string(), line.to_lowercase());
            queries.push(query);
        }
    }

    Ok(queries)
}

fn main() {
    let config = match load_config() {
        Ok(config) => config,
        Err(e) => {
            eprintln!("Error loading config: {}", e);
            return;
        }
    };

    let filename = "req.txt";
    let queries = match read_queries_from_file("qr.txt") {
        Ok(queries) => queries,
        Err(e) => {
            eprintln!("Error reading queries from qr.txt: {}", e);
            return;
        }
    };

    let result_folder = format!("Results {}", Local::now().format("%Y-%m-%d %H-%M-%S"));

    let rt = Runtime::new().unwrap();
    let (found_queries, not_found_queries, total_lines) = rt.block_on(parse_file(&filename, &queries, &result_folder)).unwrap();

    println!("Found: {} | Not Found: {} | Total Lines: {}", found_queries, not_found_queries, total_lines);

    let zip_file_name = rt.block_on(archive_results(&result_folder)).unwrap();

    rt.block_on(send_to_telegram(&config.telegram_token, &config.chat_id, &zip_file_name)).unwrap();
}

Cargo.toml:

[package]
name = "upyrsorter_analog"
version = "0.1.0"
edition = "2018"

[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
chrono = "0.4"
tokio = { version = "1", features = ["full"] }
reqwest = { version = "0.11", features = ["blocking", "json"] }

If you had read the documentation, you could have seen that the multipart functionality is also feature-gated.

In general, when a library doesn't contain an item it seems it should have, the error is either a missing feature flag or depending on the wrong version.

3 Likes

I like you, thank you so much!