<commit_before>//! An implementation of [tldr](https://github.com/tldr-pages/tldr) in Rust.
//
// Copyright (c) 2015-2018 tealdeer developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be
// copied, modified, or distributed except according to those terms.

#![deny(
    missing_docs,
    missing_debug_implementations,
    unsafe_code,
    unused_import_braces,
    unused_qualifications
)]
#![warn(
    trivial_casts,
    trivial_numeric_casts,
    missing_copy_implementations,
    unused_extern_crates,
    unused_results
)]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![cfg_attr(
    feature = "dev",
    warn(
        cast_possible_truncation,
        cast_possible_wrap,
        cast_precision_loss,
        cast_sign_loss,
        mut_mut,
        non_ascii_literal,
        option_unwrap_used,
        result_unwrap_used,
        shadow_reuse,
        shadow_same,
        unicode_not_nfc,
        wrong_self_convention,
        wrong_pub_self_convention
    )
)]

#[macro_use]
extern crate log;
extern crate ansi_term;
extern crate curl;
extern crate docopt;
#[cfg(feature = "logging")]
extern crate env_logger;
extern crate flate2;
extern crate tar;
extern crate time;
extern crate toml;
extern crate walkdir;
extern crate xdg;
#[macro_use]
extern crate serde_derive;

use std::fs::File;
use std::io::BufReader;
use std::path::{Path, PathBuf};
use std::process;

use ansi_term::Color;
use docopt::Docopt;

mod cache;
mod config;
mod error;
mod formatter;
mod tokenizer;
mod types;

use cache::Cache;
use config::{get_config_path, make_default_config, Config};
use error::TealdeerError::{CacheError, ConfigError, UpdateError};
use formatter::print_lines;
use tokenizer::Tokenizer;
use types::OsType;

const NAME: &str = "tealdeer";
const VERSION: &str = env!("CARGO_PKG_VERSION");
const USAGE: &str = "
Usage:

    tldr [options] <command>
    tldr [options]

Options:

    -h --help           Show this screen
    -v --version        Show version information
    -l --list           List all commands in the cache
    -f --render <file>  Render a specific markdown file
    -o --os <type>      Override the operating system [linux, osx, sunos]
    -u --update         Update the local cache
    -c --clear-cache    Clear the local cache
    -q --quiet          Suppress informational messages
    --config-path       Show config file path
    --seed-config       Create a basic config

Examples:

    $ tldr tar
    $ tldr --list

To control the cache:

    $ tldr --update
    $ tldr --clear-cache

To render a local file (for testing):

    $ tldr --render /path/to/file.md
";
const ARCHIVE_URL: &str = "https://github.com/tldr-pages/tldr/archive/master.tar.gz";
const MAX_CACHE_AGE: i64 = 2592000; // 30 days

#[derive(Debug, Deserialize)]
struct Args {
    arg_command: Option<String>,
    flag_help: bool,
    flag_version: bool,
    flag_list: bool,
    flag_render: Option<String>,
    flag_os: Option<OsType>,
    flag_update: bool,
    flag_clear_cache: bool,
    flag_quiet: bool,
    flag_config_path: bool,
    flag_seed_config: bool,
}

/// Print page by path
fn print_page(path: &Path) -> Result<(), String> {
    // Open file
    let file = try!(File::open(path).map_err(|msg| format!("Could not open file: {}", msg)));
    let reader = BufReader::new(file);

    // Look up config file, if none is found fall back to default config.
    let config = match Config::load() {
        Ok(config) => config,
        Err(ConfigError(msg)) => {
            eprintln!("Could not load config: {}", msg);
            process::exit(1);
        }
        Err(e) => {
            eprintln!("Could not load config: {}", e);
            process::exit(1);
        }
    };

    // Create tokenizer and print output
    let mut tokenizer = Tokenizer::new(reader);
    print_lines(&mut tokenizer, &config);

    Ok(())
}

/// Check the cache for freshness
fn check_cache(args: &Args, cache: &Cache) {
    if !args.flag_update {
        match cache.last_update() {
            Some(ago) if ago > MAX_CACHE_AGE => {
                if args.flag_quiet {
                    return;
                }
                println!(
                    "{}",
                    Color::Red.paint(format!(
                        "Cache wasn't updated for more than {} days.\n\
                         You should probably run `tldr --update` soon.",
                        MAX_CACHE_AGE / 24 / 3600
                    ))
                );
            }
            None => {
                eprintln!("Cache not found. Please run `tldr --update`.");
                process::exit(1);
            }
            _ => {}
        }
    };
}

#[cfg(feature = "logging")]
fn init_log() {
    env_logger::init();
}

#[cfg(not(feature = "logging"))]
fn init_log() {}

#[cfg(target_os = "linux")]
fn get_os() -> OsType {
    OsType::Linux
}

#[cfg(target_os = "macos")]
fn get_os() -> OsType {
    OsType::OsX
}

#[cfg(not(any(target_os = "linux", target_os = "macos")))]
fn get_os() -> OsType {
    OsType::Other
}

fn main() {
    // Initialize logger
    init_log();

    // Parse arguments
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.deserialize())
        .unwrap_or_else(|e| e.exit());

    // Show version and exit
    if args.flag_version {
        let os = get_os();
        println!("{} v{} ({})", NAME, VERSION, os);
        process::exit(0);
    }

    // Specify target OS
    let os: OsType = match args.flag_os {
        Some(os) => os,
        None => get_os(),
    };

    // Initialize cache
    let cache = Cache::new(ARCHIVE_URL, os);

    // Clear cache, pass through
    if args.flag_clear_cache {
        cache.clear().unwrap_or_else(|e| {
            match e {
                CacheError(msg) | ConfigError(msg) | UpdateError(msg) => {
                    eprintln!("Could not delete cache: {}", msg)
                }
            };
            process::exit(1);
        });
        if !args.flag_quiet {
            println!("Successfully deleted cache.");
        }
    }

    // Update cache, pass through
    if args.flag_update {
        cache.update().unwrap_or_else(|e| {
            match e {
                CacheError(msg) | ConfigError(msg) | UpdateError(msg) => {
                    eprintln!("Could not update cache: {}", msg)
                }
            };
            process::exit(1);
        });
        if !args.flag_quiet {
            println!("Successfully updated cache.");
        }
    }

    // Show config file and path, pass through
    if args.flag_config_path {
        match get_config_path() {
            Ok(config_file_path) => {
                println!("Config path is: {}", config_file_path.to_str().unwrap());
            }
            Err(ConfigError(msg)) => {
                eprintln!("Could not look up config_path: {}", msg);
                process::exit(1);
            }
            Err(_) => {
                eprintln!("Unknown error");
                process::exit(1);
            }
        }
    }

    // Create a basic config and exit
    if args.flag_seed_config {
        match make_default_config() {
            Ok(config_file_path) => {
                println!(
                    "Successfully created seed config file here: {}",
                    config_file_path.to_str().unwrap()
                );
                process::exit(0);
            }
            Err(ConfigError(msg)) => {
                eprintln!("Could not create seed config: {}", msg);
                process::exit(1);
            }
            Err(_) => {
                eprintln!("Unkown error");
                process::exit(1);
            }
        }
    }

    // Render local file and exit
    if let Some(ref file) = args.flag_render {
        let path = PathBuf::from(file);
        if let Err(msg) = print_page(&path) {
            eprintln!("{}", msg);
            process::exit(1);
        } else {
            process::exit(0);
        };
    }

    // List cached commands and exit
    if args.flag_list {
        // Check cache for freshness
        check_cache(&args, &cache);

        // Get list of pages
        let pages = cache.list_pages().unwrap_or_else(|e| {
            match e {
                CacheError(msg) | ConfigError(msg) | UpdateError(msg) => {
                    eprintln!("Could not get list of pages: {}", msg)
                }
            }
            process::exit(1);
        });

        // Print pages
        println!("{}", pages.join(", "));
        process::exit(0);
    }

    // Show command from cache
    if let Some(ref command) = args.arg_command {
        // Check cache for freshness
        check_cache(&args, &cache);

        // Search for command in cache
        if let Some(path) = cache.find_page(&command) {
            if let Err(msg) = print_page(&path) {
                eprintln!("{}", msg);
                process::exit(1);
            } else {
                process::exit(0);
            }
        } else {
            if !args.flag_quiet {
                println!("Page {} not found in cache", &command);
                println!("Try updating with `tldr --update`, or submit a pull request to:");
                println!("https://github.com/tldr-pages/tldr");
            }
            process::exit(1);
        }
    }

    // Some flags can be run without a command.
    if !(args.flag_update || args.flag_clear_cache || args.flag_config_path) {
        eprintln!("{}", USAGE);
        process::exit(1);
    }
}

