mirror of
https://github.com/roleypoly/roleypoly-v1.git
synced 2025-04-25 04:09:12 +00:00
fix redirects, fix server syncs on join
This commit is contained in:
parent
032831aff1
commit
f7238ab091
14 changed files with 132 additions and 101 deletions
|
@ -7,7 +7,7 @@ module.exports = (R, $) => {
|
|||
|
||||
ctx.body = presentable
|
||||
} catch (e) {
|
||||
console.error(e.trace)
|
||||
console.error(e.trace || e.stack)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -29,6 +29,23 @@ module.exports = (R, $) => {
|
|||
ctx.body = server
|
||||
})
|
||||
|
||||
R.get('/api/server/:id/slug', async (ctx) => {
|
||||
const { userId } = ctx.session
|
||||
const { id } = ctx.params
|
||||
|
||||
const srv = $.discord.client.guilds.get(id)
|
||||
|
||||
console.log(srv)
|
||||
|
||||
if (srv == null) {
|
||||
ctx.body = { err: 'not found' }
|
||||
ctx.status = 404
|
||||
return
|
||||
}
|
||||
|
||||
ctx.body = await $.P.serverSlug(srv)
|
||||
})
|
||||
|
||||
R.patch('/api/server/:id', async (ctx) => {
|
||||
const { userId } = ctx.session
|
||||
const { id } = ctx.params
|
||||
|
|
|
@ -34,6 +34,7 @@ class DiscordService extends Service {
|
|||
if (this.isBot) {
|
||||
this.log.info('this roleypoly is a bot')
|
||||
this.client.on('message', this.handleMessage.bind(this))
|
||||
this.client.on('guildCreate', this.handleJoin.bind(this))
|
||||
}
|
||||
|
||||
for (let server of this.client.guilds.array()) {
|
||||
|
@ -216,6 +217,10 @@ class DiscordService extends Service {
|
|||
}
|
||||
}
|
||||
|
||||
async handleJoin (guild) {
|
||||
await this.ctx.server.ensure(guild)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = DiscordService
|
||||
|
|
|
@ -10,6 +10,15 @@ class PresentationService extends Service {
|
|||
this.cache = LRU({ max: 500, maxAge: 100 * 60 * 5 })
|
||||
}
|
||||
|
||||
serverSlug (server) {
|
||||
return {
|
||||
id: server.id,
|
||||
name: server.name,
|
||||
ownerID: server.ownerID,
|
||||
icon: server.icon
|
||||
}
|
||||
}
|
||||
|
||||
async oldPresentableServers (collection, userId) {
|
||||
let servers = []
|
||||
|
||||
|
@ -39,12 +48,7 @@ class PresentationService extends Service {
|
|||
nickname: gm.nickname,
|
||||
color: gm.displayHexColor
|
||||
},
|
||||
server: {
|
||||
id: server.id,
|
||||
name: server.name,
|
||||
ownerID: server.ownerID,
|
||||
icon: server.icon
|
||||
},
|
||||
server: this.serverSlug(server),
|
||||
roles: (incRoles) ? (await this.rolesByServer(server, sd)).map(r => ({ ...r, selected: gm.roles.has(r.id) })) : [],
|
||||
message: sd.message,
|
||||
categories: sd.categories,
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
"test": "react-scripts test --env=jsdom",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"homepage": "https://rp.kat.cafe",
|
||||
"proxy": {
|
||||
"/api": {
|
||||
"target": "http://localhost:6769"
|
||||
|
|
|
@ -39,7 +39,10 @@ export const userInit = async dispatch => {
|
|||
}
|
||||
|
||||
export const userLogout = async dispatch => {
|
||||
try {
|
||||
await superagent.post('/api/auth/logout')
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: Symbol.for('reset user')
|
||||
|
|
|
@ -10,8 +10,10 @@ export default class AddServer extends Component {
|
|||
polling = null
|
||||
|
||||
componentDidMount () {
|
||||
if (this.props.match.params.server !== undefined) {
|
||||
this.pollingStop = Actions.startServerPolling(this.props.dispatch)
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
if (this.pollingStop != null) {
|
||||
|
|
|
@ -8,7 +8,8 @@ import { fetchServers } from '../../actions'
|
|||
class OauthCallback extends Component {
|
||||
state = {
|
||||
notReady: true,
|
||||
message: 'chotto matte kudasai...'
|
||||
message: 'chotto matte kudasai...',
|
||||
redirect: '/s'
|
||||
}
|
||||
|
||||
async componentDidMount () {
|
||||
|
@ -21,6 +22,13 @@ class OauthCallback extends Component {
|
|||
return
|
||||
}
|
||||
|
||||
const stateToken = sp.get('state')
|
||||
const state = JSON.parse(window.sessionStorage.getItem('state') || 'null')
|
||||
|
||||
if (state !== null && state.state === stateToken && state.redirect != undefined) {
|
||||
this.setState({ redirect: state.redirect })
|
||||
}
|
||||
|
||||
this.props.history.replace(this.props.location.pathname)
|
||||
|
||||
let counter = 0
|
||||
|
@ -35,7 +43,7 @@ class OauthCallback extends Component {
|
|||
this.props.dispatch(fetchServers)
|
||||
} catch (e) {
|
||||
counter++
|
||||
if (counter > 12) {
|
||||
if (counter > 100) {
|
||||
this.setState({ message: "i couldn't log you in. :c" })
|
||||
} else {
|
||||
setTimeout(() => { retry() }, 250)
|
||||
|
@ -61,7 +69,7 @@ class OauthCallback extends Component {
|
|||
}
|
||||
|
||||
render () {
|
||||
return (this.state.notReady) ? this.state.message : <Redirect to='/s' />
|
||||
return (this.state.notReady) ? this.state.message : <Redirect to={this.state.redirect} replace />
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,9 @@ import React, { Component } from 'react'
|
|||
import { Redirect } from 'react-router-dom'
|
||||
import superagent from 'superagent'
|
||||
import { connect } from 'react-redux'
|
||||
import uuidv4 from 'uuid/v4'
|
||||
import { fetchServers } from '../../actions'
|
||||
import { URL } from 'url';
|
||||
|
||||
|
||||
@connect()
|
||||
class OauthCallback extends Component {
|
||||
|
@ -39,11 +40,15 @@ class OauthCallback extends Component {
|
|||
}
|
||||
|
||||
async componentDidMount () {
|
||||
const state = uuidv4()
|
||||
|
||||
const oUrl = new URL(window.location.href)
|
||||
if (oUrl.searchParams.has('r')) {
|
||||
this.setState({ redirect: oUrl.searchParams.get('r') })
|
||||
}
|
||||
|
||||
window.sessionStorage.setItem('state', JSON.stringify({ state, redirect: oUrl.searchParams.get('r') }))
|
||||
|
||||
try {
|
||||
await this.setupUser()
|
||||
|
||||
|
@ -53,9 +58,7 @@ class OauthCallback extends Component {
|
|||
const { body: { url } } = await superagent.get('/api/auth/redirect?url=✔️')
|
||||
const nUrl = new URL(url)
|
||||
|
||||
if (oUrl.searchParams.has('r')) {
|
||||
nUrl.searchParams.set('r', oUrl.searchParams.get('r'))
|
||||
}
|
||||
nUrl.searchParams.set('state', state)
|
||||
|
||||
window.location.href = nUrl.toString()
|
||||
}
|
||||
|
|
47
UI/src/components/servers/ServerLanding.js
Normal file
47
UI/src/components/servers/ServerLanding.js
Normal file
|
@ -0,0 +1,47 @@
|
|||
import React, { Component } from 'react'
|
||||
import { Link, Redirect } from 'react-router-dom'
|
||||
import superagent from 'superagent'
|
||||
import discordLogo from '../../pages/images/discord-logo.svg'
|
||||
|
||||
export default class ServerLanding extends Component {
|
||||
state = {
|
||||
server: null,
|
||||
exit: false
|
||||
}
|
||||
|
||||
async componentWillMount () {
|
||||
console.log(this.props)
|
||||
|
||||
try {
|
||||
const rsp = await superagent.get(`/api/server/${this.props.match.params.server}/slug`)
|
||||
this.setState({ server: rsp.body })
|
||||
} catch (e) {
|
||||
this.setState({ exit: true })
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
render () {
|
||||
if (this.state.exit === true) {
|
||||
return <Redirect to="/" />
|
||||
}
|
||||
|
||||
if (this.state.server === null) {
|
||||
return null //SPINNER
|
||||
}
|
||||
|
||||
return <div className="landing uk-width-1-1 uk-text-center">
|
||||
<div className="uk-container">
|
||||
<section>
|
||||
<h1>Hey there.</h1>
|
||||
<h4>{this.state.server.name} uses Roleypoly to manage self-assignable roles.</h4>
|
||||
<h5><span role="img">💖</span></h5>
|
||||
</section>
|
||||
<section>
|
||||
<Link to={`/oauth/flow?r=${window.location.pathname}`} className="uk-button rp-button discord"><img src={discordLogo} className="rp-button-logo"/> Sign in with Discord</Link>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import Navigation from './Navigation'
|
|||
import RolePicker from '../role-picker'
|
||||
import RoleEditor from '../role-editor'
|
||||
import AddServer from '../add-server'
|
||||
import Error404 from '../../pages/Error404'
|
||||
|
||||
// import mockData from './mockData'
|
||||
|
||||
|
@ -23,6 +24,8 @@ const mapState = ({ servers, user, appState }) => {
|
|||
@connect(mapState)
|
||||
class Servers extends Component {
|
||||
get defaultPath () {
|
||||
console.log(this.props.servers.toJS())
|
||||
|
||||
const first = this.props.servers.first()
|
||||
if (first != null) {
|
||||
return first.get('id')
|
||||
|
@ -35,18 +38,15 @@ class Servers extends Component {
|
|||
return <div className="servers">
|
||||
<Navigation className="servers__nav" servers={this.props.servers} user={this.props.user} />
|
||||
<div className='servers__content'>
|
||||
<Switch>
|
||||
<Route path='/s/' exact render={() => <Redirect to={`/s/${this.defaultPath}`} />} />
|
||||
<Route path='/s/:server/edit' component={RoleEditor} />
|
||||
<Route path='/s/:server' render={() =>
|
||||
<Scrollbars className={`fade-element ${(this.props.fade) ? 'fade' : ''}`} autoHeight autoHeightMax='calc(100vh - 80px)'>
|
||||
<Switch>
|
||||
<Route path='/s/add' component={AddServer} exact />
|
||||
<Route path='/s/:server' component={RolePicker} exact />
|
||||
<Route path='/s/:server/edit' component={RoleEditor} />
|
||||
<Route path='/s/:server' component={RolePicker} />
|
||||
<Route path='/s' exact render={() => <Redirect to={`/s/${this.defaultPath}`} />} />
|
||||
<Route component={Error404} />
|
||||
</Switch>
|
||||
</Scrollbars>
|
||||
} />
|
||||
</Switch>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
|
|
@ -1,35 +1,14 @@
|
|||
import React, { Component, Fragment } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import Scrollbars from 'react-custom-scrollbars'
|
||||
import Typist from 'react-typist'
|
||||
import moment from 'moment'
|
||||
import React from 'react'
|
||||
import './landing.sass'
|
||||
import discordLogo from './images/discord-logo.svg'
|
||||
import RoleypolyDemo from '../components/demos/roleypoly'
|
||||
import TypingDemo from '../components/demos/typing'
|
||||
|
||||
const Landing = ({ root = false }) =>
|
||||
const Error404 = ({ root = false }) =>
|
||||
<div className="landing uk-width-1-1 uk-text-center">
|
||||
<div className="uk-container">
|
||||
<section>
|
||||
<h1>Self-assignable Discord roles for humans.</h1>
|
||||
<h4>Ditch bot commands once and for all.</h4>
|
||||
</section>
|
||||
<section>
|
||||
<Link to="/oauth/flow" className="uk-button rp-button discord"><img src={discordLogo} className="rp-button-logo"/> Sign in with Discord</Link>
|
||||
</section>
|
||||
<section uk-grid="">
|
||||
{/* Typist */}
|
||||
<div className="uk-width-1-2">
|
||||
<TypingDemo />
|
||||
<p className="subtext">Why are we stuck in the stupid ages?</p>
|
||||
</div>
|
||||
{/* role side */}
|
||||
<div className="uk-width-1-2">
|
||||
<RoleypolyDemo />
|
||||
<p className="subtext">It's 2018. We can do better.</p>
|
||||
</div>
|
||||
<h1><span role="img">💔</span> g-gomen nasai</h1>
|
||||
<h4>I'm not sure what page you were looking for <span role="img">😢</span></h4>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
export default Landing
|
||||
|
||||
export default Error404
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
import React, { Component, Fragment } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import Scrollbars from 'react-custom-scrollbars'
|
||||
import Typist from 'react-typist'
|
||||
import moment from 'moment'
|
||||
import './landing.sass'
|
||||
import discordLogo from './images/discord-logo.svg'
|
||||
import RoleypolyDemo from '../components/demos/roleypoly'
|
||||
import TypingDemo from '../components/demos/typing'
|
||||
|
||||
const Landing = ({ root = false }) =>
|
||||
<div className="landing uk-width-1-1 uk-text-center">
|
||||
<div className="uk-container">
|
||||
<section>
|
||||
<h1>Self-assignable Discord roles for humans.</h1>
|
||||
<h4>Ditch bot commands once and for all.</h4>
|
||||
</section>
|
||||
<section>
|
||||
<Link to="/oauth/flow" className="uk-button rp-button discord"><img src={discordLogo} className="rp-button-logo"/> Sign in with Discord</Link>
|
||||
</section>
|
||||
<section uk-grid="">
|
||||
{/* Typist */}
|
||||
<div className="uk-width-1-2">
|
||||
<TypingDemo />
|
||||
<p className="subtext">Why are we stuck in the stupid ages?</p>
|
||||
</div>
|
||||
{/* role side */}
|
||||
<div className="uk-width-1-2">
|
||||
<RoleypolyDemo />
|
||||
<p className="subtext">It's 2018. We can do better.</p>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
export default Landing
|
|
@ -6,7 +6,6 @@ import './pages.sass'
|
|||
import WhyNoRoles from './WhyNoRoles'
|
||||
import Error404 from './Error404'
|
||||
export { default as Landing } from './Landing'
|
||||
export { default as ServerLanding } from './ServerLanding'
|
||||
export { default as Error404 } from './Error404'
|
||||
|
||||
const Pages = (props) => {
|
||||
|
|
|
@ -7,7 +7,8 @@ import Servers from '../components/servers'
|
|||
import OauthCallback from '../components/oauth-callback'
|
||||
import OauthFlow from '../components/oauth-flow'
|
||||
import OauthBotFlow from '../components/oauth-bot-flow'
|
||||
import Pages, { Landing, Error404, ServerLanding } from '../pages'
|
||||
import Pages, { Landing, Error404 } from '../pages'
|
||||
import ServerLanding from '../components/servers/ServerLanding'
|
||||
|
||||
const aaa = (props) => (<div>{ JSON.stringify(props) }</div>)
|
||||
|
||||
|
@ -22,18 +23,15 @@ export default class AppRouter extends Component {
|
|||
}
|
||||
|
||||
return <Switch>
|
||||
{ (isLoggedIn)
|
||||
{ (isLoggedIn === true)
|
||||
|
||||
// YES LOGGED IN
|
||||
? <Fragment>
|
||||
<Route path='/s' component={Servers} />
|
||||
<Route path='/root' component={aaa} />
|
||||
</Fragment>
|
||||
? <Route path='/s' component={Servers} />
|
||||
|
||||
|
||||
// NOT LOGGED IN
|
||||
: <Fragment>
|
||||
<Route path='/s' component={ServerLanding} />
|
||||
</Fragment>
|
||||
: [<Route path='/s/:server' key={1} component={ServerLanding} />, <Route path='/s' key={2} render={() => <Redirect to="/" />} />]
|
||||
|
||||
}
|
||||
|
||||
{/* GENERAL ROUTES */}
|
||||
|
|
Loading…
Add table
Reference in a new issue