OverviewFilesCommitsIssuesDocsReleasesPeers

keet-deobfuscated / @holepunchto / keet-core / workers / mobile.js

241 lines · javascript ref:
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 }