#[cfg(test)]
mod test {
    use docopt::Docopt;
    use docopt::Error;
    use Args;
    use OsType;
    use USAGE;

    fn test_helper(argv: &[&str]) -> Result<Args, Error> {
        Docopt::new(USAGE).and_then(|d| d.argv(argv.iter()).deserialize())
    }

    #[test]
    fn test_docopt_os_case_insensitive() {
        let argv = vec!["cp", "--os", "LiNuX"];
        let os = test_helper(&argv).unwrap().flag_os.unwrap();
        assert_eq!(OsType::Linux, os);
    }

    #[test]
    fn test_docopt_expect_error() {
        let argv = vec!["cp", "--os", "lindows"];
        assert!(!test_helper(&argv).is_ok());
    }
}
<commit_msg>OS detection: Treat BSDs as "osx" (#58)<commit_after>//! An implementation of [tldr](https://github.com/tldr-pages/tldr) in Rust.
//
// Copyright (c) 2015-2018 tealdeer developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be
// copied, modified, or distributed except according to those terms.

#![deny(
    missing_docs,
    missing_debug_implementations,
    unsafe_code,
    unused_import_braces,
    unused_qualifications
)]
#![warn(
    trivial_casts,
    trivial_numeric_casts,
    missing_copy_implementations,
    unused_extern_crates,
    unused_results
)]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![cfg_attr(
    feature = "dev",
    warn(
        cast_possible_truncation,
        cast_possible_wrap,
        cast_precision_loss,
        cast_sign_loss,
        mut_mut,
        non_ascii_literal,
        option_unwrap_used,
        result_unwrap_used,
        shadow_reuse,
        shadow_same,
        unicode_not_nfc,
        wrong_self_convention,
        wrong_pub_self_convention
    )
)]

#[macro_use]
extern crate log;
extern crate ansi_term;
extern crate curl;
extern crate docopt;
#[cfg(feature = "logging")]
extern crate env_logger;
extern crate flate2;
extern crate tar;
extern crate time;
extern crate toml;
extern crate walkdir;
extern crate xdg;
#[macro_use]
extern crate serde_derive;

use std::fs::File;
use std::io::BufReader;
use std::path::{Path, PathBuf};
use std::process;

use ansi_term::Color;
use docopt::Docopt;

mod cache;
mod config;
mod error;
mod formatter;
mod tokenizer;
mod types;

use cache::Cache;
use config::{get_config_path, make_default_config, Config};
use error::TealdeerError::{CacheError, ConfigError, UpdateError};
use formatter::print_lines;
use tokenizer::Tokenizer;
use types::OsType;

const NAME: &str = "tealdeer";
const VERSION: &str = env!("CARGO_PKG_VERSION");
const USAGE: &str = "
Usage:

    tldr [options] <command>
    tldr [options]

Options:

    -h --help           Show this screen
    -v --version        Show version information
    -l --list           List all commands in the cache
    -f --render <file>  Render a specific markdown file
    -o --os <type>      Override the operating system [linux, osx, sunos]
    -u --update         Update the local cache
    -c --clear-cache    Clear the local cache
    -q --quiet          Suppress informational messages
    --config-path       Show config file path
    --seed-config       Create a basic config

Examples:

    $ tldr tar
    $ tldr --list

To control the cache:

    $ tldr --update
    $ tldr --clear-cache

To render a local file (for testing):

    $ tldr --render /path/to/file.md
";
const ARCHIVE_URL: &str = "https://github.com/tldr-pages/tldr/archive/master.tar.gz";
const MAX_CACHE_AGE: i64 = 2592000; // 30 days

#[derive(Debug, Deserialize)]
struct Args {
    arg_command: Option<String>,
    flag_help: bool,
    flag_version: bool,
    flag_list: bool,
    flag_render: Option<String>,
    flag_os: Option<OsType>,
    flag_update: bool,
    flag_clear_cache: bool,
    flag_quiet: bool,
    flag_config_path: bool,
    flag_seed_config: bool,
}

/// Print page by path
fn print_page(path: &Path) -> Result<(), String> {
    // Open file
    let file = try!(File::open(path).map_err(|msg| format!("Could not open file: {}", msg)));
    let reader = BufReader::new(file);

    // Look up config file, if none is found fall back to default config.
    let config = match Config::load() {
        Ok(config) => config,
        Err(ConfigError(msg)) => {
            eprintln!("Could not load config: {}", msg);
            process::exit(1);
        }
        Err(e) => {
            eprintln!("Could not load config: {}", e);
            process::exit(1);
        }
    };

    // Create tokenizer and print output
    let mut tokenizer = Tokenizer::new(reader);
    print_lines(&mut tokenizer, &config);

    Ok(())
}

/// Check the cache for freshness
fn check_cache(args: &Args, cache: &Cache) {
    if !args.flag_update {
        match cache.last_update() {
            Some(ago) if ago > MAX_CACHE_AGE => {
                if args.flag_quiet {
                    return;
                }
                println!(
                    "{}",
                    Color::Red.paint(format!(
                        "Cache wasn't updated for more than {} days.\n\
                         You should probably run `tldr --update` soon.",
                        MAX_CACHE_AGE / 24 / 3600
                    ))
                );
            }
            None => {
                eprintln!("Cache not found. Please run `tldr --update`.");
                process::exit(1);
            }
            _ => {}
        }
    };
}

#[cfg(feature = "logging")]
fn init_log() {
    env_logger::init();
}

#[cfg(not(feature = "logging"))]
fn init_log() {}

#[cfg(target_os = "linux")]
fn get_os() -> OsType {
    OsType::Linux
}

#[cfg(any(target_os = "macos",
          target_os = "freebsd",
          target_os = "netbsd",
          target_os = "openbsd",
          target_os = "dragonfly"))]
fn get_os() -> OsType {
    OsType::OsX
}

#[cfg(not(any(target_os = "linux",
              target_os = "macos",
              target_os = "freebsd",
              target_os = "netbsd",
              target_os = "openbsd",
              target_os = "dragonfly")))]
fn get_os() -> OsType {
    OsType::Other
}

fn main() {
    // Initialize logger
    init_log();

    // Parse arguments
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.deserialize())
        .unwrap_or_else(|e| e.exit());

    // Show version and exit
    if args.flag_version {
        let os = get_os();
        println!("{} v{} ({})", NAME, VERSION, os);
        process::exit(0);
    }

    // Specify target OS
    let os: OsType = match args.flag_os {
        Some(os) => os,
        None => get_os(),
    };

    // Initialize cache
    let cache = Cache::new(ARCHIVE_URL, os);

    // Clear cache, pass through
    if args.flag_clear_cache {
        cache.clear().unwrap_or_else(|e| {
            match e {
                CacheError(msg) | ConfigError(msg) | UpdateError(msg) => {
                    eprintln!("Could not delete cache: {}", msg)
                }
            };
            process::exit(1);
        });
        if !args.flag_quiet {
            println!("Successfully deleted cache.");
        }
    }

    // Update cache, pass through
    if args.flag_update {
        cache.update().unwrap_or_else(|e| {
            match e {
                CacheError(msg) | ConfigError(msg) | UpdateError(msg) => {
                    eprintln!("Could not update cache: {}", msg)
                }
            };
            process::exit(1);
        });
        if !args.flag_quiet {
            println!("Successfully updated cache.");
        }
    }

    // Show config file and path, pass through
    if args.flag_config_path {
        match get_config_path() {
            Ok(config_file_path) => {
                println!("Config path is: {}", config_file_path.to_str().unwrap());
            }
            Err(ConfigError(msg)) => {
                eprintln!("Could not look up config_path: {}", msg);
                process::exit(1);
            }
            Err(_) => {
                eprintln!("Unknown error");
                process::exit(1);
            }
        }
    }

    // Create a basic config and exit
    if args.flag_seed_config {
        match make_default_config() {
            Ok(config_file_path) => {
                println!(
                    "Successfully created seed config file here: {}",
                    config_file_path.to_str().unwrap()
                );
                process::exit(0);
            }
            Err(ConfigError(msg)) => {
                eprintln!("Could not create seed config: {}", msg);
                process::exit(1);
            }
            Err(_) => {
                eprintln!("Unkown error");
                process::exit(1);
            }
        }
    }

    // Render local file and exit
    if let Some(ref file) = args.flag_render {
        let path = PathBuf::from(file);
        if let Err(msg) = print_page(&path) {
            eprintln!("{}", msg);
            process::exit(1);
        } else {
            process::exit(0);
        };
    }

    // List cached commands and exit
    if args.flag_list {
        // Check cache for freshness
        check_cache(&args, &cache);

        // Get list of pages
        let pages = cache.list_pages().unwrap_or_else(|e| {
            match e {
                CacheError(msg) | ConfigError(msg) | UpdateError(msg) => {
                    eprintln!("Could not get list of pages: {}", msg)
                }
            }
            process::exit(1);
        });

        // Print pages
        println!("{}", pages.join(", "));
        process::exit(0);
    }

    // Show command from cache
    if let Some(ref command) = args.arg_command {
        // Check cache for freshness
        check_cache(&args, &cache);

        // Search for command in cache
        if let Some(path) = cache.find_page(&command) {
            if let Err(msg) = print_page(&path) {
                eprintln!("{}", msg);
                process::exit(1);
            } else {
                process::exit(0);
            }
        } else {
            if !args.flag_quiet {
                println!("Page {} not found in cache", &command);
                println!("Try updating with `tldr --update`, or submit a pull request to:");
                println!("https://github.com/tldr-pages/tldr");
            }
            process::exit(1);
        }
    }

    // Some flags can be run without a command.
    if !(args.flag_update || args.flag_clear_cache || args.flag_config_path) {
        eprintln!("{}", USAGE);
        process::exit(1);
    }
}

