UNPKG

@satorijs/core

Version:

Core components of Satorijs

188 lines (164 loc) 5.54 kB
import { Channel, Event, GuildMember, Message, Resource, User } from '@satorijs/protocol' import { clone, defineProperty, isNullable } from 'cosmokit' import { Context, Service } from 'cordis' import { Bot } from './bot' import h from '@satorijs/element' declare module '@satorijs/protocol' { interface SendOptions { session?: Session } } // Accessors export interface Session { type: string /** @deprecated */ subtype: string selfId: string platform: string timestamp: number userId?: string channelId?: string guildId?: string messageId?: string operatorId?: string roleId?: string quote?: Message referrer: any } export class Session<C extends Context = Context> { public [Service.tracker] = { associate: 'session', property: 'ctx', } public id: number // for backward compatibility public sn: number public bot!: Bot<C> public app!: C['root'] public event: Event public locales: string[] = [] constructor(bot: Bot<C>, event: Partial<Event>) { event.selfId ??= bot.selfId event.platform ??= bot.platform event.timestamp ??= Date.now() this.event = event as Event this.sn = this.id = ++bot.ctx.satori._sessionSeq defineProperty(this, 'bot', bot) defineProperty(this, 'app', bot.ctx.root) defineProperty(this, Context.current, bot.ctx) return Context.associate(this, 'session') } /** @deprecated */ get data() { return this.event } get isDirect() { return this.event.channel?.type === Channel.Type.DIRECT } set isDirect(value) { (this.event.channel ??= {} as Channel).type = value ? Channel.Type.DIRECT : Channel.Type.TEXT } get author() { return { ...this.event.user, ...this.event.member, userId: this.event.user?.id, username: this.event.user?.name, nickname: this.event.member?.name, } as GuildMember & User } get uid() { return `${this.platform}:${this.userId}` } get gid() { return `${this.platform}:${this.guildId}` } get cid() { return `${this.platform}:${this.channelId}` } get fid() { return `${this.platform}:${this.channelId}:${this.userId}` } get sid() { return `${this.platform}:${this.selfId}` } get elements() { return this.event.message?.elements } set elements(value) { this.event.message ??= {} this.event.message.elements = value } get content(): string | undefined { return this.event.message?.elements?.join('') } set content(value: string | undefined) { this.event.message ??= {} this.event.message.quote = undefined this.event.message.elements = isNullable(value) ? value : h.parse(value) if (this.event.message.elements?.[0]?.type === 'quote') { const el = this.event.message.elements.shift()! this.event.message.quote = Resource.decode(el) } } setInternal(type: string, data: any) { this.event._type = type this.event._data = data const internal = Object.create(this.bot.internal) defineProperty(this, type, Object.assign(internal, data)) } async transform(elements: h[]): Promise<h[]> { return await h.transformAsync(elements, async ({ type, attrs, children }, session) => { const render = type === 'component' ? attrs.is : this.app.get('component:' + type) if (!render) return true children = await render(attrs, children, session) return this.transform(h.toElementArray(children)) }, this) } toJSON() { const event: Event = { ...clone(this.event), sn: this.sn, login: this.bot.toJSON(), ['id' as never]: this.sn, // for backward compatibility } if (event.message?.elements) { event.message.content = this.content delete event.message.elements if (event.message.quote) { event.message.content = Resource.encode('quote', event.message.quote) + event.message.content! } } return event } } export function defineAccessor(prototype: {}, name: string, keys: string[]) { Object.defineProperty(prototype, name, { get() { return keys.reduce((data, key) => data?.[key], this) }, set(value) { // Do not set undefined value // See https://github.com/satorijs/satori/issues/166 if (value === undefined) return const _keys = keys.slice() const last = _keys.pop()! const data = _keys.reduce((data, key) => data[key] ??= {}, this) data[last] = value }, }) } defineAccessor(Session.prototype, 'type', ['event', 'type']) defineAccessor(Session.prototype, 'subtype', ['event', 'subtype']) defineAccessor(Session.prototype, 'selfId', ['event', 'selfId']) defineAccessor(Session.prototype, 'platform', ['event', 'platform']) defineAccessor(Session.prototype, 'timestamp', ['event', 'timestamp']) defineAccessor(Session.prototype, 'userId', ['event', 'user', 'id']) defineAccessor(Session.prototype, 'channelId', ['event', 'channel', 'id']) defineAccessor(Session.prototype, 'channelName', ['event', 'channel', 'name']) defineAccessor(Session.prototype, 'guildId', ['event', 'guild', 'id']) defineAccessor(Session.prototype, 'guildName', ['event', 'guild', 'name']) defineAccessor(Session.prototype, 'messageId', ['event', 'message', 'id']) defineAccessor(Session.prototype, 'operatorId', ['event', 'operator', 'id']) defineAccessor(Session.prototype, 'roleId', ['event', 'role', 'id']) defineAccessor(Session.prototype, 'quote', ['event', 'message', 'quote']) defineAccessor(Session.prototype, 'referrer', ['event', 'referrer'])