commit 094138af9ad6df7412d29e9b141dc9ddd170c84c Author: Adrian Malacoda Date: Wed Feb 22 23:27:43 2017 -0600 Initial commit diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..221e03c --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,174 @@ +[root] +name = "echobox" +version = "0.0.1" +dependencies = [ + "env_logger 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "sqlite 0.23.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aho-corasick" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "env_logger" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gcc" +version = "0.3.43" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libc" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "log" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memchr" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pkg-config" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "regex" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "sqlite" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", + "sqlite3-sys 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sqlite3-src" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sqlite3-sys" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", + "sqlite3-src 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread-id" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread_local" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unreachable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "utf8-ranges" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0638fd549427caa90c499814196d1b9e3725eb4d15d7339d6de073a680ed0ca2" +"checksum env_logger 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "99971fb1b635fe7a0ee3c4d065845bb93cca80a23b5613b5613391ece5de4144" +"checksum gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)" = "c07c758b972368e703a562686adb39125707cc1ef3399da8c019fc6c2498a75d" +"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "684f330624d8c3784fb9558ca46c4ce488073a8d22450415c5eb4f4cfb0d11b5" +"checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" +"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" +"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" +"checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01" +"checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457" +"checksum sqlite 0.23.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a3cd27f80d9229b15313403f73d9180f2368f181a870be51f07e8f7f41d7a264" +"checksum sqlite3-src 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "52f02ac7a64c3446581ee43758075d9f1cdced596d70ffe28bf02979a719dbed" +"checksum sqlite3-sys 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71fec807a1534bd13eeaaec396175d67c79bdc68df55e18a452726ec62a8fb08" +"checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a" +"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7" +"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" +"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" +"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/README.md b/README.md new file mode 100644 index 0000000..a6449e8 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# Echobox +Echobox is a database of quotes. You put in a quote, it will return back a quote. The echobox is backed by a sqlite database. + +Echobox was inspired by [fivequestionmarks's](http://infinitypedia.org/wiki/Fivequestionmarks/commands) `!echobox` command; accordingly, it is mainly intended for use in a tenquestionmarks module. However, this Echobox may not behave the same way the original does. + +In particular, `echo(&str)` may return back the input quote (not sure if fivequestionmarks does this or not). + +## Usage +### Command Line +`cargo run ""` +#### Notes +* The entire quote is one argument, so it needs to be quoted if there are spaces. +* Echobox uses the file `echobox.db` in the current working directory. There is currently not a way to change this. + +### Library +The `Echobox` type provides two constructors, `Echobox::with_file(&str)` and `Echobox::with_connection(sqlite::Connection)`. Both of these will create the database, including the single table, if it does not exist. The `Echobox` provides three methods, `echo(&str)` which inserts the input quote into the database and then returns a single random `Quote` from the database, `put(&str)` which inserts a quote, and `get(i64)` which returns a `Vec` containing the requested number of random quotes. + +The `Quote` struct represents a single quote from the echobox, and has `id` and `content`. diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..13cc129 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,74 @@ +extern crate sqlite; +use sqlite::Connection; + +const DATA_SCHEMA: &'static str = "CREATE TABLE IF NOT EXISTS quotes (content TEXT);"; +const SELECT_QUERY: &'static str = "SELECT rowid, content FROM quotes ORDER BY RANDOM() LIMIT ?;"; +const INSERT_QUERY: &'static str = "INSERT INTO quotes (content) VALUES (?);"; + +pub struct Echobox { + connection: Connection +} + +impl Echobox { + pub fn with_file (path: &str) -> Result { + let connection = sqlite::open(path)?; + Echobox::with_connection(connection) + } + + pub fn with_connection (connection: Connection) -> Result { + connection.execute(DATA_SCHEMA)?; + Result::Ok(Echobox { + connection: connection + }) + } + + pub fn echo (&self, quote: &str) -> Result { + self.put(quote)?; + Result::Ok(self.get(1)?[0].clone()) + } + + pub fn put (&self, quote: &str) -> Result<(), Error> { + let mut statement = self.connection.prepare(INSERT_QUERY)?; + statement.bind(1, quote)?; + statement.next()?; + Result::Ok(()) + } + + pub fn get (&self, number: i64) -> Result, Error> { + let mut statement = self.connection.prepare(SELECT_QUERY)?; + statement.bind(1, number)?; + let mut cursor = statement.cursor(); + + let mut quotes = vec![]; + while let Some(row) = cursor.next().unwrap() { + quotes.push(Quote { + id: row[0].as_integer().expect("Expected rowid in row"), + text: String::from(row[1].as_string().expect("Expected text in row")) + }); + } + Result::Ok(quotes) + } +} + +#[derive(Debug)] +pub enum Error { + Sql(sqlite::Error) +} + +impl From for Error { + fn from (error: sqlite::Error) -> Error { + Error::Sql(error) + } +} + +#[derive(Debug, Clone)] +pub struct Quote { + pub id: i64, + pub text: String +} + +impl std::fmt::Display for Quote { + fn fmt (&self, formatter: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { + write!(formatter, "{}", self.text) + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..f5105d2 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,19 @@ +extern crate echobox; +use echobox::Echobox; + +use std::env; + +#[macro_use] +extern crate log; +extern crate env_logger; + +const ECHOBOX_FILE: &'static str = "echobox.db"; + +fn main () { + env_logger::init().unwrap(); + + let in_quote = &env::args().nth(1).expect("Expected quote as first argument.")[..]; + let echobox = Echobox::with_file(ECHOBOX_FILE).unwrap(); + let out_quote = echobox.echo(in_quote).unwrap(); + println!("{}: {}", out_quote.id, out_quote.text); +}