Skip to content

Commit

Permalink
feat(zulip): migrate to satori v3
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Oct 16, 2023
1 parent 542af58 commit b93f076
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 98 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@
- [x] Line
- [x] Mail
- [x] Matrix
- [x] OneBot (v11,可用于 QQ)
- [x] OneBot
- [x] QQ Guild
- [x] Slack
- [x] Telegram
- [x] WhatsApp
- [x] WeCom (企业微信)
- [x] Wechat Official (微信公众号)
- [x] Zulip

## Examples

Expand Down
4 changes: 2 additions & 2 deletions adapters/discord/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ export async function decodeMessage(
return message
}

export function setupMessageGuildId(session: Partial<Session>, guildId: string) {
export function setupMessageGuildId(session: Session, guildId: string) {
session.guildId = guildId
session.isDirect = !guildId
session.subtype = guildId ? 'group' : 'private'
Expand All @@ -158,7 +158,7 @@ type ReactionEvent = Partial<
& Discord.Reaction.Event.RemoveAll
& Discord.Reaction.Event.RemoveEmoji>

function setupReaction(session: Partial<Session>, data: ReactionEvent) {
function setupReaction(session: Session, data: ReactionEvent) {
session.userId = data.user_id
session.messageId = data.message_id
session.guildId = data.guild_id
Expand Down
4 changes: 2 additions & 2 deletions adapters/kook/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ function adaptMessageSession(
return message
}

function adaptMessageCreate(data: Kook.Data, meta: Kook.MessageExtra, session: Partial<Session>) {
function adaptMessageCreate(data: Kook.Data, meta: Kook.MessageExtra, session: Session) {
session.guildId = meta.guild_id
if (data.channel_type === 'GROUP') {
session.isDirect = false
Expand All @@ -140,7 +140,7 @@ function adaptMessageModify(data: Kook.Data, meta: Kook.NoticeBody, session: Ses
adaptMessageSession(data, meta, session.event.message = {}, session.event)
}

function adaptReaction(body: Kook.NoticeBody, session: Partial<Session>) {
function adaptReaction(body: Kook.NoticeBody, session: Session) {
session.channelId = body.channel_id
session.messageId = body.msg_id
session.userId = body.user_id
Expand Down
2 changes: 1 addition & 1 deletion adapters/line/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export async function adaptMessage(bot: LineBot, message: EventMessage) {
}

export async function adaptSessions(bot: LineBot, body: WebhookEvent) {
const result: Partial<Session>[] = [bot.session({
const result: Session[] = [bot.session({
type: 'internal',
_type: `line/${hyphenate(body.type)}`,
_data: body,
Expand Down
2 changes: 1 addition & 1 deletion adapters/qq/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export async function decodeMessage(
return message
}

export function setupReaction(session: Partial<Session>, data: QQ.MessageReaction) {
export function setupReaction(session: Session, data: QQ.MessageReaction) {
session.userId = data.user_id
session.guildId = data.guild_id
session.channelId = data.channel_id
Expand Down
4 changes: 2 additions & 2 deletions adapters/slack/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ export async function adaptMessage(
}
}

export function adaptMessageDeleted(bot: SlackBot, event: MessageDeletedEvent, session: Partial<Session> = {}) {
export function adaptMessageDeleted(bot: SlackBot, event: MessageDeletedEvent, session: Session) {
session.isDirect = event.channel_type === 'im'
session.channelId = event.channel
session.guildId = event.previous_message.team
Expand All @@ -151,7 +151,7 @@ export function adaptSentAsset(file: File, session: Session) {
session.userId = file.user
}

function setupReaction(session: Partial<Session>, data: EnvelopedEvent<ReactionAddedEvent> | EnvelopedEvent<ReactionRemovedEvent>) {
function setupReaction(session: Session, data: EnvelopedEvent<ReactionAddedEvent> | EnvelopedEvent<ReactionRemovedEvent>) {
session.guildId = data.team_id
session.channelId = data.event.item.channel
session.messageId = data.event.item.ts
Expand Down
2 changes: 1 addition & 1 deletion adapters/zulip/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"@satorijs/satori": "^3.0.0-rc.1"
},
"dependencies": {
"marked": "^7.0.3"
"marked": "^9.1.2"
},
"devDependencies": {}
}
38 changes: 15 additions & 23 deletions adapters/zulip/src/bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { Internal } from './types'
import { ZulipMessageEncoder } from './message'
// @ts-ignore
import { version } from '../package.json'
import { decodeGuild, decodeMember, decodeMessage } from './utils'
import { decodeGuild, decodeMessage, decodeUser } from './utils'

export class ZulipBot extends Bot<ZulipBot.Config> {
static MessageEncoder = ZulipMessageEncoder

public http: Quester
public logger: Logger
public internal: Internal
Expand All @@ -31,16 +32,9 @@ export class ZulipBot extends Bot<ZulipBot.Config> {
ctx.plugin(HttpPolling, this)
}

async initliaze() {
const { avatar, userId, username } = await this.getSelf()
this.selfId = userId
this.username = username
this.avatar = avatar
}

async getGuildList() {
const { streams } = await this.internal.getStreams()
return streams.map(decodeGuild)
return { data: streams.map(decodeGuild) }
}

async getGuild(guildId: string) {
Expand All @@ -50,12 +44,12 @@ export class ZulipBot extends Bot<ZulipBot.Config> {

async getChannelList(guildId: string) {
const { topics } = await this.internal.getStreamTopics(guildId)
return topics.map(({ name }) => ({ channelId: name }))
return { data: topics.map(({ name }) => ({ id: name, type: Universal.Channel.Type.TEXT })) }
}

async getGuildMember(guildId: string, userId: string) {
const { user } = await this.internal.getUser(userId)
return decodeMember(user)
return decodeUser(user)
}

getUser(userId: string, guildId?: string) {
Expand All @@ -64,18 +58,18 @@ export class ZulipBot extends Bot<ZulipBot.Config> {

async getGuildMemberList(guildId: string) {
const { members } = await this.internal.getUsers()
return members.map(decodeMember)
return { data: members.map(m => ({ user: decodeUser(m) })) }
}

async getMessage(channelId: string, messageId: string) {
const { message } = await this.internal.getMessage(messageId)
const msg = await decodeMessage(this, message)
return msg
return await decodeMessage(this, message)
}

async getSelf() {
async getLogin() {
const self = await this.internal.getOwnUser()
return decodeMember(self)
this.user = decodeUser(self)
return this.toJSON()
}

async getMessageList(channelId: string, before?: string) {
Expand All @@ -88,15 +82,13 @@ export class ZulipBot extends Bot<ZulipBot.Config> {
anchor: before ?? 'newest',
apply_markdown: false,
})
return await Promise.all(messages.map(data => decodeMessage(this, data)))
const data = await Promise.all(messages.map(data => decodeMessage(this, data)))
return { data, next: data[0].id }
}

async getReactions(channelId: string, messageId: string, emoji: string): Promise<Universal.User[]> {
async getReactions(channelId: string, messageId: string, emoji: string) {
const { message } = await this.internal.getMessage(messageId)
return message.reactions.map(v => ({
userId: v.user_id.toString(),
username: v.user.full_name,
}))
return message.reactions.map(v => decodeUser(v.user))
}

async createReaction(channelId: string, messageId: string, emoji: string) {
Expand All @@ -113,7 +105,7 @@ export class ZulipBot extends Bot<ZulipBot.Config> {
}

export namespace ZulipBot {
export interface Config extends Bot.Config, Quester.Config, HttpPolling.Config {
export interface Config extends Quester.Config, HttpPolling.Config {
email: string
key: string
}
Expand Down
7 changes: 4 additions & 3 deletions adapters/zulip/src/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ export const unescape = (val: string) =>

export class ZulipMessageEncoder extends MessageEncoder<ZulipBot> {
buffer: string = ''

async flush() {
if (!this.buffer.length) return
const form = new FormData()
form.append('type', this.session.isDirect ? 'private' : 'stream')
form.append('to', this.session.isDirect
? `[${this.options.session.userId}]` : this.session.guildId)
? `[${this.options.session.userId}]`
: this.session.guildId)
form.append('content', this.buffer)
if (!this.session.isDirect) form.append('topic', this.session.channelId)

Expand All @@ -33,9 +35,8 @@ export class ZulipMessageEncoder extends MessageEncoder<ZulipBot> {
session.channelId = this.session.channelId
session.guildId = this.session.guildId
session.isDirect = this.session.isDirect
session.author = this.bot
session.app.emit(session, 'send', session)
this.results.push(session)
this.results.push(session.event.message)
}

async uploadMedia(element: h) {
Expand Down
23 changes: 13 additions & 10 deletions adapters/zulip/src/polling.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { Adapter, Quester, Schema, Time } from '@satorijs/satori'
import { Adapter, Quester, Schema, Time, Universal } from '@satorijs/satori'
import { ZulipBot } from './bot'
import { adaptSession } from './utils'

export class HttpPolling extends Adapter.Client<ZulipBot> {
export class HttpPolling extends Adapter<ZulipBot> {
static reusable = true

private timeout: NodeJS.Timeout
async start(bot: ZulipBot) {
await bot.initliaze()

async connect(bot: ZulipBot) {
await bot.getLogin()
const r = await bot.internal.registerQueue({
// event_types: `["message"]`,
})
Expand All @@ -19,19 +22,19 @@ export class HttpPolling extends Adapter.Client<ZulipBot> {
queue_id: r.queue_id,
last_event_id: last,
})
if (bot.status === 'disconnect') {
if (!bot.isActive) {
return bot.offline()
}
bot.online()
_retryCount = 0
for (const e of updates.events) {
bot.logger.debug(require('util').inspect(e, false, null, true))
bot.logger.debug('[receive] %o', e)

last = Math.max(last, e.id)
const session = await adaptSession(bot, e)

if (session) bot.dispatch(session)
bot.logger.debug(require('util').inspect(session, false, null, true))
bot.logger.debug('[session] %o', session)
}
setTimeout(polling, 0)
} catch (e) {
Expand All @@ -42,18 +45,18 @@ export class HttpPolling extends Adapter.Client<ZulipBot> {
}
if (_retryCount > retryTimes) {
bot.error = e
return bot.status = 'offline'
return bot.status = Universal.Status.OFFLINE
}
_retryCount++
bot.status = 'reconnect'
bot.status = Universal.Status.RECONNECT
this.timeout = setTimeout(() => polling(), retryInterval)
}
}
polling()
bot.logger.debug('listening updates %c', bot.sid)
}

async stop(bot: ZulipBot) {
async disconnect(bot: ZulipBot) {
clearTimeout(this.timeout)
}
}
Expand Down
Loading

0 comments on commit b93f076

Please sign in to comment.