Skip to content

Instantly share code, notes, and snippets.

@DrI-T
Last active April 27, 2021 19:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DrI-T/c14efcda880adfa879fb5b76b7247955 to your computer and use it in GitHub Desktop.
Save DrI-T/c14efcda880adfa879fb5b76b7247955 to your computer and use it in GitHub Desktop.
public folder
// this code find the peers who stated "I share my MFS public folder" and display the public folder url
let el = null;
var ipns_cache = {};
var peers = [];
var peerid = 'QmcfHufAK9ErQ9ZKJF7YX68KntYYBJngkGDoVKcZEJyRve';
var api_url = 'http://127.0.0.1:5001/api/v0/';
var gw_url = 'https://ipfs.blocring™.ml';
var label = 'I share my MFS public folder.';
console.log('this is my app running here from %s!',location.origin);
el = document.getElementsByTagName('h3')[0]; el.innerText = el.innerText.replace(':origin',location.origin)
el = document.getElementsByTagName('small')[0]; el.innerText = el.innerText.replace(':origin',location.origin)
ipfsGetPeerid().then(p => { peerid = p;
let el=document.getElementsByTagName('p')[0]; el.innerHTML=el.innerHTML.replace(/:peerid/g,p)
});
set_app_urls();
ipfsPeerConnect('Qmd2iHMauVknbzZ7HFer7yNfStR4gLY1DSiih8kjquPzWV','ws');
register(label,'only-hash=true&pin=false').catch(console.warm);
function set_app_urls() {
// echo -n 'gist:c14efcda880adfa879fb5b76b7247955' | ipfs add -n
let test_url = 'http://172.17.0.2:5001/api/v0/pin/add?arg=QmZk8fcjbVJKBU2tXVCCCZk9mUKWxFmpPrXTmBYJ6HQmXf'
fetch(test_url,{method:'POST'}).
then( resp => {
console.log('resp.url:',resp.url);
console.log('resp.status:',resp.status);
console.log('resp.content-length:',resp.headers.get('content-length'));
if (resp.status >= 200 && resp.status < 300) {
console.log('set_app_urls.resp:',resp)
api_url = 'http://127.0.0.1:5001/api/v0/';
gw_url = 'http://127.0.0.1:8080';
console.log('api_url:',api_url)
return resp;
} else {
console.log('set_app_urls.resp:',resp)
console.log('resp.statusText:',resp.statusText);
return Promise.reject(new Error(`ABORT: ${resp.status} ${resp.statusText}`));
}
}).
catch(console.warn);
}
function abort() {
window.stop();
throw new Error('ABORT');
return Promise.reject('ABORT')
}
async function publish(ev) {
let root_path = await ipfsNameResolve(peerid);
let qmroot = root_path.replace('/ipfs/','');
console.debug('qmroot:',qmroot);
let qmtemp = qmroot;
if ( (await ipfsExists('/public',qmroot))[0]) { console.debug('info: -e ipns:/public'); qmtemp = await ipfsRemove('public',qmroot); }
console.debug('qmtemp:',qmtemp);
if ( (await mfsExists('/public'))[0]) {
console.debug('info: -e /public');
qmtemp = await ipfsCopy('/public',qmtemp)
} else {
console.debug('info: ! -e /public');
let publicpath = '/ipfs/QmfMeALq9cV9LiQiirEE1Wb9DuKoe7h6wwP9Uw51Wk1GyS'; // TODO update w/ a nicer site later
qmtemp = await ipfsCopy(publicpath,qmtemp+'/public')
}
console.debug('qmtemp:',qmtemp);
ipfsNamePublish('self',qmtemp)
return register(label,'pin=true').catch(console.warm);
}
function register(label,option) {
peers = [];
let form = new FormData();
form.append('file', label)
return promized_hash = fetch(api_url+'add?file=statement.txt&'+option,{ method: 'POST', body: form }).
then(resp => resp.json()).
then(json => {
console.debug('register.add.json:',json);
let qm = json.Hash;
let el = document.getElementById('token');
if (typeof(el) != 'undefined' && el != null) {
el.innerText = `token : ${qm}`;
}
return fetch(api_url+'dht/findprovs?arg='+qm, { method: 'POST' }).
then( resp => { console.log(resp.body); return resp.body.getReader(); }).
then( reader => { return readStream(reader,resolve_peers); }).
then( _ => { return display_peers(peers); }).
catch(console.error);
}).
catch(console.warn);
}
function display_peers(peers) {
let buf = '<ol>';
let peerids = peers.map((o) => o.Responses[0].ID );
//console.log({ipns_cache: ipns_cache})
for (p of peerids) {
if (typeof(ipns_cache[p]) != 'undefined' && ipns_cache[p] != 'pending') {
buf += `<li><a title="${p}/public" href=${gw_url}${ipns_cache[p]}>@${p}/public</a>`
+` <a href=https://duckduckgo.com/?q=%2B%22${p}%22>🔎</a>`;
// console.info('ipns_cache: %s -> %s',p,ipns_cache[p]);
} else {
buf += `<li><a title="${ipns_cache[p]}" href=${gw_url}/ipns/${p}>${shortqm(p)}</a>`
+` <a href=https://duckduckgo.com/?q=%2B%22${p}%22>🔎</a>`;
}
}
buf += '</ol>';
let d = document.getElementById('peers');
d.innerHTML = buf;
return peerids;
}
async function resolve_peers(streamed_objs) {
let peerids = [];
if (streamed_objs.length > 0) {
peers.push(...streamed_objs.filter( (o) => o.Type == 4 ));
peerids = peers.map((o) => o.Responses[0].ID );
for (p of peerids) {
if (typeof(p) != 'undefined') {
if (typeof(ipns_cache[p]) == 'undefined') {
ipns_cache[p] = 'pending';
ipfsResolve(`/ipns/${p}/public`).then( qm => {
console.debug('ipns_cache[%s]: %s (update)',p,qm)
if (typeof(qm) != 'undefined') {
ipns_cache[p] = qm;
}
}).catch(console.warn)
}
}
}
}
display_peers(peers);
return peerids;
}
function shortqm(qm) {
if (typeof(qm) != 'undefined') {
return qm.substr(0,6)+'...'+qm.substr(-3)
} else {
return 'QmezgbyqFCEybpSxCtGNxfRD9uDxC53aNv5PfhB3fGUhJZ';
}
}
function readStream(reader, callback) {
let read;
var buf = ''
return reader.read().
then(read = ({ value, done }) => {
if (done) return buf;
//console.debug('value.buffer:',value.buffer)
if (buf != '') { console.debug('buf:',buf) }
buf += String.fromCharCode.apply(String, value);
// spliting the NDJSON
let lines = buf.replace(/(\n|\r)+$/, '').split("\n")
buf = (lines[lines.length-1].match(/}$/)) ? '' : lines.pop();
let objs = lines.map(JSON.parse)
// console.log('objs:',objs)
callback(objs);
if (objs.length > 0) {
return reader.read().then(read).catch(console.warn); // recursion !
} else {
return Promise.reject(String.fromCharCode.apply(String, value));
}
});
}
function ipfsGetPeerid() {
return fetch(api_url+'config?arg=Identity.PeerID', { method: 'POST', mode: 'cors' }).
then( resp => { console.log(resp); return resp.json(); }).
then( obj => { console.info('peerid:',obj); return obj.Value; }).
catch(console.error);
}
function ipfsResolve(ipath) {
var url = api_url + 'resolve?arg='+ipath+'&timeout=61s';
return fetch(url, { method:'POST' }).then(resp => resp.json())
.then( json => {
if (typeof(json) != 'undefined') {
return json.Path
} else {
return undefined
}
} )
.catch(console.error)
}
function ipfsPeerConnect(peerkey,layer) {
var url = api_url + 'dht/findpeer?arg='+peerkey;
return fetch(url,{ method:'POST' })
.then( resp => resp.text() )
.then( text => {
let ndjson = text.slice(0,-1).split('\n')
console.debug({'connect.ndjson': ndjson});
let addr;
for (let record of ndjson) {
//console.debug('connect.record:',record);
let json = JSON.parse(record);
if (json.Type != 2) { continue; }
console.debug({'ipfsPeerConnect.Addrs':json.Responses[0].Addrs});
for (let addy of json.Responses[0].Addrs) {
if (addy.match(layer+'$') && addy.match('^/ip4/')
&& ! addy.match('/ip4/127\.') && ! addy.match('/ip4/192\.') ) {
console.log('ipfsPeerConnect.addy:',addy);
addr = addy; break
}
}
}
if (typeof(addr) != 'undefined') {
return ipfsSwarmConnect(addr+'/p2p/'+peerkey).
catch(console.error);
} else {
console.error('ipfsPeerConnect.addr: undefined')
}
})
.catch(console.error);
}
function ipfsSwarmConnect(addr) {
console.log('connect.addr: ',addr);
if (typeof(addr) != 'undefined') {
url = api_url + 'swarm/connect?arg='+addr;
return fetch(url,{ method:'POST' })
.then( resp => resp.json() )
.then( obj => {
if (typeof(obj.Strings) != 'undefined' && obj.Strings[0].match('success')) {
console.log('ipfsSwarmConnect.SUCCESS:', obj);
return [true, addr];
} else {
console.warn('ipfsSwarmConnect.ERROR:', obj);
return Promise.reject([false, addr]);
}
})
.catch(console.error);
} else {
return [null, addr];
}
}
function ipfsNamePublish(k,v) {
var url = api_url + 'name/publish?key='+k+'&arg='+v+'&allow-offline=1&resolve=0';
return fetch(url,{ method:'POST' }).then(resp => resp.json())
.then( json => { return json.Value })
.catch(console.error)
}
function ipfsNameResolve(k,cb) {
var url = api_url + 'name/resolve?arg='+k;
return fetch(url,{ method:'POST' }).then(resp => resp.json())
.then( json => {
if (typeof(cb) != 'undefined') { return cb(json.Path); }
return json.Path
})
.catch(console.error);
}
function mfsGetHashByPath(mfspath) {
var url = api_url + 'files/stat?arg='+mfspath+'&hash=true'
return fetch(url,{method:'POST'})
.then( resp => resp.json() )
.then( json => {
if (typeof(json.Hash) == 'undefined') {
if (typeof(qmEmpty) != 'undefined') { return qmEmpty }
else { console.debug('mfsGetHashByPath.json.Hash: undefined'); return qmNull }
} else {
return json.Hash
}
})
.catch(console.error)
}
function mfsCopy(hash,mfspath) {
var url = api_url + 'files/cp?arg=/ipfs/'+hash+'&arg='+mfspath;
console.log('mfsCopy.url:',url);
return fetch(url,{method:'POST'})
.then( resp => resp.text() )
.then( text => { if (text != '') { console.log('mfsCopy.text:',text); } return text; })
.then( _ => { return mfsGetHashByPath(mfspath); })
.catch(console.error)
}
function mfsExists(mfspath) {
var url = api_url + 'files/stat?arg='+mfspath+'&hash=true'
return fetch(url,{method:'POST'})
.then( resp => { console.log('mfsExists.resp:',resp); return resp; } )
.then( resp => resp.json() )
.then( json => {
if (typeof json.Hash == 'undefined') {
return [false,null]
} else {
return [true,json.Hash]
}
})
.catch(console.error)
}
async function ipfsCopy(source,dest) {
let name,hash;
if (dest.match('/')) {
hash = dest.split('/')[0];
name = basename(dest);
} else {
hash = dest;
name = basename(source);
}
let [doesExist,link] = await mfsExists(source);
if (doesExist) {
var url = api_url + 'object/patch/add-link?arg='+hash+'&arg='+name+'&arg='+link;
return fetch(url,{method:'POST'})
.then( resp => resp.json() )
.then( json => { return json.Hash; })
.catch(console.error)
} else {
console.warn("ipfsCopy.source: %s doesn't exist; link: %s",source,link);
return hash;
}
}
function ipfsExists(path,qm) {
var url = api_url + 'files/stat?arg=/ipfs/'+qm+path+'&hash=true';
return fetch(url,{method:'POST'})
.then( resp => resp.json() )
.then( json => {
// console.log('ipfsExists.json:',json)
if (typeof json.Hash == 'undefined') {
return [false,null]
} else {
return [true,json.Hash]
}
})
.catch(console.error)
}
function ipfsRemove(name,hash) {
var url = api_url + 'object/patch/rm-link?arg='+hash+'&arg='+name
return fetch(url,{method:'POST',mode:'cors'})
.then( resp => resp.json() )
.then( json => {
if (typeof(json.Code) == 'undefined' ) {
return json.Hash;
} else {
console.warn('ipfsRemove.error: ! -e %s in qm: ',name,hash); // one %s works!
return hash;
}
})
.catch(console.error)
}
function basename(f) {
let s = '/';
let p = f.lastIndexOf(s,f.length-2);
let b = f.substr(p+1);
return b;
}
true;
<!DOCTYPE html><meta charset=utf8><link rel="stylesheet" href="style.css">
<link rel="icon" href="favicon.webp">
<title>Public Folders</title>
<div id=container class=shadow>
<h3>My Public Folder (:origin)</h3>
<p>You can find your <a href=http://127.0.0.1:5001/webui/#/files/public/>public</a> folder here :
<a href="http://127.0.0.1:8080/ipns/:peerid/public">ipns://:peerid/public</a>
<button onclick=publish(event)>publish</button>
<h3>Public folders in my network neighborhood</h3>
<div id=peers></div>
<small>note: you need to have :origin in your "Allow-Origins" list for this page to work.</small>
<br>--&nbsp;<br>
~<a href=https://www.drit.ml/>Dr I·T</a>
</div>
<script src=app.js></script>
/* this is a styling sheet */
body {
background-image: url(https://gateway.ipfs.io/ipfs/QmTgP6DGHgT6UgsiqTcgKQETrcGZj1XCYqsx3vK9prDECf/bg-tadahak.jpg);
background-size: auto 100%;
background-repeat: no-repeat;
background-position: center;
min-height: 100vh;
}
.dbug { border: 3px dotted red; }
#container {
max-width: 720px;
min-height: 40vh;
margin: auto;
margin-top: 15vh;
padding: 0.8rem;
background-color: white;
opacity: 0.94;
}
.shadow {
box-shadow: 5px 5px 15px 2px rgba(4,3,5,0.9);
overflow: visible;
}
.rounded {
border-radius: 0.5rem;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment