combat_service/
services.rs1use std::{collections::HashMap, sync::Arc};
8
9use chrono::Utc;
10use edda_auth::{DeviceKey, PublicKey, protocol::Session};
11use edda_client::{ClientError, auth::AuthClient, monsters::MonsterClient};
12use edda_types::monster::Monster;
13use tokio::sync::Mutex;
14use uuid::Uuid;
15
16#[derive(Debug, Clone)]
18pub struct ServicesConfig {
19 pub auth_service: String,
20 pub auth_key: PublicKey,
22 pub key: Arc<DeviceKey>,
24 pub character_service: Option<String>,
28 pub monster_service: Option<String>,
31}
32
33pub struct ServiceLogin {
35 auth: AuthClient,
36 auth_key: PublicKey,
37 key: Arc<DeviceKey>,
38 sessions: Mutex<HashMap<Uuid, Session>>,
40}
41
42impl ServiceLogin {
43 pub fn new(config: &ServicesConfig) -> Self {
45 Self {
46 auth: AuthClient::new(&config.auth_service),
47 auth_key: config.auth_key,
48 key: config.key.clone(),
49 sessions: Mutex::new(HashMap::new()),
50 }
51 }
52
53 pub async fn token(&self, campaign: Uuid) -> Result<String, ClientError> {
55 let mut sessions = self.sessions.lock().await;
56 let fresh = |s: &Session| s.claims.expires_at > Utc::now() + chrono::Duration::minutes(1);
57 if let Some(session) = sessions.get(&campaign).filter(|s| fresh(s)) {
58 return Ok(session.token.clone());
59 }
60 let session = self
61 .auth
62 .login(campaign, &self.key, Some(self.auth_key))
63 .await?;
64 let token = session.token.clone();
65 sessions.insert(campaign, session);
66 Ok(token)
67 }
68}
69
70pub struct Monsters {
72 login: Arc<ServiceLogin>,
73 url: String,
74}
75
76impl Monsters {
77 pub fn new(login: Arc<ServiceLogin>, url: String) -> Self {
79 Self { login, url }
80 }
81
82 pub async fn get(&self, campaign: Uuid, id: Uuid) -> Result<Monster, ClientError> {
84 let token = self.login.token(campaign).await?;
85 MonsterClient::new(&self.url)
86 .with_token(&token)
87 .get(id)
88 .await
89 }
90}