#[cfg(test)]
mod test {
    use docopt::Docopt;
    use docopt::Error;
    use Args;
    use OsType;
    use USAGE;

    fn test_helper(argv: &[&str]) -> Result<Args, Error> {
        Docopt::new(USAGE).and_then(|d| d.argv(argv.iter()).deserialize())
    }

    #[test]
    fn test_docopt_os_case_insensitive() {
        let argv = vec!["cp", "--os", "LiNuX"];
        let os = test_helper(&argv).unwrap().flag_os.unwrap();
        assert_eq!(OsType::Linux, os);
    }

    #[test]
    fn test_docopt_expect_error() {
        let argv = vec!["cp", "--os", "lindows"];
        assert!(!test_helper(&argv).is_ok());
    }
}
<|endoftext|>


<commit_before>extern crate ww;

use ww::map::{Map, MapRoomId};
use ww::room::Room;
use ww::direction::Direction::*;

use RoomId::*;

const NUM_ROOMS: usize = 2;

#[derive(Debug, Copy, Clone)]
enum RoomId {
  Hallway,
  AudienceChamber,
}

impl MapRoomId for RoomId {
  fn room_id(self) -> usize { self as usize }
}

fn main() {
  let mut rooms = [Room::new(); NUM_ROOMS];
  let mut map = Map::new(&mut rooms);

  map.room(Hallway).describe("Hallway", "");
  map.room(AudienceChamber).describe("Audience Chamber", "");

  map.connect(Hallway, South, AudienceChamber);

  println!("Map is {:?}", map);
}
<commit_msg>Use explicit room IDs<commit_after>extern crate ww;

use ww::map::{Map, MapRoomId};
use ww::room::Room;
use ww::direction::Direction::*;

use RoomId::*;

const MAX_ROOMS: usize = 20;

#[derive(Debug, Copy, Clone)]
enum RoomId {
  Hallway = 1,
  AudienceChamber = 2,
}

impl MapRoomId for RoomId {
  fn room_id(self) -> usize { self as usize }
}

fn main() {
  let mut rooms = [Room::new(); MAX_ROOMS];
  let mut map = Map::new(&mut rooms);

  map.room(Hallway).describe("Hallway", "");
  map.room(AudienceChamber).describe("Audience Chamber", "");

  map.connect(Hallway, South, AudienceChamber);

  println!("Map is {:?}", map);
}
<|endoftext|>


<commit_before>extern crate bencode;
extern crate crypto;
extern crate rand;
extern crate url;

use std::env;
use std::collections::HashMap;
use bencode::{deserialize_file, Bencode, TypedMethods, BencodeToString};
use crypto::sha1::Sha1;
use crypto::digest::Digest;
use rand::{random, Rng};
use url::percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET};

const PEER_ID_LENGTH:usize = 20;
const PEER_ID_PREFIX:&'static str = "ABT:";

fn gen_rand_peer_id (prefix: &str) -> String {
    let rand_length = PEER_ID_LENGTH - prefix.len();
    let rand = rand::thread_rng()
        .gen_ascii_chars()
        .take(rand_length)
        .collect::<String>();

    prefix.to_string() + &rand
}

#[derive(Debug)]
struct Metadata {
    announce: String,
    info_hash: String
}

trait MetadataDict {
    fn to_metadata (&self) -> Option<Metadata>;
}

impl MetadataDict for HashMap<String, Bencode> {
    /// Extracts information from this HashMap into a Metadata instance, if valid. Currently if it
    /// is invalid, it will just throw a runtime exception
    fn to_metadata (&self) -> Option<Metadata> {
        let announce = self.get_string("announce").unwrap();
        let info_raw = self.get("info").unwrap().to_bencode_string();
        let mut sha = Sha1::new();

        sha.input_str(&info_raw);
        let info_hash = sha.result_str();
        Some(Metadata {
            announce: announce.clone(),
            info_hash: info_hash.to_string()
        })
    }
}

fn get_tracker_response_sync (announce: String) {

}

struct TrackerRequest <'a> {
    params: HashMap<&'a str, String>
}

