增加检查discord role的接口
This commit is contained in:
parent
dba4eddee7
commit
2bf81f8e1c
@ -1,8 +0,0 @@
|
||||
.idea
|
||||
node_modules
|
||||
build
|
||||
dist
|
||||
.DS_Store
|
||||
tmp
|
||||
target
|
||||
boundle.log
|
@ -23,7 +23,7 @@ class DiscordController extends BaseController {
|
||||
record.refreshToken = tokenResponse.refresh_token
|
||||
record.scope = tokenResponse.scope
|
||||
record.tokenType = tokenResponse.token_type
|
||||
record.expiresIn = tokenResponse.expires_in || 0 + Date.now()
|
||||
record.expiresIn = (Date.now() / 1000 + tokenResponse.expires_in) | 0
|
||||
await record.save()
|
||||
if (tokenResponse && tokenResponse.access_token) {
|
||||
let uinfo = await userInfo(tokenResponse.access_token)
|
||||
|
@ -3,11 +3,12 @@ import { ZError } from 'common/ZError'
|
||||
import { role, router } from 'decorators/router'
|
||||
import logger from 'logger/logger'
|
||||
import { AuthRecord, PlatEnum } from 'modules/AuthRecord'
|
||||
import { DiscordSvr } from 'services/discord.svr'
|
||||
import { DiscordSvr, getAvableAccessToken, userGuildMember } from 'services/discord.svr'
|
||||
import { hmacsha256 } from 'utils/security.util'
|
||||
|
||||
const checkSign = (params: { address?: string; sign?: string }) => {
|
||||
const { address, sign } = params
|
||||
let { address, sign } = params
|
||||
address = address.toLowerCase()
|
||||
if (!address || !sign) {
|
||||
throw new ZError(10, 'invalid params')
|
||||
}
|
||||
@ -119,21 +120,49 @@ class MainController extends BaseController {
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否加入某guid
|
||||
*/
|
||||
@role(ROLE_ANON)
|
||||
@router('get /activity/discord/svr/:id')
|
||||
@router('post /activity/discord/guild')
|
||||
async checkDiscordJoin(req) {
|
||||
let { id } = req.params
|
||||
let { gid, address } = req.params
|
||||
checkSign(req.params)
|
||||
let verified = new DiscordSvr().checkUser(id)
|
||||
return { verified }
|
||||
address = address.toLowerCase()
|
||||
let record = await AuthRecord.findOne({ address, platform: PlatEnum.DISCORD })
|
||||
if (!record) {
|
||||
throw new ZError(12, 'not found discord record')
|
||||
}
|
||||
let accessToken = await getAvableAccessToken(record)
|
||||
// TODO:: check local cache
|
||||
let data = await userGuildMember(accessToken, gid)
|
||||
if (!data || data.code) {
|
||||
throw new ZError(13, 'not found guild')
|
||||
}
|
||||
return { result: true }
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否有某个role
|
||||
*/
|
||||
@role(ROLE_ANON)
|
||||
@router('get /activity/discord/role/:id')
|
||||
@router('post /activity/discord/role')
|
||||
async checkDiscordRole(req) {
|
||||
let { id } = req.params
|
||||
let { rid, gid, address } = req.params
|
||||
checkSign(req.params)
|
||||
let verified = new DiscordSvr().checkUserRole(id)
|
||||
return { verified }
|
||||
address = address.toLowerCase()
|
||||
let record = await AuthRecord.findOne({ address, platform: PlatEnum.DISCORD })
|
||||
if (!record) {
|
||||
throw new ZError(12, 'not found discord record')
|
||||
}
|
||||
let accessToken = await getAvableAccessToken(record)
|
||||
console.log('discord access token:', accessToken)
|
||||
// TODO:: check local cache
|
||||
let data = await userGuildMember(accessToken, gid)
|
||||
console.log(data?.roles)
|
||||
if (!data || data.code) {
|
||||
throw new ZError(13, 'not found guild')
|
||||
}
|
||||
let roleSet = new Set(data.roles)
|
||||
return { result: roleSet.has(rid) }
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ class TwitterController extends BaseController {
|
||||
record.refreshToken = tokenResponse.refresh_token
|
||||
record.scope = tokenResponse.scope
|
||||
record.tokenType = tokenResponse.token_type
|
||||
record.expiresIn = tokenResponse.expires_in || 0 + Date.now()
|
||||
record.expiresIn = (Date.now() / 1000 + tokenResponse.expires_in || 0) | 0
|
||||
await record.save()
|
||||
if (tokenResponse && tokenResponse.access_token) {
|
||||
const uinfo = await getTwitterUserInfo(tokenResponse.access_token)
|
||||
|
@ -2,6 +2,11 @@ import { ZError } from 'common/ZError'
|
||||
import { singleton } from 'decorators/singleton'
|
||||
|
||||
import { Client, Events, GatewayIntentBits, Guild } from 'discord.js'
|
||||
import { AuthRecordClass } from 'modules/AuthRecord'
|
||||
import { DocumentType } from '@typegoose/typegoose'
|
||||
|
||||
const DISCORD_API_HOST = 'https://discord.com/api/v10'
|
||||
const DISCORD_APP_HOST = 'https://discordapp.com/api'
|
||||
|
||||
export async function exchangeDiscrodCodeForToken(code: string) {
|
||||
const clientId = process.env.DISCORD_CLIENT_ID
|
||||
@ -19,7 +24,6 @@ export async function exchangeDiscrodCodeForToken(code: string) {
|
||||
client_secret: clientSecret,
|
||||
redirect_uri: redirectUri,
|
||||
code,
|
||||
scope: 'identify email',
|
||||
}),
|
||||
})
|
||||
|
||||
@ -27,15 +31,102 @@ export async function exchangeDiscrodCodeForToken(code: string) {
|
||||
return data
|
||||
}
|
||||
|
||||
export async function getAvableAccessToken(record: DocumentType<AuthRecordClass>) {
|
||||
if (record.expiresIn < Date.now() / 1000 + 60 * 5) {
|
||||
console.log('discord access token expired')
|
||||
const data = await refreshDiscordToken(record.refreshToken)
|
||||
if (data.code) {
|
||||
throw new ZError(10, 'refresh token error')
|
||||
}
|
||||
record.accessToken = data.access_token
|
||||
record.refreshToken = data.refresh_token
|
||||
record.expiresIn = (Date.now() / 1000 + data.expires_in || 0) | 0
|
||||
await record.save()
|
||||
}
|
||||
return record.accessToken
|
||||
}
|
||||
export async function refreshDiscordToken(rtoken: string) {
|
||||
const clientId = process.env.DISCORD_CLIENT_ID
|
||||
const clientSecret = process.env.DISCORD_CLIENT_SECRET
|
||||
const response = await fetch('https://discord.com/api/oauth2/token', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: new URLSearchParams({
|
||||
grant_type: 'refresh_token',
|
||||
client_id: clientId,
|
||||
client_secret: clientSecret,
|
||||
refresh_token: rtoken,
|
||||
}),
|
||||
})
|
||||
const data = await response.json()
|
||||
return data
|
||||
}
|
||||
/**
|
||||
* 用户基本信息
|
||||
* @param token
|
||||
* @returns
|
||||
*/
|
||||
export async function userInfo(token: string) {
|
||||
const response = await fetch('https://discord.com/api/users/@me', {
|
||||
const response = await fetch(`${DISCORD_APP_HOST}/users/@me`, {
|
||||
headers: {
|
||||
authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
|
||||
const data = await response.json()
|
||||
console.log(data)
|
||||
return data
|
||||
}
|
||||
/**
|
||||
* 用户所在的工会列表, oauth2方式
|
||||
* @param token
|
||||
* @returns
|
||||
*/
|
||||
export async function userGuildList(token: string) {
|
||||
const url = `${DISCORD_APP_HOST}/users/@me/guilds`
|
||||
const response = await fetch(url, {
|
||||
headers: {
|
||||
authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
const data = await response.json()
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户在某个工会的信息, oauth2方式
|
||||
* @param token
|
||||
* @param guildId
|
||||
* @returns
|
||||
* 返回的数据结构:
|
||||
* https://discord.com/developers/docs/resources/guild#guild-member-object
|
||||
*/
|
||||
export async function userGuildMember(token: string, guildId: string) {
|
||||
const url = `${DISCORD_APP_HOST}/users/@me/guilds/${guildId}/member`
|
||||
const response = await fetch(url, {
|
||||
headers: {
|
||||
authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
const data = await response.json()
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接通过discord接口, 获取工会中某用户信息
|
||||
* 返回的数据结构:
|
||||
* https://discord.com/developers/docs/resources/guild#guild-member-object
|
||||
*/
|
||||
export async function getGuildMember(uid: string) {
|
||||
const url = `${DISCORD_API_HOST}/guilds/${process.env.DISCROD_GUILD_ID}/members/${uid}`
|
||||
const token = process.env.DISCORD_BOT_TOKEN
|
||||
const response = await fetch(url, {
|
||||
headers: {
|
||||
authorization: `Bot ${token}`,
|
||||
},
|
||||
})
|
||||
const data = await response.json()
|
||||
return data
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user