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