commit
b44827f00d
6 changed files with 154 additions and 15 deletions
|
|
@ -41,6 +41,7 @@
|
|||
"lodash": "^4.17.15",
|
||||
"method-override": "^2.3.7",
|
||||
"promise": "^8.0.1",
|
||||
"ramda": "^0.27.0",
|
||||
"request": "^2.87.0",
|
||||
"request-promise": "^4.2.2",
|
||||
"response-time": "^2.3.2",
|
||||
|
|
@ -61,6 +62,7 @@
|
|||
"@types/jest": "^24.0.18",
|
||||
"@types/jsonwebtoken": "^8.3.7",
|
||||
"@types/lodash": "^4.14.141",
|
||||
"@types/ramda": "types/npm-ramda#dist",
|
||||
"@types/socket.io": "^2.1.4",
|
||||
"@types/uuid": "^3.4.5",
|
||||
"babel-eslint": "^10.0.3",
|
||||
|
|
|
|||
79
services/gunDB/contact-api/getters/feed.js
Normal file
79
services/gunDB/contact-api/getters/feed.js
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* @format
|
||||
*/
|
||||
const Common = require('shock-common')
|
||||
const isFinite = require('lodash/isFinite')
|
||||
const shuffle = require('lodash/shuffle')
|
||||
const R = require('ramda')
|
||||
|
||||
const Follows = require('./follows')
|
||||
const Wall = require('./wall')
|
||||
|
||||
/**
|
||||
* @param {number} numberOfPublicKeyGroups
|
||||
* @param {number} pageRequested
|
||||
* @returns {[ number , number ]}
|
||||
*/
|
||||
const calculateFeedPage = (numberOfPublicKeyGroups, pageRequested) => {
|
||||
// thanks to sebassdc
|
||||
|
||||
return [
|
||||
(pageRequested - 1) % numberOfPublicKeyGroups,
|
||||
Math.ceil(pageRequested / numberOfPublicKeyGroups)
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} page
|
||||
* @throws {TypeError}
|
||||
* @throws {RangeError}
|
||||
* @returns {Promise<Common.SchemaTypes.Post[]>}
|
||||
*/
|
||||
const getFeedPage = async page => {
|
||||
if (!isFinite(page)) {
|
||||
throw new TypeError(`Please provide an actual number for [page]`)
|
||||
}
|
||||
|
||||
if (page <= 0) {
|
||||
throw new RangeError(`Please provide only positive numbers for [page]`)
|
||||
}
|
||||
|
||||
const subbedPublicKeys = Object.values(await Follows.currentFollows()).map(
|
||||
f => f.user
|
||||
)
|
||||
|
||||
if (subbedPublicKeys.length === 0) {
|
||||
return []
|
||||
}
|
||||
|
||||
// say there are 20 public keys total
|
||||
// page 1: page 1 from first 10 public keys
|
||||
// page 2: page 1 from second 10 public keys
|
||||
// page 3: page 2 from first 10 public keys
|
||||
// page 4: page 2 from first 10 public keys
|
||||
// etc
|
||||
// thanks to sebassdc (github)
|
||||
|
||||
const pagedPublicKeys = R.splitEvery(10, shuffle(subbedPublicKeys))
|
||||
|
||||
const [publicKeyGroupIdx, pageToRequest] = calculateFeedPage(
|
||||
pagedPublicKeys.length,
|
||||
page
|
||||
)
|
||||
|
||||
const publicKeys = pagedPublicKeys[publicKeyGroupIdx]
|
||||
|
||||
const fetchedPages = await Promise.all(
|
||||
publicKeys.map(pk => Wall.getWallPage(pageToRequest, pk))
|
||||
)
|
||||
|
||||
const fetchedPostsGroups = fetchedPages.map(wp => Object.values(wp.posts))
|
||||
const fetchedPosts = R.flatten(fetchedPostsGroups)
|
||||
const sortered = R.sort((a, b) => b.date - a.date, fetchedPosts)
|
||||
|
||||
return sortered
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getFeedPage
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ const Key = require('../key')
|
|||
const Utils = require('../utils')
|
||||
|
||||
const Wall = require('./wall')
|
||||
const Feed = require('./feed')
|
||||
const User = require('./user')
|
||||
|
||||
/**
|
||||
|
|
@ -96,4 +97,5 @@ module.exports.Follows = require('./follows')
|
|||
module.exports.getWallPage = Wall.getWallPage
|
||||
module.exports.getWallTotalPages = Wall.getWallTotalPages
|
||||
|
||||
module.exports.getUser = User.getAnUser
|
||||
module.exports.getFeedPage = Feed.getFeedPage
|
||||
module.exports.getAnUser = User.getAnUser
|
||||
|
|
|
|||
|
|
@ -9,15 +9,19 @@ const Key = require('../key')
|
|||
const Wall = require('./user')
|
||||
|
||||
/**
|
||||
* @param {string=} publicKey
|
||||
* @returns {Promise<number>}
|
||||
*/
|
||||
const getWallTotalPages = async () => {
|
||||
const getWallTotalPages = async publicKey => {
|
||||
const totalPages = await Utils.tryAndWait(
|
||||
(_, user) =>
|
||||
user
|
||||
(gun, u) => {
|
||||
const user = publicKey ? gun.get(`~${publicKey}`) : u
|
||||
|
||||
return user
|
||||
.get(Key.WALL)
|
||||
.get(Key.NUM_OF_PAGES)
|
||||
.then(),
|
||||
.then()
|
||||
},
|
||||
v => typeof v !== 'number'
|
||||
)
|
||||
|
||||
|
|
@ -26,12 +30,13 @@ const getWallTotalPages = async () => {
|
|||
|
||||
/**
|
||||
* @param {number} page
|
||||
* @param {string=} publicKey
|
||||
* @throws {TypeError}
|
||||
* @throws {RangeError}
|
||||
* @returns {Promise<Common.SchemaTypes.WallPage>}
|
||||
*/
|
||||
const getWallPage = async page => {
|
||||
const totalPages = await getWallTotalPages()
|
||||
const getWallPage = async (page, publicKey) => {
|
||||
const totalPages = await getWallTotalPages(publicKey)
|
||||
|
||||
if (page === 0 || totalPages === 0) {
|
||||
return {
|
||||
|
|
@ -50,15 +55,18 @@ const getWallPage = async page => {
|
|||
* @type {Common.SchemaTypes.WallPage}
|
||||
*/
|
||||
const thePage = await Utils.tryAndWait(
|
||||
(_, user) =>
|
||||
new Promise(res => {
|
||||
(g, u) => {
|
||||
const user = publicKey ? g.get(`~${publicKey}`) : u
|
||||
|
||||
return new Promise(res => {
|
||||
user
|
||||
.get(Key.WALL)
|
||||
.get(Key.PAGES)
|
||||
.get(actualPageIdx.toString())
|
||||
// @ts-ignore
|
||||
.load(res)
|
||||
}),
|
||||
})
|
||||
},
|
||||
maybePage => {
|
||||
if (typeof maybePage !== 'object' || maybePage === null) {
|
||||
return true
|
||||
|
|
@ -97,9 +105,13 @@ const getWallPage = async page => {
|
|||
// delete unsuccessful writes
|
||||
if (post === null) {
|
||||
delete clean.posts[key]
|
||||
clean.count--
|
||||
} else {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
post.author = await Wall.getMyUser()
|
||||
post.author = publicKey
|
||||
? // eslint-disable-next-line no-await-in-loop
|
||||
await Wall.getAnUser(publicKey)
|
||||
: // eslint-disable-next-line no-await-in-loop
|
||||
await Wall.getMyUser()
|
||||
post.id = key
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1842,9 +1842,10 @@ module.exports = async (
|
|||
})
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
app.get(`/api/gun/wall`, async (req, res) => {
|
||||
app.get(`/api/gun/wall/:publicKey?`, async (req, res) => {
|
||||
try {
|
||||
const { page } = req.query;
|
||||
const {publicKey} = req.params
|
||||
|
||||
const pageNum = Number(page)
|
||||
|
||||
|
|
@ -1855,8 +1856,8 @@ module.exports = async (
|
|||
})
|
||||
}
|
||||
|
||||
const totalPages = await GunGetters.getWallTotalPages()
|
||||
const fetchedPage = await GunGetters.getWallPage(pageNum)
|
||||
const totalPages = await GunGetters.getWallTotalPages(publicKey)
|
||||
const fetchedPage = await GunGetters.getWallPage(pageNum, publicKey)
|
||||
|
||||
return res.status(200).json({
|
||||
...fetchedPage,
|
||||
|
|
@ -1969,6 +1970,40 @@ module.exports = async (
|
|||
ap.put(`/api/gun/follows/:publicKey`,apiGunFollowsPut)
|
||||
ap.delete(`/api/gun/follows/:publicKey`, apiGunFollowsDelete)
|
||||
|
||||
/**
|
||||
* @type {RequestHandler<{}>}
|
||||
*/
|
||||
const apiGunFeedGet = async (req, res) => {
|
||||
try {
|
||||
const { page: pageStr } = req.query;
|
||||
const page = Number(pageStr)
|
||||
|
||||
if (!isARealUsableNumber(page)) {
|
||||
return res.status(400).json({
|
||||
field: 'page',
|
||||
errorMessage: 'page must be a number'
|
||||
})
|
||||
}
|
||||
|
||||
if (page < 1) {
|
||||
return res.status(400).json({
|
||||
field: page,
|
||||
errorMessage: 'page must be a positive number'
|
||||
})
|
||||
}
|
||||
|
||||
return res.status(200).json({
|
||||
posts: await GunGetters.getFeedPage(page)
|
||||
})
|
||||
} catch (err) {
|
||||
return res.status(500).json({
|
||||
errorMessage: err.message || 'Unknown error inside /api/gun/follows/'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
ap.get(`/api/gun/feed`, apiGunFeedGet)
|
||||
|
||||
/**
|
||||
* Return app so that it can be used by express.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -633,6 +633,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
|
||||
integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
|
||||
|
||||
"@types/ramda@types/npm-ramda#dist":
|
||||
version "0.25.0"
|
||||
resolved "https://codeload.github.com/types/npm-ramda/tar.gz/9529aa3c8ff70ff84afcbc0be83443c00f30ea90"
|
||||
|
||||
"@types/range-parser@*":
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
|
||||
|
|
@ -5388,6 +5392,11 @@ ramda@^0.26.1:
|
|||
resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.26.1.tgz#8d41351eb8111c55353617fc3bbffad8e4d35d06"
|
||||
integrity sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ==
|
||||
|
||||
ramda@^0.27.0:
|
||||
version "0.27.0"
|
||||
resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.0.tgz#915dc29865c0800bf3f69b8fd6c279898b59de43"
|
||||
integrity sha512-pVzZdDpWwWqEVVLshWUHjNwuVP7SfcmPraYuqocJp1yo2U1R7P+5QAfDhdItkuoGqIBnBYrtPp7rEPqDn9HlZA==
|
||||
|
||||
random-bytes@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue