Add get friends, get people, debug view, and user 3

This commit is contained in:
Rogerio Chaves 2020-04-05 13:29:05 +02:00
parent 3653424dd8
commit 2427cc2d16
No known key found for this signature in database
GPG Key ID: E6AF5440509B1D94
7 changed files with 207 additions and 59 deletions

View File

@ -2,11 +2,11 @@ const express = require("express");
const app = express();
const port = process.env.EXPRESS_PORT || 3000;
const bodyParser = require("body-parser");
const pull = require("pull-stream");
const Client = require("ssb-client");
const ssbKeys = require("ssb-keys");
const ssbConfig = require("./ssb-config");
const { promisify, asyncRouter } = require("./utils");
const queries = require("./queries");
let ssbServer;
let profile;
@ -37,7 +37,7 @@ app.use(express.static("public"));
const router = asyncRouter(app);
router.get("/", (_req, res) => {
router.get("/", async (_req, res) => {
if (!ssbServer) {
setTimeout(() => {
res.redirect("/");
@ -49,56 +49,12 @@ router.get("/", (_req, res) => {
res.redirect("/about");
}
const getAuthorName = (data, callback) => {
let promises = [];
const authorNamePromise = promisify(ssbServer.about.latestValue, {
key: "name",
dest: data.value.author,
});
promises.push(authorNamePromise);
if (data.value.content.type == "contact") {
const contactNamePromise = promisify(ssbServer.about.latestValue, {
key: "name",
dest: data.value.content.contact,
});
promises.push(contactNamePromise);
}
Promise.all(promises)
.then(([authorName, contactName]) => {
data.value.authorName = authorName;
if (contactName) {
data.value.content.contactName = contactName;
}
callback(null, data);
})
.catch((err) => callback(err, null));
};
pull(
ssbServer.query.read({
reverse: true,
query: [
{
$filter: {
value: {
content: { type: { $in: ["post", "contact"] } },
},
},
},
],
limit: 500,
}),
pull.asyncMap(getAuthorName),
pull.collect((_err, msgs) => {
const entries = msgs.map((x) => x.value);
res.render("index", { entries, profile });
})
);
const [posts, people, friends] = await Promise.all([
queries.getPosts(ssbServer),
queries.getPeople(ssbServer),
queries.getFriends(profile, ssbServer),
]);
res.render("index", { profile, posts, people, friends });
});
router.post("/publish", async (req, res) => {
@ -141,6 +97,12 @@ router.post("/about", async (req, res) => {
res.redirect("/");
});
router.get("/debug", async (_req, res) => {
const entries = await queries.getAllEntries(ssbServer);
res.render("debug", { profile, entries });
});
const expressServer = app.listen(port, () =>
console.log(`Example app listening at http://localhost:${port}`)
);

144
app/lib/queries.js Normal file
View File

@ -0,0 +1,144 @@
const { promisify } = require("./utils");
const pull = require("pull-stream");
const mapAuthorName = (ssbServer) => (data, callback) => {
let promises = [];
const authorNamePromise = promisify(ssbServer.about.latestValue, {
key: "name",
dest: data.value.author,
});
promises.push(authorNamePromise);
if (data.value.content.type == "contact") {
const contactNamePromise = promisify(ssbServer.about.latestValue, {
key: "name",
dest: data.value.content.contact,
});
promises.push(contactNamePromise);
}
return Promise.all(promises)
.then(([authorName, contactName]) => {
data.value.authorName = authorName;
if (contactName) {
data.value.content.contactName = contactName;
}
callback(null, data);
})
.catch((err) => callback(err, null));
};
const getPosts = (ssbServer) =>
new Promise((resolve, reject) => {
pull(
ssbServer.query.read({
reverse: true,
query: [
{
$filter: {
value: {
content: { type: "post" },
},
},
},
],
limit: 500,
}),
pull.asyncMap(mapAuthorName(ssbServer)),
pull.collect((err, msgs) => {
const entries = msgs.map((x) => x.value);
if (err) return reject(err);
return resolve(entries);
})
);
});
const getPeople = (ssbServer) =>
new Promise((resolve, reject) => {
pull(
ssbServer.query.read({
reverse: true,
query: [
{
$filter: {
value: {
content: {
type: "about",
name: { $is: "string" },
},
},
},
},
],
limit: 500,
}),
pull.collect((err, msgs) => {
let people = {};
for (let person of msgs) {
const author = person.value.author;
if (author == person.value.content.about && !people[author]) {
people[author] = person.value;
}
}
if (err) return reject(err);
return resolve(Object.values(people));
})
);
});
const getFriends = (profile, ssbServer) =>
new Promise((resolve, reject) => {
pull(
ssbServer.query.read({
reverse: true,
query: [
{
$filter: {
value: {
author: profile.id,
content: {
type: "contact",
},
},
},
},
],
limit: 500,
}),
pull.asyncMap(mapAuthorName(ssbServer)),
pull.collect((err, msgs) => {
const entries = msgs.map((x) => x.value);
if (err) return reject(err);
return resolve(entries);
})
);
});
const getAllEntries = (ssbServer) =>
new Promise((resolve, reject) => {
pull(
ssbServer.query.read({
reverse: true,
limit: 100,
}),
pull.collect((err, msgs) => {
const entries = msgs.map((x) => x.value);
if (err) return reject(err);
return resolve(entries);
})
);
});
module.exports = {
mapAuthorName,
getPosts,
getPeople,
getFriends,
getAllEntries,
};

View File

@ -6,7 +6,8 @@
"scripts": {
"start": "electron .",
"start:user-2": "SSB_PORT=8009 EXPRESS_PORT=3001 CONFIG_FOLDER=social-user2 electron .",
"clear": "rm -rf ~/.social; rm -rf ~/.social-user2"
"start:user-3": "SSB_PORT=8010 EXPRESS_PORT=3002 CONFIG_FOLDER=social-user3 electron .",
"clear": "rm -rf ~/.social; rm -rf ~/.social-user2; rm -rf ~/.social-user3"
},
"author": "",
"license": "ISC",

View File

@ -1,2 +1,3 @@
</main>
</body>
</html>

View File

@ -4,6 +4,23 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Social</title>
<style>
body {
font-family: sans-serif;
margin: 0;
}
header {
padding: 20px 10px;
border-bottom: 1px solid #666;
}
header a {
display: inline-block;
padding: 0 10px;
}
main {
padding: 10px;
}
</style>
</head>
<body>
<% if (profile.name) { %>
@ -15,6 +32,8 @@
<a href="/">Home</a>
<a href="/about">About me</a>
<a href="/pubs">Pubs</a>
<a href="/debug">Debug</a>
</nav>
</header>
<% } %>
<main>

8
app/views/debug.ejs Normal file
View File

@ -0,0 +1,8 @@
<%- include('_header') %>
<% entries.map(entry => { %>
<code style="width: 80%; word-wrap: break-word;"><%= JSON.stringify(entry) %></code>
<hr />
<% }) %>
<%- include('_footer') %>

View File

@ -5,12 +5,25 @@
<input type="submit" value="Send" />
</form>
<% entries.map(entry => { %>
<% if (entry.content.type == "post") { %>
<div><%= entry.authorName %>: <%= entry.content.text %></div>
<% } else if (entry.content.type == "contact") { %>
<div><%= entry.authorName %> followed <%= entry.content.contactName %></div>
<% } %>
<% posts.map(entry => { %>
<div><%= entry.authorName %>: <%= entry.content.text %></div>
<hr />
<% }) %>
<h2>All People</h2>
<ul>
<% people.map(person => { %>
<li><%= person.content.name %> (<%= person.author.slice(0, 8) %>)</li>
<% }) %>
</ul>
<h2>Friends</h2>
<ul>
<% friends.map(friend => { %>
<li><%= friend.content.contactName %> (<%= friend.content.contact.slice(0, 8) %>)</li>
<% }) %>
</ul>
<%- include('_footer') %>