v2: init -- UI is nuked from orbit, major app restructuring

This commit is contained in:
41666 2019-02-23 18:16:31 -06:00
parent c6f5b55c1c
commit b8da886601
108 changed files with 6717 additions and 17430 deletions

79
api/auth.js Normal file
View file

@ -0,0 +1,79 @@
module.exports = (R, $) => {
R.post('/api/auth/token', async (ctx) => {
const { token } = ctx.request.body
if (token == null || token === '') {
ctx.body = { err: 'token_missing' }
ctx.status = 400
return
}
console.log(ctx.session.expiresAt >= new Date(), ctx.session.expiresAt, new Date())
if (ctx.session.accessToken === undefined || ctx.session.expiresAt >= new Date()) {
const data = await $.discord.getAuthToken(token)
ctx.session.accessToken = data.access_token
ctx.session.refreshToken = data.refresh_token
ctx.session.expiresAt = new Date() + ctx.expires_in
}
const user = await $.discord.getUser(ctx.session.accessToken)
ctx.session.userId = user.id
ctx.session.avatarHash = user.avatar
ctx.body = {
id: user.id,
avatar: user.avatar,
username: user.username,
discriminator: user.discriminator
}
})
R.get('/api/auth/user', async ctx => {
if (ctx.session.accessToken === undefined) {
ctx.body = { err: 'not_logged_in' }
ctx.status = 401
return
}
const user = await $.discord.getUser(ctx.session.accessToken)
ctx.session.userId = user.id
ctx.session.avatarHash = user.avatar
ctx.body = {
id: user.id,
avatar: user.avatar,
username: user.username,
discriminator: user.discriminator
}
})
R.get('/api/auth/redirect', ctx => {
const url = $.discord.getAuthUrl()
if (ctx.query.url === '✔️') {
ctx.body = { url }
return
}
ctx.redirect(url)
})
R.post('/api/auth/logout', ctx => {
ctx.session = null
})
R.get('/api/oauth/bot', ctx => {
const url = $.discord.getBotJoinUrl()
if (ctx.query.url === '✔️') {
ctx.body = { url }
return
}
ctx.redirect(url)
})
R.get('/api/oauth/bot/callback', ctx => {
console.log(ctx.request)
})
}

22
api/index.js Normal file
View file

@ -0,0 +1,22 @@
const log = new (require('../logger'))('api/index')
const glob = require('glob')
const PROD = process.env.NODE_ENV === 'production'
module.exports = async (router, ctx) => {
const apis = glob.sync(`./api/**/!(index).js`)
log.debug('found apis', apis)
for (let a of apis) {
if (a.endsWith('_test.js') && PROD) {
log.debug(`skipping ${a}`)
continue
}
log.debug(`mounting ${a}`)
try {
require(a.replace('api/', ''))(router, ctx)
} catch (e) {
log.error(`couldn't mount ${a}`, e)
}
}
}

130
api/servers.js Normal file
View file

@ -0,0 +1,130 @@
module.exports = (R, $) => {
R.get('/api/servers', async (ctx) => {
try {
const { userId } = ctx.session
const srv = $.discord.getRelevantServers(userId)
const presentable = await $.P.presentableServers(srv, userId)
ctx.body = presentable
} catch (e) {
console.error(e.trace || e.stack)
}
})
R.get('/api/server/:id', async (ctx) => {
const { userId } = ctx.session
const { id } = ctx.params
const srv = $.discord.client.guilds.get(id)
if (srv == null) {
ctx.body = { err: 'not found' }
ctx.status = 404
return
}
let gm
if (srv.members.has(userId)) {
gm = $.discord.gm(id, userId)
} else if ($.discord.isRoot(userId)) {
gm = $.discord.fakeGm({ id: userId })
} else {
ctx.body = { err: 'not_a_member' }
ctx.status = 400
return
}
const server = await $.P.presentableServer(srv, gm)
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
let gm = $.discord.gm(id, userId)
if (gm == null && $.discord.isRoot(userId)) {
gm = $.discord.fakeGm({ id: userId })
}
// check perms
if (!$.discord.getPermissions(gm).canManageRoles) {
ctx.status = 403
ctx.body = { err: 'cannot_manage_roles' }
return
}
const { message = null, categories = null } = ctx.request.body
// todo make less nasty
await $.server.update(id, {
...((message != null) ? { message } : {}),
...((categories != null) ? { categories } : {})
})
ctx.body = { ok: true }
})
R.get('/api/admin/servers', async ctx => {
const { userId } = ctx.session
if (!$.discord.isRoot(userId)) {
return
}
ctx.body = $.discord.client.guilds.map(g => ({ url: `${process.env.APP_URL}/s/${g.id}`, name: g.name, members: g.members.array().length, roles: g.roles.array().length }))
})
R.patch('/api/servers/:server/roles', async ctx => {
const { userId } = ctx.session
const { server } = ctx.params
let gm = $.discord.gm(server, userId)
if (gm == null && $.discord.isRoot(userId)) {
gm = $.discord.fakeGm({ id: userId })
}
// check perms
// if (!$.discord.getPermissions(gm).canManageRoles) {
// ctx.status = 403
// ctx.body = { err: 'cannot_manage_roles' }
// return
// }
const { added, removed } = ctx.request.body
const allowedRoles = await $.server.getAllowedRoles(server)
const pred = r => $.discord.safeRole(server, r) && allowedRoles.indexOf(r) !== -1
if (added.length > 0) {
gm = await gm.addRoles(added.filter(pred))
}
setTimeout(() => {
if (removed.length > 0) {
gm.removeRoles(removed.filter(pred))
}
}, 1000)
// console.log('role patch', { added, removed, allowedRoles, addedFiltered: added.filterNot(pred), removedFiltered: removed.filterNot(pred) })
ctx.body = { ok: true }
})
}

26
api/servers_test.js Normal file
View file

@ -0,0 +1,26 @@
module.exports = (R, $) => {
R.get('/api/~/relevant-servers/:user', (ctx, next) => {
// ctx.body = 'ok'
const srv = $.discord.getRelevantServers(ctx.params.user)
ctx.body = $.discord.presentableServers(srv, ctx.params.user)
return
})
R.get('/api/~/roles/:id/:userId', (ctx, next) => {
// ctx.body = 'ok'
const { id, userId } = ctx.params
const srv = $.discord.client.guilds.get(id)
if (srv === undefined) {
ctx.body = { err: 'not found' }
ctx.status = 404
return
}
const gm = srv.members.get(userId)
const roles = $.discord.presentableRoles(id, gm)
ctx.boy = roles
})
}

17
api/ui.js Normal file
View file

@ -0,0 +1,17 @@
// note, this file only contains stuff for complicated routes.
// next.js will handle anything beyond this.
module.exports = (R, $) => {
const processMappings = mapping => {
for (let p in mapping) {
R.get(p, ctx => {
$.ui.render(ctx.req, ctx.res, mapping[p], {...ctx.params, ...ctx.query})
})
}
}
processMappings({
"/s/add": "/_server_add",
"/s/:id": "/_server",
"/help/:page": "/_help"
})
}