const { Transform: e, pipeline: t } = require("streamx"),
i = require("compact-encoding"),
a = require("b4a"),
{ ConfigSchema: s } = require("@holepunchto/keet-core-schemas"),
{ UpdateConfigOperationV1: n, UpdateConfigOperationV2: o } = s.Operations,
{
CONFIG: r,
VALIDATION: c,
FEATURES: h,
GENERIC_EVENTS: u,
isFeatureSupported: E,
} = require("@holepunchto/keet-core-api")
module.exports = class {
static Operations = new Set([n.TYPE, o.TYPE])
constructor(e) {
;((this.view = e),
(this.chat = null),
(this.members = null),
(this.config = null),
(this.configV2 = null))
}
initialize() {
;((this.chat = this.view.chat),
(this.members = this.view.members),
(this.chat = this.view.chat),
(this.config = this.view.collections.config),
(this.configV2 = this.view.bee))
}
async get(e) {
const t = await this.configV2.get(e, s.Encoding)
return s.getValue(t)
}
async getAll(e = {}) {
const t = {}
for await (const { key: i, value: a } of this.createReadStream(e)) t[i] = a
return t
}
async put(e, t) {
await this.configV2.put(e, t, s.Encoding)
}
createReadStream(i = {}) {
const a = this.configV2.createReadStream(i, s.Encoding)
return t(
a,
new e({
transform(e, t) {
t(null, { key: e.key, value: s.getValue(e) })
},
}),
)
}
async getConfig() {
const e = await this.config.get(r.V1_CONFIG_KEY)
return { ...(e ? e.value : {}), ...(await this.getAll()) }
}
async isBroadcastRoom() {
const e = await this.getConfig()
return !!e && "1" === e.roomType
}
async isDisableMembershipEvents() {
return 1 === (await this.get(r.DISABLE_MEMBERSHIP_EVENTS))
}
async deletePinnedMessageIfExists(e) {
const t = (await this.get(r.PINNED_MESSAGES)) || [],
i = t.findIndex((t) => a.equals(t.key, e.key) && t.seq === e.seq)
;-1 !== i &&
(t.splice(i, 1), await this.put(r.PINNED_MESSAGES, s.encodeValue(r.PINNED_MESSAGES, t)))
}
async _validate(e, t) {
const i = s.decodeValue(e, t)
switch (e) {
case r.PINNED_MESSAGES:
return (
!(await this.view.isUnsupportedFeature(h.PINNED_MESSAGES)) &&
(
await Promise.all([this._pinLimitNotExceeded(e, i), this._pinnedMessageExists(e, i)])
).every((e) => !0 === e)
)
case r.DISABLE_MEMBERSHIP_EVENTS:
return await this.view.isFeatureSupported(h.DISABLE_MEMBERSHIP_EVENTS)
default:
return !0
}
}
_pinLimitNotExceeded(e, t) {
return t.length <= c.PINNED_MESSAGES_LIMIT
}
async _pinnedMessageExists(e, t) {
const i = t.length ? t[t.length - 1] : null
return !i || (await this.chat.messageExists(i))
}
async _maybeTrackChange({ id: e, timestamp: t, from: i, to: a }) {
;(await this.view.isFeatureSupported(h.ROOM_RENAME_EVENT)) &&
null !== i &&
i !== a &&
(await this.chat.addMessage({
id: e,
timestamp: t,
event: { type: u.ROOM_TITLE_CHANGED, value: { from: i, to: a } },
}))
}
async _applyUpdateConfigOperationV1(e, { id: t }) {
const { key: a, value: s } = e.value
if (!(await this.members.isModerator(t.key))) return
const n = await this.view.internal.getCodeVersion()
if (E(n, h.V2_CONFIG)) return this.put(a, i.encode(i.string, s))
const o = await this.getConfig()
;(s ? (o[a] = s) : delete o[a], await this.config.update(r.V1_CONFIG_KEY, o, { upsert: !0 }))
}
async _applyUpdateConfigOperationV2(e, t) {
const { id: i } = t,
{ key: a, value: n } = e.value
if ((await this.members.isModerator(i.key)) && (await this._validate(a, n))) {
if (a === r.ROOM_TITLE) {
const e = await this.get(a),
i = s.decodeValue(a, n)
await this._maybeTrackChange({ ...t, from: e, to: i })
}
await this.put(a, n)
}
}
autobaseApply(e, t) {
switch (e.type) {
case n.TYPE:
return this._applyUpdateConfigOperationV1(e, t)
case o.TYPE:
return this._applyUpdateConfigOperationV2(e, t)
}
}
async migrate() {
const e = await this.config.get(r.V1_CONFIG_KEY)
if (e && e.value)
for await (const t of Object.keys(e.value)) {
const a = e.value[t]
await this.put(t, i.encode(i.string, a))
}
}
}