summaryrefslogtreecommitdiff
path: root/src/main.rs
blob: 3b8e2d09a0092de972ab8fb1981a994781554cd9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use actix_web::{get, web, App, HttpResponse, HttpServer, Responder};
use anyhow::Result;
use rand::seq::SliceRandom;
use serde::Deserialize;

#[derive(Debug, Clone)]
struct Config {
    search_engines: Vec<Engine>,
}

impl Config {
    fn load_from<R: std::io::Read>(reader: R) -> Result<Self> {
        let mut rdr = csv::ReaderBuilder::new()
            .trim(csv::Trim::All)
            .from_reader(reader);

        let mut conf = Self {
            search_engines: vec![],
        };
        for result in rdr.deserialize() {
            let record: Engine = result?;
            conf.search_engines.push(record);
        }

        Ok(conf)
    }
}

#[derive(Deserialize, Debug, Clone)]
struct Engine {
    #[serde(rename = "NAME")]
    name: String,
    #[serde(rename = "SHORT")]
    short: String,
    #[serde(rename = "URL")]
    url: String,
    #[serde(rename = "GENERAL")]
    general: bool,
    #[serde(rename = "PRIORITY")]
    priority: usize,
}

#[get("/search/{query}")]
async fn search(config: web::Data<Config>, web::Path(query): web::Path<String>) -> impl Responder {
    if query.starts_with('!') {
        let mut split = query.split('+');
        let short = split.next();
        if let Some(short) = short {
            let query = split.collect::<Vec<&str>>().join(" ");

            let mut url: &str = "";
            for se in &config.search_engines {
                if se.short == short {
                    url = &se.url;
                }
                println!("hi");
            }
            return HttpResponse::Found()
                .header("Location", url.replace("%s", &query))
                .finish();
        }
    } else {
        let general: Vec<&Engine> = config
            .search_engines
            .iter()
            .filter(|se| se.general)
            .collect();
        let engine = general.choose(&mut rand::thread_rng()).unwrap();
        return HttpResponse::Found()
            .header("Location", engine.url.replace("%s", &query))
            .finish();
    }
    HttpResponse::BadRequest().finish()
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let f = std::fs::File::open("search_engines.csv").unwrap();
    let config = Config::load_from(f).unwrap();

    HttpServer::new(move || App::new().data(config.clone()).service(search))
        .bind("127.0.0.1:5005")?
        .run()
        .await
}