diff --git a/libs/package-lock.json b/libs/package-lock.json index 774913a391d..00827084633 100644 --- a/libs/package-lock.json +++ b/libs/package-lock.json @@ -1,6 +1,6 @@ { "name": "@audius/libs", - "version": "0.11.0", + "version": "0.11.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/libs/package.json b/libs/package.json index 90eac064032..e394ba5cb98 100644 --- a/libs/package.json +++ b/libs/package.json @@ -1,6 +1,6 @@ { "name": "@audius/libs", - "version": "0.11.0", + "version": "0.11.1", "description": "", "main": "src/index.js", "browser": { diff --git a/libs/src/index.js b/libs/src/index.js index 721fca405dd..92ae4b3a061 100644 --- a/libs/src/index.js +++ b/libs/src/index.js @@ -9,6 +9,7 @@ const DiscoveryProvider = require('./services/discoveryProvider/index') const AudiusABIDecoder = require('./services/ABIDecoder/index') const UserStateManager = require('./userStateManager') const Utils = require('./utils') +const SanityChecks = require('./sanityChecks') const Account = require('./api/account') const User = require('./api/user') @@ -267,3 +268,4 @@ module.exports = AudiusLibs module.exports.AudiusABIDecoder = AudiusABIDecoder module.exports.Utils = Utils +module.exports.SanityChecks = SanityChecks diff --git a/libs/src/sanityChecks/index.js b/libs/src/sanityChecks/index.js new file mode 100644 index 00000000000..ebbbdaae448 --- /dev/null +++ b/libs/src/sanityChecks/index.js @@ -0,0 +1,16 @@ +const isCreator = require('./isCreator') + +// Checks to run at startup to ensure a user is in a good state. +class SanityChecks { + constructor (libsInstance) { + this.libs = libsInstance + } + + async run () { + await Promise.all([ + isCreator(this.libs) + ]) + } +} + +module.exports = SanityChecks diff --git a/libs/src/sanityChecks/isCreator.js b/libs/src/sanityChecks/isCreator.js new file mode 100644 index 00000000000..f7058ebf877 --- /dev/null +++ b/libs/src/sanityChecks/isCreator.js @@ -0,0 +1,71 @@ +const axios = require('axios') + +/** Sanity check for whether a user is a creator. If not, make them one. */ + +const hasCID = async (node, cid) => { + const url = `${node.endpoint}/ipfs/${cid}` + try { + const res = await axios.head(url) + return res.status === 200 + } catch (e) { + return false + } +} + +const hasAllCID = async (node, cids) => { + const hasAll = await Promise.all(cids.map(cid => hasCID(node, cid))) + return hasAll.every(Boolean) +} + +const findCorrectNode = async (nodes, cids) => { + for (let i = 0; i < nodes.length; ++i) { + const hasAll = await hasAllCID(nodes[i], cids) + if (hasAll) return nodes[i] + } + return null +} + +const isCreator = async (libs) => { + const user = libs.userStateManager.getCurrentUser() + if ( + // There is no currently logged in user + !user || + // The user has no tracks (they shouldn't become a creator) + !user.track_count || + // The user is a creator and has a creator node endpoint + (user.is_creator && user.creator_node_endpoint) + ) return + + // Find the CIDs for all of the user's content (tracks + images) + let cids = [ + user.profile_picture, + user.cover_photo + ] + const tracks = await libs.Track.getTracks(500, 0, null, user.user_id) + tracks.forEach(track => { + cids.push(track.cover_art) + cids.push(track.metadata_multihash) + track.track_segments.forEach(segment => { + cids.push(segment.multihash) + }) + }) + cids = cids.filter(Boolean) + + // Check whether all the CIDs are availabile on a creator node + const nodes = await libs.ServiceProvider.listCreatorNodes() + const correctNode = await findCorrectNode(nodes, cids) + + // Upgrade the user to a creator + if (correctNode) { + const newUserMetadata = { ...user } + newUserMetadata.creator_node_endpoint = correctNode.endpoint + try { + await libs.User.upgradeToCreator(newUserMetadata) + } catch (e) { + console.error(e) + // We were actually a creator the whole time O_O + } + } +} + +module.exports = isCreator