const e = require("hypercore-id-encoding"),
{
getCapabilitiesForRole: t,
MemberRoles: n,
DISPLAY_TYPES: a,
GENERIC_EVENTS: s,
} = require("@holepunchto/keet-core-api"),
r = require("b4a"),
{
contract: {
hyperschema: { getEnum: i },
},
} = require("../../../schema/spec"),
o = i("@keet/room-type")
function d({ key: t, seq: n }) {
return { deviceId: e.encode(t), seq: n }
}
function l(t) {
return {
id: e.encode(t.key),
deviceId: e.encode(t.key),
swarmId: e.encode(t.profile.swarmKey),
isMobile: t.profile.isMobile,
name: t.profile.name,
status: t.status,
}
}
function c(t) {
if (!t) return null
const { key: n, blob: a } = t
return { id: e.encode(n), blob: a }
}
function m(t) {
if (!t) return null
const { key: n, path: a, version: s, size: r } = t
return { id: e.encode(n), path: a, version: s, size: r }
}
function u(e) {
if (!e) return null
const { inlined: t, blob: n, externalBlob: a, externalDrive: s } = e
return {
blob: n,
inlined: t ? r.toString(t, "base64") : null,
externalBlob: c(a),
externalDrive: m(s),
}
}
function p(e) {
return e
? (e.metadata?.userdata && (e.metadata.userdata = r.toString(e.metadata.userdata, "base64")),
{
hash: e.hash,
entry: e.entry,
metadata: e.metadata,
pointer: u(e.pointer),
preview: g(e.preview),
})
: null
}
function y(t) {
return t
? t.cleared
? { cleared: !0 }
: {
roomId: e.encode(t.roomKey),
httpLink: t.httpLink,
cleared: !1,
preview: t.preview
? { small: y(t.preview.small), medium: y(t.preview.medium), large: y(t.preview.large) }
: null,
}
: null
}
function g(e) {
return e ? { small: p(e.small), medium: p(e.medium), large: p(e.large) } : null
}
function f(t) {
if (!t) return null
const { memberJoined: n, memberLeft: a, memberRemoved: s } = t,
r = n?.memberKey || a?.memberKey || s?.memberKey,
i = r ? { memberId: e.encode(r) } : null
return { ...t, memberJoined: n && i, memberLeft: a && i, memberRemoved: s && i }
}
function b({ record: t, member: n, memberId: r, localRoom: i }) {
const { event: o, message: l, reactions: c = {}, labels: m = {} } = t,
u = f(o)
l && l.replyTo && (l.replyTo = d(l.replyTo))
let y = null
;(u && u.memberJoined && (y = { type: s.MEMBER_JOINED, value: u.memberJoined.memberId }),
u && u.memberLeft && (y = { type: s.MEMBER_LEFT, value: u.memberLeft.memberId }),
u && u.titleChanged && (y = { type: s.ROOM_TITLE_CHANGED, value: u.titleChanged }),
u && u.callStarted && (y = { type: s.CALL_STARTED, value: null }),
u && u.callHangup && (y = { type: s.CALL_HANGUP, value: null }),
u && u.callMissed && (y = { type: s.CALL_MISSED, value: null }))
const g = j(t)
return (
l && l.files && (l.files = l.files.map(p)),
{
timestamp: t.timestamp,
editedAt: t.editedAt,
memberId: r || e.encode(n?.key || t.oplog.key),
member: n ? M(n, i?.selfMember?.key) : null,
id: d(t.oplog),
deleted: t.status.isDeleted,
thread: t.id.thread,
clock: t.id.index,
message: { ...l, generic: u },
reactions: c,
labels: m,
read: t.read,
seq: t.id.index,
event: y,
replyTo: l && l.replyTo ? l.replyTo : null,
forwarded: !0 === l?.forwarded,
chat: {
text: l ? l.text : null,
edited: t.status.isEdited,
display: g,
mentions: g.filter((e) => e.type === a.MENTION),
},
files: l && l.files ? l.files : [],
file: l && l.files ? l.files[0] : null,
}
)
}
function v(e) {
return e
? {
total: e.total,
reactions: e.reactions.map((e) => ({ text: e.text, count: e.count, latest: [] })),
editedAt: e.editedAt,
}
: { total: 0, reactions: [] }
}
function I(e) {
return e.map((e) => e.reaction)
}
function k(t) {
return { sender: e.encode(t.sender), clock: t.clock, reaction: t.reaction }
}
function K(t) {
return {
roomId: e.encode(t.roomKey),
discoveryId: e.encode(t.discoveryKey),
dmMemberId: t.dm ? e.encode(t.dm) : null,
recipient: t.dm ? e.encode(t.dm) : null,
}
}
function h({ roomInfo: t, preferences: n, lastMessageMember: a, storageInfo: s, fileStats: r }) {
const i = t.dm?.length ? e.encode(t.dm[0]) : null
let o = null
return (
t.lastMessage && (o = { chat: b({ record: t.lastMessage, memberId: a?.memberId }), member: a }),
{
roomId: e.encode(t.roomKey),
discoveryId: e.encode(t.discoveryKey),
status: t.status,
stats: t.stats,
fork: t.fork,
self: {
sentLength: s ? s.hints.remoteContiguousLength : 0,
deviceId: t.selfDevice ? e.encode(t.selfDevice.key) : null,
member: t.selfMember ? M(t.selfMember, t.selfMember.key) : null,
},
digest: T(t.digest),
config: C(t.config, t.digest),
preferences: n,
lastMessage: o,
dmMemberId: i,
fileStats: r ? { total: r.total } : null,
activeCall: A(t.activeCall),
}
)
}
function A(t) {
return t
? {
callId: e.encode(t.callKey),
selfDeviceId: t.selfDeviceKey ? e.encode(t.selfDeviceKey) : null,
}
: null
}
function M(t, n) {
return t
? {
memberId: e.encode(t.key),
anonymous: !1,
name: t.profile.displayName ? t.profile.displayName.toLowerCase() : null,
status: t.status,
displayName: t.profile.displayName,
inactive: !t.status.isActive,
capabilities: Y(t.status),
avatar: g(t.profile.avatar),
local: !!n && r.equals(t.key, n),
pushNotifications: !0,
username: t.profile.username,
canDM: !!t.profile.mailbox,
}
: null
}
function R(t) {
return {
id: { memberId: e.encode(t.memberKey), roomId: e.encode(t.keys.key) },
roomId: e.encode(t.keys.key),
senderContactInfo: {
displayName: t.sender.displayName,
avatar: t.sender.avatar ? g(t.sender.avatar) : null,
memberId: e.encode(t.memberKey),
},
clock: t.clock,
message: t.message,
status: t.status,
sentAt: t.sentAt,
}
}
function D(t) {
const n = e.encode(t.id)
return {
id: n,
seedId: e.encode(t.invitationSeed),
discoveryId: n,
identityDeviceId: t.identity ? e.encode(t.identity.devicePublicKey) : null,
expires: -1,
}
}
function E(t) {
if (!t) return null
const n = t.request,
a = n.deviceKey,
s = n.device.profile.name,
r = n.identity.devicePublicKey
return { deviceName: s, deviceId: e.encode(a), identityDeviceId: e.encode(r) }
}
function T(e) {
return { ...e }
}
function L(t) {
return t ? t.map(e.encode) : null
}
function N(e) {
return { disableReadReceipts: e?.disableReadReceipts || !1 }
}
function w(e) {
return {
concurrency: e.concurrency,
maxWindow: e.maxWindow,
randomPunchInterval: e.randomPunchInterval,
connectionKeepAlive: e.connectionKeepAlive,
}
}
function C(e, t, n = []) {
return e
? {
...e,
avatar: g(e.avatar),
roomType: V(t.settings.roomType),
experimental: t.settings.isExperimental,
locked: t.settings.isJoiningDisabled,
frozen: t.settings.isAppendingDisabled,
isMembershipEventsDisabled: t.settings.isMembershipEventsDisabled,
pinnedMessages: n,
canCall: String(!t.settings.isCallingDisabled),
blindPeers: L(e.blindPeers),
}
: {}
}
function x(t) {
return t
? {
memberId: e.encode(t.attestation.memberKey),
displayName: t.profile.displayName,
username: t.profile.username,
avatar: g(t.profile.avatar),
contactInfo: r.toString(t.contactInfo, "base64"),
count: t.count,
}
: null
}
function S(t) {
return t ? { username: t.username, memberId: t.memberKey ? e.encode(t.memberKey) : null } : null
}
function B(t, n, a, s) {
let r = null
return (
a &&
(r = {
id: e.encode(a.roomKey),
status: {
isAccepted: !!a && 0 === a.stats.members.pending,
isWritable: !!a && a.status.isWritable,
},
}),
{
memberId: t,
activeRoom: r,
pendingRequest: s ? R(s) : null,
contactStatus: { isBlocked: !!n?.status?.isBlocked },
}
)
}
function O(t) {
return t ? { roomId: t.roomKey ? e.encode(t.roomKey) : null } : {}
}
function P(t) {
return {
code: t.code,
message: t.message,
stack: t.stack,
timestamp: t.timestamp,
isContractError: !0 === t.isContractError,
isKeetError: !0 === t.isKeetError,
roomId: t.roomKey ? e.encode(t.roomKey) : null,
details: O(t.details),
}
}
function _(e, t, n) {
const a = n?.displayName || ""
return {
id: e.messageId,
roomId: e.roomId,
avatar: e.avatar ?? "",
sender: { name: a },
config: { title: t.title, roomType: t.roomType },
message: {
type: e.messageType,
chatText: e.messageText,
fileType: e.fileType,
location: e.location,
},
userInfo: {
roomKey: e.roomId,
messageType: e.messageType,
isDmRoom: Q(t.roomType) === o.DirectMessage,
isBroadcast: Q(t.roomType) === o.Broadcast,
profileName: a,
},
}
}
function q(t) {
if (!t) return null
const n = 1 === t.version
return {
version: t.version,
callId: e.encode(t.callKey),
discoveryId: n ? e.encode(t.discoveryKey) : null,
createdAt: t.createdAt,
endedAt: t.endedAt,
members: t.members ? t.members.map(H) : [],
}
}
function H(t) {
return {
callId: e.encode(t.callKey),
memberId: e.encode(t.memberKey),
createdAt: t.createdAt,
devices: t.devices ? t.devices.map(J) : [],
}
}
function J(t) {
return {
callId: e.encode(t.callKey),
memberId: e.encode(t.memberKey),
deviceId: e.encode(t.deviceKey),
swarmId: e.encode(t.swarmKey),
createdAt: t.createdAt,
streams: t.streams ? t.streams.map(F) : [],
}
}
function F(t) {
return {
callId: e.encode(t.callKey),
streamId: e.encode(t.streamKey),
deviceId: e.encode(t.deviceKey),
createdAt: t.createdAt,
}
}
function j(e) {
if (!e?.message?.display) return []
let t = []
return (
e.message.display.mention &&
((e.message.display.mention = G(e.message.display.mention)),
(t = t.concat(e.message.display.mention))),
e.message.display.translation &&
((e.message.display.translation = U(e.message.display.translation)),
(t = t.concat(e.message.display.translation))),
e.message.display.httpLink &&
((e.message.display.httpLink = e.message.display.httpLink.map(z)),
(t = t.concat(e.message.display.httpLink))),
e.message.display.pearLink &&
((e.message.display.pearLink = e.message.display.pearLink.map(W)),
(t = t.concat(e.message.display.pearLink))),
e.message.display.bold &&
((e.message.display.bold = e.message.display.bold.map((e) => ({ ...e, type: a.BOLD }))),
(t = t.concat(e.message.display.bold))),
e.message.display.italic &&
((e.message.display.italic = e.message.display.italic.map((e) => ({ ...e, type: a.ITALIC }))),
(t = t.concat(e.message.display.italic))),
e.message.display.code &&
((e.message.display.code = e.message.display.code.map((e) => ({ ...e, type: a.CODE }))),
(t = t.concat(e.message.display.code))),
e.message.display.emoji &&
((e.message.display.emoji = e.message.display.emoji.map((e) => ({
...e.range,
content: e.content,
type: a.EMOJI,
}))),
(t = t.concat(e.message.display.emoji))),
e.message.display.codeBlock &&
((e.message.display.codeBlock = e.message.display.codeBlock.map((e) => ({
...e,
type: a.CODE_BLOCK,
}))),
(t = t.concat(e.message.display.codeBlock))),
e.message.display.strike &&
((e.message.display.strike = e.message.display.strike.map((e) => ({
...e,
type: a.STRIKE_THROUGH,
}))),
(t = t.concat(e.message.display.strike))),
t
)
}
function G(t) {
return Array.isArray(t)
? t.map((t) => ({
type: a.MENTION,
start: t.range.start,
length: t.range.length,
memberId: e.encode(t.memberKey),
}))
: []
}
function U(e) {
return Array.isArray(e)
? e.map((e) => ({
type: a.TRANSLATION,
start: e.range.start,
length: e.range.length,
language: e.language,
text: e.text,
}))
: []
}
function W(e) {
return { ...z(e), type: a.PEAR_LINK }
}
function z(e) {
return (
e?.preview?.file && (e.preview.file = p(e.preview.file)),
{
content: e.url,
start: e.range.start,
length: e.range.length,
type: a.HTTP_LINK,
preview: e.preview,
}
)
}
function Y(e) {
const a = e.isAdmin ? n.ADMIN : e.isModerator ? n.MODERATOR : n.PEER
return t(a)
}
function V(e) {
switch (e) {
case o.Default:
return "0"
case o.Broadcast:
return "1"
case o.DirectMessage:
return "2"
default:
throw new Error("Incompatible legacy room type:", e)
}
}
function Q(e) {
switch (e) {
case "0":
default:
return o.Default
case "1":
return o.Broadcast
case "2":
return o.DirectMessage
}
}
module.exports = {
encodeReaction: k,
encodeIdentityPairingRequest: E,
encodePrivateRoomRecord: K,
encodeDmRequest: R,
encodeRoomRecord: h,
encodeMemberRecord: M,
encodeInvitationRecord: D,
encodeChatMessage: b,
encodeImageFile: g,
encodeFile: p,
encodeFileEntry: y,
encodeReactionsDigest: v,
encodeMyReactions: I,
encodeDigest: T,
encodeConfig: C,
encodeUserSettings: N,
encodeMessageId: d,
encodeDevice: l,
encodeUser: x,
encodeContactInfo: B,
encodeReservation: S,
encodeErrorRecord: P,
encodeNotification: _,
encodeHyperDHTSettings: w,
encodeCallRecord: q,
}