const e = require("hypercore-id-encoding"),
l = require("hypercore-storage"),
t = require("multi-profile-store"),
a = require("@holepunchto/keet-push/lib/notifications.js"),
{ decodeValue: o } = require("autobase/lib/values.js"),
n = require("b4a"),
{
contract: {
hyperdispatch: { decode: i },
hyperschema: { getEnum: r },
},
} = require("../../schema/spec"),
c = r("@keet/room-type"),
s = require("../core/local"),
u = require("keet-identity-key")
function d(e) {
return "@keet/start-call" === e.name
? "call"
: "@keet/join-call" === e.name
? "call_joined"
: "@keet/end-call" === e.name || "@keet/leave-call" === e.name
? "call_hangup"
: void 0
}
function m(e) {
return "@keet/start-call" === e.name
? "Message for call"
: "@keet/join-call" === e.name
? "Message for call joined"
: "@keet/end-call" === e.name || "@keet/leave-call" === e.name
? "Message for call hangup"
: void 0
}
function y(e, l) {
switch (e) {
case c.Default:
return (l("Room type is default"), "0")
case c.Broadcast:
return (l("Room type is Broadcast"), "1")
case c.DirectMessage:
return (l("Room type is DirectMessage"), "2")
default:
throw new Error("Incompatible legacy room type:", e)
}
}
function f(e, l, t) {
try {
return !!u.verify(e, l, { expectedIdentity: t })
} catch {
return !1
}
}
module.exports = async function (r, c, { log: u = () => {}, profile: p = !0 } = {}) {
const g = t.open(r).active()
if (!g && p) return (u("no active profile is made"), null)
const { version: k, discoveryKey: h, proof: v } = a.decode(c),
b = new l(g ? g.storage : r, {
readOnly: !0,
blockCache: !1,
tableCacheIndexAndFilterBlocks: !1,
optimizeFiltersForMemory: !0,
maxOpenFiles: 1,
useDirectReads: !0,
filterPolicy: null,
})
try {
const l = s.rocks(b.rocks.columnFamily("keet/local-database"))
;(await l.ready(), u("Keet local database is ready"))
const [t, r] = await Promise.all([
l.get("@local/rooms-by-discovery-key", { discoveryKey: h }),
l.get("@local/identity"),
])
if (!t || t.status.isRemoved) return (u("Room member was removed from room"), null)
const c = await l.get("@local/room-preferences", { roomKey: t.roomKey })
if (c && (!c.status.isActive || c.status.isFullyMuted)) return null
const p = await a.receive(b, t.roomKey, v, k),
g = 1 === k ? p?.result : p,
x = 1 === k ? p?.attest : null
if ((u("Receiving notification"), !g)) return null
if ((u("Notification is good"), !g.block)) return null
if ((u("Notification was not blocked"), !g.newer)) return null
const K = g.key,
w = g.discoveryKey,
M = o(n.from(g.proof.block.value), {
autobase: t.roomKey,
encryptionKey: t.encryptionKey,
key: K,
manifest: g.proof.manifest,
index: g.block.index,
}),
[T, q] = await Promise.all([l.get("@local/devices", { device: { key: K } }), M]),
I = T?.device,
R = i(q),
[j, D] = await Promise.all([
I ? l.get("@local/contacts", { memberKey: I.memberKey }) : null,
I ? l.get("@local/members", { key: I.memberKey }) : null,
]),
F = !!j?.status.isBlocked
u("Blocked?: ", F)
const B = x ? f(x, K, r.publicKey) : D && n.equals(D.key, r.publicKey)
u(
`Member exists ?: ${null !== D} and keys are equal?: ${null !== D && n.equals(D.key, r.publicKey)}`,
)
const A = D ? D.profile.displayName : null,
P = D ? D.profile.avatar : null,
S = t ? t.config.avatar : null,
E = t ? t.digest.abi.version : 0
let N = null
switch (R.name) {
case "@keet/add-chat-message": {
const l = R.value.header.timestamp,
a = R.value.message
if (a?.files && a.files.length > 0) {
const e = a.files[0]
;((N = {
timestamp: l,
type: "file",
chatText: null,
callId: null,
fileType: e.metadata?.mimetype,
location: null,
}),
u("Message for file"))
} else if (a?.event?.locationShared)
((N = {
timestamp: l,
type: "location",
chatText: a.text,
callId: null,
fileType: null,
location: a.event.locationShared,
}),
u("Message for location"))
else if (a.text)
((N = {
timestamp: l,
type: "text",
chatText: a.text,
callId: null,
fileType: null,
location: null,
}),
u("Message for text"))
else if (a.event.callStarted && E < 23) {
if (Math.abs(Date.now() - l) > 12e4) return
;((N = {
timestamp: l,
type: "call",
chatText: null,
callId: e.encode(t.discoveryKey),
fileType: null,
location: null,
}),
u("Message for call"))
} else if (a.event.callHangup && E < 23) {
if (Math.abs(Date.now() - l) > 12e4) return
;((N = {
timestamp: l,
type: "call_hangup",
chatText: null,
callId: e.encode(t.discoveryKey),
fileType: null,
location: null,
}),
u("Message for call hangup"))
}
break
}
case "@keet/start-call":
case "@keet/join-call":
case "@keet/leave-call":
case "@keet/end-call": {
if (E < 23) return
const l = R.value.header.timestamp
if (Math.abs(Date.now() - l) > 12e4) return
const t = d(R),
a = m(R)
;((N = {
timestamp: l,
type: t,
chatText: null,
callId: e.encode(R.value.callKey),
fileType: null,
location: null,
}),
u(a))
break
}
}
const _ = {
id: null,
sender: { id: e.encode(K), length: g.length, blocked: F, self: B, name: A, memberAvatar: P },
room: {
key: t.roomKey,
title: t.config.title,
type: y(t.digest.settings.roomType, u),
roomAvatar: S,
},
proof: { discoveryKey: w, data: g.proof },
index: g.block.index,
message: N,
}
return (
(_.id = _.sender.id + (-1 !== _.index ? "/b" + _.index : "/l" + _.sender.length)),
u("Returning result"),
_
)
} catch (e) {
return (u("Error:", e), null)
} finally {
;(await b.close(), u("Storage closed"))
}
}