use std::sync::Arc;
use std::time::Duration;
use parking_lot::RwLock;
use tokio::sync::broadcast;
use tokio_util::sync::CancellationToken;
use crate::error::SteamError;
use super::auth_poll_result::AuthPollResult;
use super::auth_session::AuthSession;
use super::i_authenticator::IAuthenticator;
pub(crate) struct QrAuthSessionState {
challenge_url: RwLock<String>,
changed: broadcast::Sender<String>,
}
impl QrAuthSessionState {
pub(crate) fn new(challenge_url: String) -> Self {
let (changed, _) = broadcast::channel(16);
QrAuthSessionState {
challenge_url: RwLock::new(challenge_url),
changed,
}
}
pub(crate) fn challenge_url(&self) -> String {
self.challenge_url.read().clone()
}
pub(crate) fn set_challenge_url(&self, challenge_url: String) {
*self.challenge_url.write() = challenge_url.clone();
let _ = self.changed.send(challenge_url);
}
pub(crate) fn subscribe(&self) -> broadcast::Receiver<String> {
self.changed.subscribe()
}
}
pub struct QrAuthSession {
session: AuthSession,
state: Arc<QrAuthSessionState>,
}
impl std::fmt::Debug for QrAuthSession {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("QrAuthSession")
.field("session", &self.session)
.field("challenge_url", &self.challenge_url())
.finish()
}
}
impl QrAuthSession {
pub(crate) fn new(session: AuthSession, state: Arc<QrAuthSessionState>) -> Self {
QrAuthSession { session, state }
}
pub fn challenge_url(&self) -> String {
self.state.challenge_url()
}
pub fn challenge_url_changed(&self) -> broadcast::Receiver<String> {
self.state.subscribe()
}
pub fn authenticator(&self) -> Option<&Arc<dyn IAuthenticator>> {
self.session.authenticator()
}
pub fn client_id(&self) -> u64 {
self.session.client_id()
}
pub fn request_id(&self) -> &[u8] {
self.session.request_id()
}
pub fn polling_interval(&self) -> Duration {
self.session.polling_interval()
}
pub fn allowed_confirmations(
&self,
) -> &[steamkit_protos::steam::CAuthenticationAllowedConfirmation] {
self.session.allowed_confirmations()
}
pub async fn polling_wait_for_result(
&self,
cancellation: CancellationToken,
) -> Result<AuthPollResult, SteamError> {
self.session.polling_wait_for_result(cancellation).await
}
pub async fn poll_auth_session_status(&self) -> Result<Option<AuthPollResult>, SteamError> {
self.session.poll_auth_session_status().await
}
}