summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosias <me@josias.dev>2020-11-22 17:11:05 +0100
committerJosias <me@josias.dev>2020-11-22 17:11:05 +0100
commit842596d4918f62d6bb017b797a086d688a75eccd (patch)
treec975d464f41b52812543e91f0e90192bab79c55f
Add basic server
-rw-r--r--.gitignore1
-rw-r--r--Cargo.toml13
-rw-r--r--README.md10
-rw-r--r--search_engines.csv9
-rw-r--r--src/main.rs85
5 files changed, 118 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..d04df4b
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "oistos"
+version = "0.1.0"
+authors = ["Josias <me@josias.dev>"]
+edition = "2018"
+license = "MIT"
+
+[dependencies]
+actix-web = "3.2.0"
+serde = { version = "1.0", features = ["derive"] }
+csv = "1.1"
+anyhow = "1.0.34"
+rand = "0.7.3"
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..68c36ab
--- /dev/null
+++ b/README.md
@@ -0,0 +1,10 @@
+# oistos
+
+A search engine redirector.
+
+Redirects all calls to `localhost:5005/search/query` to a random search engine (listed in `search_engines.csv`). Also supports shortcodes to choose a specific engine (e.g. `!ddg test`).
+
+This server is particularly useful for interacting with your browser's search bar.
+
+TODO:
+- [ ] Use priority to determine chance of each search engine
diff --git a/search_engines.csv b/search_engines.csv
new file mode 100644
index 0000000..d915bac
--- /dev/null
+++ b/search_engines.csv
@@ -0,0 +1,9 @@
+NAME, SHORT, URL, GENERAL, PRIORITY
+DuckDuckGo,!ddg,https://duckduckgo.com/?q=%s,true,1
+Qwant,!wq,https://www.qwant.com/?q=%s,true,1
+StartPage,!sp,https://www.startpage.com/sp/search?query=%s,true,1
+Infinity Search,!infinity, https://infinitysearch.co/results?q=%s,true,2
+Searx,!sx,https://searx.neocities.org/#?q=%s,true,3
+metaGer,!mg,https://metager.org/meta/meta.ger3?eingabe=%s,true,2
+mojeek,!mk,https://www.mojeek.com/search?q=%s,true,2
+Ecosia,!ec,https://www.ecosia.org/search?q=%s,true,2
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..3b8e2d0
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,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
+}