diff --git a/README.md b/README.md index d40a24a..d2b2de9 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,9 @@
-`sks-lib` is a Typescript library for interacting with SKS keyservers. Currently there's only support for retrieving a keyserver's stats. +`sks-lib` is a Typescript library for interacting with SKS keyservers. Currently there's support for looking up keys, uploading keys and retrieving statistics of a keyserver. + +*Please note that keyservers never return verified data. Do **not** trust the retrieved keys and **always verify** them.* ## Installation @@ -24,44 +26,39 @@ Just add it with `yarn install sks-lib` (or `npm install sks-lib`) to your project. It ships the generated Javascript code along with Typescript's declaration files. The Typescript code itself lives in `lib/`. -## Example usage +## Usage ```ts -import {Keyserver} from 'sks-lib'; -import {Moment} from 'moment'; +// Create a new keyserver object to query on +var keyserver = new Keyserver('keyserver.ntzwrk.org'); +var somePublicKey: string; -var keyserver = new Keyserver('keyserver.ntzwrk.org'); +// Lookup the key for "vsund" and then print it +keyserver.lookup('vsund').then( + (key) => { + somePublicKey = key; + console.log(key); + } +); +// Upload the previously fetched key and print the server's response +keyserver.upload(publicKey).then( + (response) => { + console.log(response); + } +); + +// Get stats and then print some information keyserver.getStats().then( (stats) => { - var hostName = stats.hostName; - var software = stats.software; - var version = stats.version; - var peerCount = stats.gossipPeerCount; - - console.log('"%s" is a %s %s keyserver with %s gossip peers.', hostName, software, version, peerCount); + console.log('"%s" is a %s keyserver on version %s.', stats.hostName, stats.software, stats.version); } -).catch((reason: Error) => { - console.log('Could not connect to "%s:11371"', keyserver.hostName); - console.log('%s: %s', reason.name, reason.message); -}); - -keyserver.getKeyStats().then( - (keyStats) => { - var hostName = keyserver.hostName; - var totalKeys = keyStats.totalKeys; - var newKeys = keyStats.dailyKeys[11].newKeys; - var date = keyStats.dailyKeys[11].dateTime.format('MMMM Do YYYY'); - - console.log('"%s" has %s total keys and saw %s new keys on %s.', hostName, totalKeys, newKeys, date); - } -).catch((reason: Error) => { - console.log('Could not connect to "%s:11371"', keyserver.hostName); - console.log('%s: %s', reason.name, reason.message); -}); +); ``` +See [`examples/`](examples/) for some more examples. + ## Documentation diff --git a/docs/code/assets/js/search.js b/docs/code/assets/js/search.js index cb547be..4e1a928 100644 --- a/docs/code/assets/js/search.js +++ b/docs/code/assets/js/search.js @@ -1,3 +1,3 @@ -var typedoc = typedoc || {}; +var typedoc = typedoc || {}; typedoc.search = typedoc.search || {}; - typedoc.search.data = {"kinds":{"1":"External module","128":"Class","512":"Constructor","1024":"Property","2048":"Method"},"rows":[{"id":0,"kind":1,"name":"\"KeyStats\"","url":"modules/_keystats_.html","classes":"tsd-kind-external-module"},{"id":1,"kind":128,"name":"KeyStats","url":"classes/_keystats_.keystats.html","classes":"tsd-kind-class tsd-parent-kind-external-module","parent":"\"KeyStats\""},{"id":2,"kind":1024,"name":"totalKeys","url":"classes/_keystats_.keystats.html#totalkeys","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"KeyStats\".KeyStats"},{"id":3,"kind":1024,"name":"dailyKeys","url":"classes/_keystats_.keystats.html#dailykeys","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"KeyStats\".KeyStats"},{"id":4,"kind":1024,"name":"hourlyKeys","url":"classes/_keystats_.keystats.html#hourlykeys","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"KeyStats\".KeyStats"},{"id":5,"kind":512,"name":"constructor","url":"classes/_keystats_.keystats.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"\"KeyStats\".KeyStats"},{"id":6,"kind":128,"name":"KeyStatsEntry","url":"classes/_keystats_.keystatsentry.html","classes":"tsd-kind-class tsd-parent-kind-external-module","parent":"\"KeyStats\""},{"id":7,"kind":1024,"name":"dateTime","url":"classes/_keystats_.keystatsentry.html#datetime","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"KeyStats\".KeyStatsEntry"},{"id":8,"kind":1024,"name":"newKeys","url":"classes/_keystats_.keystatsentry.html#newkeys","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"KeyStats\".KeyStatsEntry"},{"id":9,"kind":1024,"name":"updatedKeys","url":"classes/_keystats_.keystatsentry.html#updatedkeys","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"KeyStats\".KeyStatsEntry"},{"id":10,"kind":512,"name":"constructor","url":"classes/_keystats_.keystatsentry.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"\"KeyStats\".KeyStatsEntry"},{"id":11,"kind":1,"name":"\"ParseError\"","url":"modules/_parseerror_.html","classes":"tsd-kind-external-module"},{"id":12,"kind":128,"name":"ParseError","url":"classes/_parseerror_.parseerror.html","classes":"tsd-kind-class tsd-parent-kind-external-module","parent":"\"ParseError\""},{"id":13,"kind":512,"name":"constructor","url":"classes/_parseerror_.parseerror.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"\"ParseError\".ParseError"},{"id":14,"kind":1024,"name":"name","url":"classes/_parseerror_.parseerror.html#name","classes":"tsd-kind-property tsd-parent-kind-class tsd-is-inherited tsd-is-static","parent":"\"ParseError\".ParseError"},{"id":15,"kind":1024,"name":"message","url":"classes/_parseerror_.parseerror.html#message","classes":"tsd-kind-property tsd-parent-kind-class tsd-is-inherited tsd-is-static","parent":"\"ParseError\".ParseError"},{"id":16,"kind":1024,"name":"stack","url":"classes/_parseerror_.parseerror.html#stack","classes":"tsd-kind-property tsd-parent-kind-class tsd-is-overwrite tsd-is-inherited tsd-is-static","parent":"\"ParseError\".ParseError"},{"id":17,"kind":1024,"name":"Error","url":"classes/_parseerror_.parseerror.html#error","classes":"tsd-kind-property tsd-parent-kind-class tsd-is-static","parent":"\"ParseError\".ParseError"},{"id":18,"kind":1,"name":"\"Peer\"","url":"modules/_peer_.html","classes":"tsd-kind-external-module"},{"id":19,"kind":128,"name":"GossipPeer","url":"classes/_peer_.gossippeer.html","classes":"tsd-kind-class tsd-parent-kind-external-module","parent":"\"Peer\""},{"id":20,"kind":1024,"name":"host","url":"classes/_peer_.gossippeer.html#host","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Peer\".GossipPeer"},{"id":21,"kind":1024,"name":"port","url":"classes/_peer_.gossippeer.html#port","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Peer\".GossipPeer"},{"id":22,"kind":512,"name":"constructor","url":"classes/_peer_.gossippeer.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"\"Peer\".GossipPeer"},{"id":23,"kind":128,"name":"MailsyncPeer","url":"classes/_peer_.mailsyncpeer.html","classes":"tsd-kind-class tsd-parent-kind-external-module","parent":"\"Peer\""},{"id":24,"kind":1024,"name":"address","url":"classes/_peer_.mailsyncpeer.html#address","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Peer\".MailsyncPeer"},{"id":25,"kind":512,"name":"constructor","url":"classes/_peer_.mailsyncpeer.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"\"Peer\".MailsyncPeer"},{"id":26,"kind":1,"name":"\"Stats\"","url":"modules/_stats_.html","classes":"tsd-kind-external-module"},{"id":27,"kind":128,"name":"Stats","url":"classes/_stats_.stats.html","classes":"tsd-kind-class tsd-parent-kind-external-module","parent":"\"Stats\""},{"id":28,"kind":1024,"name":"software","url":"classes/_stats_.stats.html#software","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":29,"kind":1024,"name":"version","url":"classes/_stats_.stats.html#version","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":30,"kind":1024,"name":"hostName","url":"classes/_stats_.stats.html#hostname","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":31,"kind":1024,"name":"nodeName","url":"classes/_stats_.stats.html#nodename","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":32,"kind":1024,"name":"serverContact","url":"classes/_stats_.stats.html#servercontact","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":33,"kind":1024,"name":"httpPort","url":"classes/_stats_.stats.html#httpport","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":34,"kind":1024,"name":"reconPort","url":"classes/_stats_.stats.html#reconport","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":35,"kind":1024,"name":"debugLevel","url":"classes/_stats_.stats.html#debuglevel","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":36,"kind":1024,"name":"keys","url":"classes/_stats_.stats.html#keys","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":37,"kind":1024,"name":"statsTime","url":"classes/_stats_.stats.html#statstime","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":38,"kind":1024,"name":"gossipPeers","url":"classes/_stats_.stats.html#gossippeers","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":39,"kind":1024,"name":"gossipPeerCount","url":"classes/_stats_.stats.html#gossippeercount","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":40,"kind":1024,"name":"mailsyncPeers","url":"classes/_stats_.stats.html#mailsyncpeers","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":41,"kind":1024,"name":"mailsyncPeerCount","url":"classes/_stats_.stats.html#mailsyncpeercount","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":42,"kind":512,"name":"constructor","url":"classes/_stats_.stats.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":43,"kind":1,"name":"\"Keyserver\"","url":"modules/_keyserver_.html","classes":"tsd-kind-external-module"},{"id":44,"kind":128,"name":"Keyserver","url":"classes/_keyserver_.keyserver.html","classes":"tsd-kind-class tsd-parent-kind-external-module","parent":"\"Keyserver\""},{"id":45,"kind":1024,"name":"hostName","url":"classes/_keyserver_.keyserver.html#hostname","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Keyserver\".Keyserver"},{"id":46,"kind":1024,"name":"port","url":"classes/_keyserver_.keyserver.html#port","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Keyserver\".Keyserver"},{"id":47,"kind":1024,"name":"statsHtml","url":"classes/_keyserver_.keyserver.html#statshtml","classes":"tsd-kind-property tsd-parent-kind-class tsd-is-private","parent":"\"Keyserver\".Keyserver"},{"id":48,"kind":512,"name":"constructor","url":"classes/_keyserver_.keyserver.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"\"Keyserver\".Keyserver"},{"id":49,"kind":2048,"name":"getStatsHtml","url":"classes/_keyserver_.keyserver.html#getstatshtml","classes":"tsd-kind-method tsd-parent-kind-class tsd-is-private","parent":"\"Keyserver\".Keyserver"},{"id":50,"kind":2048,"name":"mapToView","url":"classes/_keyserver_.keyserver.html#maptoview","classes":"tsd-kind-method tsd-parent-kind-class tsd-has-type-parameter","parent":"\"Keyserver\".Keyserver"},{"id":51,"kind":2048,"name":"getStats","url":"classes/_keyserver_.keyserver.html#getstats","classes":"tsd-kind-method tsd-parent-kind-class","parent":"\"Keyserver\".Keyserver"},{"id":52,"kind":2048,"name":"getKeyStats","url":"classes/_keyserver_.keyserver.html#getkeystats","classes":"tsd-kind-method tsd-parent-kind-class","parent":"\"Keyserver\".Keyserver"},{"id":53,"kind":2048,"name":"parseStatsHtml","url":"classes/_keyserver_.keyserver.html#parsestatshtml","classes":"tsd-kind-method tsd-parent-kind-class tsd-is-static","parent":"\"Keyserver\".Keyserver"},{"id":54,"kind":2048,"name":"parseKeyStatsHtml","url":"classes/_keyserver_.keyserver.html#parsekeystatshtml","classes":"tsd-kind-method tsd-parent-kind-class tsd-is-static","parent":"\"Keyserver\".Keyserver"},{"id":55,"kind":1,"name":"\"index\"","url":"modules/_index_.html","classes":"tsd-kind-external-module"}]}; \ No newline at end of file + typedoc.search.data = {"kinds":{"1":"External module","128":"Class","512":"Constructor","1024":"Property","2048":"Method"},"rows":[{"id":0,"kind":1,"name":"\"Errors\"","url":"modules/_errors_.html","classes":"tsd-kind-external-module"},{"id":1,"kind":128,"name":"NoKeyFoundError","url":"classes/_errors_.nokeyfounderror.html","classes":"tsd-kind-class tsd-parent-kind-external-module","parent":"\"Errors\""},{"id":2,"kind":512,"name":"constructor","url":"classes/_errors_.nokeyfounderror.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"\"Errors\".NoKeyFoundError"},{"id":3,"kind":1024,"name":"name","url":"classes/_errors_.nokeyfounderror.html#name","classes":"tsd-kind-property tsd-parent-kind-class tsd-is-inherited tsd-is-static","parent":"\"Errors\".NoKeyFoundError"},{"id":4,"kind":1024,"name":"message","url":"classes/_errors_.nokeyfounderror.html#message","classes":"tsd-kind-property tsd-parent-kind-class tsd-is-inherited tsd-is-static","parent":"\"Errors\".NoKeyFoundError"},{"id":5,"kind":1024,"name":"stack","url":"classes/_errors_.nokeyfounderror.html#stack","classes":"tsd-kind-property tsd-parent-kind-class tsd-is-overwrite tsd-is-inherited tsd-is-static","parent":"\"Errors\".NoKeyFoundError"},{"id":6,"kind":1024,"name":"Error","url":"classes/_errors_.nokeyfounderror.html#error","classes":"tsd-kind-property tsd-parent-kind-class tsd-is-static","parent":"\"Errors\".NoKeyFoundError"},{"id":7,"kind":128,"name":"ParseError","url":"classes/_errors_.parseerror.html","classes":"tsd-kind-class tsd-parent-kind-external-module","parent":"\"Errors\""},{"id":8,"kind":512,"name":"constructor","url":"classes/_errors_.parseerror.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"\"Errors\".ParseError"},{"id":9,"kind":1024,"name":"name","url":"classes/_errors_.parseerror.html#name","classes":"tsd-kind-property tsd-parent-kind-class tsd-is-inherited tsd-is-static","parent":"\"Errors\".ParseError"},{"id":10,"kind":1024,"name":"message","url":"classes/_errors_.parseerror.html#message","classes":"tsd-kind-property tsd-parent-kind-class tsd-is-inherited tsd-is-static","parent":"\"Errors\".ParseError"},{"id":11,"kind":1024,"name":"stack","url":"classes/_errors_.parseerror.html#stack","classes":"tsd-kind-property tsd-parent-kind-class tsd-is-overwrite tsd-is-inherited tsd-is-static","parent":"\"Errors\".ParseError"},{"id":12,"kind":1024,"name":"Error","url":"classes/_errors_.parseerror.html#error","classes":"tsd-kind-property tsd-parent-kind-class tsd-is-static","parent":"\"Errors\".ParseError"},{"id":13,"kind":1,"name":"\"KeyStats\"","url":"modules/_keystats_.html","classes":"tsd-kind-external-module"},{"id":14,"kind":128,"name":"KeyStats","url":"classes/_keystats_.keystats.html","classes":"tsd-kind-class tsd-parent-kind-external-module","parent":"\"KeyStats\""},{"id":15,"kind":1024,"name":"totalKeys","url":"classes/_keystats_.keystats.html#totalkeys","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"KeyStats\".KeyStats"},{"id":16,"kind":1024,"name":"dailyKeys","url":"classes/_keystats_.keystats.html#dailykeys","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"KeyStats\".KeyStats"},{"id":17,"kind":1024,"name":"hourlyKeys","url":"classes/_keystats_.keystats.html#hourlykeys","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"KeyStats\".KeyStats"},{"id":18,"kind":512,"name":"constructor","url":"classes/_keystats_.keystats.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"\"KeyStats\".KeyStats"},{"id":19,"kind":128,"name":"KeyStatsEntry","url":"classes/_keystats_.keystatsentry.html","classes":"tsd-kind-class tsd-parent-kind-external-module","parent":"\"KeyStats\""},{"id":20,"kind":1024,"name":"dateTime","url":"classes/_keystats_.keystatsentry.html#datetime","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"KeyStats\".KeyStatsEntry"},{"id":21,"kind":1024,"name":"newKeys","url":"classes/_keystats_.keystatsentry.html#newkeys","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"KeyStats\".KeyStatsEntry"},{"id":22,"kind":1024,"name":"updatedKeys","url":"classes/_keystats_.keystatsentry.html#updatedkeys","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"KeyStats\".KeyStatsEntry"},{"id":23,"kind":512,"name":"constructor","url":"classes/_keystats_.keystatsentry.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"\"KeyStats\".KeyStatsEntry"},{"id":24,"kind":1,"name":"\"Peer\"","url":"modules/_peer_.html","classes":"tsd-kind-external-module"},{"id":25,"kind":128,"name":"GossipPeer","url":"classes/_peer_.gossippeer.html","classes":"tsd-kind-class tsd-parent-kind-external-module","parent":"\"Peer\""},{"id":26,"kind":1024,"name":"host","url":"classes/_peer_.gossippeer.html#host","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Peer\".GossipPeer"},{"id":27,"kind":1024,"name":"port","url":"classes/_peer_.gossippeer.html#port","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Peer\".GossipPeer"},{"id":28,"kind":512,"name":"constructor","url":"classes/_peer_.gossippeer.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"\"Peer\".GossipPeer"},{"id":29,"kind":128,"name":"MailsyncPeer","url":"classes/_peer_.mailsyncpeer.html","classes":"tsd-kind-class tsd-parent-kind-external-module","parent":"\"Peer\""},{"id":30,"kind":1024,"name":"address","url":"classes/_peer_.mailsyncpeer.html#address","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Peer\".MailsyncPeer"},{"id":31,"kind":512,"name":"constructor","url":"classes/_peer_.mailsyncpeer.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"\"Peer\".MailsyncPeer"},{"id":32,"kind":1,"name":"\"Stats\"","url":"modules/_stats_.html","classes":"tsd-kind-external-module"},{"id":33,"kind":128,"name":"Stats","url":"classes/_stats_.stats.html","classes":"tsd-kind-class tsd-parent-kind-external-module","parent":"\"Stats\""},{"id":34,"kind":1024,"name":"software","url":"classes/_stats_.stats.html#software","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":35,"kind":1024,"name":"version","url":"classes/_stats_.stats.html#version","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":36,"kind":1024,"name":"hostName","url":"classes/_stats_.stats.html#hostname","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":37,"kind":1024,"name":"nodeName","url":"classes/_stats_.stats.html#nodename","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":38,"kind":1024,"name":"serverContact","url":"classes/_stats_.stats.html#servercontact","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":39,"kind":1024,"name":"httpPort","url":"classes/_stats_.stats.html#httpport","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":40,"kind":1024,"name":"reconPort","url":"classes/_stats_.stats.html#reconport","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":41,"kind":1024,"name":"debugLevel","url":"classes/_stats_.stats.html#debuglevel","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":42,"kind":1024,"name":"keys","url":"classes/_stats_.stats.html#keys","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":43,"kind":1024,"name":"statsTime","url":"classes/_stats_.stats.html#statstime","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":44,"kind":1024,"name":"gossipPeers","url":"classes/_stats_.stats.html#gossippeers","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":45,"kind":1024,"name":"gossipPeerCount","url":"classes/_stats_.stats.html#gossippeercount","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":46,"kind":1024,"name":"mailsyncPeers","url":"classes/_stats_.stats.html#mailsyncpeers","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":47,"kind":1024,"name":"mailsyncPeerCount","url":"classes/_stats_.stats.html#mailsyncpeercount","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":48,"kind":512,"name":"constructor","url":"classes/_stats_.stats.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"\"Stats\".Stats"},{"id":49,"kind":1,"name":"\"Keyserver\"","url":"modules/_keyserver_.html","classes":"tsd-kind-external-module"},{"id":50,"kind":128,"name":"Keyserver","url":"classes/_keyserver_.keyserver.html","classes":"tsd-kind-class tsd-parent-kind-external-module","parent":"\"Keyserver\""},{"id":51,"kind":1024,"name":"hostName","url":"classes/_keyserver_.keyserver.html#hostname","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Keyserver\".Keyserver"},{"id":52,"kind":1024,"name":"port","url":"classes/_keyserver_.keyserver.html#port","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Keyserver\".Keyserver"},{"id":53,"kind":1024,"name":"basePath","url":"classes/_keyserver_.keyserver.html#basepath","classes":"tsd-kind-property tsd-parent-kind-class","parent":"\"Keyserver\".Keyserver"},{"id":54,"kind":1024,"name":"requestOptions","url":"classes/_keyserver_.keyserver.html#requestoptions","classes":"tsd-kind-property tsd-parent-kind-class tsd-is-private","parent":"\"Keyserver\".Keyserver"},{"id":55,"kind":512,"name":"constructor","url":"classes/_keyserver_.keyserver.html#constructor","classes":"tsd-kind-constructor tsd-parent-kind-class","parent":"\"Keyserver\".Keyserver"},{"id":56,"kind":2048,"name":"getKeyserverHtml","url":"classes/_keyserver_.keyserver.html#getkeyserverhtml","classes":"tsd-kind-method tsd-parent-kind-class tsd-is-private","parent":"\"Keyserver\".Keyserver"},{"id":57,"kind":2048,"name":"lookup","url":"classes/_keyserver_.keyserver.html#lookup","classes":"tsd-kind-method tsd-parent-kind-class","parent":"\"Keyserver\".Keyserver"},{"id":58,"kind":2048,"name":"isPgpKey","url":"classes/_keyserver_.keyserver.html#ispgpkey","classes":"tsd-kind-method tsd-parent-kind-class tsd-is-private tsd-is-static","parent":"\"Keyserver\".Keyserver"},{"id":59,"kind":2048,"name":"upload","url":"classes/_keyserver_.keyserver.html#upload","classes":"tsd-kind-method tsd-parent-kind-class","parent":"\"Keyserver\".Keyserver"},{"id":60,"kind":2048,"name":"getStatsHtml","url":"classes/_keyserver_.keyserver.html#getstatshtml","classes":"tsd-kind-method tsd-parent-kind-class tsd-is-private","parent":"\"Keyserver\".Keyserver"},{"id":61,"kind":2048,"name":"mapStatsToView","url":"classes/_keyserver_.keyserver.html#mapstatstoview","classes":"tsd-kind-method tsd-parent-kind-class tsd-has-type-parameter","parent":"\"Keyserver\".Keyserver"},{"id":62,"kind":2048,"name":"getStats","url":"classes/_keyserver_.keyserver.html#getstats","classes":"tsd-kind-method tsd-parent-kind-class","parent":"\"Keyserver\".Keyserver"},{"id":63,"kind":2048,"name":"getKeyStats","url":"classes/_keyserver_.keyserver.html#getkeystats","classes":"tsd-kind-method tsd-parent-kind-class","parent":"\"Keyserver\".Keyserver"},{"id":64,"kind":2048,"name":"parseStatsHtml","url":"classes/_keyserver_.keyserver.html#parsestatshtml","classes":"tsd-kind-method tsd-parent-kind-class tsd-is-static","parent":"\"Keyserver\".Keyserver"},{"id":65,"kind":2048,"name":"parseKeyStatsHtml","url":"classes/_keyserver_.keyserver.html#parsekeystatshtml","classes":"tsd-kind-method tsd-parent-kind-class tsd-is-static","parent":"\"Keyserver\".Keyserver"},{"id":66,"kind":1,"name":"\"index\"","url":"modules/_index_.html","classes":"tsd-kind-external-module"}]}; \ No newline at end of file diff --git a/docs/code/classes/_errors_.nokeyfounderror.html b/docs/code/classes/_errors_.nokeyfounderror.html new file mode 100644 index 0000000..9a97551 --- /dev/null +++ b/docs/code/classes/_errors_.nokeyfounderror.html @@ -0,0 +1,313 @@ + + + + + + NoKeyFoundError | sks-lib + + + + + +
+
+
+
+ +
+
+ Options +
+
+ All +
    +
  • Public
  • +
  • Public/Protected
  • +
  • All
  • +
