mirror of
https://github.com/roleypoly/roleypoly-v1.git
synced 2025-06-17 02:29:10 +00:00
temp commit
This commit is contained in:
parent
e86f7ff68e
commit
6fb39d6c4d
22 changed files with 282 additions and 39 deletions
|
@ -4,7 +4,7 @@ import type { AppContext } from '../Roleypoly'
|
|||
import Eris, { type Member, Role, type Guild, type Permission as ErisPermission } from 'eris'
|
||||
import LRU from 'lru-cache'
|
||||
// $FlowFixMe
|
||||
import { OrderedSet } from 'immutable'
|
||||
import { OrderedSet, OrderedMap } from 'immutable'
|
||||
import superagent from 'superagent'
|
||||
import type { AuthTokens } from './auth'
|
||||
import type { IFetcher } from './discord/types'
|
||||
|
@ -54,6 +54,8 @@ export type MemberExt = Member & {
|
|||
}
|
||||
|
||||
export default class DiscordService extends Service {
|
||||
static _guildExpiration = +(process.env.GUILD_INVALIDATION_TIME || 36e5)
|
||||
|
||||
ctx: AppContext
|
||||
client: Eris
|
||||
|
||||
|
@ -67,6 +69,8 @@ export default class DiscordService extends Service {
|
|||
|
||||
fetcher: IFetcher
|
||||
|
||||
guilds: OrderedMap<Guild> = OrderedMap<Guild>()
|
||||
_lastGuildFetch: number
|
||||
constructor (ctx: AppContext) {
|
||||
super(ctx)
|
||||
this.ctx = ctx
|
||||
|
@ -88,14 +92,15 @@ export default class DiscordService extends Service {
|
|||
})
|
||||
|
||||
this.fetcher = new RestFetcher(this)
|
||||
this.fetchGuilds(true)
|
||||
}
|
||||
|
||||
isRoot (id: string): boolean {
|
||||
return this.cfg.rootUsers.has(id)
|
||||
}
|
||||
|
||||
getRelevantServers (user: string) {
|
||||
return this.client.guilds.filter(guild => guild.members.has(user))
|
||||
getRelevantServers (user: string): OrderedSet<Guild> {
|
||||
return this.guilds.filter(guild => guild.members.has(user))
|
||||
}
|
||||
|
||||
async gm (serverId: string, userId: string, { canFake = false }: { canFake: boolean } = {}): Promise<?MemberExt> {
|
||||
|
@ -280,6 +285,36 @@ export default class DiscordService extends Service {
|
|||
return `https://discordapp.com/oauth2/authorize?client_id=${this.cfg.clientId}&scope=bot&permissions=268435456`
|
||||
}
|
||||
|
||||
async fetchGuilds (force: boolean = false) {
|
||||
if (
|
||||
force ||
|
||||
this.guilds.isEmpty() ||
|
||||
this._lastGuildFetch + DiscordService._guildExpiration < Date.now()
|
||||
) {
|
||||
const g = await this.fetcher.getGuilds()
|
||||
this.guilds = OrderedMap(g.reduce((acc, g) => ({ ...acc, [g.id]: g }), {}))
|
||||
}
|
||||
}
|
||||
|
||||
async guild (id: string, invalidate: boolean = false): Promise<?Guild> {
|
||||
// fetch if needed
|
||||
await this.fetchGuilds()
|
||||
|
||||
// do we know about it?
|
||||
// (also don't get this if we're invalidating)
|
||||
if (invalidate === false && this.guilds.has(id)) {
|
||||
return this.guilds.get(id)
|
||||
}
|
||||
|
||||
// else let's fetch and cache.
|
||||
const g = await this.fetcher.getGuild(id)
|
||||
if (g != null) {
|
||||
this.guilds = this.guilds.set(g.id, g)
|
||||
}
|
||||
|
||||
return g
|
||||
}
|
||||
|
||||
async issueChallenge (author: string) {
|
||||
// Create a challenge
|
||||
const chall = await this.ctx.auth.createDMChallenge(author)
|
||||
|
|
|
@ -4,6 +4,8 @@ import type DiscordSvc from '../discord'
|
|||
import type ErisClient, { User, Member, Guild } from 'eris'
|
||||
import LRU from 'lru-cache'
|
||||
import logger from '../../logger'
|
||||
// $FlowFixMe
|
||||
import { OrderedSet } from 'immutable'
|
||||
const log = logger(__filename)
|
||||
|
||||
export default class BotFetcher implements IFetcher {
|
||||
|
@ -71,4 +73,31 @@ export default class BotFetcher implements IFetcher {
|
|||
return null
|
||||
}
|
||||
}
|
||||
|
||||
getGuilds = async (): Promise<Guild[]> => {
|
||||
const last: ?string = undefined
|
||||
const limit: number = 100
|
||||
let out = OrderedSet<Guild>()
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
// $FlowFixMe -- last is optional, but typedef isn't.
|
||||
const gl = await this.client.getRESTGuilds(limit, last)
|
||||
|
||||
out = out.union(gl)
|
||||
if (gl.length !== limit) {
|
||||
break
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
log.error('getAllGuilds failed', e)
|
||||
throw e
|
||||
}
|
||||
|
||||
return out.toArray()
|
||||
}
|
||||
|
||||
invalidateGuild (id: string) {
|
||||
this.cache.del(`G:${id}`)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,4 +11,6 @@ export interface IFetcher {
|
|||
getGuild: (id: string) => Promise<?Guild>;
|
||||
|
||||
getMember: (server: string, user: string) => Promise<?Member>;
|
||||
|
||||
getGuilds: () => Promise<Guild[]>;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ import { type AppContext } from '../Roleypoly'
|
|||
import { type Models } from '../models'
|
||||
import { type ServerModel } from '../models/Server'
|
||||
import type DiscordService from './discord'
|
||||
// $FlowFixMe
|
||||
import type { Sequence } from 'immutable'
|
||||
import {
|
||||
type Guild,
|
||||
type Collection
|
||||
|
@ -38,7 +40,7 @@ class PresentationService extends Service {
|
|||
}
|
||||
}
|
||||
|
||||
presentableServers (collection: Collection<Guild>, userId: string) {
|
||||
presentableServers (collection: Collection<Guild> | Sequence<Guild>, userId: string): Promise<PresentableServer[]> {
|
||||
return areduce(Array.from(collection.values()), async (acc, server) => {
|
||||
const gm = server.members.get(userId)
|
||||
if (gm == null) {
|
||||
|
|
|
@ -5,10 +5,10 @@ import type PresentationService from './presentation'
|
|||
import {
|
||||
type Guild
|
||||
} from 'eris'
|
||||
import { type ServerModel, type Category } from '../models/Server'
|
||||
import { type ServerModel, type Category } from '@roleypoly/types'
|
||||
|
||||
export default class ServerService extends Service {
|
||||
Server: any // Model<ServerModel> but flowtype is bugged
|
||||
Server: * // Model<ServerModel> but flowtype is bugged
|
||||
P: PresentationService
|
||||
constructor (ctx: AppContext) {
|
||||
super(ctx)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue