Merge branch 'release/1.0.0'
This commit is contained in:
commit
829939537b
17
WORKLOG.md
17
WORKLOG.md
@ -3,8 +3,9 @@
|
|||||||
*PRODUCTION*
|
*PRODUCTION*
|
||||||
* ACP
|
* ACP
|
||||||
* essential
|
* essential
|
||||||
* error log
|
* serde serialize privatise
|
||||||
* account lookup w/ pw reset
|
* DO postgres
|
||||||
|
* mobile styles
|
||||||
|
|
||||||
* treats
|
* treats
|
||||||
* constructs jiggle when clicked
|
* constructs jiggle when clicked
|
||||||
@ -12,15 +13,8 @@
|
|||||||
|
|
||||||
* bot game grind
|
* bot game grind
|
||||||
|
|
||||||
* serde serialize privatise
|
|
||||||
* stripe prod
|
|
||||||
* mobile styles
|
|
||||||
* change score to enum
|
* change score to enum
|
||||||
* pct based translates for combat animation
|
* pct based translates for combat animation
|
||||||
* account page
|
|
||||||
* graphs n shit
|
|
||||||
* acp init
|
|
||||||
* DO postgres
|
|
||||||
* make our own toasts / msg pane
|
* make our own toasts / msg pane
|
||||||
* send account_instances on players update
|
* send account_instances on players update
|
||||||
|
|
||||||
@ -28,6 +22,8 @@
|
|||||||
* clear skill (if currently targetted)
|
* clear skill (if currently targetted)
|
||||||
* increase power to speed up early rounds
|
* increase power to speed up early rounds
|
||||||
|
|
||||||
|
* only login / logout / register http
|
||||||
|
|
||||||
## SOON
|
## SOON
|
||||||
*SERVER*
|
*SERVER*
|
||||||
* modules
|
* modules
|
||||||
@ -38,12 +34,15 @@
|
|||||||
* empower on ko
|
* empower on ko
|
||||||
|
|
||||||
* rework vecs into sets
|
* rework vecs into sets
|
||||||
|
* remove names so games/instances are copy
|
||||||
|
|
||||||
*$$$*
|
*$$$*
|
||||||
* chatwheel
|
* chatwheel
|
||||||
* eth adapter
|
* eth adapter
|
||||||
* illusions
|
* illusions
|
||||||
* vaporwave
|
* vaporwave
|
||||||
|
* crop circles
|
||||||
|
* insects
|
||||||
* sacred geometry
|
* sacred geometry
|
||||||
* skulls / day of the dead
|
* skulls / day of the dead
|
||||||
* Aztec
|
* Aztec
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mnml-client",
|
"name": "mnml-client",
|
||||||
"version": "0.3.0",
|
"version": "1.0.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -20,15 +20,28 @@
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.unsub {
|
||||||
|
&:hover {
|
||||||
|
color: @red;
|
||||||
|
border-color: @red;
|
||||||
|
};
|
||||||
|
|
||||||
|
&:active, &.confirming {
|
||||||
|
background: @red;
|
||||||
|
color: black;
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.list {
|
.list {
|
||||||
letter-spacing: 0.25em;
|
letter-spacing: 0.25em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
|
|
||||||
figure {
|
figure {
|
||||||
font-size: 125%;
|
width: 75%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: column;
|
flex-flow: column;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
|
||||||
button {
|
button {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@ -76,3 +76,13 @@ aside {
|
|||||||
transition-duration: 0.25s;
|
transition-duration: 0.25s;
|
||||||
transition-timing-function: ease;
|
transition-timing-function: ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.team-page-ctrl {
|
||||||
|
display: flex;
|
||||||
|
height: 3em;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.team-page-ctrl h2 {
|
||||||
|
padding: 0 0.75em 0 0.75em;
|
||||||
|
}
|
||||||
|
|||||||
@ -78,6 +78,10 @@ p {
|
|||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dl {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
#mnml {
|
#mnml {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(min-content, 1fr) 8fr 1fr;
|
grid-template-columns: minmax(min-content, 1fr) 8fr 1fr;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mnml-client",
|
"name": "mnml-client",
|
||||||
"version": "0.3.0",
|
"version": "1.0.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -31,8 +31,10 @@ export const setShowLog = value => ({ type: 'SET_SHOW_LOG', value });
|
|||||||
export const setShowNav = value => ({ type: 'SET_SHOW_NAV', value });
|
export const setShowNav = value => ({ type: 'SET_SHOW_NAV', value });
|
||||||
export const setSkip = value => ({ type: 'SET_SKIP', value });
|
export const setSkip = value => ({ type: 'SET_SKIP', value });
|
||||||
export const setShop = value => ({ type: 'SET_SHOP', value });
|
export const setShop = value => ({ type: 'SET_SHOP', value });
|
||||||
|
export const setSubscription = value => ({ type: 'SET_SUBSCRIPTION', value });
|
||||||
|
|
||||||
export const setTeam = value => ({ type: 'SET_TEAM', value: Array.from(value) });
|
export const setTeam = value => ({ type: 'SET_TEAM', value: Array.from(value) });
|
||||||
|
export const setTeamPage = value => ({ type: 'SET_TEAM_PAGE', value });
|
||||||
export const setTeamSelect = value => ({ type: 'SET_TEAM_SELECT', value: Array.from(value) });
|
export const setTeamSelect = value => ({ type: 'SET_TEAM_SELECT', value: Array.from(value) });
|
||||||
|
|
||||||
export const setVboxHighlight = value => ({ type: 'SET_VBOX_HIGHLIGHT', value });
|
export const setVboxHighlight = value => ({ type: 'SET_VBOX_HIGHLIGHT', value });
|
||||||
|
|||||||
@ -30,7 +30,7 @@ document.fonts.load('16pt "Jura"').then(() => {
|
|||||||
|
|
||||||
const App = () => (
|
const App = () => (
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<StripeProvider apiKey="pk_test_PiLzjIQE7zUy3Xpott7tdQbl00uLiCesTa">
|
<StripeProvider apiKey="pk_test_Cb49tTqTXpzk7nEmlGzRrNJg00AU0aNZDj">
|
||||||
<Mnml />
|
<Mnml />
|
||||||
</StripeProvider>
|
</StripeProvider>
|
||||||
</Provider>
|
</Provider>
|
||||||
|
|||||||
@ -12,13 +12,14 @@ const addState = connect(
|
|||||||
function receiveState(state) {
|
function receiveState(state) {
|
||||||
const {
|
const {
|
||||||
account,
|
account,
|
||||||
|
subscription,
|
||||||
email,
|
email,
|
||||||
ping,
|
ping,
|
||||||
ws,
|
ws,
|
||||||
} = state;
|
} = state;
|
||||||
|
|
||||||
|
|
||||||
function setPassword(current, password) {
|
function sendSetPassword(current, password) {
|
||||||
postData('/account/password', { current, password })
|
postData('/account/password', { current, password })
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
@ -29,7 +30,7 @@ const addState = connect(
|
|||||||
.catch(error => errorToast(error));
|
.catch(error => errorToast(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
function setEmail(email) {
|
function sendSetEmail(email) {
|
||||||
postData('/account/email', { email })
|
postData('/account/email', { email })
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
@ -49,14 +50,20 @@ const addState = connect(
|
|||||||
return ws.sendMtxConstructSpawn(name);
|
return ws.sendMtxConstructSpawn(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sendSubscriptionEnding(enabled) {
|
||||||
|
return ws.sendSubscriptionEnding(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
account,
|
account,
|
||||||
|
subscription,
|
||||||
ping,
|
ping,
|
||||||
email,
|
email,
|
||||||
logout,
|
logout,
|
||||||
setPassword,
|
sendSetPassword,
|
||||||
setEmail,
|
sendSetEmail,
|
||||||
sendConstructSpawn,
|
sendConstructSpawn,
|
||||||
|
sendSubscriptionEnding,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -67,42 +74,96 @@ class AccountStatus extends Component {
|
|||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
setPassword: { current: '', password: '', confirm: ''},
|
passwordState: { current: '', password: '', confirm: ''},
|
||||||
email: null,
|
emailState: null,
|
||||||
|
unsubState: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
render(args) {
|
render(args, state) {
|
||||||
const {
|
const {
|
||||||
account,
|
account,
|
||||||
|
subscription,
|
||||||
ping,
|
ping,
|
||||||
email,
|
email,
|
||||||
logout,
|
logout,
|
||||||
setPassword,
|
sendSetEmail,
|
||||||
setEmail,
|
sendSetPassword,
|
||||||
sendConstructSpawn,
|
sendConstructSpawn,
|
||||||
|
sendSubscriptionEnding,
|
||||||
} = args;
|
} = args;
|
||||||
|
|
||||||
|
const {
|
||||||
|
passwordState,
|
||||||
|
emailState,
|
||||||
|
unsubState,
|
||||||
|
} = state;
|
||||||
|
|
||||||
if (!account) return null;
|
if (!account) return null;
|
||||||
|
|
||||||
const passwordsEqual = () =>
|
const passwordsEqual = () =>
|
||||||
this.state.setPassword.password === this.state.setPassword.confirm;
|
passwordState.password === passwordState.confirm;
|
||||||
|
|
||||||
const setPasswordDisabled = () => {
|
const setPasswordDisabled = () => {
|
||||||
const { current, password, confirm } = this.state.setPassword;
|
const { current, password, confirm } = passwordState;
|
||||||
return !(passwordsEqual() && password && current && confirm);
|
return !(passwordsEqual() && password && current && confirm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const tlClick = e => {
|
||||||
|
e.stopPropagation();
|
||||||
|
return this.setState({ unsubState: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
const subInfo = () => {
|
||||||
|
const unsubBtn = () => {
|
||||||
|
if (!subscription) return false;
|
||||||
|
|
||||||
|
// resub button
|
||||||
|
if (subscription.cancel_at_period_end) {
|
||||||
|
return <button class='stripe-btn' onClick={() => sendSubscriptionEnding(false)}>Resubscribe</button>
|
||||||
|
}
|
||||||
|
|
||||||
|
const classes = `unsub ${unsubState ? 'confirming' : ''}`;
|
||||||
|
const text = unsubState ? 'Confirm' : 'Unsubscribe'
|
||||||
|
return <button class={classes} onClick={unsub}>{text}</button>
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsub = e => {
|
||||||
|
if (unsubState) {
|
||||||
|
return sendSubscriptionEnding(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
e.stopPropagation();
|
||||||
|
return this.setState({ unsubState: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!subscription) return false;
|
||||||
|
return <div>
|
||||||
|
<h3>Subscription</h3>
|
||||||
|
<dl>
|
||||||
|
<dt>Period End</dt>
|
||||||
|
<dd>{new Date(subscription.current_period_end * 1000).toString()}</dd>
|
||||||
|
<dt>Status</dt>
|
||||||
|
<dd>{subscription.cancel_at_period_end ? 'Disabled' : 'Active'}</dd>
|
||||||
|
</dl>
|
||||||
|
{unsubBtn()}
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section class='account'>
|
<section class='account' onClick={tlClick}>
|
||||||
<div>
|
<div>
|
||||||
<h1>{account.name}</h1>
|
<h1>{account.name}</h1>
|
||||||
<dl>
|
<div class="list">
|
||||||
<dt>Subscription</dt>
|
<figure>
|
||||||
<dd>{account.subscribed ? 'some date' : 'unsubscribed'}</dd>
|
<figcaption>spawn new construct</figcaption>
|
||||||
</dl>
|
<button onClick={() => sendConstructSpawn()} type="submit">
|
||||||
<button><a href={`mailto:humans@mnml.gg?subject=Account%20Support:%20${account.name}`}>✉ support</a></button>
|
¤50
|
||||||
|
</button>
|
||||||
|
</figure>
|
||||||
|
</div>
|
||||||
<button onClick={() => logout()}>Logout</button>
|
<button onClick={() => logout()}>Logout</button>
|
||||||
|
<button><a href={`mailto:humans@mnml.gg?subject=Account%20Support:%20${account.name}`}>✉ support</a></button>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="email">Email Settings:</label>
|
<label for="email">Email Settings:</label>
|
||||||
@ -116,11 +177,11 @@ class AccountStatus extends Component {
|
|||||||
class="login-input"
|
class="login-input"
|
||||||
type="email"
|
type="email"
|
||||||
name="email"
|
name="email"
|
||||||
value={this.state.email}
|
value={emailState}
|
||||||
onInput={linkState(this, 'email')}
|
onInput={linkState(this, 'emailState')}
|
||||||
placeholder="recovery@email.tld"
|
placeholder="recovery@email.tld"
|
||||||
/>
|
/>
|
||||||
<button onClick={() => setEmail(this.state.email)}>Update</button>
|
<button onClick={() => sendSetEmail(emailState)}>Update</button>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="current">Password:</label>
|
<label for="current">Password:</label>
|
||||||
@ -128,39 +189,34 @@ class AccountStatus extends Component {
|
|||||||
class="login-input"
|
class="login-input"
|
||||||
type="password"
|
type="password"
|
||||||
name="current"
|
name="current"
|
||||||
value={this.state.setPassword.current}
|
value={passwordState.current}
|
||||||
onInput={linkState(this, 'setPassword.current')}
|
onInput={linkState(this, 'passwordState.current')}
|
||||||
placeholder="current"
|
placeholder="current"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
class="login-input"
|
class="login-input"
|
||||||
type="password"
|
type="password"
|
||||||
name="new"
|
name="new"
|
||||||
value={this.state.setPassword.password}
|
value={passwordState.password}
|
||||||
onInput={linkState(this, 'setPassword.password')}
|
onInput={linkState(this, 'passwordState.password')}
|
||||||
placeholder="new password"
|
placeholder="new password"
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
class="login-input"
|
class="login-input"
|
||||||
type="password"
|
type="password"
|
||||||
name="confirm"
|
name="confirm"
|
||||||
value={this.state.setPassword.confirm}
|
value={passwordState.confirm}
|
||||||
onInput={linkState(this, 'setPassword.confirm')}
|
onInput={linkState(this, 'passwordState.confirm')}
|
||||||
placeholder="confirm"
|
placeholder="confirm"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
disabled={setPasswordDisabled()}
|
disabled={setPasswordDisabled()}
|
||||||
onClick={() => setPassword(this.state.setPassword.current, this.state.setPassword.password)}>
|
onClick={() => sendSetPassword(passwordState.current, passwordState.password)}>
|
||||||
Set Password
|
Set Password
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="list">
|
<div>
|
||||||
<figure>
|
{subInfo()}
|
||||||
<figcaption>spawn new construct</figcaption>
|
|
||||||
<button onClick={() => sendConstructSpawn()} type="submit">
|
|
||||||
¤50
|
|
||||||
</button>
|
|
||||||
</figure>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -13,11 +13,18 @@ function pingColour(ping) {
|
|||||||
const addState = connect(
|
const addState = connect(
|
||||||
function receiveState(state) {
|
function receiveState(state) {
|
||||||
const {
|
const {
|
||||||
|
ws,
|
||||||
account,
|
account,
|
||||||
ping,
|
ping,
|
||||||
} = state;
|
} = state;
|
||||||
|
|
||||||
|
function sendAccountStates() {
|
||||||
|
ws.sendEmailState();
|
||||||
|
ws.sendSubscriptionState();
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
sendAccountStates,
|
||||||
account,
|
account,
|
||||||
ping,
|
ping,
|
||||||
};
|
};
|
||||||
@ -49,10 +56,16 @@ function AccountStatus(args) {
|
|||||||
account,
|
account,
|
||||||
ping,
|
ping,
|
||||||
accountPage,
|
accountPage,
|
||||||
|
sendAccountStates,
|
||||||
} = args;
|
} = args;
|
||||||
|
|
||||||
if (!account) return null;
|
if (!account) return null;
|
||||||
|
|
||||||
|
function accountClick() {
|
||||||
|
sendAccountStates();
|
||||||
|
accountPage();
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="account-status">
|
<div class="account-status">
|
||||||
<div class="account-info">
|
<div class="account-info">
|
||||||
@ -61,7 +74,7 @@ function AccountStatus(args) {
|
|||||||
<div class="ping-text">{ping}ms</div>
|
<div class="ping-text">{ping}ms</div>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="account-header credits">{`¤${account.balance}`}</h3>
|
<h3 class="account-header credits">{`¤${account.balance}`}</h3>
|
||||||
<button onClick={() => accountPage()}>⚙ account</button>
|
<button onClick={accountClick}>⚙ account</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ function BitsBtn(args) {
|
|||||||
} = args;
|
} = args;
|
||||||
function subscribeClick() {
|
function subscribeClick() {
|
||||||
stripe.redirectToCheckout({
|
stripe.redirectToCheckout({
|
||||||
items: [{ plan: 'plan_FGmRwawcOJJ7Nv', quantity: 1 }],
|
items: [{ plan: 'plan_Fhl9r7UdMadjGi', quantity: 1 }],
|
||||||
successUrl: 'http://localhost',
|
successUrl: 'http://localhost',
|
||||||
cancelUrl: 'http://localhost',
|
cancelUrl: 'http://localhost',
|
||||||
clientReferenceId: account.id,
|
clientReferenceId: account.id,
|
||||||
|
|||||||
@ -6,6 +6,8 @@ const actions = require('./../actions');
|
|||||||
const addState = connect(
|
const addState = connect(
|
||||||
function receiveState(state) {
|
function receiveState(state) {
|
||||||
const {
|
const {
|
||||||
|
constructs,
|
||||||
|
teamPage,
|
||||||
teamSelect,
|
teamSelect,
|
||||||
ws,
|
ws,
|
||||||
} = state;
|
} = state;
|
||||||
@ -15,18 +17,34 @@ const addState = connect(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
constructLength: constructs.length,
|
||||||
sendAccountSetTeam,
|
sendAccountSetTeam,
|
||||||
|
teamPage,
|
||||||
teamSelect,
|
teamSelect,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
function receiveDispatch(dispatch) {
|
||||||
|
function setTeamPage(value) {
|
||||||
|
return dispatch(actions.setTeamPage(value));
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
setTeamPage,
|
||||||
|
};
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
function TeamCtrl(args) {
|
function TeamCtrl(args) {
|
||||||
const {
|
const {
|
||||||
teamSelect,
|
constructLength,
|
||||||
sendAccountSetTeam,
|
sendAccountSetTeam,
|
||||||
|
setTeamPage,
|
||||||
|
teamPage,
|
||||||
|
teamSelect,
|
||||||
} = args;
|
} = args;
|
||||||
|
|
||||||
|
const disableDecrement = teamPage === 0;
|
||||||
|
const disableIncrement = (teamPage + 1) * 6 >= constructLength;
|
||||||
return (
|
return (
|
||||||
<aside>
|
<aside>
|
||||||
<div class="timer-container"></div>
|
<div class="timer-container"></div>
|
||||||
@ -36,6 +54,11 @@ function TeamCtrl(args) {
|
|||||||
onClick={sendAccountSetTeam}>
|
onClick={sendAccountSetTeam}>
|
||||||
Set Team
|
Set Team
|
||||||
</button>
|
</button>
|
||||||
|
<div class="team-page-ctrl">
|
||||||
|
<button onClick={() => setTeamPage(teamPage - 1)} disabled={disableDecrement}> « </button>
|
||||||
|
<h2> {teamPage} </h2>
|
||||||
|
<button onClick={() => setTeamPage(teamPage + 1)} disabled={disableIncrement}> » </button>
|
||||||
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ const { ConstructAvatar } = require('./construct');
|
|||||||
|
|
||||||
const addState = connect(
|
const addState = connect(
|
||||||
function receiveState(state) {
|
function receiveState(state) {
|
||||||
const { ws, constructs, teamSelect } = state;
|
const { ws, constructs, teamPage, teamSelect } = state;
|
||||||
|
|
||||||
function sendConstructSpawn(name) {
|
function sendConstructSpawn(name) {
|
||||||
return ws.sendMtxConstructSpawn(name);
|
return ws.sendMtxConstructSpawn(name);
|
||||||
@ -15,6 +15,7 @@ const addState = connect(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
constructs,
|
constructs,
|
||||||
|
teamPage,
|
||||||
teamSelect,
|
teamSelect,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -32,6 +33,7 @@ const addState = connect(
|
|||||||
function Team(args) {
|
function Team(args) {
|
||||||
const {
|
const {
|
||||||
constructs,
|
constructs,
|
||||||
|
teamPage,
|
||||||
teamSelect,
|
teamSelect,
|
||||||
setTeam,
|
setTeam,
|
||||||
} = args;
|
} = args;
|
||||||
@ -54,8 +56,12 @@ function Team(args) {
|
|||||||
teamSelect[insert] = id;
|
teamSelect[insert] = id;
|
||||||
return setTeam(teamSelect);
|
return setTeam(teamSelect);
|
||||||
}
|
}
|
||||||
|
console.log(constructs.length);
|
||||||
|
const dispConstructs = constructs.length >= ((teamPage + 1) * 6)
|
||||||
|
? constructs.slice(teamPage * 6, (teamPage + 1) * 6)
|
||||||
|
: constructs.slice(teamPage * 6, constructs.length);
|
||||||
|
|
||||||
const constructPanels = constructs.map(construct => {
|
const constructPanels = dispConstructs.map(construct => {
|
||||||
const colour = teamSelect.indexOf(construct.id);
|
const colour = teamSelect.indexOf(construct.id);
|
||||||
const selected = colour > -1;
|
const selected = colour > -1;
|
||||||
|
|
||||||
|
|||||||
@ -3,8 +3,17 @@ const eachSeries = require('async/eachSeries');
|
|||||||
const actions = require('./actions');
|
const actions = require('./actions');
|
||||||
const { TIMES } = require('./constants');
|
const { TIMES } = require('./constants');
|
||||||
const animations = require('./animations.utils');
|
const animations = require('./animations.utils');
|
||||||
|
const { infoToast, errorToast } = require('./utils');
|
||||||
|
|
||||||
function registerEvents(store) {
|
function registerEvents(store) {
|
||||||
|
function notify(msg) {
|
||||||
|
return infoToast(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
function error(msg) {
|
||||||
|
return errorToast(msg);
|
||||||
|
}
|
||||||
|
|
||||||
function setPing(ping) {
|
function setPing(ping) {
|
||||||
store.dispatch(actions.setPing(ping));
|
store.dispatch(actions.setPing(ping));
|
||||||
}
|
}
|
||||||
@ -18,6 +27,14 @@ function registerEvents(store) {
|
|||||||
setNav('play');
|
setNav('play');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setSubscription(sub) {
|
||||||
|
const { subscription } = store.getState();
|
||||||
|
if (subscription && sub.cancel_at_period_end) {
|
||||||
|
notify('Your subscription has been cancelled. Thank you for your support.');
|
||||||
|
}
|
||||||
|
store.dispatch(actions.setSubscription(sub));
|
||||||
|
}
|
||||||
|
|
||||||
function setConstructList(constructs) {
|
function setConstructList(constructs) {
|
||||||
store.dispatch(actions.setConstructs(constructs));
|
store.dispatch(actions.setConstructs(constructs));
|
||||||
}
|
}
|
||||||
@ -222,7 +239,10 @@ function registerEvents(store) {
|
|||||||
setPing,
|
setPing,
|
||||||
setShop,
|
setShop,
|
||||||
setTeam,
|
setTeam,
|
||||||
|
setSubscription,
|
||||||
setWs,
|
setWs,
|
||||||
|
|
||||||
|
notify,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -44,7 +44,10 @@ module.exports = {
|
|||||||
skip: createReducer(false, 'SET_SKIP'),
|
skip: createReducer(false, 'SET_SKIP'),
|
||||||
shop: createReducer(false, 'SET_SHOP'),
|
shop: createReducer(false, 'SET_SHOP'),
|
||||||
|
|
||||||
|
subscription: createReducer(null, 'SET_SUBSCRIPTION'),
|
||||||
|
|
||||||
team: createReducer([], 'SET_TEAM'),
|
team: createReducer([], 'SET_TEAM'),
|
||||||
|
teamPage: createReducer(0, 'SET_TEAM_PAGE'),
|
||||||
teamSelect: createReducer([null, null, null], 'SET_TEAM_SELECT'),
|
teamSelect: createReducer([null, null, null], 'SET_TEAM_SELECT'),
|
||||||
|
|
||||||
vboxHighlight: createReducer([], 'SET_VBOX_HIGHLIGHT'),
|
vboxHighlight: createReducer([], 'SET_VBOX_HIGHLIGHT'),
|
||||||
|
|||||||
@ -54,6 +54,10 @@ function createSocket(events) {
|
|||||||
send(['AccountSetTeam', { ids }]);
|
send(['AccountSetTeam', { ids }]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sendSubscriptionEnding(ending) {
|
||||||
|
send(['SubscriptionEnding', { ending }]);
|
||||||
|
}
|
||||||
|
|
||||||
function sendGameState(id) {
|
function sendGameState(id) {
|
||||||
send(['GameState', { id }]);
|
send(['GameState', { id }]);
|
||||||
}
|
}
|
||||||
@ -139,6 +143,15 @@ function createSocket(events) {
|
|||||||
function sendMtxConstructSpawn() {
|
function sendMtxConstructSpawn() {
|
||||||
send(['MtxConstructSpawn', {}]);
|
send(['MtxConstructSpawn', {}]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sendEmailState() {
|
||||||
|
send(['EmailState', {}]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendSubscriptionState() {
|
||||||
|
send(['SubscriptionState', {}]);
|
||||||
|
}
|
||||||
|
|
||||||
// -------------
|
// -------------
|
||||||
// Incoming
|
// Incoming
|
||||||
// -------------
|
// -------------
|
||||||
@ -166,6 +179,11 @@ function createSocket(events) {
|
|||||||
events.setTeam(constructs);
|
events.setTeam(constructs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onSubscriptionState(sub) {
|
||||||
|
// events.subscriptionState(`Subscription cancelled. Your subscription will remain active until ${exp}. Thank you for your support.`);
|
||||||
|
events.setSubscription(sub);
|
||||||
|
}
|
||||||
|
|
||||||
function onConstructSpawn(construct) {
|
function onConstructSpawn(construct) {
|
||||||
events.setNewConstruct(construct);
|
events.setNewConstruct(construct);
|
||||||
}
|
}
|
||||||
@ -200,6 +218,7 @@ function createSocket(events) {
|
|||||||
AccountTeam: onAccountTeam,
|
AccountTeam: onAccountTeam,
|
||||||
AccountInstances: onAccountInstances,
|
AccountInstances: onAccountInstances,
|
||||||
AccountShop: onAccountShop,
|
AccountShop: onAccountShop,
|
||||||
|
SubscriptionState: onSubscriptionState,
|
||||||
ConstructSpawn: onConstructSpawn,
|
ConstructSpawn: onConstructSpawn,
|
||||||
GameState: onGameState,
|
GameState: onGameState,
|
||||||
EmailState: onEmailState,
|
EmailState: onEmailState,
|
||||||
@ -296,6 +315,7 @@ function createSocket(events) {
|
|||||||
sendAccountInstances,
|
sendAccountInstances,
|
||||||
sendAccountSetTeam,
|
sendAccountSetTeam,
|
||||||
|
|
||||||
|
|
||||||
sendGameState,
|
sendGameState,
|
||||||
sendGameReady,
|
sendGameReady,
|
||||||
sendGameSkill,
|
sendGameSkill,
|
||||||
@ -315,6 +335,10 @@ function createSocket(events) {
|
|||||||
|
|
||||||
sendItemInfo,
|
sendItemInfo,
|
||||||
|
|
||||||
|
sendEmailState,
|
||||||
|
sendSubscriptionState,
|
||||||
|
sendSubscriptionEnding,
|
||||||
|
|
||||||
sendMtxApply,
|
sendMtxApply,
|
||||||
sendMtxBuy,
|
sendMtxBuy,
|
||||||
sendMtxConstructSpawn,
|
sendMtxConstructSpawn,
|
||||||
|
|||||||
@ -1,6 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
export MNML_USER=$(whoami)
|
|
||||||
export MNML_PG_PASSWORD=$(openssl rand -base64 16)
|
|
||||||
export MNML_PG_HOST="localhost"
|
|
||||||
|
|
||||||
@ -3,3 +3,6 @@ DATABASE_URL=postgres://mnml:password@somewhere/mnml
|
|||||||
MAIL_ADDRESS=machines@mnml.gg
|
MAIL_ADDRESS=machines@mnml.gg
|
||||||
MAIL_DOMAIN=vinyl.mnml.gg
|
MAIL_DOMAIN=vinyl.mnml.gg
|
||||||
MAIL_PASSWORD=mmmmmmmmmmmmmmmm
|
MAIL_PASSWORD=mmmmmmmmmmmmmmmm
|
||||||
|
|
||||||
|
STRIPE_SECRET=shhhhhhhhhh
|
||||||
|
STRIPE_WH_SECRET=SHHHHHHH
|
||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mnml-ops",
|
"name": "mnml-ops",
|
||||||
"version": "0.3.0",
|
"version": "1.0.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "mnml"
|
name = "mnml"
|
||||||
version = "0.3.0"
|
version = "1.0.0"
|
||||||
authors = ["ntr <ntr@smokestack.io>"]
|
authors = ["ntr <ntr@smokestack.io>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
@ -38,4 +38,5 @@ ws = "0.8"
|
|||||||
lettre = "0.9"
|
lettre = "0.9"
|
||||||
lettre_email = "0.9"
|
lettre_email = "0.9"
|
||||||
|
|
||||||
stripe-rust = { version = "0.10.4", features = ["webhooks"] }
|
stripe-rust = "0.10"
|
||||||
|
# stripe-rust = { path = "/home/ntr/code/stripe-rs" }
|
||||||
|
|||||||
@ -132,7 +132,7 @@ impl Events {
|
|||||||
match self.clients.get_mut(&id) {
|
match self.clients.get_mut(&id) {
|
||||||
Some(client) => {
|
Some(client) => {
|
||||||
client.subs.insert(obj);
|
client.subs.insert(obj);
|
||||||
info!("client subscriptions={:?}", client.subs.len());
|
info!("client={:?} subscriptions={:?}", id, client.subs.len());
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
None => return Err(format_err!("unknown client {:?}", id))
|
None => return Err(format_err!("unknown client {:?}", id))
|
||||||
|
|||||||
@ -146,6 +146,8 @@ fn main() {
|
|||||||
let pg_pool = pool.clone();
|
let pg_pool = pool.clone();
|
||||||
let mailer = mail::listen(mail_rx);
|
let mailer = mail::listen(mail_rx);
|
||||||
|
|
||||||
|
let stripe = payments::stripe_client();
|
||||||
|
|
||||||
spawn(move || http::start(http_pool, mailer));
|
spawn(move || http::start(http_pool, mailer));
|
||||||
spawn(move || warden.listen());
|
spawn(move || warden.listen());
|
||||||
spawn(move || warden::upkeep_tick(warden_tick_tx));
|
spawn(move || warden::upkeep_tick(warden_tick_tx));
|
||||||
@ -154,5 +156,5 @@ fn main() {
|
|||||||
|
|
||||||
// the main thread becomes this ws listener
|
// the main thread becomes this ws listener
|
||||||
let rpc_pool = pool.clone();
|
let rpc_pool = pool.clone();
|
||||||
rpc::start(rpc_pool, rpc_events_tx);
|
rpc::start(rpc_pool, rpc_events_tx, stripe);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
|
use std::env;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
use http::State;
|
use http::State;
|
||||||
use iron::prelude::*;
|
use iron::prelude::*;
|
||||||
use iron::response::HttpResponse;
|
|
||||||
use iron::status;
|
use iron::status;
|
||||||
use persistent::Read as Readable;
|
use persistent::Read as Readable;
|
||||||
|
|
||||||
@ -12,15 +13,16 @@ use postgres::transaction::Transaction;
|
|||||||
use failure::Error;
|
use failure::Error;
|
||||||
use failure::err_msg;
|
use failure::err_msg;
|
||||||
|
|
||||||
use stripe::{Event, EventObject, CheckoutSession, SubscriptionStatus};
|
use stripe::{Client, Event, EventObject, CheckoutSession, SubscriptionStatus, Subscription};
|
||||||
|
|
||||||
use http::{MnmlHttpError};
|
use http::{MnmlHttpError};
|
||||||
use pg::{PgPool};
|
use pg::{Db, PgPool};
|
||||||
use account;
|
use account;
|
||||||
|
use account::Account;
|
||||||
|
|
||||||
pub fn subscription_account(tx: &mut Transaction, sub: String) -> Result<Uuid, Error> {
|
pub fn subscription_account(tx: &mut Transaction, sub: String) -> Result<Uuid, Error> {
|
||||||
let query = "
|
let query = "
|
||||||
SELECT account
|
SELECT account, customer, checkout, subscription
|
||||||
FROM stripe_subscriptions
|
FROM stripe_subscriptions
|
||||||
WHERE subscription = $1;
|
WHERE subscription = $1;
|
||||||
";
|
";
|
||||||
@ -34,6 +36,69 @@ pub fn subscription_account(tx: &mut Transaction, sub: String) -> Result<Uuid, E
|
|||||||
Ok(row.get(0))
|
Ok(row.get(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn subscription_ending(tx: &mut Transaction, client: &Client, account: &Account, ending: bool) -> Result<Option<Subscription>, Error> {
|
||||||
|
let query = "
|
||||||
|
SELECT account, customer, checkout, subscription
|
||||||
|
FROM stripe_subscriptions
|
||||||
|
WHERE account = $1;
|
||||||
|
";
|
||||||
|
|
||||||
|
let result = tx
|
||||||
|
.query(query, &[&account.id])?;
|
||||||
|
|
||||||
|
let row = result.iter().next()
|
||||||
|
.ok_or(err_msg("user not subscribed"))?;
|
||||||
|
|
||||||
|
let _customer: String = row.get(1);
|
||||||
|
let _checkout: String = row.get(2);
|
||||||
|
let subscription: String = row.get(3);
|
||||||
|
|
||||||
|
let id = subscription.parse()?;
|
||||||
|
let mut params = stripe::UpdateSubscription::new();
|
||||||
|
params.cancel_at_period_end = Some(ending);
|
||||||
|
|
||||||
|
match stripe::Subscription::update(client, &id, params) {
|
||||||
|
Ok(s) => {
|
||||||
|
info!("subscription changed ending={:?} account={:?} subscription={:?}", ending, account, s);
|
||||||
|
Ok(Some(s))
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
warn!("{:?}", e);
|
||||||
|
Err(err_msg("unable to update subscription"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn account_subscription(db: &Db, client: &Client, account: &Account) -> Result<Option<Subscription>, Error> {
|
||||||
|
let query = "
|
||||||
|
SELECT account, customer, checkout, subscription
|
||||||
|
FROM stripe_subscriptions
|
||||||
|
WHERE account = $1;
|
||||||
|
";
|
||||||
|
|
||||||
|
let result = db
|
||||||
|
.query(query, &[&account.id])?;
|
||||||
|
|
||||||
|
let row = match result.iter().next() {
|
||||||
|
Some(r) => r,
|
||||||
|
None => return Ok(None),
|
||||||
|
};
|
||||||
|
|
||||||
|
let _customer: String = row.get(1);
|
||||||
|
let _checkout: String = row.get(2);
|
||||||
|
let subscription: String = row.get(3);
|
||||||
|
|
||||||
|
let id = subscription.parse()?;
|
||||||
|
|
||||||
|
match stripe::Subscription::retrieve(client, &id, &[]) {
|
||||||
|
Ok(s) => Ok(Some(s)),
|
||||||
|
Err(e) => {
|
||||||
|
warn!("{:?}", e);
|
||||||
|
Err(err_msg("unable to retrieve subscription"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// we use i64 because it is converted to BIGINT for pg
|
// we use i64 because it is converted to BIGINT for pg
|
||||||
// and we can losslessly pull it into u32 which is big
|
// and we can losslessly pull it into u32 which is big
|
||||||
// enough for the ballers
|
// enough for the ballers
|
||||||
@ -45,7 +110,7 @@ const CREDITS_SUB_BONUS: i64 = 40;
|
|||||||
// we ensure that we store each object in pg with a link to the object
|
// we ensure that we store each object in pg with a link to the object
|
||||||
// and to the account id in case of refunds
|
// and to the account id in case of refunds
|
||||||
#[derive(Debug,Clone,Serialize,Deserialize)]
|
#[derive(Debug,Clone,Serialize,Deserialize)]
|
||||||
enum StripeData {
|
pub enum StripeData {
|
||||||
Customer { account: Uuid, customer: String, checkout: String },
|
Customer { account: Uuid, customer: String, checkout: String },
|
||||||
Subscription { account: Uuid, customer: String, checkout: String, subscription: String, },
|
Subscription { account: Uuid, customer: String, checkout: String, subscription: String, },
|
||||||
|
|
||||||
@ -193,10 +258,31 @@ fn process_stripe_event(event: Event, pool: &PgPool) -> Result<String, Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn stripe(req: &mut Request) -> IronResult<Response> {
|
pub fn stripe(req: &mut Request) -> IronResult<Response> {
|
||||||
let state = req.get::<Readable<State>>().unwrap();
|
let webhook_secret = env::var("STRIPE_WH_SECRET").ok();
|
||||||
let event = match req.get::<bodyparser::Struct<Event>>() {
|
let state= req.get::<Readable<State>>().unwrap();
|
||||||
Ok(Some(b)) => b,
|
|
||||||
_ => return Err(IronError::from(MnmlHttpError::BadRequest)),
|
let event = match webhook_secret {
|
||||||
|
// prod mode
|
||||||
|
Some(s) => {
|
||||||
|
let mut payload = String::new();
|
||||||
|
req.body.read_to_string(&mut payload)
|
||||||
|
.or(Err(IronError::from(MnmlHttpError::BadRequest)))?;
|
||||||
|
|
||||||
|
let sig = match req.headers.get_raw("Stripe-Signature") {
|
||||||
|
Some(s) => String::from_utf8(s[0].clone())
|
||||||
|
.or(Err(IronError::from(MnmlHttpError::BadRequest)))?,
|
||||||
|
None => return Err(IronError::from(MnmlHttpError::BadRequest)),
|
||||||
|
};
|
||||||
|
|
||||||
|
stripe::Webhook::construct_event(payload, sig, s)
|
||||||
|
.or(Err(IronError::from(MnmlHttpError::BadRequest)))?
|
||||||
|
},
|
||||||
|
|
||||||
|
// dev server
|
||||||
|
None => match req.get::<bodyparser::Struct<Event>>() {
|
||||||
|
Ok(Some(b)) => b,
|
||||||
|
_ => return Err(IronError::from(MnmlHttpError::BadRequest)),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
match process_stripe_event(event, &state.pool) {
|
match process_stripe_event(event, &state.pool) {
|
||||||
@ -211,6 +297,13 @@ pub fn stripe(req: &mut Request) -> IronResult<Response> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn stripe_client() -> Client {
|
||||||
|
let secret = env::var("STRIPE_SECRET")
|
||||||
|
.expect("STRIPE_SECRET must be set");
|
||||||
|
|
||||||
|
stripe::Client::new(secret)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
@ -11,6 +11,8 @@ use failure::err_msg;
|
|||||||
use serde_cbor::{from_slice, to_vec};
|
use serde_cbor::{from_slice, to_vec};
|
||||||
use cookie::Cookie;
|
use cookie::Cookie;
|
||||||
|
|
||||||
|
use stripe::{Client as StripeClient, Subscription};
|
||||||
|
|
||||||
use crossbeam_channel::{unbounded, Sender as CbSender};
|
use crossbeam_channel::{unbounded, Sender as CbSender};
|
||||||
use ws::{listen, CloseCode, Message, Handler, Request, Response};
|
use ws::{listen, CloseCode, Message, Handler, Request, Response};
|
||||||
|
|
||||||
@ -23,6 +25,7 @@ use instance::{Instance, instance_state, instance_practice, instance_ready};
|
|||||||
use item::{Item, ItemInfoCtr, item_info};
|
use item::{Item, ItemInfoCtr, item_info};
|
||||||
use mtx;
|
use mtx;
|
||||||
use mail;
|
use mail;
|
||||||
|
use payments;
|
||||||
use mail::Email;
|
use mail::Email;
|
||||||
use pg::{Db};
|
use pg::{Db};
|
||||||
use pg::{PgPool};
|
use pg::{PgPool};
|
||||||
@ -37,13 +40,16 @@ pub enum RpcMessage {
|
|||||||
AccountTeam(Vec<Construct>),
|
AccountTeam(Vec<Construct>),
|
||||||
AccountInstances(Vec<Instance>),
|
AccountInstances(Vec<Instance>),
|
||||||
AccountShop(mtx::Shop),
|
AccountShop(mtx::Shop),
|
||||||
|
|
||||||
ConstructSpawn(Construct),
|
ConstructSpawn(Construct),
|
||||||
EmailState(Email),
|
|
||||||
GameState(Game),
|
GameState(Game),
|
||||||
ItemInfo(ItemInfoCtr),
|
ItemInfo(ItemInfoCtr),
|
||||||
|
|
||||||
InstanceState(Instance),
|
InstanceState(Instance),
|
||||||
|
|
||||||
|
EmailState(Option<Email>),
|
||||||
|
SubscriptionState(Option<Subscription>),
|
||||||
|
|
||||||
Pong(()),
|
Pong(()),
|
||||||
|
|
||||||
DevResolutions(Resolutions),
|
DevResolutions(Resolutions),
|
||||||
@ -75,6 +81,10 @@ enum RpcRequest {
|
|||||||
AccountConstructs {},
|
AccountConstructs {},
|
||||||
AccountSetTeam { ids: Vec<Uuid> },
|
AccountSetTeam { ids: Vec<Uuid> },
|
||||||
|
|
||||||
|
SubscriptionEnding { ending: bool },
|
||||||
|
SubscriptionState {},
|
||||||
|
EmailState {},
|
||||||
|
|
||||||
InstanceQueue {},
|
InstanceQueue {},
|
||||||
InstancePractice {},
|
InstancePractice {},
|
||||||
InstanceReady { instance_id: Uuid },
|
InstanceReady { instance_id: Uuid },
|
||||||
@ -92,6 +102,7 @@ struct Connection {
|
|||||||
pub id: usize,
|
pub id: usize,
|
||||||
pub ws: CbSender<RpcMessage>,
|
pub ws: CbSender<RpcMessage>,
|
||||||
pool: PgPool,
|
pool: PgPool,
|
||||||
|
stripe: StripeClient,
|
||||||
account: Option<Account>,
|
account: Option<Account>,
|
||||||
events: CbSender<Event>,
|
events: CbSender<Event>,
|
||||||
}
|
}
|
||||||
@ -135,13 +146,19 @@ impl Connection {
|
|||||||
|
|
||||||
let response = match v {
|
let response = match v {
|
||||||
RpcRequest::AccountState {} =>
|
RpcRequest::AccountState {} =>
|
||||||
return Ok(RpcMessage::AccountState(account.clone())),
|
Ok(RpcMessage::AccountState(account.clone())),
|
||||||
RpcRequest::AccountConstructs {} =>
|
RpcRequest::AccountConstructs {} =>
|
||||||
Ok(RpcMessage::AccountConstructs(account::constructs(&mut tx, &account)?)),
|
Ok(RpcMessage::AccountConstructs(account::constructs(&mut tx, &account)?)),
|
||||||
|
|
||||||
RpcRequest::AccountSetTeam { ids } =>
|
RpcRequest::AccountSetTeam { ids } =>
|
||||||
Ok(RpcMessage::AccountTeam(account::set_team(&mut tx, &account, ids)?)),
|
Ok(RpcMessage::AccountTeam(account::set_team(&mut tx, &account, ids)?)),
|
||||||
|
|
||||||
|
RpcRequest::EmailState {} =>
|
||||||
|
Ok(RpcMessage::EmailState(mail::select_account(&db, account.id)?)),
|
||||||
|
|
||||||
|
RpcRequest::SubscriptionState {} =>
|
||||||
|
Ok(RpcMessage::SubscriptionState(payments::account_subscription(&db, &self.stripe, &account)?)),
|
||||||
|
|
||||||
// RpcRequest::AccountShop {} =>
|
// RpcRequest::AccountShop {} =>
|
||||||
// Ok(RpcMessage::AccountShop(mtx::account_shop(&mut tx, &account)?)),
|
// Ok(RpcMessage::AccountShop(mtx::account_shop(&mut tx, &account)?)),
|
||||||
|
|
||||||
@ -192,6 +209,9 @@ impl Connection {
|
|||||||
RpcRequest::MtxBuy { mtx } =>
|
RpcRequest::MtxBuy { mtx } =>
|
||||||
Ok(RpcMessage::AccountShop(mtx::buy(&mut tx, account, mtx)?)),
|
Ok(RpcMessage::AccountShop(mtx::buy(&mut tx, account, mtx)?)),
|
||||||
|
|
||||||
|
RpcRequest::SubscriptionEnding { ending } =>
|
||||||
|
Ok(RpcMessage::SubscriptionState(payments::subscription_ending(&mut tx, &self.stripe, account, ending)?)),
|
||||||
|
|
||||||
_ => Err(format_err!("unknown request request={:?}", request)),
|
_ => Err(format_err!("unknown request request={:?}", request)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -228,15 +248,6 @@ impl Handler for Connection {
|
|||||||
let db = self.pool.get().unwrap();
|
let db = self.pool.get().unwrap();
|
||||||
let mut tx = db.transaction().unwrap();
|
let mut tx = db.transaction().unwrap();
|
||||||
|
|
||||||
// email state
|
|
||||||
match mail::select_account(&db, a.id).unwrap() {
|
|
||||||
Some(e) => {
|
|
||||||
self.ws.send(RpcMessage::EmailState(e.clone())).unwrap();
|
|
||||||
self.events.send(Event::Subscribe(self.id, e.id)).unwrap();
|
|
||||||
},
|
|
||||||
None => (),
|
|
||||||
};
|
|
||||||
|
|
||||||
// send account constructs
|
// send account constructs
|
||||||
let account_constructs = account::constructs(&mut tx, a).unwrap();
|
let account_constructs = account::constructs(&mut tx, a).unwrap();
|
||||||
self.ws.send(RpcMessage::AccountConstructs(account_constructs)).unwrap();
|
self.ws.send(RpcMessage::AccountConstructs(account_constructs)).unwrap();
|
||||||
@ -270,8 +281,10 @@ impl Handler for Connection {
|
|||||||
// if the user queries the state of something
|
// if the user queries the state of something
|
||||||
// we tell events to push updates to them
|
// we tell events to push updates to them
|
||||||
match reply {
|
match reply {
|
||||||
RpcMessage::AccountState(ref v) =>
|
RpcMessage::AccountState(ref v) => {
|
||||||
self.events.send(Event::Subscribe(self.id, v.id)).unwrap(),
|
self.account = Some(v.clone());
|
||||||
|
self.events.send(Event::Subscribe(self.id, v.id)).unwrap()
|
||||||
|
},
|
||||||
RpcMessage::GameState(ref v) =>
|
RpcMessage::GameState(ref v) =>
|
||||||
self.events.send(Event::Subscribe(self.id, v.id)).unwrap(),
|
self.events.send(Event::Subscribe(self.id, v.id)).unwrap(),
|
||||||
RpcMessage::InstanceState(ref v) =>
|
RpcMessage::InstanceState(ref v) =>
|
||||||
@ -332,7 +345,7 @@ impl Handler for Connection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(pool: PgPool, events_tx: CbSender<Event>) {
|
pub fn start(pool: PgPool, events_tx: CbSender<Event>, stripe: StripeClient) {
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
listen("127.0.0.1:40055", move |out| {
|
listen("127.0.0.1:40055", move |out| {
|
||||||
|
|
||||||
@ -364,6 +377,7 @@ pub fn start(pool: PgPool, events_tx: CbSender<Event>) {
|
|||||||
account: None,
|
account: None,
|
||||||
ws: tx,
|
ws: tx,
|
||||||
pool: pool.clone(),
|
pool: pool.clone(),
|
||||||
|
stripe: stripe.clone(),
|
||||||
events: events_tx.clone(),
|
events: events_tx.clone(),
|
||||||
}
|
}
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user