├── .gitignore ├── .travis.yml ├── README.md ├── af └── za │ └── deavmi.md ├── as └── jp │ └── tokyo.trnsz-jp.k ├── eu ├── ch │ ├── vaud │ │ └── cjdns.theswissbay.ch │ └── zurich │ │ └── 0.h.pfactum.k ├── de │ └── Frankfurt │ │ ├── h.rwfr.k │ │ └── sssemil.k ├── fr │ └── paris │ │ ├── h.totem.tfnux.org.k │ │ └── h.valdek.ml.k ├── lt │ └── vilnius │ │ └── borg.vilnius.lt.k ├── nl │ └── amsterdam │ │ ├── finlaydag33k.nl.k │ │ ├── florianb.ams.k │ │ ├── h.mercury.tfnux.org.k │ │ ├── igel-amersfoort.ams.k │ │ └── sabsare.geek.k ├── no │ └── oslo │ │ └── hyperboria.hackeriet.no.k ├── pl │ └── warsaw │ │ └── magik6k.net.k ├── ru │ ├── moscow │ │ ├── h.bunjlabs.com.k │ │ └── node01.msk.ru-mesh.net.k │ ├── novosibirsk │ │ └── meanmail.k │ └── spb │ │ ├── dskrylnikov.k │ │ └── ru.spb.tokakoka.k ├── se │ └── lulea │ │ └── bohr.willeponken.me.k ├── ua │ └── kiev │ │ ├── h.saloid.ua │ │ └── kiev │ │ └── ic.hellomouse.cf.k └── uk │ ├── birmingham │ └── cocolino.fun.k │ └── london │ └── cwningen.cymru.k ├── index.js ├── na ├── ca │ ├── ontario │ │ ├── kusoneko.moe.k │ │ ├── linux1.tor1.watters.ws.k │ │ └── stash-crypto.k │ └── quebec │ │ └── beauharnois │ │ └── larynx.ventricle.us.k └── us │ ├── california │ ├── computer-pig.k │ ├── igel-california.usa.k │ └── orange-county │ │ └── yk3music.k │ ├── massachusetts │ └── igel-massachusetts.usa.k │ ├── newyork │ └── cord.ventricle.us.k │ ├── northcarolina │ └── charlotte │ │ └── ic2.hellomouse.cf.k │ ├── pennsylvania │ └── nat.usa.k │ └── texas │ └── dallas.trnsz.k ├── package.json ├── sa └── br │ └── saopaulo │ └── sp.yetanothernerd.xyz.k ├── testAvailable.py ├── tests.js └── tests.py /.gitignore: -------------------------------------------------------------------------------- 1 | .*.swp 2 | .* 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | addons: 3 | apt: 4 | packages: 5 | - python3 6 | script: ./tests.py 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://secure.travis-ci.org/hyperboria/peers.png)](http://travis-ci.org/hyperboria/peers) 2 | 3 | > A geographically sorted list of public peering credentials for joining [Hyperboria](https://hyperboria.net/). 4 | 5 | [Hyperboria](https://hyperboria.net/) uses [cjdns](https://github.com/cjdelisle/cjdns) to construct an end-to-end-encrypted ipv6 mesh network. 6 | Connections between nodes are established manually, and traffic is restricted to the resulting social graph. 7 | 8 | This repository exists for those who don't already know somebody on Hyperboria. 9 | 10 | ## Using credentials 11 | 12 | First, set up a cjdns node. 13 | 14 | To connect your node to one of these public peers, follow [the steps in the cjdns README](https://github.com/cjdelisle/cjdns/#3-connect-your-node-to-your-friends-node). 15 | 16 | ## Adding your public node's credentials 17 | 18 | If you've created a public node, and would like to have it listed here, fork the repo, add a keyfile, run `./tests.py` (make sure your file passes the test), and submit a PR. 19 | 20 | We won't merge your credentials until our tests are passing. 21 | 22 | ### Filepath conventions 23 | Credentials are sorted geographically, by [continent](https://github.com/hyperboria/docs/blob/master/cjdns/nodeinfo-json.md#regarding-continent-codes) code. 24 | Nodes may be classified further, at the discretion of the node operator, and the administrators of the repository. 25 | 26 | The suggested format is `/continent/country/region/municipality`. For example, `/na/ca/ontario/toronto/`. 27 | 28 | Region and municipality codes are based on self identification, not any ISO standard. 29 | An operator might prefer to list their node in Cascadia instead of Washington state. 30 | For simplicity's sake, we'd prefer that new credentials conform to existing structures. 31 | 32 | ### JSON formatting 33 | 34 | We have tried to standardize the structure of the actual credential files, as such, they have the strictest requirements of anything in this repository. 35 | 36 | * Your credentials must be [valid JSON](http://jsonlint.com/). 37 | * They must contain the necessary fields: 38 | + ip/port 39 | + password 40 | + publicKey 41 | + contact (a means of contacting the operator) 42 | * The following fields are not yet required, but are recommended: 43 | + gpg, listing your 16 character pgp fingerprint (all caps, no spaces) 44 | + peerName, a human-readable name for the node 45 | * credentials should be formatted such that: 46 | - indentation uses four spaces 47 | - the file ends with a newline character. 48 | * credentials must use IP:port strings for keys 49 | - credentials using hostnames will not be accepted 50 | * If you are hosting it on a major server provider, please provide the name and shorthand for server. 51 | - On digitalocean, That may be ```digitalocean sfo2``` 52 | - On linode, that may be ```linode uswest``` or ```linode tokyo2``` 53 | - On AWS, use the region, followed by the city. Usable Server names are listed can be found on found on the [AWS WEBSITE](https://aws.amazon.com/about-aws/global-infrastructure/) 54 | 55 | EX: useastnorthernvirginia,useastohio,southamericasaopaulo 56 | 57 | ``` 58 | { 59 | "192.168.1.5:10326":{ 60 | "contact":"alice@bob.com", 61 | "gpg":"FC00FC00FC00FC00", 62 | "login":"default-login", 63 | "password":"nq1uhmf06k8c5594jqmpgy26813b81s", 64 | "peerName":"your-name-goes-here", 65 | "publicKey":"ssxlh80x0bqjfrnbkm1801xsxyd8zd45jkwn1zhlnccqj4hdqun0.k" 66 | } 67 | } 68 | ``` 69 | 70 | ### Naming your entry 71 | 72 | Credential files must end with `.k`. 73 | Otherwise, you can name your file whatever you want, but for simplicity's sake, avoid characters which will need to be escaped at the command line (or within the javascript api). 74 | 75 | ## Javascript API 76 | 77 | Peering credentials in this repository can be accessed via a simple Javascript API (using Nodejs). 78 | 79 | It's available as a module on npm: 80 | 81 | `npm install hyperboria-peers` 82 | 83 | ### Usage 84 | 85 | ```Javascript 86 | var Peers = require("hyperboria-peers"); 87 | 88 | /* return a list of public peers located in North America */ 89 | Peers.filter(function (creds, path) { 90 | return path.indexOf('NA') !== -1; 91 | }); 92 | 93 | /* return a list of public keys */ 94 | Peers.map(function (creds, path) { 95 | return creds[Object.keys(creds)[0]].publicKey; 96 | }); 97 | 98 | /* the underlying data is exposed in a nested json structure */ 99 | console.log(Peers.peers); 100 | 101 | console.log(Peers.peers.na.us.california); 102 | ``` 103 | -------------------------------------------------------------------------------- /af/za/deavmi.md: -------------------------------------------------------------------------------- 1 | "[2a04:5b81:2010::90]:6261": { 2 | "login": "deavmi_links", 3 | "password": "mu1sv9h45w41z47b9lcpl7gr56q38m0", 4 | "publicKey": "qkw11v5yff3tp3sv0dbmmk73lgwwpmcsy0v4mx3gdlmj61yhy7u0.k", 5 | "peerName": "deavmiNode" 6 | } 7 | -------------------------------------------------------------------------------- /as/jp/tokyo.trnsz-jp.k: -------------------------------------------------------------------------------- 1 | { 2 | "139.162.119.37:22237":{ 3 | "contact":"trn on irc.fc00.io", 4 | "login":"default-login", 5 | "password":"x6knr8yqg6620dd0dxf81w7sy1p4723", 6 | "peerName":"trnsz-jp", 7 | "publicKey":"u64fnj4b3s0mcbgf9zfh08qbxh556p8z2z2plw2qp97bpcdg6gf0.k" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /eu/ch/vaud/cjdns.theswissbay.ch: -------------------------------------------------------------------------------- 1 | { 2 | "81.6.2.165:56879":{ 3 | "contact":"gopfertaminomal@theswissbay.ch", 4 | "login":"theswissbay-peering-login", 5 | "password":"rr1lsx8vvxq7m5107gvsn98gc2h2l54", 6 | "peerName":"theswissbay.ch", 7 | "publicKey":"nuvtkly8swgkwsyyjrv89f4y4y0w3x17w61twgsfh9zv1r87h060.k", 8 | "website":"https://theswissbay.ch" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /eu/ch/zurich/0.h.pfactum.k: -------------------------------------------------------------------------------- 1 | { 2 | "140.238.168.104:17122":{ 3 | "contact":"oleksandr@natalenko.name", 4 | "location":"oracle zrh", 5 | "login":"eey6ay0mi3aiwohV2Eequaiciequ2eiz", 6 | "password":"bbfgfh3lgbxw9yr70wmux6jn85h9dcn", 7 | "peerName":"0.h.pfactum.k", 8 | "publicKey":"mz1hh3f7fc8bwrjvsh0rfrrjndspkj8pfdppcxnjcsu4bw7xm410.k" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /eu/de/Frankfurt/h.rwfr.k: -------------------------------------------------------------------------------- 1 | { 2 | "160.20.147.198:53340":{ 3 | "contact":"anticipaste3@gmail.com", 4 | "login":"default-login", 5 | "password":"w6db8n5gb4wtjy0ud32vhql7469g1sb", 6 | "peerName":"h.rwfr.k", 7 | "publicKey":"byxcwmgbhkcgt3vv2820vujbc65szwkn9sj7vk1x3tjdw4q0sc30.k" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /eu/de/Frankfurt/sssemil.k: -------------------------------------------------------------------------------- 1 | { 2 | "45.32.152.232:5078":{ 3 | "contact":"suleymanovemil8@gmail.com", 4 | "login":"default-login", 5 | "password":"v277jzr7r3jgk0vk1389b2c3h0gy98t", 6 | "peerName":"sssemil.k", 7 | "publicKey":"08bz912l989nzqc21q9x5qr96ns465nd71f290hb9q40z94jjw60.k" 8 | }, 9 | "[2001:19f0:6c01:1f4f:5400:03ff:fe2f:dc95]:5078":{ 10 | "contact":"suleymanovemil8@gmail.com", 11 | "login":"default-login", 12 | "password":"v277jzr7r3jgk0vk1389b2c3h0gy98t", 13 | "peerName":"sssemil.k", 14 | "publicKey":"08bz912l989nzqc21q9x5qr96ns465nd71f290hb9q40z94jjw60.k" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /eu/fr/paris/h.totem.tfnux.org.k: -------------------------------------------------------------------------------- 1 | { 2 | "163.172.26.210:27410":{ 3 | "contact":"adraenwan@tfnux.org", 4 | "login":"public-peer", 5 | "password":"ZGZWKOX5H535MG7MRYRKFMF4IY5GFCO5", 6 | "peerName":"h.totem.tfnux.org", 7 | "publicKey":"8bqv77rkzn888mcr8wu3k9b22hpczhn7c0zzyrqpj4bbx8rbf810.k" 8 | }, 9 | "[2001:bc8:2495:100::1]:27410":{ 10 | "contact":"adraenwan@tfnux.org", 11 | "login":"public-peer", 12 | "password":"ZGZWKOX5H535MG7MRYRKFMF4IY5GFCO5", 13 | "peerName":"h.totem.tfnux.org", 14 | "publicKey":"8bqv77rkzn888mcr8wu3k9b22hpczhn7c0zzyrqpj4bbx8rbf810.k" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /eu/fr/paris/h.valdek.ml.k: -------------------------------------------------------------------------------- 1 | { 2 | "51.254.84.52:40504":{ 3 | "contact":"workenergetix(a7)yandex.ru", 4 | "ipv6":"2001:41d0:a:1a3b::49", 5 | "login":"agusha", 6 | "password":"IIYTNH_B3Pb1BAET_D0MA_HA_FEHOBAPBITAG_Bminor_Em_C_D", 7 | "peerName":"valdek.ml", 8 | "publicKey":"fnqfcu85xcxk6s052xzlu5rk68z91qyyf9jtf33cp48f8cuhl4g0.k" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /eu/lt/vilnius/borg.vilnius.lt.k: -------------------------------------------------------------------------------- 1 | { 2 | "185.25.48.153:13109":{ 3 | "contact":"xmpp:borg@xabber.org", 4 | "password":"public", 5 | "peerName":"borg-vilnius", 6 | "publicKey":"pkq30hrl9zyzwn03u6lchh20crfgq46m1dfb5zwfhpx3c6v2l420.k", 7 | "user":"public" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /eu/nl/amsterdam/finlaydag33k.nl.k: -------------------------------------------------------------------------------- 1 | { 2 | "212.187.50.177:62810":{ 3 | "contact":"contact@finlaydag33k.nl", 4 | "login":"meshwithme", 5 | "password":"iwanttomesh", 6 | "peerName":"cjdns-01.finlaydag33k.nl", 7 | "publicKey":"67zwu83kcglutjp18xfhjjc41qn0m5srjc07un0bn4x09uwq1by0.k" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /eu/nl/amsterdam/florianb.ams.k: -------------------------------------------------------------------------------- 1 | { 2 | "146.185.162.175:46398":{ 3 | "contact":"info@florianb.space", 4 | "login":"public", 5 | "password":"meshwithme", 6 | "peerName":"florianb", 7 | "publicKey":"g2xyf69w70q4q2nzfyhs5ybdhpgx0uz56zxqlj27g2ytnklqvxv0.k" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /eu/nl/amsterdam/h.mercury.tfnux.org.k: -------------------------------------------------------------------------------- 1 | { 2 | "51.15.3.66:27410":{ 3 | "contact":"adraenwan@tfnux.org", 4 | "login":"public-peer", 5 | "password":"jkb46blldfp56j3lbm37nj3uj1j72h1", 6 | "peerName":"h.totem.tfnux.org", 7 | "publicKey":"8bqv77rkzn888mcr8wu3k9b22hpczhn7c0zzyrqpj4bbx8rbf810.k" 8 | }, 9 | "[2001:bc8:2495:100::1]:27410":{ 10 | "contact":"adraenwan@tfnux.org", 11 | "login":"public-peer", 12 | "password":"jkb46blldfp56j3lbm37nj3uj1j72h1", 13 | "peerName":"h.totem.tfnux.org", 14 | "publicKey":"8bqv77rkzn888mcr8wu3k9b22hpczhn7c0zzyrqpj4bbx8rbf810.k" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /eu/nl/amsterdam/igel-amersfoort.ams.k: -------------------------------------------------------------------------------- 1 | { 2 | "185.243.112.90:27823":{ 3 | "contact":"Igel@hyperboria.ca", 4 | "gpg":"A84DFFE62B451511", 5 | "password":"alfa-charlie-alfa-bravo", 6 | "peerName":"igel-amersfoort", 7 | "publicKey":"1nctdb89gtfrlnu71zyq97n14frl1r4z0ylwzc8vn7kpvrzu4yl0.k" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /eu/nl/amsterdam/sabsare.geek.k: -------------------------------------------------------------------------------- 1 | { 2 | "163.172.222.21:3111":{ 3 | "contact":"sabsare@disroot.org", 4 | "gpg":"7267 B3AF BBA3 020D DAA9 00DC A4D0 24EC FAEF 0B4D", 5 | "login":"default-login", 6 | "password":"lwmnsu9t63rzfbjj74ttv525s2phq96", 7 | "peerName":"h.sabsare.geek", 8 | "publicKey":"c6x0vfhh88ncz4by4ss3kmf09c7lp5nv9jufs8r3mkcudxfvb9v0.k" 9 | }, 10 | "[2001:bc8:25f0:200::1:f]:8060":{ 11 | "contact":"sabsare@disroot.org", 12 | "gpg":"7267 B3AF BBA3 020D DAA9 00DC A4D0 24EC FAEF 0B4D", 13 | "login":"default-login", 14 | "password":"lwmnsu9t63rzfbjj74ttv525s2phq96", 15 | "peerName":"h.sabsare.geek", 16 | "publicKey":"c6x0vfhh88ncz4by4ss3kmf09c7lp5nv9jufs8r3mkcudxfvb9v0.k" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /eu/no/oslo/hyperboria.hackeriet.no.k: -------------------------------------------------------------------------------- 1 | { 2 | "185.35.202.206:60392":{ 3 | "contact":"nett@hackeriet.no", 4 | "login":"public", 5 | "password":"bKOWX81lA1qHLdi1kxw8qZC1", 6 | "peerName":"hyperboria.hackeriet.no", 7 | "publicKey":"vufgpj15lvfcwu9rk6vg0y14rl1xhg3m491bjlus5zr6bq9llcb0.k" 8 | }, 9 | "[2a02:ed06::206]:60392":{ 10 | "contact":"nett@hackeriet.no", 11 | "login":"public", 12 | "password":"bKOWX81lA1qHLdi1kxw8qZC1", 13 | "peerName":"hyperboria.hackeriet.no", 14 | "publicKey":"vufgpj15lvfcwu9rk6vg0y14rl1xhg3m491bjlus5zr6bq9llcb0.k" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /eu/pl/warsaw/magik6k.net.k: -------------------------------------------------------------------------------- 1 | { 2 | "51.75.35.194:1132":{ 3 | "contact":"me@magik6k.net", 4 | "password":"thah9aePha1Vusha6ovhpublic", 5 | "peerName":"Magik6k-waw-public", 6 | "publicKey":"kw0vfw3tmb6u6p21z5jmmymdlumwknlg3x8muk5mcw66tdpqlw30.k" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /eu/ru/moscow/h.bunjlabs.com.k: -------------------------------------------------------------------------------- 1 | { 2 | "94.142.141.189:50433":{ 3 | "contact":"contact@bunjlabs.com", 4 | "login":"default-login", 5 | "password":"c5q2j63x5nkmt2yg2vjmlnfuh1jnjjf", 6 | "peerName":"h.bunjlabs.com", 7 | "publicKey":"0gdj2xzn01lzjjcrykjvwp8flnxkp1b3jny0drl5b168lmpsmfj0.k" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /eu/ru/moscow/node01.msk.ru-mesh.net.k: -------------------------------------------------------------------------------- 1 | { 2 | "194.67.213.84:24519":{ 3 | "contact":"show.vars@gmail.com", 4 | "login":"default-login", 5 | "password":"37yuffz9hs4lk0wjnvyzj5yx45l444v", 6 | "peerName":"node01.msk.ru-mesh.net", 7 | "publicKey":"9f79752ml0p6glqdnj93352tj3hmctmf8jg8rbgp1wj8mh09lmv0.k" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /eu/ru/novosibirsk/meanmail.k: -------------------------------------------------------------------------------- 1 | { 2 | "91.234.81.181:7485":{ 3 | "contact":"cjdns@meanmail.ru", 4 | "gpg":"82A4C11393800B6AEBC790D2EC1F3EE797AF5FA2", 5 | "login":"default-login", 6 | "password":"zfhb88fzf2lmpb5g2bgju6ps33lfr1c", 7 | "peerName":"meanmail", 8 | "publicKey":"0x3bvhjx0knnq67ruwmz369tuflr8zknkzbx7wgn60s4nujugdk0.k" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /eu/ru/spb/dskrylnikov.k: -------------------------------------------------------------------------------- 1 | { 2 | "95.213.251.59:60246":{ 3 | "contact":"skrylnikov@protonmail.com", 4 | "login":"public", 5 | "password":"public_passwd", 6 | "peerName":"dskrylnikov", 7 | "publicKey":"v0wjlvtkxdu5tr7htymsuytwxtqlrnyjlhk59pw6s11mj4ggw7p0.k" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /eu/ru/spb/ru.spb.tokakoka.k: -------------------------------------------------------------------------------- 1 | { 2 | "91.122.62.105:36510":{ 3 | "contact":"info@tokakoka.ru", 4 | "login":"default-login", 5 | "password":"hf3y45w5hf0ckl8zltldn8pry02lccd", 6 | "peerName":"ru.spb.tokakoka", 7 | "publicKey":"mvds4b1j97zn7uvxyczwsdhmcq5chs561gu0fml7996zvbvpmu00.k" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /eu/se/lulea/bohr.willeponken.me.k: -------------------------------------------------------------------------------- 1 | { 2 | "130.240.202.22:5039":{ 3 | "contact":"william@willeponken.me", 4 | "gpg":"DECA60149478ECFE", 5 | "login":"public-peer", 6 | "password":"zuqcdlv9kj0cvghl4vdx28bcz4vnzf9", 7 | "peerName":"bohr.willeponken.me", 8 | "publicKey":"b83r3fpguqp0w506n1u41dx8wk9kd7shv7ldfy7vxkkxb6h7yjj0.k" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /eu/ua/kiev/h.saloid.ua: -------------------------------------------------------------------------------- 1 | { 2 | "93.175.235.192:48433":{ 3 | "contact":"svetotled@gmail.com", 4 | "login":"saloid", 5 | "password":"w5w3xg1dm46q3qlhrfpqcy20q2skb6u", 6 | "peerName":"h.saloid.ua", 7 | "publicKey":"f9f9n0rn4d11hffvhn9y3grgg1twuqurdtxwmn0skprz510g5w90.k" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /eu/ua/kiev/kiev/ic.hellomouse.cf.k: -------------------------------------------------------------------------------- 1 | { 2 | "185.140.54.19:35907":{ 3 | "contact":"iczero4@gmail.com", 4 | "gpg":"613CE9DA0E9A3F70EC97760E4BAC4EBB8461FC7E", 5 | "login":"public", 6 | "password":"fwlmbx2f3udkd0ymknq4pwwgu2bjklx", 7 | "peerName":"ic.hellomouse.cf", 8 | "publicKey":"gtbfndu2tvfbwuydm7v0kpnqpgcburtymhz3ph9kfrjg4n8bh3j0.k" 9 | }, 10 | "[2a05:dfc7:dfc7:20::1]:35907":{ 11 | "contact":"iczero4@gmail.com", 12 | "gpg":"613CE9DA0E9A3F70EC97760E4BAC4EBB8461FC7E", 13 | "login":"public", 14 | "password":"fwlmbx2f3udkd0ymknq4pwwgu2bjklx", 15 | "peerName":"ic.hellomouse.cf", 16 | "publicKey":"gtbfndu2tvfbwuydm7v0kpnqpgcburtymhz3ph9kfrjg4n8bh3j0.k" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /eu/uk/birmingham/cocolino.fun.k: -------------------------------------------------------------------------------- 1 | { 2 | "82.5.34.168:37144":{ 3 | "contact":"arvamircea@gmail.com", 4 | "gpg":"NULL", 5 | "login":"julian_assange_public", 6 | "password":"qu3r1l25lgqkqspjhms1phclj56tvr5", 7 | "peerName":"Coco's public node", 8 | "publicKey":"3bur7ln0ccbvwwgqjn662ttwuwgyfvsnw3d0h6d1qf8x54cs4m20.k" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /eu/uk/london/cwningen.cymru.k: -------------------------------------------------------------------------------- 1 | { 2 | "44.131.22.1:43022":{ 3 | "contact":"hostmaster@cwningen.cymru", 4 | "login":"public-peer", 5 | "password":"s22z2q6y8fsj28myjlp7yx6gv0wn1q2", 6 | "peerName":"penfar.cwningen.cymru", 7 | "publicKey":"pp6c01cnz51t2vyl1jmzbply1n662c13nm6mzprx0g5djkvl3470.k" 8 | }, 9 | "44.131.22.48:9740":{ 10 | "contact":"hostmaster@cwningen.cymru", 11 | "login":"public-peer", 12 | "password":"6uyxcspqzuxycd1nrwjugmhfh7r2qwd", 13 | "peerName":"traed.cwningen.cymru", 14 | "publicKey":"p8q8bsbvlr3xjh2hqlzyfcgjsk2mjm7fl8s5w73v68925n4f6nb0.k" 15 | }, 16 | "[2001:67c:2990:b00::5d5d:812b]:43022":{ 17 | "contact":"hostmaster@cwningen.cymru", 18 | "login":"public-peer", 19 | "password":"s22z2q6y8fsj28myjlp7yx6gv0wn1q2", 20 | "peerName":"penfar.cwningen.cymru", 21 | "publicKey":"pp6c01cnz51t2vyl1jmzbply1n662c13nm6mzprx0g5djkvl3470.k" 22 | }, 23 | "[2001:67c:2990:f00::5d5d:32fd]:9740":{ 24 | "contact":"hostmaster@cwningen.cymru", 25 | "login":"public-peer", 26 | "password":"6uyxcspqzuxycd1nrwjugmhfh7r2qwd", 27 | "peerName":"traed.cwningen.cymru", 28 | "publicKey":"p8q8bsbvlr3xjh2hqlzyfcgjsk2mjm7fl8s5w73v68925n4f6nb0.k" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var Fs = require("fs"), 2 | Package = require("./package.json"), 3 | version = module.exports.version = Package.version, 4 | Path = require("path"), 5 | DIRNAME = __dirname, 6 | read = function (p) { 7 | var content = Fs.readFileSync(p, 'utf-8'); 8 | if (content.charAt(content.length - 1) !== '\n') { 9 | throw new Error("file at " + p + " did not end with a newline character"); 10 | } 11 | return JSON.parse(content); 12 | }, 13 | P = module.exports.peers = (function () { 14 | var pathFromArray = function (A) { 15 | return A.reduce(function (a, b) { return Path.join(a, b); }, ''); 16 | }; 17 | 18 | var isDir = function (fullPath) { 19 | return Fs.lstatSync(fullPath).isDirectory(); 20 | }; 21 | 22 | var getDir = function (A, f) { 23 | var p = pathFromArray(A); 24 | return Fs.readdirSync(p).filter(function (name) { 25 | var fullPath = pathFromArray([p, name]); 26 | return f(fullPath, A, name); 27 | }); 28 | }; 29 | 30 | var find = function (map, path) { 31 | /* safely search for nested values in an object via a path */ 32 | return (map && path.reduce(function (p, n) { 33 | return typeof p[n] !== 'undefined' && p[n]; 34 | }, map)) || undefined; 35 | } 36 | 37 | var peers = {}; 38 | var walk = function (A) { 39 | getDir(A, function (fullPath, A, name) { 40 | if (/^\./.test(name)) { 41 | // ignore hidden files 42 | } else if (isDir(fullPath)) { 43 | find(peers, A.slice(1))[name] = {}; 44 | walk(A.concat(name)); 45 | } else if (/\.k$/.test(name)) { 46 | var obj = find(peers, A.slice(1))[name] = read(fullPath); 47 | // embed the location in the object 48 | obj.location = A.slice(1); 49 | } 50 | }); 51 | }; 52 | 53 | walk([DIRNAME]); 54 | return peers; 55 | }()), 56 | map = module.exports.map = function (f) { 57 | var L = []; 58 | 59 | // t/f is the object a credential 60 | var isCred = function (k) { 61 | // creds end in .k 62 | return /\.k/.test(k); 63 | }; 64 | 65 | var walk = function (o, p, f) { 66 | // walk the tree of objects 67 | 68 | if (typeof(o) === 'object') { 69 | // for each key in o, walk the key 70 | Object.keys(o).forEach(function (k) { 71 | var path = p.slice(0).concat(k); 72 | 73 | if (isCred(k)) { 74 | L.push(f(o[k], path)); 75 | } 76 | walk(o[k], path, f); 77 | }); 78 | } 79 | }; 80 | 81 | walk(P, [], f); 82 | return L; 83 | }, 84 | filter = module.exports.filter = function (f) { 85 | var L = []; 86 | map(function (x, p) { 87 | if (f(x,p)) { L.push(x); } 88 | }); 89 | return L; 90 | }; 91 | 92 | -------------------------------------------------------------------------------- /na/ca/ontario/kusoneko.moe.k: -------------------------------------------------------------------------------- 1 | { 2 | "137.220.55.93:32307":{ 3 | "contact":"kusoneko@kusoneko.moe", 4 | "gpg":"5F580A604D06074DF62435268FDECBBC178C72E1", 5 | "location":"toronto", 6 | "login":"public-peer", 7 | "password":"242yl4g4nmu0rygusyhxu9xd13lrhuj", 8 | "peerName":"kusoneko.moe", 9 | "publicKey":"nvl82112jgj26sgv6r7sbuqc7wh1n7w1stsj327lbcu8n2yycf20.k" 10 | }, 11 | "[2001:19f0:b001:379:5400:3ff:fe68:1cc6]:32307":{ 12 | "contact":"kusoneko@kusoneko.moe", 13 | "gpg":"5F580A604D06074DF62435268FDECBBC178C72E1", 14 | "location":"toronto", 15 | "login":"public-peer", 16 | "password":"242yl4g4nmu0rygusyhxu9xd13lrhuj", 17 | "peerName":"kusoneko.moe", 18 | "publicKey":"nvl82112jgj26sgv6r7sbuqc7wh1n7w1stsj327lbcu8n2yycf20.k" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /na/ca/ontario/linux1.tor1.watters.ws.k: -------------------------------------------------------------------------------- 1 | { 2 | "165.227.44.84:34838":{ 3 | "contact":"wattersm@watters.ws", 4 | "gpg":"E2A3328281D1DA0A08D34FC2058F0C51586CA8C6", 5 | "location":"Digital Ocean tor1", 6 | "login":"public-access", 7 | "password":"8n2w2qu2lfndhgx8xwgp18vyq7fhvux", 8 | "peerName":"linux1.tor1.watters.ws", 9 | "publicKey":"b465hml7z3g1vj22ktqdrc3z17mwjxl44cg0mj903n9vycxzqpv0.k" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /na/ca/ontario/stash-crypto.k: -------------------------------------------------------------------------------- 1 | { 2 | "149.56.19.79:55159":{ 3 | "contact":"infrastructure@stashcrypto.com", 4 | "login":"default-login", 5 | "password":"dgv86ktpblc2h4y93fsqpshcg2lbp5d", 6 | "peerName":"git.stashcrypto.net", 7 | "publicKey":"zbfurpx9n6whzwu6vrlfgmw8g56rmchfmhxxtpg0hwhl84vqf1y0.k" 8 | }, 9 | "158.69.119.35:9218":{ 10 | "contact":"infrastructure@stashcrypto.com", 11 | "login":"default-login", 12 | "password":"w5huch4mn6tkgfp3j9sr8p8r13j3j33", 13 | "peerName":"seed.stashcrypto.net", 14 | "publicKey":"rzg61b3fsb675732g5rn8g1x61ypm1z7402n072qmrbbhgzm93f0.k" 15 | }, 16 | "[2607:5300:61:44f::]:55159":{ 17 | "contact":"infrastructure@stashcrypto.com", 18 | "login":"default-login", 19 | "password":"dgv86ktpblc2h4y93fsqpshcg2lbp5d", 20 | "peerName":"git.stashcrypto.net", 21 | "publicKey":"zbfurpx9n6whzwu6vrlfgmw8g56rmchfmhxxtpg0hwhl84vqf1y0.k" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /na/ca/quebec/beauharnois/larynx.ventricle.us.k: -------------------------------------------------------------------------------- 1 | { 2 | "149.56.98.167:3703":{ 3 | "contact":"code@ventricle.us", 4 | "gpg":"7FE895160E3314027CD3B5D37392CF088BB4345C", 5 | "location":"ovh beauharnois", 6 | "login":"public-peer", 7 | "password":"ppm6j89mgvss7uvtntcd9scy6166mwb", 8 | "peerName":"larynx.ventricle.us", 9 | "publicKey":"jg035j9hup776kwz1k4n0bwpggxp1qmts6t715x53g8vutxktzz0.k" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /na/us/california/computer-pig.k: -------------------------------------------------------------------------------- 1 | { 2 | "97.90.35.107:55602":{ 3 | "contact":"happysmash27@protonmail.com", 4 | "gpg":"1567396F2C90D234", 5 | "login":"default-login", 6 | "password":"4w386mlblb5rgypmh79gpft1l6vywj8", 7 | "peerName":"computer-pig", 8 | "publicKey":"fgyf3hnrygwlud6xp92n4q2b2h7qsghkmrrvcscrcmj7qb00c8s0.k" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /na/us/california/igel-california.usa.k: -------------------------------------------------------------------------------- 1 | { 2 | "192.169.7.142:14400":{ 3 | "contact":"Igel@hyperboria.ca", 4 | "gpg":"A84DFFE62B451511", 5 | "password":"alfa-charlie-alfa-bravo", 6 | "peerName":"igel-losangeles", 7 | "publicKey":"mh9m0411cfcg7xhdc8n6ckls1tjgnvvbdfzdgqf5196tfkw96rr0.k" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /na/us/california/orange-county/yk3music.k: -------------------------------------------------------------------------------- 1 | { 2 | "68.96.83.151:60405":{ 3 | "contact":"contact@yk3music.com", 4 | "ipfs":"/tcp/4001/ipfs/QmZEiPvrfZHapq4uiyTDEcR2szCUhDnjdS4q3Uv2b1Uh88", 5 | "ipv6":"fcbb:1db3:54fb:e519:d915:d7db:4893:4f30", 6 | "organization":"Yk3 Music", 7 | "password":"98b31ngx6mw2zcd4jwqycrkcp7jnc31", 8 | "peerName":"yk3music-irvine", 9 | "publicKey":"kllz76rusmyk3748yz3tgnv9xhtv08nd2nss31fjuwkgwf9hvys0.k" 10 | }, 11 | "[2600:8802:2600:6b9:2c1a:7ece:f34a:a61a]:60405":{ 12 | "contact":"contact@yk3music.com", 13 | "ipfs":"/tcp/4001/ipfs/QmZEiPvrfZHapq4uiyTDEcR2szCUhDnjdS4q3Uv2b1Uh88", 14 | "ipv6":"fcbb:1db3:54fb:e519:d915:d7db:4893:4f30", 15 | "organization":"Yk3 Music", 16 | "password":"98b31ngx6mw2zcd4jwqycrkcp7jnc31", 17 | "peerName":"yk3music-irvine", 18 | "publicKey":"kllz76rusmyk3748yz3tgnv9xhtv08nd2nss31fjuwkgwf9hvys0.k" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /na/us/massachusetts/igel-massachusetts.usa.k: -------------------------------------------------------------------------------- 1 | { 2 | "192.34.85.155:2359":{ 3 | "contact":"Igel@hyperboria.ca", 4 | "gpg":"A84DFFE62B451511", 5 | "password":"alfa-charlie-alfa-bravo", 6 | "peerName":"igel-boston", 7 | "publicKey":"rdxg1nzvmjdj4fyguqydmnl659p7m3x26r6un4ql966q4xt988j0.k" 8 | }, 9 | "[2602:ff65:0:1::fc00]:2359":{ 10 | "contact":"Igel@hyperboria.ca", 11 | "gpg":"A84DFFE62B451511", 12 | "password":"alfa-charlie-alfa-bravo", 13 | "peerName":"igel-boston", 14 | "publicKey":"rdxg1nzvmjdj4fyguqydmnl659p7m3x26r6un4ql966q4xt988j0.k" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /na/us/newyork/cord.ventricle.us.k: -------------------------------------------------------------------------------- 1 | { 2 | "107.170.57.34:63472":{ 3 | "contact":"code@ventricle.us", 4 | "gpg":"7FE895160E3314027CD3B5D37392CF088BB4345C", 5 | "location":"digitalocean nyc2", 6 | "login":"public-peer", 7 | "password":"ppm6j89mgvss7uvtntcd9scy6166mwb", 8 | "peerName":"cord.ventricle.us", 9 | "publicKey":"1xkf13m9r9h502yuffsq1cg13s5648bpxrtf2c3xcq1mlj893s90.k" 10 | }, 11 | "[2604:a880:0:1010::f:4001]:63472":{ 12 | "contact":"code@ventricle.us", 13 | "gpg":"7FE895160E3314027CD3B5D37392CF088BB4345C", 14 | "location":"digitalocean nyc2", 15 | "login":"public-peer", 16 | "password":"ppm6j89mgvss7uvtntcd9scy6166mwb", 17 | "peerName":"cord.ventricle.us", 18 | "publicKey":"1xkf13m9r9h502yuffsq1cg13s5648bpxrtf2c3xcq1mlj893s90.k" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /na/us/northcarolina/charlotte/ic2.hellomouse.cf.k: -------------------------------------------------------------------------------- 1 | { 2 | "185.140.54.73:30800":{ 3 | "contact":"iczero4@gmail.com", 4 | "gpg":"613CE9DA0E9A3F70EC97760E4BAC4EBB8461FC7E", 5 | "login":"public", 6 | "password":"fwlmbx2f3udkd0ymknq4pwwgu2bjklx", 7 | "peerName":"ic2.hellomouse.cf", 8 | "publicKey":"c15sfmskdpmj2qw5lfvgfuzggyyk1bjzj4lu3yf6h1x2ckclwdd0.k" 9 | }, 10 | "[2a05:dfc7:dfc8:1d3::1]:30800":{ 11 | "contact":"iczero4@gmail.com", 12 | "gpg":"613CE9DA0E9A3F70EC97760E4BAC4EBB8461FC7E", 13 | "login":"public", 14 | "password":"fwlmbx2f3udkd0ymknq4pwwgu2bjklx", 15 | "peerName":"ic2.hellomouse.cf", 16 | "publicKey":"c15sfmskdpmj2qw5lfvgfuzggyyk1bjzj4lu3yf6h1x2ckclwdd0.k" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /na/us/pennsylvania/nat.usa.k: -------------------------------------------------------------------------------- 1 | { 2 | "173.62.245.186:55249":{ 3 | "contact":"natebrune@gmail.com", 4 | "country":"us", 5 | "gpg":"C95CE6BC6735BAD7", 6 | "ipv6":"fcda:9958:9093:49f2:2677:6df6:2a5a:b01d", 7 | "password":"Public", 8 | "peerName":"NAT", 9 | "publicKey":"vgxqyputh4ldhxktg9msmr61pw938l0ymhkmryljsyzvmr0dtwy0.k", 10 | "website":"https://github.com/NateBrune" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /na/us/texas/dallas.trnsz.k: -------------------------------------------------------------------------------- 1 | { 2 | "198.58.100.240:22237":{ 3 | "contact":"jhj@trnsz.com", 4 | "login":"default-login", 5 | "password":"pqr5brz16vzzu6vhjuj7tv3n078kr5f", 6 | "peerName":"trnsz", 7 | "publicKey":"ubbtkp0txwjh44v8kkznvhjqqwr1hd2jzv5ms9zlkfk25svxvtg0.k" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hyperboria-peers", 3 | "version": "1.0.36", 4 | "description": "A geographically sorted list of public peering credentials for joining Hyperboria", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "node tests.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/hyperboria/peers.git" 12 | }, 13 | "keywords": [ 14 | "hyperboria", 15 | "fc00", 16 | "public", 17 | "peers" 18 | ], 19 | "author": "ansuz", 20 | "license": "AGPL-3.0", 21 | "bugs": { 22 | "url": "https://github.com/hyperboria/peers/issues" 23 | }, 24 | "homepage": "https://github.com/hyperboria/peers#readme" 25 | } 26 | -------------------------------------------------------------------------------- /sa/br/saopaulo/sp.yetanothernerd.xyz.k: -------------------------------------------------------------------------------- 1 | { 2 | "45.231.133.188:63319":{ 3 | "contact":"yangm97@gmail.com", 4 | "gpg":"CC7D230C1C6ED7E2", 5 | "login":"public", 6 | "password":"40wr3r9l3l5f2p812mzy5bdd80xjb6k", 7 | "peerName":"h.sp.yetanothernerd.xyz", 8 | "publicKey":"9jjq45h13t7fdq2t8tdf59p6cplnv8un35dhmwjf032wmf3340w0.k" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /testAvailable.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Ping nodes and show unavailable.""" 3 | import json 4 | import os 5 | import sys 6 | import subprocess 7 | 8 | RED = '\x1b[01;31m' 9 | GREEN = '\x1b[01;32m' 10 | YELLOW = '\x1b[01;33m' 11 | END = '\x1b[0m' 12 | 13 | 14 | def validate(path): 15 | """Test a single set of peering creds.""" 16 | result = True 17 | print("Pinging %s" % path) 18 | try: 19 | with open(path) as f: 20 | for host in json.loads(f.read()): 21 | if host[0] == '[': continue 22 | ipv4 = host.split(':')[0] 23 | res = subprocess.call(['ping', '-c3', '-W5', ipv4], stdout=subprocess.DEVNULL) 24 | if res: 25 | print(" %s%s is failed%s" % (RED, ipv4, END)) 26 | result = False 27 | else: 28 | print(" %s%s is ok%s" % (GREEN, ipv4, END)) 29 | except ValueError: 30 | print(" %sInvalid JSON!%s" % (RED, END)) 31 | result = False 32 | except KeyboardInterrupt: 33 | print(" %sInterrupt%s" % (RED, END)) 34 | sys.exit(1) 35 | return result 36 | 37 | if __name__ == "__main__": 38 | success = True 39 | for directory, subdirs, files in os.walk('.'): 40 | if len(files) > 0: 41 | if directory != '.' and not directory.startswith('./.git'): 42 | for f in files: 43 | result = validate("%s/%s" % (directory, f)) 44 | if not result: 45 | success = False 46 | if not success: 47 | sys.exit(1) 48 | -------------------------------------------------------------------------------- /tests.js: -------------------------------------------------------------------------------- 1 | /* 2 | if any of the supplied credentials: 3 | * are invalid JSON 4 | * do not end with a newline character, 5 | 6 | this file will not even load because index.js will throw errors 7 | */ 8 | 9 | var Peers = require("./index"); 10 | 11 | var isIp = function (host) { 12 | return ([ 13 | /^[\[\]0-9a-f:]*$/i, // ipv6 14 | /^[0-9\.:]*$/, // ipv4 15 | ].some(function (patt) { 16 | return patt.test(host); 17 | })); 18 | }; 19 | 20 | var credsWithDns = Peers.filter(function (x, p) { 21 | return Object.keys(x).some(function (k) { 22 | if (Array.isArray(x[k])) { return; } 23 | return !isIp(k); 24 | }); 25 | }); 26 | 27 | /* Credentials should use IPs, not dns hostnames */ 28 | if (credsWithDns.length) { 29 | console.log("The following peers are using DNS hostnames instead of IPs"); 30 | console.log(credsWithDns); 31 | } 32 | 33 | /* Credentials must have the required fields: 34 | * ip/port ✓ 35 | * password 36 | * publicKey 37 | * contact 38 | */ 39 | 40 | var requiredFields = ['password', 'publicKey', 'contact', 'peerName']; 41 | var recommendedFields = ['gpg', 'peerName']; 42 | 43 | var insufficientFields = Peers.filter(function (x, p) { 44 | var problem = false; 45 | var comment = false; 46 | 47 | var path = '/' + p.join('/'); 48 | 49 | var requiredMsg = "[%s] => %s is missing the required field '%s'"; 50 | var recommendedMsg = "[%s] => '%s' is missing the recommended field '%s'"; 51 | Object.keys(x).forEach(function (k) { 52 | if (Array.isArray(x[k])) { return; } 53 | 54 | 55 | var cred = x[k]; 56 | var fields = Object.keys(cred); 57 | 58 | recommendedFields.forEach(function (field) { 59 | if (typeof(cred[field]) !== 'undefined') { return; } 60 | console.log(recommendedMsg, path, k, field); 61 | comment = true; 62 | problem = true; 63 | }); 64 | 65 | requiredFields.forEach(function (field) { 66 | if (typeof(cred[field]) !== 'undefined') { return; } 67 | console.error(requiredMsg, path, k, field); 68 | problem = true; 69 | }) 70 | }); 71 | 72 | //if (comment || problem) { console.log(); } 73 | return problem; 74 | }); 75 | 76 | if (insufficientFields.length) { 77 | //console.log("The following peers did not have all the required fields"); 78 | //console.log(insufficientFields); 79 | } 80 | 81 | -------------------------------------------------------------------------------- /tests.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Checks that the peering details in this repo conform to a few basic rules.""" 3 | import json 4 | import os 5 | import sys 6 | 7 | REQUIRED_FIELDS = ['publicKey', 'password', 'contact', 'peerName'] 8 | RECOMMENDED_FIELDS = ['gpg', 'login'] 9 | 10 | RED = '\x1b[01;31m' 11 | GREEN = '\x1b[01;32m' 12 | YELLOW = '\x1b[01;33m' 13 | END = '\x1b[0m' 14 | 15 | 16 | def validate(path): 17 | """Test a single set of peering creds.""" 18 | print("Validating %s" % path) 19 | try: 20 | creds = open(path).read() 21 | peers = json.loads(creds) 22 | # Check formatting 23 | pretty = json.dumps(peers, sort_keys=True, indent=4, separators=(',', ':')) 24 | pretty = "%s\n" % pretty 25 | formatting = True 26 | if pretty != creds: 27 | if "--clean" in sys.argv: 28 | with open(path, 'w') as outfile: 29 | outfile.write(pretty) 30 | print(" %sJSON in %s has been fixed.%s" % (YELLOW, path, END)) 31 | else: 32 | print(" %sJSON in %s is NOT properly formatted! This is really easy to fix!" 33 | " just run tests.py --clean.%s" % (YELLOW, path, END)) 34 | formatting = False 35 | hosts = peers.keys() 36 | for host in hosts: 37 | for field in REQUIRED_FIELDS: 38 | if field not in peers[host]: 39 | print(" %sHost %s is missing the required field %s%s" % (RED, host, 40 | field, END)) 41 | return False 42 | for field in RECOMMENDED_FIELDS: 43 | if field not in peers[host]: 44 | print(" %sHost %s is missing the recommended field %s%s" % (YELLOW, host, 45 | field, END)) 46 | if formatting: 47 | return True 48 | else: 49 | return False 50 | except ValueError: 51 | print(" %sInvalid JSON!%s" % (RED, END)) 52 | return False 53 | 54 | if __name__ == "__main__": 55 | success = True 56 | for directory, subdirs, files in os.walk('.'): 57 | if len(files) > 0: 58 | if directory != '.' and not directory.startswith('./.git'): 59 | for f in files: 60 | result = validate("%s/%s" % (directory, f)) 61 | if not result: 62 | success = False 63 | if not success: 64 | sys.exit(1) 65 | --------------------------------------------------------------------------------