fix: resolve omitted search handles before saving channels
This commit is contained in:
@@ -196,6 +196,25 @@ pub fn full_description(output: &str, expected_id: &str) -> Result<String, Strin
|
||||
Ok(description)
|
||||
}
|
||||
|
||||
pub fn channel_handle(output: &str, expected_id: &str) -> Result<String, String> {
|
||||
#[derive(Deserialize)]
|
||||
struct Channel {
|
||||
channel_id: String,
|
||||
uploader_id: Option<String>,
|
||||
}
|
||||
let channel: Channel = serde_json::from_str(output)
|
||||
.map_err(|error| format!("Invalid channel metadata: {error}"))?;
|
||||
if channel.channel_id != expected_id {
|
||||
return Err("Channel metadata did not match the requested channel".into());
|
||||
}
|
||||
let handle = channel
|
||||
.uploader_id
|
||||
.filter(|handle| handle.starts_with('@'))
|
||||
.ok_or_else(|| "This channel has no available handle; no channel was saved.".to_owned())?;
|
||||
crate::config::normalize_channel(&handle).map_err(|error| error.to_string())?;
|
||||
Ok(handle)
|
||||
}
|
||||
|
||||
fn page_end(start: usize) -> io::Result<usize> {
|
||||
start
|
||||
.checked_add(PAGE_SIZE - 1)
|
||||
@@ -251,6 +270,22 @@ impl Job {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn channel(id: &str) -> io::Result<Self> {
|
||||
if !valid_channel_id(id) {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"Invalid YouTube channel ID",
|
||||
));
|
||||
}
|
||||
Self::spawn(extractor().args([
|
||||
"--flat-playlist",
|
||||
"--playlist-end",
|
||||
"1",
|
||||
"--dump-single-json",
|
||||
&format!("https://www.youtube.com/channel/{id}/videos"),
|
||||
]))
|
||||
}
|
||||
|
||||
pub fn description(id: &str) -> io::Result<Self> {
|
||||
Self::spawn(extractor().args([
|
||||
"--no-playlist",
|
||||
@@ -839,6 +874,26 @@ mod tests {
|
||||
assert_eq!(exhausted.videos.len(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn channel_handles_require_the_requested_identity_and_a_valid_handle() {
|
||||
let id = "UChAQQ9at2MDlXjvQX3vL3Yw";
|
||||
for handle in ["@ch.1676", "@敷嶋てとら"] {
|
||||
let metadata = serde_json::json!({"channel_id": id, "uploader_id": handle}).to_string();
|
||||
assert_eq!(channel_handle(&metadata, id).unwrap(), handle);
|
||||
assert!(channel_handle(&metadata, "UCaYhcUwRBNscFNUKTjgPFiA").is_err());
|
||||
}
|
||||
for handle in [
|
||||
None,
|
||||
Some("ch.1676"),
|
||||
Some("@bad/handle"),
|
||||
Some("@bad\u{1b}"),
|
||||
] {
|
||||
let metadata = serde_json::json!({"channel_id": id, "uploader_id": handle}).to_string();
|
||||
assert!(channel_handle(&metadata, id).is_err());
|
||||
}
|
||||
assert!(channel_handle("not JSON", id).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn full_descriptions_preserve_paragraphs_and_reject_mismatched_videos() {
|
||||
let metadata = r#"{"id":"jNQXAC9IVRw","description":"First paragraph.\n\n日本語\tsecond paragraph.\u001b\nLast line."}"#;
|
||||
|
||||
Reference in New Issue
Block a user