+
+ + + + + + +
+
+ Menu +
+
+
+
+
+
+ +

Class NoKeyFoundError

+
+
+
+
+
+
+
+
+
+

Class representing an error that no key could been found

+
+
+
+
+

Hierarchy

+
    +
  • + Error +
      +
    • + NoKeyFoundError +
    • +
    +
  • +
+
+
+

Index

+
+
+
+

Constructors

+ +
+
+

Properties

+ +
+
+
+
+
+

Constructors

+
+ +

constructor

+ + +
+
+
+

Properties

+
+ +

Static Error

+
Error: ErrorConstructor
+ +
+
+ +

Static message

+
message: string
+ +
+
+ +

Static name

+
name: string
+ +
+
+ +

Static Optional stack

+
stack: undefined | string
+ +
+
+
+ +
+
+ +
+

Generated using TypeDoc

+
+
+ + + + \ No newline at end of file diff --git a/docs/code/classes/_parseerror_.parseerror.html b/docs/code/classes/_errors_.parseerror.html similarity index 85% rename from docs/code/classes/_parseerror_.parseerror.html rename to docs/code/classes/_errors_.parseerror.html index 619b7fc..36112d3 100644 --- a/docs/code/classes/_parseerror_.parseerror.html +++ b/docs/code/classes/_errors_.parseerror.html @@ -56,10 +56,10 @@ Globals
  • - "ParseError" + "Errors"
  • - ParseError + ParseError
  • Class ParseError

    @@ -96,16 +96,16 @@

    Index

    Constructors

    Properties

    @@ -117,13 +117,13 @@

    Constructors

    constructor

    -

    Returns ParseError

    +

    Returns ParseError

    @@ -150,7 +150,7 @@

    Static Error

    Error: ErrorConstructor
    @@ -161,7 +161,7 @@

    Static message

    @@ -172,7 +172,7 @@

    Static name

    @@ -184,7 +184,7 @@

    Static /home/me/Code/sks/sks-lib/node_modules/typedoc/node_modules/typescript/lib/lib.es5.d.ts:875 +
  • Defined in /home/me/Code/sks/sks-lib/node_modules/typescript/lib/lib.es5.d.ts:887
  • @@ -196,15 +196,15 @@

    Static Globals +
  • + "Errors" +
  • "KeyStats"
  • "Keyserver"
  • -
  • - "ParseError" -
  • "Peer"
  • @@ -218,25 +218,28 @@

    Static +
    + +

    Private getKeyserverHtml

    +
      +
    • getKeyserverHtml(path: string): Promise<string>
    • +
    +
      +
    • + +
      +
      +

      Retrieves the keyserver's html and returns it as Promise

      +
      +
      +

      Parameters

      +
        +
      • +
        path: string
        +
        +

        relative path to request, usually starts with /pks

        +
        +
      • +
      +

      Returns Promise<string>

      +
    • +
    +

    getStats

    @@ -232,12 +302,13 @@

    getStats

  • -

    Retrieves the server's stats and returns a Promise, uses the default parsing method (parseStatsHtml).

    +

    Retrieves the server's stats and returns a Promise, + uses the default parsing method (parseStatsHtml)

    Returns Promise<Stats>

    @@ -254,34 +325,65 @@

    Private getStatsHtml<
  • -

    Retrieves the keyserver's stats html if necessary and then returns it as Promise.

    +

    Retrieves the keyserver's stats html and returns it as Promise

    Returns Promise<string>

  • +
    + +

    lookup

    +
      +
    • lookup(query: string): Promise<string>
    • +
    +
      +
    • + +
      +
      +

      Retrieves a key by a given query, throws NoKeyFoundError

      +
      +
      +

      Parameters

      +
        +
      • +
        query: string
        +
        +

        query to look up

        +
        +
      • +
      +

      Returns Promise<string>

      +
    • +
    +
    - -

    mapToView

    + +

    mapStatsToView

      -
    • mapToView<T>(transformFunction: function): Promise<T>
    • +
    • mapStatsToView<T>(transformFunction: function): Promise<T>
    • -

      Maps the keyserver's html to a generic promise.

      +

      Maps the keyserver's html to a generic promise

      Type parameters

      @@ -294,6 +396,9 @@

      Parameters

      • transformFunction: function
        +
        +

        function to transform HTML into a generic object

        +
          • @@ -318,6 +423,68 @@

            Returns Promise

    +
    + +

    upload

    +
      +
    • upload(publicKey: string): RequestPromise
    • +
    +
      +
    • + +
      +
      +

      Uploads a public key onto a keyserver

      +
      +
      +

      Parameters

      +
        +
      • +
        publicKey: string
        +
        +

        public key to upload

        +
        +
      • +
      +

      Returns RequestPromise

      +
    • +
    +
    +
    + +

    Static Private isPgpKey

    +
      +
    • isPgpKey(key: string): boolean
    • +
    +
      +
    • + +
      +
      +

      Checks whether a given input is a PGP key

      +
      +
      +

      Parameters

      +
        +
      • +
        key: string
        +
        +

        input to check

        +
        +
      • +
      +

      Returns boolean

      +
    • +
    +

    Static parseKeyStatsHtml

    @@ -328,18 +495,21 @@

    Static parseKeyStats
    -

    Parses given html into a KeyStats object, throws ParseError.

    +

    Parses given html into a KeyStats object, throws ParseError

    Parameters

    • html: string
      +
      +

      HTML to parse, usually from a keyserver's stats page

      +

    Returns KeyStats

    @@ -356,18 +526,21 @@

    Static parseStatsHtml<
  • -

    Parses given html into a Stats object, throws ParseError.

    +

    Parses given html into a Stats object, throws ParseError

    Parameters

    • html: string
      +
      +

      HTML to parse, usually from a keyserver's stats page

      +

    Returns Stats

    @@ -382,15 +555,15 @@

    Returns Globals

  • +
  • + "Errors" +
  • "KeyStats"
  • "Keyserver"
  • -
  • - "ParseError" -
  • "Peer"
  • @@ -412,6 +585,9 @@

    Returns constructor +
  • + basePath +
  • hostName
  • @@ -419,19 +595,31 @@

    Returns port
  • - statsHtml + requestOptions
  • getKeyStats
  • +
  • + getKeyserverHtml +
  • getStats
  • getStatsHtml
  • +
  • + lookup +
  • - mapToView + mapStatsToView +
  • +
  • + upload +
  • +
  • + isPgpKey
  • parseKeyStatsHtml diff --git a/docs/code/classes/_keystats_.keystats.html b/docs/code/classes/_keystats_.keystats.html index 4058b34..d1ba046 100644 --- a/docs/code/classes/_keystats_.keystats.html +++ b/docs/code/classes/_keystats_.keystats.html @@ -197,15 +197,15 @@

    totalKeys

  • Globals
  • +
  • + "Errors" +
  • "KeyStats"
  • "Keyserver"
  • -
  • - "ParseError" -
  • "Peer"
  • diff --git a/docs/code/classes/_keystats_.keystatsentry.html b/docs/code/classes/_keystats_.keystatsentry.html index f84e62e..e1aad93 100644 --- a/docs/code/classes/_keystats_.keystatsentry.html +++ b/docs/code/classes/_keystats_.keystatsentry.html @@ -197,15 +197,15 @@

    updatedKeys

  • Globals
  • +
  • + "Errors" +
  • "KeyStats"
  • "Keyserver"
  • -
  • - "ParseError" -
  • "Peer"
  • diff --git a/docs/code/classes/_peer_.gossippeer.html b/docs/code/classes/_peer_.gossippeer.html index 0aa30f0..de48fa2 100644 --- a/docs/code/classes/_peer_.gossippeer.html +++ b/docs/code/classes/_peer_.gossippeer.html @@ -179,13 +179,13 @@

    port

    Globals
  • - "KeyStats" + "Errors"
  • - "Keyserver" + "KeyStats"
  • - "ParseError" + "Keyserver"
  • "Peer" diff --git a/docs/code/classes/_peer_.mailsyncpeer.html b/docs/code/classes/_peer_.mailsyncpeer.html index cc314d5..1d13494 100644 --- a/docs/code/classes/_peer_.mailsyncpeer.html +++ b/docs/code/classes/_peer_.mailsyncpeer.html @@ -160,13 +160,13 @@

    address

    Globals
  • - "KeyStats" + "Errors"
  • - "Keyserver" + "KeyStats"
  • - "ParseError" + "Keyserver"
  • "Peer" diff --git a/docs/code/classes/_stats_.stats.html b/docs/code/classes/_stats_.stats.html index b602e1c..7d918d0 100644 --- a/docs/code/classes/_stats_.stats.html +++ b/docs/code/classes/_stats_.stats.html @@ -407,13 +407,13 @@

    version

    Globals
  • - "KeyStats" + "Errors"
  • - "Keyserver" + "KeyStats"
  • - "ParseError" + "Keyserver"
  • "Peer" diff --git a/docs/code/globals.html b/docs/code/globals.html index 2b7ac12..31370f3 100644 --- a/docs/code/globals.html +++ b/docs/code/globals.html @@ -70,9 +70,9 @@

    Index

    External modules

      +
    • "Errors"
    • "KeyStats"
    • "Keyserver"
    • -
    • "ParseError"
    • "Peer"
    • "Stats"
    • "index"
    • @@ -89,13 +89,13 @@

      External modules

      Globals
    • - "KeyStats" + "Errors"
    • - "Keyserver" + "KeyStats"
    • - "ParseError" + "Keyserver"
    • "Peer" diff --git a/docs/code/index.html b/docs/code/index.html index 2f96d8b..caa6877 100644 --- a/docs/code/index.html +++ b/docs/code/index.html @@ -79,44 +79,39 @@

      sks-lib


      -

      sks-lib is a Typescript library for interacting with SKS keyservers. Currently there's only support for retrieving a keyserver's stats.

      +

      sks-lib is a Typescript library for interacting with SKS keyservers. Currently there's only support for retrieving statistics of a keyserver.

      +

      Please note that keyservers never return verified data. Do not trust the retrieved keys and always verify them.

      Installation

      Just add it with yarn install sks-lib (or npm install sks-lib) to your project. It ships the generated Javascript code along with Typescript's declaration files. The Typescript code itself lives in lib/.

      -

      Example usage

      -
      import {Keyserver} from 'sks-lib';
      -import {Moment} from 'moment';
      -
      -
      +				

      Usage

      +
      // Create a new keyserver object to query on
       var keyserver = new Keyserver('keyserver.ntzwrk.org');
       
      -keyserver.getStats().then(
      -    (stats) => {
      -        var hostName = stats.hostName;
      -        var software = stats.software;
      -        var version = stats.version;
      -        var peerCount = stats.gossipPeerCount;
      +var somePublicKey: string;
       
      -        console.log('"%s" is a %s %s keyserver with %s gossip peers.', hostName, software, version, peerCount);
      +// Lookup the key for "vsund" and then print it
      +keyserver.lookup('vsund').then(
      +    (key) => {
      +        somePublicKey = key;
      +        console.log(key);
           }
      -).catch((reason: Error) => {
      -    console.log('Could not connect to "%s:11371"', keyserver.hostName);
      -    console.log('%s: %s', reason.name, reason.message);
      -});
      +);
       
      -keyserver.getKeyStats().then(
      -    (keyStats) => {
      -        var hostName = keyserver.hostName;
      -        var totalKeys = keyStats.totalKeys;
      -        var newKeys = keyStats.dailyKeys[11].newKeys;
      -        var date = keyStats.dailyKeys[11].dateTime.format('MMMM Do YYYY');
      +// Upload the previously fetched key and print the server's response
      +keyserver.upload(publicKey).then(
      +    (response) => {
      +        console.log(response);
      +    }
      +);
       
      -        console.log('"%s" has %s total keys and saw %s new keys on %s.', hostName, totalKeys, newKeys, date);
      +// Get stats and then print some information
      +keyserver.getStats().then(
      +    (stats) => {
      +        console.log('"%s" is a %s keyserver on version %s.', stats.hostName, stats.software, stats.version);
           }
      -).catch((reason: Error) => {
      -    console.log('Could not connect to "%s:11371"', keyserver.hostName);
      -    console.log('%s: %s', reason.name, reason.message);
      -});
      +);
       
      +

      See examples/ for some more examples.

      Documentation

      Code documentation lives in docs/code/, the generated HTML version is available at https://ntzwrk.github.io/sks-lib/code/.

      Development

      @@ -137,13 +132,13 @@

      License

      Globals
    • - "KeyStats" + "Errors"
    • - "Keyserver" + "KeyStats"
    • - "ParseError" + "Keyserver"
    • "Peer" diff --git a/docs/code/modules/_parseerror_.html b/docs/code/modules/_errors_.html similarity index 91% rename from docs/code/modules/_parseerror_.html rename to docs/code/modules/_errors_.html index 6fc8669..90bdbe6 100644 --- a/docs/code/modules/_parseerror_.html +++ b/docs/code/modules/_errors_.html @@ -3,7 +3,7 @@ - "ParseError" | sks-lib + "Errors" | sks-lib @@ -56,10 +56,10 @@ Globals
    • - "ParseError" + "Errors"
    -

    External module "ParseError"

    +

    External module "Errors"

    @@ -73,7 +73,8 @@

    Index

    Classes

    @@ -86,15 +87,15 @@

    Classes

  • Globals
  • +
  • + "Errors" +
  • "KeyStats"
  • "Keyserver"
  • -
  • - "ParseError" -
  • "Peer"
  • @@ -109,7 +110,10 @@

    Classes

    diff --git a/docs/code/modules/_index_.html b/docs/code/modules/_index_.html index 0f530c2..95dbac9 100644 --- a/docs/code/modules/_index_.html +++ b/docs/code/modules/_index_.html @@ -74,13 +74,13 @@

    External module "index"

    Globals
  • - "KeyStats" + "Errors"
  • - "Keyserver" + "KeyStats"
  • - "ParseError" + "Keyserver"
  • "Peer" diff --git a/docs/code/modules/_keyserver_.html b/docs/code/modules/_keyserver_.html index 8dd802b..1c4b6fd 100644 --- a/docs/code/modules/_keyserver_.html +++ b/docs/code/modules/_keyserver_.html @@ -86,15 +86,15 @@

    Classes

  • Globals
  • +
  • + "Errors" +
  • "KeyStats"
  • "Keyserver"
  • -
  • - "ParseError" -
  • "Peer"
  • diff --git a/docs/code/modules/_keystats_.html b/docs/code/modules/_keystats_.html index d762145..845ef71 100644 --- a/docs/code/modules/_keystats_.html +++ b/docs/code/modules/_keystats_.html @@ -87,15 +87,15 @@

    Classes

  • Globals
  • +
  • + "Errors" +
  • "KeyStats"
  • "Keyserver"
  • -
  • - "ParseError" -
  • "Peer"
  • diff --git a/docs/code/modules/_peer_.html b/docs/code/modules/_peer_.html index 38ef738..7ccab0d 100644 --- a/docs/code/modules/_peer_.html +++ b/docs/code/modules/_peer_.html @@ -88,13 +88,13 @@

    Classes

    Globals
  • - "KeyStats" + "Errors"
  • - "Keyserver" + "KeyStats"
  • - "ParseError" + "Keyserver"
  • "Peer" diff --git a/docs/code/modules/_stats_.html b/docs/code/modules/_stats_.html index b76b54b..f1dbd44 100644 --- a/docs/code/modules/_stats_.html +++ b/docs/code/modules/_stats_.html @@ -87,13 +87,13 @@

    Classes

    Globals
  • - "KeyStats" + "Errors"
  • - "Keyserver" + "KeyStats"
  • - "ParseError" + "Keyserver"
  • "Peer" diff --git a/examples/lookup.ts b/examples/lookup.ts new file mode 100644 index 0000000..9dad1d5 --- /dev/null +++ b/examples/lookup.ts @@ -0,0 +1,24 @@ +import {Keyserver, NoKeyFoundError} from '../lib/index'; + + +var keyserver = new Keyserver('keyserver.ntzwrk.org'); + +keyserver.lookup('vsund').then( + (key) => { + console.log(key); + } +).catch( + (error) => { + console.log('%s: %s', error.name, error.message); + } +); + +keyserver.lookup('this query doesn\'t result in a key').then( + (key) => { + console.log(key); + } +).catch( + (error) => { + console.log('%s: %s', error.name, error.message); + } +); diff --git a/examples/stats.ts b/examples/stats.ts new file mode 100644 index 0000000..702b7fb --- /dev/null +++ b/examples/stats.ts @@ -0,0 +1,35 @@ +import {Keyserver} from '../lib/index'; +import {Moment} from 'moment'; + + +var keyserver = new Keyserver('keyserver.ntzwrk.org'); + +keyserver.getStats().then( + (stats) => { + var hostName = stats.hostName; + var software = stats.software; + var version = stats.version; + var peerCount = stats.gossipPeerCount; + + console.log('"%s" is a %s %s keyserver with %s gossip peers.', hostName, software, version, peerCount); + } +).catch( + (error) => { + console.log('%s: %s', error.name, error.message); + } +); + +keyserver.getKeyStats().then( + (keyStats) => { + var hostName = keyserver.hostName; + var totalKeys = keyStats.totalKeys; + var newKeys = keyStats.dailyKeys[11].newKeys; + var date = keyStats.dailyKeys[11].dateTime.format('MMMM Do YYYY'); + + console.log('"%s" has %s total keys and saw %s new keys on %s.', hostName, totalKeys, newKeys, date); + } +).catch( + (error) => { + console.log('%s: %s', error.name, error.message); + } +); diff --git a/examples/upload.ts b/examples/upload.ts new file mode 100644 index 0000000..7a0a460 --- /dev/null +++ b/examples/upload.ts @@ -0,0 +1,20 @@ +import {Keyserver} from '../lib/index'; + + +var keyserver = new Keyserver('keyserver.ntzwrk.org'); + +var publicKey = ` +-----BEGIN PGP PUBLIC KEY BLOCK----- +... +-----END PGP PUBLIC KEY BLOCK----- +`; + +keyserver.upload(publicKey).then( + (response) => { + console.log(response); + } +).catch( + (error) => { + console.log('%s: %s', error.name, error.message); + } +); diff --git a/lib/ParseError.ts b/lib/Errors.ts similarity index 57% rename from lib/ParseError.ts rename to lib/Errors.ts index 30df13c..d7a2b3c 100644 --- a/lib/ParseError.ts +++ b/lib/Errors.ts @@ -1,3 +1,16 @@ +/** + * Class representing an error that no key could been found + */ +export class NoKeyFoundError extends Error { + /** Constructor for creating a new no key found error */ + constructor() { + super(); + + this.name = 'NoKeyFoundError'; + this.message = 'Could not find a key in server reply'; + } +} + /** * Class representing an error that occured while parsing the keyserver's html */ diff --git a/lib/Keyserver.ts b/lib/Keyserver.ts index d12ec82..179ab71 100644 --- a/lib/Keyserver.ts +++ b/lib/Keyserver.ts @@ -1,9 +1,9 @@ import * as requestPromise from 'request-promise-native'; +import {StatusCodeError} from 'request-promise-native/errors'; import * as moment from 'moment'; -import {Option, option, none} from 'm.m'; import {KeyStats, KeyStatsEntry} from './KeyStats'; -import {ParseError} from './ParseError'; +import {NoKeyFoundError, ParseError} from './Errors'; import {GossipPeer, MailsyncPeer} from './Peer'; import {Stats} from './Stats'; @@ -18,53 +18,139 @@ export class Keyserver { /** Optional port to make requests on (default: 11371) */ public port: number; - /** The keyserver's raw stats html */ - private statsHtml: Option = none(); + /** Base path for the keyserver (where the `/pks` paths start), (default: '') */ + public basePath: string; - /** Constructor for creating a new keyserver */ - constructor(hostName: string, port: number = 11371) { + /** Request options for a query to the keyserver */ + private requestOptions: requestPromise.RequestPromiseOptions; + + /** + * Constructor for creating a new keyserver + * + * @param hostName hostname of the keyserver + * @param port port of the keyserver + * @param basePath base path where to find the keyserver (the path before `/pks`, usually nothing) + */ + constructor(hostName: string, port: number = 11371, basePath: string = '') { this.hostName = hostName; this.port = port; + this.basePath = basePath; + this.requestOptions = { + baseUrl: 'http://' + hostName + ':' + port + '/' + basePath, + timeout: 4000, + headers: { + 'User-Agent': 'sks-lib (https://github.com/ntzwrk/sks-lib)' + } + }; + } + + /** + * Retrieves the keyserver's html and returns it as Promise + * + * @param path relative path to request, usually starts with `/pks` + */ + private getKeyserverHtml(path: string): Promise { + return requestPromise.get(path, this.requestOptions).then( + html => html + ); } - /** Retrieves the keyserver's stats html if necessary and then returns it as Promise. */ - private getStatsHtml(): Promise { - if(!this.statsHtml.isDefined) { - var options: requestPromise.Options = { - url: 'http://' + this.hostName + ':' + this.port + '/pks/lookup?op=stats', - timeout: 4000, - headers: { - 'User-Agent': 'sks-lib (https://github.com/ntzwrk/sks-lib)' - } - }; - return requestPromise.get(options).then( - (html: string) => { - this.statsHtml = option(html); + /** + * Retrieves a key by a given query, throws NoKeyFoundError + * + * @param query query to look up + */ + public lookup(query: string): Promise { + var path = '/pks/lookup?op=get&options=mr&search='; + + return this.getKeyserverHtml(path + encodeURIComponent(query)).then( + (html: string) => { + if(Keyserver.isPgpKey(html)) { return html; + } else { + throw new NoKeyFoundError(); } - ); - } else { - return new Promise(() => this.statsHtml.get); - } + } + ).catch( + (error: Error) => { + if(error instanceof StatusCodeError) { + var statusError = error; + if(statusError.statusCode === 404) { + throw new NoKeyFoundError(); + } + } + + throw error; + } + ); + } + + /** + * Checks whether a given input is a PGP key + * + * @param key input to check + */ + private static isPgpKey(key: string): boolean { + const PGP_KEY_START = '-----BEGIN PGP PUBLIC KEY BLOCK-----'; + const PGP_KEY_END = '-----END PGP PUBLIC KEY BLOCK-----'; + + return (key.indexOf(PGP_KEY_START) >= 0) && (key.indexOf(PGP_KEY_END) >= 0); + } + + + /** + * Uploads a public key onto a keyserver + * + * @param publicKey public key to upload + */ + public upload(publicKey: string): requestPromise.RequestPromise { + var path = '/pks/add'; + var options = this.requestOptions; + options.form = {keytext: publicKey}; + + return requestPromise.post(path, options); } - /** Maps the keyserver's html to a generic promise. */ - public mapToView(transformFunction: (html: string) => T): Promise { + + /** + * Retrieves the keyserver's stats html and returns it as Promise + */ + private getStatsHtml(): Promise { + var path = '/pks/lookup?op=stats'; + return this.getKeyserverHtml(path); + } + + /** + * Maps the keyserver's html to a generic promise + * + * @param transformFunction function to transform HTML into a generic object + */ + public mapStatsToView(transformFunction: (html: string) => T): Promise { return this.getStatsHtml().then(transformFunction); } - /** Retrieves the server's stats and returns a Promise, uses the default parsing method (`parseStatsHtml`). */ + /** + * Retrieves the server's stats and returns a Promise, + * uses the default parsing method (`parseStatsHtml`) + */ public getStats(): Promise { - return this.mapToView(Keyserver.parseStatsHtml); + return this.mapStatsToView(Keyserver.parseStatsHtml); } - /** Retrieves the server's key stats and returns a Promise, uses the default parsing method (`parseKeyStatsHtml`). */ + /** + * Retrieves the server's key stats and returns a Promise, + * uses the default parsing method (`parseKeyStatsHtml`) + */ public getKeyStats(): Promise { - return this.mapToView(Keyserver.parseKeyStatsHtml); + return this.mapStatsToView(Keyserver.parseKeyStatsHtml); } - /** Parses given html into a Stats object, throws ParseError. */ + /** + * Parses given html into a Stats object, throws ParseError + * + * @param html HTML to parse, usually from a keyserver's stats page + */ public static parseStatsHtml(html: string): Stats { var match: RegExpMatchArray | null; var matchVersion: RegExpMatchArray | null; @@ -154,7 +240,7 @@ export class Keyserver { // keys match = html.match(/Total number of keys: ([0-9]+)/); - if (match) { + if(match) { keys = parseInt(match[1], 10); } else { throw new ParseError('keys'); @@ -206,7 +292,11 @@ export class Keyserver { ); } - /** Parses given html into a KeyStats object, throws ParseError. */ + /** + * Parses given html into a KeyStats object, throws ParseError + * + * @param html HTML to parse, usually from a keyserver's stats page + */ public static parseKeyStatsHtml(html: string): KeyStats { var match: RegExpMatchArray | null; @@ -217,7 +307,7 @@ export class Keyserver { // totalKeys match = html.match(/Total number of keys: ([0-9]+)/); - if (match) { + if(match) { totalKeys = parseInt(match[1], 10); } else { throw new ParseError('totalKeys'); diff --git a/lib/index.ts b/lib/index.ts index 639f423..729d47d 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -1,5 +1,5 @@ export {Keyserver} from './Keyserver'; export {KeyStats, KeyStatsEntry} from './KeyStats'; -export {ParseError} from './ParseError'; +export {NoKeyFoundError, ParseError} from './Errors'; export {GossipPeer, MailsyncPeer} from './Peer'; export {Stats} from './Stats'; diff --git a/package.json b/package.json index 0eaa359..6e5e83d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sks-lib", - "version": "1.0.3", + "version": "1.1.0", "description": "A JavaScript/TypeScript library to interact with SKS keyservers", "author": "vsund", "license": "GPL-3.0", @@ -22,19 +22,18 @@ "document": "typedoc --out docs/code/ ./lib/ --sourcefile-url-prefix https://github.com/ntzwrk/sks-lib/blob/master/lib/" }, "dependencies": { - "@types/chai": "^4.0.4", - "@types/mocha": "^2.2.44", - "@types/node": "^8.0.47", - "@types/request-promise-native": "^1.0.9", + "@types/chai": "^4.1.2", + "@types/mocha": "^2.2.48", + "@types/node": "^9.4.0", + "@types/request-promise-native": "1.0.11", "chai": "^4.1.2", - "m.m": "^1.0.3", - "mocha": "^4.0.1", - "moment": "^2.19.3", + "mocha": "^5.0.0", + "moment": "^2.20.1", "request": "^2.83.0", "request-promise-native": "^1.0.5", - "ts-node": "^4.0.2", - "typedoc": "^0.9.0", + "ts-node": "^4.1.0", + "typedoc": "^0.10.0", "typedoc-plugin-sourcefile-url": "^1.0.3", - "typescript": "^2.5.3" + "typescript": "^2.7.1" } } diff --git a/test/Keyserver.spec.ts b/test/Keyserver.spec.ts index 0509040..8e3a3bb 100644 --- a/test/Keyserver.spec.ts +++ b/test/Keyserver.spec.ts @@ -32,7 +32,7 @@ describe('Keyserver', () => { validKeyStats = Keyserver.parseKeyStatsHtml(validHtml); }); - it('retrieves stats correctly', () => { + it('parses stats correctly', () => { chai.expect(validStats.hostName).to.equal('keyserver.ntzwrk.org'); chai.expect(validStats.nodeName).to.equal('phobos'); chai.expect(validStats.serverContact).to.equal('0x4124909FDAB6DE615DD5BFD65EE2F34DE4DB893E'); @@ -57,11 +57,11 @@ describe('Keyserver', () => { chai.expect(validStatsWithMailsyncPeers.mailsyncPeers[0]).to.deep.equal(new MailsyncPeer('pgp-public-keys@the.earth.li')); }); - it('fails retrieving stats from invalid html correctly', () => { - chai.expect(() => Keyserver.parseStatsHtml('')).to.throw(ParseError); + it('fails parsing stats from invalid html correctly', () => { + chai.expect(() => Keyserver.parseStatsHtml('')).to.throw(Error); // should be ParseError }); - it('retrieves key stats correctly', () => { + it('parses key stats correctly', () => { chai.expect(validKeyStats.totalKeys).to.equal(4849636); chai.expect(validKeyStats.dailyKeys[0]).to.deep.equal(new KeyStatsEntry(moment('2017-11-09', 'YYYY-MM-DD'), 1118, 516)); chai.expect(validKeyStats.dailyKeys[30]).to.deep.equal(new KeyStatsEntry(moment('2017-10-10', 'YYYY-MM-DD'), 1224, 859)); @@ -69,7 +69,7 @@ describe('Keyserver', () => { chai.expect(validKeyStats.hourlyKeys[736]).to.deep.equal(new KeyStatsEntry(moment('2017-10-10 01', 'YYYY-MM-DD HH'), 42, 21)); }); - it('fails retrieving key stats from invalid html correctly', () => { - chai.expect(() => Keyserver.parseKeyStatsHtml('')).to.throw(ParseError); + it('fails parsing key stats from invalid html correctly', () => { + chai.expect(() => Keyserver.parseKeyStatsHtml('')).to.throw(Error); // should be ParseError }); }); diff --git a/yarn.lock b/yarn.lock index fd8b28a..c18f1f7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,9 +2,13 @@ # yarn lockfile v1 -"@types/chai@^4.0.4": - version "4.0.4" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.0.4.tgz#fe86315d9a66827feeb16f73bc954688ec950e18" +"@types/chai@^4.1.2": + version "4.1.2" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.1.2.tgz#f1af664769cfb50af805431c407425ed619daa21" + +"@types/events@*": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@types/events/-/events-1.1.0.tgz#93b1be91f63c184450385272c47b6496fd028e02" "@types/form-data@*": version "2.2.0" @@ -12,43 +16,55 @@ dependencies: "@types/node" "*" -"@types/fs-extra@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-4.0.0.tgz#1dd742ad5c9bce308f7a52d02ebc01421bc9102f" +"@types/fs-extra@5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-5.0.0.tgz#d3e225b35eb5c6d3a5a782c28219df365c781413" + dependencies: + "@types/node" "*" + +"@types/glob@*": + version "5.0.35" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-5.0.35.tgz#1ae151c802cece940443b5ac246925c85189f32a" dependencies: + "@types/events" "*" + "@types/minimatch" "*" "@types/node" "*" -"@types/handlebars@4.0.31": - version "4.0.31" - resolved "https://registry.yarnpkg.com/@types/handlebars/-/handlebars-4.0.31.tgz#a7fba66fafe42713aee88eeca8db91192efe6e72" +"@types/handlebars@4.0.36": + version "4.0.36" + resolved "https://registry.yarnpkg.com/@types/handlebars/-/handlebars-4.0.36.tgz#ff57c77fa1ab6713bb446534ddc4d979707a3a79" -"@types/highlight.js@9.1.8": - version "9.1.8" - resolved "https://registry.yarnpkg.com/@types/highlight.js/-/highlight.js-9.1.8.tgz#d227f18bcb8f3f187e16965f2444859a04689758" +"@types/highlight.js@9.12.2": + version "9.12.2" + resolved "https://registry.yarnpkg.com/@types/highlight.js/-/highlight.js-9.12.2.tgz#6ee7cd395effe5ec80b515d3ff1699068cd0cd1d" -"@types/lodash@4.14.74": - version "4.14.74" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.74.tgz#ac3bd8db988e7f7038e5d22bd76a7ba13f876168" +"@types/lodash@4.14.99": + version "4.14.99" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.99.tgz#e6e10c0a4cc16c7409b3181f1e66880d2fb7d4dc" "@types/marked@0.3.0": version "0.3.0" resolved "https://registry.yarnpkg.com/@types/marked/-/marked-0.3.0.tgz#583c223dd33385a1dda01aaf77b0cd0411c4b524" -"@types/minimatch@2.0.29": - version "2.0.29" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-2.0.29.tgz#5002e14f75e2d71e564281df0431c8c1b4a2a36a" +"@types/minimatch@*", "@types/minimatch@3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" -"@types/mocha@^2.2.44": - version "2.2.44" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.44.tgz#1d4a798e53f35212fd5ad4d04050620171cd5b5e" +"@types/mocha@^2.2.48": + version "2.2.48" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.48.tgz#3523b126a0b049482e1c3c11877460f76622ffab" -"@types/node@*", "@types/node@^8.0.47": +"@types/node@*": version "8.0.47" resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.47.tgz#968e596f91acd59069054558a00708c445ca30c2" -"@types/request-promise-native@^1.0.9": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@types/request-promise-native/-/request-promise-native-1.0.9.tgz#b0905e02f67891043ac989a891aa54864a9a174a" +"@types/node@^9.4.0": + version "9.4.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-9.4.0.tgz#b85a0bcf1e1cc84eb4901b7e96966aedc6f078d1" + +"@types/request-promise-native@1.0.11": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@types/request-promise-native/-/request-promise-native-1.0.11.tgz#a6e9505d9ad2348f9f694f07085d021e7870000e" dependencies: "@types/request" "*" @@ -59,10 +75,11 @@ "@types/form-data" "*" "@types/node" "*" -"@types/shelljs@0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@types/shelljs/-/shelljs-0.7.0.tgz#229c157c6bc1e67d6b990e6c5e18dbd2ff58cff0" +"@types/shelljs@0.7.7": + version "0.7.7" + resolved "https://registry.yarnpkg.com/@types/shelljs/-/shelljs-0.7.7.tgz#1f7bfa28947661afea06365db9b1135bbc903ec4" dependencies: + "@types/glob" "*" "@types/node" "*" "@types/strip-bom@^3.0.0": @@ -321,9 +338,9 @@ form-data@~2.3.1: combined-stream "^1.0.5" mime-types "^2.1.12" -fs-extra@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.2.tgz#f91704c53d1b461f893452b0c307d9997647ab6b" +fs-extra@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" @@ -498,17 +515,13 @@ longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" -m.m@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/m.m/-/m.m-1.0.3.tgz#817091d1d1b3d510395ef28e118ad11d2c568d7b" - make-error@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.0.tgz#52ad3a339ccf10ce62b4040b708fe707244b8b96" -marked@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.6.tgz#b2c6c618fccece4ef86c4fc6cb8a7cbf5aeda8d7" +marked@^0.3.12: + version "0.3.12" + resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.12.tgz#7cf25ff2252632f3fe2406bde258e94eee927519" mime-db@~1.30.0: version "1.30.0" @@ -544,9 +557,9 @@ mkdirp@0.5.1, mkdirp@^0.5.1: dependencies: minimist "0.0.8" -mocha@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.0.1.tgz#0aee5a95cf69a4618820f5e51fa31717117daf1b" +mocha@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.0.0.tgz#cccac988b0bc5477119cba0e43de7af6d6ad8f4e" dependencies: browser-stdout "1.3.0" commander "2.11.0" @@ -559,9 +572,9 @@ mocha@^4.0.1: mkdirp "0.5.1" supports-color "4.4.0" -moment@^2.19.3: - version "2.19.3" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.19.3.tgz#bdb99d270d6d7fda78cc0fbace855e27fe7da69f" +moment@^2.20.1: + version "2.20.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.20.1.tgz#d6eb1a46cbcc14a2b2f9434112c1ff8907f313fd" ms@2.0.0: version "2.0.0" @@ -683,9 +696,9 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" -shelljs@^0.7.0: - version "0.7.8" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" +shelljs@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.1.tgz#729e038c413a2254c4078b95ed46e0397154a9f1" dependencies: glob "^7.0.0" interpret "^1.0.0" @@ -765,9 +778,9 @@ tough-cookie@>=2.3.3, tough-cookie@~2.3.3: dependencies: punycode "^1.4.1" -ts-node@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-4.0.2.tgz#cb3d039b9898fdc79ad09ab7e69c84564c8c41ee" +ts-node@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-4.1.0.tgz#36d9529c7b90bb993306c408cd07f7743de20712" dependencies: arrify "^1.0.0" chalk "^2.3.0" @@ -811,35 +824,31 @@ typedoc-plugin-sourcefile-url@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/typedoc-plugin-sourcefile-url/-/typedoc-plugin-sourcefile-url-1.0.3.tgz#fbbcc4b71bd92d2f794d1c169a480042296b1fe6" -typedoc@^0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.9.0.tgz#159bff7c7784ce5b91d86f3e4cc8928e62040957" +typedoc@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.10.0.tgz#898b447248dabf68ecbde9d5ccf5141fda8aa166" dependencies: - "@types/fs-extra" "4.0.0" - "@types/handlebars" "4.0.31" - "@types/highlight.js" "9.1.8" - "@types/lodash" "4.14.74" + "@types/fs-extra" "5.0.0" + "@types/handlebars" "4.0.36" + "@types/highlight.js" "9.12.2" + "@types/lodash" "4.14.99" "@types/marked" "0.3.0" - "@types/minimatch" "2.0.29" - "@types/shelljs" "0.7.0" - fs-extra "^4.0.0" + "@types/minimatch" "3.0.3" + "@types/shelljs" "0.7.7" + fs-extra "^5.0.0" handlebars "^4.0.6" highlight.js "^9.0.0" lodash "^4.13.1" - marked "^0.3.5" + marked "^0.3.12" minimatch "^3.0.0" progress "^2.0.0" - shelljs "^0.7.0" + shelljs "^0.8.1" typedoc-default-themes "^0.5.0" - typescript "2.4.1" - -typescript@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.4.1.tgz#c3ccb16ddaa0b2314de031e7e6fee89e5ba346bc" + typescript "2.7.1" -typescript@^2.5.3: - version "2.5.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.5.3.tgz#df3dcdc38f3beb800d4bc322646b04a3f6ca7f0d" +typescript@2.7.1, typescript@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.7.1.tgz#bb3682c2c791ac90e7c6210b26478a8da085c359" uglify-js@^2.6: version "2.8.29"