OverviewFilesCommitsIssuesDocsReleasesPeers

keet-deobfuscated / @holepunchto / keet-core / lib / core / contract / avatars.js

153 lines · javascript ref:
const e = require("b4a"),
  { KeetContractError: i } = require("./errors"),
  { fileStats: r } = require("./stats"),
  n = 524288
async function t(r, t, l) {
  if (!t && !l) return
  if (!g(l)) return
  if (
    (l.preview && (l.preview = null),
    !l.pointer.inlined && l.pointer.blob && (l.pointer.blob = null),
    !l || !l.pointer.inlined)
  )
    return t || l
  if (t && t.hash && l.hash && e.equals(t.hash, l.hash)) return { ...l, pointer: t.pointer }
  if (l.pointer.inlined.byteLength > n)
    throw i.INLINED_FILESIZE_TOO_LARGE("Cannot inline a blob that is larger than 512 KB")
  const a = await r.put(l.pointer.inlined)
  return { ...l, pointer: { blob: a } }
}
async function l(e, i, r) {
  return {
    small: await t(e, i?.small, r?.small),
    medium: await t(e, i?.medium, r?.medium),
    large: await t(e, i?.large, r?.large),
  }
}
async function a(e, i, r) {
  return await l(e, i, r)
}
async function s(e, i) {
  return o(e, i)
}
async function o(e, i) {
  i && (await Promise.all([p(e, i.small), p(e, i.medium), p(e, i.large)]))
}
async function p(e, i) {
  if (!i) return
  if (!i.pointer.blob) return
  const r = await e.get(i.pointer.blob)
  i.pointer = { inlined: r }
}
async function f({ primaryThread: e, id: i, blobs: n, db: t, oplog: a, file: s }) {
  ;(s.preview && (s.preview = await l(n, null, s.preview)),
    s.pointer.inlined && (s.pointer.inlined = null),
    s.pointer.blob && (s.pointer.blob = null))
  const o = { id: i, oplog: a, status: { isDeleted: !1 }, file: s }
  return (await t.insert("@keet/files", o), await r(t, e, o), i)
}
async function u({ primaryThread: e, files: r, id: n, blobs: t, db: l, oplog: a }) {
  if (!r || r.length < 1) return []
  if (!v(r)) throw i.FILE_RECORD_INVALID()
  const s = []
  for (const i of r)
    s.push(await f({ primaryThread: e, id: n++, blobs: t, db: l, oplog: a, file: i }))
  return s
}
async function d({ primaryThread: e, clock: i, message: r, blobs: n, db: t, oplog: l }) {
  const a = r.files || [],
    s = await u({ primaryThread: e, files: a, id: i, blobs: n, db: t, oplog: l })
  return (
    await b({ primaryThread: e, clock: i + a.length, message: r, blobs: n, db: t, oplog: l }),
    s
  )
}
async function b({ primaryThread: e, clock: i, message: r, blobs: n, db: t, oplog: l }) {
  let a = 0
  const s = r?.display?.httpLink || []
  for (const r of s)
    (r.preview?.files && (r.preview.files = []),
      r.preview?.file &&
        ((r.preview.files = await u({
          primaryThread: e,
          id: i + a,
          files: [r.preview.file],
          blobs: n,
          db: t,
          oplog: l,
        })),
        (a += r.preview.files.length)))
  const o = r?.display?.pearLink || []
  for (const r of o)
    (r.preview?.files && (r.preview.files = []),
      r.preview?.file &&
        ((r.preview.files = await u({
          primaryThread: e,
          id: i + a,
          files: [r.preview.file],
          blobs: n,
          db: t,
          oplog: l,
        })),
        (a += r.preview.files.length)))
}
async function c({ primaryThread: e, message: i, db: r, blobs: n }) {
  const t = i.message?.files || [],
    l = i.message?.display?.httpLink || []
  for (const { preview: e } of l) e && e.files && e.files.length && t.push(...e.files)
  const a = i.message?.display?.pearLink || []
  for (const { preview: e } of a) e && e.files && e.files.length && t.push(...e.files)
  await w({ primaryThread: e, files: t, db: r, blobs: n })
}
async function w({ primaryThread: e, files: i, db: n, blobs: t }) {
  if (!i || !i.length) return
  const l = await Promise.all(i.map((e) => n.get("@keet/files", { id: e }))),
    a = []
  for (const i of l)
    ((i.status.isDeleted = !0), a.push(n.insert("@keet/files", i)), a.push(r(n, e, i, i)))
  await Promise.all(a)
}
function m(i, r) {
  return (
    (!i && !r) ||
    (!(!i && r) &&
      !(i && !r) &&
      (i.hash && r.hash
        ? e.equals(i.hash, r.hash)
        : e.equals(i.pointer.inlined, r.pointer.inlined)))
  )
}
function h(e, i) {
  const r = m(e?.small, i?.small),
    n = m(e?.medium, i?.medium),
    t = m(e?.large, i?.large)
  return r && n && t
}
function g(e) {
  return (
    e.preview &&
      (e.preview?.small?.preview && (e.preview.small.preview = null),
      e.preview?.medium?.preview && (e.preview.medium.preview = null),
      e.preview?.large?.preview && (e.preview.large.preview = null)),
    !(
      (e.pointer.externalDrive && !e.pointer.externalDrive.path) ||
      (e.pointer.externalDrive && e.pointer.externalBlob)
    )
  )
}
function v(e) {
  const i = Array.isArray(e) ? e : [e]
  for (const e of i) if (!g(e)) return !1
  return !0
}
module.exports = {
  isSameAvatar: h,
  updateAvatar: a,
  updateImageFile: l,
  restoreAvatar: s,
  restoreFile: o,
  insertMessageFiles: d,
  deleteMessageFiles: c,
  MAX_INLINED_FILE_SIZE: n,
}