UNPKG

stremio-addon-client

Version:

Client library for using stremio addons (v3 protocol)

160 lines (137 loc) 3.89 kB
var URL = require('url') var errors = require('../errors') var IPFS = require('ipfs') var Room = require('ipfs-pubsub-room') var thunky = require('thunky') var qs = require('querystring') var URL = require('url') var IPFSRepo = require('ipfs-repo') // Potentially for IPFSRepo //var path = require('path') //var os = require('os') // @TODO: retry logic var TIME_TO_RETR_MISSING = 6 * 1000 var setupIPFS = thunky(function(cb) { var node = new IPFS({ EXPERIMENTAL: { pubsub: true }, // takes path; the impl can take memory repo: new IPFSRepo('./.jsipfs', { lock: 'memory' }), // overload the default IPFS node config, find defaults at https://github.com/ipfs/js-ipfs/tree/master/src/core/runtime config: { Addresses: { Swarm: [ // @todo: sockets, webrtc, web browser compatible '/ip4/127.0.0.1/tcp/1339', //'/dns4/ws-star.discovery.libp2p.io/tcp/443/wss/p2p-websocket-star', ] }, Bootstrap: [ '/ip4/127.0.0.1/tcp/4001/ipfs/QmYRaTC2DqsgXaRUJzGFagLy725v1QyYwt66kvpifPosgj', ], Discovery: { MDNS: { Enabled: false } } }, }) node.once('ready', function() { cb(null, node) }) // @TODO node.on('error', function(err) { console.error(err) }) }) function ipfsTransport(url) { var manifestUrl = url.replace('ipfs://', '/ipfs/').replace('ipns://', '/ipns/') var base = manifestUrl.replace('/manifest.json', '/') this.url = url this.manifest = function(cb) { setupIPFS(function(err, node) { if (err) return cb(err) retrFile(node, manifestUrl, function(err, resp) { if (err) return cb(err) if (!resp || typeof(resp.id) !== 'string') return cb(errors.ERR_MANIFEST_INVALID) // Find the add-on creator peer // https://github.com/ipfs/js-ipfs/issues/870 //node1.peerRouting.findPeer(node3.peerInfo.id, function(err, peer) { node.addonRoom = Room(node, resp.id) node.addonRoom.on('subscribed', function() { cb(null, resp) }) // @TODO TEMP //node.addonRoom.on 'peer joined' 'peer left' 'subscribed' }) }) } this.get = function(args, cb) { setupIPFS(function(err, node) { if (err) return cb(err) if (! node.addonRoom) return cb(errors.ERR_MANIFEST_CALL_FIRST) var p = args.map(mapArg).join('/') retrFile(node, base+p+'.json', function(err, res) { if (err && err.message.match('No such file')) { node.addonRoom.broadcast(p) setTimeout(function() { retrFile(node, base+p+'.json', cb) }, TIME_TO_RETR_MISSING) return } cb(err, res) }) }) } this.destroy = function(cb) { // @XXX: if you call this without calling manifest/get before, it will create a instance and then kill it setupIPFS(function(err, node) { if (err) return cb(err) node.stop(cb) }) } function mapArg(arg) { if (typeof(arg) === 'object') { return qs.stringify(arg, '&', '=', { encodeURIComponent: function(x) { return x } }) } else { return arg } } function retrFile(node, p, cb) { node.files.cat(p, function(err, res) { if (err) return cb(err) try { res = JSON.parse(res.toString()) } catch(e) { return cb(err) } cb(null, res) }) } function requestMissing(url, cb) { // https://github.com/ipfs/js-ipfs/issues/870 // node1.peerRouting.findPeer(node3.peerInfo.id, function(err, peer) { // https://github.com/ipfs/js-libp2p-ipfs-nodejs/tree/master/examples/echo // https://github.com/libp2p/go-libp2p/tree/master/examples/echo // https://github.com/libp2p/js-libp2p/tree/master/examples/transports } // @TODO ipns, or otherwise do not open a pubsub // @TODO: anti-spam on the pubsub, and research whether all clients have to listen return this } ipfsTransport.isValidURL = function(url) { var parsed = URL.parse(url) return parsed.protocol === 'ipfs:' || parsed.protocol === 'ipns:' } module.exports = ipfsTransport