aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/url.rs
diff options
context:
space:
mode:
authorJokler <jokler.contact@gmail.com>2017-12-11 03:35:05 +0100
committerJokler <jokler.contact@gmail.com>2017-12-11 03:35:05 +0100
commit6c3060994a3e04a59caeae7221650d0eec5e49fa (patch)
tree48da9733bba853054b6afd30167bf42b8cb3f2f3 /src/plugins/url.rs
parentab70f0e6dff916638edfc95d406922b3fd15df7d (diff)
downloadfrippy-6c3060994a3e04a59caeae7221650d0eec5e49fa.tar.gz
frippy-6c3060994a3e04a59caeae7221650d0eec5e49fa.zip
Add Url Plugin
Diffstat (limited to 'src/plugins/url.rs')
-rw-r--r--src/plugins/url.rs146
1 files changed, 146 insertions, 0 deletions
diff --git a/src/plugins/url.rs b/src/plugins/url.rs
new file mode 100644
index 0000000..ec146a0
--- /dev/null
+++ b/src/plugins/url.rs
@@ -0,0 +1,146 @@
+extern crate regex;
+extern crate reqwest;
+extern crate select;
+
+use irc::client::prelude::*;
+use irc::error::Error as IrcError;
+
+use self::regex::Regex;
+
+use std::str;
+use std::io::{self, Read};
+use self::reqwest::Client;
+use self::reqwest::header::Connection;
+
+use self::select::document::Document;
+use self::select::predicate::Name;
+
+use plugin::*;
+
+lazy_static! {
+ static ref RE: Regex = Regex::new(r"http(s)?://(\S+)").unwrap();
+}
+
+#[derive(PluginName, Debug)]
+pub struct Url {
+ max_kib: usize,
+}
+
+impl Url {
+ /// If a file is larger than `max_kib` KiB the download is stopped
+ pub fn new(max_kib: usize) -> Url {
+ Url {max_kib: max_kib}
+ }
+
+ fn grep_url(&self, msg: &str) -> Option<String> {
+ match RE.captures(msg) {
+ Some(captures) => {
+ debug!("Url captures: {:?}", captures);
+
+ Some(captures.get(0).unwrap().as_str().to_string())
+ }
+ None => None,
+ }
+ }
+
+ fn url(&self, server: &IrcServer, message: &str, target: &str) -> Result<(), IrcError> {
+ let url = match self.grep_url(message) {
+ Some(url) => url,
+ None => {
+ return Ok(());
+ }
+ };
+
+ let response = Client::new()
+ .get(&url)
+ .header(Connection::close())
+ .send();
+
+ match response {
+ Ok(mut response) => {
+ let mut body = String::new();
+
+ // 500 kilobyte buffer
+ let mut buf = [0; 500 * 1000];
+ let mut written = 0;
+ // Read until we reach EOF or max_kib KiB
+ loop {
+ let len = match response.read(&mut buf) {
+ Ok(0) => break,
+ Ok(len) => len,
+ Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
+ Err(e) => {
+ debug!("Download from \"{}\" failed: {}", url, e);
+ return Ok(())
+ }
+ };
+
+ let slice = match str::from_utf8(&buf[..len]) {
+ Ok(slice) => slice,
+ Err(e) => {
+ debug!("Failed to read bytes from \"{}\" as UTF8: {}", url, e);
+ return Ok(());
+ }
+ };
+
+ body.push_str(slice);
+ written += len;
+
+ // Check if the file is too large to download
+ if written > self.max_kib * 1024 {
+ debug!("Stopping download - File from \"{}\" is larger than {} KiB", url, self.max_kib);
+ return Ok(());
+ }
+ }
+
+ // let mut body = String::new();
+ // if let Err(e) = response.read_to_string(&mut body) {
+ // error!("Failed to read string from \"{}\": {}", url, e);
+ // return Ok(());
+ // }
+ // let doc = Document::from(body.as_ref());
+
+ let doc = Document::from(body.as_ref());
+ if let Some(title) = doc.find(Name("title")).next() {
+ let text = title.children().next().unwrap();
+ debug!("Title: {:?}", text);
+
+ server.send_privmsg(target, text.as_text().unwrap())
+
+ } else {
+ Ok(())
+ }
+ }
+ Err(e) => {
+ debug!("Bad response from \"{}\": ({})", url, e);
+ Ok(())
+ }
+ }
+ }
+}
+
+impl Plugin for Url {
+ fn is_allowed(&self, _: &IrcServer, message: &Message) -> bool {
+ match message.command {
+ Command::PRIVMSG(_, ref msg) => RE.is_match(msg),
+ _ => false,
+ }
+ }
+
+ fn execute(&self, server: &IrcServer, message: &Message) -> Result<(), IrcError> {
+ match message.command {
+ Command::PRIVMSG(_, ref content) => {
+ self.url(server, content, message.response_target().unwrap())
+ }
+ _ => Ok(()),
+ }
+ }
+
+ fn command(&self, server: &IrcServer, command: PluginCommand) -> Result<(), IrcError> {
+ server.send_notice(&command.source,
+ "This Plugin does not implement any commands.")
+ }
+}
+
+#[cfg(test)]
+mod tests {}