287 lines
12 KiB
Rust
287 lines
12 KiB
Rust
use mnml_core::mob::anim_test_game;
|
|
use mnml_core::item::item_info;
|
|
use std::time::Instant;
|
|
use uuid::Uuid;
|
|
|
|
use failure::Error;
|
|
use failure::err_msg;
|
|
|
|
use crossbeam_channel::{Sender as CbSender};
|
|
use stripe::{Client as StripeClient};
|
|
|
|
use serde_cbor::{from_slice};
|
|
|
|
use pg::{
|
|
game_concede,
|
|
game_offer_draw,
|
|
game_ready,
|
|
game_skill,
|
|
game_skill_clear,
|
|
game_state,
|
|
instance_abandon,
|
|
instance_practice,
|
|
instance_ready,
|
|
instance_state,
|
|
vbox_apply,
|
|
vbox_buy,
|
|
vbox_combine,
|
|
vbox_refill,
|
|
vbox_refund,
|
|
vbox_unequip,
|
|
};
|
|
|
|
use account::{Account};
|
|
use account;
|
|
use events::{Event};
|
|
|
|
use mtx;
|
|
use mail;
|
|
use payments;
|
|
use pg::{PgPool};
|
|
use rpc::{RpcMessage, RpcRequest, User};
|
|
|
|
|
|
#[derive(Debug,Clone)]
|
|
pub struct Authenticated {
|
|
pub account: Account,
|
|
pub id: Uuid,
|
|
|
|
events: CbSender<Event>,
|
|
ws: CbSender<RpcMessage>,
|
|
pool: PgPool,
|
|
}
|
|
|
|
impl Authenticated {
|
|
pub fn new(account: Account, ws: CbSender<RpcMessage>, events: CbSender<Event>, pool: PgPool) -> Authenticated {
|
|
Authenticated {
|
|
id: account.id,
|
|
account,
|
|
ws,
|
|
events,
|
|
pool,
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
impl User for Authenticated {
|
|
fn send(&mut self, msg: RpcMessage) -> Result<(), Error> {
|
|
// if the user queries the state of something
|
|
// we tell events to push updates to them
|
|
match msg {
|
|
RpcMessage::AccountState(ref v) => {
|
|
self.events.send(Event::Subscribe(self.id, v.id))?
|
|
},
|
|
RpcMessage::GameState(ref v) =>
|
|
self.events.send(Event::Subscribe(self.id, v.id))?,
|
|
RpcMessage::InstanceState(ref v) =>
|
|
self.events.send(Event::Subscribe(self.id, v.id))?,
|
|
_ => (),
|
|
};
|
|
|
|
self.ws.send(msg)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn connected(&mut self) -> Result<(), Error> {
|
|
info!("authenticated connection account={:?}", self.account);
|
|
let a = &self.account;
|
|
|
|
self.ws.send(RpcMessage::AccountAuthenticated(a.clone()))?;
|
|
// tell events we have connected
|
|
self.events.send(Event::Connect(self.id, a.clone(), self.ws.clone()))?;
|
|
|
|
self.ws.send(RpcMessage::AccountState(a.clone()))?;
|
|
self.events.send(Event::Subscribe(self.id, a.id))?;
|
|
|
|
// check if they have an image that needs to be generated
|
|
account::img_check(&a)?;
|
|
|
|
let db = self.pool.get()?;
|
|
let mut tx = db.transaction()?;
|
|
|
|
// send account constructs
|
|
let account_constructs = account::constructs(&mut tx, &a)?;
|
|
self.ws.send(RpcMessage::AccountConstructs(account_constructs))?;
|
|
|
|
// get account instances
|
|
// and send them to the client
|
|
let account_instances = account::account_instances(&mut tx, &a)?;
|
|
self.ws.send(RpcMessage::AccountInstances(account_instances))?;
|
|
|
|
let shop = mtx::account_shop(&mut tx, &a)?;
|
|
self.ws.send(RpcMessage::AccountShop(shop))?;
|
|
|
|
let team = account::team(&mut tx, &a)?;
|
|
self.ws.send(RpcMessage::AccountTeam(team))?;
|
|
|
|
let wheel = account::chat_wheel(&db, a.id)?;
|
|
self.ws.send(RpcMessage::ChatWheel(wheel))?;
|
|
|
|
if let Some(instance) = account::tutorial(&mut tx, &a)? {
|
|
self.ws.send(RpcMessage::InstanceState(instance))?;
|
|
}
|
|
|
|
// tx should do nothing
|
|
tx.commit()?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn receive(&mut self, data: Vec<u8>, stripe: &StripeClient) -> Result<RpcMessage, Error> {
|
|
// cast the msg to this type to receive method name
|
|
let begin = Instant::now();
|
|
let db = self.pool.get()?;
|
|
|
|
match from_slice::<RpcRequest>(&data) {
|
|
Ok(v) => {
|
|
let request = v.clone();
|
|
let response = match v {
|
|
RpcRequest::Ping {} => return Ok(RpcMessage::Pong(())),
|
|
RpcRequest::ItemInfo {} => return Ok(RpcMessage::ItemInfo(item_info())),
|
|
RpcRequest::DevResolve { skill } =>
|
|
return Ok(RpcMessage::GameState(anim_test_game(skill))),
|
|
|
|
RpcRequest::InstanceQueue {} => {
|
|
self.events.send(Event::Queue(self.id))?;
|
|
Ok(RpcMessage::QueueRequested(()))
|
|
},
|
|
RpcRequest::InstanceInvite {} => {
|
|
self.events.send(Event::Invite(self.id))?;
|
|
Ok(RpcMessage::InviteRequested(()))
|
|
},
|
|
RpcRequest::InstanceJoin { code } => {
|
|
self.events.send(Event::Join(self.id, code))?;
|
|
Ok(RpcMessage::Joining(()))
|
|
},
|
|
RpcRequest::InstanceLeave {} => {
|
|
self.events.send(Event::Leave(self.id))?;
|
|
Ok(RpcMessage::Processing(()))
|
|
},
|
|
|
|
RpcRequest::InstanceChat { instance_id, index } => {
|
|
if !self.account.subscribed {
|
|
return Err(err_msg("subscribe to unlock chat"))
|
|
}
|
|
|
|
let wheel = account::chat_wheel(&db, self.account.id)?;
|
|
|
|
if let Some(c) = wheel.get(index) {
|
|
self.events.send(Event::Chat(self.id, instance_id, c.to_string()))?;
|
|
} else {
|
|
return Err(err_msg("invalid chat index"));
|
|
}
|
|
|
|
Ok(RpcMessage::Processing(()))
|
|
},
|
|
_ => {
|
|
// all good, let's make a tx and process
|
|
let mut tx = db.transaction()?;
|
|
|
|
let res = match v {
|
|
RpcRequest::AccountState {} =>
|
|
Ok(RpcMessage::AccountState(self.account.clone())),
|
|
RpcRequest::AccountConstructs {} =>
|
|
Ok(RpcMessage::AccountConstructs(account::constructs(&mut tx, &self.account)?)),
|
|
RpcRequest::AccountInstances {} =>
|
|
Ok(RpcMessage::AccountInstances(account::account_instances(&mut tx, &self.account)?)),
|
|
RpcRequest::AccountSetTeam { ids } =>
|
|
Ok(RpcMessage::AccountTeam(account::set_team(&mut tx, &self.account, ids)?)),
|
|
|
|
RpcRequest::EmailState {} =>
|
|
Ok(RpcMessage::EmailState(mail::select_account(&db, self.account.id)?)),
|
|
|
|
RpcRequest::SubscriptionState {} =>
|
|
Ok(RpcMessage::SubscriptionState(payments::account_subscription(&db, stripe, &self.account)?)),
|
|
|
|
// RpcRequest::AccountShop {} =>
|
|
// Ok(RpcMessage::AccountShop(mtx::account_shop(&mut tx, &account)?)),
|
|
|
|
// RpcRequest::ConstructDelete" => handle_construct_delete(data, &mut tx, account),
|
|
|
|
RpcRequest::GameState { id } =>
|
|
Ok(RpcMessage::GameState(game_state(&mut tx, &self.account, id)?)),
|
|
|
|
RpcRequest::GameSkill { game_id, construct_id, target_construct_id, skill } =>
|
|
Ok(RpcMessage::GameState(game_skill(&mut tx, &self.account, game_id, construct_id, target_construct_id, skill)?)),
|
|
|
|
RpcRequest::GameSkillClear { game_id } =>
|
|
Ok(RpcMessage::GameState(game_skill_clear(&mut tx, &self.account, game_id)?)),
|
|
|
|
RpcRequest::GameReady { id } =>
|
|
Ok(RpcMessage::GameState(game_ready(&mut tx, &self.account, id)?)),
|
|
|
|
RpcRequest::GameConcede { game_id } =>
|
|
Ok(RpcMessage::GameState(game_concede(&mut tx, &self.account, game_id)?)),
|
|
|
|
RpcRequest::GameOfferDraw { game_id } =>
|
|
Ok(RpcMessage::GameState(game_offer_draw(&mut tx, &self.account, game_id)?)),
|
|
|
|
RpcRequest::InstancePractice {} =>
|
|
Ok(RpcMessage::InstanceState(instance_practice(&mut tx, &self.account)?)),
|
|
|
|
// these two can return GameState or InstanceState
|
|
RpcRequest::InstanceReady { instance_id } =>
|
|
Ok(instance_ready(&mut tx, &self.account, instance_id)?),
|
|
RpcRequest::InstanceState { instance_id } =>
|
|
Ok(instance_state(&mut tx, instance_id)?),
|
|
RpcRequest::InstanceAbandon { instance_id } =>
|
|
Ok(instance_abandon(&mut tx, &self.account, instance_id)?),
|
|
|
|
RpcRequest::VboxBuy { instance_id, group, index, construct_id } =>
|
|
Ok(RpcMessage::InstanceState(vbox_buy(&mut tx, &self.account, instance_id, group, index, construct_id)?)),
|
|
|
|
RpcRequest::VboxApply { instance_id, construct_id, index } =>
|
|
Ok(RpcMessage::InstanceState(vbox_apply(&mut tx, &self.account, instance_id, construct_id, index)?)),
|
|
|
|
RpcRequest::VboxCombine { instance_id, inv_indices, vbox_indices } =>
|
|
Ok(RpcMessage::InstanceState(vbox_combine(&mut tx, &self.account, instance_id, inv_indices, vbox_indices)?)),
|
|
|
|
RpcRequest::VboxRefill { instance_id } =>
|
|
Ok(RpcMessage::InstanceState(vbox_refill(&mut tx, &self.account, instance_id)?)),
|
|
|
|
RpcRequest::VboxRefund { instance_id, index } =>
|
|
Ok(RpcMessage::InstanceState(vbox_refund(&mut tx, &self.account, instance_id, index)?)),
|
|
|
|
RpcRequest::VboxUnequip { instance_id, construct_id, target } =>
|
|
Ok(RpcMessage::InstanceState(vbox_unequip(&mut tx, &self.account, instance_id, construct_id, target, None)?)),
|
|
|
|
RpcRequest::VboxUnequipApply { instance_id, construct_id, target, target_construct_id } =>
|
|
Ok(RpcMessage::InstanceState(vbox_unequip(&mut tx, &self.account, instance_id, construct_id, target, Some(target_construct_id))?)),
|
|
|
|
RpcRequest::MtxConstructSpawn {} =>
|
|
Ok(RpcMessage::ConstructSpawn(mtx::new_construct(&mut tx, &self.account)?)),
|
|
|
|
RpcRequest::MtxConstructApply { mtx, construct_id, name } =>
|
|
Ok(RpcMessage::AccountTeam(mtx::apply(&mut tx, &self.account, mtx, construct_id, name)?)),
|
|
|
|
RpcRequest::MtxAccountApply { mtx } =>
|
|
Ok(RpcMessage::AccountState(mtx::account_apply(&mut tx, &self.account, mtx)?)),
|
|
|
|
RpcRequest::MtxBuy { mtx } =>
|
|
Ok(RpcMessage::AccountShop(mtx::buy(&mut tx, &self.account, mtx)?)),
|
|
|
|
RpcRequest::SubscriptionEnding { ending } =>
|
|
Ok(RpcMessage::SubscriptionState(payments::subscription_ending(&mut tx, stripe, &self.account, ending)?)),
|
|
|
|
_ => Err(format_err!("unknown request request={:?}", request)),
|
|
};
|
|
|
|
tx.commit()?;
|
|
res
|
|
}
|
|
};
|
|
|
|
info!("request={:?} account={:?} duration={:?}", request, self.account.name, begin.elapsed());
|
|
|
|
return response;
|
|
},
|
|
Err(e) => {
|
|
warn!("{:?}", e);
|
|
Err(err_msg("invalid message"))
|
|
},
|
|
}
|
|
}
|
|
}
|