initial, in a state of flux
This commit is contained in:
commit
d029625142
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
venv
|
||||||
|
pinlist.json
|
19
Dockerfile
Normal file
19
Dockerfile
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
FROM ubuntu:16.04
|
||||||
|
|
||||||
|
VOLUME /var/lib/ipfs
|
||||||
|
ENV IPFS_PATH /var/lib/ipfs
|
||||||
|
|
||||||
|
ADD \
|
||||||
|
https://dist.ipfs.io/go-ipfs/v0.4.4/go-ipfs_v0.4.4_linux-amd64.tar.gz \
|
||||||
|
/usr/local/src
|
||||||
|
|
||||||
|
ADD . /var/generate-pinlist
|
||||||
|
|
||||||
|
RUN \
|
||||||
|
cd /usr/local/src && \
|
||||||
|
tar zxvf go-ipfs_v0.4.4_linux-amd64.tar.gz && \
|
||||||
|
mv go-ipfs/ipfs . && \
|
||||||
|
cd /var/generate-pinlist && \
|
||||||
|
pip -r requirements.txt && \
|
||||||
|
python generate.py && \
|
||||||
|
ipfs add pinlist.txt
|
15
README.md
Normal file
15
README.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# ipfs-autopin
|
||||||
|
|
||||||
|
I want more stuff to get pinned on more hosts.
|
||||||
|
|
||||||
|
This is a repo that generates a script that can be run to pin a bunch
|
||||||
|
of IPFS paths. The list itself will be periodically generated from this
|
||||||
|
repo and placed into ipfs under my namespace, allowing people to
|
||||||
|
fetch it consistently and automatically update their pinning lists.
|
||||||
|
|
||||||
|
# Requirements
|
||||||
|
|
||||||
|
* general-purpose interest
|
||||||
|
* not too big (blogs, metadata, documents)
|
||||||
|
* not general purpose software mirrors / etc
|
||||||
|
* maybe later
|
166
generate.py
Executable file
166
generate.py
Executable file
@ -0,0 +1,166 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#import ipfsapi
|
||||||
|
from sanelogging import log
|
||||||
|
from datetime import datetime
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
ipfsPathPattern = re.compile('\/ipfs\/([a-zA-Z0-9]+)')
|
||||||
|
|
||||||
|
#def connectIpfs(hostname='127.0.0.1',port=5001):
|
||||||
|
# ipfs = ipfsapi.connect(hostname,port)
|
||||||
|
# log.info("connected to ipfsd: %s" % ipfs.id()['ProtocolVersion'])
|
||||||
|
# return ipfs
|
||||||
|
|
||||||
|
def main():
|
||||||
|
startTime = datetime.utcnow()
|
||||||
|
log.info("generating pin list.")
|
||||||
|
generatePinList()
|
||||||
|
elapsed = datetime.utcnow() - startTime
|
||||||
|
log.info("finished in %is" % elapsed.total_seconds())
|
||||||
|
|
||||||
|
def generatePinList():
|
||||||
|
pinFiles = readPinFiles()
|
||||||
|
# ipfs = connectIpfs()
|
||||||
|
|
||||||
|
resources = []
|
||||||
|
|
||||||
|
for pinFile in pinFiles:
|
||||||
|
rs = extractResources(pinFile)
|
||||||
|
resources.extend(rs)
|
||||||
|
|
||||||
|
log.info("collected data from files.")
|
||||||
|
|
||||||
|
resources = resolveResources(resources)
|
||||||
|
|
||||||
|
output = {
|
||||||
|
"generatedAt": datetime.utcnow().strftime("%s"),
|
||||||
|
"pinList": resources
|
||||||
|
}
|
||||||
|
log.info("resources resolved, writing pinlist file")
|
||||||
|
outputFileName = 'pinlist.json'
|
||||||
|
fd = open(outputFileName + '.new','w')
|
||||||
|
json.dump(output,fd)
|
||||||
|
fd.close()
|
||||||
|
os.rename(outputFileName + '.new', outputFileName)
|
||||||
|
|
||||||
|
def extractResources(pinFile):
|
||||||
|
# this pulls out the list of ipns/ipfs
|
||||||
|
# items from the single file
|
||||||
|
output = []
|
||||||
|
if 'ipns' in pinFile['pins']:
|
||||||
|
if isinstance(pinFile['pins']['ipns'], basestring):
|
||||||
|
# single ipns name
|
||||||
|
output.append({
|
||||||
|
'type': 'ipns',
|
||||||
|
'name': pinFile['pins']['ipns'],
|
||||||
|
'fileName': os.path.basename(pinFile['fileName'])
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
# list of ipns names
|
||||||
|
for ipnsName in pinFile['pins']['ipns']:
|
||||||
|
output.append({
|
||||||
|
'type': 'ipns',
|
||||||
|
'name': ipnsName,
|
||||||
|
'fileName': os.path.basename(pinFile['fileName'])
|
||||||
|
})
|
||||||
|
|
||||||
|
if 'ipfs' in pinFile['pins']:
|
||||||
|
if isinstance(pinFile['pins']['ipfs'], basestring):
|
||||||
|
# single ipfs name
|
||||||
|
output.append({
|
||||||
|
'type': 'ipfs',
|
||||||
|
'name': pinFile['pins']['ipfs'],
|
||||||
|
'fileName': os.path.basename(pinFile['fileName'])
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
# list of ipfs names
|
||||||
|
for ipfsName in pinFile['pins']['ipfs']:
|
||||||
|
output.append({
|
||||||
|
'type': 'ipfs',
|
||||||
|
'name': ipfsName,
|
||||||
|
'fileName': os.path.basename(pinFile['fileName'])
|
||||||
|
})
|
||||||
|
return output
|
||||||
|
|
||||||
|
def resolveResources(resources):
|
||||||
|
log.info("resolving resource names for pin list")
|
||||||
|
for resource in resources:
|
||||||
|
if resource['type'] == 'ipfs':
|
||||||
|
resource['resolved'] = resource['name']
|
||||||
|
elif resource['type'] == 'ipns':
|
||||||
|
# attepmt to resolve ipns name
|
||||||
|
# FIXME try/catch
|
||||||
|
res = None
|
||||||
|
try:
|
||||||
|
res = resolveIpnsName(resource['name'])
|
||||||
|
if res:
|
||||||
|
resource['resolved'] = res
|
||||||
|
except LookupError:
|
||||||
|
log.info(
|
||||||
|
"unable to resolve ipns name '%s' from file '%s'"
|
||||||
|
% (resource['name'], resource['fileName'])
|
||||||
|
)
|
||||||
|
resource['error'] = 'unable to resolve name'
|
||||||
|
return resources
|
||||||
|
|
||||||
|
def runCommand(cmd):
|
||||||
|
p = subprocess.Popen(
|
||||||
|
cmd,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.STDOUT
|
||||||
|
)
|
||||||
|
retval = p.wait()
|
||||||
|
if retval != 0:
|
||||||
|
raise LookupError()
|
||||||
|
return p.stdout.read()
|
||||||
|
|
||||||
|
def resolveIpnsName(ipnsName):
|
||||||
|
log.debug("resolving name '%s'" % ipnsName)
|
||||||
|
res = runCommand(['ipfs', 'name', 'resolve', ipnsName])
|
||||||
|
ipfsNameMatch = ipfsPathPattern.match(res)
|
||||||
|
if not ipfsNameMatch:
|
||||||
|
log.info("unable to resolve ipns name '%s'" % ipnsName)
|
||||||
|
return None
|
||||||
|
ipfsName = ipfsNameMatch.group(1)
|
||||||
|
log.info("resolved ipns name '%s' to '%s'" % (ipnsName, ipfsName))
|
||||||
|
return ipfsName
|
||||||
|
|
||||||
|
def readPinFiles():
|
||||||
|
log.info("reading pinfiles...")
|
||||||
|
output = []
|
||||||
|
pinFiles = getPinFileNames()
|
||||||
|
for pinFileName in pinFiles:
|
||||||
|
pinFileData = parsePinFile(pinFileName)
|
||||||
|
pinFileData['fileName'] = pinFileName
|
||||||
|
output.append(pinFileData)
|
||||||
|
return output
|
||||||
|
|
||||||
|
def parsePinFile(fn):
|
||||||
|
x = {}
|
||||||
|
f = open(fn,"r")
|
||||||
|
x = yaml.load(f)
|
||||||
|
f.close()
|
||||||
|
validatePinFileData(x)
|
||||||
|
return x
|
||||||
|
|
||||||
|
def validatePinFileData(pinFileStruct):
|
||||||
|
# FIXME validate various file properties here
|
||||||
|
pass
|
||||||
|
|
||||||
|
def getPinFileNames():
|
||||||
|
thisDir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
pinDir = os.path.join(thisDir, 'pins')
|
||||||
|
pinFileNames = [
|
||||||
|
os.path.join(pinDir,f) for f in os.listdir(pinDir)
|
||||||
|
if os.path.isfile(os.path.join(pinDir, f))
|
||||||
|
]
|
||||||
|
return pinFileNames
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
7
pins/ber1-test-name.yml
Normal file
7
pins/ber1-test-name.yml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
description: test name from ber1
|
||||||
|
url: https://sneak.berlin
|
||||||
|
contact:
|
||||||
|
name: Jeffrey Paul
|
||||||
|
email: sneak@sneak.berlin
|
||||||
|
pins:
|
||||||
|
ipns: QmZKpS7iyUnDXcUxhou5arokZ5bZViZokEzDVAEGctBSMw
|
6
pins/fails.yml
Normal file
6
pins/fails.yml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
description: this ipns will intentionall not resolve
|
||||||
|
contact:
|
||||||
|
name: Jeffrey Paul
|
||||||
|
email: sneak@sneak.berlin
|
||||||
|
pins:
|
||||||
|
ipns: QmaN64WRYdHBojWFQRLxkdjtX6TEnqnCq8uAug11111111
|
14
pins/go-ipfs_v0.4.4.json
Normal file
14
pins/go-ipfs_v0.4.4.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"description": "go-ipfs v0.4.4 binaries",
|
||||||
|
"pins":
|
||||||
|
[
|
||||||
|
"/ipfs/QmXvDdqieUAUo7srRVXvsKZRmzNGkuhRqWKYXLcXnBm4dc", // go-ipfs_v0.4.4/go-ipfs_v0.4.4_darwin-386.tar.gz
|
||||||
|
"/ipfs/QmPsMMi2Lq15QDNa8vmyZwwE15KbgUnHkQz3MX8pR5oUvq", // go-ipfs_v0.4.4/go-ipfs_v0.4.4_darwin-amd64.tar.gz
|
||||||
|
"/ipfs/QmQZyL5sWdXQyS9UwPHRsSv5yXz1cWRgTV9C6zS6EsGnBv", // go-ipfs_v0.4.4/go-ipfs_v0.4.4_freebsd-amd64.tar.gz
|
||||||
|
"/ipfs/QmRCXbtDRFUVLYndxxrobsPEKSBNJtPbvq4FTMKWBWqneE", // go-ipfs_v0.4.4/go-ipfs_v0.4.4_linux-386.tar.gz
|
||||||
|
"/ipfs/QmRE6QGDsRhHT81etCKKRvUucoQTY4KqjoH8RKW6jaF7kX", // go-ipfs_v0.4.4/go-ipfs_v0.4.4_linux-amd64.tar.gz
|
||||||
|
"/ipfs/QmUb7jGAgYd4AAGX82qY3Znt2Xrx3FLC2N6jiYVMcSTcMq", // go-ipfs_v0.4.4/go-ipfs_v0.4.4_windows-386.zip
|
||||||
|
"/ipfs/QmPPNuaTHcoFesnZuVjSMaxPVifunrVqFGj3avjTaKSLz3", // go-ipfs_v0.4.4/go-ipfs_v0.4.4_windows-amd64.zip
|
||||||
|
"/ipfs/QmdZ81FrNJYnjHbzuX6L2vqfBmEvRFwUgRU2TdPHU8WNLL" // go-ipfs_v0.4.4
|
||||||
|
]
|
||||||
|
}
|
12
pins/ipfs-webui.json
Normal file
12
pins/ipfs-webui.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"description": "webui files",
|
||||||
|
"url": "https://github.com/ipfs/refs-solarnet-storage/commit/df0a2cc4b53cea15132bec2d0b96b5d2d7a87ffb",
|
||||||
|
"pins": [
|
||||||
|
"/ipfs/QmS2HL9v5YeKgQkkWMvs1EMnFtUowTEdFfSSeMT4pos1e6",
|
||||||
|
"/ipfs/QmXdu7HWdV6CUaUabd9q2ZeA4iHZLVyDRj3Gi4dsJsWjbr",
|
||||||
|
"/ipfs/QmaaqrHyAQm7gALkRW8DcfGX3u8q9rWKnxEMmf7m9z515w",
|
||||||
|
"/ipfs/QmSHDxWsMPuJQKWmVA1rB5a3NX2Eme5fPqNb63qwaqiqSp",
|
||||||
|
"/ipfs/QmctngrQAt9fjpQUZr7Bx3BsXUcif52eZGTizWhvcShsjz",
|
||||||
|
"/ipfs/QmXX7YRpU7nNBKfw75VG7Y1c3GwpSAGHRev67XVPgZFv9R"
|
||||||
|
]
|
||||||
|
}
|
11
pins/sneak.berlin.json
Normal file
11
pins/sneak.berlin.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"url": "https://sneak.berlin",
|
||||||
|
"description": "Personal blog of Jeffrey Paul",
|
||||||
|
"contact": {
|
||||||
|
"name": "Jeffrey Paul",
|
||||||
|
"email": "sneak@sneak.berlin"
|
||||||
|
},
|
||||||
|
"pins": [
|
||||||
|
"/ipns/QmaN64WRYdHBojWFQRLxkdjtX6TEnqnCq8uAugpyJJpCVp/website"
|
||||||
|
]
|
||||||
|
}
|
3
requirements.txt
Normal file
3
requirements.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
colorlog==2.10.0
|
||||||
|
PyYAML==3.12
|
||||||
|
sanelogging==1.0.1
|
Loading…
Reference in New Issue
Block a user