OverviewFilesCommitsIssuesDocsReleasesPeers

keet-cli / keet-core-4.14.4-pretty / lib / core / tasks / contacts / request.js

293 lines · javascript ref:
const e = require("hypercore-crypto"),
  t = require("signal-promise"),
  i = require("safety-catch"),
  { Task: o } = require("../task"),
  { restoreAvatar: s } = require("../../contract/avatars"),
  {
    contract: {
      hyperschema: { getEnum: r },
    },
  } = require("../../../../schema/spec"),
  {
    getWriterKey: a,
    createContactRequestOperation: n,
    generateRoomCapabilities: m,
    generatePairingCapabilities: h,
  } = require("../../invitations"),
  l = r("@keet/room-type")
module.exports = class extends o {
  constructor(e) {
    super(e)
    const t = this.description.sendContactRequest
    ;((this._roomKey = t.roomKey),
      (this._memberKey = t.memberKey),
      (this._message = t.message),
      (this._contactInfo = t.contactInfo),
      (this._member = null),
      (this._contact = null),
      (this._writerInfo = null),
      (this._contactRoomInfo = null),
      (this._privateContactRoom = null),
      (this._selfMember = null),
      (this._targetMember = null),
      (this._roomMailbox = null),
      (this._memberMailbox = null),
      (this._memberMailboxDiscoveryKey = null),
      (this._core = null),
      (this._dmRoom = null),
      (this._memberRoom = null),
      (this._privateProfile = null),
      (this._wakeupSession = null),
      (this._watcher = null),
      (this._privateProfileWatcher = null))
  }
  async _close() {
    ;(this._dmRoom &&
      (this._watcher && this._dmRoom.db.unwatch(this._watcher),
      this.keet.internalReleaseRoom(this._dmRoom)),
      this._memberRoom && this.keet.internalReleaseRoom(this._memberRoom),
      this._privateProfile &&
        (this._privateProfileWatcher &&
          this._privateProfile.db.unwatch(this._privateProfileWatcher),
        this.keet.internalReleaseRoom(this._privateProfile)),
      this._wakeupSession && this._wakeupSession.destroy())
  }
  async _createRoom() {
    const t = e.keyPair(),
      i = e.randomBytes(32),
      o = a(t.publicKey),
      s = m(o, i),
      r = { identity: this._identityInfo, privateProfile: this._privateProfileInfo },
      n = this.keet.internalCreateDeviceUpdate(r, o)
    return (
      (this._roomMailbox = s.mailboxKeyPair.publicKey),
      (this._dmRoom = await this.keet.internalCreateRoom({
        settings: { roomType: l.DirectMessage },
        initialMembers: [this._selfMember, this._targetMember],
        bootstrapDevice: n,
        keyPair: t,
        seed: i,
      })),
      this._message &&
        (await this._dmRoom.dispatch("@keet/add-chat-message", {
          message: { text: this._message },
        })),
      !0
    )
  }
  async _appendContactRequest() {
    if (!(await this.keet.internalVerifyOptimisticCore(this._core)) || this.closing) return
    const e = {
        message: this._message,
        sender: this._selfMember,
        mailbox: this._roomMailbox,
        keys: { key: this._dmRoom.key, encryptionKey: this._dmRoom.encryptionKey },
      },
      t = n(this._memberMailbox, this._identityInfo, e),
      i = {
        memberKey: this._memberKey,
        mailbox: this._memberMailbox,
        roomKey: this._dmRoom.key,
        status: { isBlocked: !1 },
      }
    return (
      await Promise.all([
        this._core.append(t),
        this._privateProfile.dispatch("@keet-private-id/add-contact", { contact: i }),
      ]),
      !0
    )
  }
  async _loadRequestWriter() {
    if (
      ((this._writerInfo = await this.local.get("@local/writers", {
        mailbox: this._memberMailbox,
      })),
      this._writerInfo)
    )
      return
    const t = e.keyPair(),
      i = a(t.publicKey)
    this._writerInfo = { mailbox: this._memberMailbox, keyPair: t, key: i }
    const o = await this.keet.internalEnterLocalTransaction()
    try {
      ;(await o.insert("@local/writers", this._writerInfo), await o.flush())
    } finally {
      await this.keet.internalExitLocalTransaction()
    }
  }
  _getQueryRange() {
    return {
      gte: { contact: this._targetMember.attestation.memberKey },
      lte: { contact: this._targetMember.attestation.memberKey },
    }
  }
  async _load() {
    if (
      (this.keet.onlineBoot.opened || (await this.keet.onlineBoot.ready()),
      (this._identityInfo = await this.local.get("@local/identity")),
      this.closing)
    )
      return !1
    const e = this._identityInfo.privateProfileKey
    if (
      ((this._privateProfileInfo = await this.local.get("@local/rooms", { roomKey: e })),
      this.closing)
    )
      return !1
    if (
      ((this._privateProfile = this.keet.internalOpenExistingRoom(e)),
      await this._privateProfile.ready(),
      this.closing)
    )
      return !1
    let t = !1
    return (
      (t = this._contactInfo ? await this._useContactInfo() : await this._useRoomKey()),
      !(
        !this._targetMember?.profile?.displayName ||
        (await this._loadRequestWriter(),
        this.closing ||
          ((this._core = this.store.get({ keyPair: this._writerInfo.keyPair })),
          await this._core.ready(),
          this.closing ||
            ((this._privateContactRoom = await this._privateProfile.db.findOne(
              "@keet-private-id/rooms-by-contact",
              this._getQueryRange(),
            )),
            (!t || this._privateContactRoom) && (await this._waitForMember(), 1))))
      )
    )
  }
  async _useContactInfo() {
    const e = await this._privateProfile.db.get("@keet-private-id/contacts", {
      memberKey: this._memberKey,
    })
    if (
      ((this._contact = e),
      (this._memberMailbox = this._contactInfo.profile.mailbox),
      (this._member = null),
      (this._memberProofs = null),
      (this._memberPairingCapabilities = h(this._memberMailbox)),
      (this._targetMember = {
        profile: this._contactInfo.profile,
        attestation: this._contactInfo.attestation,
      }),
      e?.roomKey &&
        (this._contactRoomInfo = await this._privateProfile.db.get("@keet-private-id/rooms", {
          roomKey: this._contact.roomKey,
        })),
      this.closing || this._contactRoomInfo?.status.isActive)
    )
      return !1
    const t = this._privateProfileInfo.selfMember
    return (
      (this._selfMember = {
        profile: t.profile,
        attestation: { memberKey: t.key, proof: t.proofs.profileAttestation },
      }),
      !0
    )
  }
  async _useRoomKey() {
    if (
      ((this._memberRoom = this.keet.internalOpenExistingRoom(this._roomKey)),
      await this._memberRoom.ready(),
      this.closing)
    )
      return !1
    const [e, t, i] = await Promise.all([
      this._privateProfile.db.get("@keet-private-id/contacts", { memberKey: this._memberKey }),
      this._memberRoom.db.get("@keet/members", { key: this._memberKey }),
      this._memberRoom.db.get("@keet/member-proofs", { key: this._memberKey }),
    ])
    if (
      ((this._contact = e),
      (this._member = t),
      (this._memberProofs = i),
      (this._memberMailbox = this._member.profile.mailbox),
      (this._memberPairingCapabilities = h(this._memberMailbox)),
      this.closing || !t || !i)
    )
      return !1
    if (
      ((this._targetMember = {
        profile: this._member.profile,
        attestation: { memberKey: this._member.key, proof: this._memberProofs.profileAttestation },
      }),
      e?.roomKey &&
        (this._contactRoomInfo = await this._privateProfile.db.get("@keet-private-id/rooms", {
          roomKey: this._contact.roomKey,
        })),
      this.closing || this._contactRoomInfo?.status.isActive)
    )
      return !1
    const o = this._privateProfileInfo.selfMember
    return (
      (this._selfMember = {
        profile: o.profile,
        attestation: { memberKey: o.key, proof: o.proofs.profileAttestation },
      }),
      this._targetMember.profile.avatar &&
        (await s(this._memberRoom.blobs, this._targetMember.profile.avatar)),
      !0
    )
  }
  async _waitForMember() {
    if (!this._dmRoom) {
      const e = this._privateContactRoom?.roomKey || this._contact.roomKey
      this._dmRoom = this.keet.internalOpenExistingRoom(e)
    }
    this.swarmWorker.startActiveSwarming(this._memberPairingCapabilities.swarmTopic)
    const e = (e) => {
      this._wakeupSession.announce(e, [{ key: this._core.key, length: this._core.length }])
    }
    this._wakeupSession = this.keet.protomuxWakeup.session(this._memberMailbox, {
      discoveryKey: this._memberPairingCapabilities.wakeupTopic,
      onpeeractive: e,
    })
    for (const t of this._wakeupSession.peers) t.active && e(t)
    ;(this.keet.blindPeering.addCoreBackground(this._core, {
      target: this._memberMailbox,
      referrer: this._memberMailbox,
      priority: 1,
    }),
      (this._signal = new t()),
      (this._watcher = async () => {
        try {
          const e = this._targetMember.attestation.memberKey
          ;(await this._dmRoom.db.findOne("@keet/devices-by-member-key", {
            gte: { memberKey: e },
            lte: { memberKey: e },
          })) && this._signal.notify()
        } catch (e) {
          i(e)
        }
      }),
      this._dmRoom.db.watch(this._watcher),
      this._watcher(),
      (this._privateProfileWatcher = async () => {
        try {
          const e = await await this._privateProfile.db.get("@keet-private-id/rooms", {
            roomKey: this._dmRoom.key,
          })
          e && !1 === e.status.isActive && this._signal.notify()
        } catch (e) {
          i(e)
        }
      }),
      this._privateProfile.db.watch(this._privateProfileWatcher),
      this._privateProfileWatcher(),
      await this._signal.wait(),
      this.swarmWorker.stopActiveSwarming(this._memberPairingCapabilities.swarmTopic))
  }
  async _run() {
    const e = await this._load()
    if (this.closing || !e) return
    const t = await this._createRoom()
    if (this.closing || !t) return
    const i = await this._appendContactRequest()
    !this.closing && i && (await this._waitForMember())
  }
}