M4 partial — Search shipped, browse UI live on the Pi
Sidecar gains the 'search' op via rustypipe's query().search::<VideoItem,_>() — returns id, title, channel, duration, thumbnails, view_count. Default limit 25. Addon root directory is no longer a placeholder notification: - 'Search' entry → ?action=search → keyboard input → result list → tap a result to play (each result is a play-action plugin URL). - 'Play by URL' entry → ?action=play_by_url → keyboard input → PlayMedia. - ?action=search also accepts inline 'q=…' so JSON-RPC clients can drive search without going through the on-TV keyboard (useful for share-to-TV from phone + tests). - Result labels formatted as 'Title · Channel · Duration · Views', with thumbnail + Kodi InfoLabels for richer skin views. Verified via Files.GetDirectory JSON-RPC: 19 well-formatted LTT results returned for query 'linus tech tips'. Pending M4: channel browse, playlist browse, pagination, search history. Addon version 0.0.6.
This commit is contained in:
parent
d0316ba311
commit
6a10c0045c
5 changed files with 211 additions and 13 deletions
|
|
@ -43,6 +43,17 @@ enum Request {
|
|||
#[serde(default = "sponsor::default_categories")]
|
||||
categories: Vec<String>,
|
||||
},
|
||||
/// Search YouTube for videos. Returns a list of VideoItem entries
|
||||
/// (id, name, channel_name, channel_id, duration, thumbnail, views).
|
||||
Search {
|
||||
query: String,
|
||||
#[serde(default = "default_search_limit")]
|
||||
limit: u32,
|
||||
},
|
||||
}
|
||||
|
||||
fn default_search_limit() -> u32 {
|
||||
25
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
|
|
@ -148,6 +159,10 @@ async fn handle_line(line: &str) -> Response {
|
|||
Ok(v) => Response::ok(v),
|
||||
Err(e) => Response::err(ErrorKind::Network, format!("sponsorblock: {e}")),
|
||||
},
|
||||
Request::Search { query, limit } => match resolve::search(&query, limit).await {
|
||||
Ok(v) => Response::ok(v),
|
||||
Err(e) => e.into(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,40 @@ use serde_json::Value;
|
|||
|
||||
use crate::{run_yt_dlp, HandlerError};
|
||||
|
||||
/// Search YouTube via rustypipe. Returns `SearchResult<VideoItem>` as JSON —
|
||||
/// the Python addon picks the fields it needs (id, name, channel, duration,
|
||||
/// thumbnail, view_count, …) to build a Kodi directory listing.
|
||||
pub(crate) async fn search(query: &str, limit: u32) -> Result<Value, HandlerError> {
|
||||
use rustypipe::client::RustyPipe;
|
||||
use rustypipe::model::VideoItem;
|
||||
|
||||
let rp = RustyPipe::new();
|
||||
let result = rp
|
||||
.query()
|
||||
.search::<VideoItem, _>(query)
|
||||
.await
|
||||
.map_err(|e| classify_rustypipe_error(&e))?;
|
||||
|
||||
// SearchResult<VideoItem>.items is a Paginator<VideoItem> — take the first
|
||||
// page truncated to `limit` items.
|
||||
let items_json: Vec<Value> = result
|
||||
.items
|
||||
.items
|
||||
.iter()
|
||||
.take(limit as usize)
|
||||
.filter_map(|v| serde_json::to_value(v).ok())
|
||||
.collect();
|
||||
|
||||
tracing::info!(query, count = items_json.len(), "search ok via rustypipe");
|
||||
|
||||
Ok(serde_json::json!({
|
||||
"source": "rustypipe",
|
||||
"query": query,
|
||||
"items": items_json,
|
||||
"corrected_query": result.corrected_query,
|
||||
}))
|
||||
}
|
||||
|
||||
/// DASH-ready resolve: returns rustypipe's full `video_only_streams` +
|
||||
/// `audio_streams` arrays + `details`. The Python addon builds an MPD
|
||||
/// from these and hands it to inputstream.adaptive — unlocks 1080p+ via
|
||||
|
|
|
|||
Reference in a new issue