Last active
April 27, 2021 19:08
-
-
Save DrI-T/c14efcda880adfa879fb5b76b7247955 to your computer and use it in GitHub Desktop.
public folder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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; | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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>-- <br> | |
~<a href=https://www.drit.ml/>Dr I·T</a> | |
</div> | |
<script src=app.js></script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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