bilive 0.1.1

A Rust library for interacting with Bilibili's live streaming services.
Documentation
use std::fmt::{Debug, Display};
use std::time::Duration;

use crate::bapi::*;
use crate::session::Session;

#[derive(Clone)]
pub struct User {
    pub account: Account,
    pub session: Session,
}

impl User {
    pub async fn new(session: Session) -> Result<Self, Box<dyn std::error::Error + Sync + Send>> {
        let account = session.get_account().await?;
        Ok(Self { account, session })
    }

    pub async fn get_login_qrcode(
        &self,
    ) -> Result<QrCodeInfo, Box<dyn std::error::Error + Sync + Send>> {
        self.session
            .get_qrcode()
            .await
            .map_err(|e| format!("Failed to get login QR code: {}", e).into())
    }

    pub async fn wait_for_login(
        &mut self,
        qr_code_info: QrCodeInfo,
    ) -> Result<LoginInfo, Box<dyn std::error::Error + Sync + Send>> {
        let login_info = self
            .session
            .wait_for_login(&qr_code_info.qrcode_key, Duration::from_secs(180))
            .await?;
        self.update_user_info().await?;
        Ok(login_info)
    }

    pub async fn update_user_info(
        &mut self,
    ) -> Result<(), Box<dyn std::error::Error + Sync + Send>> {
        self.account = self.session.get_account().await?;
        Ok(())
    }
}

impl Display for User {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "User {{ Account: {:?} }}", self.account)
    }
}

impl Debug for User {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self)
    }
}

#[cfg(test)]
mod tests {
    use std::io::Write;
    use std::sync::Arc;

    use qrcode::QrCode;
    use qrcode::render::svg;
    use tokio::sync::Mutex;

    use super::*;
    use crate::wbi::WBI;

    #[tokio::test]
    async fn test_user_login() {
        let session = Session::new().await.expect("Failed to create session");
        let qr_code_info = session.get_qrcode().await.expect("Failed to get qr code");
        let qr = QrCode::new(qr_code_info.url.as_str()).expect("Failed to create qrcode");
        let svg = qr
            .render()
            .min_dimensions(200, 200)
            .quiet_zone(true)
            .dark_color(svg::Color("#000000"))
            .light_color(svg::Color("#ffffff"))
            .build();

        let mut file = std::fs::File::create("test.qr.svg").expect("Failed to create svg file");
        file.write_all(svg.as_bytes())
            .expect("Failed to write svg file");

        tracing::info!("QR code saved to test.qr.svg");
        let login_info = session
            .wait_for_login(&qr_code_info.qrcode_key, Duration::from_secs(180))
            .await
            .expect("Failed to wait for login");

        let mut user = User::new(session).await.expect("Failed to create user");
        user.update_user_info()
            .await
            .expect("Failed to update user info");
        tracing::info!("User login: {:?}", user);
    }
}