plex-api 0.0.12

Library for communication with Plex server. Work in progress, not ready for any use. See github for details.
Documentation
use plex_api::{
    device::Device,
    library::{
        Collection, FromMetadata, Library, MediaItem, MetadataItem, MovieLibrary, MusicLibrary,
        PhotoLibrary, Playlist, TVLibrary,
    },
    MyPlexBuilder,
};
use rpassword::prompt_password;
use std::io::{stdin, stdout, BufRead, Write};

async fn process_playlists<T: MediaItem + FromMetadata>(playlists: Vec<Playlist<T>>) {
    println!("Received {} playlist(s)", playlists.len());

    for playlist in playlists {
        println!("Processing '{}'", playlist.title());
        println!(
            "Received {} item(s)",
            playlist
                .children()
                .await
                .expect("failed to get children")
                .len()
        );
    }
}

async fn process_collections<T: FromMetadata>(collections: Vec<Collection<T>>) {
    println!("Received {} collection(s)", collections.len());
    for collection in collections {
        println!("Processing collection '{}'", collection.title());
        let children = collection
            .children()
            .await
            .expect("failed to load collection");
        println!("Received {} items", children.len());
    }
}

async fn process_movie_library(library: MovieLibrary) {
    let movies = library.movies().await.expect("failed to get movies");
    println!("Received {} movie(s)", movies.len());

    let collections = library
        .collections()
        .await
        .expect("failed to get collections");

    process_collections(collections).await;

    let playlists = library.playlists().await.expect("failed to get playlists");
    process_playlists(playlists).await;
}

async fn process_tv_library(library: TVLibrary) {
    let shows = library.shows().await.expect("failed to get shows");
    println!("Received {} show(s)", shows.len());

    for show in shows {
        println!("Processing show '{}'", show.title());
        println!(
            "Received {} season(s)",
            show.seasons().await.expect("failed to get seasons").len()
        );
        println!(
            "Received {} episode(s)",
            show.episodes().await.expect("failed to get episodes").len()
        );
    }

    let collections = library
        .collections()
        .await
        .expect("failed to get collections");
    process_collections(collections).await;

    let playlists = library.playlists().await.expect("failed to get playlists");
    process_playlists(playlists).await;
}

async fn process_music_library(library: MusicLibrary) {
    let artists = library.artists().await.expect("failed to get artists");
    println!("Received {} artist(s)", artists.len());

    for artist in artists {
        println!("Processing artist '{}'", artist.title());
        println!(
            "Received {} album(s)",
            artist.albums().await.expect("failed to get albums").len()
        );
    }

    let playlists = library.playlists().await.expect("failed to get playlists");
    process_playlists(playlists).await;
}

async fn process_photo_library(library: PhotoLibrary) {
    let albums = library.albums().await.expect("failed to get albums");
    println!("Received {} album(s)", albums.len());

    for album in albums {
        println!("Album '{}'", album.title());
        println!(
            "Received {} album item(s)",
            album
                .contents()
                .await
                .expect("failed to get album contents")
                .len()
        );
    }

    let playlists = library.playlists().await.expect("failed to get playlists");
    process_playlists(playlists).await;
}

#[tokio::main]
async fn main() {
    let token = prompt_password("Token: ").unwrap();
    stdout().flush().unwrap();

    let myplex = MyPlexBuilder::default()
        .set_token(token)
        .build()
        .await
        .unwrap();

    let device_manager = myplex.device_manager().unwrap();
    let devices = device_manager.devices().await.unwrap();

    if devices.is_empty() {
        eprintln!("You have no devices");
        return;
    }

    let devices = devices
        .into_iter()
        .filter(|device| device.is_server())
        .collect::<Vec<Device>>();

    let device = {
        if devices.len() == 1 {
            devices.first().unwrap()
        } else {
            println!("Please selected the server you want to connect to:");
            for (idx, d) in devices.iter().enumerate() {
                println!("{}. {}", idx + 1, d.name());
            }
            let idx = stdin().lock().lines().next().unwrap().unwrap();
            let idx: usize = idx.parse().unwrap();
            if idx > devices.len() + 1 || idx < 1 {
                eprintln!("Don't be like that");
                return;
            }
            devices.get(idx - 1).unwrap()
        }
    };
    let device = match device.connect().await.unwrap() {
        plex_api::device::DeviceConnection::Server(srv) => srv,
        _ => panic!("HOW?"),
    };

    for library in device.libraries() {
        println!(
            "{} (id={}, type={})",
            library.title(),
            library.id(),
            library.library_type()
        );

        match library {
            Library::Movie(library) | Library::Video(library) => {
                process_movie_library(library).await
            }
            Library::TV(library) => process_tv_library(library).await,
            Library::Music(library) => process_music_library(library).await,
            Library::Photo(library) => process_photo_library(library).await,
        }

        println!();
    }
}