From 2a24e77358ed4ec7d0eb59666916442acd9d614a Mon Sep 17 00:00:00 2001 From: Shigma Date: Mon, 11 Sep 2023 15:59:47 +0800 Subject: [PATCH] feat(satori): implement new protocol --- adapters/discord/src/bot.ts | 38 +++++++++++++----------------- adapters/discord/src/utils.ts | 14 +++++++++-- adapters/kook/src/bot.ts | 8 +++---- adapters/kook/src/utils.ts | 12 ++++++++-- adapters/line/src/bot.ts | 11 +++++++-- adapters/matrix/src/bot.ts | 6 +++++ adapters/onebot/src/bot/message.ts | 2 +- adapters/onebot/src/utils.ts | 19 ++++++++++----- adapters/qqguild/src/utils.ts | 3 ++- adapters/slack/src/bot.ts | 8 ++++--- adapters/slack/src/utils.ts | 7 ++++++ packages/core/src/protocol.ts | 6 ++--- 12 files changed, 89 insertions(+), 45 deletions(-) diff --git a/adapters/discord/src/bot.ts b/adapters/discord/src/bot.ts index 3437ab15..26a0165e 100644 --- a/adapters/discord/src/bot.ts +++ b/adapters/discord/src/bot.ts @@ -1,5 +1,4 @@ import { Bot, Context, defineProperty, Fragment, h, isNullable, Logger, Quester, Schema, SendOptions, Universal } from '@satorijs/satori' -import { decodeChannel, decodeGuild, decodeMessage, decodeRole, decodeUser, encodeRole } from './utils' import * as Discord from './utils' import { DiscordMessageEncoder } from './message' import { Internal, Webhook } from './types' @@ -67,7 +66,7 @@ export class DiscordBot extends Bot { async getSelf() { const data = await this.internal.getCurrentUser() - return decodeUser(data) + return Discord.decodeUser(data) } async deleteMessage(channelId: string, messageId: string) { @@ -88,37 +87,34 @@ export class DiscordBot extends Bot { async getMessage(channelId: string, messageId: string) { const data = await this.internal.getChannelMessage(channelId, messageId) - return await decodeMessage(this, data) + return await Discord.decodeMessage(this, data) } async getMessageList(channelId: string, before?: string) { const messages = await this.internal.getChannelMessages(channelId, { before, limit: 100 }) - const data = await Promise.all(messages.reverse().map(data => decodeMessage(this, data, {}, false))) + const data = await Promise.all(messages.reverse().map(data => Discord.decodeMessage(this, data, {}, false))) return { data, next: data[0]?.messageId } } async getUser(userId: string) { const data = await this.internal.getUser(userId) - return decodeUser(data) + return Discord.decodeUser(data) } async getGuildMemberList(guildId: string, after?: string) { const users = await this.internal.listGuildMembers(guildId, { after, limit: 1000 }) - const data = users.map(v => decodeUser(v.user)) - return { data, next: data[999]?.userId } + const data = users.map(v => Discord.decodeGuildMember(v)) + return { data, next: data[999]?.user.id } } async getChannel(channelId: string) { const data = await this.internal.getChannel(channelId) - return decodeChannel(data) + return Discord.decodeChannel(data) } async getGuildMember(guildId: string, userId: string) { const member = await this.internal.getGuildMember(guildId, userId) - return { - ...decodeUser(member.user), - nickname: member.nick, - } + return Discord.decodeGuildMember(member) } async kickGuildMember(guildId: string, userId: string) { @@ -127,18 +123,18 @@ export class DiscordBot extends Bot { async getGuild(guildId: string) { const data = await this.internal.getGuild(guildId) - return decodeGuild(data) + return Discord.decodeGuild(data) } async getGuildList(after?: string) { const guilds = await this.internal.getCurrentUserGuilds({ after, limit: 200 }) - const data = guilds.map(decodeGuild) + const data = guilds.map(Discord.decodeGuild) return { data, next: data[199]?.id } } async getChannelList(guildId: string) { const channels = await this.internal.getGuildChannels(guildId) - return { data: channels.map(decodeChannel) } + return { data: channels.map(Discord.decodeChannel) } } createReaction(channelId: string, messageId: string, emoji: string) { @@ -163,7 +159,7 @@ export class DiscordBot extends Bot { async getReactionList(channelId: string, messageId: string, emoji: string, after?: string) { const data = await this.internal.getReactions(channelId, messageId, emoji, { after, limit: 100 }) - return { data: data.map(decodeUser), next: data[99]?.id } + return { data: data.map(Discord.decodeUser), next: data[99]?.id } } setGuildMemberRole(guildId: string, userId: string, roleId: string) { @@ -176,16 +172,16 @@ export class DiscordBot extends Bot { async getGuildRoleList(guildId: string) { const data = await this.internal.getGuildRoles(guildId) - return { data: data.map(decodeRole) } + return { data: data.map(Discord.decodeRole) } } - async createGuildRole(guildId: string, data: Partial) { - const role = await this.internal.createGuildRole(guildId, encodeRole(data)) + async createGuildRole(guildId: string, data: Partial) { + const role = await this.internal.createGuildRole(guildId, Discord.encodeRole(data)) return role.id } - async modifyGuildRole(guildId: string, roleId: string, data: Partial) { - await this.internal.modifyGuildRole(guildId, roleId, encodeRole(data)) + async modifyGuildRole(guildId: string, roleId: string, data: Partial) { + await this.internal.modifyGuildRole(guildId, roleId, Discord.encodeRole(data)) } deleteGuildRole(guildId: string, roleId: string) { diff --git a/adapters/discord/src/utils.ts b/adapters/discord/src/utils.ts index bf1e0300..f30ad566 100644 --- a/adapters/discord/src/utils.ts +++ b/adapters/discord/src/utils.ts @@ -11,6 +11,8 @@ export const sanitize = (val: string) => .replace(/@here/g, () => '\\@here') export const decodeUser = (user: Discord.User): Universal.User => ({ + id: user.id, + name: user.username, userId: user.id, avatar: `https://cdn.discordapp.com/avatars/${user.id}/${user.avatar}.png`, username: user.username, @@ -18,6 +20,14 @@ export const decodeUser = (user: Discord.User): Universal.User => ({ isBot: user.bot || false, }) +export const decodeGuildMember = (member: Discord.GuildMember): Universal.GuildMember => ({ + ...decodeUser(member.user), + user: decodeUser(member.user), + nickname: member.nick, + roles: member.roles, + avatar: member.user.avatar, +}) + export const decodeGuild = (data: Discord.Guild): Universal.Guild => ({ id: data.id, name: data.name, @@ -37,12 +47,12 @@ export const decodeAuthor = (author: Discord.User): Universal.Author => ({ nickname: author.username, }) -export const decodeRole = (role: Discord.Role): Universal.Role => ({ +export const decodeRole = (role: Discord.Role): Universal.GuildRole => ({ ...role, permissions: BigInt(role.permissions), }) -export const encodeRole = (role: Partial): Partial => ({ +export const encodeRole = (role: Partial): Partial => ({ ...role, permissions: role.permissions && '' + role.permissions, }) diff --git a/adapters/kook/src/bot.ts b/adapters/kook/src/bot.ts index 12ed4adf..39a2d95d 100644 --- a/adapters/kook/src/bot.ts +++ b/adapters/kook/src/bot.ts @@ -1,5 +1,5 @@ import { Bot, Context, Fragment, h, Quester, Schema, SendOptions, Universal } from '@satorijs/satori' -import { adaptAuthor, adaptGroup, adaptMessage, adaptUser, decodeRole, encodeRole } from './utils' +import { adaptGroup, adaptMessage, adaptUser, decodeGuildMember, decodeRole, encodeRole } from './utils' import * as Kook from './types' import FormData from 'form-data' import { WsClient } from './ws' @@ -94,7 +94,7 @@ export class KookBot extends Bot { async getGuildMemberList(guild_id: string) { const { items } = await this.request('GET', '/guild/user-list', { guild_id }) - return { data: items.map(adaptAuthor) } + return { data: items.map(decodeGuildMember) } } async setGroupNickname(guild_id: string, user_id: string, nickname: string) { @@ -153,7 +153,7 @@ export class KookBot extends Bot { return { data: items.map(decodeRole) } } - async createGuildRole(guildId: string, data: Partial) { + async createGuildRole(guildId: string, data: Partial) { const role = await this.internal.createGuildRole({ guild_id: guildId, ...data, @@ -161,7 +161,7 @@ export class KookBot extends Bot { return role.role_id.toString() } - async modifyGuildRole(guildId: string, roleId: string, data: Partial) { + async modifyGuildRole(guildId: string, roleId: string, data: Partial) { await this.internal.updateGuildRole({ guild_id: guildId, ...encodeRole(data), diff --git a/adapters/kook/src/utils.ts b/adapters/kook/src/utils.ts index f7ec95ba..82479ad4 100644 --- a/adapters/kook/src/utils.ts +++ b/adapters/kook/src/utils.ts @@ -11,18 +11,26 @@ export const adaptGroup = (data: Kook.Guild): Universal.Guild => ({ }) export const adaptUser = (user: Kook.User): Universal.User => ({ + id: user.id, + name: user.username, userId: user.id, avatar: user.avatar, username: user.username, discriminator: user.identify_num, }) +export const decodeGuildMember = (member: Kook.Author): Universal.GuildMember => ({ + ...adaptUser(member), + user: adaptUser(member), + nickname: member.nickname, +}) + export const adaptAuthor = (author: Kook.Author): Universal.Author => ({ ...adaptUser(author), nickname: author.nickname, }) -export const decodeRole = (role: Kook.GuildRole): Universal.Role => ({ +export const decodeRole = (role: Kook.GuildRole): Universal.GuildRole => ({ ...role, id: '' + role.role_id, permissions: BigInt(role.permissions), @@ -34,7 +42,7 @@ function encodeBit(value: boolean) { return isNullable(value) ? value : value ? 1 : 0 } -export const encodeRole = (role: Partial): Partial => ({ +export const encodeRole = (role: Partial): Partial => ({ ...role, role_id: +role.id, permissions: role.permissions && Number(role.permissions), diff --git a/adapters/line/src/bot.ts b/adapters/line/src/bot.ts index 317a6685..78c500f3 100644 --- a/adapters/line/src/bot.ts +++ b/adapters/line/src/bot.ts @@ -46,6 +46,8 @@ export class LineBot extends Bot { async getSelf() { const { userId, displayName, pictureUrl } = await this.internal.getBotInfo() return { + id: userId, + name: displayName, userId, nickname: displayName, avatar: pictureUrl, @@ -57,7 +59,7 @@ export class LineBot extends Bot { start, limit: 1000, }) - return { data: userIds.map(v => ({ userId: v })), next } + return { data: userIds.map(v => ({ id: v, userId: v })), next } } async getGuild(guildId: string) { @@ -72,12 +74,17 @@ export class LineBot extends Bot { async getGuildMemberList(guildId: string, start?: string) { const { memberIds, next } = await this.internal.getGroupMembersIds(guildId, { start }) - return { data: memberIds.map(v => ({ userId: v })), next } + return { data: memberIds.map(id => ({ user: { id }, userId: id })), next } } async getGuildMember(guildId: string, userId: string) { const res = await this.internal.getGroupMemberProfile(guildId, userId) return { + user: { + id: res.userId, + name: res.displayName, + avatar: res.pictureUrl, + }, userId: res.userId, nickname: res.displayName, avatar: res.pictureUrl, diff --git a/adapters/matrix/src/bot.ts b/adapters/matrix/src/bot.ts index 0bc3738b..12c3314a 100644 --- a/adapters/matrix/src/bot.ts +++ b/adapters/matrix/src/bot.ts @@ -75,6 +75,8 @@ export class MatrixBot extends Bot { let avatar: string if (profile.avatar_url) avatar = this.internal.getAssetUrl(profile.avatar_url) return { + id: userId, + name: profile.displayname, userId, avatar, username: userId, @@ -111,6 +113,10 @@ export class MatrixBot extends Bot { .map(event => { const content = event.content as Matrix.M_ROOM_MEMBER return { + user: { + id: event.state_key, + name: event.state_key, + }, userId: event.state_key, username: event.state_key, nickname: content.displayname, diff --git a/adapters/onebot/src/bot/message.ts b/adapters/onebot/src/bot/message.ts index d2a4d50f..7ea5b7db 100644 --- a/adapters/onebot/src/bot/message.ts +++ b/adapters/onebot/src/bot/message.ts @@ -58,7 +58,7 @@ export class OneBotMessageEncoder extends MessageEncoder { this.stack[1].children.push({ type: 'node', data: { - name: author.nickname || author.username || this.bot.nickname || this.bot.username, + name: author.nickname || author.username || this.bot.username, uin: author.userId || this.bot.userId, content: this.children as any, time: `${Math.floor((+author.time || Date.now()) / 1000)}`, diff --git a/adapters/onebot/src/utils.ts b/adapters/onebot/src/utils.ts index e68ea9e6..671d7707 100644 --- a/adapters/onebot/src/utils.ts +++ b/adapters/onebot/src/utils.ts @@ -8,6 +8,8 @@ export * from './types' const logger = new Logger('onebot') export const adaptUser = (user: OneBot.AccountInfo): Universal.User => ({ + id: user.tiny_id || user.user_id.toString(), + name: user.nickname, userId: user.tiny_id || user.user_id.toString(), avatar: user.user_id ? `http://q.qlogo.cn/headimg_dl?dst_uin=${user.user_id}&spec=640` : undefined, username: user.nickname, @@ -15,24 +17,29 @@ export const adaptUser = (user: OneBot.AccountInfo): Universal.User => ({ export const adaptGuildMember = (user: OneBot.SenderInfo): Universal.GuildMember => ({ ...adaptUser(user), + user: adaptUser(user), nickname: user.card, roles: [user.role], }) export const adaptQQGuildMemberInfo = (user: OneBot.GuildMemberInfo): Universal.GuildMember => ({ - userId: user.tiny_id, - username: user.nickname, + user: { + id: user.tiny_id, + name: user.nickname, + isBot: user.role_name === '机器人', + }, nickname: user.nickname, roles: user.role_name ? [user.role_name] : [], - isBot: user.role_name === '机器人', }) export const adaptQQGuildMemberProfile = (user: OneBot.GuildMemberProfile): Universal.GuildMember => ({ - userId: user.tiny_id, - username: user.nickname, + user: { + id: user.tiny_id, + name: user.nickname, + isBot: user.roles?.some(r => r.role_name === '机器人'), + }, nickname: user.nickname, roles: user.roles?.map(r => r.role_name) || [], - isBot: user.roles?.some(r => r.role_name === '机器人'), }) export const adaptAuthor = (user: OneBot.SenderInfo, anonymous?: OneBot.AnonymousInfo): Universal.Author => ({ diff --git a/adapters/qqguild/src/utils.ts b/adapters/qqguild/src/utils.ts index 2e5bc917..8a2210d3 100644 --- a/adapters/qqguild/src/utils.ts +++ b/adapters/qqguild/src/utils.ts @@ -9,9 +9,10 @@ export const adaptGuild = (guild: QQGuild.Guild): Universal.Guild => ({ }) export const adaptUser = (user: QQGuild.User): Universal.User => ({ + id: user.id, + name: user.username, isBot: user.bot, avatar: user.avatar, userId: user.id, username: user.username, - nickname: user.username, }) diff --git a/adapters/slack/src/bot.ts b/adapters/slack/src/bot.ts index aa0b20be..53468dda 100644 --- a/adapters/slack/src/bot.ts +++ b/adapters/slack/src/bot.ts @@ -1,7 +1,7 @@ import { Bot, Context, Fragment, Quester, Schema, SendOptions } from '@satorijs/satori' import { WsClient } from './ws' import { HttpServer } from './http' -import { adaptChannel, adaptGuild, adaptMessage, adaptUser } from './utils' +import { adaptChannel, adapteGuildMember, adaptGuild, adaptMessage, adaptUser } from './utils' import { SlackMessageEncoder } from './message' import { GenericMessageEvent, SlackChannel, SlackTeam, SlackUser } from './types' import FormData from 'form-data' @@ -42,6 +42,8 @@ export class SlackBot extends Bot extends Bot('POST', '/users.list') - return { data: members.map(adaptUser) } + return { data: members.map(adapteGuildMember) } } async getChannel(channelId: string, guildId?: string) { @@ -122,7 +124,7 @@ export class SlackBot extends Bot ({ + user: adaptUser(data), + ...adaptUser(data), +}) + export const adaptChannel = (data: SlackChannel): Universal.Channel => ({ id: data.id, name: data.name, diff --git a/packages/core/src/protocol.ts b/packages/core/src/protocol.ts index 5153a97b..abce75df 100644 --- a/packages/core/src/protocol.ts +++ b/packages/core/src/protocol.ts @@ -138,9 +138,9 @@ export namespace Universal { export interface User { id: string - name: string + name?: string /** @deprecated */ - userId: string + userId?: string /** @deprecated */ username?: string avatar?: string @@ -167,7 +167,7 @@ export namespace Universal { content?: string elements?: Element[] timestamp?: number - author?: User + author?: Author member?: Partial quote?: Message isDirect?: boolean