tail-fin-xhs 0.7.8

Xiaohongshu adapter for tail-fin: search, notes, comments, feed
Documentation
/// Extract an XHS note ID from a URL or bare ID.
///
/// Supports:
/// - `https://www.xiaohongshu.com/explore/{id}`
/// - `https://www.xiaohongshu.com/search_result/{id}`
/// - `https://www.xiaohongshu.com/discovery/item/{id}`
/// - Bare 24-char hex ID
pub fn extract_note_id(input: &str) -> String {
    let input = input.trim();

    for segment in &["explore/", "search_result/", "discovery/item/", "note/"] {
        if let Some(pos) = input.find(segment) {
            let after = &input[pos + segment.len()..];
            let id = after
                .split(&['/', '?', '#', '&'][..])
                .next()
                .unwrap_or(after);
            if !id.is_empty() {
                return id.to_string();
            }
        }
    }

    input.to_string()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_extract_explore_url() {
        assert_eq!(
            extract_note_id("https://www.xiaohongshu.com/explore/6789abcdef0123456789abcd"),
            "6789abcdef0123456789abcd"
        );
    }

    #[test]
    fn test_extract_search_result_url() {
        assert_eq!(
            extract_note_id(
                "https://www.xiaohongshu.com/search_result/6789abcdef0123456789abcd?xsec_token=abc"
            ),
            "6789abcdef0123456789abcd"
        );
    }

    #[test]
    fn test_extract_discovery_url() {
        assert_eq!(
            extract_note_id("https://www.xiaohongshu.com/discovery/item/6789abcdef0123456789abcd"),
            "6789abcdef0123456789abcd"
        );
    }

    #[test]
    fn test_extract_bare_id() {
        assert_eq!(
            extract_note_id("6789abcdef0123456789abcd"),
            "6789abcdef0123456789abcd"
        );
    }

    #[test]
    fn test_extract_with_whitespace() {
        assert_eq!(
            extract_note_id("  6789abcdef0123456789abcd  "),
            "6789abcdef0123456789abcd"
        );
    }
}