OverviewFilesCommitsIssuesDocsReleasesPeers

keet-cli / keet-core-4.14.4-pretty / workers / mobile.js

238 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"),
  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 }