impl <'a> TrackerRequest <'a> {
    fn new () -> TrackerRequest <'a> {
        TrackerRequest {params: HashMap::new()}
    }

    fn from_params (params: Vec<(&'a str, String)>) -> TrackerRequest <'a> {
        let mut hm = TrackerRequest::new();
        hm.add_params(params);
        hm
    }

    fn add_param (&mut self, name: &'a str, val: String) {
        self.params.insert(name, utf8_percent_encode(&val, DEFAULT_ENCODE_SET));
    }

    fn add_params (&mut self, params: Vec<(&'a str, String)>) {
        for (key, val) in params {
            self.params.insert(key, utf8_percent_encode(&val, DEFAULT_ENCODE_SET));
        }
    }
}

fn main () {
    let path = env::args().nth(1).unwrap_or_else(||panic!("no path to torrent provided"));
    let content = deserialize_file(path).unwrap_or_else(||panic!("unable to parse bencoded metadata"));
    let metadata = match content.first() {
        Some(&Bencode::Dict(ref x)) => x.to_metadata(),
        _ => panic!("no valid information in torrent file")
    }.unwrap();

    let peer_id = gen_rand_peer_id(PEER_ID_PREFIX);

    let mut req_params = TrackerRequest::from_params(vec![
                                                     ("info_hash", metadata.info_hash),
                                                     ("peer_id", peer_id)
                                                     ]);

}
<commit_msg>removing TrackerRequest<commit_after>extern crate bencode;
extern crate crypto;
extern crate rand;
extern crate url;

mod querystring;

use std::env;
use std::collections::HashMap;
use bencode::{deserialize_file, Bencode, TypedMethods, BencodeToString};
use crypto::sha1::Sha1;
use crypto::digest::Digest;
use rand::{random, Rng};
use url::percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET};

use querystring::QueryString;

const PEER_ID_LENGTH:usize = 20;
const PEER_ID_PREFIX:&'static str = "ABT:";

fn gen_rand_peer_id (prefix: &str) -> String {
    let rand_length = PEER_ID_LENGTH - prefix.len();
    let rand = rand::thread_rng()
        .gen_ascii_chars()
        .take(rand_length)
        .collect::<String>();

    prefix.to_string() + &rand
}

#[derive(Debug)]
struct Metadata {
    announce: String,
    info_hash: String
}

trait MetadataDict {
    fn to_metadata (&self) -> Option<Metadata>;
}

impl MetadataDict for HashMap<String, Bencode> {
    /// Extracts information from this HashMap into a Metadata instance, if valid. Currently if it
    /// is invalid, it will just throw a runtime exception
    fn to_metadata (&self) -> Option<Metadata> {
        let announce = self.get_string("announce").unwrap();
        let info_raw = self.get("info").unwrap().to_bencode_string();
        let mut sha = Sha1::new();

        sha.input_str(&info_raw);
        let info_hash = sha.result_str();
        Some(Metadata {
            announce: announce.clone(),
            info_hash: info_hash.to_string()
        })
    }
}

fn get_tracker_response_sync (announce: String) {

}

fn init (metadata: Metadata) {
    let peer_id = gen_rand_peer_id(PEER_ID_PREFIX);
    let mut req_params = QueryString::from(vec![
                                              ("info_hash", metadata.info_hash),
                                              ("peer_id", peer_id)]);
}

fn main () {
    let path = env::args().nth(1).unwrap_or_else(||panic!("no path to torrent provided"));
    let content = deserialize_file(path).unwrap_or_else(||panic!("unable to parse bencoded metadata"));
    let metadata = match content.first() {
        Some(&Bencode::Dict(ref x)) => x.to_metadata(),
        _ => panic!("no valid information in torrent file")
    }.unwrap();

    let peer_id = gen_rand_peer_id(PEER_ID_PREFIX);

    let req_params = QueryString::from(vec![
                                       ("info_hash", metadata.info_hash),
                                       ("peer_id", peer_id)
                                       ]).to_param_string();

    println!("params: {}", req_params);

}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::str;

#[cfg(not(windows))]
pub fn open_file() -> Option<PathBuf> {
    use std::env;
    use std::process::Command;

    let out = Command::new("kdialog").arg("--getopenurl").arg(env::current_dir().unwrap())
                                     .arg("*").output();
    let out = match out {
        Ok(out) => out,
        Err(e) => {
            println!("couldn't open dialog: {:?}", e);
            return None;
        }
    };

    if !out.status.success() {
        return None;
    }

    let file = str::from_utf8(&out.stdout).unwrap().trim();
    Some(PathBuf::from(regex!("^file://").replace(file, "")))
}

#[cfg(windows)]
mod comdlg32 {
    extern crate winapi;
    pub use self::winapi::*;

    shared_library!(ComDlg32, "comdlg32", pub fn GetOpenFileNameA(_ofn: *mut OPENFILENAME) -> BOOL,);

    pub type LPCTSTR = LPCSTR;
    pub type LPTSTR = LPSTR;

    #[repr(C)]
    #[allow(non_snake_case)]
    pub struct OPENFILENAME {
        pub lStructSize: DWORD,
        pub hwndOwner: HWND,
        pub hInstance: HINSTANCE,
        pub lpstrFilter: LPCTSTR,
        pub lpstrCustomFilter: LPTSTR,
        pub nMaxCustFilter: DWORD,
        pub nFilterIndex: DWORD,
        pub lpstrFile: LPTSTR,
        pub nMaxFile: DWORD,
        pub lpstrFileTitle: LPTSTR,
        pub nMaxFileTitle: DWORD,
        pub lpstrInitialDir: LPCTSTR,
        pub lpstrTitle: LPCTSTR,
        pub Flags: DWORD,
        pub nFileOffset: WORD,
        pub nFileExtension: WORD,
        pub lpstrDefExt: LPCTSTR,
        pub lCustData: LPARAM,
        pub lpfnHook: *const (),//LPOFNHOOKPROC,
        pub lpTemplateName: LPCTSTR,
        pub pvReserved: *const (),
        pub dwReserved: DWORD,
        pub FlagsEx: DWORD
    }

    pub fn get_GetOpenFileNameA() -> unsafe extern "system" fn(*mut OPENFILENAME) -> BOOL {
        use std::mem;
        unsafe {
            mem::transmute(ComDlg32::get_static_ref().GetOpenFileNameA)
        }
    }
}

#[cfg(windows)]
pub fn open_file() -> Option<PathBuf> {
    use self::comdlg32::*;
    use std::ffi::CStr;
    use std::mem;

    let mut file = [0u8; 260];

    let mut ofn: OPENFILENAME = unsafe { mem::zeroed() };
    ofn.lStructSize = mem::size_of::<OPENFILENAME>() as DWORD;

    ofn.lpstrFile = file.as_mut_ptr() as LPTSTR;
    ofn.nMaxFile = 260;
    ofn.lpstrFilter = b"All\0*.*\0Rust code\0*.RS\0\0".as_ptr() as LPCTSTR;
    ofn.nFilterIndex = 1;
    ofn.Flags = 0x00000800 | 0x00001000; // OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

    if unsafe { get_GetOpenFileNameA()(&mut ofn) } == TRUE {
        Some(PathBuf::from(str::from_utf8(unsafe {
            CStr::from_ptr(ofn.lpstrFile).to_bytes()
        }).unwrap()))
    } else {
        None
    }
}
<commit_msg>ui::dialog: support open_file on OSX.<commit_after>use std::path::PathBuf;
use std::str;

#[cfg(not(windows))]
pub fn open_file() -> Option<PathBuf> {
    use std::process::Command;

    let out = if cfg!(target_os = "macos") {
        Command::new("osascript").args(&["-e", "POSIX path of (choose file)"]).output()
    } else {
        Command::new("kdialog").args(&["--getopenfilename", "."]).output()
    };
    let out = match out {
        Ok(out) => out,
        Err(e) => {
            println!("couldn't open dialog: {}", e);
            return None;
        }
    };

    if !out.status.success() {
        return None;
    }

    Some(PathBuf::from(str::from_utf8(&out.stdout).unwrap().trim()))
}

#[cfg(windows)]
mod comdlg32 {
    extern crate winapi;
    pub use self::winapi::*;

    shared_library!(ComDlg32, "comdlg32", pub fn GetOpenFileNameA(_ofn: *mut OPENFILENAME) -> BOOL,);

    pub type LPCTSTR = LPCSTR;
    pub type LPTSTR = LPSTR;

    #[repr(C)]
    #[allow(non_snake_case)]
    pub struct OPENFILENAME {
        pub lStructSize: DWORD,
        pub hwndOwner: HWND,
        pub hInstance: HINSTANCE,
        pub lpstrFilter: LPCTSTR,
        pub lpstrCustomFilter: LPTSTR,
        pub nMaxCustFilter: DWORD,
        pub nFilterIndex: DWORD,
        pub lpstrFile: LPTSTR,
        pub nMaxFile: DWORD,
        pub lpstrFileTitle: LPTSTR,
        pub nMaxFileTitle: DWORD,
        pub lpstrInitialDir: LPCTSTR,
        pub lpstrTitle: LPCTSTR,
        pub Flags: DWORD,
        pub nFileOffset: WORD,
        pub nFileExtension: WORD,
        pub lpstrDefExt: LPCTSTR,
        pub lCustData: LPARAM,
        pub lpfnHook: *const (),//LPOFNHOOKPROC,
        pub lpTemplateName: LPCTSTR,
        pub pvReserved: *const (),
        pub dwReserved: DWORD,
        pub FlagsEx: DWORD
    }

    pub fn get_GetOpenFileNameA() -> unsafe extern "system" fn(*mut OPENFILENAME) -> BOOL {
        use std::mem;
        unsafe {
            mem::transmute(ComDlg32::get_static_ref().GetOpenFileNameA)
        }
    }
}

#[cfg(windows)]
pub fn open_file() -> Option<PathBuf> {
    use self::comdlg32::*;
    use std::ffi::CStr;
    use std::mem;

    let mut file = [0u8; 260];

    let mut ofn: OPENFILENAME = unsafe { mem::zeroed() };
    ofn.lStructSize = mem::size_of::<OPENFILENAME>() as DWORD;

    ofn.lpstrFile = file.as_mut_ptr() as LPTSTR;
    ofn.nMaxFile = 260;
    ofn.lpstrFilter = b"All\0*.*\0Rust code\0*.RS\0\0".as_ptr() as LPCTSTR;
    ofn.nFilterIndex = 1;
    ofn.Flags = 0x00000800 | 0x00001000; // OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

    if unsafe { get_GetOpenFileNameA()(&mut ofn) } == TRUE {
        Some(PathBuf::from(str::from_utf8(unsafe {
            CStr::from_ptr(ofn.lpstrFile).to_bytes()
        }).unwrap()))
    } else {
        None
    }
}
<|endoftext|>


<commit_before>#![crate_name = "limonite"]
#![crate_type = "bin"]
#![allow(dead_code)]

extern crate docopt;
extern crate rustc_serialize;
#[macro_use]
extern crate log;
extern crate env_logger;

use std::env;
use std::io::{BufReader, Read};
use std::fs::File;
use std::path::Path;
use docopt::Docopt;
use syntax::lexer::Lexer;
use syntax::parser::Parser;
use codegen::codegen::codegen;

pub mod syntax;
pub mod codegen;

static USAGE: &'static str = "\
Usage: limonite <file>
       limonite (-s | --stdin)
       limonite (-v | --version)

Options:
    -h, --help      Display this message
    -s, --stdin     Read input from stdin
    -v, --version   Displays current version
";

#[derive(RustcDecodable)]
struct Args {
    pub arg_file: String,
    pub flag_stdin: bool,
    pub flag_version: bool
}

fn main() {
    env_logger::init().unwrap();

    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());

    // TODO: Compile the version in from the .toml
    if args.flag_version {
        let version = env!("CARGO_PKG_VERSION");

        return println!("limonite {}", version);
    }

    let input_string = if !args.flag_stdin {
        // Read from file
        let ref file_name = &args.arg_file;
        let path = Path::new(file_name);
        let file = match File::open(&path) {
            Ok(f)  => f,
            Err(e) => panic!("Failed to open file. File error: {}", e)
        };

        let mut input_string = String::new();
        if let Err(e) = BufReader::new(file).read_to_string(&mut input_string) {
            panic!(e);
        }

        input_string
    } else {
        // Read from stdin
        let mut input_string = String::new();
        if let Err(e) = std::io::stdin().read_to_string(&mut input_string) {
            panic!(e);
        }

        input_string
    };

    // Tokanize the input
    let lexer = Lexer::new(&input_string);

    // Parse & Build an AST
    let mut parser = Parser::new(lexer);

    // Could just unwrap this?:
    let ast_root = match parser.parse() {
        Some(ast) => ast,
        None => return,
    };

    // TODO: Semantic Analysis

    // Run Code Gen
    unsafe {
        codegen("module1", ast_root, true);
    }
}
<commit_msg>Removed unused import<commit_after>#![crate_name = "limonite"]
#![crate_type = "bin"]
#![allow(dead_code)]

