
I made a CLI tool in Rust to watch the World Cup without being discovered while working.
Hello, @ekusiadadus.
Japan has made it to the finals after unexpectedly finishing first in the group of death.
I want to watch the World Cup: …… But if they find out while I’m at work, they’ll get mad at me: ……
I made a CLI tool to watch the World Cup during work in such a case.
https://github.com/ekusiadadus/samuraicup
(We lost by PK just now 😢)
How to use

🌸 World Cup 2022 CLI for Japanese football fans 🌸 Usage: samuraicli <COMMAND> Commands: real ⚽Check the World Cup in real time search 🥅Get World Cup tweets keisuke 📣Get Keisuke Honda's movement help Print this message or the help of the given subcommand(s) Options: -h, --help Print help information
Video moved during the Croatia match on December 6

How to make
It is designed, but the part to get tweets is made in a clean architecture way. (It may be quite quirky.)

The CLI part and so on are simply written in main.rs
.
I used clap to create the CLI tools.
Characters are colored randomly using owo-colors.
1. using Twitter API
We used Twitter API to retrieve World Cup tweets.
I wrote about this area in Analyzing Twitter with BigQuery and JupyterLab ~ Twitter API v2 ~. Please refer to that article.
2. creating a CLI tool in Rust
I used clap to create a CLI tool.
You can pass options in a nice way as follows.
fn cli() -> Command { Command::new("samuraicup") .about("🌸 World Cup 2022 CLI for Japanese football fans 🌸") .subcommand_required(true) .arg_required_else_help(true) .allow_external_subcommands(true) .subcommand(Command::new("real").about("⚽ worldcaps in real time")) .subcommand(Command::new("search").about("🥅Get World Cup tweets")) .subcommand(Command::new("keisuke").about("📣Get Keisuke Honda's movement")) }
The value received here is branched out with match
to execute the process.
When I wrote the process of receiving tweets, I wrote asynchronous processing using tokio.
This area is written in a clean architecture style (I think).
async fn main() -> Result<(), Box<dyn std::error::Error>> { std::env::set_var("RUST_LOG", "info"); std::env::set_var("RUST_BACKTRACE", "1"); dotenv().ok(); let db_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set"); let db_pool_size = std::env::var("DATABASE_POOL_SIZE") .ok() .and_then(|it| it.parse().ok()) .unwrap_or(5); let bearer_token = std::env::var("BEARER_TOKEN").expect("BEARER_TOKEN not set"); let app = initializer::new(initializer::Config { db_url: db_url, db_pool_size: db_pool_size, bearer_token: bearer_token, }) .await; app.infras .ensure_initialized() .await .expect("Infra initialization error"); let matches = cli().get_matches();
Summary
Now I can watch the World Cup at work without being detected!
… Oh, it doesn’t matter because I’m remote.
Let’s watch TV.
I’ll be cheering for England.
Translated with www.DeepL.com/Translator (free version)