~krathalan/wtwitch-rust

da2ffebd828927738517dd2c8276f0f2b3750bf5 — Hunter Peavey 4 years ago eb82d39
Add more deps; fully implement [h] and [v] commands; use user config player and quality for [w] command
4 files changed, 187 insertions(+), 12 deletions(-)

M Cargo.lock
M Cargo.toml
M TODO
M src/main.rs
M Cargo.lock => Cargo.lock +103 -0
@@ 1,6 1,17 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
 "hermit-abi",
 "libc",
 "winapi",
]

[[package]]
name = "autocfg"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 19,6 30,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"

[[package]]
name = "chrono"
version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "942f72db697d8767c22d46a598e01f2d3b475501ea43d0db4f16d90259182d0b"
dependencies = [
 "num-integer",
 "num-traits",
 "time",
]

[[package]]
name = "colored"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd"
dependencies = [
 "atty",
 "lazy_static",
 "winapi",
]

[[package]]
name = "curl"
version = "0.4.31"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 50,6 83,21 @@ dependencies = [
]

[[package]]
name = "hermit-abi"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9"
dependencies = [
 "libc",
]

[[package]]
name = "itoa"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"

[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 84,6 132,25 @@ dependencies = [
]

[[package]]
name = "num-integer"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b"
dependencies = [
 "autocfg",
 "num-traits",
]

[[package]]
name = "num-traits"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
dependencies = [
 "autocfg",
]

[[package]]
name = "openssl-probe"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 115,6 182,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"

[[package]]
name = "ryu"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"

[[package]]
name = "schannel"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 125,6 198,23 @@ dependencies = [
]

[[package]]
name = "serde"
version = "1.0.115"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e54c9a88f2da7238af84b5101443f0c0d0a3bbdc455e34a5c9497b1903ed55d5"

[[package]]
name = "serde_json"
version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c"
dependencies = [
 "itoa",
 "ryu",
 "serde",
]

[[package]]
name = "socket2"
version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 137,6 227,16 @@ dependencies = [
]

[[package]]
name = "time"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
dependencies = [
 "libc",
 "winapi",
]

[[package]]
name = "vcpkg"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 168,5 268,8 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
name = "wtwitch-rust"
version = "0.1.0"
dependencies = [
 "chrono",
 "colored",
 "curl",
 "serde_json",
]

M Cargo.toml => Cargo.toml +4 -1
@@ 4,7 4,10 @@ version = "0.1.0"
authors = ["Hunter Peavey <srht@krathalan.net>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde_json = "1.0"
chrono = "0.4"
colored = "2.0.0"

[dependencies.curl]
version = "0.4.31"

M TODO => TODO +9 -5
@@ 10,13 10,17 @@ Commands:
  - player
  - quality
  - block
    - implemented: adding to blocklist, printing to blocklist
    - unimplemented: remove from blocklist
  - version
  - help

Misc:
  - colors
  - debug/logging facilities
  - translations
  - environment.sh?
\ No newline at end of file
  - environment.sh?

==============
   100% DONE
==============

Commands:
  - help
  - version
\ No newline at end of file

M src/main.rs => src/main.rs +71 -6
@@ 2,8 2,11 @@ use std::env;
use std::fs;
use std::io::prelude::*;
use std::path::Path;
use chrono::prelude::*;

const PROGRAM_NAME: &str = "wtwitch";
const PROGRAM_VERSION: &str = "0.1.0";
const PROGRAM_CONTRIBUTORS: &str = "krathalan, nycko123, Léo Villeveygoux, René de Hesselle";

// Twitch API information
// This API key is intended to be used for wtwitch only -- do not use this API


@@ 50,8 53,9 @@ fn main() {
        panic!("Couldn't create config directory {}: {}", cache_path, why);
    }

    // Load data
    // Load user config
    let blocklist = load_blocklist(&blocklist_file);
    let config = load_config(&config_file);

    // Parse user command
    let command = &cli_args[1].chars().next().unwrap();


@@ 60,7 64,8 @@ fn main() {

    match command {
        'b' => block(cli_args, blocklist_file, blocklist),
        'w' => watch(cli_args),
        'w' => watch(cli_args[2].clone(), config["player"].to_string(), config["quality"].to_string()),
        'v' => version(),
        _ => help()
    }
}


@@ 107,6 112,32 @@ fn load_blocklist(path_to_blocklist: &str) -> String {
    }
}

// TODO: if config file doesn't exist yet, seed it with the default config
fn load_config(path_to_config: &str) -> serde_json::Value {
    // Load config file into string
    let path = Path::new(&path_to_config);

    // Create config file if not exists
    if !path.exists() {
        if let Err(why) = fs::File::create(&path) {
            panic!("Couldn't create config file {}: {}", path_to_config, why);
        }
    }

    // Open the path in read-only mode
    let mut file = match fs::File::open(&path) {
        Err(why) => panic!("couldn't open {}: {}", path.display(), why),
        Ok(file) => file,
    };

    // Read the file contents into a string
    let mut s = String::new();
    file.read_to_string(&mut s).unwrap();

    // Convert string into serde_json::Value
    serde_json::from_str(&s).unwrap()
}

// Commands

// TODO: Remove streamer if it's already on the blocklist


@@ 143,17 174,51 @@ fn block(args: Vec<String>, blocklist_file: String, blocklist: String) {
}

fn help() {
    unimplemented!("TODO: Implement print help")
    println!("{} - terminal user interface for Twitch

    => [w]atch [name]      - Watch [name] streamer.
    => [s]ub [name(s)]     - Subscribe to [name] streamer.
                             You can subscribe to multiple streamers in one command.
    => [u]nsub [name(s)]   - Unsubscribe from [name] streamer.
                             You can unsubscribe from multiple streamers in one command.
    => [c]heck             - View your settings and the status of streamers you are
                             subscribed to.
    => [e] [search-term]   - Search games/categories for [search-term].
    => [n] [search-term]   - Search streamers/channels for [search-term].
    => [g]ame [name]       - View the top streamers for [name] game/category.
    => [t]op               - View the top games and streamers on Twitch.
    => [l]                 - Toggle the usage of colors in wtwitch output.
    => [p]layer [program]  - Change the player program that gets passed to streamlink.
    => [q]uality [quality] - Change the video quality that gets passed to streamlink.
    => [b]lock [name(s)]   - Block [name] streamer, preventing them from appearing in any
                             output. You can block multiple streamers in one command.
    => [v]ersion           - Print the current version of wtwitch.
    => [h]elp              - Print this help.
    
    See \"man {}\" or https://krathalan.net/wtwitch.html for more information.", PROGRAM_NAME, PROGRAM_NAME);
}

fn version() {
    // Get current year
    let local_time : DateTime<Local> = Local::now();

    println!("{} v{}

    Copyright (C) {} 2019-{}
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.", PROGRAM_NAME, PROGRAM_VERSION, PROGRAM_CONTRIBUTORS, local_time.year());
}

// TODO: use user player and quality settings, fork to background
fn watch(args: Vec<String>) {
// TODO: check to make sure user player is installed and openable
//       check to make sure streamer is online
//       send notification if stream fails or cannot be opened
fn watch(streamer: String, player: String, quality: String) {
    use std::process;

    if cfg!(target_os = "windows") {
        panic!("{} does not yet support launching a stream on Windows", PROGRAM_NAME);
    } else {
        let streamlink_command = format!("streamlink -p mpv --twitch-disable-ads \"https://www.twitch.tv/{}\" best", args[2]);
        let streamlink_command = format!("streamlink -p {} --twitch-disable-ads \"https://www.twitch.tv/{}\" {}", player, streamer, quality);
        process::Command::new("sh")
                .arg("-c")
                .arg(streamlink_command)