extern crate docopt;
extern crate rustc_serialize;
#[macro_use]
extern crate log;
extern crate env_logger;

use std::io::{BufReader, Read};
use std::fs::File;
use std::path::Path;
use docopt::Docopt;
use syntax::lexer::Lexer;
use syntax::parser::Parser;
use codegen::codegen::codegen;

pub mod syntax;
pub mod codegen;

static USAGE: &'static str = "\
Usage: limonite <file>
       limonite (-s | --stdin)
       limonite (-v | --version)

Options:
    -h, --help      Display this message
    -s, --stdin     Read input from stdin
    -v, --version   Displays current version
";

#[derive(RustcDecodable)]
struct Args {
    pub arg_file: String,
    pub flag_stdin: bool,
    pub flag_version: bool
}

fn main() {
    env_logger::init().unwrap();

    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());

    // TODO: Compile the version in from the .toml
    if args.flag_version {
        let version = env!("CARGO_PKG_VERSION");

        return println!("limonite {}", version);
    }

    let input_string = if !args.flag_stdin {
        // Read from file
        let ref file_name = &args.arg_file;
        let path = Path::new(file_name);
        let file = match File::open(&path) {
            Ok(f)  => f,
            Err(e) => panic!("Failed to open file. File error: {}", e)
        };

        let mut input_string = String::new();
        if let Err(e) = BufReader::new(file).read_to_string(&mut input_string) {
            panic!(e);
        }

        input_string
    } else {
        // Read from stdin
        let mut input_string = String::new();
        if let Err(e) = std::io::stdin().read_to_string(&mut input_string) {
            panic!(e);
        }

        input_string
    };

    // Tokanize the input
    let lexer = Lexer::new(&input_string);

    // Parse & Build an AST
    let mut parser = Parser::new(lexer);

    // Could just unwrap this?:
    let ast_root = match parser.parse() {
        Some(ast) => ast,
        None => return,
    };

    // TODO: Semantic Analysis

    // Run Code Gen
    unsafe {
        codegen("module1", ast_root, true);
    }
}
<|endoftext|>


<commit_before>//  rtracker: bittorrent tracker
//  Copyright (C) 2019  Justin Noah <justinnoah@gmail.com>
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Affero General Public License as published by
//  the Free Software Foundation, either version 3 of the License.
//
//  This program is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU Affero General Public License for more details.
//
//   You should have received a copy of the GNU Affero General Public License
//   along with this program.  If not, see <https://www.gnu.org/licenses/>.

extern crate bincode;
extern crate chrono;
extern crate docopt;
extern crate env_logger;
extern crate ini;
#[macro_use]
extern crate log;
extern crate r2d2;
extern crate r2d2_sqlite;
extern crate rand;
extern crate rusqlite;
extern crate serde;
#[macro_use]
extern crate serde_derive;

use std::net::UdpSocket;
use std::thread;
use std::time::Duration;

use docopt::Docopt;

use config::ServerConfig;
use database::{db_connection_pool, db_init, db_prune};
use handler::handle_received_packet;

mod config;
mod database;
mod handler;
mod packet_data_types;
mod parse_packets;

static USAGE: &str = "
Usage: rtracker [-c <conf>]
       rtracker (--help)

Options:
    -h, --help          Show this message
    -c, --conf=<conf>   Configuration File [default: ]
";

#[derive(Deserialize)]
struct Args {
    flag_conf: String,
}

fn main() {
    env_logger::init();
    trace!("Logging initialized!");

    // parse commandline args
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.deserialize())
        .unwrap_or_else(|e| e.exit());

    let scfg = ServerConfig::new(&args.flag_conf);
    debug!("addr: {:?}", scfg.address);

    // Let's first initialize the database.
    let sock = match UdpSocket::bind(&scfg.address) {
        Ok(s) => s,
        Err(e) => panic!("{}", e),
    };
    info!("Listening on: {}", &scfg.address);
    let pool = db_connection_pool(scfg.pool_size);
    db_init(pool.get().unwrap());
    debug!("DB initialized");

    // Spawn the database pruning thread
    let prune_pool = pool.clone();
    thread::spawn(move || {
        loop {
            // Every 31min (default is 30min, this allows for some delay)
            let prune_delay = Duration::new(31 * 60u64, 0);
            thread::sleep(prune_delay);
            let prune_conn = prune_pool.get().unwrap();
            db_prune(prune_conn);
            // Prune the database
            debug!("Prune the database!");
        }
    });

    loop {
        // This will become flexible. Simply a starting point
        debug!("Init udp packet buffer");
        // UDP packet max
        let mut buf = [0u8; 1500];
        debug!("IOWait");
        let (amt, src) = sock.recv_from(&mut buf).unwrap();
        let tsock = sock.try_clone().unwrap();
        let tpool = pool.clone();
        if amt >= 16 {
            debug!("Spawn a new thread to handle the packet");
            thread::spawn(move || {
                let mut packet: Vec<u8> = buf.to_vec();
                packet.resize(amt, 0);
                handle_received_packet(packet, src, tsock, tpool.get().unwrap());
            });
        } else {
            debug!("Received a tiny packet (size: {}), ignoring", amt)
        }
    }
}
<commit_msg>Prune: every minute check for 30+ minute inactivity<commit_after>//  rtracker: bittorrent tracker
//  Copyright (C) 2019  Justin Noah <justinnoah@gmail.com>
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Affero General Public License as published by
//  the Free Software Foundation, either version 3 of the License.
//
//  This program is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU Affero General Public License for more details.
//
//   You should have received a copy of the GNU Affero General Public License
//   along with this program.  If not, see <https://www.gnu.org/licenses/>.

extern crate bincode;
extern crate chrono;
extern crate docopt;
extern crate env_logger;
extern crate ini;
#[macro_use]
extern crate log;
extern crate r2d2;
extern crate r2d2_sqlite;
extern crate rand;
extern crate rusqlite;
extern crate serde;
#[macro_use]
extern crate serde_derive;

use std::net::UdpSocket;
use std::thread;
use std::time::Duration;

use docopt::Docopt;

use config::ServerConfig;
use database::{db_connection_pool, db_init, db_prune};
use handler::handle_received_packet;

mod config;
mod database;
mod handler;
mod packet_data_types;
mod parse_packets;

static USAGE: &str = "
Usage: rtracker [-c <conf>]
       rtracker (--help)

Options:
    -h, --help          Show this message
    -c, --conf=<conf>   Configuration File [default: ]
";

#[derive(Deserialize)]
struct Args {
    flag_conf: String,
}

fn main() {
    env_logger::init();
    trace!("Logging initialized!");

    // parse commandline args
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.deserialize())
        .unwrap_or_else(|e| e.exit());

    let scfg = ServerConfig::new(&args.flag_conf);
    debug!("addr: {:?}", scfg.address);

    // Let's first initialize the database.
    let sock = match UdpSocket::bind(&scfg.address) {
        Ok(s) => s,
        Err(e) => panic!("{}", e),
    };
    info!("Listening on: {}", &scfg.address);
    let pool = db_connection_pool(scfg.pool_size);
    db_init(pool.get().unwrap());
    debug!("DB initialized");

    // Spawn the database pruning thread
    let prune_pool = pool.clone();
    thread::spawn(move || {
        loop {
            // Every minute run the prune function.
            // As of this comment, db_prune selects all torrents / connections with a (now -
            // last_active) > 30 minutes. Thus, our 30 minute prune has a polling resolution of one
            // minute.
            let prune_delay = Duration::new(60u64, 0);
            thread::sleep(prune_delay);
            debug!("Prune the database!");
            // Prune the database
            let prune_conn = prune_pool.get().unwrap();
            db_prune(prune_conn);
        }
    });

    loop {
        // This will become flexible. Simply a starting point
        debug!("Init udp packet buffer");
        // UDP packet max
        let mut buf = [0u8; 1500];
        debug!("IOWait");
        let (amt, src) = sock.recv_from(&mut buf).unwrap();
        let tsock = sock.try_clone().unwrap();
        let tpool = pool.clone();
        if amt >= 16 {
            debug!("Spawn a new thread to handle the packet");
            thread::spawn(move || {
                let mut packet: Vec<u8> = buf.to_vec();
                packet.resize(amt, 0);
                handle_received_packet(packet, src, tsock, tpool.get().unwrap());
            });
        } else {
            debug!("Received a tiny packet (size: {}), ignoring", amt)
        }
    }
}
<|endoftext|>


