From 0bf50a27a2a04bb70bf8115facc4a6cdf959e126 Mon Sep 17 00:00:00 2001 From: Muhammad Nauman Raza Date: Wed, 29 May 2024 10:57:26 +0100 Subject: [PATCH] feat: watch the selected anime in list --- src/api.rs | 28 ++++++++++++++++++++++++++-- src/handler.rs | 45 ++++++++++++++++++++++++++++++++++----------- src/ui.rs | 23 +++++++++++------------ 3 files changed, 71 insertions(+), 25 deletions(-) diff --git a/src/api.rs b/src/api.rs index dcf96fb..3421333 100644 --- a/src/api.rs +++ b/src/api.rs @@ -1,12 +1,12 @@ use serde::{Deserialize, Serialize}; +use std::fs::File; +use std::io::prelude::*; #[derive(Serialize, Deserialize, Debug)] #[allow(non_snake_case)] pub struct SearchResult { pub id: String, pub title: String, - pub url: String, - pub image: String, pub releaseDate: String, pub subOrDub: String, } @@ -18,6 +18,19 @@ pub struct Search { pub results: Vec, } +#[derive(Serialize, Deserialize, Debug)] +#[allow(non_snake_case)] +pub struct Quality { + pub url: String, + pub quality: String, +} +#[derive(Serialize, Deserialize, Debug)] +#[allow(non_snake_case)] +pub struct Watch { + pub sources: Vec, + pub download: String, +} + pub async fn query_anime(query: String) -> Result { reqwest::get(format!( "https://altoku-api.vercel.app/anime/gogoanime/{}?page=1", @@ -28,3 +41,14 @@ pub async fn query_anime(query: String) -> Result { .json::() .await } + +pub async fn get_url(id: String) -> Result { + reqwest::get(format!( + "https://altoku-api.vercel.app/anime/gogoanime/watch/{}", + id + )) + .await + .expect("Failed to get from API") + .json::() + .await +} diff --git a/src/handler.rs b/src/handler.rs index 45f7a26..12a54c6 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -1,10 +1,12 @@ -use crate::api::query_anime; +use crate::api::{get_url, query_anime}; use crate::app::{App, AppResult, ResultList}; use crate::handler::KeyCode::*; use crossterm::event::*; use tui_input::backend::crossterm::EventHandler; +use std::process::Command; + /// Handles the key events and updates the state of [`App`]. pub async fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> { match key_event { @@ -24,28 +26,49 @@ pub async fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult< code: KeyCode::Enter, .. } => { - app.list = ResultList { - state: app.list.state.clone(), - items: query_anime(app.input.to_string()).await.unwrap().results, - last_selected: app.list.last_selected, - }; - app.chunk = 2; - app.editing = false; - app.input.reset(); + if app.editing { + app.list = ResultList { + state: app.list.state.clone(), + items: query_anime(app.input.to_string()).await.unwrap().results, + last_selected: app.list.last_selected, + }; + app.chunk = 2; + app.editing = false; + app.input.reset(); + } } _ => { - if app.editing == true { + if app.editing { app.input.handle_event(&Event::Key(key_event)); } else { } } } - if app.editing != true { + if !app.editing { match key_event.code { Char('j') | Down => app.list.next(), Char('k') | Up => app.list.previous(), Char('g') => app.go_top(), Char('G') => app.go_bottom(), + KeyCode::Enter => { + if let Some(i) = app.list.state.selected() { + let mut url = String::new(); + for source in get_url(format!("{}-episode-1", app.list.items[i].id.clone())) + .await + .unwrap() + .sources + { + if source.quality == "1080p" { + url = source.url + } + } + + let output = Command::new("mpv") + .arg(format!("{}", url)) + .output() + .expect("Failed to execute `mpv`"); + } + } _ => {} } } diff --git a/src/ui.rs b/src/ui.rs index 22096fe..86c3a34 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -1,9 +1,4 @@ -use ratatui::{ - prelude::*, - style::Style, - widgets::*, - Frame, -}; +use ratatui::{prelude::*, style::Style, widgets::*, Frame}; use crate::app::App; @@ -58,12 +53,16 @@ pub fn render(app: &mut App, frame: &mut Frame) { } let list = List::new(results) - .block(Block::bordered().title("Search Results").style(match app.editing { - true => Style::default(), - false => Style::default().yellow().bold(), - })) - .style(Style::default().white()) - .highlight_style(Style::default().add_modifier(Modifier::ITALIC)) + .block( + Block::bordered() + .title("Search Results") + .style(match app.editing { + true => Style::default(), + false => Style::default().yellow().bold(), + }), + ) + .style(Style::default().white().not_bold()) + .highlight_style(Style::default().add_modifier(Modifier::BOLD)) .highlight_symbol("┃ ") .repeat_highlight_symbol(true) .direction(ListDirection::TopToBottom);