Browse Source

advancing SNH-Multiverse

psy 2 years ago
parent
commit
34d8ee2eea
11 changed files with 4416 additions and 5561 deletions
  1. 0 1
      .cspell.json
  2. 2 2
      docs/install.md
  3. 4319 5486
      package-lock.json
  4. 16 14
      package.json
  5. 1 1
      src/assets/style.css
  6. 1 3
      src/index.js
  7. 0 3
      src/models.js
  8. 42 0
      src/server.js
  9. 3 33
      src/ssb/index.js
  10. 4 4
      src/views/i18n.js
  11. 28 14
      src/views/index.js

+ 0 - 1
.cspell.json

@@ -18,7 +18,6 @@
     "abortable",
     "abortable",
     "autoconf",
     "autoconf",
     "automake",
     "automake",
-    "backlinks",
     "christianbundy",
     "christianbundy",
     "dogfood",
     "dogfood",
     "hyperaxe",
     "hyperaxe",

+ 2 - 2
docs/install.md

@@ -12,8 +12,8 @@ For a GNU/Linux based system, execute the following steps (from a shell):
     sudo apt-get install -y nodejs
     sudo apt-get install -y nodejs
     git clone https://code.03c8.net/KrakensLab/oasis
     git clone https://code.03c8.net/KrakensLab/oasis
     cd oasis
     cd oasis
-    npm -g install .
-    node .
+    npm install .
+    npm run start
 
 
 --------------
 --------------
 
 

File diff suppressed because it is too large
+ 4319 - 5486
package-lock.json


+ 16 - 14
package.json

