nostr-social-graph
Advanced tools
Comparing version 1.0.9 to 1.0.10
var B = Object.defineProperty; | ||
var g = (f, t, e) => t in f ? B(f, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : f[t] = e; | ||
var h = (f, t, e) => g(f, typeof t != "symbol" ? t + "" : t, e); | ||
var g = (a, t, e) => t in a ? B(a, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : a[t] = e; | ||
var h = (a, t, e) => g(a, typeof t != "symbol" ? t + "" : t, e); | ||
class w { | ||
@@ -49,3 +49,3 @@ constructor(t) { | ||
h(this, "ids", new w()); | ||
this.ids = new w(e && e.uniqueIds), this.root = this.id(t), this.followDistanceByUser.set(this.root, 0), this.usersByFollowDistance.set(0, /* @__PURE__ */ new Set([this.root])), e && this.deserialize(e.followLists); | ||
this.ids = new w(e && e.uniqueIds), this.root = this.id(t), this.followDistanceByUser.set(this.root, 0), this.usersByFollowDistance.set(0, /* @__PURE__ */ new Set([this.root])), e && this.deserialize(e); | ||
} | ||
@@ -72,4 +72,4 @@ id(t) { | ||
if (!this.followDistanceByUser.has(i)) { | ||
const r = s + 1; | ||
this.followDistanceByUser.set(i, r), this.usersByFollowDistance.has(r) || this.usersByFollowDistance.set(r, /* @__PURE__ */ new Set()), this.usersByFollowDistance.get(r).add(i), t.push(i); | ||
const n = s + 1; | ||
this.followDistanceByUser.set(i, n), this.usersByFollowDistance.has(n) || this.usersByFollowDistance.set(n, /* @__PURE__ */ new Set()), this.usersByFollowDistance.get(n).add(i), t.push(i); | ||
} | ||
@@ -96,17 +96,17 @@ } | ||
const i = /* @__PURE__ */ new Set(); | ||
for (const n of t.tags) | ||
if (n[0] === "p") { | ||
if (!y.test(n[1])) | ||
for (const r of t.tags) | ||
if (r[0] === "p") { | ||
if (!y.test(r[1])) | ||
continue; | ||
const d = this.id(n[1]); | ||
const d = this.id(r[1]); | ||
d !== e && i.add(d); | ||
} | ||
const r = this.followedByUser.get(e) || /* @__PURE__ */ new Set(); | ||
for (const n of r) | ||
i.has(n) || this.privateRemoveFollower(n, e); | ||
for (const n of i) | ||
this.privateAddFollower(n, e); | ||
const n = this.followedByUser.get(e) || /* @__PURE__ */ new Set(); | ||
for (const r of n) | ||
i.has(r) || this.privateRemoveFollower(r, e); | ||
for (const r of i) | ||
this.privateAddFollower(r, e); | ||
} | ||
handleMuteList(t, e, s) { | ||
var n, d, c, a; | ||
var r, d, f, c; | ||
const o = this.muteListCreatedAt.get(e); | ||
@@ -124,7 +124,7 @@ if (o && s <= o) | ||
} | ||
const r = this.mutedByUser.get(e) || /* @__PURE__ */ new Set(); | ||
for (const l of r) | ||
i.has(l) || ((n = this.mutedByUser.get(e)) == null || n.delete(l), (d = this.userMutedBy.get(l)) == null || d.delete(e)); | ||
const n = this.mutedByUser.get(e) || /* @__PURE__ */ new Set(); | ||
for (const l of n) | ||
i.has(l) || ((r = this.mutedByUser.get(e)) == null || r.delete(l), (d = this.userMutedBy.get(l)) == null || d.delete(e)); | ||
for (const l of i) | ||
this.mutedByUser.has(e) || this.mutedByUser.set(e, /* @__PURE__ */ new Set()), (c = this.mutedByUser.get(e)) == null || c.add(l), this.userMutedBy.has(l) || this.userMutedBy.set(l, /* @__PURE__ */ new Set()), (a = this.userMutedBy.get(l)) == null || a.add(e); | ||
this.mutedByUser.has(e) || this.mutedByUser.set(e, /* @__PURE__ */ new Set()), (f = this.mutedByUser.get(e)) == null || f.add(l), this.userMutedBy.has(l) || this.userMutedBy.set(l, /* @__PURE__ */ new Set()), (c = this.userMutedBy.get(l)) == null || c.add(e); | ||
} | ||
@@ -155,4 +155,4 @@ isFollowing(t, e) { | ||
else { | ||
const r = this.followDistanceByUser.get(t), n = this.followDistanceByUser.get(e); | ||
i = n && n + 1, (r === void 0 || i && i < r) && (this.followDistanceByUser.set(t, i), this.addUserByFollowDistance(i, t)); | ||
const n = this.followDistanceByUser.get(t), r = this.followDistanceByUser.get(e); | ||
i = r && r + 1, (n === void 0 || i && i < n) && (this.followDistanceByUser.set(t, i), this.addUserByFollowDistance(i, t)); | ||
} | ||
@@ -173,5 +173,5 @@ } | ||
let s = 1 / 0; | ||
for (const r of this.followersByUser.get(t) || []) { | ||
const n = this.followDistanceByUser.get(r); | ||
n !== void 0 && n + 1 < s && (s = n + 1); | ||
for (const n of this.followersByUser.get(t) || []) { | ||
const r = this.followDistanceByUser.get(n); | ||
r !== void 0 && r + 1 < s && (s = r + 1); | ||
} | ||
@@ -231,28 +231,28 @@ s === 1 / 0 ? this.followDistanceByUser.delete(t) : this.followDistanceByUser.set(t, s); | ||
for (const [o, i] of this.followedByUser) { | ||
const r = this.followListCreatedAt.get(o); | ||
if (!r) | ||
const n = this.followListCreatedAt.get(o); | ||
if (!n) | ||
continue; | ||
if (e.push([o, [...i.values()], r]), t && e.length >= t) | ||
if (e.push([o, [...i.values()], n]), t && e.length >= t) | ||
return { followLists: e, uniqueIds: this.ids.serialize() }; | ||
const n = this.muteListCreatedAt.get(o), d = this.mutedByUser.get(o); | ||
n && d && s.push([o, [...d.values()], n]); | ||
const r = this.muteListCreatedAt.get(o), d = this.mutedByUser.get(o); | ||
r && d && s.push([o, [...d.values()], r]); | ||
} | ||
return { followLists: e, uniqueIds: this.ids.serialize(), muteLists: s }; | ||
} | ||
deserialize(t, e) { | ||
var o, i; | ||
const s = (o = t[0]) == null ? void 0 : o[0]; | ||
for (const [r, n, d] of t) { | ||
for (const c of n) | ||
deserialize(t) { | ||
var i, n; | ||
const { followLists: e, muteLists: s } = t, o = (i = e[0]) == null ? void 0 : i[0]; | ||
for (const [r, d, f] of e) { | ||
for (const c of d) | ||
this.privateAddFollower(c, r); | ||
this.followListCreatedAt.set(r, d ?? 0); | ||
this.followListCreatedAt.set(r, f ?? 0); | ||
} | ||
if (e) | ||
for (const [r, n, d] of e) { | ||
this.mutedByUser.set(r, new Set(n)); | ||
for (const c of n) | ||
this.userMutedBy.has(c) || this.userMutedBy.set(c, /* @__PURE__ */ new Set()), (i = this.userMutedBy.get(c)) == null || i.add(r); | ||
this.muteListCreatedAt.set(r, d ?? 0); | ||
if (s) | ||
for (const [r, d, f] of s) { | ||
this.mutedByUser.set(r, new Set(d)); | ||
for (const c of d) | ||
this.userMutedBy.has(c) || this.userMutedBy.set(c, /* @__PURE__ */ new Set()), (n = this.userMutedBy.get(c)) == null || n.add(r); | ||
this.muteListCreatedAt.set(r, f ?? 0); | ||
} | ||
s !== this.root && this.recalculateFollowDistances(); | ||
o !== this.root && this.recalculateFollowDistances(); | ||
} | ||
@@ -287,10 +287,10 @@ getUsersByFollowDistance(t) { | ||
mergeUserLists(t, e, s, o, i) { | ||
const r = this.id(t), n = e.get(r), d = s.get(r); | ||
if (!n || d && n < d) { | ||
const c = i.get(r) || /* @__PURE__ */ new Set(), a = o.get(r) || /* @__PURE__ */ new Set(); | ||
const n = this.id(t), r = e.get(n), d = s.get(n); | ||
if (!r || d && r < d) { | ||
const f = i.get(n) || /* @__PURE__ */ new Set(), c = o.get(n) || /* @__PURE__ */ new Set(); | ||
for (const l of f) | ||
c.has(l) || (o.has(n) || o.set(n, /* @__PURE__ */ new Set()), o.get(n).add(l)); | ||
for (const l of c) | ||
a.has(l) || (o.has(r) || o.set(r, /* @__PURE__ */ new Set()), o.get(r).add(l)); | ||
for (const l of a) | ||
c.has(l) || o.get(r).delete(l); | ||
e.set(r, d ?? 0); | ||
f.has(l) || o.get(n).delete(l); | ||
e.set(n, d ?? 0); | ||
} | ||
@@ -297,0 +297,0 @@ } |
@@ -1,1 +0,1 @@ | ||
(function(c,h){typeof exports=="object"&&typeof module<"u"?h(exports):typeof define=="function"&&define.amd?define(["exports"],h):(c=typeof globalThis<"u"?globalThis:c||self,h(c["nostr-social-graph"]={}))})(this,function(c){"use strict";var U=Object.defineProperty;var m=(c,h,a)=>h in c?U(c,h,{enumerable:!0,configurable:!0,writable:!0,value:a}):c[h]=a;var f=(c,h,a)=>m(c,typeof h!="symbol"?h+"":h,a);class h{constructor(t){f(this,"strToUniqueId",new Map);f(this,"uniqueIdToStr",new Map);f(this,"currentUniqueId",0);if(t)for(const[e,s]of t)this.strToUniqueId.set(e,s),this.uniqueIdToStr.set(s,e),this.currentUniqueId=Math.max(this.currentUniqueId,s+1)}id(t){const e=this.strToUniqueId.get(t);if(e!==void 0)return e;const s=this.currentUniqueId++;return this.strToUniqueId.set(t,s),this.uniqueIdToStr.set(s,t),s}str(t){const e=this.uniqueIdToStr.get(t);if(!e)throw new Error("pub: invalid id "+t);return e}has(t){return this.strToUniqueId.has(t)}serialize(){return Array.from(this.strToUniqueId.entries())}*[Symbol.iterator](){yield*this.uniqueIdToStr.entries()}}const a=/^[0-9a-fA-F]{64}$/;class B{constructor(t,e){f(this,"root");f(this,"followDistanceByUser",new Map);f(this,"usersByFollowDistance",new Map);f(this,"followedByUser",new Map);f(this,"followersByUser",new Map);f(this,"followListCreatedAt",new Map);f(this,"mutedByUser",new Map);f(this,"userMutedBy",new Map);f(this,"muteListCreatedAt",new Map);f(this,"ids",new h);this.ids=new h(e&&e.uniqueIds),this.root=this.id(t),this.followDistanceByUser.set(this.root,0),this.usersByFollowDistance.set(0,new Set([this.root])),e&&this.deserialize(e.followLists)}id(t){return this.ids.id(t)}str(t){return this.ids.str(t)}getRoot(){return this.str(this.root)}setRoot(t){const e=this.id(t);e!==this.root&&(this.root=e,this.recalculateFollowDistances())}recalculateFollowDistances(){this.followDistanceByUser.clear(),this.usersByFollowDistance.clear(),this.followDistanceByUser.set(this.root,0),this.usersByFollowDistance.set(0,new Set([this.root]));const t=[this.root];for(;t.length>0;){const e=t.shift(),s=this.followDistanceByUser.get(e),o=this.followedByUser.get(e)||new Set;for(const i of o)if(!this.followDistanceByUser.has(i)){const r=s+1;this.followDistanceByUser.set(i,r),this.usersByFollowDistance.has(r)||this.usersByFollowDistance.set(r,new Set),this.usersByFollowDistance.get(r).add(i),t.push(i)}}}handleEvent(t){const e=(Array.isArray(t)?t:[t]).filter(s=>[3,1e4].includes(s.kind));for(const s of e){const o=s.created_at;if(o>Math.floor(Date.now()/1e3)+10*60){console.debug("event.created_at more than 10 minutes in the future",s);continue}const i=this.id(s.pubkey);s.kind===3?this.handleFollowList(s,i,o):s.kind===1e4&&this.handleMuteList(s,i,o)}}handleFollowList(t,e,s){const o=this.followListCreatedAt.get(e);if(o&&s<=o)return;this.followListCreatedAt.set(e,s);const i=new Set;for(const n of t.tags)if(n[0]==="p"){if(!a.test(n[1]))continue;const d=this.id(n[1]);d!==e&&i.add(d)}const r=this.followedByUser.get(e)||new Set;for(const n of r)i.has(n)||this.privateRemoveFollower(n,e);for(const n of i)this.privateAddFollower(n,e)}handleMuteList(t,e,s){var n,d,u,w;const o=this.muteListCreatedAt.get(e);if(o&&s<=o)return;this.muteListCreatedAt.set(e,s);const i=new Set;for(const l of t.tags)if(l[0]==="p"){if(!a.test(l[1]))continue;const y=this.id(l[1]);y!==e&&i.add(y)}const r=this.mutedByUser.get(e)||new Set;for(const l of r)i.has(l)||((n=this.mutedByUser.get(e))==null||n.delete(l),(d=this.userMutedBy.get(l))==null||d.delete(e));for(const l of i)this.mutedByUser.has(e)||this.mutedByUser.set(e,new Set),(u=this.mutedByUser.get(e))==null||u.add(l),this.userMutedBy.has(l)||this.userMutedBy.set(l,new Set),(w=this.userMutedBy.get(l))==null||w.add(e)}isFollowing(t,e){var i;const s=this.id(e),o=this.id(t);return!!((i=this.followedByUser.get(o))!=null&&i.has(s))}getFollowDistance(t){const e=this.followDistanceByUser.get(this.id(t));return e===void 0?1e3:e}addUserByFollowDistance(t,e){var s,o;this.usersByFollowDistance.has(t)||this.usersByFollowDistance.set(t,new Set),(s=this.usersByFollowDistance.get(t))==null||s.add(e);for(const i of this.usersByFollowDistance.keys())i>t&&((o=this.usersByFollowDistance.get(i))==null||o.delete(e))}privateAddFollower(t,e){var s,o;if(typeof t!="number"||typeof e!="number")throw new Error("Invalid user id");if(this.followersByUser.has(t)||this.followersByUser.set(t,new Set),(s=this.followersByUser.get(t))==null||s.add(e),this.followedByUser.has(e)||this.followedByUser.set(e,new Set),t!==this.root){let i;if(e===this.root)i=1,this.addUserByFollowDistance(i,t),this.followDistanceByUser.set(t,i);else{const r=this.followDistanceByUser.get(t),n=this.followDistanceByUser.get(e);i=n&&n+1,(r===void 0||i&&i<r)&&(this.followDistanceByUser.set(t,i),this.addUserByFollowDistance(i,t))}}(o=this.followedByUser.get(e))==null||o.add(t)}addFollower(t,e){this.privateAddFollower(this.id(e),this.id(t))}removeFollower(t,e){this.privateRemoveFollower(this.id(e),this.id(t))}privateRemoveFollower(t,e){var o,i;if((o=this.followersByUser.get(t))==null||o.delete(e),(i=this.followedByUser.get(e))==null||i.delete(t),t===this.root)return;let s=1/0;for(const r of this.followersByUser.get(t)||[]){const n=this.followDistanceByUser.get(r);n!==void 0&&n+1<s&&(s=n+1)}s===1/0?this.followDistanceByUser.delete(t):this.followDistanceByUser.set(t,s)}followerCount(t){var s;const e=this.id(t);return((s=this.followersByUser.get(e))==null?void 0:s.size)??0}followedByFriendsCount(t){var o;let e=0;const s=this.id(t);for(const i of this.followersByUser.get(s)??[])(o=this.followedByUser.get(this.root))!=null&&o.has(i)&&e++;return e}size(){let t=0,e=0;const s={};for(const o of this.followedByUser.values())t+=o.size;for(const o of this.mutedByUser.values())e+=o.size;for(const[o,i]of this.usersByFollowDistance.entries())s[o]=i.size;return{users:this.followDistanceByUser.size,follows:t,mutes:e,sizeByDistance:s}}followedByFriends(t){var o;const e=this.id(t),s=new Set;for(const i of this.followersByUser.get(e)??[])(o=this.followedByUser.get(this.root))!=null&&o.has(i)&&s.add(this.str(i));return s}getFollowedByUser(t,e=!1){const s=this.id(t),o=new Set;for(const i of this.followedByUser.get(s)||[])o.add(this.str(i));return e&&o.add(t),o}getFollowersByUser(t){const e=this.id(t),s=new Set;for(const o of this.followersByUser.get(e)||[])s.add(this.str(o));return s}serialize(t){const e=[],s=[];for(const[o,i]of this.followedByUser){const r=this.followListCreatedAt.get(o);if(!r)continue;if(e.push([o,[...i.values()],r]),t&&e.length>=t)return{followLists:e,uniqueIds:this.ids.serialize()};const n=this.muteListCreatedAt.get(o),d=this.mutedByUser.get(o);n&&d&&s.push([o,[...d.values()],n])}return{followLists:e,uniqueIds:this.ids.serialize(),muteLists:s}}deserialize(t,e){var o,i;const s=(o=t[0])==null?void 0:o[0];for(const[r,n,d]of t){for(const u of n)this.privateAddFollower(u,r);this.followListCreatedAt.set(r,d??0)}if(e)for(const[r,n,d]of e){this.mutedByUser.set(r,new Set(n));for(const u of n)this.userMutedBy.has(u)||this.userMutedBy.set(u,new Set),(i=this.userMutedBy.get(u))==null||i.add(r);this.muteListCreatedAt.set(r,d??0)}s!==this.root&&this.recalculateFollowDistances()}getUsersByFollowDistance(t){const e=this.usersByFollowDistance.get(t)||new Set,s=new Set;for(const o of e)s.add(this.str(o));return s}getFollowListCreatedAt(t){return this.followListCreatedAt.get(this.id(t))}merge(t){console.log("size before merge",this.size()),console.time("merge graph");for(const e of t)this.mergeUserLists(e,this.followListCreatedAt,t.followListCreatedAt,this.followedByUser,t.followedByUser),this.mergeUserLists(e,this.muteListCreatedAt,t.muteListCreatedAt,this.mutedByUser,t.mutedByUser);this.recalculateFollowDistances(),console.timeEnd("merge graph"),console.log("size after merge",this.size())}mergeUserLists(t,e,s,o,i){const r=this.id(t),n=e.get(r),d=s.get(r);if(!n||d&&n<d){const u=i.get(r)||new Set,w=o.get(r)||new Set;for(const l of u)w.has(l)||(o.has(r)||o.set(r,new Set),o.get(r).add(l));for(const l of w)u.has(l)||o.get(r).delete(l);e.set(r,d??0)}}*userIterator(t){const e=Array.from(this.usersByFollowDistance.keys()).sort((s,o)=>s-o);for(const s of e){if(t!==void 0&&s>t)break;const o=this.usersByFollowDistance.get(s)||new Set;for(const i of o)yield this.str(i)}}[Symbol.iterator](){return this.userIterator()}getMutedByUser(t){const e=this.id(t),s=new Set;for(const o of this.mutedByUser.get(e)||[])s.add(this.str(o));return s}getUserMutedBy(t){const e=this.id(t),s=new Set;for(const o of this.userMutedBy.get(e)||[])s.add(this.str(o));return s}}c.SocialGraph=B,c.UniqueIds=h,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})}); | ||
(function(c,h){typeof exports=="object"&&typeof module<"u"?h(exports):typeof define=="function"&&define.amd?define(["exports"],h):(c=typeof globalThis<"u"?globalThis:c||self,h(c["nostr-social-graph"]={}))})(this,function(c){"use strict";var U=Object.defineProperty;var m=(c,h,w)=>h in c?U(c,h,{enumerable:!0,configurable:!0,writable:!0,value:w}):c[h]=w;var f=(c,h,w)=>m(c,typeof h!="symbol"?h+"":h,w);class h{constructor(t){f(this,"strToUniqueId",new Map);f(this,"uniqueIdToStr",new Map);f(this,"currentUniqueId",0);if(t)for(const[e,s]of t)this.strToUniqueId.set(e,s),this.uniqueIdToStr.set(s,e),this.currentUniqueId=Math.max(this.currentUniqueId,s+1)}id(t){const e=this.strToUniqueId.get(t);if(e!==void 0)return e;const s=this.currentUniqueId++;return this.strToUniqueId.set(t,s),this.uniqueIdToStr.set(s,t),s}str(t){const e=this.uniqueIdToStr.get(t);if(!e)throw new Error("pub: invalid id "+t);return e}has(t){return this.strToUniqueId.has(t)}serialize(){return Array.from(this.strToUniqueId.entries())}*[Symbol.iterator](){yield*this.uniqueIdToStr.entries()}}const w=/^[0-9a-fA-F]{64}$/;class B{constructor(t,e){f(this,"root");f(this,"followDistanceByUser",new Map);f(this,"usersByFollowDistance",new Map);f(this,"followedByUser",new Map);f(this,"followersByUser",new Map);f(this,"followListCreatedAt",new Map);f(this,"mutedByUser",new Map);f(this,"userMutedBy",new Map);f(this,"muteListCreatedAt",new Map);f(this,"ids",new h);this.ids=new h(e&&e.uniqueIds),this.root=this.id(t),this.followDistanceByUser.set(this.root,0),this.usersByFollowDistance.set(0,new Set([this.root])),e&&this.deserialize(e)}id(t){return this.ids.id(t)}str(t){return this.ids.str(t)}getRoot(){return this.str(this.root)}setRoot(t){const e=this.id(t);e!==this.root&&(this.root=e,this.recalculateFollowDistances())}recalculateFollowDistances(){this.followDistanceByUser.clear(),this.usersByFollowDistance.clear(),this.followDistanceByUser.set(this.root,0),this.usersByFollowDistance.set(0,new Set([this.root]));const t=[this.root];for(;t.length>0;){const e=t.shift(),s=this.followDistanceByUser.get(e),o=this.followedByUser.get(e)||new Set;for(const i of o)if(!this.followDistanceByUser.has(i)){const n=s+1;this.followDistanceByUser.set(i,n),this.usersByFollowDistance.has(n)||this.usersByFollowDistance.set(n,new Set),this.usersByFollowDistance.get(n).add(i),t.push(i)}}}handleEvent(t){const e=(Array.isArray(t)?t:[t]).filter(s=>[3,1e4].includes(s.kind));for(const s of e){const o=s.created_at;if(o>Math.floor(Date.now()/1e3)+10*60){console.debug("event.created_at more than 10 minutes in the future",s);continue}const i=this.id(s.pubkey);s.kind===3?this.handleFollowList(s,i,o):s.kind===1e4&&this.handleMuteList(s,i,o)}}handleFollowList(t,e,s){const o=this.followListCreatedAt.get(e);if(o&&s<=o)return;this.followListCreatedAt.set(e,s);const i=new Set;for(const r of t.tags)if(r[0]==="p"){if(!w.test(r[1]))continue;const d=this.id(r[1]);d!==e&&i.add(d)}const n=this.followedByUser.get(e)||new Set;for(const r of n)i.has(r)||this.privateRemoveFollower(r,e);for(const r of i)this.privateAddFollower(r,e)}handleMuteList(t,e,s){var r,d,a,u;const o=this.muteListCreatedAt.get(e);if(o&&s<=o)return;this.muteListCreatedAt.set(e,s);const i=new Set;for(const l of t.tags)if(l[0]==="p"){if(!w.test(l[1]))continue;const y=this.id(l[1]);y!==e&&i.add(y)}const n=this.mutedByUser.get(e)||new Set;for(const l of n)i.has(l)||((r=this.mutedByUser.get(e))==null||r.delete(l),(d=this.userMutedBy.get(l))==null||d.delete(e));for(const l of i)this.mutedByUser.has(e)||this.mutedByUser.set(e,new Set),(a=this.mutedByUser.get(e))==null||a.add(l),this.userMutedBy.has(l)||this.userMutedBy.set(l,new Set),(u=this.userMutedBy.get(l))==null||u.add(e)}isFollowing(t,e){var i;const s=this.id(e),o=this.id(t);return!!((i=this.followedByUser.get(o))!=null&&i.has(s))}getFollowDistance(t){const e=this.followDistanceByUser.get(this.id(t));return e===void 0?1e3:e}addUserByFollowDistance(t,e){var s,o;this.usersByFollowDistance.has(t)||this.usersByFollowDistance.set(t,new Set),(s=this.usersByFollowDistance.get(t))==null||s.add(e);for(const i of this.usersByFollowDistance.keys())i>t&&((o=this.usersByFollowDistance.get(i))==null||o.delete(e))}privateAddFollower(t,e){var s,o;if(typeof t!="number"||typeof e!="number")throw new Error("Invalid user id");if(this.followersByUser.has(t)||this.followersByUser.set(t,new Set),(s=this.followersByUser.get(t))==null||s.add(e),this.followedByUser.has(e)||this.followedByUser.set(e,new Set),t!==this.root){let i;if(e===this.root)i=1,this.addUserByFollowDistance(i,t),this.followDistanceByUser.set(t,i);else{const n=this.followDistanceByUser.get(t),r=this.followDistanceByUser.get(e);i=r&&r+1,(n===void 0||i&&i<n)&&(this.followDistanceByUser.set(t,i),this.addUserByFollowDistance(i,t))}}(o=this.followedByUser.get(e))==null||o.add(t)}addFollower(t,e){this.privateAddFollower(this.id(e),this.id(t))}removeFollower(t,e){this.privateRemoveFollower(this.id(e),this.id(t))}privateRemoveFollower(t,e){var o,i;if((o=this.followersByUser.get(t))==null||o.delete(e),(i=this.followedByUser.get(e))==null||i.delete(t),t===this.root)return;let s=1/0;for(const n of this.followersByUser.get(t)||[]){const r=this.followDistanceByUser.get(n);r!==void 0&&r+1<s&&(s=r+1)}s===1/0?this.followDistanceByUser.delete(t):this.followDistanceByUser.set(t,s)}followerCount(t){var s;const e=this.id(t);return((s=this.followersByUser.get(e))==null?void 0:s.size)??0}followedByFriendsCount(t){var o;let e=0;const s=this.id(t);for(const i of this.followersByUser.get(s)??[])(o=this.followedByUser.get(this.root))!=null&&o.has(i)&&e++;return e}size(){let t=0,e=0;const s={};for(const o of this.followedByUser.values())t+=o.size;for(const o of this.mutedByUser.values())e+=o.size;for(const[o,i]of this.usersByFollowDistance.entries())s[o]=i.size;return{users:this.followDistanceByUser.size,follows:t,mutes:e,sizeByDistance:s}}followedByFriends(t){var o;const e=this.id(t),s=new Set;for(const i of this.followersByUser.get(e)??[])(o=this.followedByUser.get(this.root))!=null&&o.has(i)&&s.add(this.str(i));return s}getFollowedByUser(t,e=!1){const s=this.id(t),o=new Set;for(const i of this.followedByUser.get(s)||[])o.add(this.str(i));return e&&o.add(t),o}getFollowersByUser(t){const e=this.id(t),s=new Set;for(const o of this.followersByUser.get(e)||[])s.add(this.str(o));return s}serialize(t){const e=[],s=[];for(const[o,i]of this.followedByUser){const n=this.followListCreatedAt.get(o);if(!n)continue;if(e.push([o,[...i.values()],n]),t&&e.length>=t)return{followLists:e,uniqueIds:this.ids.serialize()};const r=this.muteListCreatedAt.get(o),d=this.mutedByUser.get(o);r&&d&&s.push([o,[...d.values()],r])}return{followLists:e,uniqueIds:this.ids.serialize(),muteLists:s}}deserialize(t){var i,n;const{followLists:e,muteLists:s}=t,o=(i=e[0])==null?void 0:i[0];for(const[r,d,a]of e){for(const u of d)this.privateAddFollower(u,r);this.followListCreatedAt.set(r,a??0)}if(s)for(const[r,d,a]of s){this.mutedByUser.set(r,new Set(d));for(const u of d)this.userMutedBy.has(u)||this.userMutedBy.set(u,new Set),(n=this.userMutedBy.get(u))==null||n.add(r);this.muteListCreatedAt.set(r,a??0)}o!==this.root&&this.recalculateFollowDistances()}getUsersByFollowDistance(t){const e=this.usersByFollowDistance.get(t)||new Set,s=new Set;for(const o of e)s.add(this.str(o));return s}getFollowListCreatedAt(t){return this.followListCreatedAt.get(this.id(t))}merge(t){console.log("size before merge",this.size()),console.time("merge graph");for(const e of t)this.mergeUserLists(e,this.followListCreatedAt,t.followListCreatedAt,this.followedByUser,t.followedByUser),this.mergeUserLists(e,this.muteListCreatedAt,t.muteListCreatedAt,this.mutedByUser,t.mutedByUser);this.recalculateFollowDistances(),console.timeEnd("merge graph"),console.log("size after merge",this.size())}mergeUserLists(t,e,s,o,i){const n=this.id(t),r=e.get(n),d=s.get(n);if(!r||d&&r<d){const a=i.get(n)||new Set,u=o.get(n)||new Set;for(const l of a)u.has(l)||(o.has(n)||o.set(n,new Set),o.get(n).add(l));for(const l of u)a.has(l)||o.get(n).delete(l);e.set(n,d??0)}}*userIterator(t){const e=Array.from(this.usersByFollowDistance.keys()).sort((s,o)=>s-o);for(const s of e){if(t!==void 0&&s>t)break;const o=this.usersByFollowDistance.get(s)||new Set;for(const i of o)yield this.str(i)}}[Symbol.iterator](){return this.userIterator()}getMutedByUser(t){const e=this.id(t),s=new Set;for(const o of this.mutedByUser.get(e)||[])s.add(this.str(o));return s}getUserMutedBy(t){const e=this.id(t),s=new Set;for(const o of this.userMutedBy.get(e)||[])s.add(this.str(o));return s}}c.SocialGraph=B,c.UniqueIds=h,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})}); |
{ | ||
"name": "nostr-social-graph", | ||
"version": "1.0.9", | ||
"version": "1.0.10", | ||
"type": "module", | ||
@@ -5,0 +5,0 @@ "packageManager": "yarn@1.22.22", |
@@ -29,3 +29,3 @@ import { SerializedUniqueIds, UniqueIds } from './UniqueIds'; | ||
this.usersByFollowDistance.set(0, new Set([this.root])); | ||
serialized && this.deserialize(serialized.followLists); | ||
serialized && this.deserialize(serialized); | ||
} | ||
@@ -361,4 +361,5 @@ | ||
private deserialize(followLists: SerializedUserList[], muteLists?: SerializedUserList[]): void { | ||
const serializedRoot = followLists[0]?.[0] | ||
private deserialize(serialized: SerializedSocialGraph): void { | ||
const { followLists, muteLists } = serialized; | ||
const serializedRoot = followLists[0]?.[0]; | ||
for (const [follower, followedUsers, createdAt] of followLists) { | ||
@@ -368,18 +369,18 @@ for (const followedUser of followedUsers) { | ||
} | ||
this.followListCreatedAt.set(follower, createdAt ?? 0) | ||
this.followListCreatedAt.set(follower, createdAt ?? 0); | ||
} | ||
if (muteLists) { | ||
for (const [muter, mutedUsers, createdAt] of muteLists) { | ||
this.mutedByUser.set(muter, new Set(mutedUsers)) | ||
this.mutedByUser.set(muter, new Set(mutedUsers)); | ||
for (const mutedUser of mutedUsers) { | ||
if (!this.userMutedBy.has(mutedUser)) { | ||
this.userMutedBy.set(mutedUser, new Set()) | ||
this.userMutedBy.set(mutedUser, new Set()); | ||
} | ||
this.userMutedBy.get(mutedUser)?.add(muter) | ||
this.userMutedBy.get(mutedUser)?.add(muter); | ||
} | ||
this.muteListCreatedAt.set(muter, createdAt ?? 0) | ||
this.muteListCreatedAt.set(muter, createdAt ?? 0); | ||
} | ||
} | ||
if (serializedRoot !== this.root) { | ||
this.recalculateFollowDistances() | ||
this.recalculateFollowDistances(); | ||
} | ||
@@ -386,0 +387,0 @@ } |
Sorry, the diff of this file is not supported yet
7896375
925