feat: watch the selected anime in list

This commit is contained in:
Muhammad Nauman Raza 2024-05-29 10:57:26 +01:00
parent 8da4398c48
commit 0bf50a27a2
3 changed files with 71 additions and 25 deletions

View file

@ -1,12 +1,12 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fs::File;
use std::io::prelude::*;
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub struct SearchResult { pub struct SearchResult {
pub id: String, pub id: String,
pub title: String, pub title: String,
pub url: String,
pub image: String,
pub releaseDate: String, pub releaseDate: String,
pub subOrDub: String, pub subOrDub: String,
} }
@ -18,6 +18,19 @@ pub struct Search {
pub results: Vec<SearchResult>, pub results: Vec<SearchResult>,
} }
#[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<Quality>,
pub download: String,
}
pub async fn query_anime(query: String) -> Result<Search, reqwest::Error> { pub async fn query_anime(query: String) -> Result<Search, reqwest::Error> {
reqwest::get(format!( reqwest::get(format!(
"https://altoku-api.vercel.app/anime/gogoanime/{}?page=1", "https://altoku-api.vercel.app/anime/gogoanime/{}?page=1",
@ -28,3 +41,14 @@ pub async fn query_anime(query: String) -> Result<Search, reqwest::Error> {
.json::<Search>() .json::<Search>()
.await .await
} }
pub async fn get_url(id: String) -> Result<Watch, reqwest::Error> {
reqwest::get(format!(
"https://altoku-api.vercel.app/anime/gogoanime/watch/{}",
id
))
.await
.expect("Failed to get from API")
.json::<Watch>()
.await
}

View file

@ -1,10 +1,12 @@
use crate::api::query_anime; use crate::api::{get_url, query_anime};
use crate::app::{App, AppResult, ResultList}; use crate::app::{App, AppResult, ResultList};
use crate::handler::KeyCode::*; use crate::handler::KeyCode::*;
use crossterm::event::*; use crossterm::event::*;
use tui_input::backend::crossterm::EventHandler; use tui_input::backend::crossterm::EventHandler;
use std::process::Command;
/// Handles the key events and updates the state of [`App`]. /// Handles the key events and updates the state of [`App`].
pub async fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> { pub async fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
match key_event { match key_event {
@ -24,28 +26,49 @@ pub async fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<
code: KeyCode::Enter, code: KeyCode::Enter,
.. ..
} => { } => {
app.list = ResultList { if app.editing {
state: app.list.state.clone(), app.list = ResultList {
items: query_anime(app.input.to_string()).await.unwrap().results, state: app.list.state.clone(),
last_selected: app.list.last_selected, items: query_anime(app.input.to_string()).await.unwrap().results,
}; last_selected: app.list.last_selected,
app.chunk = 2; };
app.editing = false; app.chunk = 2;
app.input.reset(); app.editing = false;
app.input.reset();
}
} }
_ => { _ => {
if app.editing == true { if app.editing {
app.input.handle_event(&Event::Key(key_event)); app.input.handle_event(&Event::Key(key_event));
} else { } else {
} }
} }
} }
if app.editing != true { if !app.editing {
match key_event.code { match key_event.code {
Char('j') | Down => app.list.next(), Char('j') | Down => app.list.next(),
Char('k') | Up => app.list.previous(), Char('k') | Up => app.list.previous(),
Char('g') => app.go_top(), Char('g') => app.go_top(),
Char('G') => app.go_bottom(), 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`");
}
}
_ => {} _ => {}
} }
} }

View file

@ -1,9 +1,4 @@
use ratatui::{ use ratatui::{prelude::*, style::Style, widgets::*, Frame};
prelude::*,
style::Style,
widgets::*,
Frame,
};
use crate::app::App; use crate::app::App;
@ -58,12 +53,16 @@ pub fn render(app: &mut App, frame: &mut Frame) {
} }
let list = List::new(results) let list = List::new(results)
.block(Block::bordered().title("Search Results").style(match app.editing { .block(
true => Style::default(), Block::bordered()
false => Style::default().yellow().bold(), .title("Search Results")
})) .style(match app.editing {
.style(Style::default().white()) true => Style::default(),
.highlight_style(Style::default().add_modifier(Modifier::ITALIC)) false => Style::default().yellow().bold(),
}),
)
.style(Style::default().white().not_bold())
.highlight_style(Style::default().add_modifier(Modifier::BOLD))
.highlight_symbol("") .highlight_symbol("")
.repeat_highlight_symbol(true) .repeat_highlight_symbol(true)
.direction(ListDirection::TopToBottom); .direction(ListDirection::TopToBottom);