const e = require("tiny-buffer-rpc/any"),
a = require(".."),
n = require("../lib/rpc/server"),
{ GENERIC_EVENTS: i } = require("@holepunchto/keet-core-api"),
t = require("hypercore-proof-queue"),
r = require("b4a"),
o = require("xache"),
s = require("suspendify"),
c = require("fs-native-lock"),
{ getNotificationBody: u, getNotificationTitle: d } = require("./utils/notification")
async function l(l, g) {
const p = Bare.argv[0],
f = Bare.argv[1],
y = Bare.argv[2],
w = "true" === Bare.argv[3],
h = "store" !== Bare.argv[1] || w,
k = h,
m = "ios" === Bare.platform,
b = Math.random().toString(16).slice(2),
v = "true" === Bare.argv[4],
q = Bare.argv[5],
B = Bare.argv[6],
S = Bare.argv[7],
x = Bare.argv[8] ? JSON.parse(r.toString(r.from(Bare.argv[8], "base64"))) : {},
A = x?.strings,
I = x.logFile || x.logFilePath || x.fileLogPath,
L = x.logFileMaxSize,
N = x.logLevel || "info"
let C = null,
E = 0,
R = !1
const F = (...e) => {
;(E++, M.logger.info(b, E, ...e))
},
{ keet: M } = a.from(p, {
buildType: f,
logger: { logFile: I, logLevel: N, logFileMaxSize: L },
devMirrors: k,
devUserRegistry: h,
hyperconfKey: S,
production: !0,
appVersion: B,
apiLogger: F,
mobile: !0,
storage: { id: y, wait: !0 },
})
function P(e) {
M.onerror(e)
}
v &&
require("sentry-bare").init({
release: q,
dsn: "https://cbea8d749dec25aa3e4443fe1ad280b4@o139579.ingest.us.sentry.io/4509075596967936",
})
const z = M.backendAPI,
D = new o({ maxSize: 1024 })
F("Started bare worker...")
const K = new s({
wakeupLinger: 6e3,
async pollLinger() {
const e = await U(),
a = Math.round(Math.max(1e3 * e - 1e4, 0))
return (F("app says we have", a, "left to suspend"), a)
},
async suspend() {
try {
;(F("Suspending..."),
await H,
F("Suspending queue"),
await T.suspend(),
F("Freeing lock so push can run"),
C && (await C.unlock()),
(C = null),
F("Suspending backend"),
await z.suspend(),
F("Signalling frontend to suspend"),
await G.request(!0),
K.interrupted
? F("interrupted skipping idle")
: (F("Asking bare to go Idle"), Bare.idle()))
} catch (e) {
F("Caught suspension error: " + e.stack)
}
},
async suspendCancelled() {
;(F("Signalling frontend to suspend (cancelled)"), await G.request(!1))
},
async presuspend() {
;(F("Presuspending..."), await M.presuspend())
},
async resume() {
await H
try {
;(F("Resuming..."),
await z.resume(),
F("Acquiring push lock"),
await J(),
F("Resuming push queue"),
await T.resume(),
F("Resuming concluded"))
} catch (e) {
F("Caught suspension error: " + e.stack)
}
},
async wakeup() {
;(F("Waking up"),
await H,
F("resuming backend"),
await z.resume(),
F("backgrounding the core"),
await M.wakeup(),
F("Wake up done"))
},
})
;(Bare.on("idle", function () {
console.log("Bare has fully idled, zzz....")
}),
Bare.on("suspend", function (e) {
;((R = !0),
(e = Math.max(e - 1e4, 0)),
F("Bare suspend, linger", e),
(null !== z.api.call && z.api.call.callIsActive) ||
(F("Asking suspendify to suspend"), K.suspend(e)))
}),
Bare.on("resume", function () {
;(F("Bare resume"), (R = !1), K.resume())
}),
Bare.on("wakeup", function () {
;(F("Bare wakeup"), K.wakeup())
}),
n(z, l))
const T = new t(`${p}/notifications`, async function (e) {
try {
;(!1 === z.opened && (await z.ready()),
F("Draining notification handler, got", e.length, "proofs"),
z.api.core.setProcessingNotifications(!0))
const a = M.rootCorestore,
n = new Set()
for (const i of e) {
const e = a.get({ discoveryKey: i.discoveryKey })
try {
;(await e.ready(),
i.data.block &&
e.length === i.data.block.index &&
i.data.upgrade &&
((i.data.block.nodes = []),
(i.data.upgrade.start = e.length),
(i.data.upgrade.length = 1),
(i.data.upgrade.nodes = [])),
await e.core.verify(i.data, null),
n.add(r.toString(i.discoveryKey, "hex")))
} catch (e) {
F("Ignoring proof update due to:", e.message)
}
try {
await e.close()
} catch {}
}
for (const e of n)
(F("Waking up", e), M.scheduleDiscoverySwarmingFromDiscoveryKey(r.from(e, "hex")))
F("Draining notification complete")
} catch (e) {
F("Error handling notifications queue", e)
} finally {
;(F("Draining notification complete, enabling notifications"),
z.api.core.setProcessingNotifications(!1))
}
}),
_ = l.register(512, { request: e, response: e }),
W = l.register(1280, { request: e, response: e }),
j = l.register(1536, { request: e, response: e }),
G = l.register(2816, { request: e, response: e }),
U = () => (m ? W.request({}) : 30),
V = (e) => _.request(e),
$ = () => j.request(),
H = (async function () {
;(F("Booting backend"),
await z.ready(),
Bare.off("uncaughtException", g).off("unhandledRejection", g),
Bare.on("uncaughtException", P).on("unhandledRejection", P),
F("Backend ready"),
await J(),
F("Acquired push lock"))
})()
async function J() {
;(C && (await C.unlock()), (C = new c(`${p}/lock`, { wait: !0 })), await C.lock())
}
!(async function () {
;(F("await booting in notifications"),
await H,
z.api.call.on("call-active", function () {
R && (F("Call started in bg, resuming"), K.resume())
}),
z.api.call.on("call-inactive", function () {
R &&
(F("Call ended in bg, suspending"),
z.api.call.callIsActive || (F("suspending now in 5000"), K.suspend(5e3)))
}),
F("subscribing to notifications"))
const e = await z.api.core.subscribeNotifications()
for await (const a of e)
switch (a.type) {
case i.CALL_HANGUP:
;(F("stopping call ring"),
await $(),
!z.api.call.callIsActive && R && (F("call hangup - suspending 5000"), K.suspend(5e3)))
break
case i.CALL_STARTED:
;(F("suspending"), R && K.suspend())
break
default:
if (!R) {
F("Not backgrounded, dropping")
continue
}
if (D.get(a.id)) {
F("message is in cache already, dropping", a.id)
continue
}
if ((D.set(a.id, !0), (a.strings = A), a.message)) {
const e = {
id: a.id,
threadIdentifier: a.roomId,
avatar: a.avatar,
title: d(a),
body: u(a),
userInfo: a.userInfo,
sound: { type: "named", name: "notif_default.wav" },
}
;(F("sending push notification"), V(e))
break
}
F("skipping push notification, no message")
}
})()
}
module.exports = { load: l }