<commit_before>#![feature(mpsc_select, box_syntax, fnbox)]

extern crate discord;
extern crate xivdb;
extern crate dotenv;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate ctrlc;
extern crate chrono;
#[macro_use]
extern crate log;
extern crate fern;
extern crate hyper;
extern crate make_hyper_great_again;
extern crate hyper_rustls;
extern crate ansi_term;
extern crate scraper;
extern crate uuid;
#[macro_use]
extern crate lazy_static;
extern crate envy;
#[macro_use]
extern crate error_chain;
extern crate lalafell;
#[macro_use]
extern crate diesel;
#[macro_use]
extern crate diesel_codegen;
extern crate url;
extern crate url_serde;

mod bot;
mod database;
mod listeners;
mod tasks;
mod commands;
mod lodestone;
mod config;
mod error;

use bot::LalafellBot;
use error::*;

use std::sync::mpsc::channel;

fn main() {
  if let Err(e) = inner() {
    for err in e.iter() {
      error!("{}", err);
    }
  }
}

fn inner() -> Result<()> {
  if let Err(e) = lalafell::logging::init_logger() {
    println!("Could not set up logger.");
    for err in e.iter() {
      println!("{}", err);
    }
    return Ok(());
  }

  info!("Loading .env");

  dotenv::dotenv().ok();

  info!("Reading environment variables");

  let environment: Environment = envy::from_env().expect("Invalid or missing environment variables");

  info!("Creating bot");

  let bot = bot::create_bot(environment)?;

  let (loop_cancel_tx, loop_cancel_rx) = channel();

  ctrlc::set_handler(move || {
    info!("Stopping main loop");
    loop_cancel_tx.send(()).unwrap();
  }).expect("could not set interrupt handler");

  info!("Spinning up bot");
  let thread_bot = bot.clone();
  std::thread::spawn(move || {
    if let Err(e) = thread_bot.start_loop(loop_cancel_rx) {
      error!("could not start bot loop: {}", e);
    }
  }).join().unwrap();
  info!("Exiting");
  Ok(())
}

#[derive(Debug, Deserialize)]
pub struct Environment {
  #[serde(rename = "lb_discord_bot_token")]
  pub discord_bot_token: String,
  #[serde(rename = "lb_database_location")]
  pub database_location: String,
  #[serde(rename = "lb_config_location")]
  pub config_location: String
}
<commit_msg>chore: add more todos<commit_after>#![feature(mpsc_select, box_syntax, fnbox)]

extern crate discord;
extern crate xivdb;
extern crate dotenv;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate ctrlc;
extern crate chrono;
#[macro_use]
extern crate log;
extern crate fern;
extern crate hyper;
extern crate make_hyper_great_again;
extern crate hyper_rustls;
extern crate ansi_term;
extern crate scraper;
extern crate uuid;
#[macro_use]
extern crate lazy_static;
extern crate envy;
#[macro_use]
extern crate error_chain;
extern crate lalafell;
#[macro_use]
extern crate diesel;
#[macro_use]
extern crate diesel_codegen;
extern crate url;
extern crate url_serde;

mod bot;
mod database;
mod listeners;
mod tasks;
mod commands;
mod lodestone;
mod config;
mod error;

use bot::LalafellBot;
use error::*;

use std::sync::mpsc::channel;

// TODO: move delete_all_messages to database
// TODO: move tag_instructions to database
// TODO: change tag_instructions name

fn main() {
  if let Err(e) = inner() {
    for err in e.iter() {
      error!("{}", err);
    }
  }
}

fn inner() -> Result<()> {
  if let Err(e) = lalafell::logging::init_logger() {
    println!("Could not set up logger.");
    for err in e.iter() {
      println!("{}", err);
    }
    return Ok(());
  }

  info!("Loading .env");

  dotenv::dotenv().ok();

  info!("Reading environment variables");

  let environment: Environment = envy::from_env().expect("Invalid or missing environment variables");

  info!("Creating bot");

  let bot = bot::create_bot(environment)?;

  let (loop_cancel_tx, loop_cancel_rx) = channel();

  ctrlc::set_handler(move || {
    info!("Stopping main loop");
    loop_cancel_tx.send(()).unwrap();
  }).expect("could not set interrupt handler");

  info!("Spinning up bot");
  let thread_bot = bot.clone();
  std::thread::spawn(move || {
    if let Err(e) = thread_bot.start_loop(loop_cancel_rx) {
      error!("could not start bot loop: {}", e);
    }
  }).join().unwrap();
  info!("Exiting");
  Ok(())
}

#[derive(Debug, Deserialize)]
pub struct Environment {
  #[serde(rename = "lb_discord_bot_token")]
  pub discord_bot_token: String,
  #[serde(rename = "lb_database_location")]
  pub database_location: String,
  #[serde(rename = "lb_config_location")]
  pub config_location: String
}
<|endoftext|>


<commit_before>#![crate_name = "uu_uniq"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Chirag B Jadwani <chirag.jadwani@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 */

extern crate getopts;

#[macro_use]
extern crate uucore;

use getopts::{Matches, Options};
use std::fs::File;
use std::io::{stdin, stdout, BufRead, BufReader, BufWriter, Read, Write};
use std::path::Path;
use std::str::FromStr;

static NAME: &'static str = "uniq";
static VERSION: &'static str = env!("CARGO_PKG_VERSION");

#[derive(PartialEq)]
enum Delimiters {
    Prepend,
    Separate,
    None,
}

struct Uniq {
    repeats_only: bool,
    uniques_only: bool,
    all_repeated: bool,
    delimiters: Delimiters,
    show_counts: bool,
    skip_fields: Option<usize>,
    slice_start: Option<usize>,
    slice_stop: Option<usize>,
    ignore_case: bool,
    zero_terminated: bool,
}

impl Uniq {
    pub fn print_uniq<R: Read, W: Write>(
        &self,
        reader: &mut BufReader<R>,
        writer: &mut BufWriter<W>,
    ) {
        let mut lines: Vec<String> = vec![];
        let mut first_line_printed = false;
        let delimiters = &self.delimiters;
        let line_terminator = self.get_line_terminator();

        for io_line in reader.split(line_terminator) {
            let line = String::from_utf8(crash_if_err!(1, io_line)).unwrap();
            if !lines.is_empty() && self.cmp_key(&lines[0]) != self.cmp_key(&line) {
                let print_delimiter = delimiters == &Delimiters::Prepend
                    || (delimiters == &Delimiters::Separate && first_line_printed);
                first_line_printed |= self.print_lines(writer, &lines, print_delimiter);
                lines.truncate(0);
            }
            lines.push(line);
        }
        if !lines.is_empty() {
            let print_delimiter = delimiters == &Delimiters::Prepend
                || (delimiters == &Delimiters::Separate && first_line_printed);
            self.print_lines(writer, &lines, print_delimiter);
        }
    }

    fn skip_fields(&self, line: &str) -> String {
        if let Some(skip_fields) = self.skip_fields {
            if line.split_whitespace().count() > skip_fields {
                let mut field = 0;
                let mut i = 0;
                while field < skip_fields && i < line.len() {
                    while i < line.len() && line.chars().nth(i).unwrap().is_whitespace() {
                        i = i + 1;
                    }
                    while i < line.len() && !line.chars().nth(i).unwrap().is_whitespace() {
                        i = i + 1;
                    }
                    field = field + 1;
                }
                line[i..].to_owned()
            } else {
                "".to_owned()
            }
        } else {
            line[..].to_owned()
        }
    }

    fn get_line_terminator(&self) -> u8 {
        if self.zero_terminated {
            0
        } else {
            '\n' as u8
        }
    }

    fn cmp_key(&self, line: &str) -> String {
        let fields_to_check = &self.skip_fields(line);
        let len = fields_to_check.len();
        if len > 0 {
            fields_to_check
                .chars()
                .skip(self.slice_start.unwrap_or(0))
                .take(self.slice_stop.unwrap_or(len))
                .map(|c| match c {
                    'a'...'z' if self.ignore_case => ((c as u8) - 32) as char,
                    _ => c,
                })
                .collect()
        } else {
            fields_to_check.to_owned()
        }
    }

