aboutsummaryrefslogtreecommitdiffstats
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/yt/Cargo.toml1
-rw-r--r--crates/yt/src/commands/comments/implm/mod.rs15
-rw-r--r--crates/yt/src/commands/comments/mod.rs6
-rw-r--r--crates/yt/src/commands/description/implm.rs16
-rw-r--r--crates/yt/src/commands/description/mod.rs6
-rw-r--r--crates/yt/src/commands/mod.rs29
-rw-r--r--crates/yt/src/commands/show/implm/mod.rs100
7 files changed, 112 insertions, 61 deletions
diff --git a/crates/yt/Cargo.toml b/crates/yt/Cargo.toml
index 12456fe..95f8270 100644
--- a/crates/yt/Cargo.toml
+++ b/crates/yt/Cargo.toml
@@ -50,6 +50,7 @@ url.workspace = true
uu_fmt.workspace = true
xdg = "3.0.0"
yt_dlp.workspace = true
+reqwest = "0.12.22"
[[bin]]
name = "yt"
diff --git a/crates/yt/src/commands/comments/implm/mod.rs b/crates/yt/src/commands/comments/implm/mod.rs
deleted file mode 100644
index 1c02718..0000000
--- a/crates/yt/src/commands/comments/implm/mod.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-use crate::{
- app::App, commands::comments::CommentsCommand, output::display_less, storage::db::video::Video,
-};
-
-use anyhow::Result;
-
-impl CommentsCommand {
- pub(crate) async fn implm(self, app: &App) -> Result<()> {
- let comments = Video::get_current_comments(app).await?;
-
- display_less(comments.render(app.config.global.display_colors))?;
-
- Ok(())
- }
-}
diff --git a/crates/yt/src/commands/comments/mod.rs b/crates/yt/src/commands/comments/mod.rs
deleted file mode 100644
index d87c75d..0000000
--- a/crates/yt/src/commands/comments/mod.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-use clap::Parser;
-
-mod implm;
-
-#[derive(Parser, Debug)]
-pub(crate) struct CommentsCommand {}
diff --git a/crates/yt/src/commands/description/implm.rs b/crates/yt/src/commands/description/implm.rs
deleted file mode 100644
index 7c39b1c..0000000
--- a/crates/yt/src/commands/description/implm.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-use crate::{
- app::App, commands::description::DescriptionCommand, output::display_fmt_and_less,
- storage::db::video::Video,
-};
-
-use anyhow::Result;
-
-impl DescriptionCommand {
- pub(crate) async fn implm(self, app: &App) -> Result<()> {
- let description = Video::get_current_description(app).await?;
-
- display_fmt_and_less(&description)?;
-
- Ok(())
- }
-}
diff --git a/crates/yt/src/commands/description/mod.rs b/crates/yt/src/commands/description/mod.rs
deleted file mode 100644
index b5b2a10..0000000
--- a/crates/yt/src/commands/description/mod.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-use clap::Parser;
-
-mod implm;
-
-#[derive(Parser, Debug)]
-pub(crate) struct DescriptionCommand {}
diff --git a/crates/yt/src/commands/mod.rs b/crates/yt/src/commands/mod.rs
index a6aa2af..ee8b29c 100644
--- a/crates/yt/src/commands/mod.rs
+++ b/crates/yt/src/commands/mod.rs
@@ -7,10 +7,10 @@ use tokio::runtime::Runtime;
use crate::{
app::App,
commands::{
- comments::CommentsCommand, config::ConfigCommand, database::DatabaseCommand,
- description::DescriptionCommand, download::DownloadCommand, playlist::PlaylistCommand,
- select::SelectCommand, status::StatusCommand, subscriptions::SubscriptionCommand,
- update::UpdateCommand, videos::VideosCommand, watch::WatchCommand,
+ config::ConfigCommand, database::DatabaseCommand, download::DownloadCommand,
+ playlist::PlaylistCommand, select::SelectCommand, show::ShowCommand, status::StatusCommand,
+ subscriptions::SubscriptionCommand, update::UpdateCommand, videos::VideosCommand,
+ watch::WatchCommand,
},
config::Config,
storage::db::subscription::Subscriptions,
@@ -18,13 +18,12 @@ use crate::{
pub(crate) mod implm;
-mod comments;
mod config;
mod database;
-mod description;
mod download;
mod playlist;
mod select;
+mod show;
mod status;
mod subscriptions;
mod update;
@@ -33,12 +32,6 @@ mod watch;
#[derive(Subcommand, Debug)]
pub(crate) enum Command {
- /// Display the comments of the currently playing video.
- Comments {
- #[command(flatten)]
- cmd: CommentsCommand,
- },
-
/// Show, the configuration options in effect.
Config {
#[command(flatten)]
@@ -52,12 +45,6 @@ pub(crate) enum Command {
cmd: DatabaseCommand,
},
- /// Display the description of the currently playing video
- Description {
- #[command(flatten)]
- cmd: DescriptionCommand,
- },
-
/// Download and cache URLs
Download {
#[command(flatten)]
@@ -76,6 +63,12 @@ pub(crate) enum Command {
cmd: Option<SelectCommand>,
},
+ /// Show things about the currently playing video.
+ Show {
+ #[command(subcommand)]
+ cmd: ShowCommand,
+ },
+
/// Show, which videos have been selected to be watched (and their cache status)
Status {
#[command(flatten)]
diff --git a/crates/yt/src/commands/show/implm/mod.rs b/crates/yt/src/commands/show/implm/mod.rs
new file mode 100644
index 0000000..158a25b
--- /dev/null
+++ b/crates/yt/src/commands/show/implm/mod.rs
@@ -0,0 +1,100 @@
+use std::{
+ fs::{self, OpenOptions},
+ io,
+ process::Command,
+};
+
+use crate::{
+ app::App,
+ commands::ShowCommand,
+ output::{display_fmt_and_less, display_less},
+ storage::db::video::Video,
+};
+
+use anyhow::{Context, Result, anyhow, bail};
+use tempfile::Builder;
+use tokio_util::bytes::Buf;
+
+impl ShowCommand {
+ pub(crate) async fn implm(&self, app: &App) -> Result<()> {
+ match self {
+ ShowCommand::Description {} => {
+ let description = Video::get_current_description(app).await?;
+
+ display_fmt_and_less(&description)?;
+ }
+ ShowCommand::Comments {} => {
+ let comments = Video::get_current_comments(app).await?;
+
+ display_less(comments.render(app.config.global.display_colors))?;
+ }
+ ShowCommand::Thumbnail {} => {
+ let video = Video::currently_focused(app).await?.ok_or(anyhow!(
+ "You need to have a current video to display its info"
+ ))?;
+
+ if let Some(url) = video.thumbnail_url {
+ let response = reqwest::get(url.clone())
+ .await
+ .with_context(|| format!("Failed to download thumbnail from url: {url}"))?;
+ let response = response
+ .error_for_status()
+ .context("Failed to download thumbnail")?;
+
+ let (tmp_path, mut tmp) = {
+ let file = Builder::new().prefix("yt-thumbnail-download").tempfile()?;
+ let (_, path) = file.keep()?;
+ let new_file = OpenOptions::new()
+ .write(true)
+ .read(false)
+ .create(false)
+ .truncate(true)
+ .open(&path)?;
+
+ (path, new_file)
+ };
+
+ let mut content = response.bytes().await?.reader();
+ io::copy(&mut content, &mut tmp)?;
+
+ let status = Command::new(app.config.commands.image_show.first())
+ .args(app.config.commands.image_show.tail())
+ .arg(tmp_path.as_os_str())
+ .status()
+ .context("Failed to spawn image show command")?;
+
+ if !status.success() {
+ bail!(
+ "{:?} failed with status: {}",
+ &app.config.commands.image_show.join(" "),
+ status
+ );
+ }
+
+ fs::remove_file(&tmp_path).with_context(|| {
+ format!(
+ "Failed to cleanup downloaded thumbnail image at: {}",
+ tmp_path.display()
+ )
+ })?;
+ } else {
+ eprintln!("Current video does not have a thumbnail.");
+ }
+ }
+ ShowCommand::Info {} => {
+ let video = Video::currently_focused(app).await?.ok_or(anyhow!(
+ "You need to have a current video to display its info"
+ ))?;
+
+ display_less(
+ video
+ .to_info_display(app, None)
+ .await
+ .context("Failed to format video")?,
+ )?;
+ }
+ }
+
+ Ok(())
+ }
+}