From dba4eddee76313801e10e51c735c70fa3ec22cc9 Mon Sep 17 00:00:00 2001 From: CounterFire2023 <136581895+CounterFire2023@users.noreply.github.com> Date: Thu, 28 Mar 2024 19:36:12 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0twitter=E5=A4=B4=E5=83=8F?= =?UTF-8?q?=E7=9A=84=E8=BF=94=E5=9B=9E=E5=92=8C=E4=BF=9D=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/controllers/main.controller.ts | 25 ++++++++++----------- src/controllers/oauth.controller.ts | 2 -- src/controllers/twitter.controller.ts | 3 +++ src/modules/AuthRecord.ts | 2 ++ src/services/discord.svr.ts | 29 +++++++++++++++++++++++-- src/services/twitter.svr.ts | 31 ++++++++++++++++++++++++++- 6 files changed, 75 insertions(+), 17 deletions(-) diff --git a/src/controllers/main.controller.ts b/src/controllers/main.controller.ts index f2697cb..b30d485 100644 --- a/src/controllers/main.controller.ts +++ b/src/controllers/main.controller.ts @@ -6,8 +6,8 @@ import { AuthRecord, PlatEnum } from 'modules/AuthRecord' import { DiscordSvr } from 'services/discord.svr' import { hmacsha256 } from 'utils/security.util' -const checkSign = (params: {address?: string, sign?: string}) => { - const {address, sign} = params; +const checkSign = (params: { address?: string; sign?: string }) => { + const { address, sign } = params if (!address || !sign) { throw new ZError(10, 'invalid params') } @@ -44,6 +44,7 @@ class MainController extends BaseController { result.twitter = { id: record.openId, username: record.username, + avatar: record.avatar, } break case 7: @@ -85,30 +86,30 @@ class MainController extends BaseController { return { verified } } - @role(ROLE_ANON) @router('get /activity/twitter/:address') async checkTwitterFollow(req) { let { address } = req.params - checkSign(req.params); + checkSign(req.params) address = address.toLowerCase() let record = await AuthRecord.findOne({ address, platform: PlatEnum.TWITTER }) - let result: any = { } + let result: any = {} if (!!record) { result.username = record.username result.userid = record.openId + result.avatar = record.avatar } return result - } + } @role(ROLE_ANON) @router('get /activity/discord/:address') async checkDiscord(req) { let { address } = req.params - checkSign(req.params); + checkSign(req.params) address = address.toLowerCase() let record = await AuthRecord.findOne({ address, platform: PlatEnum.DISCORD }) - let result: any = { } + let result: any = {} if (!!record) { result.verified = record.condition result.username = record.username @@ -122,17 +123,17 @@ class MainController extends BaseController { @router('get /activity/discord/svr/:id') async checkDiscordJoin(req) { let { id } = req.params - checkSign(req.params); + checkSign(req.params) let verified = new DiscordSvr().checkUser(id) - return {verified} + return { verified } } @role(ROLE_ANON) @router('get /activity/discord/role/:id') async checkDiscordRole(req) { let { id } = req.params - checkSign(req.params); + checkSign(req.params) let verified = new DiscordSvr().checkUserRole(id) - return {verified} + return { verified } } } diff --git a/src/controllers/oauth.controller.ts b/src/controllers/oauth.controller.ts index 18e88d6..1ab9876 100644 --- a/src/controllers/oauth.controller.ts +++ b/src/controllers/oauth.controller.ts @@ -1,9 +1,7 @@ - import BaseController, { ROLE_ANON } from 'common/base.controller' import { role, router } from 'decorators/router' class OauthController extends BaseController { - @role(ROLE_ANON) @router('get /oauth/redirect') @router('post /oauth/redirect') diff --git a/src/controllers/twitter.controller.ts b/src/controllers/twitter.controller.ts index 446d9e6..3c396e5 100644 --- a/src/controllers/twitter.controller.ts +++ b/src/controllers/twitter.controller.ts @@ -34,6 +34,9 @@ class TwitterController extends BaseController { record.nickname = uinfo.data?.name record.username = uinfo.data?.username record.openId = uinfo.data?.id + if (uinfo.data?.profile_image_url) { + record.avatar = uinfo.data?.profile_image_url.replace('_normal', '') + } await record.save() } if (stateArr.length > 2) { diff --git a/src/modules/AuthRecord.ts b/src/modules/AuthRecord.ts index 5c8d194..22796fd 100644 --- a/src/modules/AuthRecord.ts +++ b/src/modules/AuthRecord.ts @@ -32,6 +32,8 @@ export class AuthRecordClass extends BaseModule { @prop() public username?: string + @prop() + public avatar?: string // 对应discord上的discriminator @prop() public discriminator?: string diff --git a/src/services/discord.svr.ts b/src/services/discord.svr.ts index b5e2260..6e359dc 100644 --- a/src/services/discord.svr.ts +++ b/src/services/discord.svr.ts @@ -45,10 +45,32 @@ export class DiscordSvr { private guild: Guild public async init() { console.log('DiscordSvr init') - this.client = new Client({ intents: [GatewayIntentBits.Guilds] }) + this.client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers] }) this.client.once(Events.ClientReady, async c => { console.log(`Ready! Logged in as ${c.user.tag}`) this.guild = await this.client.guilds.fetch(process.env.DISCROD_GUILD_ID) + console.log('guild', this.guild) + await this.guild.members.fetch() + for (const member of this.guild.members.cache.values()) { + console.log(member.user) + } + }) + this.client.on(Events.GuildMemberUpdate, async (oldMember, newMember) => { + console.log('GuildMemberUpdate', oldMember, newMember) + // Check if the member's roles have changed + // if (oldMember.roles.cache.size !== newMember.roles.cache.size) { + // // Get the added and removed roles + // const addedRoles = newMember.roles.cache.filter(role => !oldMember.roles.cache.has(role.id)) + // const removedRoles = oldMember.roles.cache.filter(role => !newMember.roles.cache.has(role.id)) + // console.log('addedRoles', addedRoles) + // console.log('removedRoles', removedRoles) + // } + }) + this.client.on(Events.GuildMemberAdd, async member => { + console.log('GuildMemberAdd', member) + }) + this.client.on(Events.GuildMemberRemove, async member => { + console.log('GuildMemberRemove', member) }) this.client.login(process.env.DISCORD_BOT_TOKEN) } @@ -66,10 +88,13 @@ export class DiscordSvr { if (!this.guild) { throw new ZError(10, 'DiscordSvr not init') } + for (const member of this.guild.members.cache.values()) { + console.log(member.user) + } return this.guild.members.cache.has(uid) } - public async checkUserRole(uid: string) { + public checkUserRole(uid: string) { if (!this.guild) { throw new ZError(10, 'DiscordSvr not init') } diff --git a/src/services/twitter.svr.ts b/src/services/twitter.svr.ts index 2796ec7..f77fcf1 100644 --- a/src/services/twitter.svr.ts +++ b/src/services/twitter.svr.ts @@ -22,8 +22,37 @@ export async function exchangeTwitterCodeForToken(code: string, vcode: string) { return data } +/** + * https://developer.twitter.com/en/docs/authentication/oauth-2-0/authorization-code + * @param refreshToken + * @returns + */ +export async function refreshToken(refreshToken: string) { + const url = 'https://api.twitter.com/2/oauth2/token' + const credentials = Buffer.from(`${consumerKey}:${consumerSecret}`).toString('base64') + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + Authorization: `Basic ${credentials}`, + }, + body: new URLSearchParams({ + grant_type: 'refresh_token', + refresh_token: refreshToken, + }), + }) + const data = await response.json() + return data +} + +/** + * https://developer.twitter.com/en/docs/twitter-api/users/lookup/api-reference/get-users-me + * User rate limit (User context): 75 requests per 15-minute window per each authenticated user + * @param accessToken + * @returns + */ export async function getTwitterUserInfo(accessToken: string) { - const url = 'https://api.twitter.com/2/users/me' + const url = 'https://api.twitter.com/2/users/me?user.fields=profile_image_url' const response = await fetch(url, { method: 'GET', headers: {