    fn print_lines<W: Write>(
        &self,
        writer: &mut BufWriter<W>,
        lines: &[String],
        print_delimiter: bool,
    ) -> bool {
        let mut first_line_printed = false;
        let mut count = if self.all_repeated { 1 } else { lines.len() };
        if lines.len() == 1 && !self.repeats_only || lines.len() > 1 && !self.uniques_only {
            self.print_line(writer, &lines[0], count, print_delimiter);
            first_line_printed = true;
            count += 1;
        }
        if self.all_repeated {
            for line in lines[1..].iter() {
                self.print_line(writer, line, count, print_delimiter && !first_line_printed);
                first_line_printed = true;
                count += 1;
            }
        }
        first_line_printed
    }

    fn print_line<W: Write>(
        &self,
        writer: &mut BufWriter<W>,
        line: &str,
        count: usize,
        print_delimiter: bool,
    ) {
        let line_terminator = self.get_line_terminator();

        if print_delimiter {
            crash_if_err!(1, writer.write_all(&[line_terminator]));
        }

        crash_if_err!(
            1,
            if self.show_counts {
                writer.write_all(format!("{:7} {}", count, line).as_bytes())
            } else {
                writer.write_all(line.as_bytes())
            }
        );
        crash_if_err!(1, writer.write_all(&[line_terminator]));
    }
}

fn opt_parsed<T: FromStr>(opt_name: &str, matches: &Matches) -> Option<T> {
    matches.opt_str(opt_name).map(|arg_str| {
        let opt_val: Option<T> = arg_str.parse().ok();
        opt_val.unwrap_or_else(|| crash!(1, "Invalid argument for {}: {}", opt_name, arg_str))
    })
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = Options::new();

    opts.optflag("c", "count", "prefix lines by the number of occurrences");
    opts.optflag("d", "repeated", "only print duplicate lines");
    opts.optflagopt(
        "D",
        "all-repeated",
        "print all duplicate lines delimit-method={none(default),prepend,separate} Delimiting is done with blank lines",
        "delimit-method"
    );
    opts.optopt(
        "f",
        "skip-fields",
        "avoid comparing the first N fields",
        "N",
    );
    opts.optopt(
        "s",
        "skip-chars",
        "avoid comparing the first N characters",
        "N",
    );
    opts.optopt(
        "w",
        "check-chars",
        "compare no more than N characters in lines",
        "N",
    );
    opts.optflag(
        "i",
        "ignore-case",
        "ignore differences in case when comparing",
    );
    opts.optflag("u", "unique", "only print unique lines");
    opts.optflag("z", "zero-terminated", "end lines with 0 byte, not newline");
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => crash!(1, "{}", f),
    };

    if matches.opt_present("help") {
        println!("{} {}", NAME, VERSION);
        println!("");
        println!("Usage:");
        println!("  {0} [OPTION]... [FILE]...", NAME);
        println!("");
        print!(
            "{}",
            opts.usage(
                "Filter adjacent matching lines from INPUT (or standard input),\n\
                 writing to OUTPUT (or standard output)."
            )
        );
        println!("");
        println!(
            "Note: '{0}' does not detect repeated lines unless they are adjacent.\n\
             You may want to sort the input first, or use 'sort -u' without '{0}'.\n",
            NAME
        );
    } else if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
    } else {
        let (in_file_name, out_file_name) = match matches.free.len() {
            0 => ("-".to_owned(), "-".to_owned()),
            1 => (matches.free[0].clone(), "-".to_owned()),
            2 => (matches.free[0].clone(), matches.free[1].clone()),
            _ => {
                crash!(1, "Extra operand: {}", matches.free[2]);
            }
        };
        let uniq = Uniq {
            repeats_only: matches.opt_present("repeated") || matches.opt_present("all-repeated"),
            uniques_only: matches.opt_present("unique"),
            all_repeated: matches.opt_present("all-repeated"),
            delimiters: match matches.opt_default("all-repeated", "none") {
                Some(ref opt_arg) if opt_arg != "none" => match &(*opt_arg.as_str()) {
                    "prepend" => Delimiters::Prepend,
                    "separate" => Delimiters::Separate,
                    _ => crash!(1, "Incorrect argument for all-repeated: {}", opt_arg),
                },
                _ => Delimiters::None,
            },
            show_counts: matches.opt_present("count"),
            skip_fields: opt_parsed("skip-fields", &matches),
            slice_start: opt_parsed("skip-chars", &matches),
            slice_stop: opt_parsed("check-chars", &matches),
            ignore_case: matches.opt_present("ignore-case"),
            zero_terminated: matches.opt_present("zero-terminated"),
        };
        uniq.print_uniq(
            &mut open_input_file(in_file_name),
            &mut open_output_file(out_file_name),
        );
    }
    0
}

fn open_input_file(in_file_name: String) -> BufReader<Box<Read + 'static>> {
    let in_file = if in_file_name == "-" {
        Box::new(stdin()) as Box<Read>
    } else {
        let path = Path::new(&in_file_name[..]);
        let in_file = File::open(&path);
        let r = crash_if_err!(1, in_file);
        Box::new(r) as Box<Read>
    };
    BufReader::new(in_file)
}

fn open_output_file(out_file_name: String) -> BufWriter<Box<Write + 'static>> {
    let out_file = if out_file_name == "-" {
        Box::new(stdout()) as Box<Write>
    } else {
        let path = Path::new(&out_file_name[..]);
        let in_file = File::create(&path);
        let w = crash_if_err!(1, in_file);
        Box::new(w) as Box<Write>
    };
    BufWriter::new(out_file)
}
<commit_msg>uniq: do not allocate a new string in skip_fields<commit_after>#![crate_name = "uu_uniq"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Chirag B Jadwani <chirag.jadwani@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 */

extern crate getopts;

#[macro_use]
extern crate uucore;

use getopts::{Matches, Options};
use std::fs::File;
use std::io::{stdin, stdout, BufRead, BufReader, BufWriter, Read, Write};
use std::path::Path;
use std::str::FromStr;

static NAME: &'static str = "uniq";
static VERSION: &'static str = env!("CARGO_PKG_VERSION");

#[derive(PartialEq)]
enum Delimiters {
    Prepend,
    Separate,
    None,
}

struct Uniq {
    repeats_only: bool,
    uniques_only: bool,
    all_repeated: bool,
    delimiters: Delimiters,
    show_counts: bool,
    skip_fields: Option<usize>,
    slice_start: Option<usize>,
    slice_stop: Option<usize>,
    ignore_case: bool,
    zero_terminated: bool,
}

impl Uniq {
    pub fn print_uniq<R: Read, W: Write>(
        &self,
        reader: &mut BufReader<R>,
        writer: &mut BufWriter<W>,
    ) {
        let mut lines: Vec<String> = vec![];
        let mut first_line_printed = false;
        let delimiters = &self.delimiters;
        let line_terminator = self.get_line_terminator();

        for io_line in reader.split(line_terminator) {
            let line = String::from_utf8(crash_if_err!(1, io_line)).unwrap();
            if !lines.is_empty() && self.cmp_key(&lines[0]) != self.cmp_key(&line) {
                let print_delimiter = delimiters == &Delimiters::Prepend
                    || (delimiters == &Delimiters::Separate && first_line_printed);
                first_line_printed |= self.print_lines(writer, &lines, print_delimiter);
                lines.truncate(0);
            }
            lines.push(line);
        }
        if !lines.is_empty() {
            let print_delimiter = delimiters == &Delimiters::Prepend
                || (delimiters == &Delimiters::Separate && first_line_printed);
            self.print_lines(writer, &lines, print_delimiter);
        }
    }

