Merge pull request #76 from shocknet/follows-final

Follows final
This commit is contained in:
Daniel Lugo 2020-06-16 11:54:57 -04:00 committed by GitHub
commit 799f8e45e3
9 changed files with 318 additions and 39 deletions

View file

@ -78,9 +78,12 @@
"typescript": "^3.6.3"
},
"lint-staged": {
"*.{js,ts}": [
"*.js": [
"prettier --check",
"eslint"
],
"*.ts": [
"prettier --check"
]
},
"husky": {

View file

@ -38,6 +38,9 @@ export interface Soul {
export type OpenListenerData = Primitive | null | OpenListenerDataObj
export type OpenListener = (data: OpenListenerData, key: string) => void
export type LoadListenerData = OpenListenerData
export type LoadListener = (data: LoadListenerData, key: string) => void
export interface GUNNodeBase {
_: Soul
@ -48,6 +51,8 @@ export interface GUNNodeBase {
open(this: GUNNode, cb?: OpenListener): GUNNode
load(this: GUNNode, cb?: LoadListener): GUNNode
off(): void
user(): UserGUNNode
user(epub: string): GUNNode

View file

@ -1156,7 +1156,7 @@ const saveSeedBackup = async (mnemonicPhrase, user, SEA) => {
return new Promise((res, rej) => {
user.get(Key.SEED_BACKUP).put(encryptedSeed, ack => {
if (ack.err) {
rej(ack.err)
rej(new Error(ack.err))
} else {
res()
}
@ -1179,7 +1179,7 @@ const saveChannelsBackup = async (backups, user, SEA) => {
return new Promise((res, rej) => {
user.get(Key.CHANNELS_BACKUP).put(encryptBackups, ack => {
if (ack.err) {
rej(ack.err)
rej(new Error(ack.err))
} else {
res()
}
@ -1218,6 +1218,54 @@ const setLastSeenApp = () =>
})
})
/**
* @param {string} publicKey
* @param {boolean} isPrivate Will overwrite previous private status.
* @returns {Promise<string>}
*/
const follow = (publicKey, isPrivate) => {
/** @type {import('shock-common').Schema.Follow} */
const newFollow = {
private: isPrivate,
status: 'ok',
user: publicKey
}
return new Promise((res, rej) => {
require('../Mediator')
.getUser()
.get(Key.FOLLOWS)
.get(publicKey)
// @ts-ignore
.put(newFollow, ack => {
if (ack.err) {
rej(new Error(ack.err))
} else {
res()
}
})
})
}
/**
* @param {string} publicKey
* @returns {Promise<void>}
*/
const unfollow = publicKey =>
new Promise((res, rej) => {
require('../Mediator')
.getUser()
.get(Key.FOLLOWS)
.get(publicKey)
.put(null, ack => {
if (ack.err) {
rej(new Error(ack.err))
} else {
res()
}
})
})
module.exports = {
__createOutgoingFeed,
acceptRequest,
@ -1236,5 +1284,7 @@ module.exports = {
saveSeedBackup,
saveChannelsBackup,
disconnect,
setLastSeenApp
setLastSeenApp,
follow,
unfollow
}

View file

@ -1,29 +0,0 @@
const Key = require('./key')
const Utils = require('./utils')
/**
* @param {string} pub
* @returns {Promise<string>}
*/
exports.currentOrderAddress = async (pub) => {
const currAddr = await Utils.tryAndWait((gun) => gun.user(pub).get(Key.CURRENT_ORDER_ADDRESS).then())
if (typeof currAddr !== 'string') {
throw new TypeError('Expected user.currentOrderAddress to be an string')
}
return currAddr
}
/**
* @param {string} pub
* @returns {Promise<string|null>}
*/
exports.userToIncomingID = async (pub) => {
const incomingID = await require('../Mediator').getUser().get(Key.USER_TO_INCOMING).get(pub).then()
if (typeof incomingID === 'string') return incomingID
return null
}

View file

@ -0,0 +1,50 @@
const Common = require('shock-common')
const Logger = require('winston')
const Key = require('../key')
/**
* @typedef {Common.Schema.Follow} Follow
*/
/**
* @returns {Promise<Record<string, Common.Schema.Follow>>}
*/
exports.currentFollows = () => {
const user = require('../../Mediator').getUser()
return new Promise(res => {
user.get(Key.FOLLOWS).load(data => {
if (typeof data !== 'object' || data === null) {
Logger.warn(
`GunDb -> getters -> currentFollows() -> Current follows data as fetched from gun is not an object but ${typeof data}. This can happen if Gun lost its cache and it's still retrieving data from the network.`
)
res({})
return
}
const rejected = Object.entries(data).filter(
([_, follow]) => !Common.Schema.isFollow(follow)
)
rejected.forEach(([key, item]) => {
// expected when unfollowed
if (item !== null) {
Logger.warn(
`GunDb -> getters -> currentFollows() -> Item not conforming to schema found inside follows data. Key: ${key}, item: ${JSON.stringify(
item
)}.`
)
}
})
const passed = Object.entries(data).filter(([_, follow]) =>
Common.Schema.isFollow(follow)
)
const p = /** @type {unknown} */ (passed)
res(/** @type {Record<string, Follow>} */ (p))
})
})
}

View file

@ -0,0 +1,42 @@
/**
* @format
*/
const Key = require('../key')
const Utils = require('../utils')
/**
* @param {string} pub
* @returns {Promise<string>}
*/
exports.currentOrderAddress = async pub => {
const currAddr = await Utils.tryAndWait(gun =>
gun
.user(pub)
.get(Key.CURRENT_ORDER_ADDRESS)
.then()
)
if (typeof currAddr !== 'string') {
throw new TypeError('Expected user.currentOrderAddress to be an string')
}
return currAddr
}
/**
* @param {string} pub
* @returns {Promise<string|null>}
*/
exports.userToIncomingID = async pub => {
const incomingID = await require('../../Mediator')
.getUser()
.get(Key.USER_TO_INCOMING)
.get(pub)
.then()
if (typeof incomingID === 'string') return incomingID
return null
}
module.exports.Follows = require('./follows')

View file

@ -42,3 +42,5 @@ exports.CHANNELS_BACKUP = 'channelsBackup'
exports.LAST_SEEN_APP = 'lastSeenApp'
exports.LAST_SEEN_NODE = 'lastSeenNode'
exports.FOLLOWS = 'follows'

View file

@ -13,7 +13,6 @@ const responseTime = require("response-time");
const uuid = require("uuid/v4");
const Common = require('shock-common')
const getListPage = require("../utils/paginate");
const auth = require("../services/auth/auth");
const FS = require("../utils/fs");
@ -22,6 +21,7 @@ const LightningServices = require("../utils/lightningServices");
const GunDB = require("../services/gunDB/Mediator");
const { unprotectedRoutes, nonEncryptedRoutes } = require("../utils/protectedRoutes");
const GunActions = require("../services/gunDB/contact-api/actions")
const GunGetters = require('../services/gunDB/contact-api/getters')
const DEFAULT_MAX_NUM_ROUTES_TO_QUERY = 10;
const SESSION_ID = uuid();
@ -33,6 +33,8 @@ module.exports = async (
mySocketsEvents,
{ serverPort, CA, CA_KEY, usetls }
) => {
const {timeout5} = require('../services/gunDB/contact-api/utils')
const Http = Axios.create({
httpsAgent: new httpsAgent.Agent({
ca: await FS.readFile(CA)
@ -434,6 +436,67 @@ module.exports = async (
});
const feedObj = {
feed: [
{
id:'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
paragraphs:[
"SOme text and stuff 12"
],
profilePic:"",
username:"bobni",
media:[
{
type:'VIDEO',
ratio_x: 1024,
ratio_y: 436,
magnetUri:'magnet:?xt=urn:btih:08ada5a7a6183aae1e09d831df6748d566095a10&dn=Sintel&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.fastcast.nz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com&ws=https%3A%2F%2Fwebtorrent.io%2Ftorrents%2F&xs=https%3A%2F%2Fwebtorrent.io%2Ftorrents%2Fsintel.torrent',
},
]
},
{
id:'3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
paragraphs:[
"SOme text and stuff"
],
profilePic:"",
username:"bobni",
media:[
{
type:'VIDEO',
ratio_x: 1920,
ratio_y: 804,
magnetUri:'magnet:?xt=urn:btih:c9e15763f722f23e98a29decdfae341b98d53056&dn=Cosmos+Laundromat&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.fastcast.nz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com&ws=https%3A%2F%2Fwebtorrent.io%2Ftorrents%2F&xs=https%3A%2F%2Fwebtorrent.io%2Ftorrents%2Fcosmos-laundromat.torrent',
},
]
},
{
id:'58694a0f-3da1-471f-bd96-145571e29d72',
paragraphs:[
"SOme text and stuff"
],
profilePic:"",
username:"bobni",
media:[
{
type:'VIDEO',
ratio_x: 1920,
ratio_y: 1080,
magnetUri:'magnet:?xt=urn:btih:dd8255ecdc7ca55fb0bbf81323d87062db1f6d1c&dn=Big+Buck+Bunny&tr=udp%3A%2F%2Fexplodie.org%3A6969&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Ftracker.empire-js.us%3A1337&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.fastcast.nz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com&ws=https%3A%2F%2Fwebtorrent.io%2Ftorrents%2F&xs=https%3A%2F%2Fwebtorrent.io%2Ftorrents%2Fbig-buck-bunny.torrent',
},
]
}
]
}
user.get("FEED_POC").put(JSON.stringify(feedObj), ack => {
if (ack.err) {
//rej(new Error(ack.err))
logger.log(ack.err)
} else {
logger.log(ack.err)
}
})
//register to listen for channel backups
const onNewChannelBackup = () => {
logger.warn("Subscribing to channel backup ...")
@ -1617,7 +1680,6 @@ module.exports = async (
const GunEvent = Common.Constants.Event
const Key = require('../services/gunDB/contact-api/key')
const { timeout5 } = require('../services/gunDB/contact-api/utils')
app.get("/api/gun/lndchanbackups", async (req,res) => {
try{
@ -1633,6 +1695,18 @@ module.exports = async (
res.json({ok:"err"})
}
})
app.get("/api/gun/feedpoc", async (req,res) =>{
try{
logger.warn("FEED POC")
const user = require('../services/gunDB/Mediator').getUser()
const feedObj = await timeout5(user.get("FEED_POC").then())
logger.warn(feedObj)
res.json({data:feedObj})
} catch (err) {
//res.json({ok:"err"})
}
})
const Events = require('../services/gunDB/contact-api/events')
@ -1757,6 +1831,88 @@ module.exports = async (
}
})
/////////////////////////////////
/**
* @template P
* @typedef {import('express-serve-static-core').RequestHandler<P>} RequestHandler
*/
const ap = /** @type {Application} */ (app);
/**
* @typedef {object} FollowsRouteParams
* @prop {(string|undefined)=} publicKey
*/
/**
* @type {RequestHandler<FollowsRouteParams>}
*/
const apiGunFollowsGet = (_, res) => {
try {
// const { publicKey } = req.params;
// const currFollows = await GunGetters.currentFollows()
return res.status(200).json({})
} catch (err) {
return res.status(500).json({
errorMessage: err.message || 'Unknown ERR at GET /api/follows'
})
}
}
/**
* @type {RequestHandler<FollowsRouteParams>}
*/
const apiGunFollowsPut = (req, res) => {
try {
const { publicKey } = req.params;
if (!publicKey) {
throw new Error(`Missing publicKey route param.`)
}
// await GunActions.follow(req.params.publicKey, false)
// 201 would be extraneous here. Implement it inside app.put
return res.status(200).json({
ok: true
})
} catch (err) {
return res.status(500).json({
errorMessage: err.message || 'Unknown error inside /api/gun/follows/'
})
}
}
/**
* @type {RequestHandler<FollowsRouteParams>}
*/
const apiGunFollowsDelete = (req, res) => {
try {
const { publicKey } = req.params;
if (!publicKey) {
throw new Error(`Missing publicKey route param.`)
}
// await GunActions.unfollow(req.params.publicKey)
return res.status(200).json({
ok: true
})
} catch (err) {
return res.status(500).json({
errorMessage: err.message || 'Unknown error inside /api/gun/follows/'
})
}
}
ap.get('/api/gun/follows/', apiGunFollowsGet)
ap.get('/api/gun/follows/:publicKey', apiGunFollowsGet)
ap.put(`/api/gun/follows/:publicKey`,apiGunFollowsPut)
ap.delete(`/api/gun/follows/:publicKey`, apiGunFollowsDelete)
/**
* Return app so that it can be used by express.
*/

View file

@ -5877,9 +5877,9 @@ shellwords@^0.1.1:
integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==
shock-common@0.x.x:
version "0.2.0"
resolved "https://registry.yarnpkg.com/shock-common/-/shock-common-0.2.0.tgz#b942d4b8730890aaf192eb873957c235333eddca"
integrity sha512-K9UysxR4LnArhljK3kRNdRM2yeI52YxPe0dZ62SNvsHO5oJgE6wDV0qGy9UZYS5FoAprF5QRzzADxgqmGWin+Q==
version "0.3.0"
resolved "https://registry.yarnpkg.com/shock-common/-/shock-common-0.3.0.tgz#2e8a9c2cd1eda300a8461ea9648d250237f22f78"
integrity sha512-K0xOKkrOAvD4rlWVQD5WXASiKyfatEX2cj114LC8Wddi3wXpex5yLNdWBXNGFpL6Vc5Wzhza/sEHs4p+Q3xBmw==
dependencies:
lodash "^4.17.15"
normalizr "^3.6.0"