Skip to content

Commit

Permalink
feat(discord): message interface improvements (#212)
Browse files Browse the repository at this point in the history
  • Loading branch information
XxLittleCxX committed Apr 10, 2021
1 parent 691b7c7 commit a280e52
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 50 deletions.
66 changes: 43 additions & 23 deletions packages/adapter-discord/src/bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@ import { segment } from 'koishi-utils'
import FormData from 'form-data'
import FileType from 'file-type'

export class SenderError extends Error {
constructor(url: string, data: any, selfId: string) {
super(`Error when trying to request ${url}, data: ${JSON.stringify(data)}`)
Object.defineProperties(this, {
name: { value: 'SenderError' },
selfId: { value: selfId },
data: { value: data },
url: { value: url },
})
}
}

export class DiscordBot extends Bot<'discord'> {
_d = 0
version = 'discord'
Expand All @@ -21,15 +33,19 @@ export class DiscordBot extends Bot<'discord'> {
const headers: Record<string, any> = {
Authorization: `Bot ${this.token}`,
}
const response = await axios({
...axiosConfig,
...discord.axiosConfig,
method,
url,
headers: { ...headers, ...exHeaders },
data,
})
return response.data
try {
const response = await axios({
...axiosConfig,
...discord.axiosConfig,
method,
url,
headers: { ...headers, ...exHeaders },
data,
})
return response.data
} catch (e) {
throw new SenderError(url, data, this.selfId)
}
}

async getSelf() {
Expand Down Expand Up @@ -63,7 +79,7 @@ export class DiscordBot extends Bot<'discord'> {
delete addition.content
async function sendMessage() {
const r = await that.request('POST', requestUrl, {
content: needSend,
content: needSend.trim(),
...addition,
})
sentMessageId = r.id
Expand All @@ -72,7 +88,7 @@ export class DiscordBot extends Bot<'discord'> {
for (const code of chain) {
const { type, data } = code
if (type === 'text') {
needSend += data.content
needSend += data.content.trim()
} else if (type === 'at' && data.id) {
needSend += `<@${data.id}>`
} else if (type === 'at' && data.type === 'all') {
Expand All @@ -84,7 +100,7 @@ export class DiscordBot extends Bot<'discord'> {
} else if (type === 'face' && data.name && data.id) {
needSend += `<:${data.name}:${data.id}>`
} else {
if (needSend) await sendMessage()
if (needSend.trim()) await sendMessage()
if (type === 'share') {
const sendData = isWebhook ? {
embeds: [{ ...addition, ...data }],
Expand All @@ -109,18 +125,22 @@ export class DiscordBot extends Bot<'discord'> {
})
sentMessageId = r.id
} else {
const a = await axios.get(data.url, {
responseType: 'arraybuffer',
})
const r = await this.sendEmbedMessage(requestUrl, a.data, {
...addition,
})
sentMessageId = r.id
try {
const a = await axios.get(data.url, {
responseType: 'arraybuffer',
})
const r = await this.sendEmbedMessage(requestUrl, a.data, {
...addition,
})
sentMessageId = r.id
} catch (e) {
throw new SenderError(data.url, data, this.selfId)
}
}
}
}
}
if (needSend) await sendMessage()
if (needSend.trim()) await sendMessage()
return sentMessageId
}

Expand Down Expand Up @@ -155,12 +175,12 @@ export class DiscordBot extends Bot<'discord'> {
})
}

async getMessageFromServer(channelId: string, messageId: string) {
async $getMessage(channelId: string, messageId: string) {
return this.request<DC.Message>('GET', `/channels/${channelId}/messages/${messageId}`)
}

async getMessage(channelId: string, messageId: string): Promise<MessageInfo> {
const msg = await this.getMessageFromServer(channelId, messageId)
const msg = await this.$getMessage(channelId, messageId)
const result: MessageInfo = {
messageId: msg.id,
channelId: msg.channel_id,
Expand All @@ -172,7 +192,7 @@ export class DiscordBot extends Bot<'discord'> {
}
result.author.nickname = msg.member?.nick
if (msg.message_reference) {
const quoteMsg = await this.getMessageFromServer(msg.message_reference.channel_id, msg.message_reference.message_id)
const quoteMsg = await this.$getMessage(msg.message_reference.channel_id, msg.message_reference.message_id)
result.quote = await adaptMessage(this, quoteMsg)
}
return result
Expand Down
10 changes: 6 additions & 4 deletions packages/adapter-discord/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import { Adapter } from 'koishi-core'
import { AxiosRequestConfig } from 'axios'
import { DiscordBot } from './bot'
import WsClient from './ws'
import { Embed } from './types'

import * as dc from './types'
export * from './bot'
export * as dc from './types'

Expand All @@ -16,9 +15,12 @@ declare module 'koishi-core' {
discord?: DiscordOptions
}

interface Session {
interface Session {
discord?: {
embeds: Embed[]
mentions: dc.User[];
// eslint-disable-next-line camelcase
webhook_id?: dc.snowflake
flags: number
}
}

Expand Down
15 changes: 13 additions & 2 deletions packages/adapter-discord/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export type Payload = {
s?: number
}

type snowflake = string
export type snowflake = string

/** https://discord.com/developers/docs/resources/emoji#emoji-object */
export interface Emoji {
Expand Down Expand Up @@ -357,14 +357,25 @@ export interface ModifyGuildMember extends Pick<GuildMember, 'nick' | 'roles' |
channel_id: snowflake
}

export type AllowedMentionType = 'roles' | 'users' | 'everyone'

/** https://discord.com/developers/docs/resources/channel#allowed-mentions-object */
export interface AllowedMention {
parse?: AllowedMentionType[]
roles?: snowflake[]
users?: snowflake[]
replied_user?: boolean
}

/** https://discord.com/developers/docs/resources/webhook#execute-webhook-jsonform-params */
export interface ExecuteWebhookBody {
content: string
username?: string
avatar_url?: string
tts: boolean;
tts?: boolean;
embeds?: Embed[]
common_embeds?: Embed[]
allowed_mentions?: AllowedMention[]
}

/** https://discord.com/developers/docs/resources/channel#overwrite-object-overwrite-structure */
Expand Down
42 changes: 21 additions & 21 deletions packages/adapter-discord/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { AuthorInfo, ChannelInfo, GroupInfo, MessageInfo, segment, Session, UserInfo } from 'koishi-core'
/* eslint-disable camelcase */
import { AuthorInfo, ChannelInfo, GroupInfo, segment, Session, UserInfo } from 'koishi-core'
import { DiscordBot } from './bot'
import * as DC from './types'

Expand Down Expand Up @@ -92,7 +93,9 @@ export async function adaptMessage(bot: DiscordBot, meta: DC.Message, session: P
}
}
session.discord = {
embeds: meta.embeds,
mentions: meta.mentions,
webhook_id: meta.webhook_id,
flags: meta.flags,
}
return session
}
Expand All @@ -101,41 +104,38 @@ async function adaptMessageSession(bot: DiscordBot, meta: DC.Message, session: P
await adaptMessage(bot, meta, session)
session.messageId = meta.id
session.timestamp = new Date(meta.timestamp).valueOf() || new Date().valueOf()
session.subtype = meta.guild_id ? 'group' : 'private'
if (meta.message_reference) {
const msg = await bot.getMessageFromServer(meta.message_reference.channel_id, meta.message_reference.message_id)
session.quote = await adaptMessage(bot, msg)
session.quote.messageId = meta.message_reference.message_id
session.quote.channelId = meta.message_reference.channel_id
}
// 遇到过 cross post 的消息在这里不会传消息id
// eslint-disable-next-line camelcase
session.content = segment('quote', { id: meta.message_reference.message_id, channelId: meta.message_reference.channel_id }) + session.content
return session
}

async function adaptMessageCreate(bot: DiscordBot, meta: DC.Message, session: Partial<Session.Payload<Session.MessageAction>>) {
session.groupId = meta.guild_id
session.subtype = meta.guild_id ? 'group' : 'private'
session.channelId = meta.channel_id
await adaptMessageSession(bot, meta, session)
}

export async function adaptSession(bot: DiscordBot, input: DC.Payload) {
const session: Partial<Session.Payload<Session.MessageAction>> = {
selfId: bot.selfId,
platform: 'discord',
}
if (input.t === 'MESSAGE_CREATE') {
session.type = 'message'
await adaptMessageCreate(bot, input.d as DC.Message, session)
if (!session.content) return
const msg = input.d as DC.Message
session.groupId = msg.guild_id
session.subtype = msg.guild_id ? 'group' : 'private'
session.channelId = msg.channel_id
await adaptMessageSession(bot, input.d, session)
// dc 情况特殊 可能有 embeds 但是没有消息主体
// if (!session.content) return
if (session.userId === bot.selfId) return
} else if (input.t === 'MESSAGE_UPDATE') {
session.type = 'message-updated'
const d = input.d as DC.Message
const msg = await bot.getMessageFromServer(d.channel_id, d.id)
session.groupId = d.guild_id
session.subtype = d.guild_id ? 'group' : 'private'
session.channelId = d.channel_id
const msg = await bot.$getMessage(d.channel_id, d.id)
// Unlike creates, message updates may contain only a subset of the full message object payload
// https://discord.com/developers/docs/topics/gateway#message-update
await adaptMessageCreate(bot, msg, session)
if (!session.content) return
await adaptMessageSession(bot, msg, session)
// if (!session.content) return
if (session.userId === bot.selfId) return
} else if (input.t === 'MESSAGE_DELETE') {
session.type = 'message-deleted'
Expand Down

0 comments on commit a280e52

Please sign in to comment.