    fn skip_fields<'a>(&self, line: &'a str) -> &'a str {
        if let Some(skip_fields) = self.skip_fields {
            if line.split_whitespace().count() > skip_fields {
                let mut field = 0;
                let mut i = 0;
                while field < skip_fields && i < line.len() {
                    while i < line.len() && line.chars().nth(i).unwrap().is_whitespace() {
                        i = i + 1;
                    }
                    while i < line.len() && !line.chars().nth(i).unwrap().is_whitespace() {
                        i = i + 1;
                    }
                    field = field + 1;
                }
                &line[i..]
            } else {
                ""
            }
        } else {
            line
        }
    }

    fn get_line_terminator(&self) -> u8 {
        if self.zero_terminated {
            0
        } else {
            '\n' as u8
        }
    }

    fn cmp_key(&self, line: &str) -> String {
        let fields_to_check = self.skip_fields(line);
        let len = fields_to_check.len();
        if len > 0 {
            fields_to_check
                .chars()
                .skip(self.slice_start.unwrap_or(0))
                .take(self.slice_stop.unwrap_or(len))
                .map(|c| match c {
                    'a'...'z' if self.ignore_case => ((c as u8) - 32) as char,
                    _ => c,
                })
                .collect()
        } else {
            fields_to_check.to_owned()
        }
    }

    fn print_lines<W: Write>(
        &self,
        writer: &mut BufWriter<W>,
        lines: &[String],
        print_delimiter: bool,
    ) -> bool {
        let mut first_line_printed = false;
        let mut count = if self.all_repeated { 1 } else { lines.len() };
        if lines.len() == 1 && !self.repeats_only || lines.len() > 1 && !self.uniques_only {
            self.print_line(writer, &lines[0], count, print_delimiter);
            first_line_printed = true;
            count += 1;
        }
        if self.all_repeated {
            for line in lines[1..].iter() {
                self.print_line(writer, line, count, print_delimiter && !first_line_printed);
                first_line_printed = true;
                count += 1;
            }
        }
        first_line_printed
    }

    fn print_line<W: Write>(
        &self,
        writer: &mut BufWriter<W>,
        line: &str,
        count: usize,
        print_delimiter: bool,
    ) {
        let line_terminator = self.get_line_terminator();

        if print_delimiter {
            crash_if_err!(1, writer.write_all(&[line_terminator]));
        }

        crash_if_err!(
            1,
            if self.show_counts {
                writer.write_all(format!("{:7} {}", count, line).as_bytes())
            } else {
                writer.write_all(line.as_bytes())
            }
        );
        crash_if_err!(1, writer.write_all(&[line_terminator]));
    }
}

fn opt_parsed<T: FromStr>(opt_name: &str, matches: &Matches) -> Option<T> {
    matches.opt_str(opt_name).map(|arg_str| {
        let opt_val: Option<T> = arg_str.parse().ok();
        opt_val.unwrap_or_else(|| crash!(1, "Invalid argument for {}: {}", opt_name, arg_str))
    })
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = Options::new();

    opts.optflag("c", "count", "prefix lines by the number of occurrences");
    opts.optflag("d", "repeated", "only print duplicate lines");
    opts.optflagopt(
        "D",
        "all-repeated",
        "print all duplicate lines delimit-method={none(default),prepend,separate} Delimiting is done with blank lines",
        "delimit-method"
    );
    opts.optopt(
        "f",
        "skip-fields",
        "avoid comparing the first N fields",
        "N",
    );
    opts.optopt(
        "s",
        "skip-chars",
        "avoid comparing the first N characters",
        "N",
    );
    opts.optopt(
        "w",
        "check-chars",
        "compare no more than N characters in lines",
        "N",
    );
    opts.optflag(
        "i",
        "ignore-case",
        "ignore differences in case when comparing",
    );
    opts.optflag("u", "unique", "only print unique lines");
    opts.optflag("z", "zero-terminated", "end lines with 0 byte, not newline");
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => crash!(1, "{}", f),
    };

    if matches.opt_present("help") {
        println!("{} {}", NAME, VERSION);
        println!("");
        println!("Usage:");
        println!("  {0} [OPTION]... [FILE]...", NAME);
        println!("");
        print!(
            "{}",
            opts.usage(
                "Filter adjacent matching lines from INPUT (or standard input),\n\
                 writing to OUTPUT (or standard output)."
            )
        );
        println!("");
        println!(
            "Note: '{0}' does not detect repeated lines unless they are adjacent.\n\
             You may want to sort the input first, or use 'sort -u' without '{0}'.\n",
            NAME
        );
    } else if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
    } else {
        let (in_file_name, out_file_name) = match matches.free.len() {
            0 => ("-".to_owned(), "-".to_owned()),
            1 => (matches.free[0].clone(), "-".to_owned()),
            2 => (matches.free[0].clone(), matches.free[1].clone()),
            _ => {
                crash!(1, "Extra operand: {}", matches.free[2]);
            }
        };
        let uniq = Uniq {
            repeats_only: matches.opt_present("repeated") || matches.opt_present("all-repeated"),
            uniques_only: matches.opt_present("unique"),
            all_repeated: matches.opt_present("all-repeated"),
            delimiters: match matches.opt_default("all-repeated", "none") {
                Some(ref opt_arg) if opt_arg != "none" => match &(*opt_arg.as_str()) {
                    "prepend" => Delimiters::Prepend,
                    "separate" => Delimiters::Separate,
                    _ => crash!(1, "Incorrect argument for all-repeated: {}", opt_arg),
                },
                _ => Delimiters::None,
            },
            show_counts: matches.opt_present("count"),
            skip_fields: opt_parsed("skip-fields", &matches),
            slice_start: opt_parsed("skip-chars", &matches),
            slice_stop: opt_parsed("check-chars", &matches),
            ignore_case: matches.opt_present("ignore-case"),
            zero_terminated: matches.opt_present("zero-terminated"),
        };
        uniq.print_uniq(
            &mut open_input_file(in_file_name),
            &mut open_output_file(out_file_name),
        );
    }
    0
}

fn open_input_file(in_file_name: String) -> BufReader<Box<Read + 'static>> {
    let in_file = if in_file_name == "-" {
        Box::new(stdin()) as Box<Read>
    } else {
        let path = Path::new(&in_file_name[..]);
        let in_file = File::open(&path);
        let r = crash_if_err!(1, in_file);
        Box::new(r) as Box<Read>
    };
    BufReader::new(in_file)
}

fn open_output_file(out_file_name: String) -> BufWriter<Box<Write + 'static>> {
    let out_file = if out_file_name == "-" {
        Box::new(stdout()) as Box<Write>
    } else {
        let path = Path::new(&out_file_name[..]);
        let in_file = File::create(&path);
        let w = crash_if_err!(1, in_file);
        Box::new(w) as Box<Write>
    };
    BufWriter::new(out_file)
}
<|endoftext|>


<commit_before>#[macro_use] extern crate tera;

use tera::Tera;
use tera::Context;

extern crate iron;
extern crate router;

use iron::prelude::*;
use router::Router;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};

#[derive(Default,Clone)]
struct Spaceship {
    cache: Arc<Mutex<HashMap<String, String>>>,
    tera: Arc<Mutex<Tera>>,
}

impl Spaceship {
	fn tera<'a>(&'a self) -> &'a Arc<Mutex<Tera>> {
		&self.tera
	}
}

fn index(_: &mut Request, spaceship: &Spaceship) -> IronResult<Response> {
	let mut ctx = Context::new();
	ctx.add("title", &"spacship!");
	ctx.add("body", &"it's working");

	let obj = match spaceship.tera().lock() {
        Ok(x) => x,
        Err(_) => return Ok(Response::with((iron::status::InternalServerError)))
    };
	let content = obj.render("templates/index.html", ctx).unwrap();
	return Ok(Response::with((iron::status::Ok, content)));
}

fn main() {
    let spaceship = Spaceship{tera: Arc::new(Mutex::new(compile_templates!("templates/**/*"))), ..Default::default()};
    let mut router = Router::new();

    router.get("/", move |request: &mut Request| index(request, &spaceship), "magicid");

    Iron::new(router).http("localhost:8080").unwrap();
}
<commit_msg>More error handling<commit_after>#[macro_use] extern crate tera;

use tera::Tera;
use tera::Context;

extern crate iron;
extern crate router;

use iron::prelude::*;
use router::Router;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};

#[derive(Default,Clone)]
struct Spaceship {
    cache: Arc<Mutex<HashMap<String, String>>>,
    tera: Arc<Mutex<Tera>>,
}

impl Spaceship {
	fn tera<'a>(&'a self) -> &'a Arc<Mutex<Tera>> {
		&self.tera
	}
}

fn index(_: &mut Request, spaceship: &Spaceship) -> IronResult<Response> {
	let mut ctx = Context::new();
	ctx.add("title", &"spaceship!");
	ctx.add("body", &"it's working");

	let obj = match spaceship.tera().lock() {
        Ok(x) => x,
        Err(_) => return Ok(Response::with((iron::status::InternalServerError)))
    };
	let content = match obj.render("index.html", ctx) {
		Ok(x) => x,
		Err(_) => return Ok(Response::with((iron::status::InternalServerError)))
	};
	return Ok(Response::with((iron::status::Ok, content)));
}

fn main() {
    let spaceship = Spaceship{tera: Arc::new(Mutex::new(compile_templates!("templates/**/*"))), ..Default::default()};
    let mut router = Router::new();

    router.get("/", move |request: &mut Request| index(request, &spaceship), "magicid");

    Iron::new(router).http("localhost:8080").unwrap();
}
<|endoftext|>