nostr-geotags
is a modern ESM-only package for generating discoverable geohash and ISO-3166-1/2/3 tags using NIP_32
based on various inputs like latitude, longitude, city, country, etc. It uses iso-3166
and ngeohash
to generate geodata. This package is alpha and the API and response formats will change. This package has gone full-circle and now implements NIP-32
just as it did in the first commit.
This package was derived from needs in @nostrwatch
, an OpenSats Grant Recipient, and so was made possible by OpenSats.
The package is available on npm and can be installed using npm, yarn, or pnpm.
npm install nostr-geotags
yarn add nostr-geotags
pnpm add nostr-geotags
import ngeotags from 'nostr-geotags'
event = {}
event.kind = 1
//created_at, content etc...
event.tags = []
event.tags.push(['t', 'nostrworks'])
const inputData = {
lat: 52.5200,
lon: 13.4050,
city: 'Berlin',
countryCode: 'DE'
};
const options = {
geohash: true,
gps: true,
city: true,
iso31662: true
};
event.tags = [...event.tags, ...ngeotags(inputData, options)];
//sign and verify the event
console.log(event);
The inputData
object can contain:
The inputData
object can contain the following properties, used to generate geo-tags:
lat
(number): Latitude coordinate. No default value.lon
(number): Longitude coordinate. No default value.geohash
(string): Geohash coordinate. No default value. Will be ignored if lat & lon are also passed as input as they take precedence.city
(string): Name of the city. No default value.country
(string): Name of the country. No default value.regionName
(string): Name of the region or state. No default value.countryCode
(string): ISO-3166-1:alpha-2
country code. No default value.planetName
(string): Name of a planet.The options
object specifies which types of tags to generate.
iso31661
(boolean): Generate ISO 3166-1 tags. Default: true
.iso31662
(boolean): Generate ISO 3166-2 tags. Default: false
.iso31663
(boolean): Generate ISO 3166-3 tags. Default: true
. See ISO-3166-3 Behaviors
Please note: that these will only have an effect on the output if the input for their corresponding values were set. This is especially true for passthrough values. Some of these passthrough values may be deduped if they are not unique against ISO values.
geohash
(boolean): Includes geohash codes from ngeohash
, with diminishing resolution, based on latitude and longitude. Default: true
.city
or cityName
(boolean): Include a tag for the city in response if available. Default: true
.country
(boolean): Include a tag for the countryCode
and countryName
in response if available. Default: true
.countryCode
(boolean): Include a tag for the countryCode
in response if available. Default: true
.countryName
(boolean): Include a tag for the countryName
in response if available. Default: true
.region
(boolean): Include a tag for the regionCode
and regionName
in response if available. Default:true
.regionCode
(boolean): Include a tag for the regionCode
in response if available. Default:true
.regionName
(boolean): Include a tag for the regionName
in response if available. Default:true
.gps
(boolean): Include latitude and longitude as a 'dd' tag (de-factor GPS standards) and separate tags for lat and lon with diminishing resolution. Default: false
.planet
or planetName
(boolean): Include a tag for the planetName
in response if available. Default: false
.The function returns an array of tuples, where each tuple represents a tag and its associated data. The format of the tuples is based on NIP-01
.
'g'
) is a constant indicating the type of tag.value
of the tag, which can vary based on the input and options used. key
of the tag.standard
, which is serialized with a :
where when split standard[0]
is the the standard's identified and standard[1]
is the standard's value. This field is only used for ISO.Which tags you use depend on use-case. If your concerns are namely geospacial, using only geohashes likely suffice, if your concerns around around borders, languages or laws, ISO-3166-3
may suffice. If your concerns are mixed, a combination of standards will suffice. In most cases the defaults are good, and most likely won't need to be changed unless you are optimizing your tags array.
GPS: [ 'g', '<latitude>, <longitude>', 'dd' ]
, [ 'g', '<latitude>', 'lat' ]
and [ l', '<longitude>', 'lon' ]
lat
and lon
, an integer is returned.Geohash: [ g', '<geohash>']
(NIP-52
)
ngeohash
library.ISO-3166-1 Codes:
iso-3166
library and are based on the provided countryCode
input value. They are not passthrough.isoAsNamespace==false [default]
[ 'l', 'HU', 'ISO-3166-1' ]
[ 'l', 'HUN', 'ISO-3166-1']
[ 'l', '348', 'ISO-3166-1']
ISO-3166-2 Codes:
iso-3166
library and are based on the countryCode
and regionCode
input values. They are not passthrough values.ISO-3166-3 Codes:
City: [ 'g', 'Budapest', 'cityName' ]
Planet: [ 'g', 'Earth', 'planetName' ]
When iso31663
is enabled, it will affect the response contents. Any ISO-3166-3
code found for a given ISO-3166-1
countryCode
that is not a duplicate of it's ISO-3166-1
counterpart, will be appended to the tags array. Here's an example:
[ [ 'L', 'ISO-3166-1' ], [ 'g', 'AI', 'ISO-3166-1'], [ 'g', 'AIA', 'ISO-3166-1' ], [ 'g', '660', 'ISO-3166-1'], [ 'G', 'ISO-3166-3' ], [ 'g', 'DJ', 'ISO-3166-3' ], [ 'G', 'countryName' ], [ 'g', 'Anguilla', 'countryName' ] ]
Here two alpha2
codes are returned, the original ISO-3166-1
code, and the changed ISO-3166-3
code. Since the other ISO-3166-3
properties for AI
are the same as their ISO-3166-1
counter-parts, they are not included.
Here is the default response when lat
, lon
, countryCode
, regionName
, and planet
are provided, with everything else default
[ 'g', 'u2mwdd8q4' ],
[ 'g', 'u2mwdd8q' ],
[ 'g', 'u2mwdd8' ],
[ 'g', 'u2mwdd' ],
[ 'g', 'u2mwd' ],
[ 'g', 'u2mw' ],
[ 'g', 'u2m' ],
[ 'g', 'u2' ],
[ 'g', 'u' ],
[ 'L', 'countryCode' ],
[ 'l', 'HU', 'countryCode' ],
[ 'l', 'HUN', 'countryCode' ],
[ 'l', '348', 'countryCode' ],
[ 'L', 'countryName' ],
[ 'l', 'Hungary', 'countryName' ],
[ 'L', 'cityName' ],
[ 'l', 'Budapest', 'cityName' ]
This is a response with all options enabled (deduped, dedupe: true
)
[ 'g', 'u2mwdd8q4' ],
[ 'g', 'u2mwdd8q' ],
[ 'g', 'u2mwdd8' ],
[ 'g', 'u2mwdd' ],
[ 'g', 'u2mwd' ],
[ 'g', 'u2mw' ],
[ 'g', 'u2m' ],
[ 'g', 'u2' ],
[ 'g', 'u' ],
[ 'l', '47.5636, 19.0947', 'dd' ],
[ 'L', 'dd.lat' ],
[ 'l', '47.5636', 'dd.lat' ],
[ 'l', '47.563', 'dd.lat' ],
[ 'l', '47.56', 'dd.lat' ],
[ 'l', '47.5', 'dd.lat' ],
[ 'L', 'dd.lon' ],
[ 'l', '19.0947', 'dd.lon' ],
[ 'l', '19.094', 'dd.lon' ],
[ 'l', '19.09', 'dd.lon' ],
[ 'l', '19', 'dd.lon' ],
[ 'L', 'countryCode' ],
[ 'l', 'HU', 'countryCode' ],
[ 'l', 'HUN', 'countryCode' ],
[ 'l', '348', 'countryCode' ],
[ 'L', 'countryName' ],
[ 'l', 'Hungary', 'countryName' ],
[ 'L', 'regionCode' ],
[ 'l', 'HU-BU', 'regionCode' ],
[ 'L', 'cityName' ],
[ 'l', 'Budapest', 'cityName' ],
[ 'L', 'planetName' ],
[ 'l', 'Earth', 'planetName' ]
To build the package, run:
npm run build
To run tests:
npm test