const e = require("b4a"),
t = require("./registration"),
{ KeetContractError: i } = require("./errors"),
{ isMemberActive: s, getMemberForDeviceKey: a } = require("./query"),
{ addDevice: r, addMember: n } = require("./members"),
{
contract: {
hyperschema: { getEnum: o },
},
} = require("../../../schema/spec"),
d = o("@keet/room-type"),
c = o("@keet/build-type"),
m = [
"roomType",
"isExperimental",
"isJoiningDisabled",
"isAppendingDisabled",
"isCallingDisabled",
"isMembershipEventsDisabled",
"isAttachmentsDisabled",
"isLinksDisabled",
],
u = {
RoomType: 1,
IsExperimental: 2,
IsJoiningDisabled: 3,
IsAppendingDisabled: 4,
IsCallingDisabled: 5,
IsMembershipEventsDisabled: 6,
IsAttachmentsDisabled: 7,
IsLinksDisabled: 8,
}
async function l(
{
header: t,
digest: s,
config: o,
capabilities: c,
identity: m,
bootstrapDevice: u,
initialMembers: l,
},
p,
) {
const { genesis: y, db: g, writer: b } = p
if (!y) throw i.GENESIS_NOT_FIRST()
const k = { id: 0, count: 0, parent: null, stats: I() }
if (
(await g.insert("@keet/threads", k),
s.settings.roomType === d.Broadcast && (s.settings.isCallingDisabled = !0),
await g.insert("@keet/system-digest", s),
c && (await g.insert("@keet/room-capabilities", c)),
m && (await g.insert("@keet-private-id/identity", m)),
o && (await g.insert("@keet/room-config", o)),
l)
)
for (const i of l) {
const s = e.equals(i.attestation.memberKey, u.attestation.memberKey)
? { isAdmin: !0, isModerator: !0 }
: { isAdmin: !1, isModerator: !0 }
await n(t, i.profile, i.attestation, s, p)
}
await r(t, b.key, u.profile, u.attestation, { isActive: !0, isIndexing: !0 }, p)
const w = await a(g, b.key)
if (!u || !w) throw i.ABORT()
}
async function p({ version: e }, { db: t, writer: r, abi: n, hostcalls: o }) {
const [d, c] = await Promise.all([a(t, r.key), t.get("@keet/system-digest")])
if (!(9 !== e || (s(d) && d.status.isModerator))) return
if (!s(d) || !d.status.isModerator) throw i.ABORT()
if (c.abi.version >= e) return
e > (c.settings.isExperimental ? n.max : n.production) &&
o.interrupt({ unsupportedABI: e, digest: c })
const m = c.abi.version
;((c.abi.version = e), await A(t, m, e), await t.insert("@keet/system-digest", c))
}
async function y({ key: e, settings: t }, { db: r, writer: n }) {
const [o, d] = await Promise.all([a(r, n.key), r.get("@keet/system-digest")])
if (!s(o)) throw i.INACTIVE_MEMBER()
if (!o.status.isModerator) throw i.MODERATORS_ONLY()
if (0 === e || e > m.length) throw i.INVALID_SYSTEM_SETTING()
const c = d?.settings,
u = m[e - 1],
l = { ...c, [u]: t[u] }
await r.insert("@keet/system-digest", { ...d, settings: l })
}
async function g({ peer: e }, { db: t, writer: i }) {
const r = await a(t, i.key)
s(r) && r.status.isModerator && (await t.insert("@keet/blind-peers", e))
}
async function b({ key: e }, { db: t, writer: i }) {
const r = await a(t, i.key)
s(r) && r.status.isModerator && (await t.delete("@keet/blind-peers", { key: e }))
}
async function k({ from: e, to: t, buildType: i }, { db: r, writer: n }) {
const o = await a(r, n.key)
s(o) &&
o.status.isModerator &&
(e < 14 && t >= 14 && (await v(r), await h(r)),
e < 20 && t >= 20 && (await D(r)),
e < 24 && t >= 24 && (await f(r)),
e < 25 && t >= 25 && (await w(r, i)))
}
async function w(e, t) {
const i = await e.get("@keet/system-digest")
c[i.settings.buildType] ||
(c[t] && ((i.settings.buildType = c[t]), await e.insert("@keet/system-digest", i)))
}
async function f(e) {
if ((await e.get("@keet/system-digest")).settings.roomType === d.DirectMessage)
for await (const t of e.find("@keet/members"))
t.status.isModerator || ((t.status.isModerator = !0), await e.insert("@keet/members", t))
}
async function h(e) {
if (!(await e.get("@keet-private-id/identity"))) return
const t = { isPending: !1, isAccepted: !1, isRejected: !1, isDiscarded: !1, isSeen: !1 },
i = []
for (const s of await e.find("@keet-private-id/contact-requests").toArray()) {
const { isSeen: a, isAccepted: r, isRejected: n, isDiscarded: o } = s.status
;(s.status.isAccepted && (s.status = { ...t, isAccepted: r, isSeen: a }),
s.status.isRejected && (s.status = { ...t, isRejected: n, isSeen: a }),
s.status.isDiscarded && (s.status = { ...t, isDiscarded: o, isSeen: a }),
i.push(e.insert("@keet-private-id/contact-requests-v2", s)))
}
await Promise.all(i)
}
async function v(e) {
if (!(await e.get("@keet-private-id/identity"))) return
const t = []
for (const { memberKey: i, roomKey: s } of await e.find("@keet-private-id/contacts").toArray()) {
if (!s || !i) continue
const a = await e.get("@keet-private-id/rooms", { roomKey: s })
a && ((a.contact = i), t.push(e.insert("@keet-private-id/rooms", a)))
}
await Promise.all(t)
}
async function D(e) {
const [t, i, s] = await Promise.all([
e.get("@keet-private-id/identity"),
e.get("@keet/threads", { id: 0 }),
e.find("@keet/pinned-chat-messages").toArray(),
])
!t && i && ((i.stats.chat.pinned = s.length), await e.insert("@keet/threads", i))
}
function A(e, t, i) {
return Promise.resolve()
}
function M(e) {
;(e.add("@keet/genesis", l),
e.add("@keet/upgrade", p),
e.add("@keet/add-blind-peer", g),
e.add("@keet/remove-blind-peer", b),
e.add("@keet/update-system-settings", y),
e.add("@keet/migrate-abi", k))
}
function I() {
return {
devices: { total: 0, active: 0 },
members: { total: 0, active: 0, pending: 0 },
chat: { clock: 0, pinned: 0, threads: 0, timestamp: 0 },
files: { clock: 0 },
}
}
module.exports = { [t]: M, Settings: u }