@@ -10,13 +10,15 @@
   "author": "psy <epsylon@riseup.net>",
   "author": "psy <epsylon@riseup.net>",
   "main": "src/index.js",
   "main": "src/index.js",
   "bin": {
   "bin": {
-    "oasis": "node_modules/ssb-server/bin.js start && src/index.js"
+    "oasis": "npm run start"
   },
   },
   "scripts": {
   "scripts": {
     "dev": "nodemon --inspect src/index.js --debug --no-open",
     "dev": "nodemon --inspect src/index.js --debug --no-open",
     "fix": "common-good fix",
     "fix": "common-good fix",
-    "prestart": "git pull && npm install",
-    "start": "node src/index.js",
+    "prestart": "",
+    "start": "npm run start-server && npm run start-client",
+    "start-server": "node src/server.js &",
+    "start-client": "node src/index.js",
     "test": "tap --timeout 240 && common-good test",
     "test": "tap --timeout 240 && common-good test",
     "preversion": "npm test",
     "preversion": "npm test",
     "version": "mv docs/CHANGELOG.md ./ && changelog-version && mv CHANGELOG.md docs/ && git add docs/CHANGELOG.md"
     "version": "mv docs/CHANGELOG.md ./ && changelog-version && mv CHANGELOG.md docs/ && git add docs/CHANGELOG.md"
@@ -24,7 +26,7 @@
   "dependencies": {
   "dependencies": {
     "@fraction/base16-css": "^1.1.0",
     "@fraction/base16-css": "^1.1.0",
     "@koa/router": "^10.0.0",
     "@koa/router": "^10.0.0",
-    "debug": "^4.1.1",
+    "debug": "^4.3.1",
     "env-paths": "^2.2.0",
     "env-paths": "^2.2.0",
     "file-type": "^16.0.1",
     "file-type": "^16.0.1",
     "highlight.js": "^11.0.0",
     "highlight.js": "^11.0.0",
@@ -46,10 +48,9 @@
     "pull-paramap": "^1.2.2",
     "pull-paramap": "^1.2.2",
     "pull-sort": "^1.0.2",
     "pull-sort": "^1.0.2",
     "pull-stream": "^3.6.12",
     "pull-stream": "^3.6.12",
-    "request": "^2.88.2",
+    "request": "^2.88.1",
     "require-style": "^1.1.0",
     "require-style": "^1.1.0",
-    "secret-stack": "^6.3.0",
-    "sharp": "^0.28.0",
+    "secret-stack": "^6.3.1",
     "ssb-about": "^2.0.1",
     "ssb-about": "^2.0.1",
     "ssb-backlinks": "^2.1.1",
     "ssb-backlinks": "^2.1.1",
     "ssb-blobs": "^2.0.1",
     "ssb-blobs": "^2.0.1",
@@ -57,9 +58,9 @@
     "ssb-config": "^3.4.4",
     "ssb-config": "^3.4.4",
     "ssb-conn": "^6.0.3",
     "ssb-conn": "^6.0.3",
     "ssb-db": "^20.3.0",
     "ssb-db": "^20.3.0",
-    "ssb-ebt": "^7.0.1",
+    "ssb-ebt": "^9.1.2",
     "ssb-friends": "^4.4.7",
     "ssb-friends": "^4.4.7",
-    "ssb-invite": "^2.1.6",
+    "ssb-invite": "^3.0.1",
     "ssb-keys": "^8.0.0",
     "ssb-keys": "^8.0.0",
     "ssb-lan": "^1.0.0",
     "ssb-lan": "^1.0.0",
     "ssb-logging": "^1.0.0",
     "ssb-logging": "^1.0.0",
@@ -74,15 +75,17 @@
     "ssb-plugins": "^1.0.2",
     "ssb-plugins": "^1.0.2",
     "ssb-private1": "^1.0.1",
     "ssb-private1": "^1.0.1",
     "ssb-query": "^2.4.5",
     "ssb-query": "^2.4.5",
-    "ssb-ref": "^2.13.9",
+    "ssb-ref": "^2.16.0",
     "ssb-replicate": "^1.3.0",
     "ssb-replicate": "^1.3.0",
     "ssb-room": "^1.3.0",
     "ssb-room": "^1.3.0",
     "ssb-search": "^1.3.0",
     "ssb-search": "^1.3.0",
-    "ssb-server": "^15.3.0",
     "ssb-tangle": "^1.0.1",
     "ssb-tangle": "^1.0.1",
     "ssb-thread-schema": "^1.1.1",
     "ssb-thread-schema": "^1.1.1",
     "ssb-unix-socket": "^1.0.0",
     "ssb-unix-socket": "^1.0.0",
     "ssb-ws": "^6.2.3",
     "ssb-ws": "^6.2.3",
+    "ssb-gossip": "^1.1.1",
+    "ssb-server": "^15.3.0",
+    "ssb-tunnel": "^2.0.0",
     "yargs": "^17.0.0"
     "yargs": "^17.0.0"
   },
   },
   "devDependencies": {
   "devDependencies": {
@@ -109,15 +112,14 @@
     "tap": "^14.10.7"
     "tap": "^14.10.7"
   },
   },
   "optionalDependencies": {
   "optionalDependencies": {
-    "sharp": "^0.28.0"
+    "sharp": "^0.31.1"
   },
   },
   "bugs": {
   "bugs": {
     "url": "https://code.03c8.net/KrakensLab/snh-oasis/issues"
     "url": "https://code.03c8.net/KrakensLab/snh-oasis/issues"
   },
   },
   "homepage": "https://code.03c8.net/KrakensLab/snh-oasis",
   "homepage": "https://code.03c8.net/KrakensLab/snh-oasis",
   "directories": {
   "directories": {
-    "doc": "docs",
-    "test": "test"
+    "doc": "docs"
   },
   },
   "keywords": [],
   "keywords": [],
   "engines": {
   "engines": {

+ 1 - 1
src/assets/style.css

@@ -363,7 +363,7 @@ section {
   margin: var(--size-0) 0;
   margin: var(--size-0) 0;
   word-wrap: break-word;
   word-wrap: break-word;
   background: var(--bg);
   background: var(--bg);
-  width: 105%;
+  width: 100%;
   box-sizing: border-box;
   box-sizing: border-box;
 }
 }
 
 

+ 1 - 3
src/index.js

@@ -793,7 +793,6 @@ router
   .get("/mentions", async (ctx) => {
   .get("/mentions", async (ctx) => {
     const mentions = async () => {
     const mentions = async () => {
       const messages = await post.mentionsMe();
       const messages = await post.mentionsMe();
-
       return mentionsView({ messages });
       return mentionsView({ messages });
     };
     };
     ctx.body = await mentions();
     ctx.body = await mentions();
@@ -803,7 +802,6 @@ router
     const thread = async (message) => {
     const thread = async (message) => {
       const messages = await post.fromThread(message);
       const messages = await post.fromThread(message);
       debug("got %i messages", messages.length);
       debug("got %i messages", messages.length);
-
       return threadView({ messages });
       return threadView({ messages });
     };
     };
 
 
@@ -1023,7 +1021,7 @@ router
     const exec = util.promisify(require('node:child_process').exec);
     const exec = util.promisify(require('node:child_process').exec);
     async function updateTool() {
     async function updateTool() {
       const { stdout, stderr } = await exec('git reset --hard && git pull && npm install .');
       const { stdout, stderr } = await exec('git reset --hard && git pull && npm install .');
-      console.log("updating SNH-Oasis");
+      console.log("updating Oasis");
       console.log(stdout);
       console.log(stdout);
       console.log(stderr);
       console.log(stderr);
     }
     }

+ 0 - 3
src/models.js

@@ -76,7 +76,6 @@ module.exports = ({ cooler, isPublic }) => {
    */
    */
   const getAbout = async ({ key, feedId }) => {
   const getAbout = async ({ key, feedId }) => {
     const ssb = await cooler.open();
     const ssb = await cooler.open();
-
     const source = ssb.backlinks.read({
     const source = ssb.backlinks.read({
       reverse: true,
       reverse: true,
       query: [
       query: [
@@ -625,7 +624,6 @@ module.exports = ({ cooler, isPublic }) => {
     filter = null,
     filter = null,
   }) => {
   }) => {
     const options = configure({ query, index: "DTA" }, customOptions);
     const options = configure({ query, index: "DTA" }, customOptions);
-
     const source = ssb.backlinks.read(options);
     const source = ssb.backlinks.read(options);
     const basicSocialFilter = await socialFilter();
     const basicSocialFilter = await socialFilter();
 
 
@@ -1346,7 +1344,6 @@ module.exports = ({ cooler, isPublic }) => {
 
 
       const now = new Date();
       const now = new Date();
       const earliest = Number(now) - 1000 * 60 * 60 * 24 * periodDict[period];
       const earliest = Number(now) - 1000 * 60 * 60 * 24 * periodDict[period];
-
       const source = ssb.query.read(
       const source = ssb.query.read(
         configure({
         configure({
           query: [
           query: [

+ 42 - 0
src/server.js

@@ -0,0 +1,42 @@
+var Server = require('ssb-server')
+var config = require('ssb-config')
+var fs = require('fs')
+var path = require('path')
+
+// add required plugins
+Server
+  .use(require('ssb-master'))
+  .use(require('ssb-db'))
+  .use(require('ssb-replicate'))
+  .use(require('ssb-backlinks'))
+  .use(require('ssb-conn'))
+  .use(require('ssb-gossip'))
+  .use(require('ssb-search'))
+  .use(require('ssb-tangle'))
+  .use(require('ssb-query'))
+  .use(require('ssb-friends'))
+  .use(require('ssb-blobs'))
+  .use(require('ssb-about'))
+  .use(require('ssb-ebt'))
+  .use(require('ssb-invite'))
+  .use(require('ssb-lan'))
+  .use(require('ssb-logging'))
+  .use(require('ssb-meme'))
+  .use(require('ssb-no-auth'))
+  .use(require('ssb-onion'))
+  .use(require('ssb-ooo'))
+  .use(require('ssb-plugins'))
+  .use(require('ssb-private1'))
+  .use(require('ssb-unix-socket'))
+  .use(require('ssb-ws'))
+  .use(require('ssb-tunnel'))
+
+// load config into ssb
+var server = Server(config)
+
+// generate manifest
+var manifest = server.getManifest()
+fs.writeFileSync(
+  path.join(config.path, 'manifest.json'), // ~/.ssb/manifest.json
+  JSON.stringify(manifest)
+)

+ 3 - 33
src/ssb/index.js

@@ -7,7 +7,6 @@
 const { promisify } = require("util");
 const { promisify } = require("util");
 const ssbClient = require("ssb-client");
 const ssbClient = require("ssb-client");
 const ssbConfig = require("ssb-config");
 const ssbConfig = require("ssb-config");
-const ssbTangle = require("ssb-tangle");
 const ssbKeys = require("ssb-keys");
 const ssbKeys = require("ssb-keys");
 const debug = require("debug")("oasis");
 const debug = require("debug")("oasis");
 const path = require("path");
 const path = require("path");
@@ -18,7 +17,6 @@ const os = require("os");
 const flotilla = require("./flotilla");
 const flotilla = require("./flotilla");
 
 
 // Use temporary path if we're running a test.
 // Use temporary path if we're running a test.
-// TODO: Refactor away 'OASIS_TEST' variable.
 if (process.env.OASIS_TEST) {
 if (process.env.OASIS_TEST) {
   ssbConfig.path = fs.mkdtempSync(path.join(os.tmpdir(), "oasis-"));
   ssbConfig.path = fs.mkdtempSync(path.join(os.tmpdir(), "oasis-"));
   ssbConfig.keys = ssbKeys.generate();
   ssbConfig.keys = ssbKeys.generate();
@@ -45,18 +43,8 @@ const log = (formatter, ...args) => {
  */
  */
 const connect = (options) =>
 const connect = (options) =>
   new Promise((resolve, reject) => {
   new Promise((resolve, reject) => {
-    const onSuccess = (api) => {
-      if (api.tangle === undefined) {
-        // HACK: SSB-Tangle isn't available in Patchwork, but we want that
-        // compatibility. This code automatically injects SSB-Tangle into our
-        // stack so that we don't get weird errors when using Patchwork.
-        api.tangle = ssbTangle.init(api);
-
-        // MuxRPC supports promises but the raw plugin does not.
-        api.tangle.branch = promisify(api.tangle.branch);
-      }
-
-      resolve(api);
+    const onSuccess = (ssb) => {
+      resolve(ssb);
     };
     };
 
 
     ssbClient(process.env.OASIS_TEST ? ssbConfig.keys : null, options)
     ssbClient(process.env.OASIS_TEST ? ssbConfig.keys : null, options)
@@ -82,7 +70,6 @@ const attemptConnection = () =>
           })
           })
         )
         )
       : connect({ remote });
       : connect({ remote });
-
     originalConnect
     originalConnect
       .then((ssb) => {
       .then((ssb) => {
         debug("Connected to existing Scuttlebutt service over Unix socket");
         debug("Connected to existing Scuttlebutt service over Unix socket");
@@ -115,19 +102,13 @@ let pendingConnection = null;
 const ensureConnection = (customConfig) => {
 const ensureConnection = (customConfig) => {
   if (pendingConnection === null) {
   if (pendingConnection === null) {
     pendingConnection = new Promise((resolve) => {
     pendingConnection = new Promise((resolve) => {
+      setTimeout(() => {
       attemptConnection()
       attemptConnection()
         .then((ssb) => {
         .then((ssb) => {
           resolve(ssb);
           resolve(ssb);
         })
         })
         .catch(() => {
         .catch(() => {
-          debug("Connection attempts to existing Scuttlebutt services failed");
-          log("Starting Scuttlebutt service");
-
-          // Adjust with `customConfig`, which declares further preferences.
           serverHandle = flotilla(customConfig);
           serverHandle = flotilla(customConfig);
-
-          // Give the server a moment to start. This is a race condition. :/
-          setTimeout(() => {
             attemptConnection()
             attemptConnection()
               .then(resolve)
               .then(resolve)
               .catch((e) => {
               .catch((e) => {
@@ -147,19 +128,11 @@ const ensureConnection = (customConfig) => {
 module.exports = ({ offline }) => {
 module.exports = ({ offline }) => {
   if (offline) {
   if (offline) {
     log("Offline mode activated - not connecting to scuttlebutt peers or pubs");
     log("Offline mode activated - not connecting to scuttlebutt peers or pubs");
-    log(
-      "WARNING: Oasis can connect to the internet through your other SSB apps if they're running."
-    );
   }
   }
 
 
   // Make a copy of `ssbConfig` to avoid mutating.
   // Make a copy of `ssbConfig` to avoid mutating.
   const customConfig = JSON.parse(JSON.stringify(ssbConfig));
   const customConfig = JSON.parse(JSON.stringify(ssbConfig));
 
 
-  // This is unnecessary when https://github.com/ssbc/ssb-config/pull/72 is merged
-  customConfig.connections.incoming.unix = [
-    { scope: "device", transform: "noauth" },
-  ];
-
   // Only change the config if `--offline` is true.
   // Only change the config if `--offline` is true.
   if (offline === true) {
   if (offline === true) {
     lodash.set(customConfig, "conn.autostart", false);
     lodash.set(customConfig, "conn.autostart", false);
@@ -212,9 +185,6 @@ module.exports = ({ offline }) => {
     },
     },
   };
   };
 
 
-  // Important: This ensures that we have an SSB connection as soon as Oasis
-  // starts. If we don't do this, then we don't even attempt an SSB connection
-  // until we receive our first HTTP request.
   cooler.open();
   cooler.open();
 
 
   return cooler;
   return cooler;

+ 4 - 4
src/views/i18n.js

@@ -225,17 +225,17 @@ const i18n = {
     topics: "Temáticas",
     topics: "Temáticas",
     topicsDescription: [
     topicsDescription: [
       strong("Temáticas"),
       strong("Temáticas"),
-      " tuyas y de habitantes que apoyas, ordenadas por las más recientes. Selecciona la hora de una publicación para leer el hilo completo.",
+      " tuyas y de habitantes que apoyas, ordenadas por las más recientes. Selecciona la hora de publicación para leer el hilo completo.",
     ],
     ],
     summaries: "Resumen",
     summaries: "Resumen",
     summariesDescription: [
     summariesDescription: [
       strong("Temáticas y algunos comentarios"),
       strong("Temáticas y algunos comentarios"),
-      " tuyos y de habitantes que apoyas, ordenado por lo más reciente. Selecciona la hora de una publicación para leer el hilo completo.",
+      " tuyos y de habitantes que apoyas, ordenado por lo más reciente. Selecciona la hora de publicación para leer el hilo completo.",
     ],
     ],
     threads: "Hilos",
     threads: "Hilos",
     threadsDescription: [
     threadsDescription: [
       strong("Posts que tienen comentarios"),
       strong("Posts que tienen comentarios"),
-      " de habitantes que apoyas y de tu red extendida, ordenados por los más recientes. Selecciona la hora de una publicación para leer el hilo completo.",
+      " de habitantes que apoyas y de tu red extendida, ordenados por los más recientes. Selecciona la hora de publicación para leer el hilo completo.",
     ],
     ],
     manualMode: "Modo manual",
     manualMode: "Modo manual",
     mentions: "Menciones",
     mentions: "Menciones",
@@ -248,7 +248,7 @@ const i18n = {
     privateDescription: [
     privateDescription: [
       "Los comentarios más recientes de ",
       "Los comentarios más recientes de ",
       strong("hilos privados que te incluyen"),
       strong("hilos privados que te incluyen"),
-      ". Las publicaciones privadas están cifradas para ti, y contienen un máximo de 7 destinatarios. No se podrán añadir nuevos destinarios después de que empieze el hilo. Selecciona la hora de una publicación para leer el hilo completo.",
+      ". Las publicaciones privadas están cifradas para ti, y contienen un máximo de 7 destinatarios. No se podrán añadir nuevos destinarios después de que empieze el hilo. Selecciona la hora de publicación para leer el hilo completo.",
     ],
     ],
     // post actions
     // post actions
     comment: "Comentar",
     comment: "Comentar",

+ 28 - 14
src/views/index.js

@@ -5,6 +5,7 @@ const envPaths = require("env-paths");
 const fs = require("fs");
 const fs = require("fs");
 
 
 const homedir = require('os').homedir();
 const homedir = require('os').homedir();
+
 const supportingPath = path.join(homedir, ".ssb/flume/contacts2.json");
 const supportingPath = path.join(homedir, ".ssb/flume/contacts2.json");
 const offsetPath = path.join(homedir, ".ssb/flume/log.offset");
 const offsetPath = path.join(homedir, ".ssb/flume/log.offset");
 
 
@@ -138,13 +139,13 @@ const template = (titlePrefix, ...elements) => {
       nav(
       nav(
         ul(
         ul(
           //navLink({ href: "/imageSearch", emoji: "✧", text: i18n.imageSearch }),
           //navLink({ href: "/imageSearch", emoji: "✧", text: i18n.imageSearch }),
-          navLink({ href: "/public/latest/extended", emoji: "∞", text: i18n.extended }),
-          navLink({ href: "/public/latest/threads", emoji: "♺", text: i18n.threads }),
           navLink({ href: "/public/popular/day", emoji: "⌘", text: i18n.popular }),
           navLink({ href: "/public/popular/day", emoji: "⌘", text: i18n.popular }),
+          navLink({ href: "/mentions", emoji: "✺", text: i18n.mentions }),
           navLink({ href: "/public/latest", emoji: "☄", text: i18n.latest }),
           navLink({ href: "/public/latest", emoji: "☄", text: i18n.latest }),
-          navLink({ href: "/public/latest/topics", emoji: "ϟ", text: i18n.topics }),
           navLink({ href: "/public/latest/summaries", emoji: "※", text: i18n.summaries }),
           navLink({ href: "/public/latest/summaries", emoji: "※", text: i18n.summaries }),
-          navLink({ href: "/mentions", emoji: "✺", text: i18n.mentions }),
+          navLink({ href: "/public/latest/topics", emoji: "ϟ", text: i18n.topics }),
+          navLink({ href: "/public/latest/extended", emoji: "∞", text: i18n.extended }),
+          navLink({ href: "/public/latest/threads", emoji: "♺", text: i18n.threads }),
         )
         )
       ),
       ),
       main({ id: "content" }, elements),
       main({ id: "content" }, elements),
@@ -432,8 +433,8 @@ const post = ({ msg, aside = false }) => {
           { class: "content" },
           { class: "content" },
           pre({
           pre({
             innerHTML: highlightJs.highlight(
             innerHTML: highlightJs.highlight(
-              "json",
-              JSON.stringify(msg, null, 2)
+              JSON.stringify(msg, null, 2),
+              {language: "json", ignoreIllegals: true}
             ).value,
             ).value,
           })
           })
         )
         )
@@ -579,7 +580,7 @@ exports.authorView = ({
   relationship,
   relationship,
 }) => {
 }) => {
   const mention = `[@${name}](${feedId})`;
   const mention = `[@${name}](${feedId})`;
-  const markdownMention = highlightJs.highlight("markdown", mention).value;
+  const markdownMention = highlightJs.highlight(mention, {language: "markdown", ignoreIllegals: true}).value;
 
 
   const contactForms = [];
   const contactForms = [];
 
 
@@ -1058,11 +1059,17 @@ exports.peersView = async ({ peers }) => {
    });
    });
 
 
   const supportedList = (supporting)
   const supportedList = (supporting)
-    var supporting = JSON.parse(fs.readFileSync(supportingPath, "utf8")).value;
+  try{
+    var supporting = JSON.parse(fs.readFileSync(supportingPath, {encoding:'utf8', flag:'r'})).value;
+    var supportingValue = "true";
+  }catch{
+    var supportingValue = "false";
+  }
+  if (supportingValue === "true") {
     var arr = [];
     var arr = [];
     var keys = Object.keys(supporting);
     var keys = Object.keys(supporting);
-      var data = Object.entries(supporting[keys[0]]);
-       Object.entries(data).forEach(([key, value]) => {
+        var data = Object.entries(supporting[keys[0]]);
+        Object.entries(data).forEach(([key, value]) => {
          if (value[1]===1){
          if (value[1]===1){
           var supported = (value[0])
           var supported = (value[0])
            if (!arr.includes(supported)) {
            if (!arr.includes(supported)) {
@@ -1077,10 +1084,12 @@ exports.peersView = async ({ peers }) => {
            }
            }
          }
          }
       });
       });
+  }else{
+    var arr = [];
+  }
   var supports = arr;
   var supports = arr;
 
 
-  const blockedList = (supporting)
-    var supporting = JSON.parse(fs.readFileSync(supportingPath, "utf8")).value;
+  if (supportingValue === "true") {
     var arr = [];
     var arr = [];
     var keys = Object.keys(supporting);
     var keys = Object.keys(supporting);
       var data = Object.entries(supporting[keys[0]]);
       var data = Object.entries(supporting[keys[0]]);
@@ -1099,10 +1108,12 @@ exports.peersView = async ({ peers }) => {
            }
            }
          }
          }
       });
       });
+  }else{
+    var arr = [];
+  }
   var blocks = arr;
   var blocks = arr;
 
 
-  const recommendedList = (supporting)
-    var supporting = JSON.parse(fs.readFileSync(supportingPath, "utf8")).value;
+  if (supportingValue === "true") {
     var arr = [];
     var arr = [];
     var keys = Object.keys(supporting);
     var keys = Object.keys(supporting);
       var data = Object.entries(supporting[keys[0]]);
       var data = Object.entries(supporting[keys[0]]);
@@ -1121,6 +1132,9 @@ exports.peersView = async ({ peers }) => {
            }
            }
          }
          }
       });
       });
+  }else{
+    var arr = [];
+  }
   var recommends = arr;
   var recommends = arr;
 
 
  return template(
  return template(