diff --git a/.dockerignore b/.dockerignore index 7a2fc0a..665b496 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,6 +1,5 @@ -.git -config.json -logs -certs -cdn -node_modules +.git +.env +node_modules +dist +logs diff --git a/.eslintignore b/.eslintignore index e69de29..7c5c224 100644 --- a/.eslintignore +++ b/.eslintignore @@ -0,0 +1,2 @@ +dist +*.js \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json index c7da300..24079aa 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -4,13 +4,17 @@ "commonjs": true, "es6": true }, - "parserOptions": { - "ecmaVersion": 2020 - }, + "parser": "@typescript-eslint/parser", "globals": { "BigInt": true }, - "extends": "eslint:recommended", + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended" + ], + "plugins": [ + "@typescript-eslint" + ], "rules": { "require-atomic-updates": "warn", "no-case-declarations": "off", @@ -20,6 +24,13 @@ "no-global-assign": "off", "prefer-const": "error", "no-var": "error", + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }], + "no-extra-semi": "off", + "@typescript-eslint/no-extra-semi": "error", + "@typescript-eslint/no-empty-interface": "warn", + "@typescript-eslint/no-inferrable-types": "error", + "@typescript-eslint/explicit-function-return-type": "error", "one-var": [ "error", "never" diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..d3d40b6 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,56 @@ +name: Build and Publish Docker Image + +on: + push: + pull_request: + workflow_dispatch: + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-publish: + env: + SHOULD_PUSH_IMAGE: ${{ (github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/dev')) || github.event_name == 'workflow_dispatch' }} + runs-on: ubuntu-latest + + permissions: + contents: read + packages: write + + steps: + - name: Set up QEMU for Docker + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log into the container registry + if: ${{ env.SHOULD_PUSH_IMAGE == 'true' }} + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=raw,value=latest,enable=${{ github.ref == 'refs/heads/master' }} + type=raw,value=edge,enable=${{ github.ref == 'refs/heads/dev' }} + type=sha + + - name: Build and push Docker image + id: build-and-push + uses: docker/build-push-action@v6 + with: + platforms: linux/amd64,linux/arm64 + push: ${{ env.SHOULD_PUSH_IMAGE }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.gitignore b/.gitignore index ce5d611..bd3afc3 100644 --- a/.gitignore +++ b/.gitignore @@ -58,10 +58,7 @@ typings/ .env # custom -sign.js -t.js -p.js config.json certs -/cdn -dump.rdb \ No newline at end of file +cdn +dist \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index a810a90..53811ab 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,16 +1,47 @@ -FROM node:18-alpine - -RUN apk add --no-cache python3 make gcc g++ -WORKDIR /app - -COPY "docker/entrypoint.sh" ./ - -COPY package*.json ./ -RUN npm install bcrypt && npm rebuild bcrypt --build-from-source -RUN npm install - -COPY . ./ - -VOLUME [ "/app/config.json", "/app/certs" ] - -CMD ["sh", "entrypoint.sh"] +# syntax=docker/dockerfile:1 + +ARG app_dir="/home/node/app" + + +# * Base Node.js image +FROM node:20-alpine AS base +ARG app_dir +WORKDIR ${app_dir} + + +# * Installing production dependencies +FROM base AS dependencies + +RUN --mount=type=bind,source=package.json,target=package.json \ + --mount=type=bind,source=package-lock.json,target=package-lock.json \ + --mount=type=cache,target=/root/.npm \ + npm ci --omit=dev + + +# * Installing development dependencies and building the application +FROM base AS build + +RUN --mount=type=bind,source=package.json,target=package.json \ + --mount=type=bind,source=package-lock.json,target=package-lock.json \ + --mount=type=cache,target=/root/.npm \ + npm ci + +COPY . . +RUN npm run build + + +# * Running the final application +FROM base AS final +ARG app_dir + +RUN mkdir -p ${app_dir}/logs && chown node:node ${app_dir}/logs + +ENV NODE_ENV=production +USER node + +COPY package.json . + +COPY --from=dependencies ${app_dir}/node_modules ${app_dir}/node_modules +COPY --from=build ${app_dir}/dist ${app_dir}/dist + +CMD ["node", "."] diff --git a/README.md b/README.md index 80fc5d8..1e2a869 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # Account server -## What is this? -The account server is a replacement for several account-based services used by the WiiU and 3DS. It replaces the NNID api as well as NASC for the 3DS. It also contains a dedicated PNID api service for getting details of PNIDs outside of the consoles +Replacement for several account-based services used by the WiiU and 3DS. It replaces the NNID api as well as NASC for the 3DS. It also contains a dedicated PNID api service for getting details of PNIDs outside of the consoles (used by the website) ## Setup -TODO \ No newline at end of file +See [SETUP.md](SETUP.md) for how to self host \ No newline at end of file diff --git a/SETUP.md b/SETUP.md new file mode 100644 index 0000000..f5cbd82 --- /dev/null +++ b/SETUP.md @@ -0,0 +1,91 @@ +# Setup + +- [Required software](#required-software) + - [NodeJS](#nodejs) + - [MongoDB](#mongodb) +- [Optional features](#optional-features) + - [Redis (optional)](#redis-optional) + - [Email (optional)](#email-optional) + - [Amazon s3 server (optional)](#amazon-s3-server-optional) + - [hCaptcha (optional)](#hcaptcha-optional) +- [Configuration](#configuration) + + +## Required software + +- [NodeJS](https://nodejs.org/) +- [MongoDB](https://www.mongodb.com) + +### NodeJS + +Download and install the latest LTS version of [NodeJS](https://nodejs.org/). If using a Linux based operating system, using [nvm](https://github.com/nvm-sh/nvm) is the recommended method. _Tested on NodeJS version v18.20.5_ + +### MongoDB + +Download and install the latest version of [MongoDB](https://www.mongodb.com) + +The server assumes that MongoDB is running as a replica set, here's how to configure a basic replica set: +1. Open /etc/mongod.conf with your preferred editor. + +2. Add/modify the `replication` section with the following: +```conf +replication: + replSetName: "rs0" +``` + +3. Restart MongoDB and open a shell with `mongosh`. + +4. Initiate the replica set with `rs.initiate()` and check its status with `rs.status()`. + +## Optional features + +- [Redis](https://redis.io/) file caching +- Email address for sending automatic emails (tested with gmail) +- Amazon s3, or compatible, server for CDN methods +- [hCaptcha](https://hcaptcha.com/) for website API captcha verification + +### Redis (optional) + +Redis can be used to cache files read from disk. If Redis is not configured, then an in-memory object store is used instead. + +### Email (optional) + +Events such as account creation, email verification, etc, support sending emails to users. To enable email sending, you will need to use Amazon SES. Consult the Amazon SES documentation for more details. + +### Amazon s3 server (optional) + +Certain endpoints expect URLs for static CDN assets, such as pre-rendered Mii images. An [Amazon s3](https://aws.amazon.com/s3/) or compatible server, such as [Spaces by DigitalOcean](https://www.digitalocean.com/products/spaces), [Cloudflare R2](https://www.cloudflare.com/products/r2/), or [Backblaze B2](https://www.backblaze.com/b2/docs/), can optionally be used to store and upload these assets. If an s3 server is not configured, CDN contents will be stored on disk and served from this server. See [Configuration](#configuration) for more details. + +### hCaptcha (optional) + +The Pretendo Network website uses this server as an API for querying user information. Certain endpoints are considered more secure than others, such as registration, and can optionally be protected using [hCaptcha](https://hcaptcha.com/). If hCaptcha is not configured, no endpoints on the public facing API will be protected. + +## Configuration + +Configurations are loaded through environment variables. `.env` files are supported. All configuration options will be gone over, both required and optional. There also exists an example `.env` file + +| Name | Description | Optional | +|-----------------------------------------------|--------------------------------------------------------------------------------------------------|----------| +| `PN_ACT_CONFIG_HTTP_PORT` | The HTTP port the server listens on | No | +| `PN_ACT_CONFIG_MONGO_CONNECTION_STRING` | MongoDB connection string | No | +| `PN_ACT_CONFIG_MONGOOSE_CONNECT_OPTIONS_PATH` | Path to a `.json` file containing Mongoose connection options | Yes | +| `PN_ACT_CONFIG_REDIS_URL` | Redis URL | Yes | +| `PN_ACT_CONFIG_EMAIL_SES_REGION` | Amazon SES Region | Yes | +| `PN_ACT_CONFIG_EMAIL_SES_ACCESS_KEY` | Amazon SES Access Key | Yes | +| `PN_ACT_CONFIG_EMAIL_SES_SECRET_KEY` | Amazon SES Access Secret | Yes | +| `PN_ACT_CONFIG_EMAIL_FROM` | Email "from" address | Yes | +| `PN_ACT_CONFIG_S3_ENDPOINT` | s3 server endpoint | Yes | +| `PN_ACT_CONFIG_S3_ACCESS_KEY` | s3 secret key | Yes | +| `PN_ACT_CONFIG_S3_ACCESS_SECRET` | s3 secret | Yes | +| `PN_ACT_CONFIG_HCAPTCHA_SECRET` | hCaptcha secret (in the form `0x...`) | Yes | +| `PN_ACT_CONFIG_CDN_SUBDOMAIN` | Subdomain used to serve CDN contents if s3 is disabled | Yes | +| `PN_ACT_CONFIG_CDN_DISK_PATH` | File system path used to store CDN contents if s3 is disabled | Yes | +| `PN_ACT_CONFIG_CDN_BASE_URL` | URL for serving CDN contents (usually the same as s3 endpoint) | No | +| `PN_ACT_CONFIG_WEBSITE_BASE` | Website URL | Yes | +| `PN_ACT_CONFIG_AES_KEY` | AES-256 key used for encrypting tokens | No | +| `PN_ACT_CONFIG_DATASTORE_SIGNATURE_SECRET` | HMAC secret key (16 bytes in hex format) used to sign uploaded DataStore files | No | +| `PN_ACT_CONFIG_GRPC_MASTER_API_KEY_ACCOUNT` | Master API key to interact with the account gRPC service | No | +| `PN_ACT_CONFIG_GRPC_MASTER_API_KEY_API` | Master API key to interact with the API gRPC service | No | +| `PN_ACT_CONFIG_GRPC_PORT` | gRPC server port | No | +| `PN_ACT_CONFIG_STRIPE_SECRET_KEY` | Stripe API key. Used to cancel subscriptions when scrubbing PNIDs | Yes | +| `PN_ACT_CONFIG_SERVER_ENVIRONMENT` | Server environment. Currently only used by the Wii U Account Settings app. `prod`/`test`/`dev` | Yes | \ No newline at end of file diff --git a/create-test-user.js b/create-test-user.js deleted file mode 100644 index 047ea68..0000000 --- a/create-test-user.js +++ /dev/null @@ -1,79 +0,0 @@ -const prompt = require('prompt'); -const crypto = require('crypto'); -const database = require('./src/database'); -const { PNID } = require('./src/models/pnid'); - -prompt.message = ''; - -const properties = [ - 'username', - 'email', - { - name: 'password', - hidden: true - } -]; - -prompt.get(properties, (error, { username, email, password }) => { - const date = new Date().toISOString(); - // Sample Mii data - const miiData = 'AwAAQOlVognnx0GC2X0LLQOzuI0n2QAAAUBiAGUAbABsAGEAAABFAAAAAAAAAEBAEgCBAQRoQxggNEYUgRIXaA0AACkDUkhQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP6G'; - - const document = { - pid: 1, - creation_date: date.split('.')[0], - updated: date, - username: username, - password: password, - birthdate: '1990-01-01', - gender: 'M', - country: 'US', - language: 'en', - email: { - address: email, - primary: true, - parent: true, - reachable: true, - validated: true, - id: crypto.randomBytes(4).readUInt32LE() - }, - region: 0x310B0000, - timezone: { - name: 'America/New_York', - offset: -14400 - }, - mii: { - name: 'bella', - primary: true, - data: miiData, - id: crypto.randomBytes(4).readUInt32LE(), - hash: crypto.randomBytes(7).toString('hex'), - image_url: '', // Deprecated, will be removed - image_id: crypto.randomBytes(4).readUInt32LE() - }, - flags: { - active: true, - marketing: false, - off_device: true - }, - validation: { - // These values are temp and will be overwritten before the document saves - // These values are only being defined to get around the `E11000 duplicate key error collection` error - email_code: 1, - email_token: '' - } - }; - - const newUser = new PNID(document); - - newUser.save(async (error, newUser) => { - if (error) { - throw error; - } - - console.log(newUser); - console.log('New user created'); - }); -}); - -database.connect().then(prompt.start); \ No newline at end of file diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh deleted file mode 100644 index 2c6aa02..0000000 --- a/docker/entrypoint.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -# this doesnt check game server specific certs, only static file paths -files='config.json' - -for file in $files; do - if [ ! -f $file ]; then - echo "$PWD/$file file does not exist. Please mount and try again." - exit 1 - fi -done - -# check for keys -keys='certs/nex/datastore/secret.key certs/service/account/secret.key certs/service/account/aes.key certs/service/account/private.pem certs/service/account/public.pem' -for file in $keys; do - if [ ! -f "$file" ]; then - if [ x"${GENERATE_NEW_KEYS}" = "x" ]; then - echo "$PWD/$file file does not exist. Please mount and try again." - exit 1 - else - echo "$PWD/$file file does not exist. Generating a temporary one" - node generate-keys.js nex datastore - node generate-keys.js account - fi - fi -done - -exec node src/server.js diff --git a/example.config.json b/example.config.json deleted file mode 100644 index 33f7b24..0000000 --- a/example.config.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "http": { - "port": 7070 - }, - "mongoose": { - "connection_string": "mongodb://localhost:27017/database_name", - "options": { - "useNewUrlParser": true - } - }, - "redis": { - "client": { - "url": "redis://localhost:6379" - } - }, - "email": { - "host": "smtp.gmail.com", - "port": 587, - "secure": false, - "auth": { - "user": "username", - "pass": "password" - }, - "from": "Company Name " - }, - "s3": { - "endpoint": "nyc3.digitaloceanspaces.com", - "key": "ACCESS_KEY", - "secret": "ACCESS_SECRET" - }, - "hcaptcha": { - "secret": "0x0000000000000000000000000000000000000000" - }, - "cdn": { - "base_url": "https://local-cdn.example.com", - "subdomain": "local-cdn", - "disk_path": "/home/jon/pretend-cdn" - }, - "website_base": "https://example.com" -} \ No newline at end of file diff --git a/example.env b/example.env index 360615f..8e07339 100644 --- a/example.env +++ b/example.env @@ -6,10 +6,11 @@ PN_ACT_CONFIG_MONGOOSE_OPTION_useUnifiedTopology=true PN_ACT_CONFIG_REDIS_URL=redis://localhost:6379 PN_ACT_CONFIG_EMAIL_HOST=smtp.gmail.com PN_ACT_CONFIG_EMAIL_PORT=587 -PN_ACT_CONFIG_EMAIL_SECURE=false -PN_ACT_CONFIG_EMAIL_USERNAME=username -PN_ACT_CONFIG_EMAIL_PASSWORD=password +PN_ACT_CONFIG_EMAIL_SES_REGION=region +PN_ACT_CONFIG_EMAIL_SES_ACCESS_KEY=ACCESS_KEY +PN_ACT_CONFIG_EMAIL_SES_SECRET_KEY=ACCESS_SECRET PN_ACT_CONFIG_EMAIL_FROM=Company Name +PN_ACT_CONFIG_S3_BUCKET=BUCKET_NAME PN_ACT_CONFIG_S3_ENDPOINT=nyc3.digitaloceanspaces.com PN_ACT_CONFIG_S3_ACCESS_KEY=ACCESS_KEY PN_ACT_CONFIG_S3_ACCESS_SECRET=ACCESS_SECRET @@ -17,4 +18,7 @@ PN_ACT_CONFIG_HCAPTCHA_SECRET=0x0000000000000000000000000000000000000000 PN_ACT_CONFIG_CDN_BASE_URL=https://local-cdn.example.com PN_ACT_CONFIG_CDN_SUBDOMAIN=local-cdn PN_ACT_CONFIG_CDN_DISK_PATH=/home/jon/pretend-cdn -PN_ACT_CONFIG_WEBSITE_BASE=https://example.com \ No newline at end of file +PN_ACT_CONFIG_WEBSITE_BASE=https://example.com +PN_ACT_CONFIG_AES_KEY=abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789 +PN_ACT_CONFIG_GRPC_API_KEY=apikey +PN_ACT_CONFIG_SERVER_ENVIRONMENT=prod \ No newline at end of file diff --git a/generate-keys.js b/generate-keys.js deleted file mode 100644 index b1a311b..0000000 --- a/generate-keys.js +++ /dev/null @@ -1,145 +0,0 @@ -const NodeRSA = require('node-rsa'); -const crypto = require('crypto'); -const fs = require('fs-extra'); -const yesno = require('yesno'); -const logger = require('./logger'); -require('colors'); - -const ALLOWED_CHARS_REGEX = /[^a-zA-Z0-9_-]/g; - -async function main() { - const args = process.argv.slice(2); - - if (args.length < 1) { - logger.error('Must pass in type and optional name'); - usage(); - return; - } - - let [type, name] = args; - - type = type.toLowerCase().trim(); - - if (name) { - name = name.toLowerCase().trim(); - - if (ALLOWED_CHARS_REGEX.test(name)) { - logger.error(`Invalid name. Names must only contain [^a-zA-Z0-9_-]. Got ${name}`); - return; - } - } - - if (!['nex', 'service', 'account'].includes(type)) { - logger.error(`Invalid type. Expected nex, service, or account. Got ${type}`); - usage(); - return; - } - - if (type !== 'account' && (!name || name === '')) { - logger.error('If type is not account, a name MUST be passed'); - usage(); - return; - } - - if (type === 'service' && name === 'account') { - logger.error('Cannot use service name \'account\'. Reserved'); - usage(); - return; - } - - let path; - - if (type === 'account') { - path = `${__dirname}/certs/service/account`; - } else { - path = `${__dirname}/certs/${type}/${name}`; - } - - if (fs.pathExistsSync(path)) { - const overwrite = await yesno({ - question: 'Keys found for type name, overwrite existing keys?' - }); - - if (!overwrite) { - logger.info('Not overwriting existing keys. Exiting program'); - return; - } - } - - const publicKeyPath = `${path}/public.pem`; - const privateKeyPath = `${path}/private.pem`; - const aesKeyPath = `${path}/aes.key`; - const secretKeyPath = `${path}/secret.key`; - - // Ensure the output directories exist - logger.info('Creating output directories...'); - fs.ensureDirSync(path); - logger.success('Created output directories!'); - - const key = new NodeRSA({ b: 1024 }, null, { - environment: 'browser', - encryptionScheme: { - 'hash': 'sha256', - } - }); - - // Generate new key pair - logger.info('Generating RSA key pair...'); - logger.warn('(this may take a while)') - key.generateKeyPair(1024); - logger.success('Generated RSA key pair!'); - - // Export the keys - logger.info('Exporting public key...'); - const publicKey = key.exportKey('public'); - logger.success('Exported public key!'); - - // Saving public key - logger.info('Saving public key to disk...'); - fs.writeFileSync(publicKeyPath, publicKey); - logger.success(`Saved public key to ${publicKeyPath}!`); - - logger.info('Exporting private key...'); - const privateKey = key.exportKey('private'); - logger.success('Exported private key!'); - - // Saving private key - logger.info('Saving private key to disk...'); - fs.writeFileSync(privateKeyPath, privateKey); - logger.success(`Saved private key to ${privateKeyPath}!`); - - // Generate new AES key - logger.info('Generating AES key...'); - const aesKey = crypto.randomBytes(16); - logger.success('Generated AES key!'); - - // Saving AES key - logger.info('Saving AES key to disk...'); - fs.writeFileSync(aesKeyPath, aesKey.toString('hex')); - logger.success(`Saved AES key to ${aesKeyPath}!`); - - // Create HMAC secret key - logger.info('Generating HMAC secret...'); - const secret = crypto.randomBytes(16); - logger.success('Generated RSA key pair!'); - - logger.info('Saving HMAC secret to disk...'); - fs.writeFileSync(secretKeyPath, secret.toString('hex')); - logger.success(`Saved HMAC secret to ${secretKeyPath}!`); - - logger.success('Keys generated successfully'); -} - -// Display usage information -function usage() { - console.log('Usage: node generate-keys.js type [name]'); - - console.log('Types:'); - console.log(' - nex'); - console.log(' - service'); - console.log(' - account'); - - console.log('Name: Service or NEX server name. Not used in account type'); -} - -main().catch(logger.error); \ No newline at end of file diff --git a/migrations/add-console-type-to-nex-account.js b/migrations/add-console-type-to-nex-account.js new file mode 100644 index 0000000..b92f208 --- /dev/null +++ b/migrations/add-console-type-to-nex-account.js @@ -0,0 +1,34 @@ +const database = require('../dist/database'); +const { NEXAccount } = require('../dist/models/nex-account'); + +database.connect().then(async function () { + const nexAccountsTotal = await NEXAccount.find({}); + const nexAccounts3DS = await NEXAccount.find({ device_type: '3ds' }); + const nexAccountsWiiU = await NEXAccount.find({ device_type: 'wiiu' }); + const nexAccountsToBeChanged = await NEXAccount.find({ + device_type: { + $exists: false + } + }); + + console.log('NEX accounts (Total):', nexAccountsTotal.length); + console.log('NEX accounts (3DS):', nexAccounts3DS.length); + console.log('NEX accounts (WiiU):', nexAccountsWiiU.length); + console.log('NEX accounts (To be changed):', nexAccountsToBeChanged.length); + + for (const nexAccount of nexAccountsToBeChanged) { + if (nexAccount.owning_pid !== nexAccount.pid) { + // 3DS account + nexAccount.device_type = '3ds'; + } else { + // WiiU account + nexAccount.device_type = 'wiiu'; + } + + await nexAccount.save(); + } + + console.log('Migrated accounts'); + + process.exit(0); +}); \ No newline at end of file diff --git a/migrations/add-console-type-to-nex-account/migration.js b/migrations/add-console-type-to-nex-account/migration.js deleted file mode 100644 index af581b4..0000000 --- a/migrations/add-console-type-to-nex-account/migration.js +++ /dev/null @@ -1,32 +0,0 @@ -const database = require('../../src/database'); -const { NEXAccount } = require('../../src/models/nex-account'); - -database.connect().then(async function () { - const nexAccounts = await NEXAccount.find({}); - const nexAccounts3DS = await NEXAccount.find({ device_type: '3ds' }); - const nexAccountsWiiU = await NEXAccount.find({ device_type: 'wiiu' }); - - console.log('NEX accounts:', nexAccounts.length); - console.log('NEX accounts (3DS):', nexAccounts3DS.length); - console.log('NEX accounts (WiiU):', nexAccountsWiiU.length); - - for (const nexAccount of nexAccounts) { - let deviceType = ''; - - if (nexAccount.owning_pid !== nexAccount.pid) { - // 3DS account - deviceType = '3ds'; - } else { - // WiiU account - deviceType = 'wiiu'; - } - - nexAccount.device_type = deviceType; - - await nexAccount.save(); - } - - console.log('Migrated accounts'); - - process.exit(0); -}); \ No newline at end of file diff --git a/migrations/add-missing-friendcodes.js b/migrations/add-missing-friendcodes.js new file mode 100644 index 0000000..4ac5aff --- /dev/null +++ b/migrations/add-missing-friendcodes.js @@ -0,0 +1,36 @@ +const crypto = require('node:crypto'); +const database = require('../dist/database'); +const { NEXAccount } = require('../dist/models/nex-account'); + +database.connect().then(async function () { + const nexAccountsToBeChanged = await NEXAccount.find({ + device_type: '3ds', + friend_code: { + $exists: false + } + }); + + for (const nexAccount of nexAccountsToBeChanged) { + + if (!nexAccount.friend_code) { + const pid = nexAccount.pid; + const pidBuffer = Buffer.alloc(4); + pidBuffer.writeUInt32LE(pid); + + const hash = crypto.createHash('sha1').update(pidBuffer); + const pidHash = hash.digest(); + const checksum = pidHash[0] >> 1; + const hex = checksum.toString(16) + pid.toString(16); + const int = parseInt(hex, 16); + const friendCode = int.toString().padStart(12, '0').match(/.{1,4}/g).join('-'); + + nexAccount.friend_code = friendCode; + + await nexAccount.save(); + } + } + + console.log('Migrated accounts'); + + process.exit(0); +}); \ No newline at end of file diff --git a/migrations/add-missing-server-aes-keys.js b/migrations/add-missing-server-aes-keys.js new file mode 100644 index 0000000..7a47379 --- /dev/null +++ b/migrations/add-missing-server-aes-keys.js @@ -0,0 +1,24 @@ +const crypto = require('node:crypto'); +const database = require('../dist/database'); +const { Server } = require('../dist/models/server'); + +database.connect().then(async function () { + const servers = await Server.find({ + aes_key: { + $exists: false + } + }); + + for (const server of servers) { + + if (!server.aes_key) { + server.aes_key = crypto.randomBytes(32).toString('hex'); + + await server.save(); + } + } + + console.log('Migrated accounts'); + + process.exit(0); +}); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 79df13e..aae2c06 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,63 +1,3240 @@ { "name": "account", - "version": "1.0.0", - "lockfileVersion": 2, + "version": "2.0.0", + "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "account", - "version": "1.0.0", + "version": "2.0.0", "license": "ISC", "dependencies": { - "aws-sdk": "^2.978.0", + "@aws-sdk/client-s3": "^3.657.0", + "@aws-sdk/client-ses": "^3.515.0", + "@inquirer/prompts": "^7.2.0", + "@pretendonetwork/grpc": "^1.0.5", "bcrypt": "^5.0.0", + "buffer-crc32": "^0.2.13", "colors": "^1.4.0", "cors": "^2.8.5", + "crc": "^4.3.2", "dicer": "^0.2.5", "dotenv": "^16.0.3", + "ejs": "^3.1.10", "email-validator": "^2.0.4", "express": "^4.17.1", - "express-form-data": "^2.0.17", - "express-rate-limit": "^5.3.0", - "express-subdomain": "^1.0.5", - "formidable": "^1.2.2", + "express-rate-limit": "^6.7.0", "fs-extra": "^8.1.0", "got": "^11.8.2", "hcaptcha": "^0.1.0", "image-pixels": "^1.1.1", - "joi": "^17.6.1", - "kaitai-struct": "^0.9.0", - "lodash.get": "^4.4.2", - "lodash.set": "^4.3.2", + "is-valid-hostname": "^1.0.2", + "joi": "^17.8.3", "mii-js": "github:PretendoNetwork/mii-js", - "moment": "^2.24.0", - "moment-timezone": "^0.5.27", - "mongoose": "^5.8.3", - "mongoose-unique-validator": "^2.0.3", + "moment": "^2.29.4", + "mongoose": "^7.0.0", + "mongoose-unique-validator": "^4.0.0", "morgan": "^1.9.1", - "multer": "^1.4.3", + "nice-grpc": "^2.1.4", + "node-rsa": "^1.0.7", "nodemailer": "^6.4.2", "redis": "^4.3.1", + "stripe": "^12.3.0", "tga": "^1.0.4", + "typescript-is": "^0.19.0", "validator": "^13.7.0", "xmlbuilder": "^13.0.2", - "xmlbuilder2": "0.0.4" + "xmlbuilder2": "0.0.4", + "zod": "^3.21.4" }, "devDependencies": { - "node-rsa": "^1.0.7", - "prompt": "^1.0.0", - "yesno": "^0.4.0" + "@hcaptcha/types": "^1.0.3", + "@types/bcrypt": "^5.0.0", + "@types/buffer-crc32": "^0.2.2", + "@types/cors": "^2.8.13", + "@types/dicer": "^0.2.2", + "@types/express": "^4.17.17", + "@types/fs-extra": "^11.0.1", + "@types/morgan": "^1.9.4", + "@types/ndarray": "^1.0.11", + "@types/node": "^18.14.4", + "@types/node-rsa": "^1.1.1", + "@types/nodemailer": "^6.4.7", + "@types/qs": "^6.9.7", + "@types/validator": "^13.7.14", + "@typescript-eslint/eslint-plugin": "^5.54.1", + "@typescript-eslint/parser": "^5.54.1", + "copyfiles": "^2.4.1", + "cross-env": "^7.0.3", + "eslint": "^8.35.0", + "ndarray": "^1.0.19", + "typescript": "^4.9.5" } }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", "dev": true, "engines": { - "node": ">=0.1.90" + "node": ">=0.10.0" } }, + "node_modules/@aws-crypto/crc32": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", + "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/crc32c": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz", + "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/crc32c/node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/crc32c/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/@aws-crypto/ie11-detection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", + "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", + "dependencies": { + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/sha1-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz", + "integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==", + "dependencies": { + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/@aws-crypto/sha256-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", + "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", + "dependencies": { + "@aws-crypto/ie11-detection": "^3.0.0", + "@aws-crypto/sha256-js": "^3.0.0", + "@aws-crypto/supports-web-crypto": "^3.0.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", + "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", + "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", + "dependencies": { + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/util": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", + "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-sdk/client-s3": { + "version": "3.657.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.657.0.tgz", + "integrity": "sha512-BonugBBJ8pBAbZDAzZI48ku9K7lRUf5dbxAokIDetrejrZlXk4uN0DxuWxy6iu6J2NOHYoqmRZdKvKADgQShWA==", + "dependencies": { + "@aws-crypto/sha1-browser": "5.2.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.654.0", + "@aws-sdk/client-sts": "3.654.0", + "@aws-sdk/core": "3.654.0", + "@aws-sdk/credential-provider-node": "3.654.0", + "@aws-sdk/middleware-bucket-endpoint": "3.654.0", + "@aws-sdk/middleware-expect-continue": "3.654.0", + "@aws-sdk/middleware-flexible-checksums": "3.657.0", + "@aws-sdk/middleware-host-header": "3.654.0", + "@aws-sdk/middleware-location-constraint": "3.654.0", + "@aws-sdk/middleware-logger": "3.654.0", + "@aws-sdk/middleware-recursion-detection": "3.654.0", + "@aws-sdk/middleware-sdk-s3": "3.654.0", + "@aws-sdk/middleware-ssec": "3.654.0", + "@aws-sdk/middleware-user-agent": "3.654.0", + "@aws-sdk/region-config-resolver": "3.654.0", + "@aws-sdk/signature-v4-multi-region": "3.654.0", + "@aws-sdk/types": "3.654.0", + "@aws-sdk/util-endpoints": "3.654.0", + "@aws-sdk/util-user-agent-browser": "3.654.0", + "@aws-sdk/util-user-agent-node": "3.654.0", + "@aws-sdk/xml-builder": "3.654.0", + "@smithy/config-resolver": "^3.0.8", + "@smithy/core": "^2.4.3", + "@smithy/eventstream-serde-browser": "^3.0.9", + "@smithy/eventstream-serde-config-resolver": "^3.0.6", + "@smithy/eventstream-serde-node": "^3.0.8", + "@smithy/fetch-http-handler": "^3.2.7", + "@smithy/hash-blob-browser": "^3.1.5", + "@smithy/hash-node": "^3.0.6", + "@smithy/hash-stream-node": "^3.1.5", + "@smithy/invalid-dependency": "^3.0.6", + "@smithy/md5-js": "^3.0.6", + "@smithy/middleware-content-length": "^3.0.8", + "@smithy/middleware-endpoint": "^3.1.3", + "@smithy/middleware-retry": "^3.0.18", + "@smithy/middleware-serde": "^3.0.6", + "@smithy/middleware-stack": "^3.0.6", + "@smithy/node-config-provider": "^3.1.7", + "@smithy/node-http-handler": "^3.2.2", + "@smithy/protocol-http": "^4.1.3", + "@smithy/smithy-client": "^3.3.2", + "@smithy/types": "^3.4.2", + "@smithy/url-parser": "^3.0.6", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.18", + "@smithy/util-defaults-mode-node": "^3.0.18", + "@smithy/util-endpoints": "^2.1.2", + "@smithy/util-middleware": "^3.0.6", + "@smithy/util-retry": "^3.0.6", + "@smithy/util-stream": "^3.1.6", + "@smithy/util-utf8": "^3.0.0", + "@smithy/util-waiter": "^3.1.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "dependencies": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/client-sso": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.654.0.tgz", + "integrity": "sha512-4kBxs2IzCDtj6a6lRXa/lXK5wWpMGzwKtb+HMXf/rJYVM6x7wYRzc1hYrOd3DYkFQ/sR3dUFj+0mTP0os3aAbA==", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.654.0", + "@aws-sdk/middleware-host-header": "3.654.0", + "@aws-sdk/middleware-logger": "3.654.0", + "@aws-sdk/middleware-recursion-detection": "3.654.0", + "@aws-sdk/middleware-user-agent": "3.654.0", + "@aws-sdk/region-config-resolver": "3.654.0", + "@aws-sdk/types": "3.654.0", + "@aws-sdk/util-endpoints": "3.654.0", + "@aws-sdk/util-user-agent-browser": "3.654.0", + "@aws-sdk/util-user-agent-node": "3.654.0", + "@smithy/config-resolver": "^3.0.8", + "@smithy/core": "^2.4.3", + "@smithy/fetch-http-handler": "^3.2.7", + "@smithy/hash-node": "^3.0.6", + "@smithy/invalid-dependency": "^3.0.6", + "@smithy/middleware-content-length": "^3.0.8", + "@smithy/middleware-endpoint": "^3.1.3", + "@smithy/middleware-retry": "^3.0.18", + "@smithy/middleware-serde": "^3.0.6", + "@smithy/middleware-stack": "^3.0.6", + "@smithy/node-config-provider": "^3.1.7", + "@smithy/node-http-handler": "^3.2.2", + "@smithy/protocol-http": "^4.1.3", + "@smithy/smithy-client": "^3.3.2", + "@smithy/types": "^3.4.2", + "@smithy/url-parser": "^3.0.6", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.18", + "@smithy/util-defaults-mode-node": "^3.0.18", + "@smithy/util-endpoints": "^2.1.2", + "@smithy/util-middleware": "^3.0.6", + "@smithy/util-retry": "^3.0.6", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/client-sso-oidc": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.654.0.tgz", + "integrity": "sha512-gbHrKsEnaAtmkNCVQzLyiqMzpDaThV/bWl/ODEklI+t6stW3Pe3oDMstEHLfJ6JU5g8sYnx4VLuxlnJMtUkvPw==", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.654.0", + "@aws-sdk/credential-provider-node": "3.654.0", + "@aws-sdk/middleware-host-header": "3.654.0", + "@aws-sdk/middleware-logger": "3.654.0", + "@aws-sdk/middleware-recursion-detection": "3.654.0", + "@aws-sdk/middleware-user-agent": "3.654.0", + "@aws-sdk/region-config-resolver": "3.654.0", + "@aws-sdk/types": "3.654.0", + "@aws-sdk/util-endpoints": "3.654.0", + "@aws-sdk/util-user-agent-browser": "3.654.0", + "@aws-sdk/util-user-agent-node": "3.654.0", + "@smithy/config-resolver": "^3.0.8", + "@smithy/core": "^2.4.3", + "@smithy/fetch-http-handler": "^3.2.7", + "@smithy/hash-node": "^3.0.6", + "@smithy/invalid-dependency": "^3.0.6", + "@smithy/middleware-content-length": "^3.0.8", + "@smithy/middleware-endpoint": "^3.1.3", + "@smithy/middleware-retry": "^3.0.18", + "@smithy/middleware-serde": "^3.0.6", + "@smithy/middleware-stack": "^3.0.6", + "@smithy/node-config-provider": "^3.1.7", + "@smithy/node-http-handler": "^3.2.2", + "@smithy/protocol-http": "^4.1.3", + "@smithy/smithy-client": "^3.3.2", + "@smithy/types": "^3.4.2", + "@smithy/url-parser": "^3.0.6", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.18", + "@smithy/util-defaults-mode-node": "^3.0.18", + "@smithy/util-endpoints": "^2.1.2", + "@smithy/util-middleware": "^3.0.6", + "@smithy/util-retry": "^3.0.6", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.654.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/client-sts": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.654.0.tgz", + "integrity": "sha512-tyHa8jsBy+/NQZFHm6Q2Q09Vi9p3EH4yPy6PU8yPewpi2klreObtrUd0anJa6nzjS9SSuqnlZWsRic3cQ4QwCg==", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.654.0", + "@aws-sdk/core": "3.654.0", + "@aws-sdk/credential-provider-node": "3.654.0", + "@aws-sdk/middleware-host-header": "3.654.0", + "@aws-sdk/middleware-logger": "3.654.0", + "@aws-sdk/middleware-recursion-detection": "3.654.0", + "@aws-sdk/middleware-user-agent": "3.654.0", + "@aws-sdk/region-config-resolver": "3.654.0", + "@aws-sdk/types": "3.654.0", + "@aws-sdk/util-endpoints": "3.654.0", + "@aws-sdk/util-user-agent-browser": "3.654.0", + "@aws-sdk/util-user-agent-node": "3.654.0", + "@smithy/config-resolver": "^3.0.8", + "@smithy/core": "^2.4.3", + "@smithy/fetch-http-handler": "^3.2.7", + "@smithy/hash-node": "^3.0.6", + "@smithy/invalid-dependency": "^3.0.6", + "@smithy/middleware-content-length": "^3.0.8", + "@smithy/middleware-endpoint": "^3.1.3", + "@smithy/middleware-retry": "^3.0.18", + "@smithy/middleware-serde": "^3.0.6", + "@smithy/middleware-stack": "^3.0.6", + "@smithy/node-config-provider": "^3.1.7", + "@smithy/node-http-handler": "^3.2.2", + "@smithy/protocol-http": "^4.1.3", + "@smithy/smithy-client": "^3.3.2", + "@smithy/types": "^3.4.2", + "@smithy/url-parser": "^3.0.6", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.18", + "@smithy/util-defaults-mode-node": "^3.0.18", + "@smithy/util-endpoints": "^2.1.2", + "@smithy/util-middleware": "^3.0.6", + "@smithy/util-retry": "^3.0.6", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/core": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.654.0.tgz", + "integrity": "sha512-4Rwx7BVaNaFqmXBDmnOkMbyuIFFbpZ+ru4lr660p45zY1QoNNSalechfoRffcokLFOZO+VWEJkdcorPUUU993w==", + "dependencies": { + "@smithy/core": "^2.4.3", + "@smithy/node-config-provider": "^3.1.7", + "@smithy/property-provider": "^3.1.6", + "@smithy/protocol-http": "^4.1.3", + "@smithy/signature-v4": "^4.1.3", + "@smithy/smithy-client": "^3.3.2", + "@smithy/types": "^3.4.2", + "@smithy/util-middleware": "^3.0.6", + "fast-xml-parser": "4.4.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-env": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.654.0.tgz", + "integrity": "sha512-kogsx3Ql81JouHS7DkheCDU9MYAvK0AokxjcshDveGmf7BbgbWCA8Fnb9wjQyNDaOXNvkZu8Z8rgkX91z324/w==", + "dependencies": { + "@aws-sdk/types": "3.654.0", + "@smithy/property-provider": "^3.1.6", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-http": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.654.0.tgz", + "integrity": "sha512-tgmAH4MBi/aDR882lfw48+tDV95ZH3GWc1Eoe6DpNLiM3GN2VfU/cZwuHmi6aq+vAbdIlswBHJ/+va0fOvlyjw==", + "dependencies": { + "@aws-sdk/types": "3.654.0", + "@smithy/fetch-http-handler": "^3.2.7", + "@smithy/node-http-handler": "^3.2.2", + "@smithy/property-provider": "^3.1.6", + "@smithy/protocol-http": "^4.1.3", + "@smithy/smithy-client": "^3.3.2", + "@smithy/types": "^3.4.2", + "@smithy/util-stream": "^3.1.6", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.654.0.tgz", + "integrity": "sha512-DKSdaNu2hwdmuvnm9KnA0NLqMWxxmxSOLWjSUSoFIm++wGXUjPrRMFYKvMktaXnPuyf5my8gF/yGbwzPZ8wlTg==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.654.0", + "@aws-sdk/credential-provider-http": "3.654.0", + "@aws-sdk/credential-provider-process": "3.654.0", + "@aws-sdk/credential-provider-sso": "3.654.0", + "@aws-sdk/credential-provider-web-identity": "3.654.0", + "@aws-sdk/types": "3.654.0", + "@smithy/credential-provider-imds": "^3.2.3", + "@smithy/property-provider": "^3.1.6", + "@smithy/shared-ini-file-loader": "^3.1.7", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.654.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-node": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.654.0.tgz", + "integrity": "sha512-wPV7CNYaXDEc+SS+3R0v8SZwkHRUE1z2k2j1d49tH5QBDT4tb/k2V/biXWkwSk3hbR+IMWXmuhJDv/5lybhIvg==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.654.0", + "@aws-sdk/credential-provider-http": "3.654.0", + "@aws-sdk/credential-provider-ini": "3.654.0", + "@aws-sdk/credential-provider-process": "3.654.0", + "@aws-sdk/credential-provider-sso": "3.654.0", + "@aws-sdk/credential-provider-web-identity": "3.654.0", + "@aws-sdk/types": "3.654.0", + "@smithy/credential-provider-imds": "^3.2.3", + "@smithy/property-provider": "^3.1.6", + "@smithy/shared-ini-file-loader": "^3.1.7", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-process": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.654.0.tgz", + "integrity": "sha512-PmQoo8sZ9Q2Ow8OMzK++Z9lI7MsRUG7sNq3E72DVA215dhtTICTDQwGlXH2AAmIp7n+G9LLRds+4wo2ehG4mkg==", + "dependencies": { + "@aws-sdk/types": "3.654.0", + "@smithy/property-provider": "^3.1.6", + "@smithy/shared-ini-file-loader": "^3.1.7", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.654.0.tgz", + "integrity": "sha512-7GFme6fWEdA/XYKzZPOAdj/jS6fMBy1NdSIZsDXikS0v9jU+ZzHrAaWt13YLzHyjgxB9Sg9id9ncdY1IiubQXQ==", + "dependencies": { + "@aws-sdk/client-sso": "3.654.0", + "@aws-sdk/token-providers": "3.654.0", + "@aws-sdk/types": "3.654.0", + "@smithy/property-provider": "^3.1.6", + "@smithy/shared-ini-file-loader": "^3.1.7", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.654.0.tgz", + "integrity": "sha512-6a2g9gMtZToqSu+CusjNK5zvbLJahQ9di7buO3iXgbizXpLXU1rnawCpWxwslMpT5fLgMSKDnKDrr6wdEk7jSw==", + "dependencies": { + "@aws-sdk/types": "3.654.0", + "@smithy/property-provider": "^3.1.6", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.654.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-host-header": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.654.0.tgz", + "integrity": "sha512-rxGgVHWKp8U2ubMv+t+vlIk7QYUaRCHaVpmUlJv0Wv6Q0KeO9a42T9FxHphjOTlCGQOLcjCreL9CF8Qhtb4mdQ==", + "dependencies": { + "@aws-sdk/types": "3.654.0", + "@smithy/protocol-http": "^4.1.3", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-logger": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.654.0.tgz", + "integrity": "sha512-OQYb+nWlmASyXfRb989pwkJ9EVUMP1CrKn2eyTk3usl20JZmKo2Vjis6I0tLUkMSxMhnBJJlQKyWkRpD/u1FVg==", + "dependencies": { + "@aws-sdk/types": "3.654.0", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.654.0.tgz", + "integrity": "sha512-gKSomgltKVmsT8sC6W7CrADZ4GHwX9epk3GcH6QhebVO3LA9LRbkL3TwOPUXakxxOLLUTYdOZLIOtFf7iH00lg==", + "dependencies": { + "@aws-sdk/types": "3.654.0", + "@smithy/protocol-http": "^4.1.3", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.654.0.tgz", + "integrity": "sha512-liCcqPAyRsr53cy2tYu4qeH4MMN0eh9g6k56XzI5xd4SghXH5YWh4qOYAlQ8T66ZV4nPMtD8GLtLXGzsH8moFg==", + "dependencies": { + "@aws-sdk/types": "3.654.0", + "@aws-sdk/util-endpoints": "3.654.0", + "@smithy/protocol-http": "^4.1.3", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/region-config-resolver": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.654.0.tgz", + "integrity": "sha512-ydGOrXJxj3x0sJhsXyTmvJVLAE0xxuTWFJihTl67RtaO7VRNtd82I3P3bwoMMaDn5WpmV5mPo8fEUDRlBm3fPg==", + "dependencies": { + "@aws-sdk/types": "3.654.0", + "@smithy/node-config-provider": "^3.1.7", + "@smithy/types": "^3.4.2", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.6", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/token-providers": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.654.0.tgz", + "integrity": "sha512-D8GeJYmvbfWkQDtTB4owmIobSMexZel0fOoetwvgCQ/7L8VPph3Q2bn1TRRIXvH7wdt6DcDxA3tKMHPBkT3GlA==", + "dependencies": { + "@aws-sdk/types": "3.654.0", + "@smithy/property-provider": "^3.1.6", + "@smithy/shared-ini-file-loader": "^3.1.7", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sso-oidc": "^3.654.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/types": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.654.0.tgz", + "integrity": "sha512-VWvbED3SV+10QJIcmU/PKjsKilsTV16d1I7/on4bvD/jo1qGeMXqLDBSen3ks/tuvXZF/mFc7ZW/W2DiLVtO7A==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/util-endpoints": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.654.0.tgz", + "integrity": "sha512-i902fcBknHs0Irgdpi62+QMvzxE+bczvILXigYrlHL4+PiEnlMVpni5L5W1qCkNZXf8AaMrSBuR1NZAGp6UOUw==", + "dependencies": { + "@aws-sdk/types": "3.654.0", + "@smithy/types": "^3.4.2", + "@smithy/util-endpoints": "^2.1.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.654.0.tgz", + "integrity": "sha512-ykYAJqvnxLt7wfrqya28wuH3/7NdrwzfiFd7NqEVQf7dXVxL5RPEpD7DxjcyQo3DsHvvdUvGZVaQhozycn1pzA==", + "dependencies": { + "@aws-sdk/types": "3.654.0", + "@smithy/types": "^3.4.2", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.654.0.tgz", + "integrity": "sha512-a0ojjdBN6pqv6gB4H/QPPSfhs7mFtlVwnmKCM/QrTaFzN0U810PJ1BST3lBx5sa23I5jWHGaoFY+5q65C3clLQ==", + "dependencies": { + "@aws-sdk/types": "3.654.0", + "@smithy/node-config-provider": "^3.1.7", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/abort-controller": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.4.tgz", + "integrity": "sha512-VupaALAQlXViW3/enTf/f5l5JZYSAxoJL7f0nanhNNKnww6DGCg1oYIuNP78KDugnkwthBO6iEcym16HhWV8RQ==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/config-resolver": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.8.tgz", + "integrity": "sha512-Tv1obAC18XOd2OnDAjSWmmthzx6Pdeh63FbLin8MlPiuJ2ATpKkq0NcNOJFr0dO+JmZXnwu8FQxKJ3TKJ3Hulw==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.7", + "@smithy/types": "^3.4.2", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.6", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/core": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.4.5.tgz", + "integrity": "sha512-Z0qlPXgZ0pouYgnu/cZTEYeRAvniiKZmVl4wIbZHX/nEMHkMDV9ao6KFArsU9KndE0TuhL149xcRx45wfw1YCA==", + "dependencies": { + "@smithy/middleware-endpoint": "^3.1.3", + "@smithy/middleware-retry": "^3.0.20", + "@smithy/middleware-serde": "^3.0.6", + "@smithy/protocol-http": "^4.1.3", + "@smithy/smithy-client": "^3.3.4", + "@smithy/types": "^3.4.2", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-middleware": "^3.0.6", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/credential-provider-imds": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.3.tgz", + "integrity": "sha512-VoxMzSzdvkkjMJNE38yQgx4CfnmT+Z+5EUXkg4x7yag93eQkVQgZvN3XBSHC/ylfBbLbAtdu7flTCChX9I+mVg==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.7", + "@smithy/property-provider": "^3.1.6", + "@smithy/types": "^3.4.2", + "@smithy/url-parser": "^3.0.6", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/fetch-http-handler": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.8.tgz", + "integrity": "sha512-Lqe0B8F5RM7zkw//6avq1SJ8AfaRd3ubFUS1eVp5WszV7p6Ne5hQ4dSuMHDpNRPhgTvj4va9Kd/pcVigHEHRow==", + "dependencies": { + "@smithy/protocol-http": "^4.1.3", + "@smithy/querystring-builder": "^3.0.6", + "@smithy/types": "^3.4.2", + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/hash-node": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.6.tgz", + "integrity": "sha512-c/FHEdKK/7DU2z6ZE91L36ahyXWayR3B+FzELjnYq7wH5YqIseM24V+pWCS9kFn1Ln8OFGTf+pyYPiHZuX0s/Q==", + "dependencies": { + "@smithy/types": "^3.4.2", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/invalid-dependency": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.6.tgz", + "integrity": "sha512-czM7Ioq3s8pIXht7oD+vmgy4Wfb4XavU/k/irO8NdXFFOx7YAlsCCcKOh/lJD1mJSYQqiR7NmpZ9JviryD/7AQ==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/middleware-content-length": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.8.tgz", + "integrity": "sha512-VuyszlSO49WKh3H9/kIO2kf07VUwGV80QRiaDxUfP8P8UKlokz381ETJvwLhwuypBYhLymCYyNhB3fLAGBX2og==", + "dependencies": { + "@smithy/protocol-http": "^4.1.3", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/middleware-endpoint": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.1.3.tgz", + "integrity": "sha512-KeM/OrK8MVFUsoJsmCN0MZMVPjKKLudn13xpgwIMpGTYpA8QZB2Xq5tJ+RE6iu3A6NhOI4VajDTwBsm8pwwrhg==", + "dependencies": { + "@smithy/middleware-serde": "^3.0.6", + "@smithy/node-config-provider": "^3.1.7", + "@smithy/shared-ini-file-loader": "^3.1.7", + "@smithy/types": "^3.4.2", + "@smithy/url-parser": "^3.0.6", + "@smithy/util-middleware": "^3.0.6", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/middleware-retry": { + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.20.tgz", + "integrity": "sha512-HELCOVwYw5hFDBm69d+LmmGjBCjWnwp/t7SJiHmp+c4u9vgfIaCjdSeIdnlOsLrr5ic5jGTJXvJFUQnd987b/g==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.7", + "@smithy/protocol-http": "^4.1.3", + "@smithy/service-error-classification": "^3.0.6", + "@smithy/smithy-client": "^3.3.4", + "@smithy/types": "^3.4.2", + "@smithy/util-middleware": "^3.0.6", + "@smithy/util-retry": "^3.0.6", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/middleware-serde": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.6.tgz", + "integrity": "sha512-KKTUSl1MzOM0MAjGbudeaVNtIDo+PpekTBkCNwvfZlKndodrnvRo+00USatiyLOc0ujjO9UydMRu3O9dYML7ag==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/middleware-stack": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.6.tgz", + "integrity": "sha512-2c0eSYhTQ8xQqHMcRxLMpadFbTXg6Zla5l0mwNftFCZMQmuhI7EbAJMx6R5eqfuV3YbJ3QGyS3d5uSmrHV8Khg==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/node-config-provider": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.7.tgz", + "integrity": "sha512-g3mfnC3Oo8pOI0dYuPXLtdW1WGVb3bR2tkV21GNkm0ZvQjLTtamXAwCWt/FCb0HGvKt3gHHmF1XerG0ICfalOg==", + "dependencies": { + "@smithy/property-provider": "^3.1.6", + "@smithy/shared-ini-file-loader": "^3.1.7", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/node-http-handler": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.2.3.tgz", + "integrity": "sha512-/gcm5DJ3k1b1zEInzBGAZC8ntJ+jwrz1NcSIu+9dSXd1FfG0G6QgkDI40tt8/WYUbHtLyo8fEqtm2v29koWo/w==", + "dependencies": { + "@smithy/abort-controller": "^3.1.4", + "@smithy/protocol-http": "^4.1.3", + "@smithy/querystring-builder": "^3.0.6", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/property-provider": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.6.tgz", + "integrity": "sha512-NK3y/T7Q/Bw+Z8vsVs9MYIQ5v7gOX7clyrXcwhhIBQhbPgRl6JDrZbusO9qWDhcEus75Tg+VCxtIRfo3H76fpw==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/protocol-http": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.3.tgz", + "integrity": "sha512-GcbMmOYpH9iRqtC05RbRnc/0FssxSTHlmaNhYBTgSgNCYpdR3Kt88u5GAZTBmouzv+Zlj/VRv92J9ruuDeJuEw==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/querystring-builder": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.6.tgz", + "integrity": "sha512-sQe08RunoObe+Usujn9+R2zrLuQERi3CWvRO3BvnoWSYUaIrLKuAIeY7cMeDax6xGyfIP3x/yFWbEKSXvOnvVg==", + "dependencies": { + "@smithy/types": "^3.4.2", + "@smithy/util-uri-escape": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/querystring-parser": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.6.tgz", + "integrity": "sha512-UJKw4LlEkytzz2Wq+uIdHf6qOtFfee/o7ruH0jF5I6UAuU+19r9QV7nU3P/uI0l6+oElRHmG/5cBBcGJrD7Ozg==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/service-error-classification": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.6.tgz", + "integrity": "sha512-53SpchU3+DUZrN7J6sBx9tBiCVGzsib2e4sc512Q7K9fpC5zkJKs6Z9s+qbMxSYrkEkle6hnMtrts7XNkMJJMg==", + "dependencies": { + "@smithy/types": "^3.4.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/shared-ini-file-loader": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.7.tgz", + "integrity": "sha512-IA4K2qTJYXkF5OfVN4vsY1hfnUZjaslEE8Fsr/gGFza4TAC2A9NfnZuSY2srQIbt9bwtjHiAayrRVgKse4Q7fA==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/signature-v4": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.1.4.tgz", + "integrity": "sha512-72MiK7xYukNsnLJI9NqvUHqTu0ziEsfMsYNlWpiJfuGQnCTFKpckThlEatirvcA/LmT1h7rRO+pJD06PYsPu9Q==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/protocol-http": "^4.1.3", + "@smithy/types": "^3.4.2", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-middleware": "^3.0.6", + "@smithy/util-uri-escape": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/smithy-client": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.3.4.tgz", + "integrity": "sha512-NKw/2XxOW/Rg3rzB90HxsmGok5oS6vRzJgMh/JN4BHaOQQ4q5OuX999GmOGxEp730wbpIXIowfKZmIMXkG4v0Q==", + "dependencies": { + "@smithy/middleware-endpoint": "^3.1.3", + "@smithy/middleware-stack": "^3.0.6", + "@smithy/protocol-http": "^4.1.3", + "@smithy/types": "^3.4.2", + "@smithy/util-stream": "^3.1.8", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/types": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.4.2.tgz", + "integrity": "sha512-tHiFcfcVedVBHpmHUEUHOCCih8iZbIAYn9NvPsNzaPm/237I3imdDdZoOC8c87H5HBAVEa06tTgb+OcSWV9g5w==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/url-parser": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.6.tgz", + "integrity": "sha512-47Op/NU8Opt49KyGpHtVdnmmJMsp2hEwBdyjuFB9M2V5QVOwA7pBhhxKN5z6ztKGrMw76gd8MlbPuzzvaAncuQ==", + "dependencies": { + "@smithy/querystring-parser": "^3.0.6", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/util-base64": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", + "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/util-body-length-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", + "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/util-body-length-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz", + "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/util-config-provider": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", + "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/util-defaults-mode-browser": { + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.20.tgz", + "integrity": "sha512-HpYmCpEThQJpCKzwzrGrklhdegRfuXI9keHRrHidbyEMliCdgic6t38MikJeZEkdIcEMhO1g95HIYMzjUzB+xg==", + "dependencies": { + "@smithy/property-provider": "^3.1.6", + "@smithy/smithy-client": "^3.3.4", + "@smithy/types": "^3.4.2", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/util-defaults-mode-node": { + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.20.tgz", + "integrity": "sha512-atdsHNtAX0rwTvRRGsrONU0C0XzapH6tI8T1y/OReOvWN7uBwXqqWRft6m8egU2DgeReU0xqT3PHdGCe5VRaaQ==", + "dependencies": { + "@smithy/config-resolver": "^3.0.8", + "@smithy/credential-provider-imds": "^3.2.3", + "@smithy/node-config-provider": "^3.1.7", + "@smithy/property-provider": "^3.1.6", + "@smithy/smithy-client": "^3.3.4", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/util-endpoints": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.1.2.tgz", + "integrity": "sha512-FEISzffb4H8DLzGq1g4MuDpcv6CIG15fXoQzDH9SjpRJv6h7J++1STFWWinilG0tQh9H1v2UKWG19Jjr2B16zQ==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.7", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/util-hex-encoding": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", + "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/util-middleware": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.6.tgz", + "integrity": "sha512-BxbX4aBhI1O9p87/xM+zWy0GzT3CEVcXFPBRDoHAM+pV0eSW156pR+PSYEz0DQHDMYDsYAflC2bQNz2uaDBUZQ==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/util-retry": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.6.tgz", + "integrity": "sha512-BRZiuF7IwDntAbevqMco67an0Sr9oLQJqqRCsSPZZHYRnehS0LHDAkJk/pSmI7Z8c/1Vet294H7fY2fWUgB+Rg==", + "dependencies": { + "@smithy/service-error-classification": "^3.0.6", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/util-stream": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.1.8.tgz", + "integrity": "sha512-hoKOqSmb8FD3WLObuB5hwbM7bNIWgcnvkThokTvVq7J5PKjlLUK5qQQcB9zWLHIoSaIlf3VIv2OxZY2wtQjcRQ==", + "dependencies": { + "@smithy/fetch-http-handler": "^3.2.8", + "@smithy/node-http-handler": "^3.2.3", + "@smithy/types": "^3.4.2", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/util-uri-escape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", + "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@smithy/util-waiter": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-3.1.5.tgz", + "integrity": "sha512-jYOSvM3H6sZe3CHjzD2VQNCjWBJs+4DbtwBMvUp9y5EnnwNa7NQxTeYeQw0CKCAdGGZ3QvVkyJmvbvs5M/B10A==", + "dependencies": { + "@smithy/abort-controller": "^3.1.4", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/@aws-sdk/client-s3/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@aws-sdk/client-ses": { + "version": "3.515.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-ses/-/client-ses-3.515.0.tgz", + "integrity": "sha512-X51TvcpqJ83ZOSUa/efWl+cj3cXBF6fCb2iNghjRD2McDvzGKoiR+Zaoy05doPdh/GZ7azTBqX0qKRIyUj//wg==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.515.0", + "@aws-sdk/core": "3.513.0", + "@aws-sdk/credential-provider-node": "3.515.0", + "@aws-sdk/middleware-host-header": "3.515.0", + "@aws-sdk/middleware-logger": "3.515.0", + "@aws-sdk/middleware-recursion-detection": "3.515.0", + "@aws-sdk/middleware-user-agent": "3.515.0", + "@aws-sdk/region-config-resolver": "3.515.0", + "@aws-sdk/types": "3.515.0", + "@aws-sdk/util-endpoints": "3.515.0", + "@aws-sdk/util-user-agent-browser": "3.515.0", + "@aws-sdk/util-user-agent-node": "3.515.0", + "@smithy/config-resolver": "^2.1.1", + "@smithy/core": "^1.3.2", + "@smithy/fetch-http-handler": "^2.4.1", + "@smithy/hash-node": "^2.1.1", + "@smithy/invalid-dependency": "^2.1.1", + "@smithy/middleware-content-length": "^2.1.1", + "@smithy/middleware-endpoint": "^2.4.1", + "@smithy/middleware-retry": "^2.1.1", + "@smithy/middleware-serde": "^2.1.1", + "@smithy/middleware-stack": "^2.1.1", + "@smithy/node-config-provider": "^2.2.1", + "@smithy/node-http-handler": "^2.3.1", + "@smithy/protocol-http": "^3.1.1", + "@smithy/smithy-client": "^2.3.1", + "@smithy/types": "^2.9.1", + "@smithy/url-parser": "^2.1.1", + "@smithy/util-base64": "^2.1.1", + "@smithy/util-body-length-browser": "^2.1.1", + "@smithy/util-body-length-node": "^2.2.1", + "@smithy/util-defaults-mode-browser": "^2.1.1", + "@smithy/util-defaults-mode-node": "^2.2.0", + "@smithy/util-endpoints": "^1.1.1", + "@smithy/util-middleware": "^2.1.1", + "@smithy/util-retry": "^2.1.1", + "@smithy/util-utf8": "^2.1.1", + "@smithy/util-waiter": "^2.1.1", + "fast-xml-parser": "4.2.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-ses/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/client-sso": { + "version": "3.515.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.515.0.tgz", + "integrity": "sha512-4oGBLW476zmkdN98lAns3bObRNO+DLOfg4MDUSR6l6GYBV/zGAtoy2O/FhwYKgA2L5h2ZtElGopLlk/1Q0ePLw==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/core": "3.513.0", + "@aws-sdk/middleware-host-header": "3.515.0", + "@aws-sdk/middleware-logger": "3.515.0", + "@aws-sdk/middleware-recursion-detection": "3.515.0", + "@aws-sdk/middleware-user-agent": "3.515.0", + "@aws-sdk/region-config-resolver": "3.515.0", + "@aws-sdk/types": "3.515.0", + "@aws-sdk/util-endpoints": "3.515.0", + "@aws-sdk/util-user-agent-browser": "3.515.0", + "@aws-sdk/util-user-agent-node": "3.515.0", + "@smithy/config-resolver": "^2.1.1", + "@smithy/core": "^1.3.2", + "@smithy/fetch-http-handler": "^2.4.1", + "@smithy/hash-node": "^2.1.1", + "@smithy/invalid-dependency": "^2.1.1", + "@smithy/middleware-content-length": "^2.1.1", + "@smithy/middleware-endpoint": "^2.4.1", + "@smithy/middleware-retry": "^2.1.1", + "@smithy/middleware-serde": "^2.1.1", + "@smithy/middleware-stack": "^2.1.1", + "@smithy/node-config-provider": "^2.2.1", + "@smithy/node-http-handler": "^2.3.1", + "@smithy/protocol-http": "^3.1.1", + "@smithy/smithy-client": "^2.3.1", + "@smithy/types": "^2.9.1", + "@smithy/url-parser": "^2.1.1", + "@smithy/util-base64": "^2.1.1", + "@smithy/util-body-length-browser": "^2.1.1", + "@smithy/util-body-length-node": "^2.2.1", + "@smithy/util-defaults-mode-browser": "^2.1.1", + "@smithy/util-defaults-mode-node": "^2.2.0", + "@smithy/util-endpoints": "^1.1.1", + "@smithy/util-middleware": "^2.1.1", + "@smithy/util-retry": "^2.1.1", + "@smithy/util-utf8": "^2.1.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sso-oidc": { + "version": "3.515.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.515.0.tgz", + "integrity": "sha512-zACa8LNlPUdlNUBqQRf5a3MfouLNtcBfm84v2c8M976DwJrMGONPe1QjyLLsD38uESQiXiVQRruj/b000iMXNw==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.515.0", + "@aws-sdk/core": "3.513.0", + "@aws-sdk/middleware-host-header": "3.515.0", + "@aws-sdk/middleware-logger": "3.515.0", + "@aws-sdk/middleware-recursion-detection": "3.515.0", + "@aws-sdk/middleware-user-agent": "3.515.0", + "@aws-sdk/region-config-resolver": "3.515.0", + "@aws-sdk/types": "3.515.0", + "@aws-sdk/util-endpoints": "3.515.0", + "@aws-sdk/util-user-agent-browser": "3.515.0", + "@aws-sdk/util-user-agent-node": "3.515.0", + "@smithy/config-resolver": "^2.1.1", + "@smithy/core": "^1.3.2", + "@smithy/fetch-http-handler": "^2.4.1", + "@smithy/hash-node": "^2.1.1", + "@smithy/invalid-dependency": "^2.1.1", + "@smithy/middleware-content-length": "^2.1.1", + "@smithy/middleware-endpoint": "^2.4.1", + "@smithy/middleware-retry": "^2.1.1", + "@smithy/middleware-serde": "^2.1.1", + "@smithy/middleware-stack": "^2.1.1", + "@smithy/node-config-provider": "^2.2.1", + "@smithy/node-http-handler": "^2.3.1", + "@smithy/protocol-http": "^3.1.1", + "@smithy/smithy-client": "^2.3.1", + "@smithy/types": "^2.9.1", + "@smithy/url-parser": "^2.1.1", + "@smithy/util-base64": "^2.1.1", + "@smithy/util-body-length-browser": "^2.1.1", + "@smithy/util-body-length-node": "^2.2.1", + "@smithy/util-defaults-mode-browser": "^2.1.1", + "@smithy/util-defaults-mode-node": "^2.2.0", + "@smithy/util-endpoints": "^1.1.1", + "@smithy/util-middleware": "^2.1.1", + "@smithy/util-retry": "^2.1.1", + "@smithy/util-utf8": "^2.1.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "@aws-sdk/credential-provider-node": "^3.515.0" + } + }, + "node_modules/@aws-sdk/client-sso-oidc/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/client-sso/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/client-sts": { + "version": "3.515.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.515.0.tgz", + "integrity": "sha512-ScYuvaIDgip3atOJIA1FU2n0gJkEdveu1KrrCPathoUCV5zpK8qQmO/n+Fj/7hKFxeKdFbB+4W4CsJWYH94nlg==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/core": "3.513.0", + "@aws-sdk/middleware-host-header": "3.515.0", + "@aws-sdk/middleware-logger": "3.515.0", + "@aws-sdk/middleware-recursion-detection": "3.515.0", + "@aws-sdk/middleware-user-agent": "3.515.0", + "@aws-sdk/region-config-resolver": "3.515.0", + "@aws-sdk/types": "3.515.0", + "@aws-sdk/util-endpoints": "3.515.0", + "@aws-sdk/util-user-agent-browser": "3.515.0", + "@aws-sdk/util-user-agent-node": "3.515.0", + "@smithy/config-resolver": "^2.1.1", + "@smithy/core": "^1.3.2", + "@smithy/fetch-http-handler": "^2.4.1", + "@smithy/hash-node": "^2.1.1", + "@smithy/invalid-dependency": "^2.1.1", + "@smithy/middleware-content-length": "^2.1.1", + "@smithy/middleware-endpoint": "^2.4.1", + "@smithy/middleware-retry": "^2.1.1", + "@smithy/middleware-serde": "^2.1.1", + "@smithy/middleware-stack": "^2.1.1", + "@smithy/node-config-provider": "^2.2.1", + "@smithy/node-http-handler": "^2.3.1", + "@smithy/protocol-http": "^3.1.1", + "@smithy/smithy-client": "^2.3.1", + "@smithy/types": "^2.9.1", + "@smithy/url-parser": "^2.1.1", + "@smithy/util-base64": "^2.1.1", + "@smithy/util-body-length-browser": "^2.1.1", + "@smithy/util-body-length-node": "^2.2.1", + "@smithy/util-defaults-mode-browser": "^2.1.1", + "@smithy/util-defaults-mode-node": "^2.2.0", + "@smithy/util-endpoints": "^1.1.1", + "@smithy/util-middleware": "^2.1.1", + "@smithy/util-retry": "^2.1.1", + "@smithy/util-utf8": "^2.1.1", + "fast-xml-parser": "4.2.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "@aws-sdk/credential-provider-node": "^3.515.0" + } + }, + "node_modules/@aws-sdk/client-sts/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/core": { + "version": "3.513.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.513.0.tgz", + "integrity": "sha512-L+9DL4apWuqNKVOMJ8siAuWoRM9rZf9w1iPv8S2o83WO2jVK7E/m+rNW1dFo9HsA5V1ccDl2H2qLXx24HiHmOw==", + "dependencies": { + "@smithy/core": "^1.3.2", + "@smithy/protocol-http": "^3.1.1", + "@smithy/signature-v4": "^2.1.1", + "@smithy/smithy-client": "^2.3.1", + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.515.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.515.0.tgz", + "integrity": "sha512-45vxdyqhTAaUMERYVWOziG3K8L2TV9G4ryQS/KZ84o7NAybE9GMdoZRVmGHAO7mJJ1wQiYCM/E+i5b3NW9JfNA==", + "dependencies": { + "@aws-sdk/types": "3.515.0", + "@smithy/property-provider": "^2.1.1", + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.515.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.515.0.tgz", + "integrity": "sha512-Ba6FXK77vU4WyheiamNjEuTFmir0eAXuJGPO27lBaA8g+V/seXGHScsbOG14aQGDOr2P02OPwKGZrWWA7BFpfQ==", + "dependencies": { + "@aws-sdk/types": "3.515.0", + "@smithy/fetch-http-handler": "^2.4.1", + "@smithy/node-http-handler": "^2.3.1", + "@smithy/property-provider": "^2.1.1", + "@smithy/protocol-http": "^3.1.1", + "@smithy/smithy-client": "^2.3.1", + "@smithy/types": "^2.9.1", + "@smithy/util-stream": "^2.1.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.515.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.515.0.tgz", + "integrity": "sha512-ouDlNZdv2TKeVEA/YZk2+XklTXyAAGdbWnl4IgN9ItaodWI+lZjdIoNC8BAooVH+atIV/cZgoGTGQL7j2TxJ9A==", + "dependencies": { + "@aws-sdk/client-sts": "3.515.0", + "@aws-sdk/credential-provider-env": "3.515.0", + "@aws-sdk/credential-provider-process": "3.515.0", + "@aws-sdk/credential-provider-sso": "3.515.0", + "@aws-sdk/credential-provider-web-identity": "3.515.0", + "@aws-sdk/types": "3.515.0", + "@smithy/credential-provider-imds": "^2.2.1", + "@smithy/property-provider": "^2.1.1", + "@smithy/shared-ini-file-loader": "^2.3.1", + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.515.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.515.0.tgz", + "integrity": "sha512-Y4kHSpbxksiCZZNcvsiKUd8Fb2XlyUuONEwqWFNL82ZH6TCCjBGS31wJQCSxBHqYcOL3tiORUEJkoO7uS30uQA==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.515.0", + "@aws-sdk/credential-provider-http": "3.515.0", + "@aws-sdk/credential-provider-ini": "3.515.0", + "@aws-sdk/credential-provider-process": "3.515.0", + "@aws-sdk/credential-provider-sso": "3.515.0", + "@aws-sdk/credential-provider-web-identity": "3.515.0", + "@aws-sdk/types": "3.515.0", + "@smithy/credential-provider-imds": "^2.2.1", + "@smithy/property-provider": "^2.1.1", + "@smithy/shared-ini-file-loader": "^2.3.1", + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.515.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.515.0.tgz", + "integrity": "sha512-pSjiOA2FM63LHRKNDvEpBRp80FVGT0Mw/gzgbqFXP+sewk0WVonYbEcMDTJptH3VsLPGzqH/DQ1YL/aEIBuXFQ==", + "dependencies": { + "@aws-sdk/types": "3.515.0", + "@smithy/property-provider": "^2.1.1", + "@smithy/shared-ini-file-loader": "^2.3.1", + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.515.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.515.0.tgz", + "integrity": "sha512-j7vUkiSmuhpBvZYoPTRTI4ePnQbiZMFl6TNhg9b9DprC1zHkucsZnhRhqjOVlrw/H6J4jmcPGcHHTZ5WQNI5xQ==", + "dependencies": { + "@aws-sdk/client-sso": "3.515.0", + "@aws-sdk/token-providers": "3.515.0", + "@aws-sdk/types": "3.515.0", + "@smithy/property-provider": "^2.1.1", + "@smithy/shared-ini-file-loader": "^2.3.1", + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.515.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.515.0.tgz", + "integrity": "sha512-66+2g4z3fWwdoGReY8aUHvm6JrKZMTRxjuizljVmMyOBttKPeBYXvUTop/g3ZGUx1f8j+C5qsGK52viYBvtjuQ==", + "dependencies": { + "@aws-sdk/client-sts": "3.515.0", + "@aws-sdk/types": "3.515.0", + "@smithy/property-provider": "^2.1.1", + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/middleware-bucket-endpoint": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.654.0.tgz", + "integrity": "sha512-/lWkyeLESiK+rAB4+NCw1cVPle9RN7RW/v7B4b8ORiCn1FwZLUPmEiZSYzyh4in5oa3Mri+W/g+KafZDH6LCbA==", + "dependencies": { + "@aws-sdk/types": "3.654.0", + "@aws-sdk/util-arn-parser": "3.568.0", + "@smithy/node-config-provider": "^3.1.7", + "@smithy/protocol-http": "^4.1.3", + "@smithy/types": "^3.4.2", + "@smithy/util-config-provider": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-bucket-endpoint/node_modules/@aws-sdk/types": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.654.0.tgz", + "integrity": "sha512-VWvbED3SV+10QJIcmU/PKjsKilsTV16d1I7/on4bvD/jo1qGeMXqLDBSen3ks/tuvXZF/mFc7ZW/W2DiLVtO7A==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-bucket-endpoint/node_modules/@smithy/node-config-provider": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.7.tgz", + "integrity": "sha512-g3mfnC3Oo8pOI0dYuPXLtdW1WGVb3bR2tkV21GNkm0ZvQjLTtamXAwCWt/FCb0HGvKt3gHHmF1XerG0ICfalOg==", + "dependencies": { + "@smithy/property-provider": "^3.1.6", + "@smithy/shared-ini-file-loader": "^3.1.7", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-bucket-endpoint/node_modules/@smithy/property-provider": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.6.tgz", + "integrity": "sha512-NK3y/T7Q/Bw+Z8vsVs9MYIQ5v7gOX7clyrXcwhhIBQhbPgRl6JDrZbusO9qWDhcEus75Tg+VCxtIRfo3H76fpw==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-bucket-endpoint/node_modules/@smithy/protocol-http": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.3.tgz", + "integrity": "sha512-GcbMmOYpH9iRqtC05RbRnc/0FssxSTHlmaNhYBTgSgNCYpdR3Kt88u5GAZTBmouzv+Zlj/VRv92J9ruuDeJuEw==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-bucket-endpoint/node_modules/@smithy/shared-ini-file-loader": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.7.tgz", + "integrity": "sha512-IA4K2qTJYXkF5OfVN4vsY1hfnUZjaslEE8Fsr/gGFza4TAC2A9NfnZuSY2srQIbt9bwtjHiAayrRVgKse4Q7fA==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-bucket-endpoint/node_modules/@smithy/types": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.4.2.tgz", + "integrity": "sha512-tHiFcfcVedVBHpmHUEUHOCCih8iZbIAYn9NvPsNzaPm/237I3imdDdZoOC8c87H5HBAVEa06tTgb+OcSWV9g5w==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-bucket-endpoint/node_modules/@smithy/util-config-provider": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", + "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-bucket-endpoint/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/@aws-sdk/middleware-expect-continue": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.654.0.tgz", + "integrity": "sha512-S7fSlo8vdjkQTy9DmdF54ZsPwc+aA4z5Y9JVqAlGL9QiZe/fPtRE3GZ8BBbMICjBfMEa12tWjzhDz9su2c6PIA==", + "dependencies": { + "@aws-sdk/types": "3.654.0", + "@smithy/protocol-http": "^4.1.3", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-expect-continue/node_modules/@aws-sdk/types": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.654.0.tgz", + "integrity": "sha512-VWvbED3SV+10QJIcmU/PKjsKilsTV16d1I7/on4bvD/jo1qGeMXqLDBSen3ks/tuvXZF/mFc7ZW/W2DiLVtO7A==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-expect-continue/node_modules/@smithy/protocol-http": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.3.tgz", + "integrity": "sha512-GcbMmOYpH9iRqtC05RbRnc/0FssxSTHlmaNhYBTgSgNCYpdR3Kt88u5GAZTBmouzv+Zlj/VRv92J9ruuDeJuEw==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-expect-continue/node_modules/@smithy/types": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.4.2.tgz", + "integrity": "sha512-tHiFcfcVedVBHpmHUEUHOCCih8iZbIAYn9NvPsNzaPm/237I3imdDdZoOC8c87H5HBAVEa06tTgb+OcSWV9g5w==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-expect-continue/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/@aws-sdk/middleware-flexible-checksums": { + "version": "3.657.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.657.0.tgz", + "integrity": "sha512-aOfK0YmuL8baCqJ5nArHKyyFko/tSWMjGcegOA4Jo+XAu1PEk0wDi78vOHlv4dfSlF8sXJsAo4kaCEDF3UkGAQ==", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@aws-crypto/crc32c": "5.2.0", + "@aws-sdk/types": "3.654.0", + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/node-config-provider": "^3.1.7", + "@smithy/protocol-http": "^4.1.3", + "@smithy/types": "^3.4.2", + "@smithy/util-middleware": "^3.0.6", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@aws-sdk/types": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.654.0.tgz", + "integrity": "sha512-VWvbED3SV+10QJIcmU/PKjsKilsTV16d1I7/on4bvD/jo1qGeMXqLDBSen3ks/tuvXZF/mFc7ZW/W2DiLVtO7A==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@smithy/node-config-provider": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.7.tgz", + "integrity": "sha512-g3mfnC3Oo8pOI0dYuPXLtdW1WGVb3bR2tkV21GNkm0ZvQjLTtamXAwCWt/FCb0HGvKt3gHHmF1XerG0ICfalOg==", + "dependencies": { + "@smithy/property-provider": "^3.1.6", + "@smithy/shared-ini-file-loader": "^3.1.7", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@smithy/property-provider": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.6.tgz", + "integrity": "sha512-NK3y/T7Q/Bw+Z8vsVs9MYIQ5v7gOX7clyrXcwhhIBQhbPgRl6JDrZbusO9qWDhcEus75Tg+VCxtIRfo3H76fpw==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@smithy/protocol-http": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.3.tgz", + "integrity": "sha512-GcbMmOYpH9iRqtC05RbRnc/0FssxSTHlmaNhYBTgSgNCYpdR3Kt88u5GAZTBmouzv+Zlj/VRv92J9ruuDeJuEw==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@smithy/shared-ini-file-loader": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.7.tgz", + "integrity": "sha512-IA4K2qTJYXkF5OfVN4vsY1hfnUZjaslEE8Fsr/gGFza4TAC2A9NfnZuSY2srQIbt9bwtjHiAayrRVgKse4Q7fA==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@smithy/types": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.4.2.tgz", + "integrity": "sha512-tHiFcfcVedVBHpmHUEUHOCCih8iZbIAYn9NvPsNzaPm/237I3imdDdZoOC8c87H5HBAVEa06tTgb+OcSWV9g5w==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@smithy/util-middleware": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.6.tgz", + "integrity": "sha512-BxbX4aBhI1O9p87/xM+zWy0GzT3CEVcXFPBRDoHAM+pV0eSW156pR+PSYEz0DQHDMYDsYAflC2bQNz2uaDBUZQ==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.515.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.515.0.tgz", + "integrity": "sha512-I1MwWPzdRKM1luvdDdjdGsDjNVPhj9zaIytEchjTY40NcKOg+p2evLD2y69ozzg8pyXK63r8DdvDGOo9QPuh0A==", + "dependencies": { + "@aws-sdk/types": "3.515.0", + "@smithy/protocol-http": "^3.1.1", + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-host-header/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/middleware-location-constraint": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.654.0.tgz", + "integrity": "sha512-Duvv5c4DEQ7P6c0YlcvEUW3xCJi6X2uktafNGjILhVDMQwShSF/aFqNv/ikWU/luQcmWHZ9DtDjTR9UKLh6eTA==", + "dependencies": { + "@aws-sdk/types": "3.654.0", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-location-constraint/node_modules/@aws-sdk/types": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.654.0.tgz", + "integrity": "sha512-VWvbED3SV+10QJIcmU/PKjsKilsTV16d1I7/on4bvD/jo1qGeMXqLDBSen3ks/tuvXZF/mFc7ZW/W2DiLVtO7A==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-location-constraint/node_modules/@smithy/types": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.4.2.tgz", + "integrity": "sha512-tHiFcfcVedVBHpmHUEUHOCCih8iZbIAYn9NvPsNzaPm/237I3imdDdZoOC8c87H5HBAVEa06tTgb+OcSWV9g5w==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-location-constraint/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.515.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.515.0.tgz", + "integrity": "sha512-qXomJzg2m/5seQOxHi/yOXOKfSjwrrJSmEmfwJKJyQgdMbBcjz3Cz0H/1LyC6c5hHm6a/SZgSTzDAbAoUmyL+Q==", + "dependencies": { + "@aws-sdk/types": "3.515.0", + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-logger/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.515.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.515.0.tgz", + "integrity": "sha512-dokHLbTV3IHRIBrw9mGoxcNTnQsjlm7TpkJhPdGT9T4Mq399EyQo51u6IsVMm07RXLl2Zw7u+u9p+qWBFzmFRA==", + "dependencies": { + "@aws-sdk/types": "3.515.0", + "@smithy/protocol-http": "^3.1.1", + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-recursion-detection/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.654.0.tgz", + "integrity": "sha512-6prq+GK6hLMAbxEb83tBMb1YiTWWK196fJhFO/7gE5TUPL1v756RhQZzKV/njbwB1fIBjRBTuhYLh5Bn98HhdA==", + "dependencies": { + "@aws-sdk/core": "3.654.0", + "@aws-sdk/types": "3.654.0", + "@aws-sdk/util-arn-parser": "3.568.0", + "@smithy/core": "^2.4.3", + "@smithy/node-config-provider": "^3.1.7", + "@smithy/protocol-http": "^4.1.3", + "@smithy/signature-v4": "^4.1.3", + "@smithy/smithy-client": "^3.3.2", + "@smithy/types": "^3.4.2", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.6", + "@smithy/util-stream": "^3.1.6", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@aws-sdk/core": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.654.0.tgz", + "integrity": "sha512-4Rwx7BVaNaFqmXBDmnOkMbyuIFFbpZ+ru4lr660p45zY1QoNNSalechfoRffcokLFOZO+VWEJkdcorPUUU993w==", + "dependencies": { + "@smithy/core": "^2.4.3", + "@smithy/node-config-provider": "^3.1.7", + "@smithy/property-provider": "^3.1.6", + "@smithy/protocol-http": "^4.1.3", + "@smithy/signature-v4": "^4.1.3", + "@smithy/smithy-client": "^3.3.2", + "@smithy/types": "^3.4.2", + "@smithy/util-middleware": "^3.0.6", + "fast-xml-parser": "4.4.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@aws-sdk/types": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.654.0.tgz", + "integrity": "sha512-VWvbED3SV+10QJIcmU/PKjsKilsTV16d1I7/on4bvD/jo1qGeMXqLDBSen3ks/tuvXZF/mFc7ZW/W2DiLVtO7A==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/abort-controller": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.4.tgz", + "integrity": "sha512-VupaALAQlXViW3/enTf/f5l5JZYSAxoJL7f0nanhNNKnww6DGCg1oYIuNP78KDugnkwthBO6iEcym16HhWV8RQ==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/core": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.4.5.tgz", + "integrity": "sha512-Z0qlPXgZ0pouYgnu/cZTEYeRAvniiKZmVl4wIbZHX/nEMHkMDV9ao6KFArsU9KndE0TuhL149xcRx45wfw1YCA==", + "dependencies": { + "@smithy/middleware-endpoint": "^3.1.3", + "@smithy/middleware-retry": "^3.0.20", + "@smithy/middleware-serde": "^3.0.6", + "@smithy/protocol-http": "^4.1.3", + "@smithy/smithy-client": "^3.3.4", + "@smithy/types": "^3.4.2", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-middleware": "^3.0.6", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/fetch-http-handler": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.8.tgz", + "integrity": "sha512-Lqe0B8F5RM7zkw//6avq1SJ8AfaRd3ubFUS1eVp5WszV7p6Ne5hQ4dSuMHDpNRPhgTvj4va9Kd/pcVigHEHRow==", + "dependencies": { + "@smithy/protocol-http": "^4.1.3", + "@smithy/querystring-builder": "^3.0.6", + "@smithy/types": "^3.4.2", + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/middleware-endpoint": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.1.3.tgz", + "integrity": "sha512-KeM/OrK8MVFUsoJsmCN0MZMVPjKKLudn13xpgwIMpGTYpA8QZB2Xq5tJ+RE6iu3A6NhOI4VajDTwBsm8pwwrhg==", + "dependencies": { + "@smithy/middleware-serde": "^3.0.6", + "@smithy/node-config-provider": "^3.1.7", + "@smithy/shared-ini-file-loader": "^3.1.7", + "@smithy/types": "^3.4.2", + "@smithy/url-parser": "^3.0.6", + "@smithy/util-middleware": "^3.0.6", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/middleware-retry": { + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.20.tgz", + "integrity": "sha512-HELCOVwYw5hFDBm69d+LmmGjBCjWnwp/t7SJiHmp+c4u9vgfIaCjdSeIdnlOsLrr5ic5jGTJXvJFUQnd987b/g==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.7", + "@smithy/protocol-http": "^4.1.3", + "@smithy/service-error-classification": "^3.0.6", + "@smithy/smithy-client": "^3.3.4", + "@smithy/types": "^3.4.2", + "@smithy/util-middleware": "^3.0.6", + "@smithy/util-retry": "^3.0.6", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/middleware-serde": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.6.tgz", + "integrity": "sha512-KKTUSl1MzOM0MAjGbudeaVNtIDo+PpekTBkCNwvfZlKndodrnvRo+00USatiyLOc0ujjO9UydMRu3O9dYML7ag==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/middleware-stack": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.6.tgz", + "integrity": "sha512-2c0eSYhTQ8xQqHMcRxLMpadFbTXg6Zla5l0mwNftFCZMQmuhI7EbAJMx6R5eqfuV3YbJ3QGyS3d5uSmrHV8Khg==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/node-config-provider": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.7.tgz", + "integrity": "sha512-g3mfnC3Oo8pOI0dYuPXLtdW1WGVb3bR2tkV21GNkm0ZvQjLTtamXAwCWt/FCb0HGvKt3gHHmF1XerG0ICfalOg==", + "dependencies": { + "@smithy/property-provider": "^3.1.6", + "@smithy/shared-ini-file-loader": "^3.1.7", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/node-http-handler": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.2.3.tgz", + "integrity": "sha512-/gcm5DJ3k1b1zEInzBGAZC8ntJ+jwrz1NcSIu+9dSXd1FfG0G6QgkDI40tt8/WYUbHtLyo8fEqtm2v29koWo/w==", + "dependencies": { + "@smithy/abort-controller": "^3.1.4", + "@smithy/protocol-http": "^4.1.3", + "@smithy/querystring-builder": "^3.0.6", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/property-provider": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.6.tgz", + "integrity": "sha512-NK3y/T7Q/Bw+Z8vsVs9MYIQ5v7gOX7clyrXcwhhIBQhbPgRl6JDrZbusO9qWDhcEus75Tg+VCxtIRfo3H76fpw==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/protocol-http": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.3.tgz", + "integrity": "sha512-GcbMmOYpH9iRqtC05RbRnc/0FssxSTHlmaNhYBTgSgNCYpdR3Kt88u5GAZTBmouzv+Zlj/VRv92J9ruuDeJuEw==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/querystring-builder": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.6.tgz", + "integrity": "sha512-sQe08RunoObe+Usujn9+R2zrLuQERi3CWvRO3BvnoWSYUaIrLKuAIeY7cMeDax6xGyfIP3x/yFWbEKSXvOnvVg==", + "dependencies": { + "@smithy/types": "^3.4.2", + "@smithy/util-uri-escape": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/querystring-parser": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.6.tgz", + "integrity": "sha512-UJKw4LlEkytzz2Wq+uIdHf6qOtFfee/o7ruH0jF5I6UAuU+19r9QV7nU3P/uI0l6+oElRHmG/5cBBcGJrD7Ozg==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/service-error-classification": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.6.tgz", + "integrity": "sha512-53SpchU3+DUZrN7J6sBx9tBiCVGzsib2e4sc512Q7K9fpC5zkJKs6Z9s+qbMxSYrkEkle6hnMtrts7XNkMJJMg==", + "dependencies": { + "@smithy/types": "^3.4.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/shared-ini-file-loader": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.7.tgz", + "integrity": "sha512-IA4K2qTJYXkF5OfVN4vsY1hfnUZjaslEE8Fsr/gGFza4TAC2A9NfnZuSY2srQIbt9bwtjHiAayrRVgKse4Q7fA==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/signature-v4": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.1.4.tgz", + "integrity": "sha512-72MiK7xYukNsnLJI9NqvUHqTu0ziEsfMsYNlWpiJfuGQnCTFKpckThlEatirvcA/LmT1h7rRO+pJD06PYsPu9Q==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/protocol-http": "^4.1.3", + "@smithy/types": "^3.4.2", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-middleware": "^3.0.6", + "@smithy/util-uri-escape": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/smithy-client": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.3.4.tgz", + "integrity": "sha512-NKw/2XxOW/Rg3rzB90HxsmGok5oS6vRzJgMh/JN4BHaOQQ4q5OuX999GmOGxEp730wbpIXIowfKZmIMXkG4v0Q==", + "dependencies": { + "@smithy/middleware-endpoint": "^3.1.3", + "@smithy/middleware-stack": "^3.0.6", + "@smithy/protocol-http": "^4.1.3", + "@smithy/types": "^3.4.2", + "@smithy/util-stream": "^3.1.8", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/types": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.4.2.tgz", + "integrity": "sha512-tHiFcfcVedVBHpmHUEUHOCCih8iZbIAYn9NvPsNzaPm/237I3imdDdZoOC8c87H5HBAVEa06tTgb+OcSWV9g5w==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/url-parser": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.6.tgz", + "integrity": "sha512-47Op/NU8Opt49KyGpHtVdnmmJMsp2hEwBdyjuFB9M2V5QVOwA7pBhhxKN5z6ztKGrMw76gd8MlbPuzzvaAncuQ==", + "dependencies": { + "@smithy/querystring-parser": "^3.0.6", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/util-base64": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", + "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/util-body-length-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", + "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/util-config-provider": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", + "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/util-hex-encoding": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", + "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/util-middleware": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.6.tgz", + "integrity": "sha512-BxbX4aBhI1O9p87/xM+zWy0GzT3CEVcXFPBRDoHAM+pV0eSW156pR+PSYEz0DQHDMYDsYAflC2bQNz2uaDBUZQ==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/util-retry": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.6.tgz", + "integrity": "sha512-BRZiuF7IwDntAbevqMco67an0Sr9oLQJqqRCsSPZZHYRnehS0LHDAkJk/pSmI7Z8c/1Vet294H7fY2fWUgB+Rg==", + "dependencies": { + "@smithy/service-error-classification": "^3.0.6", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/util-stream": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.1.8.tgz", + "integrity": "sha512-hoKOqSmb8FD3WLObuB5hwbM7bNIWgcnvkThokTvVq7J5PKjlLUK5qQQcB9zWLHIoSaIlf3VIv2OxZY2wtQjcRQ==", + "dependencies": { + "@smithy/fetch-http-handler": "^3.2.8", + "@smithy/node-http-handler": "^3.2.3", + "@smithy/types": "^3.4.2", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/util-uri-escape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", + "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@aws-sdk/middleware-ssec": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.654.0.tgz", + "integrity": "sha512-k7hkQDJh4hcRJC7YojQ11kc37SY4foryen26Eafj5qYjeG2OGMW0oZTJDl1TVFJ7AcCjqIuMIo0Ho2US/2JspQ==", + "dependencies": { + "@aws-sdk/types": "3.654.0", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-ssec/node_modules/@aws-sdk/types": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.654.0.tgz", + "integrity": "sha512-VWvbED3SV+10QJIcmU/PKjsKilsTV16d1I7/on4bvD/jo1qGeMXqLDBSen3ks/tuvXZF/mFc7ZW/W2DiLVtO7A==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-ssec/node_modules/@smithy/types": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.4.2.tgz", + "integrity": "sha512-tHiFcfcVedVBHpmHUEUHOCCih8iZbIAYn9NvPsNzaPm/237I3imdDdZoOC8c87H5HBAVEa06tTgb+OcSWV9g5w==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-ssec/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.515.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.515.0.tgz", + "integrity": "sha512-nOqZjGA/GkjuJ5fUshec9Fv6HFd7ovOTxMJbw3MfAhqXuVZ6dKF41lpVJ4imNsgyFt3shUg9WDY8zGFjlYMB3g==", + "dependencies": { + "@aws-sdk/types": "3.515.0", + "@aws-sdk/util-endpoints": "3.515.0", + "@smithy/protocol-http": "^3.1.1", + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-user-agent/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.515.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.515.0.tgz", + "integrity": "sha512-RIRx9loxMgEAc/r1wPfnfShOuzn4RBi8pPPv6/jhhITEeMnJe6enAh2k5y9DdiVDDgCWZgVFSv0YkAIfzAFsnQ==", + "dependencies": { + "@aws-sdk/types": "3.515.0", + "@smithy/node-config-provider": "^2.2.1", + "@smithy/types": "^2.9.1", + "@smithy/util-config-provider": "^2.2.1", + "@smithy/util-middleware": "^2.1.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/region-config-resolver/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.654.0.tgz", + "integrity": "sha512-f8kyvbzgD3lSK1kFc3jsDCYjdutcqGO3tOzYO/QIK7BTl5lxc4rm6IKTcF2UYJsn8jiNqih7tVK8aVIGi8IF/w==", + "dependencies": { + "@aws-sdk/middleware-sdk-s3": "3.654.0", + "@aws-sdk/types": "3.654.0", + "@smithy/protocol-http": "^4.1.3", + "@smithy/signature-v4": "^4.1.3", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/@aws-sdk/types": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.654.0.tgz", + "integrity": "sha512-VWvbED3SV+10QJIcmU/PKjsKilsTV16d1I7/on4bvD/jo1qGeMXqLDBSen3ks/tuvXZF/mFc7ZW/W2DiLVtO7A==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/@smithy/protocol-http": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.3.tgz", + "integrity": "sha512-GcbMmOYpH9iRqtC05RbRnc/0FssxSTHlmaNhYBTgSgNCYpdR3Kt88u5GAZTBmouzv+Zlj/VRv92J9ruuDeJuEw==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/@smithy/signature-v4": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.1.4.tgz", + "integrity": "sha512-72MiK7xYukNsnLJI9NqvUHqTu0ziEsfMsYNlWpiJfuGQnCTFKpckThlEatirvcA/LmT1h7rRO+pJD06PYsPu9Q==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/protocol-http": "^4.1.3", + "@smithy/types": "^3.4.2", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-middleware": "^3.0.6", + "@smithy/util-uri-escape": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/@smithy/types": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.4.2.tgz", + "integrity": "sha512-tHiFcfcVedVBHpmHUEUHOCCih8iZbIAYn9NvPsNzaPm/237I3imdDdZoOC8c87H5HBAVEa06tTgb+OcSWV9g5w==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/@smithy/util-hex-encoding": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", + "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/@smithy/util-middleware": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.6.tgz", + "integrity": "sha512-BxbX4aBhI1O9p87/xM+zWy0GzT3CEVcXFPBRDoHAM+pV0eSW156pR+PSYEz0DQHDMYDsYAflC2bQNz2uaDBUZQ==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/@smithy/util-uri-escape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", + "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.515.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.515.0.tgz", + "integrity": "sha512-MQuf04rIcTXqwDzmyHSpFPF1fKEzRl64oXtCRUF3ddxTdK6wxXkePfK6wNCuL+GEbEcJAoCtIGIRpzGPJvQjHA==", + "dependencies": { + "@aws-sdk/client-sso-oidc": "3.515.0", + "@aws-sdk/types": "3.515.0", + "@smithy/property-provider": "^2.1.1", + "@smithy/shared-ini-file-loader": "^2.3.1", + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/token-providers/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/types": { + "version": "3.515.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.515.0.tgz", + "integrity": "sha512-B3gUpiMlpT6ERaLvZZ61D0RyrQPsFYDkCncLPVkZOKkCOoFU46zi1o6T5JcYiz8vkx1q9RGloQ5exh79s5pU/w==", + "dependencies": { + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/types/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/util-arn-parser": { + "version": "3.568.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.568.0.tgz", + "integrity": "sha512-XUKJWWo+KOB7fbnPP0+g/o5Ulku/X53t7i/h+sPHr5xxYTJJ9CYnbToo95mzxe7xWvkLrsNtJ8L+MnNn9INs2w==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/util-arn-parser/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.515.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.515.0.tgz", + "integrity": "sha512-UJi+jdwcGFV/F7d3+e2aQn5yZOVpDiAgfgNhPnEtgV0WozJ5/ZUeZBgWvSc/K415N4A4D/9cbBc7+I+35qzcDQ==", + "dependencies": { + "@aws-sdk/types": "3.515.0", + "@smithy/types": "^2.9.1", + "@smithy/util-endpoints": "^1.1.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-endpoints/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.495.0.tgz", + "integrity": "sha512-MfaPXT0kLX2tQaR90saBT9fWQq2DHqSSJRzW+MZWsmF+y5LGCOhO22ac/2o6TKSQm7h0HRc2GaADqYYYor62yg==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.515.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.515.0.tgz", + "integrity": "sha512-pTWQb0JCafTmLHLDv3Qqs/nAAJghcPdGQIBpsCStb0YEzg3At/dOi2AIQ683yYnXmeOxLXJDzmlsovfVObJScw==", + "dependencies": { + "@aws-sdk/types": "3.515.0", + "@smithy/types": "^2.9.1", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-browser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.515.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.515.0.tgz", + "integrity": "sha512-A/KJ+/HTohHyVXLH+t/bO0Z2mPrQgELbQO8tX+B2nElo8uklj70r5cT7F8ETsI9oOy+HDVpiL5/v45ZgpUOiPg==", + "dependencies": { + "@aws-sdk/types": "3.515.0", + "@smithy/node-config-provider": "^2.2.1", + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/util-user-agent-node/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/util-utf8-browser": { + "version": "3.259.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", + "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", + "dependencies": { + "tslib": "^2.3.1" + } + }, + "node_modules/@aws-sdk/util-utf8-browser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@aws-sdk/xml-builder": { + "version": "3.654.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.654.0.tgz", + "integrity": "sha512-qA2diK3d/ztC8HUb7NwPKbJRV01NpzTzxFn+L5G3HzJBNeKbjLcprQ/9uG9gp2UEx2Go782FI1ddrMNa0qBICA==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/xml-builder/node_modules/@smithy/types": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.4.2.tgz", + "integrity": "sha512-tHiFcfcVedVBHpmHUEUHOCCih8iZbIAYn9NvPsNzaPm/237I3imdDdZoOC8c87H5HBAVEa06tTgb+OcSWV9g5w==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/xml-builder/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", + "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.47.0.tgz", + "integrity": "sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.0.tgz", + "integrity": "sha512-H8+iZh+kCE6VR/Krj6W28Y/ZlxoZ1fOzsNt77nrdE3knkbSelW1Uus192xOFCxHyeszLj8i4APQkSIXjAoOxXg==", + "dependencies": { + "@grpc/proto-loader": "^0.7.0", + "@types/node": ">=12.12.47" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.8.tgz", + "integrity": "sha512-GU12e2c8dmdXb7XUlOgYWZ2o2i+z9/VeACkxTA/zzAe2IjclC5PnVL0lpgjhrqfpDYHzM8B1TF6pqWegMYAzlA==", + "dependencies": { + "@types/long": "^4.0.1", + "lodash.camelcase": "^4.3.0", + "long": "^4.0.0", + "protobufjs": "^7.2.4", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@grpc/proto-loader/node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, "node_modules/@hapi/hoek": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", @@ -71,10 +3248,296 @@ "@hapi/hoek": "^9.0.0" } }, + "node_modules/@hcaptcha/types": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@hcaptcha/types/-/types-1.0.3.tgz", + "integrity": "sha512-1mbU6eSGawRrqeahRrOzZo/SVLI6oZ5/azuBpSyVrRRR96CnS3fOVDWfzxpngfxKD0/I9Rwu6c/3ITqD8rXeTQ==", + "dev": true + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", + "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@inquirer/checkbox": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.0.3.tgz", + "integrity": "sha512-CEt9B4e8zFOGtc/LYeQx5m8nfqQeG/4oNNv0PUvXGG0mys+wR/WbJ3B4KfSQ4Fcr3AQfpiuFOi3fVvmPfvNbxw==", + "dependencies": { + "@inquirer/core": "^10.1.1", + "@inquirer/figures": "^1.0.8", + "@inquirer/type": "^3.0.1", + "ansi-escapes": "^4.3.2", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/confirm": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.0.tgz", + "integrity": "sha512-osaBbIMEqVFjTX5exoqPXs6PilWQdjaLhGtMDXMXg/yxkHXNq43GlxGyTA35lK2HpzUgDN+Cjh/2AmqCN0QJpw==", + "dependencies": { + "@inquirer/core": "^10.1.1", + "@inquirer/type": "^3.0.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/core": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.1.tgz", + "integrity": "sha512-rmZVXy9iZvO3ZStEe/ayuuwIJ23LSF13aPMlLMTQARX6lGUBDHGV8UB5i9MRrfy0+mZwt5/9bdy8llszSD3NQA==", + "dependencies": { + "@inquirer/figures": "^1.0.8", + "@inquirer/type": "^3.0.1", + "ansi-escapes": "^4.3.2", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/core/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/editor": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.0.tgz", + "integrity": "sha512-Z3LeGsD3WlItDqLxTPciZDbGtm0wrz7iJGS/uUxSiQxef33ZrBq7LhsXg30P7xrWz1kZX4iGzxxj5SKZmJ8W+w==", + "dependencies": { + "@inquirer/core": "^10.1.1", + "@inquirer/type": "^3.0.1", + "external-editor": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/expand": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.3.tgz", + "integrity": "sha512-MDszqW4HYBpVMmAoy/FA9laLrgo899UAga0itEjsYrBthKieDZNc0e16gdn7N3cQ0DSf/6zsTBZMuDYDQU4ktg==", + "dependencies": { + "@inquirer/core": "^10.1.1", + "@inquirer/type": "^3.0.1", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.8.tgz", + "integrity": "sha512-tKd+jsmhq21AP1LhexC0pPwsCxEhGgAkg28byjJAd+xhmIs8LUX8JbUc3vBf3PhLxWiB5EvyBE5X7JSPAqMAqg==", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/input": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.1.0.tgz", + "integrity": "sha512-16B8A9hY741yGXzd8UJ9R8su/fuuyO2e+idd7oVLYjP23wKJ6ILRIIHcnXe8/6AoYgwRS2zp4PNsW/u/iZ24yg==", + "dependencies": { + "@inquirer/core": "^10.1.1", + "@inquirer/type": "^3.0.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/number": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.3.tgz", + "integrity": "sha512-HA/W4YV+5deKCehIutfGBzNxWH1nhvUC67O4fC9ufSijn72yrYnRmzvC61dwFvlXIG1fQaYWi+cqNE9PaB9n6Q==", + "dependencies": { + "@inquirer/core": "^10.1.1", + "@inquirer/type": "^3.0.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/password": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.3.tgz", + "integrity": "sha512-3qWjk6hS0iabG9xx0U1plwQLDBc/HA/hWzLFFatADpR6XfE62LqPr9GpFXBkLU0KQUaIXZ996bNG+2yUvocH8w==", + "dependencies": { + "@inquirer/core": "^10.1.1", + "@inquirer/type": "^3.0.1", + "ansi-escapes": "^4.3.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/prompts": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.2.0.tgz", + "integrity": "sha512-ZXYZ5oGVrb+hCzcglPeVerJ5SFwennmDOPfXq1WyeZIrPGySLbl4W6GaSsBFvu3WII36AOK5yB8RMIEEkBjf8w==", + "dependencies": { + "@inquirer/checkbox": "^4.0.3", + "@inquirer/confirm": "^5.1.0", + "@inquirer/editor": "^4.2.0", + "@inquirer/expand": "^4.0.3", + "@inquirer/input": "^4.1.0", + "@inquirer/number": "^3.0.3", + "@inquirer/password": "^4.0.3", + "@inquirer/rawlist": "^4.0.3", + "@inquirer/search": "^3.0.3", + "@inquirer/select": "^4.0.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/rawlist": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.0.3.tgz", + "integrity": "sha512-5MhinSzfmOiZlRoPezfbJdfVCZikZs38ja3IOoWe7H1dxL0l3Z2jAUgbBldeyhhOkELdGvPlBfQaNbeLslib1w==", + "dependencies": { + "@inquirer/core": "^10.1.1", + "@inquirer/type": "^3.0.1", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/search": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.0.3.tgz", + "integrity": "sha512-mQTCbdNolTGvGGVCJSI6afDwiSGTV+fMLPEIMDJgIV6L/s3+RYRpxt6t0DYnqMQmemnZ/Zq0vTIRwoHT1RgcTg==", + "dependencies": { + "@inquirer/core": "^10.1.1", + "@inquirer/figures": "^1.0.8", + "@inquirer/type": "^3.0.1", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/select": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.0.3.tgz", + "integrity": "sha512-OZfKDtDE8+J54JYAFTUGZwvKNfC7W/gFCjDkcsO7HnTH/wljsZo9y/FJquOxMy++DY0+9l9o/MOZ8s5s1j5wmw==", + "dependencies": { + "@inquirer/core": "^10.1.1", + "@inquirer/figures": "^1.0.8", + "@inquirer/type": "^3.0.1", + "ansi-escapes": "^4.3.2", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, + "node_modules/@inquirer/type": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.1.tgz", + "integrity": "sha512-+ksJMIy92sOAiAccGpcKZUc3bYO07cADnscIxHBknEm3uNts3movSmBofc1908BNy5edKscxYeAdaX1NXkHS6A==", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + } + }, "node_modules/@mapbox/node-pre-gyp": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", - "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", "dependencies": { "detect-libc": "^2.0.0", "https-proxy-agent": "^5.0.0", @@ -90,6 +3553,50 @@ "node-pre-gyp": "bin/node-pre-gyp" } }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.1.tgz", + "integrity": "sha512-t7c5K033joZZMspnHg/gWPE4kandgc2OxE74aYOtGKfgB9VPuVJPix0H6fhmm2erj5PBJ21mqcx34lpIGtUCsQ==", + "optional": true, + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@oozcitak/dom": { "version": "0.0.11", "resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-0.0.11.tgz", @@ -206,6 +3713,69 @@ "node": ">=6" } }, + "node_modules/@pretendonetwork/grpc": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@pretendonetwork/grpc/-/grpc-1.0.5.tgz", + "integrity": "sha512-l5aB6R7Z2RcX8ds0LIdF7HxW5vMmKdN02G43o+RmUTPCs7ONkwvIL6hIqRAxxNXf4Mz6QYwuTXK96VKWbDgqaQ==", + "dependencies": { + "long": "^5.2.1", + "protobufjs": "^7.2.3" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, "node_modules/@redis/bloom": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz", @@ -215,9 +3785,9 @@ } }, "node_modules/@redis/client": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.5.tgz", - "integrity": "sha512-fuMnpDYSjT5JXR9rrCW1YWA4L8N/9/uS4ImT3ZEC/hcaQRI1D/9FvwjriRj1UvepIgzZXthFVKMNRzP/LNL7BQ==", + "version": "1.5.8", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.8.tgz", + "integrity": "sha512-xzElwHIO6rBAqzPeVnCzgvrnBEcFL1P0w8P65VNLRkdVW8rOE58f52hdj0BDgmsdOm4f1EoXPZtH4Fh7M/qUpw==", "dependencies": { "cluster-key-slot": "1.1.2", "generic-pool": "3.9.0", @@ -244,9 +3814,9 @@ } }, "node_modules/@redis/search": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.1.tgz", - "integrity": "sha512-pqCXTc5e7wJJgUuJiC3hBgfoFRoPxYzwn0BEfKgejTM7M/9zP3IpUcqcjgfp8hF+LoV8rHZzcNTz7V+pEIY7LQ==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.3.tgz", + "integrity": "sha512-4Dg1JjvCevdiCBTZqjhKkGoC5/BcB7k9j99kdMnaXFXg8x4eyOIVg9487CMv7/BUVkFLZCaIh8ead9mU15DNng==", "peerDependencies": { "@redis/client": "^1.0.0" } @@ -288,6 +3858,1136 @@ "url": "https://github.com/sindresorhus/is?sponsor=1" } }, + "node_modules/@smithy/abort-controller": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.1.1.tgz", + "integrity": "sha512-1+qdrUqLhaALYL0iOcN43EP6yAXXQ2wWZ6taf4S2pNGowmOc5gx+iMQv+E42JizNJjB0+gEadOXeV1Bf7JWL1Q==", + "dependencies": { + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/abort-controller/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/chunked-blob-reader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-3.0.0.tgz", + "integrity": "sha512-sbnURCwjF0gSToGlsBiAmd1lRCmSn72nu9axfJu5lIx6RUEgHu6GwTMbqCdhQSi0Pumcm5vFxsi9XWXb2mTaoA==", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/chunked-blob-reader-native": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-3.0.0.tgz", + "integrity": "sha512-VDkpCYW+peSuM4zJip5WDfqvg2Mo/e8yxOv3VF1m11y7B8KKMKVFtmZWDe36Fvk8rGuWrPZHHXZ7rR7uM5yWyg==", + "dependencies": { + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/chunked-blob-reader-native/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/chunked-blob-reader-native/node_modules/@smithy/util-base64": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", + "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/chunked-blob-reader-native/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/chunked-blob-reader-native/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/chunked-blob-reader-native/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/@smithy/chunked-blob-reader/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/@smithy/config-resolver": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.1.1.tgz", + "integrity": "sha512-lxfLDpZm+AWAHPFZps5JfDoO9Ux1764fOgvRUBpHIO8HWHcSN1dkgsago1qLRVgm1BZ8RCm8cgv99QvtaOWIhw==", + "dependencies": { + "@smithy/node-config-provider": "^2.2.1", + "@smithy/types": "^2.9.1", + "@smithy/util-config-provider": "^2.2.1", + "@smithy/util-middleware": "^2.1.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/config-resolver/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/core": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-1.3.2.tgz", + "integrity": "sha512-tYDmTp0f2TZVE18jAOH1PnmkngLQ+dOGUlMd1u67s87ieueNeyqhja6z/Z4MxhybEiXKOWFOmGjfTZWFxljwJw==", + "dependencies": { + "@smithy/middleware-endpoint": "^2.4.1", + "@smithy/middleware-retry": "^2.1.1", + "@smithy/middleware-serde": "^2.1.1", + "@smithy/protocol-http": "^3.1.1", + "@smithy/smithy-client": "^2.3.1", + "@smithy/types": "^2.9.1", + "@smithy/util-middleware": "^2.1.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/core/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.2.1.tgz", + "integrity": "sha512-7XHjZUxmZYnONheVQL7j5zvZXga+EWNgwEAP6OPZTi7l8J4JTeNh9aIOfE5fKHZ/ee2IeNOh54ZrSna+Vc6TFA==", + "dependencies": { + "@smithy/node-config-provider": "^2.2.1", + "@smithy/property-provider": "^2.1.1", + "@smithy/types": "^2.9.1", + "@smithy/url-parser": "^2.1.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/eventstream-codec": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.1.1.tgz", + "integrity": "sha512-E8KYBxBIuU4c+zrpR22VsVrOPoEDzk35bQR3E+xm4k6Pa6JqzkDOdMyf9Atac5GPNKHJBdVaQ4JtjdWX2rl/nw==", + "dependencies": { + "@aws-crypto/crc32": "3.0.0", + "@smithy/types": "^2.9.1", + "@smithy/util-hex-encoding": "^2.1.1", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/eventstream-codec/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/eventstream-serde-browser": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.9.tgz", + "integrity": "sha512-PiQLo6OQmZAotJweIcObL1H44gkvuJACKMNqpBBe5Rf2Ax1DOcGi/28+feZI7yTe1ERHlQQaGnm8sSkyDUgsMg==", + "dependencies": { + "@smithy/eventstream-serde-universal": "^3.0.8", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-browser/node_modules/@smithy/types": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.4.2.tgz", + "integrity": "sha512-tHiFcfcVedVBHpmHUEUHOCCih8iZbIAYn9NvPsNzaPm/237I3imdDdZoOC8c87H5HBAVEa06tTgb+OcSWV9g5w==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-browser/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/@smithy/eventstream-serde-config-resolver": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.6.tgz", + "integrity": "sha512-iew15It+c7WfnVowWkt2a7cdPp533LFJnpjDQgfZQcxv2QiOcyEcea31mnrk5PVbgo0nNH3VbYGq7myw2q/F6A==", + "dependencies": { + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-config-resolver/node_modules/@smithy/types": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.4.2.tgz", + "integrity": "sha512-tHiFcfcVedVBHpmHUEUHOCCih8iZbIAYn9NvPsNzaPm/237I3imdDdZoOC8c87H5HBAVEa06tTgb+OcSWV9g5w==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-config-resolver/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/@smithy/eventstream-serde-node": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.8.tgz", + "integrity": "sha512-6m+wI+fT0na+6oao6UqALVA38fsScCpoG5UO/A8ZSyGLnPM2i4MS1cFUhpuALgvLMxfYoTCh7qSeJa0aG4IWpQ==", + "dependencies": { + "@smithy/eventstream-serde-universal": "^3.0.8", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-node/node_modules/@smithy/types": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.4.2.tgz", + "integrity": "sha512-tHiFcfcVedVBHpmHUEUHOCCih8iZbIAYn9NvPsNzaPm/237I3imdDdZoOC8c87H5HBAVEa06tTgb+OcSWV9g5w==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-node/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/@smithy/eventstream-serde-universal": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.8.tgz", + "integrity": "sha512-09tqzIQ6e+7jLqGvRji1yJoDbL/zob0OFhq75edgStWErGLf16+yI5hRc/o9/YAybOhUZs/swpW2SPn892G5Gg==", + "dependencies": { + "@smithy/eventstream-codec": "^3.1.5", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-universal/node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-universal/node_modules/@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/eventstream-serde-universal/node_modules/@smithy/eventstream-codec": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-3.1.5.tgz", + "integrity": "sha512-6pu+PT2r+5ZnWEV3vLV1DzyrpJ0TmehQlniIDCSpZg6+Ji2SfOI38EqUyQ+O8lotVElCrfVc9chKtSMe9cmCZQ==", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^3.4.2", + "@smithy/util-hex-encoding": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/eventstream-serde-universal/node_modules/@smithy/types": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.4.2.tgz", + "integrity": "sha512-tHiFcfcVedVBHpmHUEUHOCCih8iZbIAYn9NvPsNzaPm/237I3imdDdZoOC8c87H5HBAVEa06tTgb+OcSWV9g5w==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-universal/node_modules/@smithy/util-hex-encoding": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", + "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-universal/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.4.1.tgz", + "integrity": "sha512-VYGLinPsFqH68lxfRhjQaSkjXM7JysUOJDTNjHBuN/ykyRb2f1gyavN9+VhhPTWCy32L4yZ2fdhpCs/nStEicg==", + "dependencies": { + "@smithy/protocol-http": "^3.1.1", + "@smithy/querystring-builder": "^2.1.1", + "@smithy/types": "^2.9.1", + "@smithy/util-base64": "^2.1.1", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/fetch-http-handler/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/hash-blob-browser": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-3.1.5.tgz", + "integrity": "sha512-Vi3eoNCmao4iKglS80ktYnBOIqZhjbDDwa1IIbF/VaJ8PsHnZTQ5wSicicPrU7nTI4JPFn92/txzWkh4GlK18Q==", + "dependencies": { + "@smithy/chunked-blob-reader": "^3.0.0", + "@smithy/chunked-blob-reader-native": "^3.0.0", + "@smithy/types": "^3.4.2", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/hash-blob-browser/node_modules/@smithy/types": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.4.2.tgz", + "integrity": "sha512-tHiFcfcVedVBHpmHUEUHOCCih8iZbIAYn9NvPsNzaPm/237I3imdDdZoOC8c87H5HBAVEa06tTgb+OcSWV9g5w==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/hash-blob-browser/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/@smithy/hash-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.1.1.tgz", + "integrity": "sha512-Qhoq0N8f2OtCnvUpCf+g1vSyhYQrZjhSwvJ9qvR8BUGOtTXiyv2x1OD2e6jVGmlpC4E4ax1USHoyGfV9JFsACg==", + "dependencies": { + "@smithy/types": "^2.9.1", + "@smithy/util-buffer-from": "^2.1.1", + "@smithy/util-utf8": "^2.1.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/hash-node/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/hash-stream-node": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-3.1.5.tgz", + "integrity": "sha512-61CyFCzqN3VBfcnGX7mof/rkzLb8oHjm4Lr6ZwBIRpBssBb8d09ChrZAqinP2rUrA915BRNkq9NpJz18N7+3hQ==", + "dependencies": { + "@smithy/types": "^3.4.2", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/hash-stream-node/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/hash-stream-node/node_modules/@smithy/types": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.4.2.tgz", + "integrity": "sha512-tHiFcfcVedVBHpmHUEUHOCCih8iZbIAYn9NvPsNzaPm/237I3imdDdZoOC8c87H5HBAVEa06tTgb+OcSWV9g5w==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/hash-stream-node/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/hash-stream-node/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/hash-stream-node/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/@smithy/invalid-dependency": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.1.1.tgz", + "integrity": "sha512-7WTgnKw+VPg8fxu2v9AlNOQ5yaz6RA54zOVB4f6vQuR0xFKd+RzlCpt0WidYTsye7F+FYDIaS/RnJW4pxjNInw==", + "dependencies": { + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/invalid-dependency/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/is-array-buffer": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.1.1.tgz", + "integrity": "sha512-xozSQrcUinPpNPNPds4S7z/FakDTh1MZWtRP/2vQtYB/u3HYrX2UXuZs+VhaKBd6Vc7g2XPr2ZtwGBNDN6fNKQ==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/is-array-buffer/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/md5-js": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-3.0.6.tgz", + "integrity": "sha512-Ze690T8O3M5SVbb70WormwrKzVf9QQRtIuxtJDgpUQDkmt+PtdYDetBbyCbF9ryupxLw6tgzWKgwffAShhVIXQ==", + "dependencies": { + "@smithy/types": "^3.4.2", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/md5-js/node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/md5-js/node_modules/@smithy/types": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.4.2.tgz", + "integrity": "sha512-tHiFcfcVedVBHpmHUEUHOCCih8iZbIAYn9NvPsNzaPm/237I3imdDdZoOC8c87H5HBAVEa06tTgb+OcSWV9g5w==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/md5-js/node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/md5-js/node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/md5-js/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" + }, + "node_modules/@smithy/middleware-content-length": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.1.1.tgz", + "integrity": "sha512-rSr9ezUl9qMgiJR0UVtVOGEZElMdGFyl8FzWEF5iEKTlcWxGr2wTqGfDwtH3LAB7h+FPkxqv4ZU4cpuCN9Kf/g==", + "dependencies": { + "@smithy/protocol-http": "^3.1.1", + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-content-length/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.4.1.tgz", + "integrity": "sha512-XPZTb1E2Oav60Ven3n2PFx+rX9EDsU/jSTA8VDamt7FXks67ekjPY/XrmmPDQaFJOTUHJNKjd8+kZxVO5Ael4Q==", + "dependencies": { + "@smithy/middleware-serde": "^2.1.1", + "@smithy/node-config-provider": "^2.2.1", + "@smithy/shared-ini-file-loader": "^2.3.1", + "@smithy/types": "^2.9.1", + "@smithy/url-parser": "^2.1.1", + "@smithy/util-middleware": "^2.1.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-endpoint/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/middleware-retry": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.1.1.tgz", + "integrity": "sha512-eMIHOBTXro6JZ+WWzZWd/8fS8ht5nS5KDQjzhNMHNRcG5FkNTqcKpYhw7TETMYzbLfhO5FYghHy1vqDWM4FLDA==", + "dependencies": { + "@smithy/node-config-provider": "^2.2.1", + "@smithy/protocol-http": "^3.1.1", + "@smithy/service-error-classification": "^2.1.1", + "@smithy/smithy-client": "^2.3.1", + "@smithy/types": "^2.9.1", + "@smithy/util-middleware": "^2.1.1", + "@smithy/util-retry": "^2.1.1", + "tslib": "^2.5.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-retry/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/middleware-retry/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@smithy/middleware-serde": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.1.1.tgz", + "integrity": "sha512-D8Gq0aQBeE1pxf3cjWVkRr2W54t+cdM2zx78tNrVhqrDykRA7asq8yVJij1u5NDtKzKqzBSPYh7iW0svUKg76g==", + "dependencies": { + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-serde/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/middleware-stack": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.1.1.tgz", + "integrity": "sha512-KPJhRlhsl8CjgGXK/DoDcrFGfAqoqvuwlbxy+uOO4g2Azn1dhH+GVfC3RAp+6PoL5PWPb+vt6Z23FP+Mr6qeCw==", + "dependencies": { + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-stack/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/node-config-provider": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.2.1.tgz", + "integrity": "sha512-epzK3x1xNxA9oJgHQ5nz+2j6DsJKdHfieb+YgJ7ATWxzNcB7Hc+Uya2TUck5MicOPhDV8HZImND7ZOecVr+OWg==", + "dependencies": { + "@smithy/property-provider": "^2.1.1", + "@smithy/shared-ini-file-loader": "^2.3.1", + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/node-config-provider/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/node-http-handler": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.3.1.tgz", + "integrity": "sha512-gLA8qK2nL9J0Rk/WEZSvgin4AppvuCYRYg61dcUo/uKxvMZsMInL5I5ZdJTogOvdfVug3N2dgI5ffcUfS4S9PA==", + "dependencies": { + "@smithy/abort-controller": "^2.1.1", + "@smithy/protocol-http": "^3.1.1", + "@smithy/querystring-builder": "^2.1.1", + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/node-http-handler/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/property-provider": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.1.1.tgz", + "integrity": "sha512-FX7JhhD/o5HwSwg6GLK9zxrMUrGnb3PzNBrcthqHKBc3dH0UfgEAU24xnJ8F0uow5mj17UeBEOI6o3CF2k7Mhw==", + "dependencies": { + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/property-provider/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/protocol-http": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.1.1.tgz", + "integrity": "sha512-6ZRTSsaXuSL9++qEwH851hJjUA0OgXdQFCs+VDw4tGH256jQ3TjYY/i34N4vd24RV3nrjNsgd1yhb57uMoKbzQ==", + "dependencies": { + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/protocol-http/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/querystring-builder": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.1.1.tgz", + "integrity": "sha512-C/ko/CeEa8jdYE4gt6nHO5XDrlSJ3vdCG0ZAc6nD5ZIE7LBp0jCx4qoqp7eoutBu7VrGMXERSRoPqwi1WjCPbg==", + "dependencies": { + "@smithy/types": "^2.9.1", + "@smithy/util-uri-escape": "^2.1.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/querystring-builder/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/querystring-parser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.1.1.tgz", + "integrity": "sha512-H4+6jKGVhG1W4CIxfBaSsbm98lOO88tpDWmZLgkJpt8Zkk/+uG0FmmqMuCAc3HNM2ZDV+JbErxr0l5BcuIf/XQ==", + "dependencies": { + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/querystring-parser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/service-error-classification": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.1.1.tgz", + "integrity": "sha512-txEdZxPUgM1PwGvDvHzqhXisrc5LlRWYCf2yyHfvITWioAKat7srQvpjMAvgzf0t6t7j8yHrryXU9xt7RZqFpw==", + "dependencies": { + "@smithy/types": "^2.9.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.3.1.tgz", + "integrity": "sha512-2E2kh24igmIznHLB6H05Na4OgIEilRu0oQpYXo3LCNRrawHAcfDKq9004zJs+sAMt2X5AbY87CUCJ7IpqpSgdw==", + "dependencies": { + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/signature-v4": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.1.1.tgz", + "integrity": "sha512-Hb7xub0NHuvvQD3YwDSdanBmYukoEkhqBjqoxo+bSdC0ryV9cTfgmNjuAQhTPYB6yeU7hTR+sPRiFMlxqv6kmg==", + "dependencies": { + "@smithy/eventstream-codec": "^2.1.1", + "@smithy/is-array-buffer": "^2.1.1", + "@smithy/types": "^2.9.1", + "@smithy/util-hex-encoding": "^2.1.1", + "@smithy/util-middleware": "^2.1.1", + "@smithy/util-uri-escape": "^2.1.1", + "@smithy/util-utf8": "^2.1.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/signature-v4/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/smithy-client": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.3.1.tgz", + "integrity": "sha512-YsTdU8xVD64r2pLEwmltrNvZV6XIAC50LN6ivDopdt+YiF/jGH6PY9zUOu0CXD/d8GMB8gbhnpPsdrjAXHS9QA==", + "dependencies": { + "@smithy/middleware-endpoint": "^2.4.1", + "@smithy/middleware-stack": "^2.1.1", + "@smithy/protocol-http": "^3.1.1", + "@smithy/types": "^2.9.1", + "@smithy/util-stream": "^2.1.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/smithy-client/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/types": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.9.1.tgz", + "integrity": "sha512-vjXlKNXyprDYDuJ7UW5iobdmyDm6g8dDG+BFUncAg/3XJaN45Gy5RWWWUVgrzIK7S4R1KWgIX5LeJcfvSI24bw==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/types/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/url-parser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.1.1.tgz", + "integrity": "sha512-qC9Bv8f/vvFIEkHsiNrUKYNl8uKQnn4BdhXl7VzQRP774AwIjiSMMwkbT+L7Fk8W8rzYVifzJNYxv1HwvfBo3Q==", + "dependencies": { + "@smithy/querystring-parser": "^2.1.1", + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/url-parser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-base64": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.1.1.tgz", + "integrity": "sha512-UfHVpY7qfF/MrgndI5PexSKVTxSZIdz9InghTFa49QOvuu9I52zLPLUHXvHpNuMb1iD2vmc6R+zbv/bdMipR/g==", + "dependencies": { + "@smithy/util-buffer-from": "^2.1.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-base64/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-body-length-browser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.1.1.tgz", + "integrity": "sha512-ekOGBLvs1VS2d1zM2ER4JEeBWAvIOUKeaFch29UjjJsxmZ/f0L3K3x0dEETgh3Q9bkZNHgT+rkdl/J/VUqSRag==", + "dependencies": { + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/util-body-length-browser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-body-length-node": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.2.1.tgz", + "integrity": "sha512-/ggJG+ta3IDtpNVq4ktmEUtOkH1LW64RHB5B0hcr5ZaWBmo96UX2cIOVbjCqqDickTXqBWZ4ZO0APuaPrD7Abg==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-body-length-node/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-buffer-from": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.1.1.tgz", + "integrity": "sha512-clhNjbyfqIv9Md2Mg6FffGVrJxw7bgK7s3Iax36xnfVj6cg0fUG7I4RH0XgXJF8bxi+saY5HR21g2UPKSxVCXg==", + "dependencies": { + "@smithy/is-array-buffer": "^2.1.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-buffer-from/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-config-provider": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.2.1.tgz", + "integrity": "sha512-50VL/tx9oYYcjJn/qKqNy7sCtpD0+s8XEBamIFo4mFFTclKMNp+rsnymD796uybjiIquB7VCB/DeafduL0y2kw==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-config-provider/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.1.1.tgz", + "integrity": "sha512-lqLz/9aWRO6mosnXkArtRuQqqZBhNpgI65YDpww4rVQBuUT7qzKbDLG5AmnQTCiU4rOquaZO/Kt0J7q9Uic7MA==", + "dependencies": { + "@smithy/property-provider": "^2.1.1", + "@smithy/smithy-client": "^2.3.1", + "@smithy/types": "^2.9.1", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-browser/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-defaults-mode-node": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.2.0.tgz", + "integrity": "sha512-iFJp/N4EtkanFpBUtSrrIbtOIBf69KNuve03ic1afhJ9/korDxdM0c6cCH4Ehj/smI9pDCfVv+bqT3xZjF2WaA==", + "dependencies": { + "@smithy/config-resolver": "^2.1.1", + "@smithy/credential-provider-imds": "^2.2.1", + "@smithy/node-config-provider": "^2.2.1", + "@smithy/property-provider": "^2.1.1", + "@smithy/smithy-client": "^2.3.1", + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-node/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-endpoints": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-1.1.1.tgz", + "integrity": "sha512-sI4d9rjoaekSGEtq3xSb2nMjHMx8QXcz2cexnVyRWsy4yQ9z3kbDpX+7fN0jnbdOp0b3KSTZJZ2Yb92JWSanLw==", + "dependencies": { + "@smithy/node-config-provider": "^2.2.1", + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@smithy/util-endpoints/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-hex-encoding": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.1.1.tgz", + "integrity": "sha512-3UNdP2pkYUUBGEXzQI9ODTDK+Tcu1BlCyDBaRHwyxhA+8xLP8agEKQq4MGmpjqb4VQAjq9TwlCQX0kP6XDKYLg==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-hex-encoding/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-middleware": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.1.1.tgz", + "integrity": "sha512-mKNrk8oz5zqkNcbcgAAepeJbmfUW6ogrT2Z2gDbIUzVzNAHKJQTYmH9jcy0jbWb+m7ubrvXKb6uMjkSgAqqsFA==", + "dependencies": { + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-middleware/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-retry": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.1.1.tgz", + "integrity": "sha512-Mg+xxWPTeSPrthpC5WAamJ6PW4Kbo01Fm7lWM1jmGRvmrRdsd3192Gz2fBXAMURyXpaNxyZf6Hr/nQ4q70oVEA==", + "dependencies": { + "@smithy/service-error-classification": "^2.1.1", + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@smithy/util-retry/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-stream": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.1.1.tgz", + "integrity": "sha512-J7SMIpUYvU4DQN55KmBtvaMc7NM3CZ2iWICdcgaovtLzseVhAqFRYqloT3mh0esrFw+3VEK6nQFteFsTqZSECQ==", + "dependencies": { + "@smithy/fetch-http-handler": "^2.4.1", + "@smithy/node-http-handler": "^2.3.1", + "@smithy/types": "^2.9.1", + "@smithy/util-base64": "^2.1.1", + "@smithy/util-buffer-from": "^2.1.1", + "@smithy/util-hex-encoding": "^2.1.1", + "@smithy/util-utf8": "^2.1.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-stream/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-uri-escape": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.1.1.tgz", + "integrity": "sha512-saVzI1h6iRBUVSqtnlOnc9ssU09ypo7n+shdQ8hBTZno/9rZ3AuRYvoHInV57VF7Qn7B+pFJG7qTzFiHxWlWBw==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-uri-escape/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-utf8": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.1.1.tgz", + "integrity": "sha512-BqTpzYEcUMDwAKr7/mVRUtHDhs6ZoXDi9NypMvMfOr/+u1NW7JgqodPDECiiLboEm6bobcPcECxzjtQh865e9A==", + "dependencies": { + "@smithy/util-buffer-from": "^2.1.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-utf8/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@smithy/util-waiter": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-2.1.1.tgz", + "integrity": "sha512-kYy6BLJJNif+uqNENtJqWdXcpqo1LS+nj1AfXcDhOpqpSHJSAkVySLyZV9fkmuVO21lzGoxjvd1imGGJHph/IA==", + "dependencies": { + "@smithy/abort-controller": "^2.1.1", + "@smithy/types": "^2.9.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-waiter/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "node_modules/@szmarczak/http-timer": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", @@ -299,10 +4999,30 @@ "node": ">=10" } }, - "node_modules/@types/bson": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.5.tgz", - "integrity": "sha512-vVLwMUqhYJSQ/WKcE60eFqcyuWse5fGH+NMAXHuKrUAPoryq3ATxk5o4bgYNtg5aOM4APVg7Hnb3ASqUYG0PKg==", + "node_modules/@types/bcrypt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.0.tgz", + "integrity": "sha512-agtcFKaruL8TmcvqbndlqHPSJgsolhf/qPWchFlgnW1gECTN/nKbFcoFnvKAQRFfKbh+BO6A3SWdJu9t+xF3Lw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/buffer-crc32": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@types/buffer-crc32/-/buffer-crc32-0.2.2.tgz", + "integrity": "sha512-UpJyUKgG33LVehYtv9k2x4HUEY5ThV62YNGFBbQNBgtoky/0tQCceh8BPI9r3XL5hQ1tGmq34jGWNRBKf2P1UQ==", + "dev": true, "dependencies": { "@types/node": "*" } @@ -318,11 +5038,93 @@ "@types/responselike": "^1.0.0" } }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.13", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", + "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/dicer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@types/dicer/-/dicer-0.2.2.tgz", + "integrity": "sha512-UPLqCYey+jn5Mf57KFDwxD/7VZYDsbYUi3iyTehLFVjlbvl/JcUTPaot8uKNYLO0EoZpey+rC/s5AF3VxfeC2Q==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.35", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", + "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/fs-extra": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.1.tgz", + "integrity": "sha512-MxObHvNl4A69ofaTRU8DFqvgzzv8s9yRtaPPm5gud9HDNvpB3GPQFvNuTWAI59B9huVGV5jXYJwbCsmBsOGYWA==", + "dev": true, + "dependencies": { + "@types/jsonfile": "*", + "@types/node": "*" + } + }, "node_modules/@types/http-cache-semantics": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" }, + "node_modules/@types/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "dev": true + }, + "node_modules/@types/jsonfile": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.1.tgz", + "integrity": "sha512-GSgiRCVeapDN+3pqA35IkQwasaCh/0YFH5dEF6S88iDvEn901DjOeH3/QPY+XYP1DFzDZPvIvfeEgk+7br5png==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/keyv": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", @@ -331,19 +5133,66 @@ "@types/node": "*" } }, - "node_modules/@types/mongodb": { - "version": "3.6.20", - "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.20.tgz", - "integrity": "sha512-WcdpPJCakFzcWWD9juKoZbRtQxKIMYF/JIAM4JrNHrMcnJL6/a2NWjXxW7fo9hxboxxkg+icff8d7+WIEvKgYQ==", + "node_modules/@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" + }, + "node_modules/@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "dev": true + }, + "node_modules/@types/morgan": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.4.tgz", + "integrity": "sha512-cXoc4k+6+YAllH3ZHmx4hf7La1dzUk6keTR4bF4b4Sc0mZxU/zK4wO7l+ZzezXm/jkYj/qC+uYGZrarZdIVvyQ==", + "dev": true, "dependencies": { - "@types/bson": "*", "@types/node": "*" } }, + "node_modules/@types/ndarray": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@types/ndarray/-/ndarray-1.0.11.tgz", + "integrity": "sha512-hOZVTN24zDHwCHaW7mF9n1vHJt83fZhNZ0YYRBwQGhA96yBWWDPTDDlqJatagHIOJB0a4xoNkNc+t/Cxd+6qUA==", + "dev": true + }, "node_modules/@types/node": { - "version": "18.13.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", - "integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==" + "version": "18.17.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.6.tgz", + "integrity": "sha512-fGmT/P7z7ecA6bv/ia5DlaWCH4YeZvAQMNpUhrJjtAhOhZfoxS1VLUgU2pdk63efSjQaOJWdXMuAJsws+8I6dg==" + }, + "node_modules/@types/node-rsa": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/node-rsa/-/node-rsa-1.1.1.tgz", + "integrity": "sha512-itzxtaBgk4OMbrCawVCvas934waMZWjW17v7EYgFVlfYS/cl0/P7KZdojWCq9SDJMI5cnLQLUP8ayhVCTY8TEg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/nodemailer": { + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.9.tgz", + "integrity": "sha512-XYG8Gv+sHjaOtUpiuytahMy2mM3rectgroNbs6R3djZEKmPNiIJwe9KqOJBGzKKnNZNKvnuvmugBgpq3w/S0ig==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "dev": true }, "node_modules/@types/responselike": { "version": "1.0.0", @@ -353,11 +5202,251 @@ "@types/node": "*" } }, + "node_modules/@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", + "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", + "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, + "node_modules/@types/validator": { + "version": "13.11.1", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.1.tgz", + "integrity": "sha512-d/MUkJYdOeKycmm75Arql4M5+UuXmf4cHdHKsyw1GcvnNgL6s77UkgSgJ8TE/rI5PYsnwYq5jkcWBLuN/MpQ1A==", + "dev": true + }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" + }, + "node_modules/@types/whatwg-url": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", + "dependencies": { + "@types/node": "*", + "@types/webidl-conversions": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, + "node_modules/abort-controller-x": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/abort-controller-x/-/abort-controller-x-0.4.3.tgz", + "integrity": "sha512-VtUwTNU8fpMwvWGn4xE93ywbogTYsuT+AUxAXOeelbXuQVIwNmC5YLeho9sH4vZ4ITW8414TTAOG1nW6uIVHCA==" + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -371,9 +5460,10 @@ } }, "node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -381,6 +5471,15 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, "node_modules/acorn-node": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", @@ -391,6 +5490,17 @@ "xtend": "^4.0.2" } }, + "node_modules/acorn-node/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/acorn-walk": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", @@ -410,27 +5520,6 @@ "node": ">= 6.0.0" } }, - "node_modules/agent-base/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/agent-base/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -446,6 +5535,31 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -454,10 +5568,19 @@ "node": ">=8" } }, - "node_modules/append-field": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } }, "node_modules/aproba": { "version": "2.0.0", @@ -477,9 +5600,9 @@ } }, "node_modules/are-we-there-yet/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -497,6 +5620,12 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, "node_modules/arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", @@ -515,6 +5644,15 @@ "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", "integrity": "sha512-GQTc6Uupx1FCavi5mPzBvVT7nEOeWMmUA9P95wpfpW1XwMSKs+KaymD5C2Up7KAUKg/mYwbsUYzdZWcoajlNZg==" }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/arraybuffer-to-string": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/arraybuffer-to-string/-/arraybuffer-to-string-1.0.2.tgz", @@ -539,58 +5677,18 @@ "node_modules/async": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", - "dev": true + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/atob-lite": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-2.0.0.tgz", "integrity": "sha512-LEeSAWeh2Gfa2FtlQE1shxQ8zi5F9GHarrGKz08TMdODD5T4eH6BMsvtnhbWZ+XQn+Gb6om/917ucvRu7l7ukw==" }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/aws-sdk": { - "version": "2.1313.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1313.0.tgz", - "integrity": "sha512-8GMdtV2Uch3HL2c6+P3lNZFTcg/fqq9L3EWYRLb6ljCZvWKTssjdkjSJFDyTReNgeiKV224YRPYQbKpOEz4flQ==", - "dependencies": { - "buffer": "4.9.2", - "events": "1.1.1", - "ieee754": "1.1.13", - "jmespath": "0.16.0", - "querystring": "0.2.0", - "sax": "1.2.1", - "url": "0.10.3", - "util": "^0.12.4", - "uuid": "8.0.0", - "xml2js": "0.4.19" - }, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -626,7 +5724,9 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "optional": true, + "peer": true }, "node_modules/basic-auth": { "version": "2.0.1", @@ -645,12 +5745,12 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "node_modules/bcrypt": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.0.tgz", - "integrity": "sha512-RHBS7HI5N5tEnGTmtR/pppX0mmDSBpQ4aCBsj7CEQfYXDcO74A8sIBYcJMuCsis2E81zDxeENYhv66oZwLiA+Q==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", "hasInstallScript": true, "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.10", + "@mapbox/node-pre-gyp": "^1.0.11", "node-addon-api": "^5.0.0" }, "engines": { @@ -670,47 +5770,6 @@ "resolved": "https://registry.npmjs.org/bit-buffer/-/bit-buffer-0.2.5.tgz", "integrity": "sha512-x1yGnmXvFg6e3DiyRztElbcn1bsCTFSoM/ncAzY62uE0JdTl5xlKJd0ooqLYoPbhdsnpehSIQrdIvclcZJYwiA==" }, - "node_modules/bl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", - "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", - "dependencies": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/bl/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/bl/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/bl/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/bluebird": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" - }, "node_modules/bmp-js": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", @@ -739,6 +5798,24 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/bowser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -748,6 +5825,18 @@ "concat-map": "0.0.1" } }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/brfs": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/brfs/-/brfs-2.0.2.tgz", @@ -763,21 +5852,44 @@ } }, "node_modules/bson": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz", - "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==", + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/bson/-/bson-5.5.1.tgz", + "integrity": "sha512-ix0EwukN2EpC0SRWIj/7B5+A6uQMQy6KMREI9qQqvgpkV2frH63T0UDVd1SYedL6dNCmDBYB3QtXi4ISk9YT+g==", "engines": { - "node": ">=0.6.19" + "node": ">=14.20.1" } }, "node_modules/buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "optional": true, + "peer": true, "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "engines": { + "node": "*" } }, "node_modules/buffer-equal": { @@ -803,17 +5915,26 @@ "resolved": "https://registry.npmjs.org/buffer-to-uint8array/-/buffer-to-uint8array-1.1.0.tgz", "integrity": "sha512-JVTSbtA6YuOGdu5NL0ffizsBwuwbTXfV7OC91FhazMz9UKP/KlDS+Z7wuiSRClbnTQz52fJgVXI9YDXQRVl2sQ==" }, - "node_modules/busboy": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", - "integrity": "sha512-InWFDomvlkEj+xWLBfU3AvnbVYqeTWmQopiW0tWWEy5yehYm2YkGEc59sUmw/4ty5Zj/b0WHGs1LgecuBSBGrg==", - "dependencies": { - "dicer": "0.2.5", - "readable-stream": "1.1.x" - }, - "engines": { - "node": ">=0.8.0" - } + "node_modules/buffer/node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "optional": true, + "peer": true }, "node_modules/bytes": { "version": "3.1.2", @@ -832,9 +5953,9 @@ } }, "node_modules/cacheable-request": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", - "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", "dependencies": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", @@ -860,11 +5981,40 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, "node_modules/chownr": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", @@ -873,11 +6023,32 @@ "node": ">=10" } }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "engines": { + "node": ">= 12" + } + }, "node_modules/clip-pixels": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/clip-pixels/-/clip-pixels-1.0.1.tgz", "integrity": "sha512-nJ22fZvCwkJfMppkOEE7GciLX08rDnVzEJ+U46kBFZtwNzH2V4tNxMWa9Tc365WspCxy1c3NtGJ5EeT4SgjmCA==" }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/clone-response": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", @@ -897,6 +6068,22 @@ "node": ">=0.10.0" } }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, "node_modules/color-support": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", @@ -943,10 +6130,15 @@ "typedarray": "^0.0.6" } }, + "node_modules/concat-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "node_modules/concat-stream/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -970,84 +6162,6 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/connect-multiparty": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/connect-multiparty/-/connect-multiparty-2.2.0.tgz", - "integrity": "sha512-zKcpA7cuXGEhuw9Pz7JmVCFmp85jzGLGm/iiagXTwyEAJp4ypLPtRS/V4IGuGb9KjjrgHBs6P/gDCpZHnFzksA==", - "dependencies": { - "http-errors": "~1.7.0", - "multiparty": "~4.2.1", - "on-finished": "~2.3.0", - "qs": "~6.5.2", - "type-is": "~1.6.16" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/connect-multiparty/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/connect-multiparty/node_modules/http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/connect-multiparty/node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/connect-multiparty/node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/connect-multiparty/node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - }, - "node_modules/connect-multiparty/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/connect-multiparty/node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "engines": { - "node": ">=0.6" - } - }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -1090,6 +6204,63 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "node_modules/copyfiles": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/copyfiles/-/copyfiles-2.4.1.tgz", + "integrity": "sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==", + "dev": true, + "dependencies": { + "glob": "^7.0.5", + "minimatch": "^3.0.3", + "mkdirp": "^1.0.4", + "noms": "0.0.0", + "through2": "^2.0.1", + "untildify": "^4.0.0", + "yargs": "^16.1.0" + }, + "bin": { + "copyfiles": "copyfiles", + "copyup": "copyfiles" + } + }, + "node_modules/copyfiles/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/copyfiles/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/copyfiles/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -1107,13 +6278,52 @@ "node": ">= 0.10" } }, - "node_modules/cycle": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", - "integrity": "sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==", - "dev": true, + "node_modules/crc": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/crc/-/crc-4.3.2.tgz", + "integrity": "sha512-uGDHf4KLLh2zsHa8D8hIQ1H/HtFQhyHrc0uhHBcoKGol/Xnb+MPYfUMw7cvON6ze/GUESTudKayDcJC5HnJv1A==", "engines": { - "node": ">=0.4.0" + "node": ">=12" + }, + "peerDependencies": { + "buffer": ">=6.0.3" + }, + "peerDependenciesMeta": { + "buffer": { + "optional": true + } + } + }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" } }, "node_modules/d": { @@ -1142,11 +6352,19 @@ } }, "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { - "ms": "2.0.0" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/decompress-response": { @@ -1200,14 +6418,6 @@ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" }, - "node_modules/denque": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", - "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", - "engines": { - "node": ">=0.10" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -1226,9 +6436,9 @@ } }, "node_modules/detect-libc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", - "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", "engines": { "node": ">=8" } @@ -1245,12 +6455,39 @@ "node": ">=0.8.0" } }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/dotenv": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", "engines": { "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" } }, "node_modules/dtype": { @@ -1269,10 +6506,15 @@ "readable-stream": "^2.0.2" } }, + "node_modules/duplexer2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "node_modules/duplexer2/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -1310,6 +6552,20 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/email-validator": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/email-validator/-/email-validator-2.0.4.tgz", @@ -1417,11 +6673,31 @@ "es6-symbol": "^3.1.1" } }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/escodegen": { "version": "1.14.3", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", @@ -1443,6 +6719,174 @@ "source-map": "~0.6.1" } }, + "node_modules/escodegen/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.47.0.tgz", + "integrity": "sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "^8.47.0", + "@humanwhocodes/config-array": "^0.11.10", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", @@ -1455,6 +6899,48 @@ "node": ">=4" } }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, "node_modules/estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", @@ -1493,14 +6979,6 @@ "es5-ext": "~0.10.14" } }, - "node_modules/events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==", - "engines": { - "node": ">=0.4.x" - } - }, "node_modules/express": { "version": "4.18.2", "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", @@ -1542,61 +7020,29 @@ "node": ">= 0.10.0" } }, - "node_modules/express-form-data": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/express-form-data/-/express-form-data-2.0.19.tgz", - "integrity": "sha512-QWulRIYvZV/ZOuO0+SNpCs9Gl0st9SssYtm5Icfm17p2MU4HASLpd4K5w8fwnXB/lPPskecVSeqjVWi2SwIb1A==", - "dependencies": { - "connect-multiparty": "^2.2.0", - "fs-extra": "^9.1.0", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": ">=5.0.0" - } - }, - "node_modules/express-form-data/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/express-form-data/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/express-form-data/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/express-rate-limit": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.5.1.tgz", - "integrity": "sha512-MTjE2eIbHv5DyfuFz4zLYWxpqVhEhkTiwFGuB74Q9CSou2WHO52nlE5y3Zlg6SIsiYUIPj6ifFxnkPz6O3sIUg==" + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.9.0.tgz", + "integrity": "sha512-AnISR3V8qy4gpKM62/TzYdoFO9NV84fBx0POXzTryHU/qGUJBWuVGd+JhbvtVmKBv37t8/afmqdnv16xWoQxag==", + "engines": { + "node": ">= 14.0.0" + }, + "peerDependencies": { + "express": "^4 || ^5" + } }, - "node_modules/express-subdomain": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/express-subdomain/-/express-subdomain-1.0.5.tgz", - "integrity": "sha512-tpYy7MPgDoouxA4r+BnGI43yxYakbSSpQn7MjEYM0ssHeipTM1YiIoK3i4pCAgoXoks22Yb5C4QFkOYBYczZcw==" + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/ext": { "version": "1.7.0", @@ -1616,6 +7062,19 @@ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -1624,20 +7083,39 @@ "node >=0.6.0" ] }, - "node_modules/eyes": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", - "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", - "dev": true, - "engines": { - "node": "> 0.1.90" - } - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -1648,6 +7126,48 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, + "node_modules/fast-xml-parser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", + "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", + "funding": [ + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + }, + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/file-type": { "version": "10.11.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-10.11.0.tgz", @@ -1656,6 +7176,45 @@ "node": ">=6" } }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/finalhandler": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", @@ -1673,6 +7232,54 @@ "node": ">= 0.8" } }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, "node_modules/flatten-vertex-data": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/flatten-vertex-data/-/flatten-vertex-data-1.0.2.tgz", @@ -1686,14 +7293,6 @@ "resolved": "https://registry.npmjs.org/flip-pixels/-/flip-pixels-1.0.2.tgz", "integrity": "sha512-oXbJGbjDnfJRWPC7Va38EFhd+A8JWE5/hCiKcK8qjCdbLj9DTpsq6MEudwpRTH+V4qq+Jw7d3pUgQdSr3x3mTA==" }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dependencies": { - "is-callable": "^1.1.3" - } - }, "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -1715,15 +7314,6 @@ "node": ">= 0.12" } }, - "node_modules/formidable": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", - "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", - "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" - } - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -1817,13 +7407,22 @@ "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==" }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3" }, "funding": { @@ -1871,15 +7470,51 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, "dependencies": { - "get-intrinsic": "^1.1.3" + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/got": { @@ -1907,9 +7542,15 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true }, "node_modules/har-schema": { "version": "2.0.0", @@ -1943,10 +7584,18 @@ "node": ">= 0.4.0" } }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", "engines": { "node": ">= 0.4" }, @@ -1954,13 +7603,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dependencies": { - "has-symbols": "^1.0.2" - }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "engines": { "node": ">= 0.4" }, @@ -2036,27 +7682,6 @@ "node": ">= 6" } }, - "node_modules/https-proxy-agent/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/https-proxy-agent/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -2068,10 +7693,14 @@ "node": ">=0.10.0" } }, - "node_modules/ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } }, "node_modules/image-pixels": { "version": "1.1.1", @@ -2117,6 +7746,31 @@ "node": ">=6" } }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2131,6 +7785,17 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "node_modules/iota-array": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/iota-array/-/iota-array-1.0.0.tgz", + "integrity": "sha512-pZ2xT+LOHckCatGQ3DcG/a+QuEqvoxqkiL7tvE8nn3uuu+f6i1TtpB5/FtWFbxUuVr5PZCx8KskuGatbJDXOWA==", + "dev": true + }, + "node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -2139,21 +7804,6 @@ "node": ">= 0.10" } }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-base64": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/is-base64/-/is-base64-0.0.6.tgz", @@ -2197,21 +7847,10 @@ "node": ">=4" } }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", "dependencies": { "has": "^1.0.3" }, @@ -2219,6 +7858,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -2227,18 +7875,34 @@ "node": ">=8" } }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" } }, "node_modules/is-plain-obj": { @@ -2254,24 +7918,6 @@ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" }, - "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -2282,28 +7928,48 @@ "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" }, + "node_modules/is-valid-hostname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-valid-hostname/-/is-valid-hostname-1.0.2.tgz", + "integrity": "sha512-X/kiF3Xndj6WI7l/yLyzR7V1IbQd6L4S4cewSL0fRciemPmHbaXIKR2qtf+zseH+lbMG0vFp4HvCUe7amGZVhw==" + }, "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true }, "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" }, - "node_modules/jmespath": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", - "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", + "node_modules/jake": { + "version": "10.8.7", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", + "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, "engines": { - "node": ">= 0.6.0" + "node": ">=10" } }, "node_modules/joi": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.7.1.tgz", - "integrity": "sha512-teoLhIvWE298R6AeJywcjR4sX2hHjB3/xJX4qPjg+gTg+c0mzUDsziYlqPmLomq9gVsfaMcgPaGc7VxtD/9StA==", + "version": "17.9.2", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.9.2.tgz", + "integrity": "sha512-Itk/r+V4Dx0V3c7RLFdRh12IOjySm2/WGPMubBT92cQvRfYZhPM2W0hZlctjj72iES8jsRCwp7S/cRmWBnJ4nw==", "dependencies": { "@hapi/hoek": "^9.0.0", "@hapi/topo": "^5.0.0", @@ -2317,6 +7983,18 @@ "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.3.7.tgz", "integrity": "sha512-9IXdWudL61npZjvLuVe/ktHiA41iE8qFyLB+4VDTblEsWBzeg8WQTlktdUK4CdncUqtUgUg0bbOmTE2bKBKaBQ==" }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", @@ -2337,6 +8015,12 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -2364,41 +8048,54 @@ "node": ">=0.6.0" } }, - "node_modules/kaitai-struct": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/kaitai-struct/-/kaitai-struct-0.9.0.tgz", - "integrity": "sha512-mfoBu9+IGqaY3ykG1TyAy9omOAZWtheqESQOvo/HKIQVTz+gRPVCNBnhjbO+8wAQ77RD33wYvLBWmITuXIviQg==" - }, "node_modules/kareem": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.2.tgz", - "integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ==" + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", + "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==", + "engines": { + "node": ">=12.0.0" + } }, "node_modules/keyv": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", - "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", + "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", "dependencies": { "json-buffer": "3.0.1" } }, "node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" }, "node_modules/lodash.foreach": { "version": "4.5.0", @@ -2410,10 +8107,15 @@ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" }, - "node_modules/lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==" + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" }, "node_modules/lowercase-keys": { "version": "2.0.0", @@ -2457,9 +8159,9 @@ } }, "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "bin": { "semver": "bin/semver.js" } @@ -2499,6 +8201,15 @@ "node": ">=0.10.0" } }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -2507,6 +8218,19 @@ "node": ">= 0.6" } }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/mii-js": { "version": "1.0.4", "resolved": "git+ssh://git@github.com/PretendoNetwork/mii-js.git#5d8eb8013514a13b0df6eb4a5bfd8b5a63fb9861", @@ -2573,9 +8297,9 @@ } }, "node_modules/minipass": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.0.3.tgz", - "integrity": "sha512-OW2r4sQ0sI+z5ckEt5c1Tri4xTgZwYDxpE54eqWlQloQRoWtXjqt9udJ5Z4dSv7wK+nfFI7FRXyCpBSft+gpFw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "engines": { "node": ">=8" } @@ -2604,14 +8328,14 @@ } }, "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dependencies": { - "minimist": "^1.2.6" - }, + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "bin": { "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/moment": { @@ -2622,39 +8346,33 @@ "node": "*" } }, - "node_modules/moment-timezone": { - "version": "0.5.40", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.40.tgz", - "integrity": "sha512-tWfmNkRYmBkPJz5mr9GVDn9vRlVZOTe6yqY92rFxiOdWXbjaR0+9LwQnZGGuNR63X456NqmEkbskte8tWL5ePg==", - "dependencies": { - "moment": ">= 2.9.0" - }, - "engines": { - "node": "*" - } - }, "node_modules/mongodb": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.3.tgz", - "integrity": "sha512-Psm+g3/wHXhjBEktkxXsFMZvd3nemI0r3IPsE0bU+4//PnvNWKkzhZcEsbPcYiWqe8XqXJJEg4Tgtr7Raw67Yw==", + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.9.0.tgz", + "integrity": "sha512-g+GCMHN1CoRUA+wb1Agv0TI4YTSiWr42B5ulkiAfLLHitGK1R+PkSAf3Lr5rPZwi/3F04LiaZEW0Kxro9Fi2TA==", "dependencies": { - "bl": "^2.2.1", - "bson": "^1.1.4", - "denque": "^1.4.1", - "optional-require": "^1.1.8", - "safe-buffer": "^5.1.2" + "bson": "^5.5.0", + "mongodb-connection-string-url": "^2.6.0", + "socks": "^2.7.1" }, "engines": { - "node": ">=4" + "node": ">=14.20.1" }, "optionalDependencies": { - "saslprep": "^1.0.0" + "@mongodb-js/saslprep": "^1.1.0" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.0.0", + "kerberos": "^1.0.0 || ^2.0.0", + "mongodb-client-encryption": ">=2.3.0 <3", + "snappy": "^7.2.2" }, "peerDependenciesMeta": { - "aws4": { + "@aws-sdk/credential-providers": { "optional": true }, - "bson-ext": { + "@mongodb-js/zstd": { "optional": true }, "kerberos": { @@ -2663,77 +8381,58 @@ "mongodb-client-encryption": { "optional": true }, - "mongodb-extjson": { - "optional": true - }, "snappy": { "optional": true } } }, - "node_modules/mongodb/node_modules/optional-require": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz", - "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==", + "node_modules/mongodb-connection-string-url": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", + "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", "dependencies": { - "require-at": "^1.0.6" - }, - "engines": { - "node": ">=4" + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" } }, "node_modules/mongoose": { - "version": "5.13.15", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.15.tgz", - "integrity": "sha512-cxp1Gbb8yUWkaEbajdhspSaKzAvsIvOtRlYD87GN/P2QEUhpd6bIvebi36T6M0tIVAMauNaK9SPA055N3PwF8Q==", + "version": "7.6.5", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.6.5.tgz", + "integrity": "sha512-ElHgGWVKQUawKBn0DXuHmSd3W5w5Kb8JUbDNQH30odhYCDKq9GCh+E1/SuN8jZGxrHgFyLrvYxLSpC36BpqS+w==", "dependencies": { - "@types/bson": "1.x || 4.0.x", - "@types/mongodb": "^3.5.27", - "bson": "^1.1.4", - "kareem": "2.3.2", - "mongodb": "3.7.3", - "mongoose-legacy-pluralize": "1.0.2", - "mpath": "0.8.4", - "mquery": "3.2.5", - "ms": "2.1.2", - "optional-require": "1.0.x", - "regexp-clone": "1.0.0", - "safe-buffer": "5.2.1", - "sift": "13.5.2", - "sliced": "1.0.1" + "bson": "^5.5.0", + "kareem": "2.5.1", + "mongodb": "5.9.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "16.0.1" }, "engines": { - "node": ">=4.0.0" + "node": ">=14.20.1" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/mongoose" } }, - "node_modules/mongoose-legacy-pluralize": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", - "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==", - "peerDependencies": { - "mongoose": "*" - } - }, "node_modules/mongoose-unique-validator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/mongoose-unique-validator/-/mongoose-unique-validator-2.0.3.tgz", - "integrity": "sha512-3/8pmvAC1acBZS6eWKAWQUiZBlARE1wyWtjga4iQ2wDJeOfRlIKmAvTNHSZXKaAf7RCRUd7wh7as6yWAOrjpQg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mongoose-unique-validator/-/mongoose-unique-validator-4.0.0.tgz", + "integrity": "sha512-lOvL7wOZ8wM2Kggk6zPZuglmld7hmzf6TdNk/h9EidTH9iZNLl3Y2ZgRPjYd/so1AODLawehY56roa6HjX6jew==", "dependencies": { "lodash.foreach": "^4.1.0", - "lodash.get": "^4.0.2" + "lodash.get": "^4.0.2", + "lodash.merge": "^4.6.2" }, "peerDependencies": { - "mongoose": "^5.2.1" + "mongoose": "^7.0.0" } }, "node_modules/mongoose/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/morgan": { "version": "1.10.0", @@ -2750,6 +8449,19 @@ "node": ">= 0.8.0" } }, + "node_modules/morgan/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/morgan/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/morgan/node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -2762,113 +8474,63 @@ } }, "node_modules/mpath": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.4.tgz", - "integrity": "sha512-DTxNZomBcTWlrMW76jy1wvV37X/cNNxPW1y2Jzd4DZkAaC5ZGsm8bfGfNOthcDuRJujXLqiuS6o3Tpy0JEoh7g==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", "engines": { "node": ">=4.0.0" } }, "node_modules/mquery": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.5.tgz", - "integrity": "sha512-VjOKHHgU84wij7IUoZzFRU07IAxd5kWJaDmyUzQlbjHjyoeK5TNeeo8ZsFDtTYnSgpW6n/nMNIHvE3u8Lbrf4A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", "dependencies": { - "bluebird": "3.5.1", - "debug": "3.1.0", - "regexp-clone": "^1.0.0", - "safe-buffer": "5.1.2", - "sliced": "1.0.1" + "debug": "4.x" }, "engines": { - "node": ">=4.0.0" + "node": ">=14.0.0" } }, - "node_modules/mquery/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/mquery/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/multer": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", - "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", - "deprecated": "Multer 1.x is affected by CVE-2022-24434. This is fixed in v1.4.4-lts.1 which drops support for versions of Node.js before 6. Please upgrade to at least Node.js 6 and version 1.4.4-lts.1 of Multer. If you need support for older versions of Node.js, we are open to accepting patches that would fix the CVE on the main 1.x release line, whilst maintaining compatibility with Node.js 0.10.", - "dependencies": { - "append-field": "^1.0.0", - "busboy": "^0.2.11", - "concat-stream": "^1.5.2", - "mkdirp": "^0.5.4", - "object-assign": "^4.1.1", - "on-finished": "^2.3.0", - "type-is": "^1.6.4", - "xtend": "^4.0.0" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/multiparty": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-4.2.3.tgz", - "integrity": "sha512-Ak6EUJZuhGS8hJ3c2fY6UW5MbkGUPMBEGd13djUzoY/BHqV/gTuFWtC6IuVA7A2+v3yjBS6c4or50xhzTQZImQ==", - "dependencies": { - "http-errors": "~1.8.1", - "safe-buffer": "5.2.1", - "uid-safe": "2.1.5" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/multiparty/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/multiparty/node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/multiparty/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "engines": { - "node": ">= 0.6" - } + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, + "node_modules/ndarray": { + "version": "1.0.19", + "resolved": "https://registry.npmjs.org/ndarray/-/ndarray-1.0.19.tgz", + "integrity": "sha512-B4JHA4vdyZU30ELBw3g7/p9bZupyew5a7tX1Y/gGeF2hafrPaQZhgrGQfsvgfYbgdFZjYwuEcnaobeM/WMW+HQ==", + "dev": true, + "dependencies": { + "iota-array": "^1.0.0", + "is-buffer": "^1.0.2" + } + }, + "node_modules/ndarray/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, "node_modules/negotiator": { @@ -2879,20 +8541,43 @@ "node": ">= 0.6" } }, + "node_modules/nested-error-stacks": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.1.tgz", + "integrity": "sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==" + }, "node_modules/next-tick": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" }, + "node_modules/nice-grpc": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/nice-grpc/-/nice-grpc-2.1.5.tgz", + "integrity": "sha512-xqtgW+9VpKD+J3G3sl9+ggR//DmYGrNgjfuEznTU3eL/zRLhn/SwSzl2Elw7TiPknEQ54hDtaOP6VQ8ktv+6fA==", + "dependencies": { + "@grpc/grpc-js": "^1.8.18", + "abort-controller-x": "^0.4.0", + "nice-grpc-common": "^2.0.2" + } + }, + "node_modules/nice-grpc-common": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/nice-grpc-common/-/nice-grpc-common-2.0.2.tgz", + "integrity": "sha512-7RNWbls5kAL1QVUOXvBsv1uO0wPQK3lHv+cY1gwkTzirnG1Nop4cBJZubpgziNbaVc/bl9QJcyvsf/NQxa3rjQ==", + "dependencies": { + "ts-error": "^1.0.6" + } + }, "node_modules/node-addon-api": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" }, "node_modules/node-fetch": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -2908,23 +8593,63 @@ } } }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/node-rsa": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/node-rsa/-/node-rsa-1.1.1.tgz", "integrity": "sha512-Jd4cvbJMryN21r5HgxQOpMEqv+ooke/korixNNK3mGqfGJmy0M77WDDzo/05969+OkMy3XW1UuZsSmW9KQm7Fw==", - "dev": true, "dependencies": { "asn1": "^0.2.4" } }, "node_modules/nodemailer": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.1.tgz", - "integrity": "sha512-qHw7dOiU5UKNnQpXktdgQ1d3OFgRAekuvbJLcdG5dnEo/GtcTHRYM7+UfJARdOFU9WUQO8OiIamgWPmiSFHYAA==", + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.4.tgz", + "integrity": "sha512-CXjQvrQZV4+6X5wP6ZIgdehJamI63MFoYFGGPtHudWym9qaEHDNdPzaj5bfMCvxG1vhAileSWW90q7nL0N36mA==", "engines": { "node": ">=6.0.0" } }, + "node_modules/noms": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/noms/-/noms-0.0.0.tgz", + "integrity": "sha512-lNDU9VJaOPxUmXcLb+HQFeUgQQPtMI24Gt6hgfuMHRJgMRHMF/qZ4HJD3GDru4sSw9IQl2jPjAYnQrdIeLbwow==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "~1.0.31" + } + }, + "node_modules/noms/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, "node_modules/nopt": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", @@ -3017,30 +8742,31 @@ "wrappy": "1" } }, - "node_modules/optional-require": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz", - "integrity": "sha512-RV2Zp2MY2aeYK5G+B/Sps8lW5NHAzE5QClbFP15j+PWmP+T9PxlJXBOOLoSAdgwFvS4t0aMR4vpedMkbHfh0nA==", - "engines": { - "node": ">=4" - } - }, "node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" }, "engines": { "node": ">= 0.8.0" } }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/p-cancelable": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", @@ -3049,6 +8775,48 @@ "node": ">=8" } }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse-rect": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/parse-rect/-/parse-rect-1.2.0.tgz", @@ -3065,6 +8833,15 @@ "node": ">= 0.8" } }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -3073,6 +8850,15 @@ "node": ">=0.10.0" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -3083,6 +8869,15 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -3093,6 +8888,18 @@ "resolved": "https://registry.npmjs.org/pick-by-alias/-/pick-by-alias-1.2.0.tgz", "integrity": "sha512-ESj2+eBxhGrcA1azgHs7lARG5+5iLakc/6nlfbpjcLl00HuuUOIuORhYXN4D1HfvMSKuVtFQjAlnwi1JHEeDIw==" }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/pngjs": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", @@ -3102,9 +8909,10 @@ } }, "node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, "engines": { "node": ">= 0.8.0" } @@ -3119,20 +8927,27 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, - "node_modules/prompt": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.3.0.tgz", - "integrity": "sha512-ZkaRWtaLBZl7KKAKndKYUL8WqNT+cQHKRZnT4RYYms48jQkFw3rrBL+/N5K/KtdEveHkxs982MX2BkDKub2ZMg==", - "dev": true, + "node_modules/protobufjs": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.4.tgz", + "integrity": "sha512-AT+RJgD2sH8phPmCf7OUZR8xGdcJRga4+1cOaXJ64hvcSkVhNcRHOwIxUatPH15+nj59WAGTDv3LSGZPEQbJaQ==", + "hasInstallScript": true, "dependencies": { - "@colors/colors": "1.5.0", - "async": "3.2.3", - "read": "1.0.x", - "revalidator": "0.1.x", - "winston": "2.x" + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" }, "engines": { - "node": ">= 6.0.0" + "node": ">=12.0.0" } }, "node_modules/proxy-addr": { @@ -3183,14 +8998,25 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", - "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", - "engines": { - "node": ">=0.4.x" - } + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/quick-lru": { "version": "5.1.1", @@ -3216,14 +9042,6 @@ "quote-stream": "bin/cmd.js" } }, - "node_modules/random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -3246,18 +9064,6 @@ "node": ">= 0.8" } }, - "node_modules/read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", - "dev": true, - "dependencies": { - "mute-stream": "~0.0.4" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/readable-stream": { "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", @@ -3269,28 +9075,24 @@ "string_decoder": "~0.10.x" } }, - "node_modules/readable-stream/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" - }, "node_modules/redis": { - "version": "4.6.4", - "resolved": "https://registry.npmjs.org/redis/-/redis-4.6.4.tgz", - "integrity": "sha512-wi2tgDdQ+Q8q+PR5FLRx4QvDiWaA+PoJbrzsyFqlClN5R4LplHqN3scs/aGjE//mbz++W19SgxiEnQ27jnCRaA==", + "version": "4.6.7", + "resolved": "https://registry.npmjs.org/redis/-/redis-4.6.7.tgz", + "integrity": "sha512-KrkuNJNpCwRm5vFJh0tteMxW8SaUzkm5fBH7eL5hd/D0fAkzvapxbfGPP/r+4JAXdQuX7nebsBkBqA2RHB7Usw==", "dependencies": { "@redis/bloom": "1.2.0", - "@redis/client": "1.5.5", + "@redis/client": "1.5.8", "@redis/graph": "1.1.0", "@redis/json": "1.0.4", - "@redis/search": "1.1.1", + "@redis/search": "1.1.3", "@redis/time-series": "1.0.4" } }, - "node_modules/regexp-clone": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz", - "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==" + "node_modules/reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", + "optional": true }, "node_modules/request": { "version": "2.88.2", @@ -3340,20 +9142,20 @@ "uuid": "bin/uuid" } }, - "node_modules/require-at": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz", - "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==", + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", + "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", "dependencies": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -3369,6 +9171,15 @@ "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/responselike": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", @@ -3385,13 +9196,14 @@ "resolved": "https://registry.npmjs.org/restructure/-/restructure-2.0.1.tgz", "integrity": "sha512-e0dOpjm5DseomnXx2M5lpdZ5zoHqF1+bqdMJUohoYVVQa7cBdnk7fdmeI6byNWP/kiME72EeTiSypTCVnpLiDg==" }, - "node_modules/revalidator": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", - "integrity": "sha512-xcBILK2pA9oh4SiinPEZfhP8HfrB/ha+a2fTMyl7Om2WjlDVrOQy99N2MXXlUHqGJz4qEu2duXxHJjDWuK/0xg==", + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, "engines": { - "node": ">= 0.4.0" + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, "node_modules/rimraf": { @@ -3408,6 +9220,29 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -3432,23 +9267,6 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "node_modules/saslprep": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", - "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", - "optional": true, - "dependencies": { - "sparse-bitfield": "^3.0.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/sax": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", - "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" - }, "node_modules/scope-analyzer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/scope-analyzer/-/scope-analyzer-2.1.2.tgz", @@ -3464,9 +9282,9 @@ } }, "node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -3500,6 +9318,19 @@ "node": ">= 0.8.0" } }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -3534,6 +9365,27 @@ "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", "integrity": "sha512-b6i4ZpVuUxB9h5gfCxPiusKYkqTMOjEbBs4wMaFbkfia4yFv92UKZ6Df8WXcKbn08JNL/abvg3FnMAOfakDvUw==" }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -3548,19 +9400,45 @@ } }, "node_modules/sift": { - "version": "13.5.2", - "resolved": "https://registry.npmjs.org/sift/-/sift-13.5.2.tgz", - "integrity": "sha512-+gxdEOMA2J+AI+fVsCqeNn7Tgx3M9ZN9jdi95939l1IJ8cZsqS8sqpJyOkic2SJk+1+98Uwryt/gL6XDaV+UZA==" + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", + "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, - "node_modules/sliced": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", - "integrity": "sha512-VZBmZP8WU3sMOZm1bdgTadsQbcscK0UM8oKxKVBs4XAhUo2Xxzm/OFMGBkPusxw9xL3Uy8LrzEqGqJhclsr0yA==" + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } }, "node_modules/source-map": { "version": "0.6.1", @@ -3610,15 +9488,6 @@ "node": ">=0.10.0" } }, - "node_modules/stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/static-eval": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.1.0.tgz", @@ -3648,10 +9517,15 @@ "through2": "~2.0.3" } }, + "node_modules/static-module/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "node_modules/static-module/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -3734,6 +9608,46 @@ "node": ">=8" } }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stripe": { + "version": "12.18.0", + "resolved": "https://registry.npmjs.org/stripe/-/stripe-12.18.0.tgz", + "integrity": "sha512-cYjgBM2SY/dTm8Lr6eMyyONaHTZHA/QjHxFUIW5WH8FevSRIGAVtXEmBkUXF1fsqe7QvvRgQSGSJZmjDacegGg==", + "dependencies": { + "@types/node": ">=8.1.0", + "qs": "^6.11.0" + }, + "engines": { + "node": ">=12.*" + } + }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -3746,13 +9660,13 @@ } }, "node_modules/tar": { - "version": "6.1.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", - "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", - "minipass": "^4.0.0", + "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" @@ -3761,16 +9675,11 @@ "node": ">=10" } }, - "node_modules/tar/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true }, "node_modules/tga": { "version": "1.0.7", @@ -3784,6 +9693,19 @@ "node": ">=6.0.0" } }, + "node_modules/tga/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/tga/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -3793,10 +9715,15 @@ "xtend": "~4.0.1" } }, + "node_modules/through2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "node_modules/through2/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -3820,6 +9747,17 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/to-array-buffer": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/to-array-buffer/-/to-array-buffer-2.2.2.tgz", @@ -3830,6 +9768,18 @@ "string-to-arraybuffer": "^1.0.0" } }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -3851,9 +9801,39 @@ } }, "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/ts-error": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/ts-error/-/ts-error-1.0.6.tgz", + "integrity": "sha512-tLJxacIQUM82IR7JO1UUkKlYuUTmoY9HBJAmNWFzheSlDS5SPMcNIepejHJa4BpPQLAcbRhRf3GDJzyj6rbKvA==" + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } }, "node_modules/tunnel-agent": { "version": "0.6.0", @@ -3877,16 +9857,29 @@ "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" }, "node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, "dependencies": { - "prelude-ls": "~1.1.2" + "prelude-ls": "^1.2.1" }, "engines": { "node": ">= 0.8.0" } }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -3904,15 +9897,34 @@ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, - "node_modules/uid-safe": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", - "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", - "dependencies": { - "random-bytes": "~1.0.0" + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" }, "engines": { - "node": ">= 0.8" + "node": ">=4.2.0" + } + }, + "node_modules/typescript-is": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/typescript-is/-/typescript-is-0.19.0.tgz", + "integrity": "sha512-SAJEx2cxbQZhfOjDEjPnQJt1qRS1M3wrKbUwvsywVHWGbMgM1dcIf9gPWNDS1/dgTa/7Iexk2mmAHHsP9MeCsA==", + "dependencies": { + "nested-error-stacks": "^2", + "tsutils": "^3.17.1" + }, + "engines": { + "node": ">=6.14.4" + }, + "optionalDependencies": { + "reflect-metadata": ">=0.1.12" + }, + "peerDependencies": { + "typescript": "^4.1.5" } }, "node_modules/universalify": { @@ -3931,6 +9943,15 @@ "node": ">= 0.8" } }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -3939,32 +9960,6 @@ "punycode": "^2.1.0" } }, - "node_modules/url": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", - "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", - "dependencies": { - "punycode": "1.3.2", - "querystring": "0.2.0" - } - }, - "node_modules/url/node_modules/punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" - }, - "node_modules/util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -3978,18 +9973,10 @@ "node": ">= 0.4.0" } }, - "node_modules/uuid": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", - "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/validator": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.9.0.tgz", - "integrity": "sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==", + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", "engines": { "node": ">= 0.10" } @@ -4021,36 +10008,38 @@ "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" }, "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" } }, - "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, "node_modules/wide-align": { @@ -4061,71 +10050,35 @@ "string-width": "^1.0.2 || 2 || 3 || 4" } }, - "node_modules/winston": { - "version": "2.4.7", - "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.7.tgz", - "integrity": "sha512-vLB4BqzCKDnnZH9PHGoS2ycawueX4HLqENXQitvFHczhgW2vFpSOn31LZtVr1KU8YTw7DS4tM+cqyovxo8taVg==", - "dev": true, - "dependencies": { - "async": "^2.6.4", - "colors": "1.0.x", - "cycle": "1.0.x", - "eyes": "0.1.x", - "isstream": "0.1.x", - "stack-trace": "0.0.x" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/winston/node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/winston/node_modules/colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", - "dev": true, - "engines": { - "node": ">=0.1.90" - } - }, "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "engines": { "node": ">=0.10.0" } }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, - "node_modules/xml2js": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~9.0.1" - } - }, - "node_modules/xml2js/node_modules/xmlbuilder": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ==", - "engines": { - "node": ">=4.0" - } - }, "node_modules/xmlbuilder": { "version": "13.0.2", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz", @@ -4155,3288 +10108,74 @@ "node": ">=0.4" } }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, - "node_modules/yesno": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/yesno/-/yesno-0.4.0.tgz", - "integrity": "sha512-tdBxmHvbXPBKYIg81bMCB7bVeDmHkRzk5rVJyYYXurwKkHq/MCd8rz4HSJUP7hW0H2NlXiq8IFiWvYKEHhlotA==", - "dev": true - } - }, - "dependencies": { - "@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true - }, - "@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" - }, - "@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", - "requires": { - "@hapi/hoek": "^9.0.0" - } - }, - "@mapbox/node-pre-gyp": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", - "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", - "requires": { - "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - } - }, - "@oozcitak/dom": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-0.0.11.tgz", - "integrity": "sha512-BUNzbWpSn0Y7Yo8qgjVCM0axw2A6ncZaY7iC8msZIpuL6vYDP19zRqYI5bYWgBkgDXiap4cFEFsFrauyYAgKnw==", - "requires": { - "@oozcitak/infra": "1.0.4", - "@oozcitak/url": "0.0.8", - "@oozcitak/util": "1.0.2" - }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dependencies": { - "@oozcitak/util": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-1.0.2.tgz", - "integrity": "sha512-4n8B1cWlJleSOSba5gxsMcN4tO8KkkcvXhNWW+ADqvq9Xj+Lrl9uCa90GRpjekqQJyt84aUX015DG81LFpZYXA==" - } - } - }, - "@oozcitak/infra": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-1.0.4.tgz", - "integrity": "sha512-PIYPFk/MUzdhdeEBWL8TOEmEHyN60pWDCzXdN6XyNQHwt1i0YNUCOZ434Qa8WNuwJlOCNTrZFK8nlirIOF06Eg==", - "requires": { - "@oozcitak/util": "1.0.2" - }, - "dependencies": { - "@oozcitak/util": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-1.0.2.tgz", - "integrity": "sha512-4n8B1cWlJleSOSba5gxsMcN4tO8KkkcvXhNWW+ADqvq9Xj+Lrl9uCa90GRpjekqQJyt84aUX015DG81LFpZYXA==" - } - } - }, - "@oozcitak/url": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@oozcitak/url/-/url-0.0.8.tgz", - "integrity": "sha512-PR1ZCwaYvm781f0V14y2Uu8CM94k/znGfNpzJive5XjuDuCtMDFB3MYhSdVNZDG95faupVuFTph2lzn38S0zKg==", - "requires": { - "@oozcitak/infra": "1.0.3", - "@oozcitak/util": "1.0.2", - "@oozcitak/uts46": "0.0.8" - }, - "dependencies": { - "@oozcitak/infra": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-1.0.3.tgz", - "integrity": "sha512-9O2wxXGnRzy76O1XUxESxDGsXT5kzETJPvYbreO4mv6bqe1+YSuux2cZTagjJ/T4UfEwFJz5ixanOqB0QgYAag==", - "requires": { - "@oozcitak/util": "1.0.1" - }, - "dependencies": { - "@oozcitak/util": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-1.0.1.tgz", - "integrity": "sha512-dFwFqcKrQnJ2SapOmRD1nQWEZUtbtIy9Y6TyJquzsalWNJsKIPxmTI0KG6Ypyl8j7v89L2wixH9fQDNrF78hKg==" - } - } - }, - "@oozcitak/util": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-1.0.2.tgz", - "integrity": "sha512-4n8B1cWlJleSOSba5gxsMcN4tO8KkkcvXhNWW+ADqvq9Xj+Lrl9uCa90GRpjekqQJyt84aUX015DG81LFpZYXA==" - } - } - }, - "@oozcitak/util": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-1.0.3.tgz", - "integrity": "sha512-md38Xc0kBJ8I4aBI13xtX7r4RtSi9HByNVaqcVQeal3PSSbPKmtX1l6+8/YbfaIcP+fyLuwnOxHpYoh/R2DONw==" - }, - "@oozcitak/uts46": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@oozcitak/uts46/-/uts46-0.0.8.tgz", - "integrity": "sha512-/m/ytADxqWfGiNvenR5wkX7NGBRKQlypufv0w2NRAoWIGDuRLeweClJPRxV41Mln3HNtlF08OKoFFRUG8ztvGQ==", - "requires": { - "@oozcitak/util": "1.0.2", - "punycode": "2.1.1" - }, - "dependencies": { - "@oozcitak/util": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-1.0.2.tgz", - "integrity": "sha512-4n8B1cWlJleSOSba5gxsMcN4tO8KkkcvXhNWW+ADqvq9Xj+Lrl9uCa90GRpjekqQJyt84aUX015DG81LFpZYXA==" - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - } - } - }, - "@redis/bloom": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz", - "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==", - "requires": {} - }, - "@redis/client": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.5.tgz", - "integrity": "sha512-fuMnpDYSjT5JXR9rrCW1YWA4L8N/9/uS4ImT3ZEC/hcaQRI1D/9FvwjriRj1UvepIgzZXthFVKMNRzP/LNL7BQ==", - "requires": { - "cluster-key-slot": "1.1.2", - "generic-pool": "3.9.0", - "yallist": "4.0.0" - } - }, - "@redis/graph": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.0.tgz", - "integrity": "sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==", - "requires": {} - }, - "@redis/json": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.4.tgz", - "integrity": "sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==", - "requires": {} - }, - "@redis/search": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.1.tgz", - "integrity": "sha512-pqCXTc5e7wJJgUuJiC3hBgfoFRoPxYzwn0BEfKgejTM7M/9zP3IpUcqcjgfp8hF+LoV8rHZzcNTz7V+pEIY7LQ==", - "requires": {} - }, - "@redis/time-series": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.4.tgz", - "integrity": "sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==", - "requires": {} - }, - "@sideway/address": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", - "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", - "requires": { - "@hapi/hoek": "^9.0.0" - } - }, - "@sideway/formula": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" - }, - "@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" - }, - "@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==" - }, - "@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "requires": { - "defer-to-connect": "^2.0.0" - } - }, - "@types/bson": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.5.tgz", - "integrity": "sha512-vVLwMUqhYJSQ/WKcE60eFqcyuWse5fGH+NMAXHuKrUAPoryq3ATxk5o4bgYNtg5aOM4APVg7Hnb3ASqUYG0PKg==", - "requires": { - "@types/node": "*" - } - }, - "@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "requires": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" - } - }, - "@types/http-cache-semantics": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", - "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" - }, - "@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "requires": { - "@types/node": "*" - } - }, - "@types/mongodb": { - "version": "3.6.20", - "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.20.tgz", - "integrity": "sha512-WcdpPJCakFzcWWD9juKoZbRtQxKIMYF/JIAM4JrNHrMcnJL6/a2NWjXxW7fo9hxboxxkg+icff8d7+WIEvKgYQ==", - "requires": { - "@types/bson": "*", - "@types/node": "*" - } - }, - "@types/node": { - "version": "18.13.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", - "integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==" - }, - "@types/responselike": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", - "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", - "requires": { - "@types/node": "*" - } - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - } - }, - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" - }, - "acorn-node": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", - "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", - "requires": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" - } - }, - "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==" - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "requires": { - "debug": "4" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "append-field": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" - }, - "aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" - }, - "are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - } - } - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, - "array-from": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", - "integrity": "sha512-GQTc6Uupx1FCavi5mPzBvVT7nEOeWMmUA9P95wpfpW1XwMSKs+KaymD5C2Up7KAUKg/mYwbsUYzdZWcoajlNZg==" - }, - "arraybuffer-to-string": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer-to-string/-/arraybuffer-to-string-1.0.2.tgz", - "integrity": "sha512-WbIYlLVmvIAyUBdQRRuyGOJRriOQy9OAsWcyURmsRQp9+g647hdMSS2VFKXbJLVw0daUu06hqwLXm9etVrXI9A==" - }, - "asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==" - }, - "async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" - }, - "atob-lite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-2.0.0.tgz", - "integrity": "sha512-LEeSAWeh2Gfa2FtlQE1shxQ8zi5F9GHarrGKz08TMdODD5T4eH6BMsvtnhbWZ+XQn+Gb6om/917ucvRu7l7ukw==" - }, - "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" - }, - "aws-sdk": { - "version": "2.1313.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1313.0.tgz", - "integrity": "sha512-8GMdtV2Uch3HL2c6+P3lNZFTcg/fqq9L3EWYRLb6ljCZvWKTssjdkjSJFDyTReNgeiKV224YRPYQbKpOEz4flQ==", - "requires": { - "buffer": "4.9.2", - "events": "1.1.1", - "ieee754": "1.1.13", - "jmespath": "0.16.0", - "querystring": "0.2.0", - "sax": "1.2.1", - "url": "0.10.3", - "util": "^0.12.4", - "uuid": "8.0.0", - "xml2js": "0.4.19" - } - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==" - }, - "aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "basic-auth": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", - "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", - "requires": { - "safe-buffer": "5.1.2" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, - "bcrypt": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.0.tgz", - "integrity": "sha512-RHBS7HI5N5tEnGTmtR/pppX0mmDSBpQ4aCBsj7CEQfYXDcO74A8sIBYcJMuCsis2E81zDxeENYhv66oZwLiA+Q==", - "requires": { - "@mapbox/node-pre-gyp": "^1.0.10", - "node-addon-api": "^5.0.0" - } - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "bit-buffer": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/bit-buffer/-/bit-buffer-0.2.5.tgz", - "integrity": "sha512-x1yGnmXvFg6e3DiyRztElbcn1bsCTFSoM/ncAzY62uE0JdTl5xlKJd0ooqLYoPbhdsnpehSIQrdIvclcZJYwiA==" - }, - "bl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", - "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "bluebird": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" - }, - "bmp-js": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", - "integrity": "sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==" - }, - "body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "brfs": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brfs/-/brfs-2.0.2.tgz", - "integrity": "sha512-IrFjVtwu4eTJZyu8w/V2gxU7iLTtcHih67sgEdzrhjLBMHp2uYefUBfdM4k2UvcuWMgV7PQDZHSLeNWnLFKWVQ==", - "requires": { - "quote-stream": "^1.0.1", - "resolve": "^1.1.5", - "static-module": "^3.0.2", - "through2": "^2.0.0" - } - }, - "bson": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz", - "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==" - }, - "buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "buffer-equal": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", - "integrity": "sha512-RgSV6InVQ9ODPdLWJ5UAqBqJBOg370Nz6ZQtRzpt6nUjc8v0St97uJ4PYC6NztqIScrAXafKM3mZPMygSe1ggA==" - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "buffer-to-arraybuffer": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", - "integrity": "sha512-3dthu5CYiVB1DEJp61FtApNnNndTckcqe4pFcLdvHtrpG+kcyekCJKg4MRiDcFW7A6AODnXB9U4dwQiCW5kzJQ==" - }, - "buffer-to-uint8array": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-to-uint8array/-/buffer-to-uint8array-1.1.0.tgz", - "integrity": "sha512-JVTSbtA6YuOGdu5NL0ffizsBwuwbTXfV7OC91FhazMz9UKP/KlDS+Z7wuiSRClbnTQz52fJgVXI9YDXQRVl2sQ==" - }, - "busboy": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", - "integrity": "sha512-InWFDomvlkEj+xWLBfU3AvnbVYqeTWmQopiW0tWWEy5yehYm2YkGEc59sUmw/4ty5Zj/b0WHGs1LgecuBSBGrg==", - "requires": { - "dicer": "0.2.5", - "readable-stream": "1.1.x" - } - }, - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - }, - "cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==" - }, - "cacheable-request": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", - "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", - "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" - } - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" - }, - "clip-pixels": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/clip-pixels/-/clip-pixels-1.0.1.tgz", - "integrity": "sha512-nJ22fZvCwkJfMppkOEE7GciLX08rDnVzEJ+U46kBFZtwNzH2V4tNxMWa9Tc365WspCxy1c3NtGJ5EeT4SgjmCA==" - }, - "clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "requires": { - "mimic-response": "^1.0.0" - } - }, - "cluster-key-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", - "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==" - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" - }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "connect-multiparty": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/connect-multiparty/-/connect-multiparty-2.2.0.tgz", - "integrity": "sha512-zKcpA7cuXGEhuw9Pz7JmVCFmp85jzGLGm/iiagXTwyEAJp4ypLPtRS/V4IGuGb9KjjrgHBs6P/gDCpZHnFzksA==", - "requires": { - "http-errors": "~1.7.0", - "multiparty": "~4.2.1", - "on-finished": "~2.3.0", - "qs": "~6.5.2", - "type-is": "~1.6.16" - }, - "dependencies": { - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" - }, - "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", - "requires": { - "ee-first": "1.1.1" - } - }, - "qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==" - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" - } - } - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" - }, - "content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "requires": { - "safe-buffer": "5.2.1" - } - }, - "content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" - }, - "convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" - }, - "cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, - "cycle": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", - "integrity": "sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==", - "dev": true - }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "dash-ast": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-2.0.1.tgz", - "integrity": "sha512-5TXltWJGc+RdnabUGzhRae1TRq6m4gr+3K2wQX0is5/F2yS6MJXJvLyI3ErAnsAXuJoGqvfVD5icRgim07DrxQ==" - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "requires": { - "mimic-response": "^3.1.0" - }, - "dependencies": { - "mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" - } - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" - }, - "defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==" - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" - }, - "denque": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", - "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==" - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" - }, - "detect-libc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", - "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" - }, - "dicer": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", - "integrity": "sha512-FDvbtnq7dzlPz0wyYlOExifDEZcu8h+rErEXgfxqmLfRfC/kJidEFh4+effJRO3P0xmfqyPbSMG0LveNRfTKVg==", - "requires": { - "readable-stream": "1.1.x", - "streamsearch": "0.1.2" - } - }, - "dotenv": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==" - }, - "dtype": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dtype/-/dtype-2.0.0.tgz", - "integrity": "sha512-s2YVcLKdFGS0hpFqJaTwscsyt0E8nNFdmo73Ocd81xNPj4URI4rj6D60A+vFMIw7BXWlb4yRkEwfBqcZzPGiZg==" - }, - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", - "requires": { - "readable-stream": "^2.0.2" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "email-validator": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/email-validator/-/email-validator-2.0.4.tgz", - "integrity": "sha512-gYCwo7kh5S3IDyZPLZf6hSS0MnZT8QmJFqYvbqlDZSbwdZlY6QZWxJ4i/6UhITOJ4XzyI647Bm2MXKCLqnJ4nQ==" - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "requires": { - "once": "^1.4.0" - } - }, - "es5-ext": { - "version": "0.10.62", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", - "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", - "requires": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "next-tick": "^1.1.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-map": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", - "integrity": "sha512-mz3UqCh0uPCIqsw1SSAkB/p0rOzF/M0V++vyN7JqlPtSW/VsYgQBvVvqMLmfBuyMzTpLnNqi6JmcSizs4jy19A==", - "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-set": "~0.1.5", - "es6-symbol": "~3.1.1", - "event-emitter": "~0.3.5" - } - }, - "es6-set": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.6.tgz", - "integrity": "sha512-TE3LgGLDIBX332jq3ypv6bcOpkLO0AslAQo7p2VqX/1N46YNsvIWgvjojjSEnWEGWMhr1qUbYeTSir5J6mFHOw==", - "requires": { - "d": "^1.0.1", - "es5-ext": "^0.10.62", - "es6-iterator": "~2.0.3", - "es6-symbol": "^3.1.3", - "event-emitter": "^0.3.5", - "type": "^2.7.2" - }, - "dependencies": { - "type": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", - "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" - } - } - }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "escodegen": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", - "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", - "requires": { - "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" - }, - "estree-is-function": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/estree-is-function/-/estree-is-function-1.0.0.tgz", - "integrity": "sha512-nSCWn1jkSq2QAtkaVLJZY2ezwcFO161HVc174zL1KPW3RJ+O6C3eJb8Nx7OXzvhoEv+nLgSR1g71oWUHUDTrJA==" - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" - }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==" - }, - "express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.1", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - } - }, - "express-form-data": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/express-form-data/-/express-form-data-2.0.19.tgz", - "integrity": "sha512-QWulRIYvZV/ZOuO0+SNpCs9Gl0st9SssYtm5Icfm17p2MU4HASLpd4K5w8fwnXB/lPPskecVSeqjVWi2SwIb1A==", - "requires": { - "connect-multiparty": "^2.2.0", - "fs-extra": "^9.1.0", - "signal-exit": "^3.0.7" - }, - "dependencies": { - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" - } - } - }, - "express-rate-limit": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.5.1.tgz", - "integrity": "sha512-MTjE2eIbHv5DyfuFz4zLYWxpqVhEhkTiwFGuB74Q9CSou2WHO52nlE5y3Zlg6SIsiYUIPj6ifFxnkPz6O3sIUg==" - }, - "express-subdomain": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/express-subdomain/-/express-subdomain-1.0.5.tgz", - "integrity": "sha512-tpYy7MPgDoouxA4r+BnGI43yxYakbSSpQn7MjEYM0ssHeipTM1YiIoK3i4pCAgoXoks22Yb5C4QFkOYBYczZcw==" - }, - "ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", - "requires": { - "type": "^2.7.2" - }, - "dependencies": { - "type": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", - "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==" - }, - "eyes": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", - "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" - }, - "file-type": { - "version": "10.11.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-10.11.0.tgz", - "integrity": "sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw==" - }, - "finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - } - }, - "flatten-vertex-data": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/flatten-vertex-data/-/flatten-vertex-data-1.0.2.tgz", - "integrity": "sha512-BvCBFK2NZqerFTdMDgqfHBwxYWnxeCkwONsw6PvBMcUXqo8U/KDWwmXhqx1x2kLIg7DqIsJfOaJFOmlua3Lxuw==", - "requires": { - "dtype": "^2.0.0" - } - }, - "flip-pixels": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/flip-pixels/-/flip-pixels-1.0.2.tgz", - "integrity": "sha512-oXbJGbjDnfJRWPC7Va38EFhd+A8JWE5/hCiKcK8qjCdbLj9DTpsq6MEudwpRTH+V4qq+Jw7d3pUgQdSr3x3mTA==" - }, - "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "requires": { - "is-callable": "^1.1.3" - } - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==" - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "formidable": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", - "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==" - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - } - }, - "generic-pool": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", - "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==" - }, - "get-assigned-identifiers": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", - "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==" - }, - "get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - } - }, - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "requires": { - "pump": "^3.0.0" - } - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "requires": { - "get-intrinsic": "^1.1.3" - } - }, - "got": { - "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "requires": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" - } - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==" - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" - }, - "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "requires": { - "has-symbols": "^1.0.2" - } - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" - }, - "hcaptcha": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/hcaptcha/-/hcaptcha-0.1.1.tgz", - "integrity": "sha512-iMrDmH2VpIEKOrcKWidVjI89FdDKTEdZ7PfPWkP27sTazIIkob8YfdY2ezaufAnWBiUUcvzsn0qF+dyXtBH2Vw==" - }, - "http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" - }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "requires": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "requires": { - "agent-base": "6", - "debug": "4" + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } + "engines": { + "node": ">=12" } }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" } }, - "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" - }, - "image-pixels": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/image-pixels/-/image-pixels-1.1.1.tgz", - "integrity": "sha512-NQgoJVHiOWfmQnkEPSvOD8iuKUfm3AUXKdelCN8tQWT9NtwOd5qHofUci0Fcua6d28eq4gBXRKz7MQd8QK53rg==", - "requires": { - "arr-flatten": "^1.1.0", - "arraybuffer-to-string": "^1.0.2", - "bmp-js": "^0.1.0", - "brfs": "^2.0.1", - "buffer-to-arraybuffer": "0.0.5", - "buffer-to-uint8array": "^1.1.0", - "clip-pixels": "^1.0.1", - "es6-weak-map": "^2.0.2", - "flip-pixels": "^1.0.1", - "image-type": "^3.0.0", - "is-base64": "0.0.6", - "is-blob": "^2.0.0", - "is-browser": "^2.1.0", - "is-buffer": "^2.0.3", - "is-plain-obj": "^1.1.0", - "is-promise": "^2.1.0", - "is-url": "^1.2.4", - "jpeg-js": "^0.3.4", - "object-assign": "^4.1.1", - "omggif": "^1.0.9", - "parse-rect": "^1.2.0", - "pngjs": "^3.3.3", - "primitive-pool": "^1.1.0", - "request": "^2.88.0", - "string-to-arraybuffer": "^1.0.1", - "to-array-buffer": "^2.1.0" - } - }, - "image-type": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/image-type/-/image-type-3.1.0.tgz", - "integrity": "sha512-edYRXKQ3WD2yHXFGUbwoJVn5v7j1A6Z505uZUYIfzCwOOhPGLYSc3VOucF9fqbsaUbgb37DdjOU+WV4uo7ZooQ==", - "requires": { - "file-type": "^10.9.0" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - }, - "is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-base64": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/is-base64/-/is-base64-0.0.6.tgz", - "integrity": "sha512-u1cuGk5DbKVfoKvqtF+nV4a4VWN+0npvTuOzyEcScqriIJbQrExdEr2lVkqt3pCIgW5aS7hI1Us9qYaK4FXrZQ==" - }, - "is-blob": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-blob/-/is-blob-2.1.0.tgz", - "integrity": "sha512-SZ/fTft5eUhQM6oF/ZaASFDEdbFVe89Imltn9uZr03wdKMcWNVYSMjQPFtg05QuNkt5l5c135ElvXEQG0rk4tw==" - }, - "is-browser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-browser/-/is-browser-2.1.0.tgz", - "integrity": "sha512-F5rTJxDQ2sW81fcfOR1GnCXT6sVJC104fCyfj+mjpwNEwaPYSn5fte5jiHmBg3DHsIoL/l8Kvw5VN5SsTRcRFQ==" - }, - "is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" - }, - "is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" - }, - "is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "requires": { - "has": "^1.0.3" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==" - }, - "is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" - }, - "is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, - "is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" - }, - "jmespath": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", - "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==" - }, - "joi": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.7.1.tgz", - "integrity": "sha512-teoLhIvWE298R6AeJywcjR4sX2hHjB3/xJX4qPjg+gTg+c0mzUDsziYlqPmLomq9gVsfaMcgPaGc7VxtD/9StA==", - "requires": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.3", - "@sideway/formula": "^3.0.1", - "@sideway/pinpoint": "^2.0.0" - } - }, - "jpeg-js": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.3.7.tgz", - "integrity": "sha512-9IXdWudL61npZjvLuVe/ktHiA41iE8qFyLB+4VDTblEsWBzeg8WQTlktdUK4CdncUqtUgUg0bbOmTE2bKBKaBQ==" - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" - }, - "json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" - }, - "json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, - "kaitai-struct": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/kaitai-struct/-/kaitai-struct-0.9.0.tgz", - "integrity": "sha512-mfoBu9+IGqaY3ykG1TyAy9omOAZWtheqESQOvo/HKIQVTz+gRPVCNBnhjbO+8wAQ77RD33wYvLBWmITuXIviQg==" - }, - "kareem": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.2.tgz", - "integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ==" - }, - "keyv": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", - "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", - "requires": { - "json-buffer": "3.0.1" - } - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.foreach": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", - "integrity": "sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==" - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" - }, - "lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==" - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "magic-string": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.1.tgz", - "integrity": "sha512-sCuTz6pYom8Rlt4ISPFn6wuFodbKMIHUMv4Qko9P17dpxb7s52KJTmRuZZqHdGmLCK9AOcDare039nRIcfdkEg==", - "requires": { - "sourcemap-codec": "^1.4.1" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "requires": { - "semver": "^6.0.0" + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" - }, - "memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "optional": true - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" - }, - "merge-source-map": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.0.4.tgz", - "integrity": "sha512-PGSmS0kfnTnMJCzJ16BLLCEe6oeYCamKFFdQKshi4BmM6FUwipjVOcBFGxqtQtirtAG4iZvHlqST9CpZKqlRjA==", - "requires": { - "source-map": "^0.5.6" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" - } - } - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" - }, - "mii-js": { - "version": "git+ssh://git@github.com/PretendoNetwork/mii-js.git#5d8eb8013514a13b0df6eb4a5bfd8b5a63fb9861", - "from": "mii-js@github:PretendoNetwork/mii-js", - "requires": { - "bit-buffer": "^0.2.5" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" - }, - "minipass": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.0.3.tgz", - "integrity": "sha512-OW2r4sQ0sI+z5ckEt5c1Tri4xTgZwYDxpE54eqWlQloQRoWtXjqt9udJ5Z4dSv7wK+nfFI7FRXyCpBSft+gpFw==" - }, - "minizlib": { + "node_modules/yoctocolors-cjs": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", + "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", + "engines": { + "node": ">=18" }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "requires": { - "minimist": "^1.2.6" + "node_modules/zod": { + "version": "3.22.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", + "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" } - }, - "moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" - }, - "moment-timezone": { - "version": "0.5.40", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.40.tgz", - "integrity": "sha512-tWfmNkRYmBkPJz5mr9GVDn9vRlVZOTe6yqY92rFxiOdWXbjaR0+9LwQnZGGuNR63X456NqmEkbskte8tWL5ePg==", - "requires": { - "moment": ">= 2.9.0" - } - }, - "mongodb": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.3.tgz", - "integrity": "sha512-Psm+g3/wHXhjBEktkxXsFMZvd3nemI0r3IPsE0bU+4//PnvNWKkzhZcEsbPcYiWqe8XqXJJEg4Tgtr7Raw67Yw==", - "requires": { - "bl": "^2.2.1", - "bson": "^1.1.4", - "denque": "^1.4.1", - "optional-require": "^1.1.8", - "safe-buffer": "^5.1.2", - "saslprep": "^1.0.0" - }, - "dependencies": { - "optional-require": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz", - "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==", - "requires": { - "require-at": "^1.0.6" - } - } - } - }, - "mongoose": { - "version": "5.13.15", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.15.tgz", - "integrity": "sha512-cxp1Gbb8yUWkaEbajdhspSaKzAvsIvOtRlYD87GN/P2QEUhpd6bIvebi36T6M0tIVAMauNaK9SPA055N3PwF8Q==", - "requires": { - "@types/bson": "1.x || 4.0.x", - "@types/mongodb": "^3.5.27", - "bson": "^1.1.4", - "kareem": "2.3.2", - "mongodb": "3.7.3", - "mongoose-legacy-pluralize": "1.0.2", - "mpath": "0.8.4", - "mquery": "3.2.5", - "ms": "2.1.2", - "optional-require": "1.0.x", - "regexp-clone": "1.0.0", - "safe-buffer": "5.2.1", - "sift": "13.5.2", - "sliced": "1.0.1" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "mongoose-legacy-pluralize": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", - "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==", - "requires": {} - }, - "mongoose-unique-validator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/mongoose-unique-validator/-/mongoose-unique-validator-2.0.3.tgz", - "integrity": "sha512-3/8pmvAC1acBZS6eWKAWQUiZBlARE1wyWtjga4iQ2wDJeOfRlIKmAvTNHSZXKaAf7RCRUd7wh7as6yWAOrjpQg==", - "requires": { - "lodash.foreach": "^4.1.0", - "lodash.get": "^4.0.2" - } - }, - "morgan": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", - "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", - "requires": { - "basic-auth": "~2.0.1", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-finished": "~2.3.0", - "on-headers": "~1.0.2" - }, - "dependencies": { - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", - "requires": { - "ee-first": "1.1.1" - } - } - } - }, - "mpath": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.4.tgz", - "integrity": "sha512-DTxNZomBcTWlrMW76jy1wvV37X/cNNxPW1y2Jzd4DZkAaC5ZGsm8bfGfNOthcDuRJujXLqiuS6o3Tpy0JEoh7g==" - }, - "mquery": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.5.tgz", - "integrity": "sha512-VjOKHHgU84wij7IUoZzFRU07IAxd5kWJaDmyUzQlbjHjyoeK5TNeeo8ZsFDtTYnSgpW6n/nMNIHvE3u8Lbrf4A==", - "requires": { - "bluebird": "3.5.1", - "debug": "3.1.0", - "regexp-clone": "^1.0.0", - "safe-buffer": "5.1.2", - "sliced": "1.0.1" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "multer": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", - "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", - "requires": { - "append-field": "^1.0.0", - "busboy": "^0.2.11", - "concat-stream": "^1.5.2", - "mkdirp": "^0.5.4", - "object-assign": "^4.1.1", - "on-finished": "^2.3.0", - "type-is": "^1.6.4", - "xtend": "^4.0.0" - } - }, - "multiparty": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-4.2.3.tgz", - "integrity": "sha512-Ak6EUJZuhGS8hJ3c2fY6UW5MbkGUPMBEGd13djUzoY/BHqV/gTuFWtC6IuVA7A2+v3yjBS6c4or50xhzTQZImQ==", - "requires": { - "http-errors": "~1.8.1", - "safe-buffer": "5.2.1", - "uid-safe": "2.1.5" - }, - "dependencies": { - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" - }, - "http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==" - } - } - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" - }, - "next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" - }, - "node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" - }, - "node-fetch": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "node-rsa": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/node-rsa/-/node-rsa-1.1.1.tgz", - "integrity": "sha512-Jd4cvbJMryN21r5HgxQOpMEqv+ooke/korixNNK3mGqfGJmy0M77WDDzo/05969+OkMy3XW1UuZsSmW9KQm7Fw==", - "dev": true, - "requires": { - "asn1": "^0.2.4" - } - }, - "nodemailer": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.1.tgz", - "integrity": "sha512-qHw7dOiU5UKNnQpXktdgQ1d3OFgRAekuvbJLcdG5dnEo/GtcTHRYM7+UfJARdOFU9WUQO8OiIamgWPmiSFHYAA==" - }, - "nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "requires": { - "abbrev": "1" - } - }, - "normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" - }, - "npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "requires": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" - }, - "object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==" - }, - "omggif": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", - "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "requires": { - "wrappy": "1" - } - }, - "optional-require": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz", - "integrity": "sha512-RV2Zp2MY2aeYK5G+B/Sps8lW5NHAzE5QClbFP15j+PWmP+T9PxlJXBOOLoSAdgwFvS4t0aMR4vpedMkbHfh0nA==" - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, - "p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==" - }, - "parse-rect": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/parse-rect/-/parse-rect-1.2.0.tgz", - "integrity": "sha512-4QZ6KYbnE6RTwg9E0HpLchUM9EZt6DnDxajFZZDSV4p/12ZJEvPO702DZpGvRYEPo00yKDys7jASi+/w7aO8LA==", - "requires": { - "pick-by-alias": "^1.2.0" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" - }, - "pick-by-alias": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pick-by-alias/-/pick-by-alias-1.2.0.tgz", - "integrity": "sha512-ESj2+eBxhGrcA1azgHs7lARG5+5iLakc/6nlfbpjcLl00HuuUOIuORhYXN4D1HfvMSKuVtFQjAlnwi1JHEeDIw==" - }, - "pngjs": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", - "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==" - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==" - }, - "primitive-pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/primitive-pool/-/primitive-pool-1.1.0.tgz", - "integrity": "sha512-pl4l1R9OWWb4XmUpeX30yGz8ukZ25EiLhwlP2KqOqCb8NkwJt8qUeuCQEsk8CiAS7msICbPD18csu8jcIX7GNg==" - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "prompt": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.3.0.tgz", - "integrity": "sha512-ZkaRWtaLBZl7KKAKndKYUL8WqNT+cQHKRZnT4RYYms48jQkFw3rrBL+/N5K/KtdEveHkxs982MX2BkDKub2ZMg==", - "dev": true, - "requires": { - "@colors/colors": "1.5.0", - "async": "3.2.3", - "read": "1.0.x", - "revalidator": "0.1.x", - "winston": "2.x" - } - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - } - }, - "psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" - }, - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "requires": { - "side-channel": "^1.0.4" - } - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==" - }, - "quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==" - }, - "quote-stream": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/quote-stream/-/quote-stream-1.0.2.tgz", - "integrity": "sha512-kKr2uQ2AokadPjvTyKJQad9xELbZwYzWlNfI3Uz2j/ib5u6H9lDP7fUUR//rMycd0gv4Z5P1qXMfXR8YpIxrjQ==", - "requires": { - "buffer-equal": "0.0.1", - "minimist": "^1.1.3", - "through2": "^2.0.0" - } - }, - "random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==" - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", - "dev": true, - "requires": { - "mute-stream": "~0.0.4" - } - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" - } - } - }, - "redis": { - "version": "4.6.4", - "resolved": "https://registry.npmjs.org/redis/-/redis-4.6.4.tgz", - "integrity": "sha512-wi2tgDdQ+Q8q+PR5FLRx4QvDiWaA+PoJbrzsyFqlClN5R4LplHqN3scs/aGjE//mbz++W19SgxiEnQ27jnCRaA==", - "requires": { - "@redis/bloom": "1.2.0", - "@redis/client": "1.5.5", - "@redis/graph": "1.1.0", - "@redis/json": "1.0.4", - "@redis/search": "1.1.1", - "@redis/time-series": "1.0.4" - } - }, - "regexp-clone": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz", - "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==" - }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - } - } - }, - "require-at": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz", - "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==" - }, - "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "requires": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" - }, - "responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "requires": { - "lowercase-keys": "^2.0.0" - } - }, - "restructure": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/restructure/-/restructure-2.0.1.tgz", - "integrity": "sha512-e0dOpjm5DseomnXx2M5lpdZ5zoHqF1+bqdMJUohoYVVQa7cBdnk7fdmeI6byNWP/kiME72EeTiSypTCVnpLiDg==" - }, - "revalidator": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", - "integrity": "sha512-xcBILK2pA9oh4SiinPEZfhP8HfrB/ha+a2fTMyl7Om2WjlDVrOQy99N2MXXlUHqGJz4qEu2duXxHJjDWuK/0xg==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "saslprep": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", - "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", - "optional": true, - "requires": { - "sparse-bitfield": "^3.0.3" - } - }, - "sax": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", - "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" - }, - "scope-analyzer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/scope-analyzer/-/scope-analyzer-2.1.2.tgz", - "integrity": "sha512-5cfCmsTYV/wPaRIItNxatw02ua/MThdIUNnUOCYp+3LSEJvnG804ANw2VLaavNILIfWXF1D1G2KNANkBBvInwQ==", - "requires": { - "array-from": "^2.1.1", - "dash-ast": "^2.0.1", - "es6-map": "^0.1.5", - "es6-set": "^0.1.5", - "es6-symbol": "^3.1.1", - "estree-is-function": "^1.0.0", - "get-assigned-identifiers": "^1.1.0" - } - }, - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "requires": { - "lru-cache": "^6.0.0" - } - }, - "send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "requires": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "dependencies": { - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - } - } - }, - "serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "shallow-copy": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", - "integrity": "sha512-b6i4ZpVuUxB9h5gfCxPiusKYkqTMOjEbBs4wMaFbkfia4yFv92UKZ6Df8WXcKbn08JNL/abvg3FnMAOfakDvUw==" - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "sift": { - "version": "13.5.2", - "resolved": "https://registry.npmjs.org/sift/-/sift-13.5.2.tgz", - "integrity": "sha512-+gxdEOMA2J+AI+fVsCqeNn7Tgx3M9ZN9jdi95939l1IJ8cZsqS8sqpJyOkic2SJk+1+98Uwryt/gL6XDaV+UZA==" - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "sliced": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", - "integrity": "sha512-VZBmZP8WU3sMOZm1bdgTadsQbcscK0UM8oKxKVBs4XAhUo2Xxzm/OFMGBkPusxw9xL3Uy8LrzEqGqJhclsr0yA==" - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "optional": true - }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" - }, - "sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", - "optional": true, - "requires": { - "memory-pager": "^1.0.2" - } - }, - "sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", - "dev": true - }, - "static-eval": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.1.0.tgz", - "integrity": "sha512-agtxZ/kWSsCkI5E4QifRwsaPs0P0JmZV6dkLz6ILYfFYQGn+5plctanRN+IC8dJRiFkyXHrwEE3W9Wmx67uDbw==", - "requires": { - "escodegen": "^1.11.1" - } - }, - "static-module": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/static-module/-/static-module-3.0.4.tgz", - "integrity": "sha512-gb0v0rrgpBkifXCa3yZXxqVmXDVE+ETXj6YlC/jt5VzOnGXR2C15+++eXuMDUYsePnbhf+lwW0pE1UXyOLtGCw==", - "requires": { - "acorn-node": "^1.3.0", - "concat-stream": "~1.6.0", - "convert-source-map": "^1.5.1", - "duplexer2": "~0.1.4", - "escodegen": "^1.11.1", - "has": "^1.0.1", - "magic-string": "0.25.1", - "merge-source-map": "1.0.4", - "object-inspect": "^1.6.0", - "readable-stream": "~2.3.3", - "scope-analyzer": "^2.0.1", - "shallow-copy": "~0.0.1", - "static-eval": "^2.0.5", - "through2": "~2.0.3" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" - }, - "streamsearch": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", - "integrity": "sha512-jos8u++JKm0ARcSUTAZXOVC0mSox7Bhn6sBgty73P1f3JGf7yG2clTbBNHUdde/kdvP2FESam+vM6l8jBrNxHA==" - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" - }, - "string-to-arraybuffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-to-arraybuffer/-/string-to-arraybuffer-1.0.2.tgz", - "integrity": "sha512-DaGZidzi93dwjQen5I2osxR9ERS/R7B1PFyufNMnzhj+fmlDQAc1DSDIJVJhgI8Oq221efIMbABUBdPHDRt43Q==", - "requires": { - "atob-lite": "^2.0.0", - "is-base64": "^0.1.0" - }, - "dependencies": { - "is-base64": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-base64/-/is-base64-0.1.0.tgz", - "integrity": "sha512-WRRyllsGXJM7ZN7gPTCCQ/6wNPTRDwiWdPK66l5sJzcU/oOzcIcRRf0Rux8bkpox/1yjt0F6VJRsQOIG2qz5sg==" - } - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" - }, - "tar": { - "version": "6.1.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", - "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^4.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - } - } - }, - "tga": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/tga/-/tga-1.0.7.tgz", - "integrity": "sha512-GFVJwov5aJTMgh8U1QfaRheIELXo+dYc1qYIvQEIqZX4n+S6Fj/SDWsdbelHt7WP08xOR6W1z5aJQ+Ilh5gIeA==", - "requires": { - "debug": "^2.6.1", - "restructure": "^2.0.0" - } - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "to-array-buffer": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/to-array-buffer/-/to-array-buffer-2.2.2.tgz", - "integrity": "sha512-ZLcA71btdGxBs6WH2559ybYfoQ23756bZACcU9pIUwbBJ4Bwr1DHW96XfXQoKSk87pYo9zp2VsWrcX+At988Bw==", - "requires": { - "flatten-vertex-data": "^1.0.2", - "is-blob": "^2.0.1", - "string-to-arraybuffer": "^1.0.0" - } - }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" - }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" - }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "requires": { - "prelude-ls": "~1.1.2" - } - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" - }, - "uid-safe": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", - "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", - "requires": { - "random-bytes": "~1.0.0" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "requires": { - "punycode": "^2.1.0" - } - }, - "url": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", - "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" - } - } - }, - "util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "requires": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" - }, - "uuid": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", - "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==" - }, - "validator": { - "version": "13.9.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.9.0.tgz", - "integrity": "sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - }, - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" - } - } - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" - } - }, - "wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "requires": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "winston": { - "version": "2.4.7", - "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.7.tgz", - "integrity": "sha512-vLB4BqzCKDnnZH9PHGoS2ycawueX4HLqENXQitvFHczhgW2vFpSOn31LZtVr1KU8YTw7DS4tM+cqyovxo8taVg==", - "dev": true, - "requires": { - "async": "^2.6.4", - "colors": "1.0.x", - "cycle": "1.0.x", - "eyes": "0.1.x", - "isstream": "0.1.x", - "stack-trace": "0.0.x" - }, - "dependencies": { - "async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - }, - "colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", - "dev": true - } - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "xml2js": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", - "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "~9.0.1" - }, - "dependencies": { - "xmlbuilder": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ==" - } - } - }, - "xmlbuilder": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz", - "integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==" - }, - "xmlbuilder2": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/xmlbuilder2/-/xmlbuilder2-0.0.4.tgz", - "integrity": "sha512-4l+sSxet6EkVooCNlNgcImwrUZrk5BMRlJV6xUH9y19rwbwxB+OMfvlWT0hppDcVLjWM0Mu6FnpV/UGB4y/Feg==", - "requires": { - "@oozcitak/dom": "0.0.11", - "@oozcitak/infra": "1.0.4", - "@oozcitak/util": "1.0.3" - } - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "yesno": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/yesno/-/yesno-0.4.0.tgz", - "integrity": "sha512-tdBxmHvbXPBKYIg81bMCB7bVeDmHkRzk5rVJyYYXurwKkHq/MCd8rz4HSJUP7hW0H2NlXiq8IFiWvYKEHhlotA==", - "dev": true } } } diff --git a/package.json b/package.json index bed4955..0e27670 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,16 @@ { "name": "account", - "version": "1.0.0", + "version": "2.0.0", "description": "", - "main": "./src/server.js", + "main": "./dist/server.js", "scripts": { - "lint": "./node_modules/.bin/eslint .", + "lint": "eslint .", + "lint:fix": "eslint --fix .", + "build": "npm run lint && npm run clean && npx tsc && npx tsc-alias && npm run copy-static", + "clean": "rimraf ./dist", + "copy-static": "copyfiles -e \"src/**/*.ts\" -u 1 \"src/**/*\" dist", "start": "node .", - "start:dev": "NODE_ENV=development node ." + "start:dev": "cross-env NODE_ENV=development node ." }, "repository": { "type": "git", @@ -20,43 +24,65 @@ }, "homepage": "https://github.com/PretendoNetwork/account#readme", "dependencies": { - "aws-sdk": "^2.978.0", + "@aws-sdk/client-s3": "^3.657.0", + "@aws-sdk/client-ses": "^3.515.0", + "@inquirer/prompts": "^7.2.0", + "@pretendonetwork/grpc": "^1.0.5", "bcrypt": "^5.0.0", + "buffer-crc32": "^0.2.13", "colors": "^1.4.0", "cors": "^2.8.5", + "crc": "^4.3.2", "dicer": "^0.2.5", "dotenv": "^16.0.3", + "ejs": "^3.1.10", "email-validator": "^2.0.4", "express": "^4.17.1", - "express-form-data": "^2.0.17", - "express-rate-limit": "^5.3.0", - "express-subdomain": "^1.0.5", - "formidable": "^1.2.2", + "express-rate-limit": "^6.7.0", "fs-extra": "^8.1.0", "got": "^11.8.2", "hcaptcha": "^0.1.0", "image-pixels": "^1.1.1", - "joi": "^17.6.1", - "kaitai-struct": "^0.9.0", - "lodash.get": "^4.4.2", - "lodash.set": "^4.3.2", + "is-valid-hostname": "^1.0.2", + "joi": "^17.8.3", "mii-js": "github:PretendoNetwork/mii-js", - "moment": "^2.24.0", - "moment-timezone": "^0.5.27", - "mongoose": "^5.8.3", - "mongoose-unique-validator": "^2.0.3", + "moment": "^2.29.4", + "mongoose": "^7.0.0", + "mongoose-unique-validator": "^4.0.0", "morgan": "^1.9.1", - "multer": "^1.4.3", + "nice-grpc": "^2.1.4", + "node-rsa": "^1.0.7", "nodemailer": "^6.4.2", "redis": "^4.3.1", + "stripe": "^12.3.0", "tga": "^1.0.4", + "typescript-is": "^0.19.0", "validator": "^13.7.0", "xmlbuilder": "^13.0.2", - "xmlbuilder2": "0.0.4" + "xmlbuilder2": "0.0.4", + "zod": "^3.21.4" }, "devDependencies": { - "node-rsa": "^1.0.7", - "prompt": "^1.0.0", - "yesno": "^0.4.0" + "@hcaptcha/types": "^1.0.3", + "@types/bcrypt": "^5.0.0", + "@types/buffer-crc32": "^0.2.2", + "@types/cors": "^2.8.13", + "@types/dicer": "^0.2.2", + "@types/express": "^4.17.17", + "@types/fs-extra": "^11.0.1", + "@types/morgan": "^1.9.4", + "@types/ndarray": "^1.0.11", + "@types/node": "^18.14.4", + "@types/node-rsa": "^1.1.1", + "@types/nodemailer": "^6.4.7", + "@types/qs": "^6.9.7", + "@types/validator": "^13.7.14", + "@typescript-eslint/eslint-plugin": "^5.54.1", + "@typescript-eslint/parser": "^5.54.1", + "copyfiles": "^2.4.1", + "cross-env": "^7.0.3", + "eslint": "^8.35.0", + "ndarray": "^1.0.19", + "typescript": "^4.9.5" } } diff --git a/pnid-scrub.js b/pnid-scrub.js new file mode 100644 index 0000000..d1abadf --- /dev/null +++ b/pnid-scrub.js @@ -0,0 +1,38 @@ +const { connect } = require('./dist/database'); +const { PNID } = require('./dist/models/pnid'); +const { confirm, input } = require('@inquirer/prompts'); + +async function bootstrap() { + await connect(); + + const pnidName = await input({ message: 'What PNID do you want to delete?' }); + const pnid = await PNID.findOne({ username:pnidName.trim() }); + if (!pnid) { + console.log("Could not find PNID"); + process.exit(1); + } + + console.log('Before:', pnid); + + if (pnid.deleted) { + console.log("PNID is already marked as deleted"); + process.exit(1); + } + + const confirmed = await confirm({ message: 'Do you want to delete this PNID',default: false }); + if (!confirmed) { + console.log("Aborted"); + process.exit(1); + } + + await pnid.scrub(); + await pnid.save(); + + console.log('After:', pnid); + if (pnid.deleted) console.log("SUCCESSFULLY DELETED"); + else console.log("COULD NOT DELETE"); + + process.exit(0); +} + +bootstrap(); diff --git a/src/assets/emails/confirmationTemplate.html b/src/assets/emails/confirmationTemplate.html index e8eebe2..0a94625 100644 --- a/src/assets/emails/confirmationTemplate.html +++ b/src/assets/emails/confirmationTemplate.html @@ -179,7 +179,7 @@ - Note: this email message was auto-generated, please do not respond. For further assistance, please join our Discord server. + Note: this email message was auto-generated, please do not respond. For further assistance, please join our Discord server or make a post on our Forum. diff --git a/src/assets/emails/genericTemplate.html b/src/assets/emails/genericTemplate.html index 5f189c9..ce875fe 100644 --- a/src/assets/emails/genericTemplate.html +++ b/src/assets/emails/genericTemplate.html @@ -146,7 +146,7 @@ - Note: this email message was auto-generated, please do not respond. For further assistance, please join our Discord server. + Note: this email message was auto-generated, please do not respond. For further assistance, please join our Discord server or make a post on our Forum. diff --git a/src/assets/user-info-settings/index.css b/src/assets/user-info-settings/index.css new file mode 100644 index 0000000..9d9440c --- /dev/null +++ b/src/assets/user-info-settings/index.css @@ -0,0 +1,307 @@ +html { + background: #FF0000; +} + +body { + font-family: Poppins, Arial, Helvetica, sans-serif; + font-size: 15px; + width: 1280px; + margin: 0; + overflow: auto; + box-sizing: border-box; + background: #EAEAEA; +} + +button:active, +.server-selection input:checked + label { + box-shadow: inset 0 0px 10px 0 rgba(66, 45, 120, 0.75) !important; + color: #9D6FF3; +} + +header { + position: relative; + color: #FFF; + height: 70px; + line-height: 70px; + border-bottom: 2px solid #4F2E8C; + background: -webkit-gradient(linear, left top, left bottom, from(#9D6FF3), to(#673DB6)); + z-index: 19; +} + +header h1 { + margin: 0; + font-size: 30px; + text-align: center; + font-weight: normal; +} + +button, +.button, +input[type="submit"] { + font-family: Poppins, Arial, Helvetica, sans-serif; + color: #45297A; + min-width: 200px; + -webkit-box-sizing: content-box; + box-sizing: content-box; + -webkit-box-align: center; + -webkit-box-pack: center; + min-height: 60px; + text-align: center; + font-size: 28px; + background: -webkit-gradient(linear, left top, left bottom, from(#FFF), color-stop(0.5, #FFF), color-stop(0.8, #F6F6F6), color-stop(0.95, #F5F5F5), to(#BBB)) 0 0; + border-radius: 12px; + cursor: pointer; + border: 0; + box-shadow: 0 1px 5px rgba(0, 0, 0, 0.4); + margin: 5px; +} + +.body-content { + margin: 30px 60px 0 220px; +} + +div.group h2 { + font-weight: normal; +} + +div.group { + width: 485px; + display: inline-block; + margin: 0 5px; +} + +div.body-content > h1 { + margin: 15px 0 0 0; +} + +div.group > * { + margin: 5px 0; + font-size: 30px; +} + +div.group > p.content, +div.group > input[type="text"], +div.group > input[type="date"], +div.group > textarea, +div.group > select { + background: #FFF; + color: #6A6C75; + padding: 10px; + border-radius: 8px; + font-size: 25px; + box-shadow: none; + border: none; + width: 100%; + height: 58px; + box-sizing: border-box; + -moz-appearance: none; + -webkit-appearance: none; + appearance: none; + text-indent: 1px; + text-overflow: ''; + line-height: 38px; + resize: none; +} + +div.group > input[type="text"], +div.group > input[type="date"] { + color: #9D6FF3; +} + +div.group > select { + content: ' '; + background-color: #FFF; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' fill='%23673DB6' viewBox='0 0 256 256'%3E%3Cpath d='M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z'%3E%3C/path%3E%3C/svg%3E"); + background-size: 40px; + background-position: 440px center; + background-repeat: no-repeat; + color: #9D6FF3; + cursor: pointer; +} + +div.group > span { + color: #000; +} + +div.group > svg { + fill: #9D6FF3; + border: none; + height: 40px; + width: 40px; + padding: 0px; + margin-bottom: -10px; + margin-left: 5px; + -webkit-box-sizing: border-box; + -webkit-user-select: none; + box-sizing: border-box; + user-select: none; +} + +.account-info { + float: left; + width: 220px; + -webkit-box-sizing: content-box; + -webkit-box-align: center; + -webkit-box-pack: center; + box-sizing: content-box; +} + +.account-info > img { + display: inline-block; + width: 128px; + height: 128px; + overflow: hidden; + border-radius: 100%; + background: #E4DBF2; + margin: 30px 30px 0 46px; + box-shadow: 0-1px 2px rgba(0, 0, 0, 0.4); +} + +.account-info > .content { + text-align: center; + color: #673DB6; + margin: 0; +} + +.account-info > h3.content { + font-weight: normal; + color: #9D6FF3; + font-size: 20px; +} + +.account-info .access-level-banned { + background: rgba(255, 63, 0, 0.3); + color: #FF3F00; + border-color: #FF3F00; +} + +.account-info .tier-level-1 { + background: #934D4D; + color: #FF8484; + border-color: #FF8484; +} + +.account-info .tier-level-2 { + background: #316C59; + color: #59C9A5; + border-color: #59C9A5; +} + +.account-info .tier-level-3 { + background: #6B5E84; + color: #CAB1FB; + border-color: #CAB1FB; +} + +.account-info .access-level-1 { + background: #3B918C; + color: #64F7EF; + border-color: #64F7EF; +} + +.account-info .access-level-2 { + background: #917235; + color: #FFC759; + border-color: #FFC759; +} + +.account-info .access-level-3 { + background: #3A973C; + color: #5AFF15; + border-color: #5AFF15; +} + +.account-info .tier-name { + margin: 5px auto; + line-height: 1.2em; + border-radius: 1.2em; + border-width: 2px; + border-style: solid; + padding: 4px 16px; + width: min-content; + display: inline-block; +} + +div.group > p.content > button { + min-width: 100px; + min-height: 20px; + display: block; + width: 100px; + float: right; +} + +div.radio { + display: inline-block; +} + +.server-selection input { + opacity: 0; + position: absolute; + width: 130px; + height: 70px; + cursor: pointer; +} + +div.radio label { + display: inline-block; + color: #6A6C75; + padding: 0 10px; + min-width: 110px; + -webkit-box-sizing: content-box; + box-sizing: content-box; + -webkit-box-align: center; + -webkit-box-pack: center; + text-align: center; + background: -webkit-gradient(linear, left top, left bottom, from(#FFF), color-stop(0.5, #FFF), color-stop(0.8, #F6F6F6), color-stop(0.95, #F5F5F5), to(#BBB)) 0 0; + cursor: pointer; + border: 0; + box-shadow: 0 1px 5px rgba(0, 0, 0, 0.4); + margin: 5px; + font-weight: normal; + font-size: 15px; + -o-border-radius: 10px; + -webkit-border-radius: 10px; + -moz-border-radius: 10px; + -ms-border-radius: 10px; + border-radius: 10px; +} + +div.radio label h2 { + display: inline-block; + font-weight: normal; +} + +div.radio label svg { + margin: -6px 0; +} + +header .fixed-bottom-button.left { + padding: 0 60px 0 40px !important; +} + +.fixed-bottom-button.left { + right: auto; + left: 0; + border-radius: 0 40px 0 0; +} + +header .fixed-bottom-button { + min-width: 120px; + padding: 0 40px 0 60px; +} + +.fixed-bottom-button, +input[type="submit"] { + position: fixed; + bottom: 0; + right: 0; + height: 85px; + line-height: 100px; + padding: 0 40px 0 60px; + background: -webkit-gradient(linear, left top, left bottom, from(#FFF), color-stop(0.5, #FFF), to(#E6E6E6)) 0 0; + font-size: 28px; + z-index: 20; + border-radius: 40px 0 0 0; + margin: 0; + border: none; +} \ No newline at end of file diff --git a/src/cache.js b/src/cache.js deleted file mode 100644 index 6cd89e2..0000000 --- a/src/cache.js +++ /dev/null @@ -1,212 +0,0 @@ -const fs = require('fs-extra'); -const redis = require('redis'); -const { config, disabledFeatures } = require('./config-manager'); -let client; - -const memoryCache = {}; - -const SERVICE_CERTS_BASE = `${__dirname}/../certs/service`; -const NEX_CERTS_BASE = `${__dirname}/../certs/nex`; -const LOCAL_CDN_BASE = `${__dirname}/../cdn`; - -async function connect() { - if (!disabledFeatures.redis) { - client = redis.createClient(config.redis.client); - client.on('error', (err) => console.log('Redis Client Error', err)); - - await client.connect(); - } -} - -async function setCachedFile(fileName, value) { - if (disabledFeatures.redis) { - memoryCache[fileName] = value; - } else { - await client.set(fileName, value); - } -} - -async function getCachedFile(fileName, encoding) { - let cachedFile; - - if (disabledFeatures.redis) { - cachedFile = memoryCache[fileName] || null; - } else { - cachedFile = await client.get(fileName); - } - - if (cachedFile !== null) { - cachedFile = Buffer.from(cachedFile, encoding); - } - - return cachedFile; -} - -// NEX server cache functions - -async function getNEXPublicKey(name, encoding) { - let publicKey = await getCachedFile(`nex:${name}:public_key`, encoding); - - if (publicKey === null) { - publicKey = await fs.readFile(`${NEX_CERTS_BASE}/${name}/public.pem`, { encoding }); - await setNEXPublicKey(name, publicKey); - } - - return publicKey; -} - -async function getNEXPrivateKey(name, encoding) { - let privateKey = await getCachedFile(`nex:${name}:private_key`, encoding); - - if (privateKey === null) { - privateKey = await fs.readFile(`${NEX_CERTS_BASE}/${name}/private.pem`, { encoding }); - await setNEXPrivateKey(name, privateKey); - } - - return privateKey; -} - -async function getNEXSecretKey(name, encoding) { - let secretKey = await getCachedFile(`nex:${name}:secret_key`, encoding); - - if (secretKey === null) { - const fileBuffer = await fs.readFile(`${NEX_CERTS_BASE}/${name}/secret.key`, { encoding: 'utf8' }); - secretKey = Buffer.from(fileBuffer, encoding); - await setNEXSecretKey(name, secretKey); - } - - return secretKey; -} - -async function getNEXAESKey(name, encoding) { - let aesKey = await getCachedFile(`nex:${name}:aes_key`, encoding); - - if (aesKey === null) { - const fileBuffer = await fs.readFile(`${NEX_CERTS_BASE}/${name}/aes.key`, { encoding: 'utf8' }); - aesKey = Buffer.from(fileBuffer, encoding); - await setNEXAESKey(name, aesKey); - } - - return aesKey; -} - -async function setNEXPublicKey(name, value) { - await setCachedFile(`nex:${name}:public_key`, value); -} - -async function setNEXPrivateKey(name, value) { - await setCachedFile(`nex:${name}:private_key`, value); -} - -async function setNEXSecretKey(name, value) { - await setCachedFile(`nex:${name}:secret_key`, value); -} - -async function setNEXAESKey(name, value) { - await setCachedFile(`nex:${name}:aes_key`, value); -} - -// 3rd party service cache functions - -async function getServicePublicKey(name, encoding) { - let publicKey = await getCachedFile(`service:${name}:public_key`, encoding); - - if (publicKey === null) { - publicKey = await fs.readFile(`${SERVICE_CERTS_BASE}/${name}/public.pem`, { encoding }); - await setServicePublicKey(name, publicKey); - } - - return publicKey; -} - -async function getServicePrivateKey(name, encoding) { - let privateKey = await getCachedFile(`service:${name}:private_key`, encoding); - - if (privateKey === null) { - privateKey = await fs.readFile(`${SERVICE_CERTS_BASE}/${name}/private.pem`, { encoding }); - await setServicePrivateKey(name, privateKey); - } - - return privateKey; -} - -async function getServiceSecretKey(name, encoding) { - let secretKey = await getCachedFile(`service:${name}:secret_key`, encoding); - - if (secretKey === null) { - const fileBuffer = await fs.readFile(`${SERVICE_CERTS_BASE}/${name}/secret.key`, { encoding: 'utf8' }); - secretKey = Buffer.from(fileBuffer, encoding); - await setServiceSecretKey(name, secretKey); - } - - return secretKey; -} - -async function getServiceAESKey(name, encoding) { - let aesKey = await getCachedFile(`service:${name}:aes_key`, encoding); - - if (aesKey === null) { - const fileBuffer = await fs.readFile(`${SERVICE_CERTS_BASE}/${name}/aes.key`, { encoding: 'utf8' }); - aesKey = Buffer.from(fileBuffer, encoding); - await setServiceAESKey(name, aesKey); - } - - return aesKey; -} - -async function setServicePublicKey(name, value) { - await setCachedFile(`service:${name}:public_key`, value); -} - -async function setServicePrivateKey(name, value) { - await setCachedFile(`service:${name}:private_key`, value); -} - -async function setServiceSecretKey(name, value) { - await setCachedFile(`service:${name}:secret_key`, value); -} - -async function setServiceAESKey(name, value) { - await setCachedFile(`service:${name}:aes_key`, value); -} - -// Local CDN cache functions - -async function getLocalCDNFile(name, encoding) { - let file = await getCachedFile(`local_cdn:${name}`, encoding); - - if (file === null) { - if (await fs.pathExists(`${LOCAL_CDN_BASE}/${name}`)) { - file = await fs.readFile(`${LOCAL_CDN_BASE}/${name}`, { encoding }); - await setLocalCDNFile(name, file); - } - } - - return file; -} - -async function setLocalCDNFile(name, value) { - await setCachedFile(`local_cdn:${name}`, value); -} - -module.exports = { - connect, - getNEXPublicKey, - getNEXPrivateKey, - getNEXSecretKey, - getNEXAESKey, - setNEXPublicKey, - setNEXPrivateKey, - setNEXSecretKey, - setNEXAESKey, - getServicePublicKey, - getServicePrivateKey, - getServiceSecretKey, - getServiceAESKey, - setServicePublicKey, - setServicePrivateKey, - setServiceSecretKey, - setServiceAESKey, - getLocalCDNFile, - setLocalCDNFile -}; \ No newline at end of file diff --git a/src/cache.ts b/src/cache.ts new file mode 100644 index 0000000..7515446 --- /dev/null +++ b/src/cache.ts @@ -0,0 +1,61 @@ +import fs from 'fs-extra'; +import * as redis from 'redis'; +import { config, disabledFeatures } from '@/config-manager'; + +let client: redis.RedisClientType; + +const memoryCache: Record = {}; + +const LOCAL_CDN_BASE = `${__dirname}/../cdn`; + +export async function connect(): Promise { + if (!disabledFeatures.redis) { + client = redis.createClient(config.redis.client); + client.on('error', (err) => console.log('Redis Client Error', err)); + + await client.connect(); + } +} + +export async function setCachedFile(fileName: string, value: Buffer): Promise { + if (disabledFeatures.redis) { + memoryCache[fileName] = value; + } else { + await client.set(fileName, value); + } +} + +export async function getCachedFile(fileName: string, encoding?: BufferEncoding): Promise { + let cachedFile = Buffer.alloc(0); + + if (disabledFeatures.redis) { + cachedFile = memoryCache[fileName] || null; + } else { + const redisValue = await client.get(fileName); + if (redisValue) { + cachedFile = Buffer.from(redisValue, encoding); + } + } + + return cachedFile; +} + +// * Local CDN cache functions + +export async function getLocalCDNFile(name: string, encoding?: BufferEncoding): Promise { + let file = await getCachedFile(`local_cdn:${name}`, encoding); + + if (file === null) { + if (await fs.pathExists(`${LOCAL_CDN_BASE}/${name}`)) { + const fileBuffer = await fs.readFile(`${LOCAL_CDN_BASE}/${name}`, { encoding }); + file = Buffer.from(fileBuffer); + await setLocalCDNFile(name, file); + } + } + + return file; +} + +export async function setLocalCDNFile(name: string, value: Buffer): Promise { + await setCachedFile(`local_cdn:${name}`, value); +} \ No newline at end of file diff --git a/src/config-manager.js b/src/config-manager.js deleted file mode 100644 index 6376355..0000000 --- a/src/config-manager.js +++ /dev/null @@ -1,335 +0,0 @@ -const fs = require('fs-extra'); -const get = require('lodash.get'); -const set = require('lodash.set'); -const logger = require('../logger'); - -require('dotenv').config(); - -/** - * @typedef {Object} Config - * @property {object} http HTTP server settings - * @property {number} http.port HTTP port the server will listen on - * @property {object} mongoose Mongose connection settings - * @property {string} mongoose.connection_string MongoDB connection string - * @property {object} mongoose.options MongoDB connection options - * @property {object} [redis] redis settings - * @property {string} [redis.client] redis client settings - * @property {string} [redis.client.url] redis server URL - * @property {object} [email] node-mailer client settings - * @property {string} [email.host] SMTP server address - * @property {number} [email.port] SMTP server port - * @property {boolean} [email.secure] Secure SMTP - * @property {string} [email.from] Email 'from' name/address - * @property {object} [email.auth] Email authentication settings - * @property {string} [email.auth.user] Email username - * @property {string} [email.auth.pass] Email password - * @property {object} [s3] s3 client settings - * @property {object} [s3.endpoint] s3 endpoint URL - * @property {string} [s3.key] s3 access key - * @property {string} [s3.secret] s3 access secret - * @property {object} [hcaptcha] hCaptcha settings - * @property {string} [hcaptcha.secret] hCaptcha secret - * @property {object} cdn CDN config settings - * @property {object} [cdn.subdomain] Subdomain used for serving CDN contents when s3 is disabled - * @property {string} [cdn.disk_path] Fully qualified file system path for storing and reading local CDN contents - * @property {string} cdn.base_url Base URL for CDN server - * @property {string} website_base Base URL for service website (used with emails) - */ - -/** - * @type {Config} - */ -let config = {}; - -/** - * @typedef {Object} DisabledFeatures - * @property {boolean} redis true if redis is disabled - * @property {boolean} email true if email sending is disabled - * @property {boolean} captcha true if captcha verification is disabled - * @property {boolean} s3 true if s3 services is disabled - */ - -/** - * @type {DisabledFeatures} - */ -const disabledFeatures = { - redis: false, - email: false, - captcha: false, - s3: false -}; - -const requiredFields = [ - ['http.port', 'PN_ACT_CONFIG_HTTP_PORT', Number], - ['mongoose.connection_string', 'PN_ACT_CONFIG_MONGO_CONNECTION_STRING'], - ['cdn.base_url', 'PN_ACT_CONFIG_CDN_BASE_URL'] -]; - -function configure() { - const usingEnv = process.env.PN_ACT_PREFER_ENV_CONFIG === 'true'; - - if (usingEnv) { - logger.info('Loading config from environment variable'); - - config = { - http: { - port: Number(process.env.PN_ACT_CONFIG_HTTP_PORT) - }, - mongoose: { - connection_string: process.env.PN_ACT_CONFIG_MONGO_CONNECTION_STRING, - options: Object.keys(process.env) - .filter(key => key.startsWith('PN_ACT_CONFIG_MONGOOSE_OPTION_')) - .reduce((obj, key) => { - obj[key.split('_').pop()] = process.env[key]; - return obj; - }, {}) - }, - redis: { - client: { - url: process.env.PN_ACT_CONFIG_REDIS_URL - } - }, - email: { - host: process.env.PN_ACT_CONFIG_EMAIL_HOST, - port: Number(process.env.PN_ACT_CONFIG_EMAIL_PORT), - secure: Boolean(process.env.PN_ACT_CONFIG_EMAIL_SECURE), - auth: { - user: process.env.PN_ACT_CONFIG_EMAIL_USERNAME, - pass: process.env.PN_ACT_CONFIG_EMAIL_PASSWORD - }, - from: process.env.PN_ACT_CONFIG_EMAIL_FROM - }, - s3: { - endpoint: process.env.PN_ACT_CONFIG_S3_ENDPOINT, - key: process.env.PN_ACT_CONFIG_S3_ACCESS_KEY, - secret: process.env.PN_ACT_CONFIG_S3_ACCESS_SECRET - }, - hcaptcha: { - secret: process.env.PN_ACT_CONFIG_HCAPTCHA_SECRET - }, - cdn: { - subdomain: process.env.PN_ACT_CONFIG_CDN_SUBDOMAIN, - disk_path: process.env.PN_ACT_CONFIG_CDN_DISK_PATH, - base_url: process.env.PN_ACT_CONFIG_CDN_BASE_URL - }, - website_base: process.env.PN_ACT_CONFIG_WEBSITE_BASE - }; - } else { - logger.info('Loading config from config.json'); - - if (!fs.pathExistsSync(`${__dirname}/../config.json`)) { - logger.error('Failed to locate config.json file'); - process.exit(0); - } - - config = require(`${__dirname}/../config.json`); - } - - logger.info('Config loaded, checking integrity'); - - // * Check for required settings - for (const requiredField of requiredFields) { - const [keyPath, env, convertType] = requiredField; - - const configValue = get(config, keyPath); - const envValue = get(process.env, keyPath); - - if (!configValue || (typeof configValue === 'string' && configValue.trim() === '')) { - if (!envValue || envValue.trim() === '') { - logger.error(`Failed to locate required field ${keyPath}. Set ${keyPath} in config.json or the ${env} environment variable`); - - process.exit(0); - } else { - logger.info(`${keyPath} not found in config, using environment variable ${env}`); - - const newValue = envValue; - - set(config, keyPath, convertType ? convertType(newValue) : newValue); - } - } - } - - // * Check for optional settings - - const redisCheck = get(config, 'redis.client.url'); - - if (!redisCheck || redisCheck.trim() === '') { - if (usingEnv) { - logger.warn('Failed to find Redis connection url. Disabling feature and using in-memory cache. To enable feature set the PN_ACT_CONFIG_REDIS_URL environment variable'); - - } else { - logger.warn('Failed to find Redis connection url. Disabling feature and using in-memory cache. To enable feature set redis.client.url in your config.json'); - - } - - disabledFeatures.redis = true; - } - - const emailHostCheck = get(config, 'email.host'); - - if (!emailHostCheck || emailHostCheck.trim() === '') { - if (usingEnv) { - logger.warn('Failed to find email SMTP host. Disabling feature. To enable feature set the PN_ACT_CONFIG_EMAIL_HOST environment variable'); - } else { - logger.warn('Failed to find email SMTP host. Disabling feature. To enable feature set email.host in your config.json'); - } - - - disabledFeatures.email = true; - } - - const emailPortCheck = get(config, 'email.port'); - - if (!emailPortCheck) { - if (usingEnv) { - logger.warn('Failed to find email SMTP port. Disabling feature. To enable feature set the PN_ACT_CONFIG_EMAIL_PORT environment variable'); - } else { - logger.warn('Failed to find email SMTP port. Disabling feature. To enable feature set email.port in your config.json'); - } - - disabledFeatures.email = true; - } - - const emailSecureCheck = get(config, 'email.secure'); - - if (emailSecureCheck === undefined) { - if (usingEnv) { - logger.warn('Failed to find email SMTP secure flag. Disabling feature. To enable feature set the PN_ACT_CONFIG_EMAIL_SECURE environment variable'); - } else { - - logger.warn('Failed to find email SMTP secure flag. Disabling feature. To enable feature set email.secure in your config.json'); - } - - disabledFeatures.email = true; - } - - const emailUsernameCheck = get(config, 'email.auth.user'); - - if (!emailUsernameCheck || emailUsernameCheck.trim() === '') { - if (usingEnv) { - logger.warn('Failed to find email account username. Disabling feature. To enable feature set the auth.user environment variable'); - } else { - - logger.warn('Failed to find email account username. Disabling feature. To enable feature set email.auth.user in your config.json'); - } - - disabledFeatures.email = true; - } - - const emailPasswordCheck = get(config, 'email.auth.pass'); - - if (!emailPasswordCheck || emailPasswordCheck.trim() === '') { - if (usingEnv) { - logger.warn('Failed to find email account password. Disabling feature. To enable feature set the PN_ACT_CONFIG_EMAIL_PASSWORD environment variable'); - } else { - - logger.warn('Failed to find email account password. Disabling feature. To enable feature set email.auth.pass in your config.json'); - } - - disabledFeatures.email = true; - } - - const emailFromCheck = get(config, 'email.from'); - - if (!emailFromCheck || emailFromCheck.trim() === '') { - if (usingEnv) { - logger.warn('Failed to find email from config. Disabling feature. To enable feature set the PN_ACT_CONFIG_EMAIL_FROM environment variable'); - } else { - - logger.warn('Failed to find email from config. Disabling feature. To enable feature set email.from in your config.json'); - } - - disabledFeatures.email = true; - } - - if (!disabledFeatures.email) { - const websiteBaseCheck = get(config, 'website_base'); - - if (!websiteBaseCheck || websiteBaseCheck.trim() === '') { - if (usingEnv) { - logger.error('Email sending is enabled and no website base was configured. Set the PN_ACT_CONFIG_WEBSITE_BASE environment variable'); - } else { - logger.error('Email sending is enabled and no website base was configured. Set website_base in your config.json'); - } - - process.exit(0); - } - } - - const captchaSecretCheck = get(config, 'hcaptcha.secret'); - - if (!captchaSecretCheck || captchaSecretCheck.trim() === '') { - if (usingEnv) { - logger.warn('Failed to find captcha secret config. Disabling feature. To enable feature set the PN_ACT_CONFIG_HCAPTCHA_SECRET environment variable'); - } else { - logger.warn('Failed to find captcha secret config. Disabling feature. To enable feature set hcaptcha.secret in your config.json'); - } - - disabledFeatures.captcha = true; - } - - const s3EndpointCheck = get(config, 's3.endpoint'); - - if (!s3EndpointCheck || s3EndpointCheck.trim() === '') { - if (usingEnv) { - logger.warn('Failed to find s3 endpoint config. Disabling feature. To enable feature set the PN_ACT_CONFIG_S3_ENDPOINT environment variable'); - } else { - logger.warn('Failed to find s3 endpoint config. Disabling feature. To enable feature set s3.endpoint in your config.json'); - } - - disabledFeatures.s3 = true; - } else { - } - - const s3AccessKeyCheck = get(config, 's3.key'); - - if (!s3AccessKeyCheck || s3AccessKeyCheck.trim() === '') { - if (usingEnv) { - logger.warn('Failed to find s3 access key config. Disabling feature. To enable feature set the PN_ACT_CONFIG_S3_ACCESS_KEY environment variable'); - } else { - logger.warn('Failed to find s3 access key config. Disabling feature. To enable feature set s3.key in your config.json'); - } - - disabledFeatures.s3 = true; - } - - const s3SecretKeyCheck = get(config, 's3.secret'); - - if (!s3SecretKeyCheck || s3SecretKeyCheck.trim() === '') { - if (usingEnv) { - logger.warn('Failed to find s3 secret key config. Disabling feature. To enable feature set the PN_ACT_CONFIG_S3_ACCESS_SECRET environment variable'); - } else { - logger.warn('Failed to find s3 secret key config. Disabling feature. To enable feature set s3.secret in your config.json'); - } - - disabledFeatures.s3 = true; - } - - if (disabledFeatures.s3) { - const cdnSubdomainCheck = get(config, 'cdn.subdomain'); - - if (!cdnSubdomainCheck || cdnSubdomainCheck.trim() === '') { - if (usingEnv) { - logger.error('s3 file storage is disabled and no CDN subdomain was set. Set the PN_ACT_CONFIG_CDN_SUBDOMAIN environment variable'); - } else { - logger.error('s3 file storage is disabled and no CDN subdomain was set. Set cdn.subdomain in your config.json'); - } - - process.exit(0); - } - - if (disabledFeatures.redis) { - logger.warn('Both s3 and Redis are disabled. Large CDN files will use the in-memory cache, which may result in high memory use. Please enable s3 if you\'re running a production server.'); - } - - logger.warn(`s3 file storage disabled. Using disk-based file storage. Please ensure cdn.base_url config or PN_ACT_CONFIG_CDN_BASE env variable is set to point to this server with the subdomain being ${config.cdn.subdomain}`); - } - - module.exports.config = config; -} - -module.exports = { - configure, - config, - disabledFeatures -}; \ No newline at end of file diff --git a/src/config-manager.ts b/src/config-manager.ts new file mode 100644 index 0000000..dc3080d --- /dev/null +++ b/src/config-manager.ts @@ -0,0 +1,273 @@ +import fs from 'fs-extra'; +import mongoose from 'mongoose'; +import dotenv from 'dotenv'; +import isValidHostname from 'is-valid-hostname'; +import { LOG_INFO, LOG_WARN, LOG_ERROR, formatHostnames } from '@/logger'; +import { type Config, domainServices, optionalDomainServices } from '@/types/common/config'; + +dotenv.config(); + +export const disabledFeatures = { + redis: false, + email: false, + captcha: false, + s3: false, + datastore: false +}; + +const hexadecimalStringRegex = /^[0-9a-f]+$/i; + +LOG_INFO('Loading config'); + +let mongooseConnectOptions: mongoose.ConnectOptions = {}; + +if (process.env.PN_ACT_CONFIG_MONGOOSE_CONNECT_OPTIONS_PATH) { + mongooseConnectOptions = fs.readJSONSync(process.env.PN_ACT_CONFIG_MONGOOSE_CONNECT_OPTIONS_PATH); +} + +if (process.env.PN_ACT_CONFIG_EMAIL_SECURE) { + if (process.env.PN_ACT_CONFIG_EMAIL_SECURE !== 'true' && process.env.PN_ACT_CONFIG_EMAIL_SECURE !== 'false') { + LOG_ERROR(`PN_ACT_CONFIG_EMAIL_SECURE must be either true or false, got ${process.env.PN_ACT_CONFIG_EMAIL_SECURE}`); + process.exit(0); + } +} + +export const config: Config = { + http: { + port: Number(process.env.PN_ACT_CONFIG_HTTP_PORT || '') + }, + mongoose: { + connection_string: process.env.PN_ACT_CONFIG_MONGO_CONNECTION_STRING || '', + options: mongooseConnectOptions + }, + redis: { + client: { + url: process.env.PN_ACT_CONFIG_REDIS_URL || '' + } + }, + email: { + ses: { + region: process.env.PN_ACT_CONFIG_EMAIL_SES_REGION || '', + key: process.env.PN_ACT_CONFIG_EMAIL_SES_ACCESS_KEY || '', + secret: process.env.PN_ACT_CONFIG_EMAIL_SES_SECRET_KEY || '' + }, + from: process.env.PN_ACT_CONFIG_EMAIL_FROM || '' + }, + s3: { + bucket: process.env.PN_ACT_CONFIG_S3_BUCKET || '', + endpoint: process.env.PN_ACT_CONFIG_S3_ENDPOINT || '', + key: process.env.PN_ACT_CONFIG_S3_ACCESS_KEY || '', + secret: process.env.PN_ACT_CONFIG_S3_ACCESS_SECRET || '', + region: process.env.PN_ACT_CONFIG_S3_REGION || '', + forcePathStyle: process.env.PN_ACT_CONFIG_S3_FORCE_PATH_STYLE === 'true' + }, + hcaptcha: { + secret: process.env.PN_ACT_CONFIG_HCAPTCHA_SECRET || '' + }, + cdn: { + subdomain: process.env.PN_ACT_CONFIG_CDN_SUBDOMAIN, + disk_path: process.env.PN_ACT_CONFIG_CDN_DISK_PATH || '', + base_url: process.env.PN_ACT_CONFIG_CDN_BASE_URL || '' + }, + website_base: process.env.PN_ACT_CONFIG_WEBSITE_BASE || '', + aes_key: process.env.PN_ACT_CONFIG_AES_KEY || '', + grpc: { + master_api_keys: { + account: process.env.PN_ACT_CONFIG_GRPC_MASTER_API_KEY_ACCOUNT || '', + api: process.env.PN_ACT_CONFIG_GRPC_MASTER_API_KEY_API || '', + }, + port: Number(process.env.PN_ACT_CONFIG_GRPC_PORT || ''), + }, + server_environment: process.env.PN_ACT_CONFIG_SERVER_ENVIRONMENT || '', + datastore: { + signature_secret: process.env.PN_ACT_CONFIG_DATASTORE_SIGNATURE_SECRET || '' + }, + domains: { + api: (process.env.PN_ACT_CONFIG_DOMAINS_API || 'api.pretendo.cc').split(','), + assets: (process.env.PN_ACT_CONFIG_DOMAINS_ASSETS || 'assets.pretendo.cc').split(','), + cbvc: (process.env.PN_ACT_CONFIG_DOMAINS_CBVC || 'cbvc.cdn.pretendo.cc').split(','), + conntest: (process.env.PN_ACT_CONFIG_DOMAINS_CONNTEST || 'conntest.pretendo.cc').split(','), + datastore: (process.env.PN_ACT_CONFIG_DOMAINS_DATASTORE || 'datastore.pretendo.cc').split(','), + local_cdn: (process.env.PN_ACT_CONFIG_DOMAINS_LOCAL_CDN || '').split(','), + nasc: (process.env.PN_ACT_CONFIG_DOMAINS_NASC || 'nasc.pretendo.cc').split(','), + nnas: (process.env.PN_ACT_CONFIG_DOMAINS_NNAS || 'c.account.pretendo.cc,account.pretendo.cc').split(','), + } +}; + +if (process.env.PN_ACT_CONFIG_STRIPE_SECRET_KEY) { + config.stripe = { + secret_key: process.env.PN_ACT_CONFIG_STRIPE_SECRET_KEY + }; +} + +// * Add the old config option for backwards compatibility +if (config.cdn.subdomain) { + config.domains.local_cdn.push(config.cdn.subdomain); +} + +let configValid = true; + +LOG_INFO('Config loaded, checking integrity'); + +for (const service of domainServices) { + const validDomains: string[] = []; + const invalidDomains: string[] = []; + + const uniqueDomains = [...new Set(config.domains[service])]; + + for (const domain of uniqueDomains) { + isValidHostname(domain) ? validDomains.push(domain) : invalidDomains.push(domain); + } + + if (validDomains.length === 0 && !optionalDomainServices.includes(service)) { + LOG_ERROR(`No valid domains found for ${service}. Set the PN_ACT_CONFIG_DOMAINS_${service.toUpperCase()} environment variable to a valid domain`); + configValid = false; + } + + if (invalidDomains.length) { + LOG_WARN(`Invalid domain(s) skipped for ${service}: ${formatHostnames(invalidDomains)}`); + } + + config.domains[service] = validDomains; +} + +if (!config.http.port) { + LOG_ERROR('Failed to find HTTP port. Set the PN_ACT_CONFIG_HTTP_PORT environment variable'); + configValid = false; +} + +if (!config.mongoose.connection_string) { + LOG_ERROR('Failed to find MongoDB connection string. Set the PN_ACT_CONFIG_MONGO_CONNECTION_STRING environment variable'); + configValid = false; +} + +if (!config.cdn.base_url) { + LOG_ERROR('Failed to find asset CDN base URL. Set the PN_ACT_CONFIG_CDN_BASE_URL environment variable'); + configValid = false; +} + +if (!config.redis.client.url) { + LOG_WARN('Failed to find Redis connection url. Disabling feature and using in-memory cache. To enable feature set the PN_ACT_CONFIG_REDIS_URL environment variable'); + disabledFeatures.redis = true; +} + +if (!config.email.ses.region) { + LOG_WARN('Failed to find AWS SES region. Disabling feature. To enable feature set the PN_ACT_CONFIG_EMAIL_SES_REGION environment variable'); + disabledFeatures.email = true; +} + +if (!config.email.ses.key) { + LOG_WARN('Failed to find AWS SES access key. Disabling feature. To enable feature set the PN_ACT_CONFIG_EMAIL_SES_ACCESS_KEY environment variable'); + disabledFeatures.email = true; +} + +if (!config.email.ses.secret) { + LOG_WARN('Failed to find AWS SES secret key. Disabling feature. To enable feature set the PN_ACT_CONFIG_EMAIL_SES_SECRET_KEY environment variable'); + disabledFeatures.email = true; +} + +if (!config.email.from) { + LOG_WARN('Failed to find email from config. Disabling feature. To enable feature set the PN_ACT_CONFIG_EMAIL_FROM environment variable'); + disabledFeatures.email = true; +} + +if (!disabledFeatures.email) { + if (!config.website_base) { + LOG_ERROR('Email sending is enabled and no website base was configured. Set the PN_ACT_CONFIG_WEBSITE_BASE environment variable'); + configValid = false; + } +} + +if (!config.hcaptcha.secret) { + LOG_WARN('Failed to find captcha secret config. Disabling feature. To enable feature set the PN_ACT_CONFIG_HCAPTCHA_SECRET environment variable'); + disabledFeatures.captcha = true; +} + +if (!config.s3.bucket) { + LOG_WARN('Failed to find S3 bucket config. Disabling feature. To enable feature set the PN_ACT_CONFIG_S3_BUCKET environment variable'); + disabledFeatures.s3 = true; +} + +if (!config.s3.endpoint) { + LOG_WARN('Failed to find S3 endpoint config. Disabling feature. To enable feature set the PN_ACT_CONFIG_S3_ENDPOINT environment variable'); + disabledFeatures.s3 = true; +} + +if (!config.s3.key) { + LOG_WARN('Failed to find S3 access key config. Disabling feature. To enable feature set the PN_ACT_CONFIG_S3_ACCESS_KEY environment variable'); + disabledFeatures.s3 = true; +} + +if (!config.s3.secret) { + LOG_WARN('Failed to find S3 secret key config. Disabling feature. To enable feature set the PN_ACT_CONFIG_S3_ACCESS_SECRET environment variable'); + disabledFeatures.s3 = true; +} + +if (!config.s3.region) { + LOG_WARN('Failed to find S3 region config. Disabling feature. To enable feature set the PN_ACT_CONFIG_S3_REGION environment variable'); + disabledFeatures.s3 = true; +} + +if (!config.server_environment) { + LOG_WARN('Failed to find server environment. To change the environment, set the PN_ACT_CONFIG_SERVER_ENVIRONMENT environment variable. Defaulting to prod'); + config.server_environment = 'prod'; +} + +if (disabledFeatures.s3) { + if (config.domains.local_cdn.length === 0) { + LOG_ERROR('S3 file storage is disabled and no CDN domain was set. Set the PN_ACT_CONFIG_DOMAINS_LOCAL_CDN environment variable'); + configValid = false; + } + + if (!config.cdn.disk_path) { + LOG_ERROR('S3 file storage is disabled and no CDN disk path was set. Set the PN_ACT_CONFIG_CDN_DISK_PATH environment variable'); + configValid = false; + } + + if (configValid) { + LOG_WARN(`S3 file storage disabled. Using disk-based file storage. Please ensure cdn.base_url config or PN_ACT_CONFIG_CDN_BASE env variable is set to point to this server with the domain being one of ${formatHostnames(config.domains.local_cdn)}`); + + if (disabledFeatures.redis) { + LOG_WARN('Both S3 and Redis are disabled. Large CDN files will use the in-memory cache, which may result in high memory use. Please enable S3 if you\'re running a production server.'); + } + } +} + +if (!config.aes_key) { + LOG_ERROR('Token AES key is not set. Set the PN_ACT_CONFIG_AES_KEY environment variable to your AES-256-CBC key'); + configValid = false; +} + +if (!config.grpc.master_api_keys.account) { + LOG_ERROR('Master gRPC API key for the account service is not set. Set the PN_ACT_CONFIG_GRPC_MASTER_API_KEY_ACCOUNT environment variable'); + configValid = false; +} + +if (!config.grpc.master_api_keys.api) { + LOG_ERROR('Master gRPC API key for the api service is not set. Set the PN_ACT_CONFIG_GRPC_MASTER_API_KEY_API environment variable'); + configValid = false; +} + +if (!config.grpc.port) { + LOG_ERROR('Failed to find gRPC port. Set the PN_ACT_CONFIG_GRPC_PORT environment variable'); + configValid = false; +} + +if (!config.stripe?.secret_key) { + LOG_WARN('Failed to find Stripe api key! If a PNID is deleted with an active subscription, the subscription will *NOT* be canceled! Set the PN_ACT_CONFIG_STRIPE_SECRET_KEY environment variable to enable'); +} + +if (!config.datastore.signature_secret) { + LOG_WARN('Datastore signature secret key is not set. Disabling feature. To enable feature set the PN_ACT_CONFIG_DATASTORE_SIGNATURE_SECRET environment variable'); + disabledFeatures.datastore = true; +} else { + if (config.datastore.signature_secret.length !== 32 || !hexadecimalStringRegex.test(config.datastore.signature_secret)) { + LOG_ERROR('Datastore signature secret key must be a 32-character hexadecimal string.'); + configValid = false; + } +} + +if (!configValid) { + LOG_ERROR('Config is invalid. Exiting'); + process.exit(0); +} \ No newline at end of file diff --git a/src/database.js b/src/database.js deleted file mode 100644 index bfce6ef..0000000 --- a/src/database.js +++ /dev/null @@ -1,274 +0,0 @@ -const mongoose = require('mongoose'); -const bcrypt = require('bcrypt'); -const joi = require('joi'); -const util = require('./util'); -const { PNID } = require('./models/pnid'); -const { Server } = require('./models/server'); -const logger = require('../logger'); -const { config } = require('./config-manager'); -const { connection_string, options } = config.mongoose; - -// TODO: Extend this later with more settings -const discordConnectionSchema = joi.object({ - id: joi.string() -}); - -let connection; - -async function connect() { - await mongoose.connect(connection_string, options); - - connection = mongoose.connection; - connection.on('error', console.error.bind(console, 'connection error:')); - - module.exports.connection = connection; -} - -function verifyConnected() { - if (!connection) { - throw new Error('Cannot make database requets without being connected'); - } -} - -async function getUserByUsername(username) { - verifyConnected(); - - if (typeof username !== 'string') { - return null; - } - - const user = await PNID.findOne({ - usernameLower: username.toLowerCase() - }); - - return user; -} - -async function getUserByPID(pid) { - verifyConnected(); - - const user = await PNID.findOne({ - pid - }); - - return user; -} - -async function getUserByEmailAddress(email) { - verifyConnected(); - - const user = await PNID.findOne({ - 'email.address': new RegExp(email, 'i') // * Ignore case - }); - - return user; -} - -async function doesUserExist(username) { - verifyConnected(); - - return !!await getUserByUsername(username); -} - -async function getUserBasic(token) { - verifyConnected(); - - // Wii U sends Basic auth as `username password`, where the password may not have spaces - // This is not to spec, but that is the consoles fault not ours - const [username, password] = Buffer.from(token, 'base64').toString().split(' '); - const user = await getUserByUsername(username); - - if (!user) { - return null; - } - - const hashedPassword = util.nintendoPasswordHash(password, user.pid); - - if (!bcrypt.compareSync(hashedPassword, user.password)) { - return null; - } - - return user; -} - -async function getUserBearer(token) { - verifyConnected(); - - try { - const decryptedToken = await util.decryptToken(Buffer.from(token, 'base64')); - const unpackedToken = util.unpackToken(decryptedToken); - - const user = await getUserByPID(unpackedToken.pid); - - if (user) { - const expireTime = Math.floor((Number(unpackedToken.expire_time) / 1000)); - - if (Math.floor(Date.now() / 1000) > expireTime) { - return null; - } - } - - return user; - } catch (error) { - // TODO: Handle error - logger.error(error); - return null; - } -} - -async function getUserProfileJSONByPID(pid) { - verifyConnected(); - - const user = await getUserByPID(pid); - const device = user.get('devices')[0]; // Just grab the first device - let device_attributes; - - if (device) { - device_attributes = device.get('device_attributes').map(({name, value, created_date}) => { - const deviceAttributeDocument = { - name, - value - }; - - if (created_date) { - deviceAttributeDocument.created_date = created_date; - } - - return { - device_attribute: deviceAttributeDocument - }; - }); - } - - const userObject = { - //accounts: {}, We need to figure this out, no idea what these values mean or what they do - active_flag: user.get('flags.active') ? 'Y' : 'N', - birth_date: user.get('birthdate'), - country: user.get('country'), - create_date: user.get('creation_date'), - device_attributes: device_attributes, - gender: user.get('gender'), - language: user.get('language'), - updated: user.get('updated'), - marketing_flag: user.get('flags.marketing') ? 'Y' : 'N', - off_device_flag: user.get('flags.off_device') ? 'Y' : 'N', - pid: user.get('pid'), - email: { - address: user.get('email.address'), - id: user.get('email.id'), - parent: user.get('email.parent') ? 'Y' : 'N', - primary: user.get('email.primary') ? 'Y' : 'N', - reachable: user.get('email.reachable') ? 'Y' : 'N', - type: 'DEFAULT', - updated_by: 'USER', // Can also be INTERNAL WS, don't know the difference - validated: user.get('email.validated') ? 'Y' : 'N' - }, - mii: { - status: 'COMPLETED', - data: user.get('mii.data').replace(/(\r\n|\n|\r)/gm, ''), - id: user.get('mii.id'), - mii_hash: user.get('mii.hash'), - mii_images: { - mii_image: { - // Images MUST be loaded over HTTPS or console ignores them - // Bunny CDN is the only CDN which seems to support TLS 1.0/1.1 (required) - cached_url: `${config.cdn.base_url}/mii/${user.pid}/standard.tga`, - id: user.get('mii.image_id'), - url: `${config.cdn.base_url}/mii/${user.pid}/standard.tga`, - type: 'standard' - } - }, - name: user.get('mii.name'), - primary: user.get('mii.primary') ? 'Y' : 'N', - }, - region: user.get('region'), - tz_name: user.get('timezone.name'), - user_id: user.get('username'), - utc_offset: user.get('timezone.offset') - }; - - if (user.get('email.validated')) { - userObject.email.validated_date = user.get('email.validated_date'); - } - - return userObject; -} - -function getServer(gameServerId, accessMode) { - return Server.findOne({ - game_server_id: gameServerId, - access_mode: accessMode, - }); -} - -function getServerByTitleId(titleId, accessMode) { - return Server.findOne({ - title_ids: titleId, - access_mode: accessMode, - }); -} - -async function addUserConnection(pnid, data, type) { - if (type === 'discord') { - return await addUserConnectionDiscord(pnid, data); - } -} - -async function addUserConnectionDiscord(pnid, data) { - const valid = discordConnectionSchema.validate(data); - - if (valid.error) { - return { - app: 'api', - status: 400, - error: 'Invalid or missing connection data' - }; - } - - await PNID.updateOne({ pid: pnid.get('pid') }, { - $set: { - 'connections.discord.id': data.id - } - }); - - return { - app: 'api', - status: 200 - }; -} - -async function removeUserConnection(pnid, type) { - // Add more connections later? - if (type === 'discord') { - return await removeUserConnectionDiscord(pnid); - } -} - -async function removeUserConnectionDiscord(pnid) { - await PNID.updateOne({ pid: pnid.get('pid') }, { - $set: { - 'connections.discord.id': '' - } - }); - - return { - app: 'api', - status: 200 - }; -} - -module.exports = { - connect, - connection, - getUserByUsername, - getUserByPID, - getUserByEmailAddress, - doesUserExist, - getUserBasic, - getUserBearer, - getUserProfileJSONByPID, - getServer, - getServerByTitleId, - addUserConnection, - removeUserConnection, -}; \ No newline at end of file diff --git a/src/database.ts b/src/database.ts new file mode 100644 index 0000000..72c1f7e --- /dev/null +++ b/src/database.ts @@ -0,0 +1,309 @@ +import mongoose from 'mongoose'; +import bcrypt from 'bcrypt'; +import joi from 'joi'; +import { nintendoPasswordHash, decryptToken, unpackToken } from '@/util'; +import { PNID } from '@/models/pnid'; +import { Server } from '@/models/server'; +import { LOG_ERROR } from '@/logger'; +import { config } from '@/config-manager'; +import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; +import { IDeviceAttribute } from '@/types/mongoose/device-attribute'; +import { HydratedServerDocument } from '@/types/mongoose/server'; +import { PNIDProfile } from '@/types/services/nnas/pnid-profile'; +import { ConnectionData } from '@/types/services/api/connection-data'; +import { ConnectionResponse } from '@/types/services/api/connection-response'; +import { DiscordConnectionData } from '@/types/services/api/discord-connection-data'; + +const connection_string = config.mongoose.connection_string; +const options = config.mongoose.options; + +// TODO - Extend this later with more settings +const discordConnectionSchema = joi.object({ + id: joi.string() +}); + +const accessModeOrder: Record = { + prod: ['prod'], + test: ['test', 'prod'], + dev: ['dev', 'test', 'prod'] +}; + +let _connection: mongoose.Connection; + +export async function connect(): Promise { + await mongoose.connect(connection_string, options); + + _connection = mongoose.connection; + _connection.on('error', console.error.bind(console, 'connection error:')); +} + +export function connection(): mongoose.Connection { + return _connection; +} + +export function verifyConnected(): void { + if (!connection()) { + throw new Error('Cannot make database requets without being connected'); + } +} + +export async function getPNIDByUsername(username: string): Promise { + verifyConnected(); + + return await PNID.findOne({ + usernameLower: username.toLowerCase() + }); +} + +export async function getPNIDByPID(pid: number): Promise { + verifyConnected(); + + return await PNID.findOne({ + pid + }); +} + +export async function getPNIDByEmailAddress(email: string): Promise { + verifyConnected(); + + // TODO - Update documents to store email normalized + return await PNID.findOne({ + 'email.address': email + }); +} + +export async function doesPNIDExist(username: string): Promise { + verifyConnected(); + + return !!await getPNIDByUsername(username); +} + +export async function getPNIDByBasicAuth(token: string): Promise { + verifyConnected(); + + // * Wii U sends Basic auth as `username password`, where the password may not have spaces + // * This is not to spec, but that is the consoles fault not ours + const decoded = Buffer.from(token, 'base64').toString(); + const parts = decoded.split(' '); + + const username = parts[0]; + const password = parts[1]; + + const pnid = await getPNIDByUsername(username); + + if (!pnid) { + return null; + } + + const hashedPassword = nintendoPasswordHash(password, pnid.pid); + + if (!bcrypt.compareSync(hashedPassword, pnid.password)) { + return null; + } + + return pnid; +} + +export async function getPNIDByTokenAuth(token: string): Promise { + verifyConnected(); + + try { + const decryptedToken = decryptToken(Buffer.from(token, 'hex')); + const unpackedToken = unpackToken(decryptedToken); + const pnid = await getPNIDByPID(unpackedToken.pid); + + if (pnid) { + const expireTime = Math.floor((Number(unpackedToken.expire_time) / 1000)); + + if (Math.floor(Date.now() / 1000) > expireTime) { + return null; + } + } + + return pnid; + } catch (error: any) { + // TODO - Handle error + LOG_ERROR(error); + return null; + } +} + +export async function getPNIDProfileJSONByPID(pid: number): Promise { + verifyConnected(); + + const pnid = await getPNIDByPID(pid); + + if (!pnid) { + return null; + } + + const device = pnid.devices[0]; // * Just grab the first device + let device_attributes: { + device_attribute: { + name: string; + value: string; + created_date: string; + }; + }[] = []; + + if (device) { + device_attributes = device.device_attributes.map((attribute: IDeviceAttribute) => { + const name = attribute.name; + const value = attribute.value; + const created_date = attribute.created_date; + + return { + device_attribute: { + name, + value, + created_date: created_date ? created_date : '' + } + }; + }); + } + + return { + // *accounts: {}, // * We need to figure this out, no idea what these values mean or what they do + active_flag: pnid.flags.active ? 'Y' : 'N', + birth_date: pnid.birthdate, + country: pnid.country, + create_date: pnid.creation_date, + device_attributes: device_attributes, + gender: pnid.gender, + language: pnid.language, + updated: pnid.updated, + marketing_flag: pnid.flags.marketing ? 'Y' : 'N', + off_device_flag: pnid.flags.off_device ? 'Y' : 'N', + pid: pnid.pid, + email: { + address: pnid.email.address, + id: pnid.email.id, + parent: pnid.email.parent ? 'Y' : 'N', + primary: pnid.email.primary ? 'Y' : 'N', + reachable: pnid.email.reachable ? 'Y' : 'N', + type: 'DEFAULT', + updated_by: 'USER', // * Can also be INTERNAL WS, don't know the difference + validated: pnid.email.validated ? 'Y' : 'N', + validated_date: pnid.email.validated ? pnid.email.validated_date : '' + }, + mii: { + status: 'COMPLETED', + data: pnid.mii.data.replace(/(\r\n|\n|\r)/gm, ''), + id: pnid.mii.id, + mii_hash: pnid.mii.hash, + mii_images: { + mii_image: { + // * Images MUST be loaded over HTTPS or console ignores them + // * Bunny CDN is the only CDN which seems to support TLS 1.0/1.1 (required) + cached_url: `${config.cdn.base_url}/mii/${pnid.pid}/standard.tga`, + id: pnid.mii.image_id, + url: `${config.cdn.base_url}/mii/${pnid.pid}/standard.tga`, + type: 'standard' + } + }, + name: pnid.mii.name, + primary: pnid.mii.primary ? 'Y' : 'N', + }, + region: pnid.region, + tz_name: pnid.timezone.name, + user_id: pnid.username, + utc_offset: pnid.timezone.offset + }; +} + +export async function getServerByGameServerID(gameServerID: string, accessMode: string): Promise { + const searchModes = accessModeOrder[accessMode] ?? accessModeOrder.prod; // Default to prod if invalid mode + + const servers = await Server.find({ + game_server_id: gameServerID, + access_mode: { $in: searchModes } + }); + + for (const mode of searchModes) { + const server = servers.find(s => s.access_mode === mode); + if (server) return server; + } + + return null; +} + +export async function getServerByTitleID(titleID: string, accessMode: string): Promise { + const searchModes = accessModeOrder[accessMode] ?? accessModeOrder.prod; + + const servers = await Server.find({ + title_ids: titleID, + access_mode: { $in: searchModes } + }); + + for (const mode of searchModes) { + const server = servers.find(s => s.access_mode === mode); + if (server) return server; + } + + return null; +} + +export async function getServerByClientID(clientID: string, accessMode: string): Promise { + const searchModes = accessModeOrder[accessMode] ?? accessModeOrder.prod; + + const servers = await Server.find({ + client_id: clientID, + access_mode: { $in: searchModes } + }); + + for (const mode of searchModes) { + const server = servers.find(s => s.access_mode === mode); + if (server) return server; + } + + return null; +} + +export async function addPNIDConnection(pnid: HydratedPNIDDocument, data: ConnectionData, type: string): Promise { + if (type === 'discord') { + return await addPNIDConnectionDiscord(pnid, data); + } +} + +export async function addPNIDConnectionDiscord(pnid: HydratedPNIDDocument, data: DiscordConnectionData): Promise { + const valid = discordConnectionSchema.validate(data); + + if (valid.error) { + return { + app: 'api', + status: 400, + error: 'Invalid or missing connection data' + }; + } + + await PNID.updateOne({ pid: pnid.pid }, { + $set: { + 'connections.discord.id': data.id + } + }); + + return { + app: 'api', + status: 200 + }; +} + +export async function removePNIDConnection(pnid: HydratedPNIDDocument, type: string): Promise { + // * Add more connections later? + if (type === 'discord') { + return await removePNIDConnectionDiscord(pnid); + } +} + +export async function removePNIDConnectionDiscord(pnid: HydratedPNIDDocument): Promise { + await PNID.updateOne({ pid: pnid.pid }, { + $set: { + 'connections.discord.id': '' + } + }); + + return { + app: 'api', + status: 200 + }; +} \ No newline at end of file diff --git a/logger.js b/src/logger.ts similarity index 67% rename from logger.js rename to src/logger.ts index 07215de..df73beb 100644 --- a/logger.js +++ b/src/logger.ts @@ -1,7 +1,9 @@ -const fs = require('fs-extra'); -require('colors'); +import fs from 'fs-extra'; +import colors from 'colors'; -const root = __dirname; +colors.enable(); + +const root = process.env.PN_ACT_LOGGER_PATH ? process.env.PN_ACT_LOGGER_PATH : `${__dirname}/..`; fs.ensureDirSync(`${root}/logs`); const streams = { @@ -10,9 +12,9 @@ const streams = { error: fs.createWriteStream(`${root}/logs/error.log`), warn: fs.createWriteStream(`${root}/logs/warn.log`), info: fs.createWriteStream(`${root}/logs/info.log`) -}; +} as const; -function success(input) { +export function LOG_SUCCESS(input: string): void { const time = new Date(); input = `[${time.getHours()}:${time.getMinutes()}:${time.getSeconds()}] [SUCCESS]: ${input}`; streams.success.write(`${input}\n`); @@ -20,7 +22,7 @@ function success(input) { console.log(`${input}`.green.bold); } -function error(input) { +export function LOG_ERROR(input: string): void { const time = new Date(); input = `[${time.getHours()}:${time.getMinutes()}:${time.getSeconds()}] [ERROR]: ${input}`; streams.error.write(`${input}\n`); @@ -28,7 +30,7 @@ function error(input) { console.log(`${input}`.red.bold); } -function warn(input) { +export function LOG_WARN(input: string): void { const time = new Date(); input = `[${time.getHours()}:${time.getMinutes()}:${time.getSeconds()}] [WARN]: ${input}`; streams.warn.write(`${input}\n`); @@ -36,7 +38,7 @@ function warn(input) { console.log(`${input}`.yellow.bold); } -function info(input) { +export function LOG_INFO(input: string): void { const time = new Date(); input = `[${time.getHours()}:${time.getMinutes()}:${time.getSeconds()}] [INFO]: ${input}`; streams.info.write(`${input}\n`); @@ -44,9 +46,6 @@ function info(input) { console.log(`${input}`.cyan.bold); } -module.exports = { - success, - error, - warn, - info -}; \ No newline at end of file +export function formatHostnames(hostnames: string[]): string { + return hostnames.map(d => `'${d}'`).join(', '); +} \ No newline at end of file diff --git a/src/mailer.js b/src/mailer.js deleted file mode 100644 index 7292f6e..0000000 --- a/src/mailer.js +++ /dev/null @@ -1,65 +0,0 @@ -const nodemailer = require('nodemailer'); -const { config, disabledFeatures } = require('./config-manager'); -const path = require('path'); -const fs = require("fs"); -const genericEmailTemplate = fs.readFileSync(path.join(__dirname, './assets/emails/genericTemplate.html'), 'utf8'); -const confirmationEmailTemplate = fs.readFileSync(path.join(__dirname, './assets/emails/confirmationTemplate.html'), 'utf8'); - -let transporter; - -if (!disabledFeatures.email) { - transporter = nodemailer.createTransport(config.email); -} - -/** - @param {Object} options - @param {String} options.to The address of the recipient - @param {String} options.subject The subject of the email - - @param {String} options.username The username of the user (shown in the greeting) - @param {String} options.preview The preview text of the email (shown in the inbox by the email client) - @param {String} options.text The text version of the email - - @param {String} options.paragraph The main content of the email - - @param {Object} options.confirmation Whether or not the email is a confirmation email - @param {String} options.confirmation.href The link to the confirmation page - @param {String} options.confirmation.code The confirmation code - - @param {Object} options.link An object containing the link to be shown in the email - @param {String} options.link.href The URL of the link - @param {String} options.link.text The text of the link - -*/ -async function sendMail(options) { - if (!disabledFeatures.email) { - const { to, subject, username, paragraph, preview, text, link, confirmation } = options; - - let html = confirmation ? confirmationEmailTemplate : genericEmailTemplate; - - html = html.replace(/{{username}}/g, username); - html = html.replace(/{{paragraph}}/g, paragraph); - html = html.replace(/{{preview}}/g, (preview || "")); - html = html.replace(/{{confirmation-href}}/g, (confirmation?.href || "")); - html = html.replace(/{{confirmation-code}}/g, (confirmation?.code || "")); - - if (link) { - const { href, text } = link; - - const button = ` ${text}` - html = html.replace(//g, button); - } - - await transporter.sendMail({ - from: config.email.from, - to, - subject, - text, - html - }); - } -} - -module.exports = { - sendMail -}; diff --git a/src/mailer.ts b/src/mailer.ts new file mode 100644 index 0000000..10efd10 --- /dev/null +++ b/src/mailer.ts @@ -0,0 +1,58 @@ +import path from 'node:path'; +import fs from 'node:fs'; +import nodemailer from 'nodemailer'; +import * as aws from '@aws-sdk/client-ses'; +import { config, disabledFeatures } from '@/config-manager'; +import { MailerOptions } from '@/types/common/mailer-options'; + +const genericEmailTemplate = fs.readFileSync(path.join(__dirname, './assets/emails/genericTemplate.html'), 'utf8'); +const confirmationEmailTemplate = fs.readFileSync(path.join(__dirname, './assets/emails/confirmationTemplate.html'), 'utf8'); + +let transporter: nodemailer.Transporter; + +if (!disabledFeatures.email) { + const ses = new aws.SES({ + apiVersion: '2010-12-01', + region: config.email.ses.region, + credentials: { + accessKeyId: config.email.ses.key, + secretAccessKey: config.email.ses.secret + } + }); + + transporter = transporter = nodemailer.createTransport({ + SES: { + ses, + aws + } + }); +} + +export async function sendMail(options: MailerOptions): Promise { + if (!disabledFeatures.email) { + const { to, subject, username, paragraph, preview, text, link, confirmation } = options; + + let html = confirmation ? confirmationEmailTemplate : genericEmailTemplate; + + html = html.replace(/{{username}}/g, username); + html = html.replace(/{{paragraph}}/g, paragraph || ''); + html = html.replace(/{{preview}}/g, preview || ''); + html = html.replace(/{{confirmation-href}}/g, confirmation?.href || ''); + html = html.replace(/{{confirmation-code}}/g, confirmation?.code || ''); + + if (link) { + const { href, text } = link; + + const button = ` ${text}`; + html = html.replace(//g, button); + } + + await transporter.sendMail({ + from: config.email.from, + to, + subject, + text, + html + }); + } +} diff --git a/src/middleware/api.js b/src/middleware/api.js deleted file mode 100644 index d6489d1..0000000 --- a/src/middleware/api.js +++ /dev/null @@ -1,19 +0,0 @@ -const xmlbuilder = require('xmlbuilder'); -const database = require('../database'); - -async function APIMiddleware(request, response, next) { - const { headers } = request; - - if (!headers.authorization || !(headers.authorization.startsWith('Bearer'))) { - return next(); - } - - const token = headers.authorization.split(' ')[1]; - const user = await database.getUserBearer(token); - - request.pnid = user; - - return next(); -} - -module.exports = APIMiddleware; \ No newline at end of file diff --git a/src/middleware/api.ts b/src/middleware/api.ts new file mode 100644 index 0000000..8a5f915 --- /dev/null +++ b/src/middleware/api.ts @@ -0,0 +1,24 @@ +import express from 'express'; +import { getValueFromHeaders } from '@/util'; +import { getPNIDByTokenAuth } from '@/database'; + +async function APIMiddleware(request: express.Request, _response: express.Response, next: express.NextFunction): Promise { + const authHeader = getValueFromHeaders(request.headers, 'authorization'); + + if (!authHeader || !(authHeader.startsWith('Bearer'))) { + return next(); + } + + try { + const token = authHeader.split(' ')[1]; + const pnid = await getPNIDByTokenAuth(token); + + request.pnid = pnid; + } catch (error) { + // TODO - Log error + } + + return next(); +} + +export default APIMiddleware; \ No newline at end of file diff --git a/src/middleware/cemu.js b/src/middleware/cemu.js deleted file mode 100644 index c6e8441..0000000 --- a/src/middleware/cemu.js +++ /dev/null @@ -1,9 +0,0 @@ -async function CemuMiddleware(request, response, next) { - const subdomain = request.subdomains.reverse().join('.'); - - request.isCemu = subdomain === 'c.account'; - - return next(); -} - -module.exports = CemuMiddleware; \ No newline at end of file diff --git a/src/middleware/cemu.ts b/src/middleware/cemu.ts new file mode 100644 index 0000000..6edca3b --- /dev/null +++ b/src/middleware/cemu.ts @@ -0,0 +1,11 @@ +import express from 'express'; + +function CemuMiddleware(request: express.Request, _response: express.Response, next: express.NextFunction): void { + const subdomain = request.subdomains.reverse().join('.'); + + request.isCemu = subdomain === 'c.account'; + + return next(); +} + +export default CemuMiddleware; \ No newline at end of file diff --git a/src/middleware/client-header.js b/src/middleware/client-header.js deleted file mode 100644 index 1999223..0000000 --- a/src/middleware/client-header.js +++ /dev/null @@ -1,38 +0,0 @@ -const xmlbuilder = require('xmlbuilder'); - -const VALID_CLIENT_ID_SECRET_PAIRS = { - // 'Key' is the client ID, 'Value' is the client secret - 'a2efa818a34fa16b8afbc8a74eba3eda': 'c91cdb5658bd4954ade78533a339cf9a', // Possibly WiiU exclusive? - 'daf6227853bcbdce3d75baee8332b': '3eff548eac636e2bf45bb7b375e7b6b0', // Possibly 3DS exclusive? - 'ea25c66c26b403376b4c5ed94ab9cdea': 'd137be62cb6a2b831cad8c013b92fb55', // Possibly 3DS exclusive? -}; - - -function nintendoClientHeaderCheck(request, response, next) { - response.set('Content-Type', 'text/xml'); - response.set('Server', 'Nintendo 3DS (http)'); - response.set('X-Nintendo-Date', new Date().getTime()); - - const {headers} = request; - - if ( - !headers['x-nintendo-client-id'] || - !headers['x-nintendo-client-secret'] || - !VALID_CLIENT_ID_SECRET_PAIRS[headers['x-nintendo-client-id']] || - headers['x-nintendo-client-secret'] !== VALID_CLIENT_ID_SECRET_PAIRS[headers['x-nintendo-client-id']] - ) { - return response.send(xmlbuilder.create({ - errors: { - error: { - cause: 'client_id', - code: '0004', - message: 'API application invalid or incorrect application credentials' - } - } - }).end()); - } - - return next(); -} - -module.exports = nintendoClientHeaderCheck; \ No newline at end of file diff --git a/src/middleware/client-header.ts b/src/middleware/client-header.ts new file mode 100644 index 0000000..483f8dc --- /dev/null +++ b/src/middleware/client-header.ts @@ -0,0 +1,42 @@ +import express from 'express'; +import xmlbuilder from 'xmlbuilder'; +import { getValueFromHeaders } from '@/util'; + +const VALID_CLIENT_ID_SECRET_PAIRS: Record = { + // * 'Key' is the client ID, 'Value' is the client secret + 'a2efa818a34fa16b8afbc8a74eba3eda': 'c91cdb5658bd4954ade78533a339cf9a', // * Possibly WiiU exclusive? + 'daf6227853bcbdce3d75baee8332b': '3eff548eac636e2bf45bb7b375e7b6b0', // * Possibly 3DS exclusive? + 'ea25c66c26b403376b4c5ed94ab9cdea': 'd137be62cb6a2b831cad8c013b92fb55', // * Possibly 3DS exclusive? +}; + +function nintendoClientHeaderCheck(request: express.Request, response: express.Response, next: express.NextFunction): void { + response.set('Content-Type', 'text/xml'); + response.set('Server', 'Nintendo 3DS (http)'); + response.set('X-Nintendo-Date', new Date().getTime().toString()); + + const clientID = getValueFromHeaders(request.headers, 'x-nintendo-client-id'); + const clientSecret = getValueFromHeaders(request.headers, 'x-nintendo-client-secret'); + + if ( + !clientID || + !clientSecret || + !VALID_CLIENT_ID_SECRET_PAIRS[clientID] || + clientSecret !== VALID_CLIENT_ID_SECRET_PAIRS[clientID] + ) { + response.send(xmlbuilder.create({ + errors: { + error: { + cause: 'client_id', + code: '0004', + message: 'API application invalid or incorrect application credentials' + } + } + }).end()); + + return; + } + + return next(); +} + +export default nintendoClientHeaderCheck; \ No newline at end of file diff --git a/src/middleware/console-status-verification.ts b/src/middleware/console-status-verification.ts new file mode 100644 index 0000000..a26d9b6 --- /dev/null +++ b/src/middleware/console-status-verification.ts @@ -0,0 +1,158 @@ +import crypto from 'node:crypto'; +import express from 'express'; +import xmlbuilder from 'xmlbuilder'; +import { Device } from '@/models/device'; +import { getValueFromHeaders } from '@/util'; + +async function consoleStatusVerificationMiddleware(request: express.Request, response: express.Response, next: express.NextFunction): Promise { + if (!request.certificate || !request.certificate.valid) { + response.status(400).send(xmlbuilder.create({ + error: { + code: '0110', + message: 'Unlinked device' + } + }).end()); + + return; + } + + const deviceIDHeader = getValueFromHeaders(request.headers, 'x-nintendo-device-id'); + + if (!deviceIDHeader) { + response.status(400).send(xmlbuilder.create({ + error: { + code: '0002', + message: 'deviceId format is invalid' + } + }).end()); + + return; + } + + const deviceID = Number(deviceIDHeader); + + if (isNaN(deviceID)) { + response.status(400).send(xmlbuilder.create({ + error: { + code: '0002', + message: 'deviceId format is invalid' + } + }).end()); + + return; + } + + const serialNumber = getValueFromHeaders(request.headers, 'x-nintendo-serial-number'); + + // TODO - Verify serial numbers somehow? + // * This is difficult to do safely because serial numbers are + // * inherently insecure. + // * Information about their structure can be found here: + // * https://www.3dbrew.org/wiki/Serials + // * Given this, anyone can generate a valid serial number which + // * passes these checks, even if the serial number isn't real. + // * The 3DS also futher complicates things, as it never sends + // * the complete serial number. The 3DS omits the check digit, + // * meaning any attempt to verify the serial number of a 3DS + // * family of console will ALWAYS fail. Nintendo likely just + // * has a database of all known serials which they are able to + // * compare against. We are not so lucky + if (!serialNumber) { + response.status(400).send(xmlbuilder.create({ + error: { + code: '0002', + message: 'serialNumber format is invalid' + } + }).end()); + + return; + } + + let device = await Device.findOne({ + serial: serialNumber, + }); + + const certificateHash = crypto.createHash('sha256').update(request.certificate._certificate).digest('base64'); + + if (!device && request.certificate.consoleType === '3ds') { + // * A 3DS console document will ALWAYS be created by NASC before + // * Hitting the NNAS server. NASC stores the serial number at + // * the time the device document was created. Therefore we can + // * know that serial tampering happened on the 3DS if this fails + // * to find a device document. + response.status(400).send(xmlbuilder.create({ + error: { + code: '0002', + message: 'serialNumber format is invalid' + } + }).end()); + + return; + } else if (device && !device.certificate_hash && request.certificate.consoleType === '3ds') { + device.certificate_hash = certificateHash; + + await device.save(); + } + + device = await Device.findOne({ + certificate_hash: certificateHash, + }); + + if (!device) { + // * Device must be a fresh Wii U + device = await Device.create({ + model: 'wup', + device_id: deviceID, + serial: serialNumber, + linked_pids: [], + certificate_hash: certificateHash + }); + } + + if (device.serial !== serialNumber) { + // TODO - Change this to a different error + response.status(400).send(xmlbuilder.create({ + error: { + cause: 'Bad Request', + code: '1600', + message: 'Unable to process request' + } + }).end()); + + return; + } + + const certificateDeviceID = parseInt(request.certificate.certificateName.slice(2).split('-')[0], 16); + + if (deviceID !== certificateDeviceID) { + // TODO - Change this to a different error + response.status(400).send(xmlbuilder.create({ + error: { + cause: 'Bad Request', + code: '1600', + message: 'Unable to process request' + } + }).end()); + + return; + } + + if (device.access_level < 0) { + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + code: '0012', + message: 'Device has been banned by game server' // TODO - This is not the right error message + } + } + }).end()); + + return; + } + + request.device = device; + + return next(); +} + +export default consoleStatusVerificationMiddleware; \ No newline at end of file diff --git a/src/middleware/device-certificate.js b/src/middleware/device-certificate.js deleted file mode 100644 index 7598091..0000000 --- a/src/middleware/device-certificate.js +++ /dev/null @@ -1,16 +0,0 @@ -const NintendoCertificate = require('../nintendo-certificate'); - -async function deviceCertificateMiddleware(request, response, next) { - const { headers } = request; - - if (!headers['x-nintendo-device-cert']) { - return next(); - } - - const certificate = headers['x-nintendo-device-cert']; - request.certificate = new NintendoCertificate(certificate); - - return next(); -} - -module.exports = deviceCertificateMiddleware; \ No newline at end of file diff --git a/src/middleware/device-certificate.ts b/src/middleware/device-certificate.ts new file mode 100644 index 0000000..4080d89 --- /dev/null +++ b/src/middleware/device-certificate.ts @@ -0,0 +1,17 @@ +import express from 'express'; +import NintendoCertificate from '@/nintendo-certificate'; +import { getValueFromHeaders } from '@/util'; + +function deviceCertificateMiddleware(request: express.Request, _response: express.Response, next: express.NextFunction): void { + const certificate = getValueFromHeaders(request.headers, 'x-nintendo-device-cert'); + + if (!certificate) { + return next(); + } + + request.certificate = new NintendoCertificate(certificate); + + return next(); +} + +export default deviceCertificateMiddleware; \ No newline at end of file diff --git a/src/middleware/host-limit.ts b/src/middleware/host-limit.ts new file mode 100644 index 0000000..c23e49e --- /dev/null +++ b/src/middleware/host-limit.ts @@ -0,0 +1,14 @@ +import express from 'express'; + +export function restrictHostnames( + allowedHostnames: string[], + fn: TFn +): (request: express.Request, response: express.Response, next: () => void) => void | TFn { + return (request: express.Request, response: express.Response, next: () => void) => { + if (allowedHostnames.includes(request.hostname)) { + return fn(request, response, next); + } + + return next(); + }; +} \ No newline at end of file diff --git a/src/middleware/nasc.js b/src/middleware/nasc.js deleted file mode 100644 index 4bb91a9..0000000 --- a/src/middleware/nasc.js +++ /dev/null @@ -1,213 +0,0 @@ -const crypto = require('crypto'); -const { Device } = require('../models/device'); -const { NEXAccount } = require('../models/nex-account'); -const util = require('../util'); -const database = require('../database'); -const NintendoCertificate = require('../nintendo-certificate'); - -async function NASCMiddleware(request, response, next) { - const requestParams = request.body; - - if (!requestParams.action || - !requestParams.fcdcert || - !requestParams.csnum || - !requestParams.macadr || - !requestParams.titleid || - !requestParams.servertype - ) { - return response.status(200).send(util.nascError('null')); // This is what Nintendo sends - } - - const action = util.nintendoBase64Decode(requestParams.action).toString(); - const fcdcert = util.nintendoBase64Decode(requestParams.fcdcert); - const serialNumber = util.nintendoBase64Decode(requestParams.csnum).toString(); - const macAddress = util.nintendoBase64Decode(requestParams.macadr).toString(); - const titleID = util.nintendoBase64Decode(requestParams.titleid).toString(); - const environment = util.nintendoBase64Decode(requestParams.servertype).toString(); - - const macAddressHash = crypto.createHash('sha256').update(macAddress).digest('base64'); - const fcdcertHash = crypto.createHash('sha256').update(fcdcert).digest('base64'); - - let pid; - let pidHmac; - let password; - - if (requestParams.userid) { - pid = util.nintendoBase64Decode(requestParams.userid).toString(); - } - - if (requestParams.uidhmac) { - pidHmac = util.nintendoBase64Decode(requestParams.uidhmac).toString(); - } - - if (requestParams.passwd) { - password = util.nintendoBase64Decode(requestParams.passwd).toString(); - } - - if (action !== 'LOGIN' && action !== 'SVCLOC') { - return response.status(200).send(util.nascError('null')); // This is what Nintendo sends - } - - const cert = new NintendoCertificate(fcdcert); - - if (!cert.valid) { - return response.status(200).send(util.nascError('121')); - } - - if (!validNintendoMACAddress(macAddress)) { - return response.status(200).send(util.nascError('null')); - } - - let model; - switch (serialNumber[0]) { - case 'C': - model = 'ctr'; - break; - case 'S': - model = 'spr'; - break; - case 'A': - model = 'ftr'; - break; - case 'Y': - model = 'ktr'; - break; - case 'Q': - model = 'red'; - break; - case 'N': - model = 'jan'; - break; - } - - if (!model) { - return response.status(200).send(util.nascError('null')); - } - - let device = await Device.findOne({ - model, - serial: serialNumber, - environment, - mac_hash: macAddressHash, - fcdcert_hash: fcdcertHash, - }); - - if (device) { - if (device.get('access_level') < 0) { - return response.status(200).send(util.nascError('102')); - } - - if (pid) { - const linkedPIDs = device.get('linked_pids'); - - if (!linkedPIDs.includes(pid)) { - return response.status(200).send(util.nascError('102')); - } - } - } - - if (titleID === '0004013000003202') { - if (password && !pid && !pidHmac) { - // Register new user - - const session = await database.connection.startSession(); - await session.startTransaction(); - - try { - // Create new NEX account - const nexAccount = await new NEXAccount({ - device_type: '3ds', - password - }); - - await nexAccount.generatePID(); - - await nexAccount.save({ session }); - - pid = nexAccount.get('pid'); - - // Set password - - if (!device) { - device = new Device({ - is_emulator: false, - model, - serial: serialNumber, - environment, - mac_hash: macAddressHash, - fcdcert_hash: fcdcertHash, - linked_pids: [pid] - }); - } else { - device.linked_pids.push(pid); - } - - await device.save({ session }); - - await session.commitTransaction(); - } catch (error) { - logger.error('[NASC] REGISTER ACCOUNT: ' + error); - - await session.abortTransaction(); - - // 3DS expects 200 even on error - return response.status(200).send(util.nascError('102')); - } finally { - // * This runs regardless of failure - // * Returning on catch will not prevent this from running - await session.endSession(); - } - } - } - - const nexUser = await NEXAccount.findOne({ pid }); - - if (!nexUser || nexUser.get('access_level') < 0) { - return response.status(200).send(util.nascError('102')); - } - - request.nexUser = nexUser; - - return next(); -} - -// https://www.adminsub.net/mac-address-finder/nintendo -// Saves us from doing an OUI lookup each time -const NINTENDO_VENDER_OUIS = [ - 'ECC40D', 'E84ECE', 'E0F6B5', 'E0E751', 'E00C7F', 'DC68EB', - 'D86BF7', 'D4F057', 'CCFB65', 'CC9E00', 'B8AE6E', 'B88AEC', - 'B87826', 'A4C0E1', 'A45C27', 'A438CC', '9CE635', '98E8FA', - '98B6E9', '98415C', '9458CB', '8CCDE8', '8C56C5', '7CBB8A', - '78A2A0', '7048F7', '64B5C6', '606BFF', '5C521E', '58BDA3', - '582F40', '48A5E7', '40F407', '40D28A', '34AF2C', '342FBD', - '2C10C1', '182A7B', '0403D6', '002709', '002659', '0025A0', - '0024F3', '002444', '00241E', '0023CC', '002331', '0022D7', - '0022AA', '00224C', '0021BD', '002147', '001FC5', '001F32', - '001EA9', '001E35', '001DBC', '001CBE', '001BEA', '001B7A', - '001AE9', '0019FD', '00191D', '0017AB', '001656', '0009BF', - 'ECC40D', 'E84ECE', 'E0F6B5', 'E0E751', 'E00C7F', 'DC68EB', - 'D86BF7', 'D4F057', 'CCFB65', 'CC9E00', 'B8AE6E', 'B88AEC', - 'B87826', 'A4C0E1', 'A45C27', 'A438CC', '9CE635', '98E8FA', - '98B6E9', '98415C', '9458CB', '8CCDE8', '8C56C5', '7CBB8A', - '78A2A0', '7048F7', '64B5C6', '606BFF', '5C521E', '58BDA3', - '582F40', '48A5E7', '40F407', '40D28A', '34AF2C', '342FBD', - '2C10C1', '182A7B', '0403D6', '002709', '002659', '0025A0', - '0024F3', '002444', '00241E', '0023CC', '002331', '0022D7', - '0022AA', '00224C', '0021BD', '002147', '001FC5', '001F32', - '001EA9', '001E35', '001DBC', '001CBE', '001BEA', '001B7A', - '001AE9', '0019FD', '00191D', '0017AB', '001656', '0009BF' -]; - -// TODO: Make something better -const MAC_REGEX = /^[0-9a-fA-F]{12}$/; - -// Maybe should later parse more data out -function validNintendoMACAddress(macAddress) { - if (!NINTENDO_VENDER_OUIS.includes(macAddress.substring(0, 6).toUpperCase())) { - return false; - } - - return MAC_REGEX.test(macAddress); -} - -module.exports = NASCMiddleware; \ No newline at end of file diff --git a/src/middleware/nasc.ts b/src/middleware/nasc.ts new file mode 100644 index 0000000..7ef7053 --- /dev/null +++ b/src/middleware/nasc.ts @@ -0,0 +1,274 @@ +import crypto from 'node:crypto'; +import express from 'express'; +import { Device } from '@/models/device'; +import { NEXAccount } from '@/models/nex-account'; +import { nascError, nintendoBase64Decode } from '@/util'; +import { connection as databaseConnection } from '@/database'; +import NintendoCertificate from '@/nintendo-certificate'; +import { LOG_ERROR } from '@/logger'; +import { NASCRequestParams } from '@/types/services/nasc/request-params'; + +async function NASCMiddleware(request: express.Request, response: express.Response, next: express.NextFunction): Promise { + const requestParams: NASCRequestParams = request.body; + + if (!requestParams.action || + !requestParams.fcdcert || + !requestParams.csnum || + !requestParams.macadr || + !requestParams.titleid || + !requestParams.servertype + ) { + response.status(200).send(nascError('null').toString()); // * This is what Nintendo sends + return; + } + + const action = nintendoBase64Decode(requestParams.action).toString(); + const fcdcert = nintendoBase64Decode(requestParams.fcdcert); + const serialNumber = nintendoBase64Decode(requestParams.csnum).toString(); + const macAddress = nintendoBase64Decode(requestParams.macadr).toString(); + const titleID = nintendoBase64Decode(requestParams.titleid).toString(); + const environment = nintendoBase64Decode(requestParams.servertype).toString(); + + const macAddressHash = crypto.createHash('sha256').update(macAddress).digest('base64'); + const fcdcertHash = crypto.createHash('sha256').update(fcdcert).digest('base64'); + + let pid = 0; // * Real PIDs are always positive and non-zero + let pidHmac = ''; + let password = ''; + + if (requestParams.userid) { + pid = Number(nintendoBase64Decode(requestParams.userid).toString()); + } + + if (requestParams.uidhmac) { + pidHmac = nintendoBase64Decode(requestParams.uidhmac).toString(); + } + + if (requestParams.passwd) { + password = nintendoBase64Decode(requestParams.passwd).toString(); + } + + if (action !== 'LOGIN' && action !== 'SVCLOC') { + response.status(200).send(nascError('null').toString()); // * This is what Nintendo sends + return; + } + + const cert = new NintendoCertificate(fcdcert); + + if (!cert.valid) { + response.status(200).send(nascError('121').toString()); + return; + } + + if (!validNintendoMACAddress(macAddress)) { + response.status(200).send(nascError('null').toString()); + return; + } + + let model = ''; + switch (serialNumber[0]) { + case 'C': + model = 'ctr'; + break; + case 'S': + model = 'spr'; + break; + case 'A': + model = 'ftr'; + break; + case 'Y': + model = 'ktr'; + break; + case 'Q': + model = 'red'; + break; + case 'N': + model = 'jan'; + break; + } + + if (!model) { + response.status(200).send(nascError('null').toString()); + return; + } + + let nexAccount = null; + if (pid) { + nexAccount = await NEXAccount.findOne({ pid }); + + // TODO - 102 is a DEVICE ban. Is there an error for ACCOUNT bans? + if (!nexAccount || nexAccount.access_level < 0) { + response.status(200).send(nascError('102').toString()); + return; + } + } + + + let device = await Device.findOne({ + fcdcert_hash: fcdcertHash, + }); + + if (device) { + if (device.access_level < 0) { + response.status(200).send(nascError('102').toString()); + return; + } + + if (pid) { + const linkedPIDs = device.linked_pids; + + // * If a user performs a system transfer from + // * a console to another using a Nintendo account + // * during the transfer and both consoles have + // * a Pretendo account, the new device won't have + // * the user's PID. + // * + // * So, the linked PIDs won't have the user's PID + // * anymore. + if (!linkedPIDs.includes(pid)) { + device.linked_pids.push(pid); + + await device.save(); + } + } + + if (device.serial !== serialNumber) { + // * 150 is a custom error code + response.status(200).send(nascError('150').toString()); + return; + } + } + + // * Workaround for edge case on system transfers + // * if a console that has a Pretendo account performs + // * a system transfer using the Nintendo account to + // * another that doesn't have a Pretendo account. + // * + // * This would make the Pretendo account to not have + // * a device on the database. + if (!device && pid) { + device = new Device({ + model, + serial: serialNumber, + environment, + mac_hash: macAddressHash, + fcdcert_hash: fcdcertHash, + linked_pids: [pid] + }); + + await device.save(); + } + + if (titleID === '0004013000003202') { + if (password && !pid && !pidHmac) { + // * Register new user + + const session = await databaseConnection().startSession(); + await session.startTransaction(); + + try { + // * Create new NEX account + nexAccount = new NEXAccount({ + device_type: '3ds', + password + }); + + await nexAccount.generatePID(); + + await nexAccount.save({ session }); + + pid = nexAccount.pid; + + const pidBuffer = Buffer.alloc(4); + pidBuffer.writeUInt32LE(pid); + + const hash = crypto.createHash('sha1').update(pidBuffer); + const pidHash = hash.digest(); + const checksum = pidHash[0] >> 1; + const hex = checksum.toString(16) + pid.toString(16); + const int = parseInt(hex, 16); + const friendCode = int.toString().padStart(12, '0').match(/.{1,4}/g)!.join('-'); + + nexAccount.friend_code = friendCode; + + await nexAccount.save({ session }); + + // * Set password + + if (!device) { + device = new Device({ + model, + serial: serialNumber, + environment, + mac_hash: macAddressHash, + fcdcert_hash: fcdcertHash, + linked_pids: [pid] + }); + } else { + device.linked_pids.push(pid); + } + + await device.save({ session }); + + await session.commitTransaction(); + } catch (error) { + LOG_ERROR('[NASC] REGISTER ACCOUNT: ' + error); + + await session.abortTransaction(); + + // * 151 is a custom error code + response.status(200).send(nascError('151').toString()); + return; + } finally { + // * This runs regardless of failure + // * Returning on catch will not prevent this from running + await session.endSession(); + } + } + } + + request.nexAccount = nexAccount; + + return next(); +} + +// * https://www.adminsub.net/mac-address-finder/nintendo +// * Saves us from doing an OUI lookup each time +const NINTENDO_VENDER_OUIS = [ + 'ECC40D', 'E84ECE', 'E0F6B5', 'E0E751', 'E00C7F', 'DC68EB', + 'D86BF7', 'D4F057', 'CCFB65', 'CC9E00', 'B8AE6E', 'B88AEC', + 'B87826', 'A4C0E1', 'A45C27', 'A438CC', '9CE635', '98E8FA', + '98B6E9', '98415C', '9458CB', '8CCDE8', '8C56C5', '7CBB8A', + '78A2A0', '7048F7', '64B5C6', '606BFF', '5C521E', '58BDA3', + '582F40', '48A5E7', '40F407', '40D28A', '34AF2C', '342FBD', + '2C10C1', '182A7B', '0403D6', '002709', '002659', '0025A0', + '0024F3', '002444', '00241E', '0023CC', '002331', '0022D7', + '0022AA', '00224C', '0021BD', '002147', '001FC5', '001F32', + '001EA9', '001E35', '001DBC', '001CBE', '001BEA', '001B7A', + '001AE9', '0019FD', '00191D', '0017AB', '001656', '0009BF', + 'ECC40D', 'E84ECE', 'E0F6B5', 'E0E751', 'E00C7F', 'DC68EB', + 'D86BF7', 'D4F057', 'CCFB65', 'CC9E00', 'B8AE6E', 'B88AEC', + 'B87826', 'A4C0E1', 'A45C27', 'A438CC', '9CE635', '98E8FA', + '98B6E9', '98415C', '9458CB', '8CCDE8', '8C56C5', '7CBB8A', + '78A2A0', '7048F7', '64B5C6', '606BFF', '5C521E', '58BDA3', + '582F40', '48A5E7', '40F407', '40D28A', '34AF2C', '342FBD', + '2C10C1', '182A7B', '0403D6', '002709', '002659', '0025A0', + '0024F3', '002444', '00241E', '0023CC', '002331', '0022D7', + '0022AA', '00224C', '0021BD', '002147', '001FC5', '001F32', + '001EA9', '001E35', '001DBC', '001CBE', '001BEA', '001B7A', + '001AE9', '0019FD', '00191D', '0017AB', '001656', '0009BF' +]; + +// TODO - Make something better +const MAC_REGEX = /^[0-9a-fA-F]{12}$/; + +// * Maybe should later parse more data out +function validNintendoMACAddress(macAddress: string): boolean { + if (!NINTENDO_VENDER_OUIS.includes(macAddress.substring(0, 6).toUpperCase())) { + return false; + } + + return MAC_REGEX.test(macAddress); +} + +export default NASCMiddleware; diff --git a/src/middleware/pnid.js b/src/middleware/pnid.js deleted file mode 100644 index d28d745..0000000 --- a/src/middleware/pnid.js +++ /dev/null @@ -1,65 +0,0 @@ -const xmlbuilder = require('xmlbuilder'); -const database = require('../database'); - -async function PNIDMiddleware(request, response, next) { - const { headers } = request; - - if (!headers.authorization || !(headers.authorization.startsWith('Bearer') || headers.authorization.startsWith('Basic'))) { - return next(); - } - - let [type, token] = headers.authorization.split(' '); - let user; - - if (request.isCemu) { - token = Buffer.from(token, 'hex').toString('base64'); - } - - if (type === 'Basic') { - user = await database.getUserBasic(token); - } else { - user = await database.getUserBearer(token); - } - - if (!user) { - response.status(401); - - if (type === 'Bearer') { - return response.send(xmlbuilder.create({ - errors: { - error: { - cause: 'access_token', - code: '0005', - message: 'Invalid access token' - } - } - }).end()); - } - - return response.send(xmlbuilder.create({ - errors: { - error: { - code: '1105', - message: 'Email address, username, or password, is not valid' - } - } - }).end()); - } - - if (user.get('access_level') < 0) { - return response.status(400).send(xmlbuilder.create({ - errors: { - error: { - code: '0122', - message: 'Device has been banned by game server' - } - } - }).end()); - } - - request.pnid = user; - - return next(); -} - -module.exports = PNIDMiddleware; \ No newline at end of file diff --git a/src/middleware/pnid.ts b/src/middleware/pnid.ts new file mode 100644 index 0000000..f858839 --- /dev/null +++ b/src/middleware/pnid.ts @@ -0,0 +1,87 @@ +import express from 'express'; +import xmlbuilder from 'xmlbuilder'; +import { getValueFromHeaders } from '@/util'; +import { getPNIDByBasicAuth, getPNIDByTokenAuth } from '@/database'; +import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; + +async function PNIDMiddleware(request: express.Request, response: express.Response, next: express.NextFunction): Promise { + const authHeader = getValueFromHeaders(request.headers, 'authorization'); + + if (!authHeader || !(authHeader.startsWith('Bearer') || authHeader.startsWith('Basic'))) { + return next(); + } + + const parts = authHeader.split(' '); + const type = parts[0]; + let token = parts[1]; + let pnid: HydratedPNIDDocument | null; + + if (request.isCemu) { + token = Buffer.from(token, 'hex').toString('base64'); + } + + if (type === 'Basic') { + pnid = await getPNIDByBasicAuth(token); + } else { + pnid = await getPNIDByTokenAuth(token); + } + + if (!pnid) { + if (type === 'Bearer') { + response.status(401).send(xmlbuilder.create({ + errors: { + error: { + cause: 'access_token', + code: '0005', + message: 'Invalid access token' + } + } + }).end()); + + return; + } + + response.status(401).send(xmlbuilder.create({ + errors: { + error: { + code: '1105', + message: 'Email address, username, or password, is not valid' + } + } + }).end()); + + return; + } + + if (pnid.deleted) { + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + code: '0112', + message: pnid.username + } + } + }).end()); + + return; + } + + if (pnid.access_level < 0) { + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + code: '0108', + message: 'Account has been banned' + } + } + }).end()); + + return; + } + + request.pnid = pnid; + + return next(); +} + +export default PNIDMiddleware; \ No newline at end of file diff --git a/src/middleware/ratelimit.js b/src/middleware/ratelimit.js deleted file mode 100644 index 0951794..0000000 --- a/src/middleware/ratelimit.js +++ /dev/null @@ -1,11 +0,0 @@ -const crypto = require('crypto'); -const ratelimit = require('express-rate-limit'); - -module.exports = ratelimit({ - windowMs: 60 * 1000, - max: 1, - keyGenerator: request => { - const data = request.headers['x-nintendo-device-cert']; - return crypto.createHash('md5').update(data).digest('hex'); - } -}); \ No newline at end of file diff --git a/src/middleware/ratelimit.ts b/src/middleware/ratelimit.ts new file mode 100644 index 0000000..c12f7f1 --- /dev/null +++ b/src/middleware/ratelimit.ts @@ -0,0 +1,18 @@ +import crypto from 'node:crypto'; +import express from 'express'; +import ratelimit from 'express-rate-limit'; +import { getValueFromHeaders } from '@/util'; + +export default ratelimit({ + windowMs: 60 * 1000, + max: 1, + keyGenerator: (request: express.Request): string => { + let data = getValueFromHeaders(request.headers, 'x-nintendo-device-cert'); + + if (!data) { + data = request.ip; + } + + return crypto.createHash('md5').update(data).digest('hex'); + } +}); \ No newline at end of file diff --git a/src/middleware/xml-parser.js b/src/middleware/xml-parser.js deleted file mode 100644 index 323e045..0000000 --- a/src/middleware/xml-parser.js +++ /dev/null @@ -1,53 +0,0 @@ -const xmlbuilder = require('xmlbuilder'); -const { document: xmlParser } = require('xmlbuilder2'); - -function XMLMiddleware(request, response, next) { - if (request.method == 'POST' || request.method == 'PUT') { - const headers = request.headers; - let body = ''; - - if ( - !headers['content-type'] || - !headers['content-type'].toLowerCase().includes('xml') - ) { - return next(); - } - - if ( - !headers['content-length'] || - parseInt(headers['content-length']) === 0 - ) { - return next(); - } - - request.setEncoding('utf-8'); - request.on('data', (chunk) => { - body += chunk; - }); - - request.on('end', () => { - try { - request.body = xmlParser(body); - request.body = request.body.toObject(); - } catch (error) { - response.status(401); - - // TODO: This is not a real error code, check to see if better one exists - return response.send(xmlbuilder.create({ - errors: { - error: { - code: '0004', - message: 'XML parse error' - } - } - }).end()); - } - - next(); - }); - } else { - next(); - } -} - -module.exports = XMLMiddleware; \ No newline at end of file diff --git a/src/middleware/xml-parser.ts b/src/middleware/xml-parser.ts new file mode 100644 index 0000000..9732053 --- /dev/null +++ b/src/middleware/xml-parser.ts @@ -0,0 +1,55 @@ +import express from 'express'; +import xmlbuilder from 'xmlbuilder'; +import { document as xmlParser } from 'xmlbuilder2'; +import { getValueFromHeaders, mapToObject } from '@/util'; + +function XMLMiddleware(request: express.Request, response: express.Response, next: express.NextFunction): void { + if (request.method == 'POST' || request.method == 'PUT') { + const contentType = getValueFromHeaders(request.headers, 'content-type'); + const contentLength = getValueFromHeaders(request.headers, 'content-length'); + let body = ''; + + if ( + !contentType || + !contentType.toLowerCase().includes('xml') + ) { + return next(); + } + + if ( + !contentLength || + parseInt(contentLength) === 0 + ) { + return next(); + } + + request.setEncoding('utf-8'); + request.on('data', (chunk: string) => { + body += chunk; + }); + + request.on('end', () => { + try { + request.body = xmlParser(body); + request.body = request.body.toObject(); + request.body = mapToObject(request.body); + } catch (error) { + // TODO - This is not a real error code, check to see if better one exists + return response.status(401).send(xmlbuilder.create({ + errors: { + error: { + code: '0004', + message: 'XML parse error' + } + } + }).end()); + } + + next(); + }); + } else { + next(); + } +} + +export default XMLMiddleware; \ No newline at end of file diff --git a/src/mii.js b/src/mii.js deleted file mode 100644 index 437ae16..0000000 --- a/src/mii.js +++ /dev/null @@ -1,214 +0,0 @@ -const KaitaiStream = require('kaitai-struct/KaitaiStream'); - -class Mii extends KaitaiStream { - constructor(arrayBuffer, byteOffset) { - super(arrayBuffer, byteOffset); - - this.decode(); - } - - decode() { - // Decode raw data - // A lot of this goes unused - this.unknown1 = this.readU1(); - this.characterSet = this.readBitsIntBe(2); - this.regionLock = this.readBitsIntBe(2); - this.profanityFlag = this.readBitsIntBe(1) !== 0; - this.copying = this.readBitsIntBe(1) !== 0; - this.unknown2 = this.readBitsIntBe(2); - this.slotIndex = this.readBitsIntBe(4); - this.pageIndex = this.readBitsIntBe(4); - this.version = this.readBitsIntBe(4); - this.unknown3 = this.readBitsIntBe(4); - this.systemId = Array(8).fill().map(() => this.readU1()); - this.avatarId = Array(4).fill().map(() => this.readU1()); - this.clientId = Array(6).fill().map(() => this.readU1()); - this.padding = this.readU2le(); - this.miiMetaData = this.readU2le(); - this.miiName = Buffer.from(this.readBytes(20)).toString('utf16le'); - this.height = this.readU1(); - this.build = this.readU1(); - this.faceColor = this.readBitsIntBe(3); - this.faceType = this.readBitsIntBe(4); - this.mingle = this.readBitsIntBe(1) !== 0; - this.faceMakeup = this.readBitsIntBe(4); - this.faceWrinkles = this.readBitsIntBe(4); - this.alignToByte(); - this.hairType = this.readU1(); - this.unknown5 = this.readBitsIntBe(4); - this.hairFlip = this.readBitsIntBe(1) !== 0; - this.hairColor = this.readBitsIntBe(3); - this.alignToByte(); - this.eyeData = this.readU4le(); - this.eyebrowData = this.readU4le(); - this.noseData = this.readU2le(); - this.mouthData = this.readU2le(); - this.mouthData2 = this.readU2le(); - this.facialHairData = this.readU2le(); - this.glassesData = this.readU2le(); - this.moleData = this.readU2le(); - this.creatorName = Buffer.from(this.readBytes(20)).toString('utf16le'); - this.padding2 = this.readU2le(); - this.checksum = this.readU2le(); - - // Carve out more specific data from the above values - // TODO: read these bits directly instead of getting them later - - this.gender = (this.miiMetaData & 1); - this.birthMonth = ((this.miiMetaData >> 1) & 15); - this.birthDay = ((this.miiMetaData >> 5) & 31); - this.favoriteColor = ((this.miiMetaData >> 10) & 15); - this.favorite = ((this.miiMetaData >> 14) & 1); - - this.eyeType = (this.eyeData & 63); - this.eyeColor = ((this.eyeData >> 6) & 7); - this.eyeSize = ((this.eyeData >> 9) & 7); - this.eyeStretch = ((this.eyeData >> 13) & 7); - this.eyeRotation = ((this.eyeData >> 16) & 31); - this.eyeHorizontal = ((this.eyeData >> 21) & 15); - this.eyeVertical = ((this.eyeData >> 25) & 31); - - this.eyebrowType = (this.eyebrowData & 31); - this.eyebrowColor = ((this.eyebrowData >> 5) & 7); - this.eyebrowSize = ((this.eyebrowData >> 8) & 15); - this.eyebrowStretch = ((this.eyebrowData >> 12) & 7); - this.eyebrowRotation = ((this.eyebrowData >> 16) & 15); - this.eyebrowHorizontal = ((this.eyebrowData >> 21) & 15); - this.eyebrowVertical = ((this.eyebrowData >> 25) & 31); - - this.noseType = (this.noseData & 31); - this.noseSize = ((this.noseData >> 5) & 15); - this.noseVertical = ((this.noseData >> 9) & 31); - - - this.mouthType = (this.mouthData & 63); - this.mouthColor = ((this.mouthData >> 6) & 7); - this.mouthSize = ((this.mouthData >> 9) & 15); - this.mouthStretch = ((this.mouthData >> 13) & 7); - - this.mouthVertical = (this.mouthData2 & 31); - this.facialHairMustache = ((this.mouthData2 >> 5) & 7); - - this.facialHairType = (this.facialHairData & 7); - this.facialHairColor = ((this.facialHairData >> 3) & 7); - this.facialHairSize = ((this.facialHairData >> 6) & 15); - this.facialHairVertical = ((this.facialHairData >> 10) & 31); - - this.glassesType = (this.glassesData & 15); - this.glassesColor = (this.glassesData >> 4) & 7; - this.glassesSize = (this.glassesData >> 7) & 15; - this.glassesVertical = (this.glassesData >> 11) & 15; - - this.moleEnable = (this.moleData >> 15); - this.moleSize = ((this.moleData >> 1) & 15); - this.moleHorizontal = ((this.moleData >> 5) & 31); - this.moleVertical = ((this.moleData >> 10) & 31); - } - - toStudioMii() { - /* - Can also disable randomization with: - - let miiStudioData = Buffer.alloc(0x2F); - let next = 256; - - and removing "randomizer" and the "miiStudioData.writeUInt8(randomizer);" call - */ - const miiStudioData = Buffer.alloc(0x2F); - const randomizer = Math.floor(256 * Math.random()); - let next = randomizer; - let pos = 1; - - function encodeMiiPart(partValue) { - const encoded = (7 + (partValue ^ next)) % 256; - next = encoded; - - miiStudioData.writeUInt8(encoded, pos); - pos++; - } - - miiStudioData.writeUInt8(randomizer); - - if (this.facialHairColor === 0) { - encodeMiiPart(8); - } else { - encodeMiiPart(this.facialHairColor); - } - - encodeMiiPart(this.facialHairType); - encodeMiiPart(this.build); - encodeMiiPart(this.eyeStretch); - encodeMiiPart(this.eyeColor + 8); - encodeMiiPart(this.eyeRotation); - encodeMiiPart(this.eyeSize); - encodeMiiPart(this.eyeType); - encodeMiiPart(this.eyeHorizontal); - encodeMiiPart(this.eyeVertical); - encodeMiiPart(this.eyebrowStretch); - - if (this.eyebrowColor === 0) { - encodeMiiPart(8); - } else { - encodeMiiPart(this.eyebrowColor); - } - - encodeMiiPart(this.eyebrowRotation); - encodeMiiPart(this.eyebrowSize); - encodeMiiPart(this.eyebrowType); - encodeMiiPart(this.eyebrowHorizontal); - encodeMiiPart(this.eyebrowVertical); - encodeMiiPart(this.faceColor); - encodeMiiPart(this.faceMakeup); - encodeMiiPart(this.faceType); - encodeMiiPart(this.faceWrinkles); - encodeMiiPart(this.favoriteColor); - encodeMiiPart(this.gender); - - if (this.glassesColor == 0) { - encodeMiiPart(8); - } else if (this.glassesColor < 6) { - encodeMiiPart(this.glassesColor + 13); - } else { - encodeMiiPart(0); - } - - encodeMiiPart(this.glassesSize); - encodeMiiPart(this.glassesType); - encodeMiiPart(this.glassesVertical); - - if (this.hairColor == 0) { - encodeMiiPart(8); - } else { - encodeMiiPart(this.hairColor); - } - - encodeMiiPart(this.hairFlip ? 1 : 0); - encodeMiiPart(this.hairType); - encodeMiiPart(this.height); - encodeMiiPart(this.moleSize); - encodeMiiPart(this.moleEnable); - encodeMiiPart(this.moleHorizontal); - encodeMiiPart(this.moleVertical); - encodeMiiPart(this.mouthStretch); - - if (this.mouthColor < 4) { - encodeMiiPart(this.mouthColor + 19); - } else { - encodeMiiPart(0); - } - - encodeMiiPart(this.mouthSize); - encodeMiiPart(this.mouthType); - encodeMiiPart(this.mouthVertical); - encodeMiiPart(this.facialHairSize); - encodeMiiPart(this.facialHairMustache); - encodeMiiPart(this.facialHairVertical); - encodeMiiPart(this.noseSize); - encodeMiiPart(this.noseType); - encodeMiiPart(this.noseVertical); - - return miiStudioData; - } -} - -module.exports = Mii; \ No newline at end of file diff --git a/src/models/device.js b/src/models/device.js deleted file mode 100644 index 00d667b..0000000 --- a/src/models/device.js +++ /dev/null @@ -1,58 +0,0 @@ -const { Schema, model } = require('mongoose'); - -const DeviceAttributeSchema = new Schema({ - created_date: String, - name: String, - value: String, -}); - -const DeviceAttribute = model('DeviceAttribute', DeviceAttributeSchema); - -const DeviceSchema = new Schema({ - is_emulator: { - type: Boolean, - default: false - }, - model: { - type: String, - enum: [ - 'wup', // Nintendo Wii U - 'ctr', // Nintendo 3DS - 'spr', // Nintendo 3DS XL - 'ftr', // Nintendo 2DS - 'ktr', // New Nintendo 3DS - 'red', // New Nintendo 3DS XL - 'jan' // New Nintendo 2DS XL - ] - }, - device_id: Number, - device_type: Number, - serial: String, - device_attributes: [DeviceAttributeSchema], - soap: { - token: String, - account_id: Number, - }, - // 3DS-specific stuff - environment: String, - mac_hash: String, - fcdcert_hash: String, - linked_pids: [Number], - access_level: { - type: Number, - default: 0 // 0: standard, 1: tester, 2: mod?, 3: dev - }, - server_access_level: { - type: String, - default: 'prod' // everyone is in production by default - } -}); - -const Device = model('Device', DeviceSchema); - -module.exports = { - DeviceSchema, - Device, - DeviceAttributeSchema, - DeviceAttribute -}; \ No newline at end of file diff --git a/src/models/device.ts b/src/models/device.ts new file mode 100644 index 0000000..61dbfbb --- /dev/null +++ b/src/models/device.ts @@ -0,0 +1,47 @@ +import { Schema, model } from 'mongoose'; +import { IDeviceAttribute, IDeviceAttributeMethods, DeviceAttributeModel } from '@/types/mongoose/device-attribute'; +import { IDevice, IDeviceMethods, DeviceModel } from '@/types/mongoose/device'; + +const DeviceAttributeSchema = new Schema({ + created_date: String, + name: String, + value: String +}); + +export const DeviceSchema = new Schema({ + model: { + type: String, + enum: [ + 'wup', // * Nintendo Wii U + 'ctr', // * Nintendo 3DS + 'spr', // * Nintendo 3DS XL + 'ftr', // * Nintendo 2DS + 'ktr', // * New Nintendo 3DS + 'red', // * New Nintendo 3DS XL + 'jan' // * New Nintendo 2DS XL + ] + }, + device_id: Number, + device_type: Number, + serial: String, + device_attributes: [DeviceAttributeSchema], + soap: { + token: String, + account_id: Number, + }, + environment: String, + mac_hash: String, // * 3DS-specific + fcdcert_hash: String, // * 3DS-specific + linked_pids: [Number], + access_level: { + type: Number, + default: 0 // * 0: standard, 1: tester, 2: mod?, 3: dev + }, + server_access_level: { + type: String, + default: 'prod' // * everyone is in production by default + }, + certificate_hash: String +}); + +export const Device = model('Device', DeviceSchema); \ No newline at end of file diff --git a/src/models/nex-account.js b/src/models/nex-account.ts similarity index 55% rename from src/models/nex-account.js rename to src/models/nex-account.ts index fbffd69..c731f07 100644 --- a/src/models/nex-account.js +++ b/src/models/nex-account.ts @@ -1,11 +1,12 @@ -const { Schema, model } = require('mongoose'); -const uniqueValidator = require('mongoose-unique-validator'); +import { Schema, model } from 'mongoose'; +import uniqueValidator from 'mongoose-unique-validator'; +import { INEXAccount, INEXAccountMethods, NEXAccountModel } from '@/types/mongoose/nex-account'; -const NEXAccountSchema = new Schema({ +const NEXAccountSchema = new Schema({ device_type: { type: String, enum: [ - // Only track the family here not the model + // * Only track the family here not the model 'wiiu', '3ds', ] @@ -18,12 +19,13 @@ const NEXAccountSchema = new Schema({ owning_pid: Number, access_level: { type: Number, - default: 0 // 0: standard, 1: tester, 2: mod?, 3: dev + default: 0 // * 0: standard, 1: tester, 2: mod?, 3: dev }, server_access_level: { type: String, - default: 'prod' // everyone is in production by default + default: 'prod' // * everyone is in production by default }, + friend_code: String }); NEXAccountSchema.plugin(uniqueValidator, { message: '{PATH} already in use.' }); @@ -36,21 +38,23 @@ NEXAccountSchema.plugin(uniqueValidator, { message: '{PATH} already in use.' }); https://account.nintendo.net/v1/api/admin/mapped_ids?input_type=pid&output_type=user_id&input=1799999999 returns `prodtest1` and the next few accounts counting down seem to be admin, service and internal test accounts */ -NEXAccountSchema.methods.generatePID = async function () { - const min = 1000000000; // The console (WiiU) seems to not accept PIDs smaller than this +NEXAccountSchema.method('generatePID', async function generatePID(): Promise { + const min = 1000000000; // * The console (WiiU) seems to not accept PIDs smaller than this const max = 1799999999; - let pid = Math.floor(Math.random() * (max - min + 1) + min); + const pid = Math.floor(Math.random() * (max - min + 1) + min); const inuse = await NEXAccount.findOne({ pid }); - pid = (inuse ? await NEXAccount.generatePID() : pid); + if (inuse) { + await this.generatePID(); + } else { + this.pid = pid; + } +}); - this.set('pid', pid); -}; - -NEXAccountSchema.methods.generatePassword = function () { - function character() { +NEXAccountSchema.method('generatePassword', function generatePassword(): void { + function character(): string | number { const offset = Math.floor(Math.random() * 62); if (offset < 10) return offset; if (offset < 36) return String.fromCharCode(offset + 55); @@ -60,15 +64,10 @@ NEXAccountSchema.methods.generatePassword = function () { const output = []; while (output.length < 16) { - output.push(character()); + output.push(String(character())); } - this.set('password', output.join('')); -}; + this.password = output.join(''); +}); -const NEXAccount = model('NEXAccount', NEXAccountSchema); - -module.exports = { - NEXAccountSchema, - NEXAccount, -}; \ No newline at end of file +export const NEXAccount = model('NEXAccount', NEXAccountSchema); \ No newline at end of file diff --git a/src/models/pnid.js b/src/models/pnid.js deleted file mode 100644 index 5cf0f99..0000000 --- a/src/models/pnid.js +++ /dev/null @@ -1,239 +0,0 @@ -const { Schema, model } = require('mongoose'); -const uniqueValidator = require('mongoose-unique-validator'); -const bcrypt = require('bcrypt'); -const crypto = require('crypto'); -const imagePixels = require('image-pixels'); -const TGA = require('tga'); -const got = require('got'); -const util = require('../util'); -const { DeviceSchema } = require('./device'); -const Mii = require('mii-js'); - -const PNIDSchema = new Schema({ - access_level: { - type: Number, - default: 0 // 0: standard, 1: tester, 2: mod?, 3: dev - }, - server_access_level: { - type: String, - default: 'prod' // everyone is in production by default - }, - pid: { - type: Number, - unique: true - }, - creation_date: String, - updated: String, - username: { - type: String, - unique: true, - minlength: 6, - maxlength: 16 - }, - usernameLower: { - type: String, - unique: true - }, - password: String, - birthdate: String, - gender: String, - country: String, - language: String, - email: { - address: String, - primary: Boolean, - parent: Boolean, - reachable: Boolean, - validated: Boolean, - validated_date: String, - id: { - type: Number, - unique: true - } - }, - region: Number, - timezone: { - name: String, - offset: Number - }, - mii: { - name: String, - primary: Boolean, - data: String, - id: { - type: Number, - unique: true - }, - hash: { - type: String, - unique: true - }, - image_url: String, - image_id: { - type: Number, - unique: true - }, - }, - flags: { - active: Boolean, - marketing: Boolean, - off_device: Boolean - }, - devices: [DeviceSchema], - identification: { // user identification tokens - email_code: { - type: String, - unique: true - }, - email_token: { - type: String, - unique: true - }, - access_token: { - value: String, - ttl: Number - }, - refresh_token: { - value: String, - ttl: Number - } - }, - connections: { - discord: { - id: String - } - } -}); - -PNIDSchema.plugin(uniqueValidator, {message: '{PATH} already in use.'}); - -/* - According to http://pf2m.com/tools/rank.php Nintendo PID's start at 1,800,000,000 and count down with each account - This means the max PID is 1799999999 and hard-limits the number of potential accounts to 1,800,000,000 - The author of that site does not give any information on how they found this out, but it does seem to hold true - https://account.nintendo.net/v1/api/admin/mapped_ids?input_type=pid&output_type=user_id&input=1800000000 returns nothing - https://account.nintendo.net/v1/api/admin/mapped_ids?input_type=pid&output_type=user_id&input=1799999999 returns `prodtest1` - and the next few accounts counting down seem to be admin, service and internal test accounts -*/ -PNIDSchema.methods.generatePID = async function() { - const min = 1000000000; // The console (WiiU) seems to not accept PIDs smaller than this - const max = 1799999999; - - let pid = Math.floor(Math.random() * (max - min + 1) + min); - - const inuse = await PNID.findOne({ - pid - }); - - pid = (inuse ? await PNID.generatePID() : pid); - - this.set('pid', pid); -}; - -PNIDSchema.methods.generateEmailValidationCode = async function() { - // WiiU passes the PID along with the email code - // Does not actually need to be unique to all users - const code = Math.random().toFixed(6).split('.')[1]; // Dirty one-liner to generate numbers of 6 length and padded 0 - - this.set('identification.email_code', code); -}; - -PNIDSchema.methods.generateEmailValidationToken = async function() { - let token = crypto.randomBytes(32).toString('hex'); - - const inuse = await PNID.findOne({ - 'identification.email_token': token - }); - - token = (inuse ? await PNID.generateEmailValidationToken() : token); - - this.set('identification.email_token', token); -}; - -PNIDSchema.methods.getDevice = async function(document) { - const devices = this.get('devices'); - - return devices.find(device => { - return ( - (device.device_id === document.device_id) && - (device.device_type === document.device_type) && - (device.serial === document.serial) - ); - }); -}; - -PNIDSchema.methods.addDevice = async function(device) { - this.devices.push(device); - - await this.save(); -}; - -PNIDSchema.methods.removeDevice = async function(device) { - this.devices = this.devices.filter(({ _id }) => _id !== device._id); - - await this.save(); -}; - -PNIDSchema.methods.updateMii = async function({name, primary, data}) { - this.set('mii.name', name); - this.set('mii.primary', primary === 'Y'); - this.set('mii.data', data); - this.set('mii.hash', crypto.randomBytes(7).toString('hex')); - this.set('mii.id', crypto.randomBytes(4).readUInt32LE()); - this.set('mii.image_id', crypto.randomBytes(4).readUInt32LE()); - - await this.generateMiiImages(); - - await this.save(); -}; - -PNIDSchema.methods.generateMiiImages = async function() { - const miiData = this.get('mii.data'); - const mii = new Mii(Buffer.from(miiData, 'base64')); - const miiStudioUrl = mii.studioUrl({ - type: 'face', - width: '128', - instanceCount: '1', - }); - const miiStudioNormalFaceImageData = await got(miiStudioUrl).buffer(); - const pngData = await imagePixels(miiStudioNormalFaceImageData); - const tga = TGA.createTgaBuffer(pngData.width, pngData.height, pngData.data); - - const userMiiKey = `mii/${this.get('pid')}`; - - await util.uploadCDNAsset('pn-cdn', `${userMiiKey}/standard.tga`, tga, 'public-read'); - await util.uploadCDNAsset('pn-cdn', `${userMiiKey}/normal_face.png`, miiStudioNormalFaceImageData, 'public-read'); - - const expressions = ['frustrated', 'smile_open_mouth', 'wink_left', 'sorrow', 'surprise_open_mouth']; - for (const expression of expressions) { - const miiStudioExpressionUrl = mii.studioUrl({ - type: 'face', - expression: expression, - width: '128', - instanceCount: '1', - }); - const miiStudioExpressionImageData = await got(miiStudioExpressionUrl).buffer(); - await util.uploadCDNAsset('pn-cdn', `${userMiiKey}/${expression}.png`, miiStudioExpressionImageData, 'public-read'); - } - - const miiStudioBodyUrl = mii.studioUrl({ - type: 'all_body', - width: '270', - instanceCount: '1', - }); - const miiStudioBodyImageData = await got(miiStudioBodyUrl).buffer(); - await util.uploadCDNAsset('pn-cdn', `${userMiiKey}/body.png`, miiStudioBodyImageData, 'public-read'); -}; - -PNIDSchema.methods.getServerMode = function () { - const serverMode = this.get('server_mode') || 'prod'; - - return serverMode; -}; - -const PNID = model('PNID', PNIDSchema); - -module.exports = { - PNIDSchema, - PNID -}; \ No newline at end of file diff --git a/src/models/pnid.ts b/src/models/pnid.ts new file mode 100644 index 0000000..a5509d0 --- /dev/null +++ b/src/models/pnid.ts @@ -0,0 +1,293 @@ +import crypto from 'node:crypto'; +import { Schema, model } from 'mongoose'; +import uniqueValidator from 'mongoose-unique-validator'; +import imagePixels from 'image-pixels'; +import TGA from 'tga'; +import got from 'got'; +import Mii from 'mii-js'; +import Stripe from 'stripe'; +import { DeviceSchema } from '@/models/device'; +import { uploadCDNAsset } from '@/util'; +import { LOG_ERROR, LOG_WARN } from '@/logger'; +import { IPNID, IPNIDMethods, PNIDModel } from '@/types/mongoose/pnid'; +import { PNIDPermissionFlag } from '@/types/common/permission-flags'; +import { config } from '@/config-manager'; + +let stripe: Stripe; + +if (config.stripe?.secret_key) { + stripe = new Stripe(config.stripe.secret_key, { + apiVersion: '2022-11-15', + typescript: true, + }); +} + +const PNIDSchema = new Schema({ + deleted: { + type: Boolean, + default: false + }, + permissions: { + type: BigInt, + default: 0n + }, + access_level: { + type: Number, + default: 0 // * 0: standard, 1: tester, 2: mod?, 3: dev + }, + server_access_level: { + type: String, + default: 'prod' // * everyone is in production by default + }, + pid: { + type: Number, + unique: true + }, + creation_date: String, + updated: String, + username: { + type: String, + unique: true, + minlength: 6, + maxlength: 16 + }, + usernameLower: { + type: String, + unique: true + }, + password: String, + birthdate: String, + gender: String, + country: String, + language: String, + email: { + address: String, + primary: Boolean, + parent: Boolean, + reachable: Boolean, + validated: Boolean, + validated_date: String, + id: Number + }, + region: Number, + timezone: { + name: String, + offset: Number + }, + mii: { + name: String, + primary: Boolean, + data: String, + id: Number, + hash: String, + image_url: String, + image_id: Number, + }, + flags: { + active: Boolean, + marketing: Boolean, + off_device: Boolean + }, + devices: [DeviceSchema], + identification: { // * user identification tokens + email_code: { + type: String, + unique: true + }, + email_token: { + type: String, + unique: true + }, + access_token: { + value: String, + ttl: Number + }, + refresh_token: { + value: String, + ttl: Number + } + }, + connections: { + discord: { + id: String + }, + stripe: { + customer_id: String, + subscription_id: String, + price_id: String, + tier_level: Number, + tier_name: String, + latest_webhook_timestamp: Number + } + } +}, { id: false }); + +PNIDSchema.plugin(uniqueValidator, {message: '{PATH} already in use.'}); + +/* + According to http://pf2m.com/tools/rank.php Nintendo PID's start at 1,800,000,000 and count down with each account + This means the max PID is 1799999999 and hard-limits the number of potential accounts to 1,800,000,000 + The author of that site does not give any information on how they found this out, but it does seem to hold true + https://account.nintendo.net/v1/api/admin/mapped_ids?input_type=pid&output_type=user_id&input=1800000000 returns nothing + https://account.nintendo.net/v1/api/admin/mapped_ids?input_type=pid&output_type=user_id&input=1799999999 returns `prodtest1` + and the next few accounts counting down seem to be admin, service and internal test accounts +*/ +PNIDSchema.method('generatePID', async function generatePID(): Promise { + const min = 1000000000; // * The console (WiiU) seems to not accept PIDs smaller than this + const max = 1799999999; + + const pid = Math.floor(Math.random() * (max - min + 1) + min); + + const inuse = await PNID.findOne({ + pid + }); + + if (inuse) { + await this.generatePID(); + } else { + this.pid = pid; + } +}); + +PNIDSchema.method('generateEmailValidationCode', async function generateEmailValidationCode(): Promise { + // * WiiU passes the PID along with the email code + // * Does not actually need to be unique to all users + const code = Math.random().toFixed(6).split('.')[1]; // * Dirty one-liner to generate numbers of 6 length and padded 0 + + this.identification.email_code = code; +}); + +PNIDSchema.method('generateEmailValidationToken', async function generateEmailValidationToken(): Promise { + const token = crypto.randomBytes(32).toString('hex'); + + const inuse = await PNID.findOne({ + 'identification.email_token': token + }); + + if (inuse) { + await this.generateEmailValidationToken(); + } else { + this.identification.email_token = token; + } +}); + +PNIDSchema.method('updateMii', async function updateMii({ name, primary, data }: { name: string; primary: string; data: string; }): Promise { + this.mii.name = name; + this.mii.primary = primary === 'Y'; + this.mii.data = data; + this.mii.hash = crypto.randomBytes(7).toString('hex'); + this.mii.id = crypto.randomBytes(4).readUInt32LE(); + this.mii.image_id = crypto.randomBytes(4).readUInt32LE(); + + await this.generateMiiImages(); + + await this.save(); +}); + +PNIDSchema.method('generateMiiImages', async function generateMiiImages(): Promise { + const miiData = this.mii.data; + const mii = new Mii(Buffer.from(miiData, 'base64')); + const miiStudioUrl = mii.studioUrl({ + type: 'face', + width: 128, + instanceCount: 1, + }); + const miiStudioNormalFaceImageData = await got(miiStudioUrl).buffer(); + const pngData = await imagePixels(miiStudioNormalFaceImageData); + const tga = TGA.createTgaBuffer(pngData.width, pngData.height, Uint8Array.from(pngData.data), false); + + const userMiiKey = `mii/${this.pid}`; + + await uploadCDNAsset(config.s3.bucket, `${userMiiKey}/standard.tga`, tga, 'public-read'); + await uploadCDNAsset(config.s3.bucket, `${userMiiKey}/normal_face.png`, miiStudioNormalFaceImageData, 'public-read'); + + const expressions = ['frustrated', 'smile_open_mouth', 'wink_left', 'sorrow', 'surprise_open_mouth']; + for (const expression of expressions) { + const miiStudioExpressionUrl = mii.studioUrl({ + type: 'face', + expression: expression, + width: 128, + instanceCount: 1, + }); + const miiStudioExpressionImageData = await got(miiStudioExpressionUrl).buffer(); + await uploadCDNAsset(config.s3.bucket, `${userMiiKey}/${expression}.png`, miiStudioExpressionImageData, 'public-read'); + } + + const miiStudioBodyUrl = mii.studioUrl({ + type: 'all_body', + width: 270, + instanceCount: 1, + }); + const miiStudioBodyImageData = await got(miiStudioBodyUrl).buffer(); + await uploadCDNAsset(config.s3.bucket, `${userMiiKey}/body.png`, miiStudioBodyImageData, 'public-read'); +}); + +PNIDSchema.method('scrub', async function scrub() { + // * Remove all personal info from a PNID + // * Username and PID remain so thye do not get assigned again + + if (this.connections?.stripe?.subscription_id) { + try { + if (stripe) { + await stripe.subscriptions.del(this.connections.stripe.subscription_id); + } else { + LOG_WARN(`SCRUBBING USER DATA FOR USER ${this.username}. HAS STRIPE SUBSCRIPTION ${this.connections.stripe.subscription_id}, BUT STRIPE CLIENT NOT ENABLED. SUBSCRIPTION NOT CANCELED`); + } + } catch (error) { + LOG_ERROR(`ERROR REMOVING ${this.username} STRIPE SUBSCRIPTION. ${error}`); + } + } + + await this.updateMii({ + name: 'Default', + primary: 'Y', + data: 'AwAAQOlVognnx0GC2/uogAOzuI0n2QAAAEBEAGUAZgBhAHUAbAB0AAAAAAAAAEBAAAAhAQJoRBgmNEYUgRIXaA0AACkAUkhQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGm9' + }); + + this.deleted = true; + this.access_level = 0; + this.server_access_level = 'prod'; + this.creation_date = ''; + this.birthdate = ''; + this.gender = ''; + this.country = ''; + this.language = ''; + this.email.address = ''; + this.email.primary = false; + this.email.parent = false; + this.email.reachable = false; + this.email.validated = false; + this.email.validated_date = ''; + this.email.id = 0; + this.region = 0; + this.timezone.name = ''; + this.timezone.offset = 0; + this.mii.id = 0; + this.mii.hash = ''; + this.mii.image_url = ''; + this.mii.image_id = 0; + this.flags.active = false; + this.flags.marketing = false; + this.flags.off_device = false; + this.connections.discord.id = ''; + this.connections.stripe.customer_id = ''; + this.connections.stripe.subscription_id = ''; + this.connections.stripe.price_id = ''; + this.connections.stripe.tier_level = 0; + this.connections.stripe.tier_name = ''; + this.connections.stripe.latest_webhook_timestamp = 0; +}); + +PNIDSchema.method('hasPermission', function hasPermission(flag: PNIDPermissionFlag): boolean { + return (this.permissions & flag) === flag; +}); + +PNIDSchema.method('addPermission', function addPermission(flag: PNIDPermissionFlag): void { + this.permissions |= flag; +}); + +PNIDSchema.method('clearPermission', function clearPermission(flag: PNIDPermissionFlag): void { + this.permissions &= ~flag; +}); + +export const PNID = model('PNID', PNIDSchema); \ No newline at end of file diff --git a/src/models/server.js b/src/models/server.js deleted file mode 100644 index 8b70a7a..0000000 --- a/src/models/server.js +++ /dev/null @@ -1,23 +0,0 @@ -const { Schema, model } = require('mongoose'); -const uniqueValidator = require('mongoose-unique-validator'); - -const ServerSchema = new Schema({ - ip: String, // Example: 1.1.1.1 - port: Number, // Example: 60000 - service_name: String, // Example: friends - service_type: String, // Example: nex - game_server_id: String, // Example: 00003200 - title_ids: [String], // Example: ["000500001018DB00", "000500001018DC00", "000500001018DD00"] - access_mode: String, // Example: prod - maintenance_mode: Boolean, // Example: false - device: Number, // Example: 1 (WiiU) -}); - -ServerSchema.plugin(uniqueValidator, { message: '{PATH} already in use.' }); - -const Server = model('Server', ServerSchema); - -module.exports = { - ServerSchema, - Server, -}; \ No newline at end of file diff --git a/src/models/server.ts b/src/models/server.ts new file mode 100644 index 0000000..3ab6fce --- /dev/null +++ b/src/models/server.ts @@ -0,0 +1,21 @@ +import { Schema, model } from 'mongoose'; +import uniqueValidator from 'mongoose-unique-validator'; +import { IServer, IServerMethods, ServerModel } from '@/types/mongoose/server'; + +const ServerSchema = new Schema({ + client_id: String, + ip: String, + port: Number, + service_name: String, + service_type: String, + game_server_id: String, + title_ids: [String], + access_mode: String, + maintenance_mode: Boolean, + device: Number, + aes_key: String +}); + +ServerSchema.plugin(uniqueValidator, { message: '{PATH} already in use.' }); + +export const Server = model('Server', ServerSchema); \ No newline at end of file diff --git a/src/nintendo-certificate.js b/src/nintendo-certificate.ts similarity index 71% rename from src/nintendo-certificate.js rename to src/nintendo-certificate.ts index 6df33ee..38e7a1a 100644 --- a/src/nintendo-certificate.js +++ b/src/nintendo-certificate.ts @@ -1,7 +1,6 @@ -// Parse Nintendo certificates - -const crypto = require('crypto'); -const NodeRSA = require('node-rsa'); +import crypto from 'node:crypto'; +import NodeRSA from 'node-rsa'; +import { SignatureSize } from '@/types/common/signature-size'; const WIIU_DEVICE_PUB_PEM = `-----BEGIN PUBLIC KEY----- MFIwEAYHKoZIzj0CAQYFK4EEABsDPgAEAP1WBBgs8XUJIQDDCK5IOZEbb5+h1TqV @@ -42,46 +41,61 @@ const CTR_LFCS_B_PUB = Buffer.from([ 0xAF, 0x07, 0xEB, 0x9C, 0xBF, 0xA9, 0xC9 ]); -// Signature options +// * Signature options const SIGNATURE_SIZES = { - RSA_4096_SHA1: { + RSA_4096_SHA1: { SIZE: 0x200, PADDING_SIZE: 0x3C }, - RSA_2048_SHA1: { + RSA_2048_SHA1: { SIZE: 0x100, PADDING_SIZE: 0x3C }, - ELLIPTIC_CURVE_SHA1: { + ELLIPTIC_CURVE_SHA1: { SIZE: 0x3C, PADDING_SIZE: 0x40 }, - RSA_4096_SHA256: { + RSA_4096_SHA256: { SIZE: 0x200, PADDING_SIZE: 0x3C }, - RSA_2048_SHA256: { + RSA_2048_SHA256: { SIZE: 0x100, PADDING_SIZE: 0x3C }, - ECDSA_SHA256: { + ECDSA_SHA256: { SIZE: 0x3C, PADDING_SIZE: 0x40 } -}; +} as const; class NintendoCertificate { - constructor(certificate) { - this._certificate = null; - this._certificateBody = null; - this.signatureType = null; - this.signature = null; - this.issuer = null; - this.keyType = null; - this.certificateName = null; - this.ngKeyId = null; - this.publicKey = null; - this.valid = null; + _certificate: Buffer; + _certificateBody: Buffer; + signatureType: number; + signature: Buffer; + issuer: string; + keyType: number; + certificateName: string; + ngKeyID: number; + publicKey: Buffer; + valid: boolean; + publicKeyData: Buffer; + consoleType: string; + + constructor(certificate: string | Buffer) { + this._certificate = Buffer.alloc(0); + this._certificateBody = Buffer.alloc(0); + this.signatureType = 0; + this.signature = Buffer.alloc(0); + this.issuer = ''; + this.keyType = 0; + this.certificateName = ''; + this.ngKeyID = 0; + this.publicKey = Buffer.alloc(0); + this.valid = false; + this.publicKeyData = Buffer.alloc(0); + this.consoleType = ''; if (certificate) { if (certificate instanceof Buffer) { @@ -91,19 +105,19 @@ class NintendoCertificate { } this._parseCertificateData(); - this._verifySignature(); } } - _parseCertificateData() { + _parseCertificateData(): void { if (this._certificate.length === 0x110) { - // Assume fcdcert (3DS LFCS) + // * Assume fcdcert (3DS LFCS) + this.consoleType = '3ds'; this.signature = this._certificate.subarray(0x0, 0x100); this._certificateBody = this._certificate.subarray(0x100); this._verifySignatureLFCS(); } else { - // Assume regular certificate + // * Assume regular certificate this.signatureType = this._certificate.readUInt32BE(0x00); const signatureTypeSizes = this._signatureTypeSizes(this.signatureType); @@ -114,12 +128,20 @@ class NintendoCertificate { this.issuer = this._certificate.subarray(0x80, 0xC0).toString().split('\0')[0]; this.keyType = this._certificate.readUInt32BE(0xC0); this.certificateName = this._certificate.subarray(0xC4, 0x104).toString().split('\0')[0]; - this.ngKeyId = this._certificate.readUInt32BE(0x104); + this.ngKeyID = this._certificate.readUInt32BE(0x104); this.publicKeyData = this._certificate.subarray(0x108); + + if (this.issuer === 'Root-CA00000003-MS00000012') { + this.consoleType = 'wiiu'; + } else { + this.consoleType = '3ds'; + } + + this._verifySignature(); } } - _signatureTypeSizes(signatureType) { + _signatureTypeSizes(signatureType: number): SignatureSize { switch (signatureType) { case 0x10000: return SIGNATURE_SIZES.RSA_4096_SHA1; @@ -138,7 +160,7 @@ class NintendoCertificate { } } - _verifySignature() { + _verifySignature(): void { switch (this.keyType) { case 0x0: this._verifySignatureRSA4096(); @@ -157,7 +179,7 @@ class NintendoCertificate { } } - _verifySignatureRSA4096() { + _verifySignatureRSA4096(): void { const publicKey = new NodeRSA(); publicKey.importKey({ @@ -168,7 +190,7 @@ class NintendoCertificate { this.valid = publicKey.verify(this._certificateBody, this.signature); } - _verifySignatureRSA2048() { + _verifySignatureRSA2048(): void { const publicKey = new NodeRSA(); publicKey.importKey({ @@ -179,21 +201,21 @@ class NintendoCertificate { this.valid = publicKey.verify(this._certificateBody, this.signature); } - // Huge thanks to Myria for helping get ECDSA working - // with Nodes native crypto module and getting the keys - // from bytes to PEM! - // https://github.com/Myriachan - _verifySignatureECDSA() { - const pem = this.issuer == 'Root-CA00000003-MS00000012' ? WIIU_DEVICE_PUB_PEM : CTR_DEVICE_PUB_PEM; - const key = crypto.createPublicKey({ - key: pem - }); - key.dsaEncoding = 'ieee-p1363'; + // * Huge thanks to Myria for helping get ECDSA working + // * with Nodes native crypto module and getting the keys + // * from bytes to PEM! + // * https://github.com/Myriachan + _verifySignatureECDSA(): void { + const pem = this.consoleType === 'wiiu' ? WIIU_DEVICE_PUB_PEM : CTR_DEVICE_PUB_PEM; + const key = { + key: pem, + dsaEncoding: 'ieee-p1363' as crypto.DSAEncoding + }; this.valid = crypto.verify('sha256', this._certificateBody, key, this.signature); } - _verifySignatureLFCS() { + _verifySignatureLFCS(): void { const publicKey = new NodeRSA(); publicKey.importKey({ @@ -205,4 +227,4 @@ class NintendoCertificate { } } -module.exports = NintendoCertificate; \ No newline at end of file +export default NintendoCertificate; \ No newline at end of file diff --git a/src/server.js b/src/server.js deleted file mode 100644 index 9372a3a..0000000 --- a/src/server.js +++ /dev/null @@ -1,93 +0,0 @@ -process.title = 'Pretendo - Account'; - -const configManager = require('./config-manager'); - -configManager.configure(); - -const express = require('express'); -const morgan = require('morgan'); -const xmlparser = require('./middleware/xml-parser'); -const cache = require('./cache'); -const database = require('./database'); -const util = require('./util'); -const logger = require('../logger'); - -const { config } = configManager; - -const { http: { port } } = config; -const app = express(); - -const conntest = require('./services/conntest'); -const nnid = require('./services/nnid'); -const nasc = require('./services/nasc'); -const datastore = require('./services/datastore'); -const api = require('./services/api'); -const localcdn = require('./services/local-cdn'); -const assets = require('./services/assets'); - -// START APPLICATION - -// Create router -logger.info('Setting up Middleware'); -app.use(morgan('dev')); -app.use(express.json()); -app.use(express.urlencoded({ - extended: true -})); -app.use(xmlparser); - -// import the servers into one -app.use(conntest); -app.use(nnid); -app.use(nasc); -app.use(datastore); -app.use(api); -app.use(localcdn); -app.use(assets); - -// 404 handler -logger.info('Creating 404 status handler'); -app.use((request, response) => { - const fullUrl = util.fullUrl(request); - const deviceId = request.headers['X-Nintendo-Device-ID'] || 'Unknown'; - - logger.warn(`HTTP 404 at ${fullUrl} from ${deviceId}`); - - response.set('Content-Type', 'text/xml'); - response.set('Server', 'Nintendo 3DS (http)'); - response.set('X-Nintendo-Date', new Date().getTime()); - - response.status(404); - response.send('0008Not Found'); -}); - -// non-404 error handler -logger.info('Creating non-404 status handler'); -app.use((error, request, response) => { - const status = error.status || 500; - const fullUrl = util.fullUrl(request); - const deviceId = request.headers['X-Nintendo-Device-ID'] || 'Unknown'; - - logger.warn(`HTTP ${status} at ${fullUrl} from ${deviceId}: ${error.message}`); - - response.status(status); - response.json({ - app: 'api', - status, - error: error.message - }); -}); - -async function main() { - // Starts the server - logger.info('Starting server'); - - await database.connect(); - await cache.connect(); - - app.listen(port, () => { - logger.success(`Server started on port ${port}`); - }); -} - -main().catch(console.error); \ No newline at end of file diff --git a/src/server.ts b/src/server.ts new file mode 100644 index 0000000..4d63d04 --- /dev/null +++ b/src/server.ts @@ -0,0 +1,122 @@ +process.title = 'Pretendo - Account'; +process.on('uncaughtException', (err, origin) => { + console.log(err); + console.log(origin); +}); +process.on('SIGTERM', () => { + process.exit(0); +}); + +import express from 'express'; +import morgan from 'morgan'; +import xmlbuilder from 'xmlbuilder'; +import xmlparser from '@/middleware/xml-parser'; +import { connect as connectCache } from '@/cache'; +import { connect as connectDatabase } from '@/database'; +import { startGRPCServer } from '@/services/grpc/server'; +import { fullUrl, getValueFromHeaders } from '@/util'; +import { LOG_INFO, LOG_SUCCESS, LOG_WARN } from '@/logger'; + +import conntest from '@/services/conntest'; +import cbvc from '@/services/cbvc'; +import nnas from '@/services/nnas'; +import nasc from '@/services/nasc'; +import datastore from '@/services/datastore'; +import api from '@/services/api'; +import localcdn from '@/services/local-cdn'; +import assets from '@/services/assets'; + +import { config, disabledFeatures } from '@/config-manager'; + +const app = express(); + +// * START APPLICATION +app.set('view engine', 'ejs'); +app.set('views', __dirname + '/views'); + +// * Create router +LOG_INFO('Setting up Middleware'); +app.use(morgan('dev')); +app.use(express.json()); +app.use(express.urlencoded({ + extended: true +})); +app.use(xmlparser); + +// * import the servers into one +app.use(conntest); +app.use(cbvc); +app.use(nnas); +app.use(nasc); +app.use(api); +app.use(localcdn); +app.use(assets); + +if (!disabledFeatures.datastore) { + app.use(datastore); +} + +// * 404 handler +LOG_INFO('Creating 404 status handler'); +app.use((request: express.Request, response: express.Response): void => { + const url = fullUrl(request); + let deviceID = getValueFromHeaders(request.headers, 'X-Nintendo-Device-ID'); + + if (!deviceID) { + deviceID = 'Unknown'; + } + + LOG_WARN(`HTTP 404 at ${url} from ${deviceID}`); + + response.set('Content-Type', 'text/xml'); + response.set('Server', 'Nintendo 3DS (http)'); + response.set('X-Nintendo-Date', new Date().getTime().toString()); + + response.status(404).send(xmlbuilder.create({ + errors: { + error: { + cause: '', + code: '0008', + message: 'Not Found' + } + } + }).end()); +}); + +// * non-404 error handler +LOG_INFO('Creating non-404 status handler'); +app.use((error: any, request: express.Request, response: express.Response, _next: express.NextFunction): void => { + const status = error.status || 500; + const url = fullUrl(request); + let deviceID = getValueFromHeaders(request.headers, 'X-Nintendo-Device-ID'); + + if (!deviceID) { + deviceID = 'Unknown'; + } + + LOG_WARN(`HTTP ${status} at ${url} from ${deviceID}: ${error.message}`); + + response.status(status).json({ + app: 'api', + status, + error: error.message + }); +}); + +async function main(): Promise { + // * Starts the server + LOG_INFO('Starting server'); + + await connectDatabase(); + LOG_SUCCESS('Database connected'); + await connectCache(); + LOG_SUCCESS('Cache enabled'); + await startGRPCServer(); + LOG_SUCCESS(`gRPC server started on port ${config.grpc.port}`); + + app.listen(config.http.port, () => { + LOG_SUCCESS(`HTTP server started on port ${config.http.port}`); + }); +} + +main().catch(console.error); diff --git a/src/services/api/index.js b/src/services/api/index.js deleted file mode 100644 index 8db69f5..0000000 --- a/src/services/api/index.js +++ /dev/null @@ -1,36 +0,0 @@ -// handles "api.nintendo.cc" endpoints - -const express = require('express'); -const subdomain = require('express-subdomain'); -const cors = require('cors'); -const APIMiddleware = require('../../middleware/api'); -const logger = require('../../../logger'); -const routes = require('./routes'); - -// Router to handle the subdomain restriction -const api = express.Router(); - -logger.info('[USER API] Importing middleware'); -api.use(APIMiddleware); -api.use(cors()); -api.options('*', cors()); - -// Setup routes -logger.info('[USER API] Applying imported routes'); -api.use('/v1/connections', routes.V1.CONNECTIONS); -api.use('/v1/email', routes.V1.EMAIL); -api.use('/v1/forgot-password', routes.V1.FORGOT_PASSWORD); -api.use('/v1/login', routes.V1.LOGIN); -api.use('/v1/register', routes.V1.REGISTER); -api.use('/v1/reset-password', routes.V1.RESET_PASSWORD); -api.use('/v1/user', routes.V1.USER); - - -// Main router for endpoints -const router = express.Router(); - -// Create subdomains -logger.info('[USER API] Creating \'api\' subdomain'); -router.use(subdomain('api', api)); - -module.exports = router; \ No newline at end of file diff --git a/src/services/api/index.ts b/src/services/api/index.ts new file mode 100644 index 0000000..b7ad859 --- /dev/null +++ b/src/services/api/index.ts @@ -0,0 +1,36 @@ +import express from 'express'; +import cors from 'cors'; +import APIMiddleware from '@/middleware/api'; +import { formatHostnames, LOG_INFO } from '@/logger'; + +import { V1 } from '@/services/api/routes'; +import { config } from '@/config-manager'; +import { restrictHostnames } from '@/middleware/host-limit'; + +// * Router to handle the subdomain restriction +const api = express.Router(); + +LOG_INFO('[USER API] Importing middleware'); +api.use(APIMiddleware); +api.use(cors()); +api.options('*', cors()); + +// * Setup routes +LOG_INFO('[USER API] Applying imported routes'); +api.use('/v1/connections', V1.CONNECTIONS); +api.use('/v1/email', V1.EMAIL); +api.use('/v1/forgot-password', V1.FORGOT_PASSWORD); +api.use('/v1/login', V1.LOGIN); +api.use('/v1/register', V1.REGISTER); +api.use('/v1/reset-password', V1.RESET_PASSWORD); +api.use('/v1/user', V1.USER); + + +// * Main router for endpoints +const router = express.Router(); + +// * Create domains +LOG_INFO(`[USER API] Registering api router with domains: ${formatHostnames(config.domains.api)}`); +router.use(restrictHostnames(config.domains.api, api)); + +export default router; \ No newline at end of file diff --git a/src/services/api/routes/index.js b/src/services/api/routes/index.js deleted file mode 100644 index 217a96d..0000000 --- a/src/services/api/routes/index.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = { - V1: { - CONNECTIONS: require('./v1/connections'), - EMAIL: require('./v1/email'), - FORGOT_PASSWORD: require('./v1/forgotPassword'), - LOGIN: require('./v1/login'), - REGISTER: require('./v1/register'), - RESET_PASSWORD: require('./v1/resetPassword'), - USER: require('./v1/user'), - } -}; \ No newline at end of file diff --git a/src/services/api/routes/index.ts b/src/services/api/routes/index.ts new file mode 100644 index 0000000..6f25c45 --- /dev/null +++ b/src/services/api/routes/index.ts @@ -0,0 +1,17 @@ +import connections_v1 from '@/services/api/routes/v1/connections'; +import email_v1 from '@/services/api/routes/v1/email'; +import forgotPassword_v1 from '@/services/api/routes/v1/forgotPassword'; +import login_v1 from '@/services/api/routes/v1/login'; +import register_v1 from '@/services/api/routes/v1/register'; +import resetPassword_v1 from '@/services/api/routes/v1/resetPassword'; +import user_v1 from '@/services/api/routes/v1/user'; + +export const V1 = { + CONNECTIONS: connections_v1, + EMAIL: email_v1, + FORGOT_PASSWORD: forgotPassword_v1, + LOGIN: login_v1, + REGISTER: register_v1, + RESET_PASSWORD: resetPassword_v1, + USER: user_v1 +}; \ No newline at end of file diff --git a/src/services/api/routes/v1/connections.js b/src/services/api/routes/v1/connections.js deleted file mode 100644 index 76e41c7..0000000 --- a/src/services/api/routes/v1/connections.js +++ /dev/null @@ -1,77 +0,0 @@ -const router = require('express').Router(); -const database = require('../../../../database'); - -const VALID_CONNECTION_TYPES = [ - 'discord' -]; - -/** - * [POST] - * Implementation of for: https://api.pretendo.cc/v1/connections/add/TYPE - * Description: Adds an account connection to the users PNID - */ -router.post('/add/:type', async (request, response) => { - const { body, pnid } = request; - const { type } = request.params; - const { data } = body; - - if (!pnid) { - return response.status(400).json({ - app: 'api', - status: 400, - error: 'Invalid or missing access token' - }); - } - - if (!data) { - return response.status(400).json({ - app: 'api', - status: 400, - error: 'Invalid or missing connection data' - }); - } - - if (!VALID_CONNECTION_TYPES.includes(type)) { - return response.status(400).json({ - app: 'api', - status: 400, - error: 'Invalid or missing connection type' - }); - } - - const result = await database.addUserConnection(pnid, data, type); - - response.status(result.status).json(result); -}); - -/** - * [DELETE] - * Implementation of for: https://api.pretendo.cc/v1/connections/remove/TYPE - * Description: Removes an account connection from the users PNID - */ -router.delete('/remove/:type', async (request, response) => { - const { pnid } = request; - const { type } = request.params; - - if (!pnid) { - return response.status(400).json({ - app: 'api', - status: 400, - error: 'Invalid or missing access token' - }); - } - - if (!VALID_CONNECTION_TYPES.includes(type)) { - return response.status(400).json({ - app: 'api', - status: 400, - error: 'Invalid or missing connection type' - }); - } - - const result = await database.removeUserConnection(pnid, type); - - response.status(result.status).json(result); -}); - -module.exports = router; \ No newline at end of file diff --git a/src/services/api/routes/v1/connections.ts b/src/services/api/routes/v1/connections.ts new file mode 100644 index 0000000..2a0612a --- /dev/null +++ b/src/services/api/routes/v1/connections.ts @@ -0,0 +1,105 @@ +import express from 'express'; +import { addPNIDConnection, removePNIDConnection } from '@/database'; + +const router = express.Router(); + +const VALID_CONNECTION_TYPES = [ + 'discord' +]; + +/** + * [POST] + * Implementation of for: https://api.pretendo.cc/v1/connections/add/TYPE + * Description: Adds an account connection to the users PNID + */ +router.post('/add/:type', async (request: express.Request, response: express.Response): Promise => { + const data = request.body?.data; + const pnid = request.pnid; + const type = request.params.type; + + if (!pnid) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Invalid or missing access token' + }); + + return; + } + + if (!data) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Invalid or missing connection data' + }); + + return; + } + + if (!VALID_CONNECTION_TYPES.includes(type)) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Invalid or missing connection type' + }); + + return; + } + + let result = await addPNIDConnection(pnid, data, type); + + if (!result) { + result = { + app: 'api', + status: 500, + error: 'Unknown server error' + }; + } + + response.status(result.status || 500).json(result); +}); + +/** + * [DELETE] + * Implementation of for: https://api.pretendo.cc/v1/connections/remove/TYPE + * Description: Removes an account connection from the users PNID + */ +router.delete('/remove/:type', async (request: express.Request, response: express.Response): Promise => { + const pnid = request.pnid; + const type = request.params.type; + + if (!pnid) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Invalid or missing access token' + }); + + return; + } + + if (!VALID_CONNECTION_TYPES.includes(type)) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Invalid or missing connection type' + }); + + return; + } + + let result = await removePNIDConnection(pnid, type); + + if (!result) { + result = { + app: 'api', + status: 500, + error: 'Unknown server error' + }; + } + + response.status(result.status).json(result); +}); + +export default router; \ No newline at end of file diff --git a/src/services/api/routes/v1/email.js b/src/services/api/routes/v1/email.js deleted file mode 100644 index 561e651..0000000 --- a/src/services/api/routes/v1/email.js +++ /dev/null @@ -1,42 +0,0 @@ -const router = require('express').Router(); -const moment = require('moment'); -const { PNID } = require('../../../../models/pnid'); -const util = require('../../../../util'); - -router.get('/verify', async (request, response) => { - const { token } = request.query; - - if (!token || token.trim() == '') { - return response.status(400).json({ - app: 'api', - status: 400, - error: 'Missing email token' - }); - } - - const pnid = await PNID.findOne({ - 'identification.email_token': token - }); - - if (!pnid) { - return response.status(400).json({ - app: 'api', - status: 400, - error: 'Invalid email token' - }); - } - - const validatedDate = moment().format('YYYY-MM-DDTHH:MM:SS'); - - pnid.set('email.reachable', true); - pnid.set('email.validated', true); - pnid.set('email.validated_date', validatedDate); - - await pnid.save(); - - await util.sendEmailConfirmedEmail(pnid); - - response.status(200).send('Email validated. You may close this window'); -}); - -module.exports = router; \ No newline at end of file diff --git a/src/services/api/routes/v1/email.ts b/src/services/api/routes/v1/email.ts new file mode 100644 index 0000000..fa306c5 --- /dev/null +++ b/src/services/api/routes/v1/email.ts @@ -0,0 +1,48 @@ +import express from 'express'; +import moment from 'moment'; +import { PNID } from '@/models/pnid'; +import { getValueFromQueryString, sendEmailConfirmedEmail } from '@/util'; + +const router = express.Router(); + +router.get('/verify', async (request: express.Request, response: express.Response): Promise => { + const token = getValueFromQueryString(request.query, 'token'); + + if (!token || token.trim() == '') { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Missing email token' + }); + + return; + } + + const pnid = await PNID.findOne({ + 'identification.email_token': token + }); + + if (!pnid) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Invalid email token' + }); + + return; + } + + const validatedDate = moment().format('YYYY-MM-DDTHH:MM:SS'); + + pnid.email.reachable = true; + pnid.email.validated = true; + pnid.email.validated_date = validatedDate; + + await pnid.save(); + + await sendEmailConfirmedEmail(pnid); + + response.status(200).send('Email validated. You may close this window'); +}); + +export default router; \ No newline at end of file diff --git a/src/services/api/routes/v1/forgotPassword.js b/src/services/api/routes/v1/forgotPassword.js deleted file mode 100644 index 7dd4948..0000000 --- a/src/services/api/routes/v1/forgotPassword.js +++ /dev/null @@ -1,36 +0,0 @@ -const router = require('express').Router(); -const validator = require('validator'); -const database = require('../../../../database'); -const util = require('../../../../util'); - -router.post('/', async (request, response) => { - const { body } = request; - const { input } = body; - - if (!input || input.trim() === '') { - return response.status(400).json({ - app: 'api', - status: 400, - error: 'Invalid or missing input' - }); - } - - let pnid; - - if (validator.isEmail(input)) { - pnid = await database.getUserByEmailAddress(input); - } else { - pnid = await database.getUserByUsername(input); - } - - if (pnid) { - await util.sendForgotPasswordEmail(pnid); - } - - response.json({ - app: 'api', - status: 200 - }); -}); - -module.exports = router; \ No newline at end of file diff --git a/src/services/api/routes/v1/forgotPassword.ts b/src/services/api/routes/v1/forgotPassword.ts new file mode 100644 index 0000000..99f127d --- /dev/null +++ b/src/services/api/routes/v1/forgotPassword.ts @@ -0,0 +1,70 @@ +import express from 'express'; +import validator from 'validator'; +import hcaptcha from 'hcaptcha'; +import { getPNIDByEmailAddress, getPNIDByUsername } from '@/database'; +import { sendForgotPasswordEmail } from '@/util'; +import { config, disabledFeatures } from '@/config-manager'; +import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; + +const router = express.Router(); + +router.post('/', async (request: express.Request, response: express.Response): Promise => { + const input = request.body?.input; + const hCaptchaResponse = request.body.hCaptchaResponse?.trim(); + + if (!disabledFeatures.captcha) { + if (!hCaptchaResponse || hCaptchaResponse === '') { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Must fill in captcha', + }); + + return; + } + + const captchaVerify = await hcaptcha.verify( + config.hcaptcha.secret, + hCaptchaResponse + ); + + if (!captchaVerify.success) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Captcha verification failed', + }); + + return; + } + } + + if (!input || input.trim() === '') { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Invalid or missing input' + }); + + return; + } + + let pnid: HydratedPNIDDocument | null; + + if (validator.isEmail(input)) { + pnid = await getPNIDByEmailAddress(input); + } else { + pnid = await getPNIDByUsername(input); + } + + if (pnid) { + await sendForgotPasswordEmail(pnid); + } + + response.json({ + app: 'api', + status: 200 + }); +}); + +export default router; \ No newline at end of file diff --git a/src/services/api/routes/v1/login.js b/src/services/api/routes/v1/login.js deleted file mode 100644 index e342ea5..0000000 --- a/src/services/api/routes/v1/login.js +++ /dev/null @@ -1,129 +0,0 @@ -const router = require('express').Router(); -const bcrypt = require('bcrypt'); -const fs = require('fs-extra'); -const database = require('../../../../database'); -const cache = require('../../../../cache'); -const util = require('../../../../util'); - -/** - * [POST] - * Implementation of for: https://api.pretendo.cc/v1/login - * Description: Generates an access token for an API user - * TODO: Replace this with a more robust OAuth2 implementation - */ -router.post('/', async (request, response) => { - const { body } = request; - const { grant_type, username, password, refresh_token } = body; - - if (!['password', 'refresh_token'].includes(grant_type)) { - return response.status(400).json({ - app: 'api', - status: 400, - error: 'Invalid grant type' - }); - } - - if (grant_type === 'password' && (!username || username.trim() === '')) { - return response.status(400).json({ - app: 'api', - status: 400, - error: 'Invalid or missing username' - }); - } - - if (grant_type === 'password' && (!password || password.trim() === '')) { - return response.status(400).json({ - app: 'api', - status: 400, - error: 'Invalid or missing password' - }); - } - - if (grant_type === 'refresh_token' && (!refresh_token || refresh_token.trim() === '')) { - return response.status(400).json({ - app: 'api', - status: 400, - error: 'Invalid or missing refresh token' - }); - } - - let pnid; - if (grant_type === 'password') { - pnid = await database.getUserByUsername(username); - if (!pnid) { - return response.status(400).json({ - app: 'api', - status: 400, - error: 'User not found' - }); - } - - const hashedPassword = util.nintendoPasswordHash(password, pnid.get('pid')); - - if (!pnid || !bcrypt.compareSync(hashedPassword, pnid.password)) { - return response.status(400).json({ - app: 'api', - status: 400, - error: 'Invalid or missing password' - }); - } - } else { - pnid = await database.getUserBearer(refresh_token); - if (!pnid) { - return response.status(400).json({ - app: 'api', - status: 400, - error: 'Invalid or missing refresh token' - }); - } - } - - const cryptoPath = `${__dirname}/../../../../../certs/service/account`; - - if (!await fs.pathExists(cryptoPath)) { - // Need to generate keys - return response.status(500).json({ - app: 'api', - status: 500, - error: 'Failed to locate crypto keys. Please contact an administrator' - }); - } - - const publicKey = await cache.getServicePublicKey('account'); - const secretKey = await cache.getServiceSecretKey('account'); - - const cryptoOptions = { - public_key: publicKey, - hmac_secret: secretKey - }; - - const accessTokenOptions = { - system_type: 0xF, // API - token_type: 0x1, // OAuth Access, - pid: pnid.get('pid'), - access_level: pnid.get('access_level'), - title_id: BigInt(0), - expire_time: BigInt(Date.now() + (3600 * 1000)) - }; - - const refreshTokenOptions = { - system_type: 0xF, // API - token_type: 0x2, // OAuth Refresh, - pid: pnid.get('pid'), - access_level: pnid.get('access_level'), - title_id: BigInt(0), - expire_time: BigInt(Date.now() + (3600 * 1000)) - }; - - const accessToken = await util.generateToken(cryptoOptions, accessTokenOptions); - const refreshToken = await util.generateToken(cryptoOptions, refreshTokenOptions); - - response.json({ - access_token: accessToken, - token_type: 'Bearer', - expires_in: 3600, - refresh_token: refreshToken - }); -}); - -module.exports = router; \ No newline at end of file diff --git a/src/services/api/routes/v1/login.ts b/src/services/api/routes/v1/login.ts new file mode 100644 index 0000000..7d778f2 --- /dev/null +++ b/src/services/api/routes/v1/login.ts @@ -0,0 +1,146 @@ +import express from 'express'; +import bcrypt from 'bcrypt'; +import { getPNIDByUsername, getPNIDByTokenAuth } from '@/database'; +import { nintendoPasswordHash, generateToken} from '@/util'; +import { config } from '@/config-manager'; +import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; + +const router = express.Router(); + +/** + * [POST] + * Implementation of for: https://api.pretendo.cc/v1/login + * Description: Generates an access token for an API user + * TODO: Replace this with a more robust OAuth2 implementation + */ +router.post('/', async (request: express.Request, response: express.Response): Promise => { + const grantType = request.body?.grant_type; + const username = request.body?.username; + const password = request.body?.password; + const refreshToken = request.body?.refresh_token; + + if (!['password', 'refresh_token'].includes(grantType)) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Invalid grant type' + }); + + return; + } + + if (grantType === 'password' && (!username || username.trim() === '')) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Invalid or missing username' + }); + + return; + } + + if (grantType === 'password' && (!password || password.trim() === '')) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Invalid or missing password' + }); + + return; + } + + if (grantType === 'refresh_token' && (!refreshToken || refreshToken.trim() === '')) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Invalid or missing refresh token' + }); + + return; + } + + let pnid: HydratedPNIDDocument | null; + + if (grantType === 'password') { + pnid = await getPNIDByUsername(username); + + if (!pnid) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'User not found' + }); + + return; + } + + const hashedPassword = nintendoPasswordHash(password, pnid.pid); + + if (!pnid || !bcrypt.compareSync(hashedPassword, pnid.password)) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Invalid or missing password' + }); + + return; + } + } else { + pnid = await getPNIDByTokenAuth(refreshToken); + + if (!pnid) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Invalid or missing refresh token' + }); + + return; + } + } + + if (pnid.deleted) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'User not found' + }); + + return; + } + + const accessTokenOptions = { + system_type: 0x3, // * API + token_type: 0x1, // * OAuth Access + pid: pnid.pid, + access_level: pnid.access_level, + title_id: BigInt(0), + expire_time: BigInt(Date.now() + (3600 * 1000)) + }; + + const refreshTokenOptions = { + system_type: 0x3, // * API + token_type: 0x2, // * OAuth Refresh + pid: pnid.pid, + access_level: pnid.access_level, + title_id: BigInt(0), + expire_time: BigInt(Date.now() + (3600 * 1000)) + }; + + const accessTokenBuffer = await generateToken(config.aes_key, accessTokenOptions); + const refreshTokenBuffer = await generateToken(config.aes_key, refreshTokenOptions); + + const accessToken = accessTokenBuffer ? accessTokenBuffer.toString('hex') : ''; + const newRefreshToken = refreshTokenBuffer ? refreshTokenBuffer.toString('hex') : ''; + + // TODO - Handle null tokens + + response.json({ + access_token: accessToken, + token_type: 'Bearer', + expires_in: 3600, + refresh_token: newRefreshToken + }); +}); + +export default router; \ No newline at end of file diff --git a/src/services/api/routes/v1/register.js b/src/services/api/routes/v1/register.ts similarity index 53% rename from src/services/api/routes/v1/register.js rename to src/services/api/routes/v1/register.ts index 729bc41..3bf0cad 100644 --- a/src/services/api/routes/v1/register.js +++ b/src/services/api/routes/v1/register.ts @@ -1,28 +1,31 @@ -const router = require('express').Router(); -const emailvalidator = require('email-validator'); -const fs = require('fs-extra'); -const moment = require('moment'); -const crypto = require('crypto'); -const hcaptcha = require('hcaptcha'); -const bcrypt = require('bcrypt'); -const Mii = require('mii-js'); -const { PNID } = require('../../../../models/pnid'); -const { NEXAccount } = require('../../../../models/nex-account'); -const database = require('../../../../database'); -const cache = require('../../../../cache'); -const util = require('../../../../util'); -const logger = require('../../../../../logger'); -const { config, disabledFeatures } = require('../../../../config-manager'); -const PNID_VALID_CHARACTERS_REGEX = /^[\w\-\.]*$/gm; -const PNID_PUNCTUATION_START_REGEX = /^[\_\-\.]/gm; -const PNID_PUNCTUATION_END_REGEX = /[\_\-\.]$/gm; -const PNID_PUNCTUATION_DUPLICATE_REGEX = /[\_\-\.]{2,}/gm; +import crypto from 'node:crypto'; +import express from 'express'; +import emailvalidator from 'email-validator'; +import bcrypt from 'bcrypt'; +import moment from 'moment'; +import hcaptcha from 'hcaptcha'; +import Mii from 'mii-js'; +import { doesPNIDExist, connection as databaseConnection } from '@/database'; +import { nintendoPasswordHash, sendConfirmationEmail, generateToken } from '@/util'; +import { LOG_ERROR } from '@/logger'; +import { PNID } from '@/models/pnid'; +import { NEXAccount } from '@/models/nex-account'; +import { config, disabledFeatures } from '@/config-manager'; +import { HydratedNEXAccountDocument } from '@/types/mongoose/nex-account'; +import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; -// This sucks +const router = express.Router(); + +const PNID_VALID_CHARACTERS_REGEX = /^[\w\-.]*$/; +const PNID_PUNCTUATION_START_REGEX = /^[_\-.]/; +const PNID_PUNCTUATION_END_REGEX = /[_\-.]$/; +const PNID_PUNCTUATION_DUPLICATE_REGEX = /[_\-.]{2,}/; + +// * This sucks const PASSWORD_WORD_OR_NUMBER_REGEX = /(?=.*[a-zA-Z])(?=.*\d).*/; -const PASSWORD_WORD_OR_PUNCTUATION_REGEX = /(?=.*[a-zA-Z])(?=.*[\_\-\.]).*/; -const PASSWORD_NUMBER_OR_PUNCTUATION_REGEX = /(?=.*\d)(?=.*[\_\-\.]).*/; +const PASSWORD_WORD_OR_PUNCTUATION_REGEX = /(?=.*[a-zA-Z])(?=.*[_\-.]).*/; +const PASSWORD_NUMBER_OR_PUNCTUATION_REGEX = /(?=.*\d)(?=.*[_\-.]).*/; const PASSWORD_REPEATED_CHARACTER_REGEX = /(.)\1\1/; const DEFAULT_MII_DATA = Buffer.from('AwAAQOlVognnx0GC2/uogAOzuI0n2QAAAEBEAGUAZgBhAHUAbAB0AAAAAAAAAEBAAAAhAQJoRBgmNEYUgRIXaA0AACkAUkhQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGm9', 'base64'); @@ -32,201 +35,241 @@ const DEFAULT_MII_DATA = Buffer.from('AwAAQOlVognnx0GC2/uogAOzuI0n2QAAAEBEAGUAZg * Implementation of: https://api.pretendo.cc/v1/register * Description: Creates a new user PNID */ -router.post('/', async (request, response) => { - const { body } = request; - - const email = body.email?.trim(); - const username = body.username?.trim(); - const miiName = body.mii_name?.trim(); - const password = body.password?.trim(); - const passwordConfirm = body.password_confirm?.trim(); - const hCaptchaResponse = body.hCaptchaResponse?.trim(); +router.post('/', async (request: express.Request, response: express.Response): Promise => { + const email = request.body.email?.trim(); + const username = request.body.username?.trim(); + const miiName = request.body.mii_name?.trim(); + const password = request.body.password?.trim(); + const passwordConfirm = request.body.password_confirm?.trim(); + const hCaptchaResponse = request.body.hCaptchaResponse?.trim(); if (!disabledFeatures.captcha) { if (!hCaptchaResponse || hCaptchaResponse === '') { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Must fill in captcha' }); + + return; } const captchaVerify = await hcaptcha.verify(config.hcaptcha.secret, hCaptchaResponse); if (!captchaVerify.success) { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Captcha verification failed' }); + + return; } } if (!email || email === '') { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Must enter an email address' }); + + return; } if (!emailvalidator.validate(email)) { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Invalid email address' }); + + return; } if (!username || username === '') { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Must enter a username' }); + + return; } if (username.length < 6) { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Username is too short' }); + + return; } if (username.length > 16) { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Username is too long' }); + + return; } if (!PNID_VALID_CHARACTERS_REGEX.test(username)) { console.log(Buffer.from(username)); - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Username contains invalid characters' }); + + return; } if (PNID_PUNCTUATION_START_REGEX.test(username)) { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Username cannot begin with punctuation characters' }); + + return; } if (PNID_PUNCTUATION_END_REGEX.test(username)) { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Username cannot end with punctuation characters' }); + + return; } if (PNID_PUNCTUATION_DUPLICATE_REGEX.test(username)) { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Two or more punctuation characters cannot be used in a row' }); + + return; } - const userExists = await database.doesUserExist(username); + const userExists = await doesPNIDExist(username); if (userExists) { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'PNID already in use' }); + + return; } if (!miiName || miiName === '') { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Must enter a Mii name' }); + + return; } if (!password || password === '') { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Must enter a password' }); + + return; } if (password.length < 6) { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Password is too short' }); + + return; } if (password.length > 16) { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Password is too long' }); + + return; } if (password.toLowerCase() === username.toLowerCase()) { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Password cannot be the same as username' }); + + return; } if (!PASSWORD_WORD_OR_NUMBER_REGEX.test(password) && !PASSWORD_WORD_OR_PUNCTUATION_REGEX.test(password) && !PASSWORD_NUMBER_OR_PUNCTUATION_REGEX.test(password)) { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Password must have combination of letters, numbers, and/or punctuation characters' }); + + return; } if (PASSWORD_REPEATED_CHARACTER_REGEX.test(password)) { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Password may not have 3 repeating characters' }); + + return; } if (password !== passwordConfirm) { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Passwords do not match' }); + + return; } - const miiNameBuffer = Buffer.from(miiName, 'utf16le'); // UTF8 to UTF16 + const miiNameBuffer = Buffer.from(miiName, 'utf16le'); // * UTF8 to UTF16 if (miiNameBuffer.length > 0x14) { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Mii name too long' }); + + return; } const mii = new Mii(DEFAULT_MII_DATA); mii.miiName = miiName; const creationDate = moment().format('YYYY-MM-DDTHH:MM:SS'); - let pnid; - let nexAccount; + let pnid: HydratedPNIDDocument; + let nexAccount: HydratedNEXAccountDocument; - const session = await database.connection.startSession(); + const session = await databaseConnection().startSession(); await session.startTransaction(); try { @@ -239,59 +282,59 @@ router.post('/', async (request, response) => { await nexAccount.generatePID(); await nexAccount.generatePassword(); - // Quick hack to get the PIDs to match - // TODO: Change this maybe? - // NN with a NNID will always use the NNID PID - // even if the provided NEX PID is different - // To fix this we make them the same PID - nexAccount.owning_pid = nexAccount.get('pid'); + // * Quick hack to get the PIDs to match + // TODO - Change this maybe? + // * NN with a NNID will always use the NNID PID + // * even if the provided NEX PID is different + // * To fix this we make them the same PID + nexAccount.owning_pid = nexAccount.pid; await nexAccount.save({ session }); - const primaryPasswordHash = util.nintendoPasswordHash(password, nexAccount.get('pid')); + const primaryPasswordHash = nintendoPasswordHash(password, nexAccount.pid); const passwordHash = await bcrypt.hash(primaryPasswordHash, 10); pnid = new PNID({ - pid: nexAccount.get('pid'), + pid: nexAccount.pid, creation_date: creationDate, updated: creationDate, username: username, usernameLower: username.toLowerCase(), password: passwordHash, - birthdate: '1990-01-01', // TODO: Change this - gender: 'M', // TODO: Change this - country: 'US', // TODO: Change this - language: 'en', // TODO: Change this + birthdate: '1990-01-01', // TODO - Change this + gender: 'M', // TODO - Change this + country: 'US', // TODO - Change this + language: 'en', // TODO - Change this email: { address: email.toLowerCase(), - primary: true, // TODO: Change this - parent: true, // TODO: Change this - reachable: false, // TODO: Change this - validated: false, // TODO: Change this + primary: true, // TODO - Change this + parent: true, // TODO - Change this + reachable: false, // TODO - Change this + validated: false, // TODO - Change this id: crypto.randomBytes(4).readUInt32LE() }, - region: 0x310B0000, // TODO: Change this + region: 0x310B0000, // TODO - Change this timezone: { - name: 'America/New_York', // TODO: Change this - offset: -14400 // TODO: Change this + name: 'America/New_York', // TODO - Change this + offset: -14400 // TODO - Change this }, mii: { name: miiName, - primary: true, // TODO: Change this + primary: true, // TODO - Change this data: mii.encode().toString('base64'), id: crypto.randomBytes(4).readUInt32LE(), hash: crypto.randomBytes(7).toString('hex'), - image_url: '', // deprecated, will be removed in the future + image_url: '', // * deprecated, will be removed in the future image_id: crypto.randomBytes(4).readUInt32LE() }, flags: { - active: true, // TODO: Change this - marketing: true, // TODO: Change this - off_device: true // TODO: Change this + active: true, // TODO - Change this + marketing: true, // TODO - Change this + off_device: true // TODO - Change this }, identification: { - email_code: 1, // will be overwritten before saving - email_token: '' // will be overwritten before saving + email_code: 1, // * will be overwritten before saving + email_token: '' // * will be overwritten before saving } }); @@ -302,63 +345,52 @@ router.post('/', async (request, response) => { await pnid.save({ session }); await session.commitTransaction(); - } catch (error) { - logger.error('[POST] /v1/register: ' + error); + } catch (error: any) { + LOG_ERROR('[POST] /v1/register: ' + error); + if (error.stack) console.error(error.stack); await session.abortTransaction(); - return response.status(400).json({ + response.status(500).json({ app: 'api', - status: 400, - error: 'Password must have combination of letters, numbers, and/or punctuation characters' + status: 500, + error: 'Internal server error' }); + + return; } finally { // * This runs regardless of failure // * Returning on catch will not prevent this from running await session.endSession(); } - await util.sendConfirmationEmail(pnid); - - const cryptoPath = `${__dirname}/../../../../../certs/service/account`; - - if (!await fs.pathExists(cryptoPath)) { - // Need to generate keys - return response.status(500).json({ - app: 'api', - status: 500, - error: 'Failed to locate crypto keys. Please contact an administrator' - }); - } - - const publicKey = await cache.getServicePublicKey('account'); - const secretKey = await cache.getServiceSecretKey('account'); - - const cryptoOptions = { - public_key: publicKey, - hmac_secret: secretKey - }; + await sendConfirmationEmail(pnid); const accessTokenOptions = { - system_type: 0xF, // API - token_type: 0x1, // OAuth Access, - pid: pnid.get('pid'), - access_level: 0, + system_type: 0x3, // * API + token_type: 0x1, // * OAuth Access + pid: pnid.pid, + access_level: pnid.access_level, title_id: BigInt(0), expire_time: BigInt(Date.now() + (3600 * 1000)) }; const refreshTokenOptions = { - system_type: 0xF, // API - token_type: 0x2, // OAuth Refresh, - pid: pnid.get('pid'), - access_level: 0, + system_type: 0x3, // * API + token_type: 0x2, // * OAuth Refresh + pid: pnid.pid, + access_level: pnid.access_level, title_id: BigInt(0), expire_time: BigInt(Date.now() + (3600 * 1000)) }; - const accessToken = await util.generateToken(cryptoOptions, accessTokenOptions); - const refreshToken = await util.generateToken(cryptoOptions, refreshTokenOptions); + const accessTokenBuffer = await generateToken(config.aes_key, accessTokenOptions); + const refreshTokenBuffer = await generateToken(config.aes_key, refreshTokenOptions); + + const accessToken = accessTokenBuffer ? accessTokenBuffer.toString('hex') : ''; + const refreshToken = refreshTokenBuffer ? refreshTokenBuffer.toString('hex') : ''; + + // TODO - Handle null tokens response.json({ access_token: accessToken, @@ -368,4 +400,4 @@ router.post('/', async (request, response) => { }); }); -module.exports = router; \ No newline at end of file +export default router; \ No newline at end of file diff --git a/src/services/api/routes/v1/resetPassword.js b/src/services/api/routes/v1/resetPassword.ts similarity index 57% rename from src/services/api/routes/v1/resetPassword.js rename to src/services/api/routes/v1/resetPassword.ts index 8afb3b1..ad401fb 100644 --- a/src/services/api/routes/v1/resetPassword.js +++ b/src/services/api/routes/v1/resetPassword.ts @@ -1,117 +1,140 @@ -const router = require('express').Router(); -const bcrypt = require('bcrypt'); -const { PNID } = require('../../../../models/pnid'); -const util = require('../../../../util'); +import express from 'express'; +import bcrypt from 'bcrypt'; +import { PNID } from '@/models/pnid'; +import { decryptToken, unpackToken, nintendoPasswordHash } from '@/util'; +import { Token } from '@/types/common/token'; -// This sucks +const router = express.Router(); + +// * This sucks const PASSWORD_WORD_OR_NUMBER_REGEX = /(?=.*[a-zA-Z])(?=.*\d).*/; -const PASSWORD_WORD_OR_PUNCTUATION_REGEX = /(?=.*[a-zA-Z])(?=.*[\_\-\.]).*/; -const PASSWORD_NUMBER_OR_PUNCTUATION_REGEX = /(?=.*\d)(?=.*[\_\-\.]).*/; +const PASSWORD_WORD_OR_PUNCTUATION_REGEX = /(?=.*[a-zA-Z])(?=.*[_\-.]).*/; +const PASSWORD_NUMBER_OR_PUNCTUATION_REGEX = /(?=.*\d)(?=.*[_\-.]).*/; const PASSWORD_REPEATED_CHARACTER_REGEX = /(.)\1\1/; -router.post('/', async (request, response) => { - const { body } = request; - const password = body.password?.trim(); - const passwordConfirm = body.password_confirm?.trim(); - const token = body.token?.trim(); +router.post('/', async (request: express.Request, response: express.Response): Promise => { + const password = request.body.password?.trim(); + const passwordConfirm = request.body.password_confirm?.trim(); + const token = request.body.token?.trim(); if (!token || token === '') { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Missing token' }); + + return; } - let unpackedToken; + let unpackedToken: Token; try { - const decryptedToken = await util.decryptToken(Buffer.from(token, 'base64')); - unpackedToken = util.unpackToken(decryptedToken); + const decryptedToken = await decryptToken(Buffer.from(token, 'hex')); + unpackedToken = unpackToken(decryptedToken); } catch (error) { - console.log(error); - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Invalid token' }); + + return; } if (unpackedToken.expire_time < Date.now()) { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Token expired' }); + + return; } const pnid = await PNID.findOne({ pid: unpackedToken.pid }); if (!pnid) { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Invalid token. No user found' }); + + return; } if (!password || password === '') { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Must enter a password' }); + + return; } if (password.length < 6) { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Password is too short' }); + + return; } if (password.length > 16) { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Password is too long' }); + + return; } - if (password.toLowerCase() === pnid.get('usernameLower')) { - return response.status(400).json({ + if (password.toLowerCase() === pnid.usernameLower) { + response.status(400).json({ app: 'api', status: 400, error: 'Password cannot be the same as username' }); + + return; } if (!PASSWORD_WORD_OR_NUMBER_REGEX.test(password) && !PASSWORD_WORD_OR_PUNCTUATION_REGEX.test(password) && !PASSWORD_NUMBER_OR_PUNCTUATION_REGEX.test(password)) { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Password must have combination of letters, numbers, and/or punctuation characters' }); + + return; } if (PASSWORD_REPEATED_CHARACTER_REGEX.test(password)) { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Password may not have 3 repeating characters' }); + + return; } if (password !== passwordConfirm) { - return response.status(400).json({ + response.status(400).json({ app: 'api', status: 400, error: 'Passwords do not match' }); + + return; } - const primaryPasswordHash = util.nintendoPasswordHash(password, pnid.get('pid')); + const primaryPasswordHash = nintendoPasswordHash(password, pnid.pid); const passwordHash = await bcrypt.hash(primaryPasswordHash, 10); pnid.password = passwordHash; @@ -124,4 +147,4 @@ router.post('/', async (request, response) => { }); }); -module.exports = router; \ No newline at end of file +export default router; \ No newline at end of file diff --git a/src/services/api/routes/v1/user.js b/src/services/api/routes/v1/user.js deleted file mode 100644 index 7008548..0000000 --- a/src/services/api/routes/v1/user.js +++ /dev/null @@ -1,127 +0,0 @@ -const router = require('express').Router(); -const joi = require('joi'); -const { PNID } = require('../../../../models/pnid'); -const { config } = require('../../../../config-manager'); - -// TODO: Extend this later with more settings -const userSchema = joi.object({ - mii: joi.object({ - name: joi.string(), - primary: joi.string(), - data: joi.string(), - }) -}); - -/** - * [GET] - * Implementation of for: https://api.pretendo.cc/v1/user - * Description: Gets PNID details about the current user - */ -router.get('/', async (request, response) => { - const { pnid } = request; - - if (!pnid) { - return response.status(400).json({ - app: 'api', - status: 400, - error: 'Invalid or missing access token' - }); - } - - return response.json({ - access_level: pnid.get('access_level'), - server_access_level: pnid.get('server_access_level'), - pid: pnid.get('pid'), - creation_date: pnid.get('creation_date'), - updated: pnid.get('updated'), - username: pnid.get('username'), - birthdate: pnid.get('birthdate'), - gender: pnid.get('gender'), - country: pnid.get('country'), - email: { - address: pnid.get('email.address'), - }, - timezone: { - name: pnid.get('timezone.name') - }, - mii: { - data: pnid.get('mii.data'), - name: pnid.get('mii.name'), - image_url: `${config.cdn.base_url}/mii/${pnid.get('pid')}/normal_face.png` - }, - flags: { - marketing: pnid.get('flags.marketing') - }, - connections: { - discord: { - id: pnid.get('connections.discord.id') - } - } - }); -}); - -/** - * [POST] - * Implementation of for: https://api.pretendo.cc/v1/user - * Description: Updates PNID certain details about the current user - */ -router.post('/', async (request, response) => { - const { body, pnid } = request; - - if (!pnid) { - return response.status(400).json({ - app: 'api', - status: 400, - error: 'Invalid or missing access token' - }); - } - - const valid = userSchema.validate(body); - - if (valid.error) { - return response.status(400).json({ - app: 'api', - status: 400, - error: valid.error - }); - } - - const { pid } = pnid; - - const updateData = {}; - - await PNID.updateOne({ pid }, { $set: updateData }).exec(); - - return response.json({ - access_level: pnid.get('access_level'), - server_access_level: pnid.get('server_access_level'), - pid: pnid.get('pid'), - creation_date: pnid.get('creation_date'), - updated: pnid.get('updated'), - username: pnid.get('username'), - birthdate: pnid.get('birthdate'), - gender: pnid.get('gender'), - country: pnid.get('country'), - email: { - address: pnid.get('email.address'), - }, - timezone: { - name: pnid.get('timezone.name') - }, - mii: { - data: pnid.get('mii.data'), - name: pnid.get('mii.name'), - image_url: `${config.cdn.base_url}/mii/${pnid.get('pid')}/normal_face.png` - }, - flags: { - marketing: pnid.get('flags.marketing') - }, - connections: { - discord: { - id: pnid.get('connections.discord.id') - } - } - }); -}); - -module.exports = router; \ No newline at end of file diff --git a/src/services/api/routes/v1/user.ts b/src/services/api/routes/v1/user.ts new file mode 100644 index 0000000..f024551 --- /dev/null +++ b/src/services/api/routes/v1/user.ts @@ -0,0 +1,232 @@ +import express from 'express'; +import { z } from 'zod'; +import Mii from 'mii-js'; +import { config } from '@/config-manager'; +import { PNID } from '@/models/pnid'; +import { UpdateUserRequest } from '@/types/services/api/update-user-request'; + +const router = express.Router(); + +// TODO - Extend this later with more settings +const userSchema = z.object({ + mii: z.object({ + name: z.string().trim(), + primary: z.enum(['Y', 'N']), + data: z.string(), + }).optional(), + environment: z.enum(['prod', 'test', 'dev']).optional() +}); + +/** + * [GET] + * Implementation of for: https://api.pretendo.cc/v1/user + * Description: Gets PNID details about the current user + */ +router.get('/', async (request: express.Request, response: express.Response): Promise => { + const pnid = request.pnid; + + if (!pnid) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Invalid or missing access token' + }); + + return; + } + + response.json({ + access_level: pnid.access_level, + server_access_level: pnid.server_access_level, + pid: pnid.pid, + creation_date: pnid.creation_date, + updated: pnid.updated, + username: pnid.username, + birthdate: pnid.birthdate, + gender: pnid.gender, + country: pnid.country, + email: { + address: pnid.email.address, + }, + timezone: { + name: pnid.timezone.name + }, + mii: { + data: pnid.mii.data, + name: pnid.mii.name, + image_url: `${config.cdn.base_url}/mii/${pnid.pid}/normal_face.png` + }, + flags: { + marketing: pnid.flags.marketing + }, + connections: { + discord: { + id: pnid.connections.discord.id + }, + stripe: { + tier_name: pnid.connections.stripe.tier_name, + tier_level: pnid.connections.stripe.tier_level + } + } + }); +}); + +/** + * [POST] + * Implementation of for: https://api.pretendo.cc/v1/user + * Description: Updates PNID certain details about the current user + */ +router.post('/', async (request: express.Request, response: express.Response): Promise => { + const pnid = request.pnid; + const updateUserRequest: UpdateUserRequest = request.body; + + if (!pnid) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Invalid or missing access token' + }); + + return; + } + + const result = userSchema.safeParse(updateUserRequest); + + if (!result.success) { + response.status(400).json({ + app: 'api', + status: 400, + error: result.error + }); + + return; + } + + if (result.data.mii) { + const miiNameBuffer = Buffer.from(result.data.mii.name, 'utf16le'); // * UTF8 to UTF16 + + if (miiNameBuffer.length < 1) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Mii name too short' + }); + + return; + } + + if (miiNameBuffer.length > 0x14) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Mii name too long' + }); + + return; + } + + try { + const miiDataBuffer = Buffer.from(result.data.mii.data, 'base64'); + + if (miiDataBuffer.length < 0x60) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Mii data too short' + }); + + return; + } + + if (miiDataBuffer.length > 0x60) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Mii data too long' + }); + + return; + } + + const mii = new Mii(miiDataBuffer); + mii.validate(); + } catch (_) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Failed to decode Mii data' + }); + + return; + } + + await pnid.updateMii({ + name: result.data.mii.name, + primary: result.data.mii.primary, + data: result.data.mii.data + }); + } + + const updateData: Record = {}; + + if (result.data.environment) { + const environment = result.data.environment; + + if (environment === 'test' && pnid.access_level < 1) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Do not have permission to enter this environment' + }); + + return; + } + + if (environment === 'dev' && pnid.access_level < 3) { + response.status(400).json({ + app: 'api', + status: 400, + error: 'Do not have permission to enter this environment' + }); + + return; + } + + updateData.server_access_level = environment; + } + + await PNID.updateOne({ pid: pnid.pid }, { $set: updateData }).exec(); + + response.json({ + access_level: pnid.access_level, + server_access_level: pnid.server_access_level, + pid: pnid.pid, + creation_date: pnid.creation_date, + updated: pnid.updated, + username: pnid.username, + birthdate: pnid.birthdate, + gender: pnid.gender, + country: pnid.country, + email: { + address: pnid.email.address, + }, + timezone: { + name: pnid.timezone.name + }, + mii: { + data: pnid.mii.data, + name: pnid.mii.name, + image_url: `${config.cdn.base_url}/mii/${pnid.pid}/normal_face.png` + }, + flags: { + marketing: pnid.flags.marketing + }, + connections: { + discord: { + id: pnid.connections.discord.id + } + } + }); +}); + +export default router; \ No newline at end of file diff --git a/src/services/assets/index.js b/src/services/assets/index.js deleted file mode 100644 index 2059739..0000000 --- a/src/services/assets/index.js +++ /dev/null @@ -1,22 +0,0 @@ -// handles serving assets - -const express = require('express'); -const subdomain = require('express-subdomain'); -const logger = require('../../../logger'); -const path = require('path'); - -// Router to handle the subdomain restriction -const assets = express.Router(); - -// Setup public folder -logger.info('[assets] Setting up public folder'); -assets.use(express.static(path.join(__dirname, '../../assets'))); - -// Main router for endpoints -const router = express.Router(); - -// Create subdomains -logger.info('[conntest] Creating \'assets\' subdomain'); -router.use(subdomain('assets', assets)); - -module.exports = router; \ No newline at end of file diff --git a/src/services/assets/index.ts b/src/services/assets/index.ts new file mode 100644 index 0000000..72d1a52 --- /dev/null +++ b/src/services/assets/index.ts @@ -0,0 +1,23 @@ +// * handles serving assets + +import path from 'node:path'; +import express from 'express'; +import { LOG_INFO, formatHostnames } from '@/logger'; +import { config } from '@/config-manager'; +import { restrictHostnames } from '@/middleware/host-limit'; + +// * Router to handle the subdomain restriction +const assets = express.Router(); + +// * Setup public folder +LOG_INFO('[assets] Setting up public folder'); +assets.use(express.static(path.join(__dirname, '../../assets'))); + +// * Main router for endpoints +const router = express.Router(); + +// * Create domains +LOG_INFO(`[assets] Creating assets router with domains: ${formatHostnames(config.domains.assets)}`); +router.use(restrictHostnames(config.domains.assets, assets)); + +export default router; \ No newline at end of file diff --git a/src/services/cbvc/index.ts b/src/services/cbvc/index.ts new file mode 100644 index 0000000..79cd3c4 --- /dev/null +++ b/src/services/cbvc/index.ts @@ -0,0 +1,32 @@ +// * handles CBVC (CTR Browser Version Check?) endpoints + +import express from 'express'; +import { LOG_INFO, formatHostnames } from '@/logger'; +import { config } from '@/config-manager'; +import { restrictHostnames } from '@/middleware/host-limit'; + +// * Router to handle the subdomain restriction +const cbvc = express.Router(); + +// * Setup route +LOG_INFO('[CBVC] Applying imported routes'); +cbvc.get('/:consoleType/:unknown/:region', (request: express.Request, response: express.Response): void => { + response.set('Content-Type', 'text/plain'); + + // * https://www.3dbrew.org/wiki/Internet_Browser#Forced_system-update + // * The returned value is a number which the Internet Browser then compares + // * with its own version number. If the version number isn't higher than the + // * returned value, it will show a console update message. + // * + // * Return 0 and allow any browser to connect. + response.send('0'); +}); + +// * Main router for endpoints +const router = express.Router(); + +// * Create domains +LOG_INFO(`[CBVC] Creating cbvc router with domains: ${formatHostnames(config.domains.cbvc)}`); +router.use(restrictHostnames(config.domains.cbvc, cbvc)); + +export default router; diff --git a/src/services/conntest/index.js b/src/services/conntest/index.js deleted file mode 100644 index ebe2515..0000000 --- a/src/services/conntest/index.js +++ /dev/null @@ -1,36 +0,0 @@ -// handles conntest endpoints - -const express = require('express'); -const subdomain = require('express-subdomain'); -const logger = require('../../../logger'); - -// Router to handle the subdomain restriction -const conntest = express.Router(); - -// Setup route -logger.info('[conntest] Applying imported routes'); -conntest.get('/', async (request, response) => { - response.set('Content-Type', 'text/html'); - response.set('X-Organization', 'Nintendo'); - - response.send(` - - - -HTML Page - - -This is test.html page - - -`) -}); - -// Main router for endpoints -const router = express.Router(); - -// Create subdomains -logger.info('[conntest] Creating \'conntest\' subdomain'); -router.use(subdomain('conntest', conntest)); - -module.exports = router; \ No newline at end of file diff --git a/src/services/conntest/index.ts b/src/services/conntest/index.ts new file mode 100644 index 0000000..738ad41 --- /dev/null +++ b/src/services/conntest/index.ts @@ -0,0 +1,37 @@ +// * handles conntest endpoints + +import express from 'express'; +import { LOG_INFO, formatHostnames } from '@/logger'; +import { restrictHostnames } from '@/middleware/host-limit'; +import { config } from '@/config-manager'; + +// * Router to handle the subdomain restriction +const conntest = express.Router(); + +// * Setup route +LOG_INFO('[conntest] Applying imported routes'); +conntest.get('/', (request: express.Request, response: express.Response): void => { + response.set('Content-Type', 'text/html'); + response.set('X-Organization', 'Nintendo'); + + response.send(` + + + +HTML Page + + +This is test.html page + + +`); +}); + +// * Main router for endpoints +const router = express.Router(); + +// * Create domains +LOG_INFO(`[conntest] Creating conntest router with domains: ${formatHostnames(config.domains.conntest)}`); +router.use(restrictHostnames(config.domains.conntest, conntest)); + +export default router; \ No newline at end of file diff --git a/src/services/datastore/index.js b/src/services/datastore/index.js deleted file mode 100644 index ab263d2..0000000 --- a/src/services/datastore/index.js +++ /dev/null @@ -1,20 +0,0 @@ -const express = require('express'); -const subdomain = require('express-subdomain'); -const logger = require('../../../logger'); -const routes = require('./routes'); - -// Router to handle the subdomain -const datastore = express.Router(); - -// Setup routes -logger.info('[DATASTORE] Applying imported routes'); -datastore.use(routes.UPLOAD); - -// Main router for endpoints -const router = express.Router(); - -// Create subdomains -logger.info('[DATASTORE] Creating \'datastore\' subdomain'); -router.use(subdomain('datastore', datastore)); - -module.exports = router; \ No newline at end of file diff --git a/src/services/datastore/index.ts b/src/services/datastore/index.ts new file mode 100644 index 0000000..296547d --- /dev/null +++ b/src/services/datastore/index.ts @@ -0,0 +1,22 @@ +import express from 'express'; +import { LOG_INFO, formatHostnames } from '@/logger'; + +import upload from '@/services/datastore/routes/upload'; +import { restrictHostnames } from '@/middleware/host-limit'; +import { config } from '@/config-manager'; + +// * Router to handle the subdomain +const datastore = express.Router(); + +// * Setup routes +LOG_INFO('[DATASTORE] Applying imported routes'); +datastore.use(upload); + +// * Main router for endpoints +const router = express.Router(); + +// * Create domains +LOG_INFO(`[DATASTORE] Creating datastore router with domains: ${formatHostnames(config.domains.datastore)}`); +router.use(restrictHostnames(config.domains.datastore, datastore)); + +export default router; \ No newline at end of file diff --git a/src/services/datastore/routes/index.js b/src/services/datastore/routes/index.js deleted file mode 100644 index 34215ff..0000000 --- a/src/services/datastore/routes/index.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - UPLOAD: require('./upload.js'), -}; \ No newline at end of file diff --git a/src/services/datastore/routes/upload.js b/src/services/datastore/routes/upload.js deleted file mode 100644 index 18f13b6..0000000 --- a/src/services/datastore/routes/upload.js +++ /dev/null @@ -1,74 +0,0 @@ -const crypto = require('crypto'); -const router = require('express').Router(); -const Dicer = require('dicer'); -const fs = require('fs'); -const util = require('../../../util'); - -const signatureSecret = fs.readFileSync(`${__dirname}/../../../../certs/nex/datastore/secret.key`); - -function multipartParser(request, response, next) { - const RE_BOUNDARY = /^multipart\/.+?(?:; boundary=(?:(?:"(.+)")|(?:([^\s]+))))$/i; - const RE_FILE_NAME = /name="(.*)"/; - const boundary = RE_BOUNDARY.exec(request.header('content-type')); - const dicer = new Dicer({ boundary: boundary[1] || boundary[2] }); - const files = {}; - - dicer.on('part', part => { - let fileBuffer = Buffer.alloc(0); - let fileName = ''; - - part.on('header', header => { - fileName = RE_FILE_NAME.exec(header['content-disposition'][0])[1]; - }); - - part.on('data', data => { - fileBuffer = Buffer.concat([fileBuffer, data]); - }); - - part.on('end', () => { - files[fileName] = fileBuffer; - }); - }); - - dicer.on('finish', function () { - request.files = files; - return next(); - }); - - request.pipe(dicer); -} - -router.post('/upload', multipartParser, async (request, response) => { - const { - bucket, // Space name - key, // path - file, // the file content - acl, // S3 ACL - pid, // uploading user PID - date, // upload time - signature, // data signature - } = request.files; - - // Signatures only good for 1 minute - const minute = 1000 * 60; - const minuteAgo = Date.now() - minute; - - if (Number(date) < Math.floor(minuteAgo / 1000)) { - return response.sendStatus(400); - } - - const data = pid.toString() + bucket.toString() + key.toString() + date.toString(); - - const hmac = crypto.createHmac('sha256', signatureSecret).update(data).digest('hex'); - - console.log(hmac, signature.toString()); - - if (hmac !== signature.toString()) { - return response.sendStatus(400); - } - - await util.uploadCDNAsset(bucket.toString(), key.toString(), file, acl.toString()); - response.sendStatus(200); -}); - -module.exports = router; \ No newline at end of file diff --git a/src/services/datastore/routes/upload.ts b/src/services/datastore/routes/upload.ts new file mode 100644 index 0000000..9827781 --- /dev/null +++ b/src/services/datastore/routes/upload.ts @@ -0,0 +1,100 @@ +import crypto from 'node:crypto'; +import express from 'express'; +import Dicer from 'dicer'; +import { uploadCDNAsset } from '@/util'; +import { config } from '@/config-manager'; + +const router = express.Router(); + +function multipartParser(request: express.Request, response: express.Response, next: express.NextFunction): void { + const RE_BOUNDARY = /^multipart\/.+?(?:; boundary=(?:(?:"(.+)")|(?:([^\s]+))))$/i; + const RE_FILE_NAME = /name="(.*)"/; + + const contentType = request.header('content-type'); + + if (!contentType) { + return next(); + } + + const boundary = RE_BOUNDARY.exec(contentType); + + if (!boundary) { + return next(); + } + + const dicer = new Dicer({ boundary: boundary[1] || boundary[2] }); + const files: Record = {}; + + dicer.on('part', (part: Dicer.PartStream) => { + let fileBuffer = Buffer.alloc(0); + let fileName = ''; + + part.on('header', header => { + const contentDisposition = header['content-disposition' as keyof object]; + const regexResult = RE_FILE_NAME.exec(contentDisposition); + + if (regexResult) { + fileName = regexResult[0]; + } + }); + + part.on('data', (data: Buffer | string) => { + if (data instanceof String) { + data = Buffer.from(data); + } + + fileBuffer = Buffer.concat([fileBuffer, data as Buffer]); + }); + + part.on('end', () => { + files[fileName] = fileBuffer; + }); + }); + + dicer.on('finish', function () { + request.files = files; + return next(); + }); + + request.pipe(dicer); +} + +router.post('/upload', multipartParser, async (request: express.Request, response: express.Response): Promise => { + if (!request.files) { + response.sendStatus(500); + return; + } + + const bucket = request.files.bucket.toString(); + const key = request.files.key.toString(); + const file = request.files.file; + const acl = request.files.acl.toString(); + const pid = request.files.pid.toString(); + const date = request.files.date.toString(); + const signature = request.files.signature.toString(); + + // * Signatures only good for 1 minute + const minute = 1000 * 60; + const minuteAgo = Date.now() - minute; + + if (Number(date) < Math.floor(minuteAgo / 1000)) { + response.sendStatus(400); + return; + } + + const data = `${pid}${bucket}${key}${date}`; + + const hmac = crypto.createHmac('sha256', config.datastore.signature_secret).update(data).digest('hex'); + + console.log(hmac, signature); + + if (hmac !== signature) { + response.sendStatus(400); + return; + } + + await uploadCDNAsset(bucket, key, file, acl); + response.sendStatus(200); +}); + +export default router; \ No newline at end of file diff --git a/src/services/grpc/account/api-key-middleware.ts b/src/services/grpc/account/api-key-middleware.ts new file mode 100644 index 0000000..2a6158d --- /dev/null +++ b/src/services/grpc/account/api-key-middleware.ts @@ -0,0 +1,15 @@ +import { Status, ServerMiddlewareCall, CallContext, ServerError } from 'nice-grpc'; +import { config } from '@/config-manager'; + +export async function* apiKeyMiddleware( + call: ServerMiddlewareCall, + context: CallContext, +): AsyncGenerator { + const apiKey = context.metadata.get('X-API-Key'); + + if (!apiKey || apiKey !== config.grpc.master_api_keys.account) { + throw new ServerError(Status.UNAUTHENTICATED, 'Missing or invalid API key'); + } + + return yield* call.next(call.request, context); +} \ No newline at end of file diff --git a/src/services/grpc/account/exchange-token-for-user-data.ts b/src/services/grpc/account/exchange-token-for-user-data.ts new file mode 100644 index 0000000..347c4da --- /dev/null +++ b/src/services/grpc/account/exchange-token-for-user-data.ts @@ -0,0 +1,62 @@ +import { Status, ServerError } from 'nice-grpc'; +import { ExchangeTokenForUserDataRequest } from '@pretendonetwork/grpc/account/exchange_token_for_user_data'; +import { GetUserDataResponse } from '@pretendonetwork/grpc/account/get_user_data_rpc'; +import { getPNIDByTokenAuth } from '@/database'; +import { PNID_PERMISSION_FLAGS } from '@/types/common/permission-flags'; +import { config } from '@/config-manager'; + +export async function exchangeTokenForUserData(request: ExchangeTokenForUserDataRequest): Promise { + if (!request.token.trim()) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Invalid token'); + } + + const pnid = await getPNIDByTokenAuth(request.token); + + if (!pnid) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Invalid token'); + } + + return { + deleted: pnid.deleted, + pid: pnid.pid, + username: pnid.username, + accessLevel: pnid.access_level, + serverAccessLevel: pnid.server_access_level, + mii: { + name: pnid.mii.name, + data: pnid.mii.data, + url: `${config.cdn.base_url}/mii/${pnid.pid}/standard.tga`, + }, + creationDate: pnid.creation_date, + birthdate: pnid.birthdate, + gender: pnid.gender, + country: pnid.country, + language: pnid.language, + emailAddress: pnid.email.address, + tierName: pnid.connections.stripe.tier_name, + permissions: { + bannedAllPermanently: pnid.hasPermission(PNID_PERMISSION_FLAGS.BANNED_ALL_PERMANENTLY), + bannedAllTemporarily: pnid.hasPermission(PNID_PERMISSION_FLAGS.BANNED_ALL_TEMPORARILY), + betaAccess: pnid.hasPermission(PNID_PERMISSION_FLAGS.BETA_ACCESS), + accessAdminPanel: pnid.hasPermission(PNID_PERMISSION_FLAGS.ACCESS_ADMIN_PANEL), + createServerConfigs: pnid.hasPermission(PNID_PERMISSION_FLAGS.CREATE_SERVER_CONFIGS), + modifyServerConfigs: pnid.hasPermission(PNID_PERMISSION_FLAGS.MODIFY_SERVER_CONFIGS), + deployServer: pnid.hasPermission(PNID_PERMISSION_FLAGS.DEPLOY_SERVER), + modifyPnids: pnid.hasPermission(PNID_PERMISSION_FLAGS.MODIFY_PNIDS), + modifyNexAccounts: pnid.hasPermission(PNID_PERMISSION_FLAGS.MODIFY_NEX_ACCOUNTS), + modifyConsoles: pnid.hasPermission(PNID_PERMISSION_FLAGS.MODIFY_CONSOLES), + banPnids: pnid.hasPermission(PNID_PERMISSION_FLAGS.BAN_PNIDS), + banNexAccounts: pnid.hasPermission(PNID_PERMISSION_FLAGS.BAN_NEX_ACCOUNTS), + banConsoles: pnid.hasPermission(PNID_PERMISSION_FLAGS.BAN_CONSOLES), + moderateMiiverse: pnid.hasPermission(PNID_PERMISSION_FLAGS.MODERATE_MIIVERSE), + createApiKeys: pnid.hasPermission(PNID_PERMISSION_FLAGS.CREATE_API_KEYS), + createBossTasks: pnid.hasPermission(PNID_PERMISSION_FLAGS.CREATE_BOSS_TASKS), + updateBossTasks: pnid.hasPermission(PNID_PERMISSION_FLAGS.UPDATE_BOSS_TASKS), + deleteBossTasks: pnid.hasPermission(PNID_PERMISSION_FLAGS.DELETE_BOSS_TASKS), + uploadBossFiles: pnid.hasPermission(PNID_PERMISSION_FLAGS.UPLOAD_BOSS_FILES), + updateBossFiles: pnid.hasPermission(PNID_PERMISSION_FLAGS.UPDATE_BOSS_FILES), + deleteBossFiles: pnid.hasPermission(PNID_PERMISSION_FLAGS.DELETE_BOSS_FILES), + updatePnidPermissions: pnid.hasPermission(PNID_PERMISSION_FLAGS.UPDATE_PNID_PERMISSIONS) + } + }; +} \ No newline at end of file diff --git a/src/services/grpc/account/get-nex-data.ts b/src/services/grpc/account/get-nex-data.ts new file mode 100644 index 0000000..38a938d --- /dev/null +++ b/src/services/grpc/account/get-nex-data.ts @@ -0,0 +1,23 @@ +import { Status, ServerError } from 'nice-grpc'; +import {GetNEXDataRequest,GetNEXDataResponse, DeepPartial } from '@pretendonetwork/grpc/account/get_nex_data_rpc'; +import { NEXAccount } from '@/models/nex-account'; + +export async function getNEXData(request: GetNEXDataRequest): Promise> { + const nexAccount = await NEXAccount.findOne({ pid: request.pid }); + + if (!nexAccount) { + throw new ServerError( + Status.INVALID_ARGUMENT, + 'No NEX account found', + ); + } + + return { + pid: nexAccount.pid, + password: nexAccount.password, + owningPid: nexAccount.owning_pid, + accessLevel: nexAccount.access_level, + serverAccessLevel: nexAccount.server_access_level, + friendCode: nexAccount.friend_code + }; +} diff --git a/src/services/grpc/account/get-nex-password.ts b/src/services/grpc/account/get-nex-password.ts new file mode 100644 index 0000000..a872d2b --- /dev/null +++ b/src/services/grpc/account/get-nex-password.ts @@ -0,0 +1,18 @@ +import { Status, ServerError } from 'nice-grpc'; +import {GetNEXPasswordRequest,GetNEXPasswordResponse, DeepPartial } from '@pretendonetwork/grpc/account/get_nex_password_rpc'; +import { NEXAccount } from '@/models/nex-account'; + +export async function getNEXPassword(request: GetNEXPasswordRequest): Promise> { + const nexAccount = await NEXAccount.findOne({ pid: request.pid }); + + if (!nexAccount) { + throw new ServerError( + Status.INVALID_ARGUMENT, + 'No NEX account found', + ); + } + + return { + password: nexAccount.password + }; +} diff --git a/src/services/grpc/account/get-user-data.ts b/src/services/grpc/account/get-user-data.ts new file mode 100644 index 0000000..80d2704 --- /dev/null +++ b/src/services/grpc/account/get-user-data.ts @@ -0,0 +1,60 @@ +import { Status, ServerError } from 'nice-grpc'; +import { GetUserDataRequest, GetUserDataResponse } from '@pretendonetwork/grpc/account/get_user_data_rpc'; +import { getPNIDByPID } from '@/database'; +import { PNID_PERMISSION_FLAGS } from '@/types/common/permission-flags'; +import { config } from '@/config-manager'; + +export async function getUserData(request: GetUserDataRequest): Promise { + const pnid = await getPNIDByPID(request.pid); + + if (!pnid) { + throw new ServerError( + Status.INVALID_ARGUMENT, + 'No PNID found', + ); + } + + return { + deleted: pnid.deleted, + pid: pnid.pid, + username: pnid.username, + accessLevel: pnid.access_level, + serverAccessLevel: pnid.server_access_level, + mii: { + name: pnid.mii.name, + data: pnid.mii.data, + url: `${config.cdn.base_url}/mii/${pnid.pid}/standard.tga`, + }, + creationDate: pnid.creation_date, + birthdate: pnid.birthdate, + gender: pnid.gender, + country: pnid.country, + language: pnid.language, + emailAddress: pnid.email.address, + tierName: pnid.connections.stripe.tier_name, + permissions: { + bannedAllPermanently: pnid.hasPermission(PNID_PERMISSION_FLAGS.BANNED_ALL_PERMANENTLY), + bannedAllTemporarily: pnid.hasPermission(PNID_PERMISSION_FLAGS.BANNED_ALL_TEMPORARILY), + betaAccess: pnid.hasPermission(PNID_PERMISSION_FLAGS.BETA_ACCESS), + accessAdminPanel: pnid.hasPermission(PNID_PERMISSION_FLAGS.ACCESS_ADMIN_PANEL), + createServerConfigs: pnid.hasPermission(PNID_PERMISSION_FLAGS.CREATE_SERVER_CONFIGS), + modifyServerConfigs: pnid.hasPermission(PNID_PERMISSION_FLAGS.MODIFY_SERVER_CONFIGS), + deployServer: pnid.hasPermission(PNID_PERMISSION_FLAGS.DEPLOY_SERVER), + modifyPnids: pnid.hasPermission(PNID_PERMISSION_FLAGS.MODIFY_PNIDS), + modifyNexAccounts: pnid.hasPermission(PNID_PERMISSION_FLAGS.MODIFY_NEX_ACCOUNTS), + modifyConsoles: pnid.hasPermission(PNID_PERMISSION_FLAGS.MODIFY_CONSOLES), + banPnids: pnid.hasPermission(PNID_PERMISSION_FLAGS.BAN_PNIDS), + banNexAccounts: pnid.hasPermission(PNID_PERMISSION_FLAGS.BAN_NEX_ACCOUNTS), + banConsoles: pnid.hasPermission(PNID_PERMISSION_FLAGS.BAN_CONSOLES), + moderateMiiverse: pnid.hasPermission(PNID_PERMISSION_FLAGS.MODERATE_MIIVERSE), + createApiKeys: pnid.hasPermission(PNID_PERMISSION_FLAGS.CREATE_API_KEYS), + createBossTasks: pnid.hasPermission(PNID_PERMISSION_FLAGS.CREATE_BOSS_TASKS), + updateBossTasks: pnid.hasPermission(PNID_PERMISSION_FLAGS.UPDATE_BOSS_TASKS), + deleteBossTasks: pnid.hasPermission(PNID_PERMISSION_FLAGS.DELETE_BOSS_TASKS), + uploadBossFiles: pnid.hasPermission(PNID_PERMISSION_FLAGS.UPLOAD_BOSS_FILES), + updateBossFiles: pnid.hasPermission(PNID_PERMISSION_FLAGS.UPDATE_BOSS_FILES), + deleteBossFiles: pnid.hasPermission(PNID_PERMISSION_FLAGS.DELETE_BOSS_FILES), + updatePnidPermissions: pnid.hasPermission(PNID_PERMISSION_FLAGS.UPDATE_PNID_PERMISSIONS) + } + }; +} \ No newline at end of file diff --git a/src/services/grpc/account/implementation.ts b/src/services/grpc/account/implementation.ts new file mode 100644 index 0000000..37a9dd4 --- /dev/null +++ b/src/services/grpc/account/implementation.ts @@ -0,0 +1,13 @@ +import { getUserData } from '@/services/grpc/account/get-user-data'; +import { getNEXPassword } from '@/services/grpc/account/get-nex-password'; +import { getNEXData } from '@/services/grpc/account/get-nex-data'; +import { updatePNIDPermissions } from '@/services/grpc/account/update-pnid-permissions'; +import { exchangeTokenForUserData } from '@/services/grpc/account/exchange-token-for-user-data'; + +export const accountServiceImplementation = { + getUserData, + getNEXPassword, + getNEXData, + updatePNIDPermissions, + exchangeTokenForUserData +}; diff --git a/src/services/grpc/account/update-pnid-permissions.ts b/src/services/grpc/account/update-pnid-permissions.ts new file mode 100644 index 0000000..d547311 --- /dev/null +++ b/src/services/grpc/account/update-pnid-permissions.ts @@ -0,0 +1,159 @@ +import { Status, ServerError } from 'nice-grpc'; +import { UpdatePNIDPermissionsRequest } from '@pretendonetwork/grpc/account/update_pnid_permissions'; +import { getPNIDByPID } from '@/database'; +import { PNID_PERMISSION_FLAGS } from '@/types/common/permission-flags'; +import type { Empty } from '@pretendonetwork/grpc/api/google/protobuf/empty'; + +export async function updatePNIDPermissions(request: UpdatePNIDPermissionsRequest): Promise { + const pnid = await getPNIDByPID(request.pid); + + if (!pnid) { + throw new ServerError( + Status.INVALID_ARGUMENT, + 'No PNID found', + ); + } + + if (!request.permissions) { + throw new ServerError( + Status.INVALID_ARGUMENT, + 'Permissions flags not found', + ); + } + + if (request.permissions.bannedAllPermanently === true) { + await pnid.addPermission(PNID_PERMISSION_FLAGS.BANNED_ALL_PERMANENTLY); + } else if (request.permissions.bannedAllPermanently === false) { + await pnid.clearPermission(PNID_PERMISSION_FLAGS.BANNED_ALL_PERMANENTLY); + } + + if (request.permissions.bannedAllTemporarily === true) { + await pnid.addPermission(PNID_PERMISSION_FLAGS.BANNED_ALL_TEMPORARILY); + } else if (request.permissions.bannedAllTemporarily === false) { + await pnid.clearPermission(PNID_PERMISSION_FLAGS.BANNED_ALL_TEMPORARILY); + } + + if (request.permissions.betaAccess === true) { + await pnid.addPermission(PNID_PERMISSION_FLAGS.BETA_ACCESS); + } else if (request.permissions.betaAccess === false) { + await pnid.clearPermission(PNID_PERMISSION_FLAGS.BETA_ACCESS); + } + + if (request.permissions.accessAdminPanel === true) { + await pnid.addPermission(PNID_PERMISSION_FLAGS.ACCESS_ADMIN_PANEL); + } else if (request.permissions.accessAdminPanel === false) { + await pnid.clearPermission(PNID_PERMISSION_FLAGS.ACCESS_ADMIN_PANEL); + } + + if (request.permissions.createServerConfigs === true) { + await pnid.addPermission(PNID_PERMISSION_FLAGS.CREATE_SERVER_CONFIGS); + } else if (request.permissions.createServerConfigs === false) { + await pnid.clearPermission(PNID_PERMISSION_FLAGS.CREATE_SERVER_CONFIGS); + } + + if (request.permissions.modifyServerConfigs === true) { + await pnid.addPermission(PNID_PERMISSION_FLAGS.MODIFY_SERVER_CONFIGS); + } else if (request.permissions.modifyServerConfigs === false) { + await pnid.clearPermission(PNID_PERMISSION_FLAGS.MODIFY_SERVER_CONFIGS); + } + + if (request.permissions.deployServer === true) { + await pnid.addPermission(PNID_PERMISSION_FLAGS.DEPLOY_SERVER); + } else if (request.permissions.deployServer === false) { + await pnid.clearPermission(PNID_PERMISSION_FLAGS.DEPLOY_SERVER); + } + + if (request.permissions.modifyPnids === true) { + await pnid.addPermission(PNID_PERMISSION_FLAGS.MODIFY_PNIDS); + } else if (request.permissions.modifyPnids === false) { + await pnid.clearPermission(PNID_PERMISSION_FLAGS.MODIFY_PNIDS); + } + + if (request.permissions.modifyNexAccounts === true) { + await pnid.addPermission(PNID_PERMISSION_FLAGS.MODIFY_NEX_ACCOUNTS); + } else if (request.permissions.modifyNexAccounts === false) { + await pnid.clearPermission(PNID_PERMISSION_FLAGS.MODIFY_NEX_ACCOUNTS); + } + + if (request.permissions.modifyConsoles === true) { + await pnid.addPermission(PNID_PERMISSION_FLAGS.MODIFY_CONSOLES); + } else if (request.permissions.modifyConsoles === false) { + await pnid.clearPermission(PNID_PERMISSION_FLAGS.MODIFY_CONSOLES); + } + + if (request.permissions.banPnids === true) { + await pnid.addPermission(PNID_PERMISSION_FLAGS.BAN_PNIDS); + } else if (request.permissions.banPnids === false) { + await pnid.clearPermission(PNID_PERMISSION_FLAGS.BAN_PNIDS); + } + + if (request.permissions.banNexAccounts === true) { + await pnid.addPermission(PNID_PERMISSION_FLAGS.BAN_NEX_ACCOUNTS); + } else if (request.permissions.banNexAccounts === false) { + await pnid.clearPermission(PNID_PERMISSION_FLAGS.BAN_NEX_ACCOUNTS); + } + + if (request.permissions.banConsoles === true) { + await pnid.addPermission(PNID_PERMISSION_FLAGS.BAN_CONSOLES); + } else if (request.permissions.banConsoles === false) { + await pnid.clearPermission(PNID_PERMISSION_FLAGS.BAN_CONSOLES); + } + + if (request.permissions.moderateMiiverse === true) { + await pnid.addPermission(PNID_PERMISSION_FLAGS.MODERATE_MIIVERSE); + } else if (request.permissions.moderateMiiverse === false) { + await pnid.clearPermission(PNID_PERMISSION_FLAGS.MODERATE_MIIVERSE); + } + + if (request.permissions.createApiKeys === true) { + await pnid.addPermission(PNID_PERMISSION_FLAGS.CREATE_API_KEYS); + } else if (request.permissions.createApiKeys === false) { + await pnid.clearPermission(PNID_PERMISSION_FLAGS.CREATE_API_KEYS); + } + + if (request.permissions.createBossTasks === true) { + await pnid.addPermission(PNID_PERMISSION_FLAGS.CREATE_BOSS_TASKS); + } else if (request.permissions.createBossTasks === false) { + await pnid.clearPermission(PNID_PERMISSION_FLAGS.CREATE_BOSS_TASKS); + } + + if (request.permissions.updateBossTasks === true) { + await pnid.addPermission(PNID_PERMISSION_FLAGS.UPDATE_BOSS_TASKS); + } else if (request.permissions.updateBossTasks === false) { + await pnid.clearPermission(PNID_PERMISSION_FLAGS.UPDATE_BOSS_TASKS); + } + + if (request.permissions.deleteBossTasks === true) { + await pnid.addPermission(PNID_PERMISSION_FLAGS.DELETE_BOSS_TASKS); + } else if (request.permissions.deleteBossTasks === false) { + await pnid.clearPermission(PNID_PERMISSION_FLAGS.DELETE_BOSS_TASKS); + } + + if (request.permissions.uploadBossFiles === true) { + await pnid.addPermission(PNID_PERMISSION_FLAGS.UPLOAD_BOSS_FILES); + } else if (request.permissions.uploadBossFiles === false) { + await pnid.clearPermission(PNID_PERMISSION_FLAGS.UPLOAD_BOSS_FILES); + } + + if (request.permissions.updateBossFiles === true) { + await pnid.addPermission(PNID_PERMISSION_FLAGS.UPDATE_BOSS_FILES); + } else if (request.permissions.updateBossFiles === false) { + await pnid.clearPermission(PNID_PERMISSION_FLAGS.UPDATE_BOSS_FILES); + } + + if (request.permissions.deleteBossFiles === true) { + await pnid.addPermission(PNID_PERMISSION_FLAGS.DELETE_BOSS_FILES); + } else if (request.permissions.deleteBossFiles === false) { + await pnid.clearPermission(PNID_PERMISSION_FLAGS.DELETE_BOSS_FILES); + } + + if (request.permissions.updatePnidPermissions === true) { + await pnid.addPermission(PNID_PERMISSION_FLAGS.UPDATE_PNID_PERMISSIONS); + } else if (request.permissions.updatePnidPermissions === false) { + await pnid.clearPermission(PNID_PERMISSION_FLAGS.UPDATE_PNID_PERMISSIONS); + } + + await pnid.save(); + + return {}; +} \ No newline at end of file diff --git a/src/services/grpc/api/api-key-middleware.ts b/src/services/grpc/api/api-key-middleware.ts new file mode 100644 index 0000000..215df34 --- /dev/null +++ b/src/services/grpc/api/api-key-middleware.ts @@ -0,0 +1,15 @@ +import { Status, ServerMiddlewareCall, CallContext, ServerError } from 'nice-grpc'; +import { config } from '@/config-manager'; + +export async function* apiKeyMiddleware( + call: ServerMiddlewareCall, + context: CallContext, +): AsyncGenerator { + const apiKey = context.metadata.get('X-API-Key'); + + if (!apiKey || apiKey !== config.grpc.master_api_keys.api) { + throw new ServerError(Status.UNAUTHENTICATED, 'Missing or invalid API key'); + } + + return yield* call.next(call.request, context); +} \ No newline at end of file diff --git a/src/services/grpc/api/authentication-middleware.ts b/src/services/grpc/api/authentication-middleware.ts new file mode 100644 index 0000000..c466c9e --- /dev/null +++ b/src/services/grpc/api/authentication-middleware.ts @@ -0,0 +1,55 @@ +import { Status, ServerMiddlewareCall, CallContext, ServerError } from 'nice-grpc'; +import { getPNIDByTokenAuth } from '@/database'; +import type { HydratedPNIDDocument } from '@/types/mongoose/pnid'; + +// * These paths require that a token be present +const TOKEN_REQUIRED_PATHS = [ + '/api.API/GetUserData', + '/api.API/UpdateUserData', + '/api.API/ResetPassword', // * This paths token is not an authentication token, it is a password reset token + '/api.API/SetDiscordConnectionData', + '/api.API/SetStripeConnectionData', + '/api.API/RemoveConnection' +]; + +export type AuthenticationCallContextExt = { + pnid: HydratedPNIDDocument | null; +}; + +export async function* authenticationMiddleware( + call: ServerMiddlewareCall, + context: CallContext, +): AsyncGenerator { + const token = context.metadata.get('X-Token')?.trim(); + + if (!token && TOKEN_REQUIRED_PATHS.includes(call.method.path)) { + throw new ServerError(Status.UNAUTHENTICATED, 'Missing or invalid authentication token'); + } + + try { + let pnid = null; + + if (token) { + pnid = await getPNIDByTokenAuth(token); + } + + if (!pnid && TOKEN_REQUIRED_PATHS.includes(call.method.path)) { + throw new ServerError(Status.UNAUTHENTICATED, 'Missing or invalid authentication token'); + } + + return yield* call.next(call.request, { + ...context, + pnid + }); + } catch (error) { + let message = 'Unknown server error'; + + console.log(error); + + if (error instanceof Error) { + message = error.message; + } + + throw new ServerError(Status.INVALID_ARGUMENT, message); + } +} \ No newline at end of file diff --git a/src/services/grpc/api/forgot-password.ts b/src/services/grpc/api/forgot-password.ts new file mode 100644 index 0000000..45b9b6e --- /dev/null +++ b/src/services/grpc/api/forgot-password.ts @@ -0,0 +1,29 @@ +import { Status, ServerError } from 'nice-grpc'; +import validator from 'validator'; +import { ForgotPasswordRequest } from '@pretendonetwork/grpc/api/forgot_password_rpc'; +import { getPNIDByEmailAddress, getPNIDByUsername } from '@/database'; +import { sendForgotPasswordEmail } from '@/util'; +import type { Empty } from '@pretendonetwork/grpc/api/google/protobuf/empty'; +import type { HydratedPNIDDocument } from '@/types/mongoose/pnid'; + +export async function forgotPassword(request: ForgotPasswordRequest): Promise { + const input = request.emailAddressOrUsername.trim(); + + if (!input) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Invalid or missing input'); + } + + let pnid: HydratedPNIDDocument | null; + + if (validator.isEmail(input)) { + pnid = await getPNIDByEmailAddress(input); + } else { + pnid = await getPNIDByUsername(input); + } + + if (pnid) { + await sendForgotPasswordEmail(pnid); + } + + return {}; +} \ No newline at end of file diff --git a/src/services/grpc/api/get-user-data.ts b/src/services/grpc/api/get-user-data.ts new file mode 100644 index 0000000..150f6cb --- /dev/null +++ b/src/services/grpc/api/get-user-data.ts @@ -0,0 +1,45 @@ +import { CallContext } from 'nice-grpc'; +import { GetUserDataResponse, DeepPartial } from '@pretendonetwork/grpc/api/get_user_data_rpc'; +import { config } from '@/config-manager'; +import type { Empty } from '@pretendonetwork/grpc/api/google/protobuf/empty'; +import type { AuthenticationCallContextExt } from '@/services/grpc/api/authentication-middleware'; + +export async function getUserData(_request: Empty, context: CallContext & AuthenticationCallContextExt): Promise> { + // * This is asserted in authentication-middleware, we know this is never null + const pnid = context.pnid!; + + return { + deleted: pnid.deleted, + creationDate: pnid.creation_date, + updatedDate: pnid.updated, + pid: pnid.pid, + username: pnid.username, + accessLevel: pnid.access_level, + serverAccessLevel: pnid.server_access_level, + mii: { + name: pnid.mii.name, + data: pnid.mii.data, + url: `${config.cdn.base_url}/mii/${pnid.pid}/standard.tga`, + }, + birthday: pnid.birthdate, + gender: pnid.gender, + country: pnid.country, + timezone: pnid.timezone.name, + language: pnid.language, + emailAddress: pnid.email.address, + connections: { + discord: { + id: pnid.connections.discord.id + }, + stripe: { + customerId: pnid.connections.stripe.customer_id, + subscriptionId: pnid.connections.stripe.subscription_id, + priceId: pnid.connections.stripe.price_id, + tierLevel: pnid.connections.stripe.tier_level, + tierName: pnid.connections.stripe.tier_name, + latestWebhookTimestamp: BigInt(pnid.connections.stripe.latest_webhook_timestamp ?? 0) + } + }, + marketingFlag: pnid.flags.marketing + }; +} diff --git a/src/services/grpc/api/implementation.ts b/src/services/grpc/api/implementation.ts new file mode 100644 index 0000000..bc0c8fe --- /dev/null +++ b/src/services/grpc/api/implementation.ts @@ -0,0 +1,19 @@ +import { register } from '@/services/grpc/api/register'; +import { login } from '@/services/grpc/api/login'; +import { getUserData } from '@/services/grpc/api/get-user-data'; +import { updateUserData } from '@/services/grpc/api/update-user-data'; +import { forgotPassword } from '@/services/grpc/api/forgot-password'; +import { resetPassword } from '@/services/grpc/api/reset-password'; +import { setDiscordConnectionData } from '@/services/grpc/api/set-discord-connection-data'; +import { setStripeConnectionData } from '@/services/grpc/api/set-stripe-connection-data'; + +export const apiServiceImplementation = { + register, + login, + getUserData, + updateUserData, + forgotPassword, + resetPassword, + setDiscordConnectionData, + setStripeConnectionData +}; \ No newline at end of file diff --git a/src/services/grpc/api/login.ts b/src/services/grpc/api/login.ts new file mode 100644 index 0000000..8c4bfea --- /dev/null +++ b/src/services/grpc/api/login.ts @@ -0,0 +1,89 @@ +import { Status, ServerError } from 'nice-grpc'; +import { LoginRequest, LoginResponse, DeepPartial } from '@pretendonetwork/grpc/api/login_rpc'; +import bcrypt from 'bcrypt'; +import { getPNIDByUsername, getPNIDByTokenAuth } from '@/database'; +import { nintendoPasswordHash, generateToken} from '@/util'; +import { config } from '@/config-manager'; +import type { HydratedPNIDDocument } from '@/types/mongoose/pnid'; + +export async function login(request: LoginRequest): Promise> { + const grantType = request.grantType?.trim(); + const username = request.username?.trim(); + const password = request.password?.trim(); + const refreshToken = request.refreshToken?.trim(); + + if (!['password', 'refresh_token'].includes(grantType)) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Invalid grant type'); + } + + if (grantType === 'password' && !username) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Invalid or missing username'); + } + + if (grantType === 'password' && !password) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Invalid or missing password'); + } + + if (grantType === 'refresh_token' && !refreshToken) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Invalid or missing refresh token'); + } + + let pnid: HydratedPNIDDocument | null; + + if (grantType === 'password') { + pnid = await getPNIDByUsername(username!); // * We know username will never be null here + + if (!pnid) { + throw new ServerError(Status.INVALID_ARGUMENT, 'User not found'); + } + + const hashedPassword = nintendoPasswordHash(password!, pnid.pid); // * We know password will never be null here + + if (!bcrypt.compareSync(hashedPassword, pnid.password)) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Password is incorrect'); + } + } else { + pnid = await getPNIDByTokenAuth(refreshToken!); // * We know refreshToken will never be null here + + if (!pnid) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Invalid or missing refresh token'); + } + } + + if (pnid.deleted) { + throw new ServerError(Status.UNAUTHENTICATED, 'Account has been deleted'); + } + + const accessTokenOptions = { + system_type: 0x3, // * API + token_type: 0x1, // * OAuth Access + pid: pnid.pid, + access_level: pnid.access_level, + title_id: BigInt(0), + expire_time: BigInt(Date.now() + (3600 * 1000)) + }; + + const refreshTokenOptions = { + system_type: 0x3, // * API + token_type: 0x2, // * OAuth Refresh + pid: pnid.pid, + access_level: pnid.access_level, + title_id: BigInt(0), + expire_time: BigInt(Date.now() + (3600 * 1000)) + }; + + const accessTokenBuffer = await generateToken(config.aes_key, accessTokenOptions); + const refreshTokenBuffer = await generateToken(config.aes_key, refreshTokenOptions); + + const accessToken = accessTokenBuffer ? accessTokenBuffer.toString('hex') : ''; + const newRefreshToken = refreshTokenBuffer ? refreshTokenBuffer.toString('hex') : ''; + + // TODO - Handle null tokens + + return { + accessToken: accessToken, + tokenType: 'Bearer', + expiresIn: 3600, + refreshToken: newRefreshToken + }; +} \ No newline at end of file diff --git a/src/services/grpc/api/register.ts b/src/services/grpc/api/register.ts new file mode 100644 index 0000000..566c5a1 --- /dev/null +++ b/src/services/grpc/api/register.ts @@ -0,0 +1,264 @@ +import crypto from 'node:crypto'; +import { Status, ServerError } from 'nice-grpc'; +import { RegisterRequest, DeepPartial } from '@pretendonetwork/grpc/api/register_rpc'; +import { LoginResponse } from '@pretendonetwork/grpc/api/login_rpc'; +import emailvalidator from 'email-validator'; +import bcrypt from 'bcrypt'; +import moment from 'moment'; +import hcaptcha from 'hcaptcha'; +import Mii from 'mii-js'; +import { doesPNIDExist, connection as databaseConnection } from '@/database'; +import { nintendoPasswordHash, sendConfirmationEmail, generateToken } from '@/util'; +import { LOG_ERROR } from '@/logger'; +import { PNID } from '@/models/pnid'; +import { NEXAccount } from '@/models/nex-account'; +import { config, disabledFeatures } from '@/config-manager'; +import type { HydratedNEXAccountDocument } from '@/types/mongoose/nex-account'; +import type { HydratedPNIDDocument } from '@/types/mongoose/pnid'; + +const PNID_VALID_CHARACTERS_REGEX = /^[\w\-.]*$/; +const PNID_PUNCTUATION_START_REGEX = /^[_\-.]/; +const PNID_PUNCTUATION_END_REGEX = /[_\-.]$/; +const PNID_PUNCTUATION_DUPLICATE_REGEX = /[_\-.]{2,}/; + +// * This sucks +const PASSWORD_WORD_OR_NUMBER_REGEX = /(?=.*[a-zA-Z])(?=.*\d).*/; +const PASSWORD_WORD_OR_PUNCTUATION_REGEX = /(?=.*[a-zA-Z])(?=.*[_\-.]).*/; +const PASSWORD_NUMBER_OR_PUNCTUATION_REGEX = /(?=.*\d)(?=.*[_\-.]).*/; +const PASSWORD_REPEATED_CHARACTER_REGEX = /(.)\1\1/; + +const DEFAULT_MII_DATA = Buffer.from('AwAAQOlVognnx0GC2/uogAOzuI0n2QAAAEBEAGUAZgBhAHUAbAB0AAAAAAAAAEBAAAAhAQJoRBgmNEYUgRIXaA0AACkAUkhQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGm9', 'base64'); + +export async function register(request: RegisterRequest): Promise> { + const email = request.email?.trim(); + const username = request.username?.trim(); + const miiName = request.miiName?.trim(); + const password = request.password?.trim(); + const passwordConfirm = request.passwordConfirm?.trim(); + const captchaResponse = request.captchaResponse?.trim(); + + // * Only validate the captcha if that's enabled + if (!disabledFeatures.captcha) { + if (!captchaResponse) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Must fill in captcha'); + } + + const captchaVerify = await hcaptcha.verify(config.hcaptcha.secret, captchaResponse); + + if (!captchaVerify.success) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Captcha verification failed'); + } + } + + if (!email) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Must enter an email address'); + } + + if (!emailvalidator.validate(email)) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Invalid email address'); + } + + if (!username) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Must enter a username'); + } + + if (username.length < 6) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Username is too short'); + } + + if (username.length > 16) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Username is too long'); + } + + if (!PNID_VALID_CHARACTERS_REGEX.test(username)) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Username contains invalid characters'); + } + + if (PNID_PUNCTUATION_START_REGEX.test(username)) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Username cannot begin with punctuation characters'); + } + + if (PNID_PUNCTUATION_END_REGEX.test(username)) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Username cannot end with punctuation characters'); + } + + if (PNID_PUNCTUATION_DUPLICATE_REGEX.test(username)) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Two or more punctuation characters cannot be used in a row'); + } + + const userExists = await doesPNIDExist(username); + + if (userExists) { + throw new ServerError(Status.INVALID_ARGUMENT, 'PNID already in use'); + } + + if (!miiName) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Must enter a Mii name'); + } + + const miiNameBuffer = Buffer.from(miiName, 'utf16le'); // * UTF8 to UTF16 + + if (miiNameBuffer.length > 0x14) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Mii name too long'); + } + + if (!password) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Must enter a password'); + } + + if (password.length < 6 || password.length > 16) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Password must be between 6 and 16 characters long'); + } + + if (password.toLowerCase() === username.toLowerCase()) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Password cannot be the same as username'); + } + + if (!PASSWORD_WORD_OR_NUMBER_REGEX.test(password) && !PASSWORD_WORD_OR_PUNCTUATION_REGEX.test(password) && !PASSWORD_NUMBER_OR_PUNCTUATION_REGEX.test(password)) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Password must have combination of letters, numbers, and/or punctuation characters'); + } + + if (PASSWORD_REPEATED_CHARACTER_REGEX.test(password)) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Password may not have 3 repeating characters'); + } + + if (password !== passwordConfirm) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Passwords do not match'); + } + + const mii = new Mii(DEFAULT_MII_DATA); + mii.miiName = miiName; + + const creationDate = moment().format('YYYY-MM-DDTHH:MM:SS'); + let pnid: HydratedPNIDDocument; + let nexAccount: HydratedNEXAccountDocument; + + const session = await databaseConnection().startSession(); + await session.startTransaction(); + + try { + // * PNIDs can only be registered from a Wii U + // * So assume website users are WiiU NEX accounts + nexAccount = new NEXAccount({ + device_type: 'wiiu', + }); + + await nexAccount.generatePID(); + await nexAccount.generatePassword(); + + // * Quick hack to get the PIDs to match + // TODO - Change this maybe? + // * NN with a NNID will always use the NNID PID + // * even if the provided NEX PID is different + // * To fix this we make them the same PID + nexAccount.owning_pid = nexAccount.pid; + + await nexAccount.save({ session }); + + const primaryPasswordHash = nintendoPasswordHash(password, nexAccount.pid); + const passwordHash = await bcrypt.hash(primaryPasswordHash, 10); + + pnid = new PNID({ + pid: nexAccount.pid, + creation_date: creationDate, + updated: creationDate, + username: username, + usernameLower: username.toLowerCase(), + password: passwordHash, + birthdate: '1990-01-01', // TODO - Change this + gender: 'M', // TODO - Change this + country: 'US', // TODO - Change this + language: 'en', // TODO - Change this + email: { + address: email.toLowerCase(), + primary: true, // TODO - Change this + parent: true, // TODO - Change this + reachable: false, // TODO - Change this + validated: false, // TODO - Change this + id: crypto.randomBytes(4).readUInt32LE() + }, + region: 0x310B0000, // TODO - Change this + timezone: { + name: 'America/New_York', // TODO - Change this + offset: -14400 // TODO - Change this + }, + mii: { + name: miiName, + primary: true, // TODO - Change this + data: mii.encode().toString('base64'), + id: crypto.randomBytes(4).readUInt32LE(), + hash: crypto.randomBytes(7).toString('hex'), + image_url: '', // * deprecated, will be removed in the future + image_id: crypto.randomBytes(4).readUInt32LE() + }, + flags: { + active: true, // TODO - Change this + marketing: true, // TODO - Change this + off_device: true // TODO - Change this + }, + identification: { + email_code: 1, // * will be overwritten before saving + email_token: '' // * will be overwritten before saving + } + }); + + await pnid.generateEmailValidationCode(); + await pnid.generateEmailValidationToken(); + await pnid.generateMiiImages(); + + await pnid.save({ session }); + + await session.commitTransaction(); + } catch (error) { + let message = 'Unknown Mongo error'; + + if (error instanceof Error) { + message = error.message; + } + + LOG_ERROR(`[gRPC] /api.API/Register: ${message}`); + + await session.abortTransaction(); + + throw new ServerError(Status.INVALID_ARGUMENT, message); + } finally { + // * This runs regardless of failure + // * Returning on catch will not prevent this from running + await session.endSession(); + } + + await sendConfirmationEmail(pnid); + + const accessTokenOptions = { + system_type: 0x3, // * API + token_type: 0x1, // * OAuth Access + pid: pnid.pid, + access_level: pnid.access_level, + title_id: BigInt(0), + expire_time: BigInt(Date.now() + (3600 * 1000)) + }; + + const refreshTokenOptions = { + system_type: 0x3, // * API + token_type: 0x2, // * OAuth Refresh + pid: pnid.pid, + access_level: pnid.access_level, + title_id: BigInt(0), + expire_time: BigInt(Date.now() + (3600 * 1000)) + }; + + const accessTokenBuffer = await generateToken(config.aes_key, accessTokenOptions); + const refreshTokenBuffer = await generateToken(config.aes_key, refreshTokenOptions); + + const accessToken = accessTokenBuffer ? accessTokenBuffer.toString('hex') : ''; + const refreshToken = refreshTokenBuffer ? refreshTokenBuffer.toString('hex') : ''; + + // TODO - Handle null tokens + + return { + accessToken: accessToken, + tokenType: 'Bearer', + expiresIn: 3600, + refreshToken: refreshToken + }; +} \ No newline at end of file diff --git a/src/services/grpc/api/reset-password.ts b/src/services/grpc/api/reset-password.ts new file mode 100644 index 0000000..be90236 --- /dev/null +++ b/src/services/grpc/api/reset-password.ts @@ -0,0 +1,78 @@ +import bcrypt from 'bcrypt'; +import { Status, ServerError } from 'nice-grpc'; +import { ResetPasswordRequest } from '@pretendonetwork/grpc/api/reset_password_rpc'; +import { decryptToken, unpackToken, nintendoPasswordHash } from '@/util'; +import { getPNIDByPID } from '@/database'; +import type { Empty } from '@pretendonetwork/grpc/api/google/protobuf/empty'; +import type { Token } from '@/types/common/token'; + +// * This sucks +const PASSWORD_WORD_OR_NUMBER_REGEX = /(?=.*[a-zA-Z])(?=.*\d).*/; +const PASSWORD_WORD_OR_PUNCTUATION_REGEX = /(?=.*[a-zA-Z])(?=.*[_\-.]).*/; +const PASSWORD_NUMBER_OR_PUNCTUATION_REGEX = /(?=.*\d)(?=.*[_\-.]).*/; +const PASSWORD_REPEATED_CHARACTER_REGEX = /(.)\1\1/; + +export async function resetPassword(request: ResetPasswordRequest): Promise { + const password = request.password.trim(); + const passwordConfirm = request.passwordConfirm.trim(); + const token = request.token.trim(); + + if (!token) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Missing token'); + } + + let unpackedToken: Token; + try { + const decryptedToken = await decryptToken(Buffer.from(token, 'base64')); + unpackedToken = unpackToken(decryptedToken); + } catch (error) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Invalid token'); + } + + if (unpackedToken.expire_time < Date.now()) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Token expired'); + } + + const pnid = await getPNIDByPID(unpackedToken.pid); + + if (!pnid) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Invalid token. No user found'); + } + + if (!password) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Must enter a password'); + } + + if (password.length < 6) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Password is too short'); + } + + if (password.length > 16) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Password is too long'); + } + + if (password.toLowerCase() === pnid.usernameLower) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Password cannot be the same as username'); + } + + if (!PASSWORD_WORD_OR_NUMBER_REGEX.test(password) && !PASSWORD_WORD_OR_PUNCTUATION_REGEX.test(password) && !PASSWORD_NUMBER_OR_PUNCTUATION_REGEX.test(password)) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Password must have combination of letters, numbers, and/or punctuation characters'); + } + + if (PASSWORD_REPEATED_CHARACTER_REGEX.test(password)) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Password may not have 3 repeating characters'); + } + + if (password !== passwordConfirm) { + throw new ServerError(Status.INVALID_ARGUMENT, 'Passwords do not match'); + } + + const primaryPasswordHash = nintendoPasswordHash(password, pnid.pid); + const passwordHash = await bcrypt.hash(primaryPasswordHash, 10); + + pnid.password = passwordHash; + + await pnid.save(); + + return {}; +} \ No newline at end of file diff --git a/src/services/grpc/api/set-discord-connection-data.ts b/src/services/grpc/api/set-discord-connection-data.ts new file mode 100644 index 0000000..84688ec --- /dev/null +++ b/src/services/grpc/api/set-discord-connection-data.ts @@ -0,0 +1,25 @@ +import { Status, ServerError, CallContext } from 'nice-grpc'; +import { SetDiscordConnectionDataRequest } from '@pretendonetwork/grpc/api/set_discord_connection_data_rpc'; +import type { Empty } from '@pretendonetwork/grpc/api/google/protobuf/empty'; +import type { AuthenticationCallContextExt } from '@/services/grpc/api/authentication-middleware'; + +export async function setDiscordConnectionData(request: SetDiscordConnectionDataRequest, context: CallContext & AuthenticationCallContextExt): Promise{ + // * This is asserted in authentication-middleware, we know this is never null + const pnid = context.pnid!; + + try { + pnid.connections.discord.id = request.id; + + await pnid.save(); + } catch (error) { + let message = 'Unknown Mongo error'; + + if (error instanceof Error) { + message = error.message; + } + + throw new ServerError(Status.INVALID_ARGUMENT, message); + } + + return {}; +} \ No newline at end of file diff --git a/src/services/grpc/api/set-stripe-connection-data.ts b/src/services/grpc/api/set-stripe-connection-data.ts new file mode 100644 index 0000000..2af96b8 --- /dev/null +++ b/src/services/grpc/api/set-stripe-connection-data.ts @@ -0,0 +1,90 @@ +import { Status, ServerError, CallContext } from 'nice-grpc'; +import { SetStripeConnectionDataRequest } from '@pretendonetwork/grpc/api/set_stripe_connection_data_rpc'; +import { PNID } from '@/models/pnid'; +import type { Empty } from '@pretendonetwork/grpc/api/google/protobuf/empty'; +import type { AuthenticationCallContextExt } from '@/services/grpc/api/authentication-middleware'; + +type StripeMongoUpdateScheme = { + access_level?: number; + server_access_level?: string; + 'connections.stripe.customer_id'?: string; + 'connections.stripe.subscription_id'?: string; + 'connections.stripe.price_id'?: string; + 'connections.stripe.tier_level'?: number; + 'connections.stripe.tier_name'?: string; + 'connections.stripe.latest_webhook_timestamp': number; +}; + +export async function setStripeConnectionData(request: SetStripeConnectionDataRequest, context: CallContext & AuthenticationCallContextExt): Promise{ + // * This is asserted in authentication-middleware, we know this is never null + const pnid = context.pnid!; + + const updateData: StripeMongoUpdateScheme = { + 'connections.stripe.latest_webhook_timestamp': Number(request.timestamp) + }; + + if (request.customerId && !pnid.connections.stripe.customer_id) { + updateData['connections.stripe.customer_id'] = request.customerId; + } + + // * These checks allow for null/0 values in order to reset data if needed + + if (request.accessLevel !== undefined) { + updateData.access_level = request.accessLevel; + } + + if (request.serverAccessLevel !== undefined) { + updateData.server_access_level = request.serverAccessLevel; + } + + if (request.subscriptionId !== undefined) { + updateData['connections.stripe.subscription_id'] = request.subscriptionId; + } + + if (request.subscriptionId !== undefined) { + updateData['connections.stripe.subscription_id'] = request.subscriptionId; + } + + if (request.priceId !== undefined) { + updateData['connections.stripe.price_id'] = request.priceId; + } + + if (request.tierLevel !== undefined) { + updateData['connections.stripe.tier_level'] = request.tierLevel; + } + + if (request.tierName !== undefined) { + updateData['connections.stripe.tier_name'] = request.tierName; + } + + try { + if (pnid.connections.stripe.latest_webhook_timestamp && pnid.connections.stripe.customer_id) { + // * Stripe customer data has already been initialized, update it + await PNID.updateOne({ + pid: pnid.pid, + 'connections.stripe.latest_webhook_timestamp': { + $lte: request.timestamp + } + }, { $set: updateData }).exec(); + } else { + // * Initialize a new Stripe user + if (!request.customerId) { + throw new ServerError(Status.INVALID_ARGUMENT, 'No Stripe user data found and no custom ID provided'); + } + + PNID.updateOne({ pid: pnid.pid }, { + $set: updateData + }, { upsert: true }).exec(); + } + } catch (error) { + let message = 'Unknown Mongo error'; + + if (error instanceof Error) { + message = error.message; + } + + throw new ServerError(Status.INVALID_ARGUMENT, message); + } + + return {}; +} \ No newline at end of file diff --git a/src/services/grpc/api/update-user-data.ts b/src/services/grpc/api/update-user-data.ts new file mode 100644 index 0000000..a842f38 --- /dev/null +++ b/src/services/grpc/api/update-user-data.ts @@ -0,0 +1,47 @@ +import { CallContext } from 'nice-grpc'; +import { UpdateUserDataRequest, DeepPartial } from '@pretendonetwork/grpc/api/update_user_data_rpc'; +import { GetUserDataResponse } from '@pretendonetwork/grpc/api/get_user_data_rpc'; +import { config } from '@/config-manager'; +import type { AuthenticationCallContextExt } from '@/services/grpc/api/authentication-middleware'; + +export async function updateUserData(_request: UpdateUserDataRequest, context: CallContext & AuthenticationCallContextExt): Promise> { + // * This is asserted in authentication-middleware, we know this is never null + const pnid = context.pnid!; + + // TODO - STUBBED, DO SOMETHING HERE + + return { + deleted: pnid.deleted, + creationDate: pnid.creation_date, + updatedDate: pnid.updated, + pid: pnid.pid, + username: pnid.username, + accessLevel: pnid.access_level, + serverAccessLevel: pnid.server_access_level, + mii: { + name: pnid.mii.name, + data: pnid.mii.data, + url: `${config.cdn.base_url}/mii/${pnid.pid}/standard.tga`, + }, + birthday: pnid.birthdate, + gender: pnid.gender, + country: pnid.country, + timezone: pnid.timezone.name, + language: pnid.language, + emailAddress: pnid.email.address, + connections: { + discord: { + id: pnid.connections.discord.id + }, + stripe: { + customerId: pnid.connections.stripe.customer_id, + subscriptionId: pnid.connections.stripe.subscription_id, + priceId: pnid.connections.stripe.price_id, + tierLevel: pnid.connections.stripe.tier_level, + tierName: pnid.connections.stripe.tier_name, + latestWebhookTimestamp: BigInt(pnid.connections.stripe.latest_webhook_timestamp ?? 0) + } + }, + marketingFlag: pnid.flags.marketing + }; +} diff --git a/src/services/grpc/server.ts b/src/services/grpc/server.ts new file mode 100644 index 0000000..3032034 --- /dev/null +++ b/src/services/grpc/server.ts @@ -0,0 +1,21 @@ +import { createServer } from 'nice-grpc'; +import { AccountDefinition } from '@pretendonetwork/grpc/account/account_service'; +import { APIDefinition } from '@pretendonetwork/grpc/api/api_service'; + +import { apiKeyMiddleware as accountApiKeyMiddleware } from '@/services/grpc/account/api-key-middleware'; +import { apiKeyMiddleware as apiApiKeyMiddleware } from '@/services/grpc/api/api-key-middleware'; +import { authenticationMiddleware as apiAuthenticationMiddleware } from '@/services/grpc/api/authentication-middleware'; + +import { accountServiceImplementation } from '@/services/grpc/account/implementation'; +import { apiServiceImplementation } from '@/services/grpc/api/implementation'; + +import { config } from '@/config-manager'; + +export async function startGRPCServer(): Promise { + const server = createServer(); + + server.with(accountApiKeyMiddleware).add(AccountDefinition, accountServiceImplementation); + server.with(apiApiKeyMiddleware).with(apiAuthenticationMiddleware).add(APIDefinition, apiServiceImplementation); + + await server.listen(`0.0.0.0:${config.grpc.port}`); +} \ No newline at end of file diff --git a/src/services/local-cdn/index.js b/src/services/local-cdn/index.js deleted file mode 100644 index b0e3985..0000000 --- a/src/services/local-cdn/index.js +++ /dev/null @@ -1,30 +0,0 @@ -const express = require('express'); -const subdomain = require('express-subdomain'); -const logger = require('../../../logger'); -const { config, disabledFeatures } = require('../../config-manager'); - -if (!disabledFeatures.s3) { - // * s3 enabled, no need for this - - module.exports = express.Router(); - - return; -} - -const routes = require('./routes'); - -// Router to handle the subdomain -const localcdn = express.Router(); - -// Setup routes -logger.info('[LOCAL-CDN] Applying imported routes'); -localcdn.use(routes.GET); - -// Main router for endpoints -const router = express.Router(); - -// Create subdomains -logger.info(`[LOCAL-CDN] Creating '${config.cdn.subdomain}' subdomain`); -router.use(subdomain(config.cdn.subdomain, localcdn)); - -module.exports = router; \ No newline at end of file diff --git a/src/services/local-cdn/index.ts b/src/services/local-cdn/index.ts new file mode 100644 index 0000000..5c837ee --- /dev/null +++ b/src/services/local-cdn/index.ts @@ -0,0 +1,27 @@ +import express from 'express'; +import { config, disabledFeatures } from '@/config-manager'; +import { LOG_INFO, formatHostnames } from '@/logger'; + +import get from '@/services/local-cdn/routes/get'; +import { restrictHostnames } from '@/middleware/host-limit'; + +const router = express.Router(); + +if (disabledFeatures.s3) { + // * s3 disabled, setup local CDN + + // * Router to handle the subdomain + const localcdn = express.Router(); + + // * Setup routes + LOG_INFO('[LOCAL-CDN] Applying imported routes'); + localcdn.use(get); + + // * Create domains + LOG_INFO(`[LOCAL-CDN] Creating cdn router with domains: ${formatHostnames(config.domains.local_cdn)}`); + router.use(restrictHostnames(config.domains.local_cdn, localcdn)); +} else { + LOG_INFO('[LOCAL-CDN] s3 enabled, skipping local CDN'); +} + +export default router; \ No newline at end of file diff --git a/src/services/local-cdn/routes/get.js b/src/services/local-cdn/routes/get.js deleted file mode 100644 index 7ae69b9..0000000 --- a/src/services/local-cdn/routes/get.js +++ /dev/null @@ -1,16 +0,0 @@ -const router = require('express').Router(); -const cache = require('../../../cache'); - -router.get('/*', async (request, response) => { - const filePath = request.params[0]; - - const file = await cache.getLocalCDNFile(filePath); - - if (file) { - response.send(file); - } else { - response.sendStatus(404); - } -}); - -module.exports = router; \ No newline at end of file diff --git a/src/services/local-cdn/routes/get.ts b/src/services/local-cdn/routes/get.ts new file mode 100644 index 0000000..c98b586 --- /dev/null +++ b/src/services/local-cdn/routes/get.ts @@ -0,0 +1,18 @@ +import express from 'express'; +import { getLocalCDNFile } from '@/cache'; + +const router = express.Router(); + +router.get('/*', async (request: express.Request, response: express.Response): Promise => { + const filePath = request.params[0]; + + const file = await getLocalCDNFile(filePath); + + if (file) { + response.send(file); + } else { + response.sendStatus(404); + } +}); + +export default router; \ No newline at end of file diff --git a/src/services/local-cdn/routes/index.js b/src/services/local-cdn/routes/index.js deleted file mode 100644 index 033fca1..0000000 --- a/src/services/local-cdn/routes/index.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - GET: require('./get.js'), -}; \ No newline at end of file diff --git a/src/services/nasc/index.js b/src/services/nasc/index.js deleted file mode 100644 index 9f4f9f3..0000000 --- a/src/services/nasc/index.js +++ /dev/null @@ -1,26 +0,0 @@ -// handles NASC endpoints - -const express = require('express'); -const subdomain = require('express-subdomain'); -const NASCMiddleware = require('../../middleware/nasc'); -const logger = require('../../../logger'); -const routes = require('./routes'); - -// Router to handle the subdomain restriction -const nasc = express.Router(); - -logger.info('[NASC] Importing middleware'); -nasc.use(NASCMiddleware); - -// Setup routes -logger.info('[NASC] Applying imported routes'); -nasc.use('/ac', routes.AC); - -// Main router for endpoints -const router = express.Router(); - -// Create subdomains -logger.info('[NASC] Creating \'nasc\' subdomain'); -router.use(subdomain('nasc', nasc)); - -module.exports = router; \ No newline at end of file diff --git a/src/services/nasc/index.ts b/src/services/nasc/index.ts new file mode 100644 index 0000000..50cb0c8 --- /dev/null +++ b/src/services/nasc/index.ts @@ -0,0 +1,28 @@ +// * handles NASC endpoints + +import express from 'express'; +import NASCMiddleware from '@/middleware/nasc'; +import { LOG_INFO, formatHostnames } from '@/logger'; + +import ac from '@/services/nasc/routes/ac'; +import { restrictHostnames } from '@/middleware/host-limit'; +import { config } from '@/config-manager'; + +// * Router to handle the subdomain restriction +const nasc = express.Router(); + +LOG_INFO('[NASC] Importing middleware'); +nasc.use(NASCMiddleware); + +// * Setup routes +LOG_INFO('[NASC] Applying imported routes'); +nasc.use('/ac', ac); + +// * Main router for endpoints +const router = express.Router(); + +// * Create domains +LOG_INFO(`[NASC] Creating nasc router with domains: ${formatHostnames(config.domains.nasc)}`); +router.use(restrictHostnames(config.domains.nasc, nasc)); + +export default router; \ No newline at end of file diff --git a/src/services/nasc/routes/ac.js b/src/services/nasc/routes/ac.js deleted file mode 100644 index 66d08d4..0000000 --- a/src/services/nasc/routes/ac.js +++ /dev/null @@ -1,106 +0,0 @@ -const fs = require('fs-extra'); -const express = require('express'); -const util = require('../../../util'); -const database = require('../../../database'); -const cache = require('../../../cache'); - -const router = express.Router(); - -/** - * [POST] - * Replacement for: https://nasc.nintendowifi.net/ac - * Description: Gets a NEX server address and token - */ -router.post('/', async (request, response) => { - const requestParams = request.body; - const action = util.nintendoBase64Decode(requestParams.action).toString(); - let responseData; - - switch (action) { - case 'LOGIN': - responseData = await processLoginRequest(request); - break; - case 'SVCLOC': - responseData = await processServiceTokenRequest(request); - break; - } - - response.status(200).send(responseData.toString()); -}); - -/** - * - * @param {express.Request} request - */ -async function processLoginRequest(request) { - const requestParams = request.body; - const titleID = util.nintendoBase64Decode(requestParams.titleid).toString(); - const { nexUser } = request; - - // TODO: REMOVE AFTER PUBLIC LAUNCH - // LET EVERYONE IN THE `test` FRIENDS SERVER - // THAT WAY EVERYONE CAN GET AN ASSIGNED PID - let serverAccessLevel = 'test'; - if (titleID !== '0004013000003202') { - serverAccessLevel = nexUser.get('server_access_level'); - } - - const server = await database.getServerByTitleId(titleID, serverAccessLevel); - - if (!server || !server.service_name || !server.ip || !server.port) { - return util.nascError('110'); - } - - const { service_name, ip, port } = server; - - const cryptoPath = `${__dirname}/../../../../certs/nex/${service_name}`; - - const publicKey = await cache.getNEXPublicKey(service_name); - const secretKey = await cache.getNEXSecretKey(service_name); - - const cryptoOptions = { - public_key: publicKey, - hmac_secret: secretKey - }; - - const tokenOptions = { - system_type: 0x2, // 3DS - token_type: 0x3, // nex token, - pid: nexUser.get('pid'), - access_level: 0, - title_id: BigInt(parseInt(titleID, 16)), - expire_time: BigInt(Date.now() + (3600 * 1000)) - }; - - let nexToken = await util.generateToken(cryptoOptions, tokenOptions); - nexToken = util.nintendoBase64Encode(Buffer.from(nexToken, 'base64')); - - const params = new URLSearchParams({ - locator: util.nintendoBase64Encode(`${ip}:${port}`), - retry: util.nintendoBase64Encode('0'), - returncd: util.nintendoBase64Encode('001'), - token: nexToken, - datetime: util.nintendoBase64Encode(Date.now().toString()), - }); - - return params; -} - -/** - * - * @param {express.Request} request - */ -async function processServiceTokenRequest(request) { - const params = new URLSearchParams({ - retry: util.nintendoBase64Encode('0'), - returncd: util.nintendoBase64Encode('007'), - servicetoken: util.nintendoBase64Encode(Buffer.alloc(64).toString()), // hard coded for now - statusdata: util.nintendoBase64Encode('Y'), - svchost: util.nintendoBase64Encode('n/a'), - datetime: util.nintendoBase64Encode(Date.now().toString()), - }); - - return params; -} - -module.exports = router; \ No newline at end of file diff --git a/src/services/nasc/routes/ac.ts b/src/services/nasc/routes/ac.ts new file mode 100644 index 0000000..1a8c616 --- /dev/null +++ b/src/services/nasc/routes/ac.ts @@ -0,0 +1,115 @@ +import express from 'express'; +import { nintendoBase64Encode, nintendoBase64Decode, nascDateTime, nascError, generateToken } from '@/util'; +import { getServerByTitleID } from '@/database'; +import { NASCRequestParams } from '@/types/services/nasc/request-params'; +import { HydratedServerDocument } from '@/types/mongoose/server'; + +const router = express.Router(); + +/** + * [POST] + * Replacement for: https://nasc.nintendowifi.net/ac + * Description: Gets a NEX server address and token + */ +router.post('/', async (request: express.Request, response: express.Response): Promise => { + const requestParams: NASCRequestParams = request.body; + const action = nintendoBase64Decode(requestParams.action).toString(); + const titleID = nintendoBase64Decode(requestParams.titleid).toString(); + const nexAccount = request.nexAccount; + let responseData = nascError('null'); + + if (!nexAccount) { + response.status(200).send(responseData.toString()); + return; + } + + // TODO - REMOVE AFTER PUBLIC LAUNCH + // * LET EVERYONE IN THE `test` FRIENDS SERVER + // * THAT WAY EVERYONE CAN GET AN ASSIGNED PID + let serverAccessLevel = 'test'; + if (titleID !== '0004013000003202') { + serverAccessLevel = nexAccount.server_access_level; + } + + const server = await getServerByTitleID(titleID, serverAccessLevel); + + if (!server || !server.aes_key) { + response.status(200).send(nascError('110').toString()); + return; + } + + if (server.maintenance_mode) { + // TODO - FIND THE REAL UNDER MAINTENANCE ERROR CODE. 110 IS NOT IT + response.status(200).send(nascError('110').toString()); + return; + } + + if (action === 'LOGIN' && server.port <= 0 && server.ip !== '0.0.0.0') { + // * Addresses of 0.0.0.0:0 are allowed + // * They are expected for titles with no NEX server + response.status(200).send(nascError('110').toString()); + return; + } + + switch (action) { + case 'LOGIN': + responseData = await processLoginRequest(server, nexAccount.pid, titleID); + break; + case 'SVCLOC': + responseData = await processServiceTokenRequest(server, nexAccount.pid, titleID); + break; + } + + response.status(200).send(responseData.toString()); +}); + +async function processLoginRequest(server: HydratedServerDocument, pid: number, titleID: string): Promise { + const tokenOptions = { + system_type: 0x2, // * 3DS + token_type: 0x3, // * NEX token + pid: pid, + access_level: 0, + title_id: BigInt(parseInt(titleID, 16)), + expire_time: BigInt(Date.now() + (3600 * 1000)) + }; + + // TODO - Handle null tokens + + const nexTokenBuffer = await generateToken(server.aes_key, tokenOptions); + const nexToken = nintendoBase64Encode(nexTokenBuffer || ''); + + return new URLSearchParams({ + locator: nintendoBase64Encode(`${server.ip}:${server.port}`), + retry: nintendoBase64Encode('0'), + returncd: nintendoBase64Encode('001'), + token: nexToken, + datetime: nintendoBase64Encode(nascDateTime()), + }); +} + +async function processServiceTokenRequest(server: HydratedServerDocument, pid: number, titleID: string): Promise { + const tokenOptions = { + system_type: 0x2, // * 3DS + token_type: 0x4, // * Service token + pid: pid, + access_level: 0, + title_id: BigInt(parseInt(titleID, 16)), + expire_time: BigInt(Date.now() + (3600 * 1000)) + }; + + // TODO - Handle null tokens + + const serviceTokenBuffer = await generateToken(server.aes_key, tokenOptions); + const serviceToken = nintendoBase64Encode(serviceTokenBuffer || ''); + + return new URLSearchParams({ + retry: nintendoBase64Encode('0'), + returncd: nintendoBase64Encode('007'), + servicetoken: serviceToken, + statusdata: nintendoBase64Encode('Y'), + svchost: nintendoBase64Encode('n/a'), + datetime: nintendoBase64Encode(nascDateTime()), + }); +} + +export default router; \ No newline at end of file diff --git a/src/services/nasc/routes/index.js b/src/services/nasc/routes/index.js deleted file mode 100644 index 971f25d..0000000 --- a/src/services/nasc/routes/index.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - AC: require('./ac') -}; \ No newline at end of file diff --git a/src/services/nnas/index.ts b/src/services/nnas/index.ts new file mode 100644 index 0000000..2cacf1c --- /dev/null +++ b/src/services/nnas/index.ts @@ -0,0 +1,69 @@ +// * handles "account.nintendo.net" endpoints + +import path from 'node:path'; +import express from 'express'; +import clientHeaderCheck from '@/middleware/client-header'; +import cemuMiddleware from '@/middleware/cemu'; +import pnidMiddleware from '@/middleware/pnid'; +import { LOG_INFO, formatHostnames } from '@/logger'; + +import admin from '@/services/nnas/routes/admin'; +import content from '@/services/nnas/routes/content'; +import devices from '@/services/nnas/routes/devices'; +import miis from '@/services/nnas/routes/miis'; +import oauth from '@/services/nnas/routes/oauth'; +import people from '@/services/nnas/routes/people'; +import provider from '@/services/nnas/routes/provider'; +import support from '@/services/nnas/routes/support'; +import settings from '@/services/nnas/routes/account-settings'; +import { config } from '@/config-manager'; +import { restrictHostnames } from '@/middleware/host-limit'; + +// * Router to handle the subdomain restriction +const nnas = express.Router(); + +// * Static routes for the user information app +async function setCSSHeader(request: express.Request, response: express.Response, next: express.NextFunction): Promise { + response.set('Content-Type', 'text/css'); + return next(); +} + +async function setJSHeader(request: express.Request, response: express.Response, next: express.NextFunction): Promise { + response.set('Content-Type', 'text/javascript'); + return next(); +} + +async function setIMGHeader(request: express.Request, response: express.Response, next: express.NextFunction): Promise { + response.set('Content-Type', 'image/png'); + return next(); +} + +// * Setup routes +LOG_INFO('[NNAS] Applying imported routes'); +nnas.use('/v1/account-settings/', settings); +nnas.use('/v1/account-settings/css/', setCSSHeader, express.static(path.join(__dirname, '../../assets/user-info-settings'))); +nnas.use('/v1/account-settings/js/', setJSHeader, express.static(path.join(__dirname, '../../assets/user-info-settings'))); +nnas.use('/v1/account-settings/img/', setIMGHeader, express.static(path.join(__dirname, '../../assets/user-info-settings'))); + +LOG_INFO('[NNAS] Importing middleware'); +nnas.use(clientHeaderCheck); +nnas.use(cemuMiddleware); +nnas.use(pnidMiddleware); + +nnas.use('/v1/api/admin', admin); +nnas.use('/v1/api/content', content); +nnas.use('/v1/api/devices', devices); +nnas.use('/v1/api/miis', miis); +nnas.use('/v1/api/oauth20', oauth); +nnas.use('/v1/api/people', people); +nnas.use('/v1/api/provider', provider); +nnas.use('/v1/api/support', support); + +// * Main router for endpoints +const router = express.Router(); + +// * Create domains +LOG_INFO(`[NNAS] Creating nnas router with domains: ${formatHostnames(config.domains.nnas)}`); +router.use(restrictHostnames(config.domains.nnas, nnas)); + +export default router; \ No newline at end of file diff --git a/src/services/nnas/regions.json b/src/services/nnas/regions.json new file mode 100644 index 0000000..69ad94c --- /dev/null +++ b/src/services/nnas/regions.json @@ -0,0 +1,42182 @@ +[ + { + "id": 1, + "iso_code": "JP", + "name": "Japan", + "translations": { + "japanese": "日本", + "english": "Japan", + "french": "Japon", + "german": "Japan", + "italian": "Giappone", + "spanish": "Japón", + "chinese_simple": "日本", + "korean": "일본", + "dutch": "Japan", + "portuguese": "Japão", + "russian": "Япония", + "chinese_traditional": "日本", + "unknown1": "Japan", + "unknown2": "Japan", + "unknown3": "Japan", + "unknown4": "Japan" + }, + "regions": [ + { + "id": 16777216, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 35.683593344, + "longitude": 139.762953297 + } + }, + { + "id": 16908288, + "name": "Tokyo", + "translations": { + "japanese": "東京都", + "english": "Tokyo", + "french": "Tokyo", + "german": "Tokio", + "italian": "Tokyo", + "spanish": "Tokio", + "chinese_simple": "东京都", + "korean": "도쿄 도", + "dutch": "Tokio", + "portuguese": "Tóquio", + "russian": "Токио", + "chinese_traditional": "東京都", + "unknown1": "Tokyo", + "unknown2": "Tokyo", + "unknown3": "Tokyo", + "unknown4": "Tokyo" + }, + "coordinates": { + "latitude": 35.683593344, + "longitude": 139.762953297 + } + }, + { + "id": 16973824, + "name": "Hokkaido", + "translations": { + "japanese": "北海道", + "english": "Hokkaido", + "french": "Hokkaido", + "german": "Hokkaido", + "italian": "Hokkaido", + "spanish": "Hokaido", + "chinese_simple": "北海道", + "korean": "홋카이도", + "dutch": "Hokkaido", + "portuguese": "Hokkaido", + "russian": "Хоккайдо", + "chinese_traditional": "北海道", + "unknown1": "Hokkaido", + "unknown2": "Hokkaido", + "unknown3": "Hokkaido", + "unknown4": "Hokkaido" + }, + "coordinates": { + "latitude": 43.055419432, + "longitude": 141.328509312 + } + }, + { + "id": 17039360, + "name": "Aomori", + "translations": { + "japanese": "青森県", + "english": "Aomori", + "french": "Aomori", + "german": "Aomori", + "italian": "Aomori", + "spanish": "Aomori", + "chinese_simple": "青森县", + "korean": "아오모리 현", + "dutch": "Aomori", + "portuguese": "Aomori", + "russian": "Аомори", + "chinese_traditional": "青森縣", + "unknown1": "Aomori", + "unknown2": "Aomori", + "unknown3": "Aomori", + "unknown4": "Aomori" + }, + "coordinates": { + "latitude": 40.81420852, + "longitude": 140.768205054 + } + }, + { + "id": 17104896, + "name": "Iwate", + "translations": { + "japanese": "岩手県", + "english": "Iwate", + "french": "Iwate", + "german": "Iwate", + "italian": "Iwate", + "spanish": "Iwate", + "chinese_simple": "岩手县", + "korean": "이와테 현", + "dutch": "Iwate", + "portuguese": "Iwate", + "russian": "Иватэ", + "chinese_traditional": "岩手縣", + "unknown1": "Iwate", + "unknown2": "Iwate", + "unknown3": "Iwate", + "unknown4": "Iwate" + }, + "coordinates": { + "latitude": 39.693603064, + "longitude": 141.163713942 + } + }, + { + "id": 17170432, + "name": "Miyagi", + "translations": { + "japanese": "宮城県", + "english": "Miyagi", + "french": "Miyagi", + "german": "Miyagi", + "italian": "Miyagi", + "spanish": "Miyagi", + "chinese_simple": "宫城县", + "korean": "미야기 현", + "dutch": "Miyagi", + "portuguese": "Miyagi", + "russian": "Мияги", + "chinese_traditional": "宮城縣", + "unknown1": "Miyagi", + "unknown2": "Miyagi", + "unknown3": "Miyagi", + "unknown4": "Miyagi" + }, + "coordinates": { + "latitude": 38.254394096, + "longitude": 140.90004135 + } + }, + { + "id": 17235968, + "name": "Akita", + "translations": { + "japanese": "秋田県", + "english": "Akita", + "french": "Akita", + "german": "Akita", + "italian": "Akita", + "spanish": "Akita", + "chinese_simple": "秋田县", + "korean": "아키타 현", + "dutch": "Akita", + "portuguese": "Akita", + "russian": "Акита", + "chinese_traditional": "秋田縣", + "unknown1": "Akita", + "unknown2": "Akita", + "unknown3": "Akita", + "unknown4": "Akita" + }, + "coordinates": { + "latitude": 39.710082556, + "longitude": 140.098037216 + } + }, + { + "id": 17301504, + "name": "Yamagata", + "translations": { + "japanese": "山形県", + "english": "Yamagata", + "french": "Yamagata", + "german": "Yamagata", + "italian": "Yamagata", + "spanish": "Yamagata", + "chinese_simple": "山形县", + "korean": "야마가타 현", + "dutch": "Yamagata", + "portuguese": "Yamagata", + "russian": "Ямагата", + "chinese_traditional": "山形縣", + "unknown1": "Yamagata", + "unknown2": "Yamagata", + "unknown3": "Yamagata", + "unknown4": "Yamagata" + }, + "coordinates": { + "latitude": 38.248900932, + "longitude": 140.345230271 + } + }, + { + "id": 17367040, + "name": "Fukushima", + "translations": { + "japanese": "福島県", + "english": "Fukushima", + "french": "Fukushima", + "german": "Fukushima", + "italian": "Fukushima", + "spanish": "Fukushima", + "chinese_simple": "福岛县", + "korean": "후쿠시마 현", + "dutch": "Fukushima", + "portuguese": "Fukushima", + "russian": "Фукусима", + "chinese_traditional": "福島縣", + "unknown1": "Fukushima", + "unknown2": "Fukushima", + "unknown3": "Fukushima", + "unknown4": "Fukushima" + }, + "coordinates": { + "latitude": 37.754516172, + "longitude": 140.471573388 + } + }, + { + "id": 17432576, + "name": "Ibaraki", + "translations": { + "japanese": "茨城県", + "english": "Ibaraki", + "french": "Ibaraki", + "german": "Ibaraki", + "italian": "Ibaraki", + "spanish": "Ibaraki", + "chinese_simple": "茨城县", + "korean": "이바라키 현", + "dutch": "Ibaraki", + "portuguese": "Ibaraki", + "russian": "Ибараки", + "chinese_traditional": "茨城縣", + "unknown1": "Ibaraki", + "unknown2": "Ibaraki", + "unknown3": "Ibaraki", + "unknown4": "Ibaraki" + }, + "coordinates": { + "latitude": 36.375732008, + "longitude": 140.471573388 + } + }, + { + "id": 17498112, + "name": "Tochigi", + "translations": { + "japanese": "栃木県", + "english": "Tochigi", + "french": "Tochigi", + "german": "Tochigi", + "italian": "Tochigi", + "spanish": "Tochigi", + "chinese_simple": "枥木县", + "korean": "도치기 현", + "dutch": "Tochigi", + "portuguese": "Tochigi", + "russian": "Тотиги", + "chinese_traditional": "枋木縣", + "unknown1": "Tochigi", + "unknown2": "Tochigi", + "unknown3": "Tochigi", + "unknown4": "Tochigi" + }, + "coordinates": { + "latitude": 36.546020092, + "longitude": 139.867323698 + } + }, + { + "id": 17563648, + "name": "Gunma", + "translations": { + "japanese": "群馬県", + "english": "Gunma", + "french": "Gunma", + "german": "Gunma", + "italian": "Gunma", + "spanish": "Gunma", + "chinese_simple": "群马县", + "korean": "군마 현", + "dutch": "Gunma", + "portuguese": "Gunma", + "russian": "Гумма", + "chinese_traditional": "群馬縣", + "unknown1": "Gunma", + "unknown2": "Gunma", + "unknown3": "Gunma", + "unknown4": "Gunma" + }, + "coordinates": { + "latitude": 36.397704664, + "longitude": 139.065319564 + } + }, + { + "id": 17629184, + "name": "Saitama", + "translations": { + "japanese": "埼玉県", + "english": "Saitama", + "french": "Saitama", + "german": "Saitama", + "italian": "Saitama", + "spanish": "Saitama", + "chinese_simple": "琦玉县", + "korean": "사이타마 현", + "dutch": "Saitama", + "portuguese": "Saitama", + "russian": "Сайтама", + "chinese_traditional": "埼玉縣", + "unknown1": "Saitama", + "unknown2": "Saitama", + "unknown3": "Saitama", + "unknown4": "Saitama" + }, + "coordinates": { + "latitude": 35.87036092, + "longitude": 139.587171569 + } + }, + { + "id": 17694720, + "name": "Chiba", + "translations": { + "japanese": "千葉県", + "english": "Chiba", + "french": "Chiba", + "german": "Chiba", + "italian": "Chiba", + "spanish": "Chiba", + "chinese_simple": "千叶县", + "korean": "지바 현", + "dutch": "Chiba", + "portuguese": "Chiba", + "russian": "Тиба", + "chinese_traditional": "千葉縣", + "unknown1": "Chiba", + "unknown2": "Chiba", + "unknown3": "Chiba", + "unknown4": "Chiba" + }, + "coordinates": { + "latitude": 35.59570272, + "longitude": 140.103530395 + } + }, + { + "id": 17760256, + "name": "Kanagawa", + "translations": { + "japanese": "神奈川県", + "english": "Kanagawa", + "french": "Kanagawa", + "german": "Kanagawa", + "italian": "Kanagawa", + "spanish": "Kanagawa", + "chinese_simple": "神奈川县", + "korean": "가나가와 현", + "dutch": "Kanagawa", + "portuguese": "Kanagawa", + "russian": "Канагава", + "chinese_traditional": "神奈川縣", + "unknown1": "Kanagawa", + "unknown2": "Kanagawa", + "unknown3": "Kanagawa", + "unknown4": "Kanagawa" + }, + "coordinates": { + "latitude": 35.436400964, + "longitude": 139.653089717 + } + }, + { + "id": 17825792, + "name": "Toyama", + "translations": { + "japanese": "富山県", + "english": "Toyama", + "french": "Toyama", + "german": "Toyama", + "italian": "Toyama", + "spanish": "Toyama", + "chinese_simple": "富山县", + "korean": "도야마 현", + "dutch": "Toyama", + "portuguese": "Toyama", + "russian": "Тояма", + "chinese_traditional": "富山縣", + "unknown1": "Toyama", + "unknown2": "Toyama", + "unknown3": "Toyama", + "unknown4": "Toyama" + }, + "coordinates": { + "latitude": 36.705321848, + "longitude": 137.203131883 + } + }, + { + "id": 17891328, + "name": "Ishikawa", + "translations": { + "japanese": "石川県", + "english": "Ishikawa", + "french": "Ishikawa", + "german": "Ishikawa", + "italian": "Ishikawa", + "spanish": "Ishikawa", + "chinese_simple": "石川县", + "korean": "이시카와 현", + "dutch": "Ishikawa", + "portuguese": "Ishikawa", + "russian": "Исикава", + "chinese_traditional": "石川縣", + "unknown1": "Ishikawa", + "unknown2": "Ishikawa", + "unknown3": "Ishikawa", + "unknown4": "Ishikawa" + }, + "coordinates": { + "latitude": 36.584472240000004, + "longitude": 136.637334446 + } + }, + { + "id": 17956864, + "name": "Fukui", + "translations": { + "japanese": "福井県", + "english": "Fukui", + "french": "Fukui", + "german": "Fukui", + "italian": "Fukui", + "spanish": "Fukui", + "chinese_simple": "福井县", + "korean": "후쿠이 현", + "dutch": "Fukui", + "portuguese": "Fukui", + "russian": "Фукуи", + "chinese_traditional": "福井縣", + "unknown1": "Fukui", + "unknown2": "Fukui", + "unknown3": "Fukui", + "unknown4": "Fukui" + }, + "coordinates": { + "latitude": 36.051635332000004, + "longitude": 136.225346021 + } + }, + { + "id": 18022400, + "name": "Yamanashi", + "translations": { + "japanese": "山梨県", + "english": "Yamanashi", + "french": "Yamanashi", + "german": "Yamanashi", + "italian": "Yamanashi", + "spanish": "Yamanashi", + "chinese_simple": "山梨县", + "korean": "야마나시 현", + "dutch": "Yamanashi", + "portuguese": "Yamanashi", + "russian": "Яманаси", + "chinese_traditional": "山梨縣", + "unknown1": "Yamanashi", + "unknown2": "Yamanashi", + "unknown3": "Yamanashi", + "unknown4": "Yamanashi" + }, + "coordinates": { + "latitude": 35.661620688, + "longitude": 138.554453917 + } + }, + { + "id": 18087936, + "name": "Nagano", + "translations": { + "japanese": "長野県", + "english": "Nagano", + "french": "Nagano", + "german": "Nagano", + "italian": "Nagano", + "spanish": "Nagano", + "chinese_simple": "长野县", + "korean": "나가노 현", + "dutch": "Nagano", + "portuguese": "Nagano", + "russian": "Нагано", + "chinese_traditional": "長野縣", + "unknown1": "Nagano", + "unknown2": "Nagano", + "unknown3": "Nagano", + "unknown4": "Nagano" + }, + "coordinates": { + "latitude": 36.655883372, + "longitude": 138.19190410299998 + } + }, + { + "id": 18153472, + "name": "Niigata", + "translations": { + "japanese": "新潟県", + "english": "Niigata", + "french": "Niigata", + "german": "Niigata", + "italian": "Niigata", + "spanish": "Niigata", + "chinese_simple": "新泻县", + "korean": "니가타 현", + "dutch": "Niigata", + "portuguese": "Niigata", + "russian": "Ниигата", + "chinese_traditional": "新潟縣", + "unknown1": "Niigata", + "unknown2": "Niigata", + "unknown3": "Niigata", + "unknown4": "Niigata" + }, + "coordinates": { + "latitude": 37.908324764, + "longitude": 139.048840027 + } + }, + { + "id": 18219008, + "name": "Gifu", + "translations": { + "japanese": "岐阜県", + "english": "Gifu", + "french": "Gifu", + "german": "Gifu", + "italian": "Gifu", + "spanish": "Gifu", + "chinese_simple": "歧阜县", + "korean": "기후 현", + "dutch": "Gifu", + "portuguese": "Gifu", + "russian": "Гифу", + "chinese_traditional": "岐阜縣", + "unknown1": "Gifu", + "unknown2": "Gifu", + "unknown3": "Gifu", + "unknown4": "Gifu" + }, + "coordinates": { + "latitude": 35.392455652, + "longitude": 136.763677563 + } + }, + { + "id": 18284544, + "name": "Shizuoka", + "translations": { + "japanese": "静岡県", + "english": "Shizuoka", + "french": "Shizuoka", + "german": "Shizuoka", + "italian": "Shizuoka", + "spanish": "Shizuoka", + "chinese_simple": "静冈县", + "korean": "시즈오카 현", + "dutch": "Shizuoka", + "portuguese": "Shizuoka", + "russian": "Сидзуока", + "chinese_traditional": "靜岡縣", + "unknown1": "Shizuoka", + "unknown2": "Shizuoka", + "unknown3": "Shizuoka", + "unknown4": "Shizuoka" + }, + "coordinates": { + "latitude": 34.969482024, + "longitude": 138.406138084 + } + }, + { + "id": 18350080, + "name": "Aichi", + "translations": { + "japanese": "愛知県", + "english": "Aichi", + "french": "Aichi", + "german": "Aichi", + "italian": "Aichi", + "spanish": "Aichi", + "chinese_simple": "爱知县", + "korean": "아이치 현", + "dutch": "Aichi", + "portuguese": "Aichi", + "russian": "Айти", + "chinese_traditional": "愛知縣", + "unknown1": "Aichi", + "unknown2": "Aichi", + "unknown3": "Aichi", + "unknown4": "Aichi" + }, + "coordinates": { + "latitude": 35.161742764, + "longitude": 136.966925186 + } + }, + { + "id": 18415616, + "name": "Mie", + "translations": { + "japanese": "三重県", + "english": "Mie", + "french": "Mie", + "german": "Mie", + "italian": "Mie", + "spanish": "Mie", + "chinese_simple": "三重县", + "korean": "미에 현", + "dutch": "Mie", + "portuguese": "Mie", + "russian": "Миэ", + "chinese_traditional": "三重縣", + "unknown1": "Mie", + "unknown2": "Mie", + "unknown3": "Mie", + "unknown4": "Mie" + }, + "coordinates": { + "latitude": 34.727782808, + "longitude": 136.521977687 + } + }, + { + "id": 18481152, + "name": "Shiga", + "translations": { + "japanese": "滋賀県", + "english": "Shiga", + "french": "Shiga", + "german": "Shiga", + "italian": "Shiga", + "spanish": "Shiga", + "chinese_simple": "滋贺县", + "korean": "시가 현", + "dutch": "Shiga", + "portuguese": "Shiga", + "russian": "Сига", + "chinese_traditional": "滋賀縣", + "unknown1": "Shiga", + "unknown2": "Shiga", + "unknown3": "Shiga", + "unknown4": "Shiga" + }, + "coordinates": { + "latitude": 34.985961516, + "longitude": 135.912234818 + } + }, + { + "id": 18546688, + "name": "Kyoto", + "translations": { + "japanese": "京都府", + "english": "Kyoto", + "french": "Kyoto", + "german": "Kyoto", + "italian": "Kyoto", + "spanish": "Kioto", + "chinese_simple": "京都府", + "korean": "교토 부", + "dutch": "Kyoto", + "portuguese": "Quioto", + "russian": "Киото", + "chinese_traditional": "京都府", + "unknown1": "Kyoto", + "unknown2": "Kyoto", + "unknown3": "Kyoto", + "unknown4": "Kyoto" + }, + "coordinates": { + "latitude": 35.007934172, + "longitude": 135.73095991099999 + } + }, + { + "id": 18612224, + "name": "Osaka", + "translations": { + "japanese": "大阪府", + "english": "Osaka", + "french": "Osaka", + "german": "Osaka", + "italian": "Osaka", + "spanish": "Osaka", + "chinese_simple": "大阪府", + "korean": "오사카 부", + "dutch": "Osaka", + "portuguese": "Osaca", + "russian": "Осака", + "chinese_traditional": "大阪府", + "unknown1": "Osaka", + "unknown2": "Osaka", + "unknown3": "Osaka", + "unknown4": "Osaka" + }, + "coordinates": { + "latitude": 34.672851168, + "longitude": 135.522219109 + } + }, + { + "id": 18677760, + "name": "Hyogo", + "translations": { + "japanese": "兵庫県", + "english": "Hyogo", + "french": "Hyogo", + "german": "Hyogo", + "italian": "Hyogo", + "spanish": "Hiogo", + "chinese_simple": "兵库县", + "korean": "효고 현", + "dutch": "Hyogo", + "portuguese": "Hyogo", + "russian": "Хёго", + "chinese_traditional": "兵庫縣", + "unknown1": "Hyogo", + "unknown2": "Hyogo", + "unknown3": "Hyogo", + "unknown4": "Hyogo" + }, + "coordinates": { + "latitude": 34.68933066, + "longitude": 135.214601085 + } + }, + { + "id": 18743296, + "name": "Nara", + "translations": { + "japanese": "奈良県", + "english": "Nara", + "french": "Nara", + "german": "Nara", + "italian": "Nara", + "spanish": "Nara", + "chinese_simple": "奈良县", + "korean": "나라 현", + "dutch": "Nara", + "portuguese": "Nara", + "russian": "Нара", + "chinese_traditional": "奈良縣", + "unknown1": "Nara", + "unknown2": "Nara", + "unknown3": "Nara", + "unknown4": "Nara" + }, + "coordinates": { + "latitude": 34.68933066, + "longitude": 135.829837133 + } + }, + { + "id": 18808832, + "name": "Wakayama", + "translations": { + "japanese": "和歌山県", + "english": "Wakayama", + "french": "Wakayama", + "german": "Wakayama", + "italian": "Wakayama", + "spanish": "Wakayama", + "chinese_simple": "和歌山县", + "korean": "와카야마 현", + "dutch": "Wakayama", + "portuguese": "Wakayama", + "russian": "Вакаяма", + "chinese_traditional": "和歌山縣", + "unknown1": "Wakayama", + "unknown2": "Wakayama", + "unknown3": "Wakayama", + "unknown4": "Wakayama" + }, + "coordinates": { + "latitude": 34.222411720000004, + "longitude": 135.165162474 + } + }, + { + "id": 18874368, + "name": "Tottori", + "translations": { + "japanese": "鳥取県", + "english": "Tottori", + "french": "Tottori", + "german": "Tottori", + "italian": "Tottori", + "spanish": "Totori", + "chinese_simple": "鸟取县", + "korean": "돗토리 현", + "dutch": "Tottori", + "portuguese": "Tottori", + "russian": "Тоттори", + "chinese_traditional": "鳥取縣", + "unknown1": "Tottori", + "unknown2": "Tottori", + "unknown3": "Tottori", + "unknown4": "Tottori" + }, + "coordinates": { + "latitude": 35.480346276, + "longitude": 134.236815223 + } + }, + { + "id": 18939904, + "name": "Shimane", + "translations": { + "japanese": "島根県", + "english": "Shimane", + "french": "Shimane", + "german": "Shimane", + "italian": "Shimane", + "spanish": "Shimane", + "chinese_simple": "岛根县", + "korean": "시마네 현", + "dutch": "Shimane", + "portuguese": "Shimane", + "russian": "Симанэ", + "chinese_traditional": "島根縣", + "unknown1": "Shimane", + "unknown2": "Shimane", + "unknown3": "Shimane", + "unknown4": "Shimane" + }, + "coordinates": { + "latitude": 35.452880456, + "longitude": 133.066768096 + } + }, + { + "id": 19005440, + "name": "Okayama", + "translations": { + "japanese": "岡山県", + "english": "Okayama", + "french": "Okayama", + "german": "Okayama", + "italian": "Okayama", + "spanish": "Okayama", + "chinese_simple": "冈山县", + "korean": "오카야마 현", + "dutch": "Okayama", + "portuguese": "Okayama", + "russian": "Окаяма", + "chinese_traditional": "岡山縣", + "unknown1": "Okayama", + "unknown2": "Okayama", + "unknown3": "Okayama", + "unknown4": "Okayama" + }, + "coordinates": { + "latitude": 34.656371676, + "longitude": 133.918210841 + } + }, + { + "id": 19070976, + "name": "Hiroshima", + "translations": { + "japanese": "広島県", + "english": "Hiroshima", + "french": "Hiroshima", + "german": "Hiroshima", + "italian": "Hiroshima", + "spanish": "Hiroshima", + "chinese_simple": "广岛县", + "korean": "히로시마 현", + "dutch": "Hiroshima", + "portuguese": "Hiroshima", + "russian": "Хиросима", + "chinese_traditional": "廣島縣", + "unknown1": "Hiroshima", + "unknown2": "Hiroshima", + "unknown3": "Hiroshima", + "unknown4": "Hiroshima" + }, + "coordinates": { + "latitude": 34.392699804, + "longitude": 132.462518406 + } + }, + { + "id": 19136512, + "name": "Yamaguchi", + "translations": { + "japanese": "山口県", + "english": "Yamaguchi", + "french": "Yamaguchi", + "german": "Yamaguchi", + "italian": "Yamaguchi", + "spanish": "Yamaguchi", + "chinese_simple": "山口县", + "korean": "야마구치 현", + "dutch": "Yamaguchi", + "portuguese": "Yamaguchi", + "russian": "Ямагути", + "chinese_traditional": "山口縣", + "unknown1": "Yamaguchi", + "unknown2": "Yamaguchi", + "unknown3": "Yamaguchi", + "unknown4": "Yamaguchi" + }, + "coordinates": { + "latitude": 34.156493752, + "longitude": 131.457266649 + } + }, + { + "id": 19202048, + "name": "Tokushima", + "translations": { + "japanese": "徳島県", + "english": "Tokushima", + "french": "Tokushima", + "german": "Tokushima", + "italian": "Tokushima", + "spanish": "Tokushima", + "chinese_simple": "德岛县", + "korean": "도쿠시마 현", + "dutch": "Tokushima", + "portuguese": "Tokushima", + "russian": "Токусима", + "chinese_traditional": "德島縣", + "unknown1": "Tokushima", + "unknown2": "Tokushima", + "unknown3": "Tokushima", + "unknown4": "Tokushima" + }, + "coordinates": { + "latitude": 34.063109964, + "longitude": 134.571899142 + } + }, + { + "id": 19267584, + "name": "Kagawa", + "translations": { + "japanese": "香川県", + "english": "Kagawa", + "french": "Kagawa", + "german": "Kagawa", + "italian": "Kagawa", + "spanish": "Kagawa", + "chinese_simple": "香川县", + "korean": "가가와 현", + "dutch": "Kagawa", + "portuguese": "Kagawa", + "russian": "Кагава", + "chinese_traditional": "香川縣", + "unknown1": "Kagawa", + "unknown2": "Kagawa", + "unknown3": "Kagawa", + "unknown4": "Kagawa" + }, + "coordinates": { + "latitude": 34.310302344, + "longitude": 134.055540316 + } + }, + { + "id": 19333120, + "name": "Ehime", + "translations": { + "japanese": "愛媛県", + "english": "Ehime", + "french": "Ehime", + "german": "Ehime", + "italian": "Ehime", + "spanish": "Ehime", + "chinese_simple": "爱媛县", + "korean": "에히메 현", + "dutch": "Ehime", + "portuguese": "Ehime", + "russian": "Эхимэ", + "chinese_traditional": "愛媛縣", + "unknown1": "Ehime", + "unknown2": "Ehime", + "unknown3": "Ehime", + "unknown4": "Ehime" + }, + "coordinates": { + "latitude": 33.83789024, + "longitude": 132.775629609 + } + }, + { + "id": 19398656, + "name": "Kochi", + "translations": { + "japanese": "高知県", + "english": "Kochi", + "french": "Kochi", + "german": "Kochi", + "italian": "Kochi", + "spanish": "Kochi", + "chinese_simple": "高知县", + "korean": "고치 현", + "dutch": "Kochi", + "portuguese": "Kochi", + "russian": "Коти", + "chinese_traditional": "高知縣", + "unknown1": "Kochi", + "unknown2": "Kochi", + "unknown3": "Kochi", + "unknown4": "Kochi" + }, + "coordinates": { + "latitude": 33.56323204, + "longitude": 133.550167848 + } + }, + { + "id": 19464192, + "name": "Fukuoka", + "translations": { + "japanese": "福岡県", + "english": "Fukuoka", + "french": "Fukuoka", + "german": "Fukuoka", + "italian": "Fukuoka", + "spanish": "Fukuoka", + "chinese_simple": "福冈县", + "korean": "후쿠오카 현", + "dutch": "Fukuoka", + "portuguese": "Fukuoka", + "russian": "Фукуока", + "chinese_traditional": "福岡縣", + "unknown1": "Fukuoka", + "unknown2": "Fukuoka", + "unknown3": "Fukuoka", + "unknown4": "Fukuoka" + }, + "coordinates": { + "latitude": 33.579711532, + "longitude": 130.375110386 + } + }, + { + "id": 19529728, + "name": "Saga", + "translations": { + "japanese": "佐賀県", + "english": "Saga", + "french": "Saga", + "german": "Saga", + "italian": "Saga", + "spanish": "Saga", + "chinese_simple": "佐贺县", + "korean": "사가 현", + "dutch": "Saga", + "portuguese": "Saga", + "russian": "Сага", + "chinese_traditional": "佐賀縣", + "unknown1": "Saga", + "unknown2": "Saga", + "unknown3": "Saga", + "unknown4": "Saga" + }, + "coordinates": { + "latitude": 33.239135364, + "longitude": 130.303699059 + } + }, + { + "id": 19595264, + "name": "Nagasaki", + "translations": { + "japanese": "長崎県", + "english": "Nagasaki", + "french": "Nagasaki", + "german": "Nagasaki", + "italian": "Nagasaki", + "spanish": "Nagasaki", + "chinese_simple": "长崎县", + "korean": "나가사키 현", + "dutch": "Nagasaki", + "portuguese": "Nagasáqui", + "russian": "Нагасаки", + "chinese_traditional": "長崎縣", + "unknown1": "Nagasaki", + "unknown2": "Nagasaki", + "unknown3": "Nagasaki", + "unknown4": "Nagasaki" + }, + "coordinates": { + "latitude": 32.728271112, + "longitude": 129.869737918 + } + }, + { + "id": 19660800, + "name": "Kumamoto", + "translations": { + "japanese": "熊本県", + "english": "Kumamoto", + "french": "Kumamoto", + "german": "Kumamoto", + "italian": "Kumamoto", + "spanish": "Kumamoto", + "chinese_simple": "熊本县", + "korean": "구마모토 현", + "dutch": "Kumamoto", + "portuguese": "Kumamoto", + "russian": "Кумамото", + "chinese_traditional": "熊本縣", + "unknown1": "Kumamoto", + "unknown2": "Kumamoto", + "unknown3": "Kumamoto", + "unknown4": "Kumamoto" + }, + "coordinates": { + "latitude": 32.805175408, + "longitude": 130.710194305 + } + }, + { + "id": 19726336, + "name": "Oita", + "translations": { + "japanese": "大分県", + "english": "Oita", + "french": "Oita", + "german": "Oita", + "italian": "Oita", + "spanish": "Oita", + "chinese_simple": "大分县", + "korean": "오이타 현", + "dutch": "Oita", + "portuguese": "Oita", + "russian": "Оита", + "chinese_traditional": "大分縣", + "unknown1": "Oita", + "unknown2": "Oita", + "unknown3": "Oita", + "unknown4": "Oita" + }, + "coordinates": { + "latitude": 33.228149036, + "longitude": 131.61656883999999 + } + }, + { + "id": 19791872, + "name": "Miyazaki", + "translations": { + "japanese": "宮崎県", + "english": "Miyazaki", + "french": "Miyazaki", + "german": "Miyazaki", + "italian": "Miyazaki", + "spanish": "Miyazaki", + "chinese_simple": "宫崎县", + "korean": "미야자키 현", + "dutch": "Miyazaki", + "portuguese": "Miyazaki", + "russian": "Миядзаки", + "chinese_traditional": "宮崎縣", + "unknown1": "Miyazaki", + "unknown2": "Miyazaki", + "unknown3": "Miyazaki", + "unknown4": "Miyazaki" + }, + "coordinates": { + "latitude": 31.931762332, + "longitude": 131.413321217 + } + }, + { + "id": 19857408, + "name": "Kagoshima", + "translations": { + "japanese": "鹿児島県", + "english": "Kagoshima", + "french": "Kagoshima", + "german": "Kagoshima", + "italian": "Kagoshima", + "spanish": "Kagoshima", + "chinese_simple": "鹿儿岛县", + "korean": "가고시마 현", + "dutch": "Kagoshima", + "portuguese": "Kagoshima", + "russian": "Кагосима", + "chinese_traditional": "鹿兒島縣", + "unknown1": "Kagoshima", + "unknown2": "Kagoshima", + "unknown3": "Kagoshima", + "unknown4": "Kagoshima" + }, + "coordinates": { + "latitude": 31.547240852, + "longitude": 130.550892114 + } + }, + { + "id": 19922944, + "name": "Okinawa", + "translations": { + "japanese": "沖縄県", + "english": "Okinawa", + "french": "Okinawa", + "german": "Okinawa", + "italian": "Okinawa", + "spanish": "Okinawa", + "chinese_simple": "冲绳县", + "korean": "오키나와 현", + "dutch": "Okinawa", + "portuguese": "Okinawa", + "russian": "Окинава", + "chinese_traditional": "沖繩縣", + "unknown1": "Okinawa", + "unknown2": "Okinawa", + "unknown3": "Okinawa", + "unknown4": "Okinawa" + }, + "coordinates": { + "latitude": 26.20239228, + "longitude": 127.683452676 + } + } + ] + }, + { + "id": 8, + "iso_code": "AI", + "name": "Anguilla", + "translations": { + "japanese": "アンギラ", + "english": "Anguilla", + "french": "Anguilla", + "german": "Anguilla", + "italian": "Anguilla", + "spanish": "Anguila", + "chinese_simple": "安圭拉", + "korean": "앵귈라", + "dutch": "Anguilla", + "portuguese": "Anguilha", + "russian": "Ангилья", + "chinese_traditional": "Anguilla", + "unknown1": "Anguilla", + "unknown2": "Anguilla", + "unknown3": "Anguilla", + "unknown4": "Anguilla" + }, + "regions": [ + { + "id": 134217728, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 18.215331824, + "longitude": -63.044725911 + } + }, + { + "id": 134283264, + "name": "Anguilla", + "translations": { + "japanese": "アンギラ", + "english": "Anguilla", + "french": "Anguilla", + "german": "Anguilla", + "italian": "Anguilla", + "spanish": "Anguila", + "chinese_simple": "安圭拉", + "korean": "앵귈라", + "dutch": "Anguilla", + "portuguese": "Anguilha", + "russian": "Ангилья", + "chinese_traditional": "Anguilla", + "unknown1": "Anguilla", + "unknown2": "Anguilla", + "unknown3": "Anguilla", + "unknown4": "Anguilla" + }, + "coordinates": { + "latitude": 18.215331824, + "longitude": -63.044725911 + } + } + ] + }, + { + "id": 9, + "iso_code": "AG", + "name": "Antigua and Barbuda", + "translations": { + "japanese": "アンティグア・バーブーダ", + "english": "Antigua and Barbuda", + "french": "Antigua-et-Barbuda", + "german": "Antigua und Barbuda", + "italian": "Antigua e Barbuda", + "spanish": "Antigua y Barbuda", + "chinese_simple": "安提瓜和巴布达", + "korean": "앤티가 바부다", + "dutch": "Antigua en Barbuda", + "portuguese": "Antígua e Barbuda", + "russian": "Антигуа и Барбуда", + "chinese_traditional": "Antigua and Barbuda", + "unknown1": "Antigua and Barbuda", + "unknown2": "Antigua and Barbuda", + "unknown3": "Antigua and Barbuda", + "unknown4": "Antigua and Barbuda" + }, + "regions": [ + { + "id": 150994944, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 17.111205860000002, + "longitude": -61.847212889000005 + } + }, + { + "id": 151126016, + "name": "Saint John", + "translations": { + "japanese": "セント・ジョン", + "english": "Saint John", + "french": "Saint-Jean", + "german": "Saint John's", + "italian": "Saint John", + "spanish": "Saint John", + "chinese_simple": "圣约翰区", + "korean": "세인트존", + "dutch": "Saint John", + "portuguese": "Saint John", + "russian": "Сент-Джон", + "chinese_traditional": "Saint John", + "unknown1": "Saint John", + "unknown2": "Saint John", + "unknown3": "Saint John", + "unknown4": "Saint John" + }, + "coordinates": { + "latitude": 17.111205860000002, + "longitude": -61.847212889000005 + } + }, + { + "id": 151191552, + "name": "Barbuda", + "translations": { + "japanese": "バーブーダ島", + "english": "Barbuda", + "french": "Barbuda", + "german": "Barbuda", + "italian": "Barbuda", + "spanish": "Barbuda", + "chinese_simple": "巴布达岛", + "korean": "바부다", + "dutch": "Barbuda", + "portuguese": "Barbuda", + "russian": "Барбуда", + "chinese_traditional": "Barbuda", + "unknown1": "Barbuda", + "unknown2": "Barbuda", + "unknown3": "Barbuda", + "unknown4": "Barbuda" + }, + "coordinates": { + "latitude": 17.63305644, + "longitude": -61.830733351999996 + } + }, + { + "id": 151257088, + "name": "Saint George", + "translations": { + "japanese": "セント・ジョージ", + "english": "Saint George", + "french": "Saint-Georges", + "german": "Saint George", + "italian": "Saint George", + "spanish": "Saint George", + "chinese_simple": "圣乔治区", + "korean": "세인트조지", + "dutch": "Saint George", + "portuguese": "Saint George", + "russian": "Сент-Джордж", + "chinese_traditional": "Saint George", + "unknown1": "Saint George", + "unknown2": "Saint George", + "unknown3": "Saint George", + "unknown4": "Saint George" + }, + "coordinates": { + "latitude": 17.133178516, + "longitude": -61.797774278000006 + } + }, + { + "id": 151322624, + "name": "Saint Mary", + "translations": { + "japanese": "セント・メアリー", + "english": "Saint Mary", + "french": "Sainte-Marie", + "german": "Saint Mary", + "italian": "Saint Mary", + "spanish": "Saint Mary", + "chinese_simple": "圣玛丽区", + "korean": "세인트메리", + "dutch": "Saint Mary", + "portuguese": "Saint Mary", + "russian": "Сент-Мэри", + "chinese_traditional": "Saint Mary", + "unknown1": "Saint Mary", + "unknown2": "Saint Mary", + "unknown3": "Saint Mary", + "unknown4": "Saint Mary" + }, + "coordinates": { + "latitude": 17.0288084, + "longitude": -61.880171962999995 + } + }, + { + "id": 151388160, + "name": "Saint Paul", + "translations": { + "japanese": "セント・ポール", + "english": "Saint Paul", + "french": "Saint-Paul", + "german": "Saint Paul", + "italian": "Saint Paul", + "spanish": "Saint Paul", + "chinese_simple": "圣保罗区", + "korean": "세인트폴", + "dutch": "Saint Paul", + "portuguese": "Saint Paul", + "russian": "Сент-Пол", + "chinese_traditional": "Saint Paul", + "unknown1": "Saint Paul", + "unknown2": "Saint Paul", + "unknown3": "Saint Paul", + "unknown4": "Saint Paul" + }, + "coordinates": { + "latitude": 17.0288084, + "longitude": -61.781294740999996 + } + }, + { + "id": 151453696, + "name": "Saint Peter", + "translations": { + "japanese": "セント・ピーター", + "english": "Saint Peter", + "french": "Saint-Pierre", + "german": "Saint Peter", + "italian": "Saint Peter", + "spanish": "Saint Peter", + "chinese_simple": "圣彼得区", + "korean": "세인트피터", + "dutch": "Saint Peter", + "portuguese": "Saint Peter", + "russian": "Сент-Петер", + "chinese_traditional": "Saint Peter", + "unknown1": "Saint Peter", + "unknown2": "Saint Peter", + "unknown3": "Saint Peter", + "unknown4": "Saint Peter" + }, + "coordinates": { + "latitude": 17.078246876, + "longitude": -61.764815204 + } + }, + { + "id": 151519232, + "name": "Saint Philip", + "translations": { + "japanese": "セント・フィリップ", + "english": "Saint Philip", + "french": "Saint-Philippe", + "german": "Saint Philip", + "italian": "Saint Philip", + "spanish": "Saint Philip", + "chinese_simple": "圣菲利普区", + "korean": "세인트필립", + "dutch": "Saint Philip", + "portuguese": "Saint Philip", + "russian": "Сент-Филип", + "chinese_traditional": "Saint Philip", + "unknown1": "Saint Philip", + "unknown2": "Saint Philip", + "unknown3": "Saint Philip", + "unknown4": "Saint Philip" + }, + "coordinates": { + "latitude": 17.045287892, + "longitude": -61.69889705600001 + } + } + ] + }, + { + "id": 10, + "iso_code": "AR", + "name": "Argentina", + "translations": { + "japanese": "アルゼンチン", + "english": "Argentina", + "french": "Argentine", + "german": "Argentinien", + "italian": "Argentina", + "spanish": "Argentina", + "chinese_simple": "阿根廷", + "korean": "아르헨티나", + "dutch": "Argentinië", + "portuguese": "Argentina", + "russian": "Аргентина", + "chinese_traditional": "Argentina", + "unknown1": "Argentina", + "unknown2": "Argentina", + "unknown3": "Argentina", + "unknown4": "Argentina" + }, + "regions": [ + { + "id": 167772160, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": -34.584961568, + "longitude": -58.67215542700001 + } + }, + { + "id": 167903232, + "name": "Distrito Federal", + "translations": { + "japanese": "特別区", + "english": "Distrito Federal", + "french": "District Fédéral", + "german": "Autonome Stadt Buenos Aires", + "italian": "Capitale Federale", + "spanish": "Ciudad de Buenos Aires", + "chinese_simple": "联邦首都区", + "korean": "아르헨티나 연방구", + "dutch": "Federaal District", + "portuguese": "Distrito Federal", + "russian": "Федеральный округ", + "chinese_traditional": "Distrito Federal", + "unknown1": "Distrito Federal", + "unknown2": "Distrito Federal", + "unknown3": "Distrito Federal", + "unknown4": "Distrito Federal" + }, + "coordinates": { + "latitude": -34.584961568, + "longitude": -58.67215542700001 + } + }, + { + "id": 167968768, + "name": "Buenos Aires", + "translations": { + "japanese": "ブエノスアイレス州", + "english": "Buenos Aires", + "french": "Buenos Aires", + "german": "Buenos Aires", + "italian": "Buenos Aires", + "spanish": "Provincia de Buenos Aires", + "chinese_simple": "布宜诺斯艾利斯省", + "korean": "부에노스아이레스 주", + "dutch": "Buenos Aires", + "portuguese": "Buenos Aires", + "russian": "Буэнос-Айрес", + "chinese_traditional": "Buenos Aires", + "unknown1": "Buenos Aires", + "unknown2": "Buenos Aires", + "unknown3": "Buenos Aires", + "unknown4": "Buenos Aires" + }, + "coordinates": { + "latitude": -34.9310309, + "longitude": -57.947055799 + } + }, + { + "id": 168034304, + "name": "Catamarca", + "translations": { + "japanese": "カタマルカ州", + "english": "Catamarca", + "french": "Catamarca", + "german": "Catamarca", + "italian": "Catamarca", + "spanish": "Catamarca", + "chinese_simple": "卡塔马卡省", + "korean": "카타마르카 주", + "dutch": "Catamarca", + "portuguese": "Catamarca", + "russian": "Катамарка", + "chinese_traditional": "Catamarca", + "unknown1": "Catamarca", + "unknown2": "Catamarca", + "unknown3": "Catamarca", + "unknown4": "Catamarca" + }, + "coordinates": { + "latitude": -28.465576872, + "longitude": -65.780329053 + } + }, + { + "id": 168099840, + "name": "Chaco", + "translations": { + "japanese": "チャコ州", + "english": "Chaco", + "french": "Chaco", + "german": "Chaco", + "italian": "Chaco", + "spanish": "Chaco", + "chinese_simple": "查科省", + "korean": "차코 주", + "dutch": "Chaco", + "portuguese": "Chaco", + "russian": "Чако", + "chinese_traditional": "Chaco", + "unknown1": "Chaco", + "unknown2": "Chaco", + "unknown3": "Chaco", + "unknown4": "Chaco" + }, + "coordinates": { + "latitude": -27.449341532, + "longitude": -58.979773451 + } + }, + { + "id": 168165376, + "name": "Chubut", + "translations": { + "japanese": "チュブト州", + "english": "Chubut", + "french": "Chubut", + "german": "Chubut", + "italian": "Chubut", + "spanish": "Chubut", + "chinese_simple": "丘布特省", + "korean": "추부트 주", + "dutch": "Chubut", + "portuguese": "Chubut", + "russian": "Чубут", + "chinese_traditional": "Chubut", + "unknown1": "Chubut", + "unknown2": "Chubut", + "unknown3": "Chubut", + "unknown4": "Chubut" + }, + "coordinates": { + "latitude": -43.297119672, + "longitude": -65.099174857 + } + }, + { + "id": 168230912, + "name": "Córdoba", + "translations": { + "japanese": "コルドバ州", + "english": "Córdoba", + "french": "Córdoba", + "german": "Córdoba", + "italian": "Córdoba", + "spanish": "Córdoba", + "chinese_simple": "科尔多瓦省", + "korean": "코르도바 주", + "dutch": "Córdoba", + "portuguese": "Córdova", + "russian": "Кордова", + "chinese_traditional": "Córdoba", + "unknown1": "Córdoba", + "unknown2": "Córdoba", + "unknown3": "Córdoba", + "unknown4": "Córdoba" + }, + "coordinates": { + "latitude": -31.398926447999997, + "longitude": -64.181813964 + } + }, + { + "id": 168296448, + "name": "Corrientes", + "translations": { + "japanese": "コリエンテス州", + "english": "Corrientes", + "french": "Corrientes", + "german": "Corrientes", + "italian": "Corrientes", + "spanish": "Corrientes", + "chinese_simple": "科连特斯省", + "korean": "코리엔테스 주", + "dutch": "Corrientes", + "portuguese": "Corrientes", + "russian": "Корриентес", + "chinese_traditional": "Corrientes", + "unknown1": "Corrientes", + "unknown2": "Corrientes", + "unknown3": "Corrientes", + "unknown4": "Corrientes" + }, + "coordinates": { + "latitude": -27.465821024, + "longitude": -58.831457618 + } + }, + { + "id": 168361984, + "name": "Entre Ríos", + "translations": { + "japanese": "エントレ・リオス州", + "english": "Entre Ríos", + "french": "Entre Ríos", + "german": "Entre Ríos", + "italian": "Entre Ríos", + "spanish": "Entre Ríos", + "chinese_simple": "恩特雷里奥斯省", + "korean": "엔트레리오스 주", + "dutch": "Entre Ríos", + "portuguese": "Entre Ríos", + "russian": "Энтре-Риос", + "chinese_traditional": "Entre Ríos", + "unknown1": "Entre Ríos", + "unknown2": "Entre Ríos", + "unknown3": "Entre Ríos", + "unknown4": "Entre Ríos" + }, + "coordinates": { + "latitude": -31.728516288, + "longitude": -60.528849929 + } + }, + { + "id": 168427520, + "name": "Formosa", + "translations": { + "japanese": "フォルモサ州", + "english": "Formosa", + "french": "Formosa", + "german": "Formosa", + "italian": "Formosa", + "spanish": "Formosa", + "chinese_simple": "福尔摩沙省", + "korean": "포르모사 주", + "dutch": "Formosa", + "portuguese": "Formosa", + "russian": "Формоса", + "chinese_traditional": "Formosa", + "unknown1": "Formosa", + "unknown2": "Formosa", + "unknown3": "Formosa", + "unknown4": "Formosa" + }, + "coordinates": { + "latitude": -26.180420648000002, + "longitude": -58.177769317 + } + }, + { + "id": 168493056, + "name": "Jujuy", + "translations": { + "japanese": "フフイ州", + "english": "Jujuy", + "french": "Jujuy", + "german": "Jujuy", + "italian": "Jujuy", + "spanish": "Jujuy", + "chinese_simple": "胡胡伊省", + "korean": "후후이 주", + "dutch": "Jujuy", + "portuguese": "Jujuy", + "russian": "Жужуй", + "chinese_traditional": "Jujuy", + "unknown1": "Jujuy", + "unknown2": "Jujuy", + "unknown3": "Jujuy", + "unknown4": "Jujuy" + }, + "coordinates": { + "latitude": -24.180908951999996, + "longitude": -65.296929301 + } + }, + { + "id": 168558592, + "name": "La Pampa", + "translations": { + "japanese": "ラ・パンパ州", + "english": "La Pampa", + "french": "La Pampa", + "german": "La Pampa", + "italian": "La Pampa", + "spanish": "La Pampa", + "chinese_simple": "拉潘帕省", + "korean": "라팜파 주", + "dutch": "La Pampa", + "portuguese": "La Pampa", + "russian": "Ла-Пампа", + "chinese_traditional": "La Pampa", + "unknown1": "La Pampa", + "unknown2": "La Pampa", + "unknown3": "La Pampa", + "unknown4": "La Pampa" + }, + "coordinates": { + "latitude": -36.611939084, + "longitude": -64.280691186 + } + }, + { + "id": 168624128, + "name": "La Rioja", + "translations": { + "japanese": "ラ・リオハ州", + "english": "La Rioja", + "french": "La Rioja", + "german": "La Rioja", + "italian": "La Rioja", + "spanish": "La Rioja", + "chinese_simple": "拉里奥哈省", + "korean": "라리오하 주", + "dutch": "La Rioja", + "portuguese": "La Rioja", + "russian": "Ла-Риоха", + "chinese_traditional": "La Rioja", + "unknown1": "La Rioja", + "unknown2": "La Rioja", + "unknown3": "La Rioja", + "unknown4": "La Rioja" + }, + "coordinates": { + "latitude": -29.432373736000002, + "longitude": -66.846005779 + } + }, + { + "id": 168689664, + "name": "Mendoza", + "translations": { + "japanese": "メンドーサ州", + "english": "Mendoza", + "french": "Mendoza", + "german": "Mendoza", + "italian": "Mendoza", + "spanish": "Mendoza", + "chinese_simple": "门多萨省", + "korean": "멘도사 주", + "dutch": "Mendoza", + "portuguese": "Mendoza", + "russian": "Мендоса", + "chinese_traditional": "Mendoza", + "unknown1": "Mendoza", + "unknown2": "Mendoza", + "unknown3": "Mendoza", + "unknown4": "Mendoza" + }, + "coordinates": { + "latitude": -32.882080728, + "longitude": -68.812563861 + } + }, + { + "id": 168755200, + "name": "Misiones", + "translations": { + "japanese": "ミシオネス州", + "english": "Misiones", + "french": "Misiones", + "german": "Misiones", + "italian": "Misiones", + "spanish": "Misiones", + "chinese_simple": "米西奥内斯省", + "korean": "미시오네스 주", + "dutch": "Misiones", + "portuguese": "Misiones", + "russian": "Мисьонес", + "chinese_traditional": "Misiones", + "unknown1": "Misiones", + "unknown2": "Misiones", + "unknown3": "Misiones", + "unknown4": "Misiones" + }, + "coordinates": { + "latitude": -27.377930399999997, + "longitude": -55.88162049500001 + } + }, + { + "id": 168820736, + "name": "Neuquén", + "translations": { + "japanese": "ネウケン州", + "english": "Neuquén", + "french": "Neuquén", + "german": "Neuquén", + "italian": "Neuquén", + "spanish": "Neuquén", + "chinese_simple": "内乌肯省", + "korean": "네우켄 주", + "dutch": "Neuquén", + "portuguese": "Neuquén", + "russian": "Неукен", + "chinese_traditional": "Neuquén", + "unknown1": "Neuquén", + "unknown2": "Neuquén", + "unknown3": "Neuquén", + "unknown4": "Neuquén" + }, + "coordinates": { + "latitude": -38.946533784, + "longitude": -68.065491517 + } + }, + { + "id": 168886272, + "name": "Río Negro", + "translations": { + "japanese": "リオネグロ州", + "english": "Río Negro", + "french": "Río Negro", + "german": "Río Negro", + "italian": "Río Negro", + "spanish": "Río Negro", + "chinese_simple": "里奥内格罗省", + "korean": "리오네그로 주", + "dutch": "Río Negro", + "portuguese": "Río Negro", + "russian": "Рио-Негро", + "chinese_traditional": "Río Negro", + "unknown1": "Río Negro", + "unknown2": "Río Negro", + "unknown3": "Río Negro", + "unknown4": "Río Negro" + }, + "coordinates": { + "latitude": -40.797730052, + "longitude": -62.9952873 + } + }, + { + "id": 168951808, + "name": "Salta", + "translations": { + "japanese": "サルタ州", + "english": "Salta", + "french": "Salta", + "german": "Salta", + "italian": "Salta", + "spanish": "Salta", + "chinese_simple": "萨尔塔省", + "korean": "살타 주", + "dutch": "Salta", + "portuguese": "Salta", + "russian": "Сальта", + "chinese_traditional": "Salta", + "unknown1": "Salta", + "unknown2": "Salta", + "unknown3": "Salta", + "unknown4": "Salta" + }, + "coordinates": { + "latitude": -24.779663827999997, + "longitude": -65.41228606 + } + }, + { + "id": 169017344, + "name": "San Juan", + "translations": { + "japanese": "サン・フアン州", + "english": "San Juan", + "french": "San Juan", + "german": "San Juan", + "italian": "San Juan", + "spanish": "San Juan", + "chinese_simple": "圣胡安省", + "korean": "산후안 주", + "dutch": "San Juan", + "portuguese": "San Juan", + "russian": "Сан-Хуан", + "chinese_traditional": "San Juan", + "unknown1": "San Juan", + "unknown2": "San Juan", + "unknown3": "San Juan", + "unknown4": "San Juan" + }, + "coordinates": { + "latitude": -31.536255548, + "longitude": -68.532411732 + } + }, + { + "id": 169082880, + "name": "San Luis", + "translations": { + "japanese": "サン・ルイス州", + "english": "San Luis", + "french": "San Luis", + "german": "San Luis", + "italian": "San Luis", + "spanish": "San Luis", + "chinese_simple": "圣路易斯省", + "korean": "산루이스 주", + "dutch": "San Luis", + "portuguese": "San Luís", + "russian": "Сан-Луис", + "chinese_traditional": "San Luis", + "unknown1": "San Luis", + "unknown2": "San Luis", + "unknown3": "San Luis", + "unknown4": "San Luis" + }, + "coordinates": { + "latitude": -33.299561192, + "longitude": -66.34612649 + } + }, + { + "id": 169148416, + "name": "Santa Cruz", + "translations": { + "japanese": "サンタ・クルス州", + "english": "Santa Cruz", + "french": "Santa Cruz", + "german": "Santa Cruz", + "italian": "Santa Cruz", + "spanish": "Santa Cruz", + "chinese_simple": "圣克鲁斯省", + "korean": "산타크루스 주", + "dutch": "Santa Cruz", + "portuguese": "Santa Cruz", + "russian": "Санта-Крус", + "chinese_traditional": "Santa Cruz", + "unknown1": "Santa Cruz", + "unknown2": "Santa Cruz", + "unknown3": "Santa Cruz", + "unknown4": "Santa Cruz" + }, + "coordinates": { + "latitude": -51.63024946, + "longitude": -69.213565928 + } + }, + { + "id": 169213952, + "name": "Santa Fe", + "translations": { + "japanese": "サンタ・フェ州", + "english": "Santa Fe", + "french": "Santa Fe", + "german": "Santa Fe", + "italian": "Santa Fe", + "spanish": "Santa Fe", + "chinese_simple": "圣菲省", + "korean": "산타페 주", + "dutch": "Santa Fe", + "portuguese": "Santa Fé", + "russian": "Санта-Фе", + "chinese_traditional": "Santa Fe", + "unknown1": "Santa Fe", + "unknown2": "Santa Fe", + "unknown3": "Santa Fe", + "unknown4": "Santa Fe" + }, + "coordinates": { + "latitude": -31.629639335999997, + "longitude": -60.699138477999995 + } + }, + { + "id": 169279488, + "name": "Santiago del Estero", + "translations": { + "japanese": "サンティアゴ・デル・エステロ州", + "english": "Santiago del Estero", + "french": "Santiago del Estero", + "german": "Santiago del Estero", + "italian": "Santiago del Estero", + "spanish": "Santiago del Estero", + "chinese_simple": "圣地亚哥-德尔埃斯特罗省", + "korean": "산티아고델에스테로 주", + "dutch": "Santiago del Estero", + "portuguese": "Santiago del Estero", + "russian": "Сантьяго-дель-Эстеро", + "chinese_traditional": "Santiago del Estero", + "unknown1": "Santiago del Estero", + "unknown2": "Santiago del Estero", + "unknown3": "Santiago del Estero", + "unknown4": "Santiago del Estero" + }, + "coordinates": { + "latitude": -27.778931372000002, + "longitude": -64.264211649 + } + }, + { + "id": 169345024, + "name": "Tierra del Fuego, Antártida e Islas del Atlántico Sur", + "translations": { + "japanese": "ティエラ・デル・フエゴ州", + "english": "Tierra del Fuego, Antártida e Islas del Atlántico Sur", + "french": "Terre de Feu, Antarctique et Îles de l’Atlantique Sud", + "german": "Feuerland", + "italian": "Terra del Fuoco", + "spanish": "Tierra del Fuego", + "chinese_simple": "火地岛省", + "korean": "티에라델푸에고 주", + "dutch": "Vuurland", + "portuguese": "Terra do Fogo, Antártida e Ilhas do Atlântico Sul", + "russian": "Огненная Земля", + "chinese_traditional": "Tierra del Fuego, Antártida e Islas del Atlántico Sur", + "unknown1": "Tierra del Fuego, Antártida e Islas del Atlántico Sur", + "unknown2": "Tierra del Fuego, Antártida e Islas del Atlántico Sur", + "unknown3": "Tierra del Fuego, Antártida e Islas del Atlántico Sur", + "unknown4": "Tierra del Fuego, Antártida e Islas del Atlántico Sur" + }, + "coordinates": { + "latitude": -54.799805088, + "longitude": -68.296205035 + } + }, + { + "id": 169410560, + "name": "Tucumán", + "translations": { + "japanese": "トゥクマン州", + "english": "Tucumán", + "french": "Tucumán", + "german": "Tucumán", + "italian": "Tucumán", + "spanish": "Tucumán", + "chinese_simple": "图库曼省", + "korean": "투쿠만 주", + "dutch": "Tucumán", + "portuguese": "Tucumán", + "russian": "Тукуман", + "chinese_traditional": "Tucumán", + "unknown1": "Tucumán", + "unknown2": "Tucumán", + "unknown3": "Tucumán", + "unknown4": "Tucumán" + }, + "coordinates": { + "latitude": -26.812134508, + "longitude": -65.214531616 + } + } + ] + }, + { + "id": 11, + "iso_code": "AW", + "name": "Aruba", + "translations": { + "japanese": "アルバ", + "english": "Aruba", + "french": "Aruba", + "german": "Aruba", + "italian": "Aruba", + "spanish": "Aruba", + "chinese_simple": "阿鲁巴", + "korean": "아루바", + "dutch": "Aruba", + "portuguese": "Aruba", + "russian": "Аруба", + "chinese_traditional": "Aruba", + "unknown1": "Aruba", + "unknown2": "Aruba", + "unknown3": "Aruba", + "unknown4": "Aruba" + }, + "regions": [ + { + "id": 184549376, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 12.513427592, + "longitude": -70.032049599 + } + }, + { + "id": 184614912, + "name": "Aruba", + "translations": { + "japanese": "アルバ", + "english": "Aruba", + "french": "Aruba", + "german": "Aruba", + "italian": "Aruba", + "spanish": "Aruba", + "chinese_simple": "阿鲁巴", + "korean": "아루바", + "dutch": "Aruba", + "portuguese": "Aruba", + "russian": "Аруба", + "chinese_traditional": "Aruba", + "unknown1": "Aruba", + "unknown2": "Aruba", + "unknown3": "Aruba", + "unknown4": "Aruba" + }, + "coordinates": { + "latitude": 12.513427592, + "longitude": -70.032049599 + } + } + ] + }, + { + "id": 12, + "iso_code": "BS", + "name": "Bahamas", + "translations": { + "japanese": "バハマ", + "english": "Bahamas", + "french": "Bahamas", + "german": "Bahamas", + "italian": "Bahamas", + "spanish": "Bahamas", + "chinese_simple": "巴哈马", + "korean": "바하마", + "dutch": "Bahama's", + "portuguese": "Bahamas", + "russian": "Багамские острова", + "chinese_traditional": "Bahamas", + "unknown1": "Bahamas", + "unknown2": "Bahamas", + "unknown3": "Bahamas", + "unknown4": "Bahamas" + }, + "regions": [ + { + "id": 201326592, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 25.081786824, + "longitude": -77.34896402700001 + } + }, + { + "id": 201392128, + "name": "Bahamas", + "translations": { + "japanese": "バハマ", + "english": "Bahamas", + "french": "Bahamas", + "german": "Bahamas", + "italian": "Bahamas", + "spanish": "Bahamas", + "chinese_simple": "巴哈马", + "korean": "바하마", + "dutch": "Bahama's", + "portuguese": "Bahamas", + "russian": "Багамские острова", + "chinese_traditional": "Bahamas", + "unknown1": "Bahamas", + "unknown2": "Bahamas", + "unknown3": "Bahamas", + "unknown4": "Bahamas" + }, + "coordinates": { + "latitude": 25.081786824, + "longitude": -77.34896402700001 + } + } + ] + }, + { + "id": 13, + "iso_code": "BB", + "name": "Barbados", + "translations": { + "japanese": "バルバドス", + "english": "Barbados", + "french": "Barbade", + "german": "Barbados", + "italian": "Barbados", + "spanish": "Barbados", + "chinese_simple": "巴巴多斯", + "korean": "바베이도스", + "dutch": "Barbados", + "portuguese": "Barbados", + "russian": "Барбадос", + "chinese_traditional": "Barbados", + "unknown1": "Barbados", + "unknown2": "Barbados", + "unknown3": "Barbados", + "unknown4": "Barbados" + }, + "regions": [ + { + "id": 218103808, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 13.095702976, + "longitude": -59.611489035999995 + } + }, + { + "id": 218169344, + "name": "Barbados", + "translations": { + "japanese": "バルバドス", + "english": "Barbados", + "french": "Barbade", + "german": "Barbados", + "italian": "Barbados", + "spanish": "Barbados", + "chinese_simple": "巴巴多斯", + "korean": "바베이도스", + "dutch": "Barbados", + "portuguese": "Barbados", + "russian": "Барбадос", + "chinese_traditional": "Barbados", + "unknown1": "Barbados", + "unknown2": "Barbados", + "unknown3": "Barbados", + "unknown4": "Barbados" + }, + "coordinates": { + "latitude": 13.095702976, + "longitude": -59.611489035999995 + } + } + ] + }, + { + "id": 14, + "iso_code": "BZ", + "name": "Belize", + "translations": { + "japanese": "ベリーズ", + "english": "Belize", + "french": "Belize", + "german": "Belize", + "italian": "Belize", + "spanish": "Belice", + "chinese_simple": "伯利兹", + "korean": "벨리즈", + "dutch": "Belize", + "portuguese": "Belize", + "russian": "Белиз", + "chinese_traditional": "Belize", + "unknown1": "Belize", + "unknown2": "Belize", + "unknown3": "Belize", + "unknown4": "Belize" + }, + "regions": [ + { + "id": 234881024, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 17.24853496, + "longitude": -88.763789989 + } + }, + { + "id": 235012096, + "name": "Cayo", + "translations": { + "japanese": "カヨー州", + "english": "Cayo", + "french": "Cayo", + "german": "Cayo", + "italian": "Cayo", + "spanish": "Cayo", + "chinese_simple": "卡约区", + "korean": "카요 주", + "dutch": "Cayo", + "portuguese": "Cayo", + "russian": "Кайо", + "chinese_traditional": "Cayo", + "unknown1": "Cayo", + "unknown2": "Cayo", + "unknown3": "Cayo", + "unknown4": "Cayo" + }, + "coordinates": { + "latitude": 17.24853496, + "longitude": -88.763789989 + } + }, + { + "id": 235077632, + "name": "Belize", + "translations": { + "japanese": "ベリーズ州", + "english": "Belize", + "french": "Belize", + "german": "Belize", + "italian": "Belize", + "spanish": "Belice", + "chinese_simple": "伯利兹城", + "korean": "벨리즈 주", + "dutch": "Belize", + "portuguese": "Belize", + "russian": "Белиз", + "chinese_traditional": "Belize", + "unknown1": "Belize", + "unknown2": "Belize", + "unknown3": "Belize", + "unknown4": "Belize" + }, + "coordinates": { + "latitude": 17.479247848, + "longitude": -88.18151301500001 + } + }, + { + "id": 235143168, + "name": "Corozal", + "translations": { + "japanese": "コロサル州", + "english": "Corozal", + "french": "Corozal", + "german": "Corozal", + "italian": "Corozal", + "spanish": "Corozal", + "chinese_simple": "科罗萨尔区", + "korean": "코로살 주", + "dutch": "Corozal", + "portuguese": "Corozal", + "russian": "Корозал", + "chinese_traditional": "Corozal", + "unknown1": "Corozal", + "unknown2": "Corozal", + "unknown3": "Corozal", + "unknown4": "Corozal" + }, + "coordinates": { + "latitude": 18.380126744000002, + "longitude": -88.379267459 + } + }, + { + "id": 235208704, + "name": "Orange Walk", + "translations": { + "japanese": "オレンジウォーク州", + "english": "Orange Walk", + "french": "Orange Walk", + "german": "Orange Walk", + "italian": "Orange Walk", + "spanish": "Orange Walk", + "chinese_simple": "橘园区", + "korean": "오렌지워크 주", + "dutch": "Orange Walk", + "portuguese": "Orange Walk", + "russian": "Ориндж Уолк", + "chinese_traditional": "Orange Walk", + "unknown1": "Orange Walk", + "unknown2": "Orange Walk", + "unknown3": "Orange Walk", + "unknown4": "Orange Walk" + }, + "coordinates": { + "latitude": 18.061523232, + "longitude": -88.549556008 + } + }, + { + "id": 235274240, + "name": "Stann Creek", + "translations": { + "japanese": "スタンクリーク州", + "english": "Stann Creek", + "french": "Stann Creek", + "german": "Stann Creek", + "italian": "Stann Creek", + "spanish": "Stann Creek", + "chinese_simple": "斯坦港区", + "korean": "스탠크리크 주", + "dutch": "Stann Creek", + "portuguese": "Stann Creek", + "russian": "Стэн Крик", + "chinese_traditional": "Stann Creek", + "unknown1": "Stann Creek", + "unknown2": "Stann Creek", + "unknown3": "Stann Creek", + "unknown4": "Stann Creek" + }, + "coordinates": { + "latitude": 16.962890432000002, + "longitude": -88.214472089 + } + }, + { + "id": 235339776, + "name": "Toledo", + "translations": { + "japanese": "トレド州", + "english": "Toledo", + "french": "Toledo", + "german": "Toledo", + "italian": "Toledo", + "spanish": "Toledo", + "chinese_simple": "托莱多区", + "korean": "톨레도 주", + "dutch": "Toledo", + "portuguese": "Toledo", + "russian": "Толедо", + "chinese_traditional": "Toledo", + "unknown1": "Toledo", + "unknown2": "Toledo", + "unknown3": "Toledo", + "unknown4": "Toledo" + }, + "coordinates": { + "latitude": 16.09497052, + "longitude": -88.79674906300001 + } + } + ] + }, + { + "id": 15, + "iso_code": "BO", + "name": "Bolivia", + "translations": { + "japanese": "ボリビア", + "english": "Bolivia", + "french": "Bolivie", + "german": "Bolivien", + "italian": "Bolivia", + "spanish": "Bolivia", + "chinese_simple": "玻利维亚", + "korean": "볼리비아", + "dutch": "Bolivia", + "portuguese": "Bolívia", + "russian": "Боливия", + "chinese_traditional": "Bolivia", + "unknown1": "Bolivia", + "unknown2": "Bolivia", + "unknown3": "Bolivia", + "unknown4": "Bolivia" + }, + "regions": [ + { + "id": 251658240, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": -16.495972515999995, + "longitude": -68.147889202 + } + }, + { + "id": 251789312, + "name": "La Paz", + "translations": { + "japanese": "ラパス県", + "english": "La Paz", + "french": "La Paz", + "german": "La Paz", + "italian": "La Paz", + "spanish": "La Paz", + "chinese_simple": "拉巴斯省", + "korean": "라파스 주", + "dutch": "La Paz", + "portuguese": "La Paz", + "russian": "Ла-Пас", + "chinese_traditional": "La Paz", + "unknown1": "La Paz", + "unknown2": "La Paz", + "unknown3": "La Paz", + "unknown4": "La Paz" + }, + "coordinates": { + "latitude": -16.495972515999995, + "longitude": -68.147889202 + } + }, + { + "id": 251854848, + "name": "Chuquisaca", + "translations": { + "japanese": "チュキサカ県", + "english": "Chuquisaca", + "french": "Chuquisaca", + "german": "Chuquisaca", + "italian": "Chuquisaca", + "spanish": "Chuquisaca", + "chinese_simple": "丘基萨卡省", + "korean": "추키사카 주", + "dutch": "Chuquisaca", + "portuguese": "Chuquisaca", + "russian": "Чукисака", + "chinese_traditional": "Chuquisaca", + "unknown1": "Chuquisaca", + "unknown2": "Chuquisaca", + "unknown3": "Chuquisaca", + "unknown4": "Chuquisaca" + }, + "coordinates": { + "latitude": -19.039307448000002, + "longitude": -65.258477048 + } + }, + { + "id": 251920384, + "name": "Cochabamba", + "translations": { + "japanese": "コチャバンバ県", + "english": "Cochabamba", + "french": "Cochabamba", + "german": "Cochabamba", + "italian": "Cochabamba", + "spanish": "Cochabamba", + "chinese_simple": "科恰班巴省", + "korean": "코차밤바 주", + "dutch": "Cochabamba", + "portuguese": "Cochabamba", + "russian": "Кочабамба", + "chinese_traditional": "Cochabamba", + "unknown1": "Cochabamba", + "unknown2": "Cochabamba", + "unknown3": "Cochabamba", + "unknown4": "Cochabamba" + }, + "coordinates": { + "latitude": -17.38037192, + "longitude": -66.148372046 + } + }, + { + "id": 251985920, + "name": "El Beni", + "translations": { + "japanese": "ベニ県", + "english": "El Beni", + "french": "Beni", + "german": "Beni", + "italian": "Beni", + "spanish": "El Beni", + "chinese_simple": "贝尼省", + "korean": "엘베니 주", + "dutch": "Beni", + "portuguese": "El Beni", + "russian": "Бени", + "chinese_traditional": "El Beni", + "unknown1": "El Beni", + "unknown2": "El Beni", + "unknown3": "El Beni", + "unknown4": "El Beni" + }, + "coordinates": { + "latitude": -14.831543823999993, + "longitude": -64.895927234 + } + }, + { + "id": 252051456, + "name": "Oruro", + "translations": { + "japanese": "オルロ県", + "english": "Oruro", + "french": "Oruro", + "german": "Oruro", + "italian": "Oruro", + "spanish": "Oruro", + "chinese_simple": "奥鲁罗省", + "korean": "오루로 주", + "dutch": "Oruro", + "portuguese": "Oruro", + "russian": "Оруро", + "chinese_traditional": "Oruro", + "unknown1": "Oruro", + "unknown2": "Oruro", + "unknown3": "Oruro", + "unknown4": "Oruro" + }, + "coordinates": { + "latitude": -17.979126796000003, + "longitude": -67.148130624 + } + }, + { + "id": 252116992, + "name": "Pando", + "translations": { + "japanese": "パンド県", + "english": "Pando", + "french": "Pando", + "german": "Pando", + "italian": "Pando", + "spanish": "Pando", + "chinese_simple": "潘多省", + "korean": "판도 주", + "dutch": "Pando", + "portuguese": "Pando", + "russian": "Пандо", + "chinese_traditional": "Pando", + "unknown1": "Pando", + "unknown2": "Pando", + "unknown3": "Pando", + "unknown4": "Pando" + }, + "coordinates": { + "latitude": -11.030274336000005, + "longitude": -68.730166176 + } + }, + { + "id": 252182528, + "name": "Potosí", + "translations": { + "japanese": "ポトシ県", + "english": "Potosí", + "french": "Potosí", + "german": "Potosí", + "italian": "Potosí", + "spanish": "Potosí", + "chinese_simple": "波托西省", + "korean": "포토시 주", + "dutch": "Potosí", + "portuguese": "Potosí", + "russian": "Потоси", + "chinese_traditional": "Potosí", + "unknown1": "Potosí", + "unknown2": "Potosí", + "unknown3": "Potosí", + "unknown4": "Potosí" + }, + "coordinates": { + "latitude": -19.583130683999997, + "longitude": -65.747369979 + } + }, + { + "id": 252248064, + "name": "Santa Cruz", + "translations": { + "japanese": "サンタ・クルス県", + "english": "Santa Cruz", + "french": "Santa Cruz", + "german": "Santa Cruz", + "italian": "Santa Cruz", + "spanish": "Santa Cruz", + "chinese_simple": "圣克鲁斯省", + "korean": "산타크루스 주", + "dutch": "Santa Cruz", + "portuguese": "Santa Cruz", + "russian": "Санта-Крус", + "chinese_traditional": "Santa Cruz", + "unknown1": "Santa Cruz", + "unknown2": "Santa Cruz", + "unknown3": "Santa Cruz", + "unknown4": "Santa Cruz" + }, + "coordinates": { + "latitude": -17.797852383999995, + "longitude": -63.16557584900001 + } + }, + { + "id": 252313600, + "name": "Tarija", + "translations": { + "japanese": "タリハ県", + "english": "Tarija", + "french": "Tarija", + "german": "Tarija", + "italian": "Tarija", + "spanish": "Tarija", + "chinese_simple": "塔里哈省", + "korean": "타리하 주", + "dutch": "Tarija", + "portuguese": "Tarija", + "russian": "Тариха", + "chinese_traditional": "Tarija", + "unknown1": "Tarija", + "unknown2": "Tarija", + "unknown3": "Tarija", + "unknown4": "Tarija" + }, + "coordinates": { + "latitude": -21.511231248, + "longitude": -64.747611401 + } + } + ] + }, + { + "id": 16, + "iso_code": "BR", + "name": "Brazil", + "translations": { + "japanese": "ブラジル", + "english": "Brazil", + "french": "Brésil", + "german": "Brasilien", + "italian": "Brasile", + "spanish": "Brasil", + "chinese_simple": "巴西", + "korean": "브라질", + "dutch": "Brazilië", + "portuguese": "Brasil", + "russian": "Бразилия", + "chinese_traditional": "Brazil", + "unknown1": "Brazil", + "unknown2": "Brazil", + "unknown3": "Brazil", + "unknown4": "Brazil" + }, + "regions": [ + { + "id": 268435456, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": -15.781861195999994, + "longitude": -47.911017766000015 + } + }, + { + "id": 268566528, + "name": "Distrito Federal", + "translations": { + "japanese": "ディストリト・フェデラル州", + "english": "Distrito Federal", + "french": "District Fédéral", + "german": "Distrito Federal", + "italian": "Distretto Federale", + "spanish": "Distrito Federal", + "chinese_simple": "联邦区", + "korean": "브라질 연방구", + "dutch": "Federaal District", + "portuguese": "Distrito Federal", + "russian": "Федеральный округ", + "chinese_traditional": "Distrito Federal", + "unknown1": "Distrito Federal", + "unknown2": "Distrito Federal", + "unknown3": "Distrito Federal", + "unknown4": "Distrito Federal" + }, + "coordinates": { + "latitude": -15.781861195999994, + "longitude": -47.911017766000015 + } + }, + { + "id": 268632064, + "name": "Acre", + "translations": { + "japanese": "アクレ州", + "english": "Acre", + "french": "Acre", + "german": "Acre", + "italian": "Acre", + "spanish": "Acre", + "chinese_simple": "阿克里州", + "korean": "아크리 주", + "dutch": "Acre", + "portuguese": "Acre", + "russian": "Акри", + "chinese_traditional": "Acre", + "unknown1": "Acre", + "unknown2": "Acre", + "unknown3": "Acre", + "unknown4": "Acre" + }, + "coordinates": { + "latitude": -9.964600520000005, + "longitude": -67.79632574600001 + } + }, + { + "id": 268697600, + "name": "Alagoas", + "translations": { + "japanese": "アラゴアス州", + "english": "Alagoas", + "french": "Alagoas", + "german": "Alagoas", + "italian": "Alagoas", + "spanish": "Alagoas", + "chinese_simple": "阿拉戈斯州", + "korean": "알라고아스 주", + "dutch": "Alagoas", + "portuguese": "Alagoas", + "russian": "Алагоас", + "chinese_traditional": "Alagoas", + "unknown1": "Alagoas", + "unknown2": "Alagoas", + "unknown3": "Alagoas", + "unknown4": "Alagoas" + }, + "coordinates": { + "latitude": -9.662476499999997, + "longitude": -35.71616038600001 + } + }, + { + "id": 268763136, + "name": "Amapá", + "translations": { + "japanese": "アマパー州", + "english": "Amapá", + "french": "Amapá", + "german": "Amapá", + "italian": "Amapá", + "spanish": "Amapá", + "chinese_simple": "阿马帕州", + "korean": "아마파 주", + "dutch": "Amapá", + "portuguese": "Amapá", + "russian": "Амапа", + "chinese_traditional": "Amapá", + "unknown1": "Amapá", + "unknown2": "Amapá", + "unknown3": "Amapá", + "unknown4": "Amapá" + }, + "coordinates": { + "latitude": 0.032958984, + "longitude": -51.047622974999996 + } + }, + { + "id": 268828672, + "name": "Amazonas", + "translations": { + "japanese": "アマゾナス州", + "english": "Amazonas", + "french": "Amazonas", + "german": "Amazonas", + "italian": "Amazonas", + "spanish": "Amazonas", + "chinese_simple": "亚马孙州", + "korean": "아마조나스 주", + "dutch": "Amazonas", + "portuguese": "Amazonas", + "russian": "Амазонас", + "chinese_traditional": "Amazonas", + "unknown1": "Amazonas", + "unknown2": "Amazonas", + "unknown3": "Amazonas", + "unknown4": "Amazonas" + }, + "coordinates": { + "latitude": -3.109131848000004, + "longitude": -60.023477461 + } + }, + { + "id": 268894208, + "name": "Bahia", + "translations": { + "japanese": "バイア州", + "english": "Bahia", + "french": "Bahia", + "german": "Bahia", + "italian": "Bahia", + "spanish": "Bahía", + "chinese_simple": "巴伊亚州", + "korean": "바이아 주", + "dutch": "Bahia", + "portuguese": "Bahia", + "russian": "Баия", + "chinese_traditional": "Bahia", + "unknown1": "Bahia", + "unknown2": "Bahia", + "unknown3": "Bahia", + "unknown4": "Bahia" + }, + "coordinates": { + "latitude": -12.980347555999998, + "longitude": -38.51218849700001 + } + }, + { + "id": 268959744, + "name": "Ceará", + "translations": { + "japanese": "セアラ州", + "english": "Ceará", + "french": "Ceará", + "german": "Ceará", + "italian": "Ceará", + "spanish": "Ceará", + "chinese_simple": "塞阿拉州", + "korean": "세아라 주", + "dutch": "Ceará", + "portuguese": "Ceará", + "russian": "Сеара", + "chinese_traditional": "Ceará", + "unknown1": "Ceará", + "unknown2": "Ceará", + "unknown3": "Ceará", + "unknown4": "Ceará" + }, + "coordinates": { + "latitude": -3.768311527999998, + "longitude": -38.57261346600001 + } + }, + { + "id": 269025280, + "name": "Espírito Santo", + "translations": { + "japanese": "エスピリト・サント州", + "english": "Espírito Santo", + "french": "Espírito Santo", + "german": "Espírito Santo", + "italian": "Espírito Santo", + "spanish": "Espírito Santo", + "chinese_simple": "圣埃斯皮里图州", + "korean": "이스피리투산투 주", + "dutch": "Espírito Santo", + "portuguese": "Espírito Santo", + "russian": "Эспириту-Санту", + "chinese_traditional": "Espírito Santo", + "unknown1": "Espírito Santo", + "unknown2": "Espírito Santo", + "unknown3": "Espírito Santo", + "unknown4": "Espírito Santo" + }, + "coordinates": { + "latitude": -20.313721496, + "longitude": -40.346910283 + } + }, + { + "id": 269090816, + "name": "Mato Grosso do Sul", + "translations": { + "japanese": "マット・グロッソ・ド・スル州", + "english": "Mato Grosso do Sul", + "french": "Mato Grosso do Sul", + "german": "Mato Grosso do Sul", + "italian": "Mato Grosso do Sul", + "spanish": "Mato Grosso do Sul", + "chinese_simple": "南马托格罗索州", + "korean": "마투그로수두술 주", + "dutch": "Mato Grosso do Sul", + "portuguese": "Mato Grosso do Sul", + "russian": "Мату-Гросу-ду-Сул", + "chinese_traditional": "Mato Grosso do Sul", + "unknown1": "Mato Grosso do Sul", + "unknown2": "Mato Grosso do Sul", + "unknown3": "Mato Grosso do Sul", + "unknown4": "Mato Grosso do Sul" + }, + "coordinates": { + "latitude": -20.445557432, + "longitude": -54.612696146000005 + } + }, + { + "id": 269156352, + "name": "Maranhão", + "translations": { + "japanese": "マラニョン州", + "english": "Maranhão", + "french": "Maranhão", + "german": "Maranhão", + "italian": "Maranhão", + "spanish": "Maranhão", + "chinese_simple": "马拉尼昂州", + "korean": "마라냥 주", + "dutch": "Maranhão", + "portuguese": "Maranhão", + "russian": "Мараньян", + "chinese_traditional": "Maranhão", + "unknown1": "Maranhão", + "unknown2": "Maranhão", + "unknown3": "Maranhão", + "unknown4": "Maranhão" + }, + "coordinates": { + "latitude": -2.5158701360000038, + "longitude": -44.26354691 + } + }, + { + "id": 269221888, + "name": "Mato Grosso", + "translations": { + "japanese": "マット・グロッソ州", + "english": "Mato Grosso", + "french": "Mato Grosso", + "german": "Mato Grosso", + "italian": "Mato Grosso", + "spanish": "Mato Grosso", + "chinese_simple": "马托格罗索州", + "korean": "마투그로수 주", + "dutch": "Mato Grosso", + "portuguese": "Mato Grosso", + "russian": "Мату-Гросу", + "chinese_traditional": "Mato Grosso", + "unknown1": "Mato Grosso", + "unknown2": "Mato Grosso", + "unknown3": "Mato Grosso", + "unknown4": "Mato Grosso" + }, + "coordinates": { + "latitude": -15.578614127999998, + "longitude": -56.079374939000004 + } + }, + { + "id": 269287424, + "name": "Minas Gerais", + "translations": { + "japanese": "ミナス・ジェライス州", + "english": "Minas Gerais", + "french": "Minas Gerais", + "german": "Minas Gerais", + "italian": "Minas Gerais", + "spanish": "Minas Gerais", + "chinese_simple": "米纳斯吉拉斯州", + "korean": "미나스 제라이스 주", + "dutch": "Minas Gerais", + "portuguese": "Minas Gerais", + "russian": "Минас-Жерайс", + "chinese_traditional": "Minas Gerais", + "unknown1": "Minas Gerais", + "unknown2": "Minas Gerais", + "unknown3": "Minas Gerais", + "unknown4": "Minas Gerais" + }, + "coordinates": { + "latitude": -19.912720523999994, + "longitude": -43.928462991 + } + }, + { + "id": 269352960, + "name": "Pará", + "translations": { + "japanese": "パラー州", + "english": "Pará", + "french": "Pará", + "german": "Pará", + "italian": "Pará", + "spanish": "Pará", + "chinese_simple": "帕拉州", + "korean": "파라 주", + "dutch": "Pará", + "portuguese": "Pará", + "russian": "Пара", + "chinese_traditional": "Pará", + "unknown1": "Pará", + "unknown2": "Pará", + "unknown3": "Pará", + "unknown4": "Pará" + }, + "coordinates": { + "latitude": -1.4447031560000028, + "longitude": -48.482308382000014 + } + }, + { + "id": 269418496, + "name": "Paraíba", + "translations": { + "japanese": "パライーバ州", + "english": "Paraíba", + "french": "Paraíba", + "german": "Paraíba", + "italian": "Paraíba", + "spanish": "Paraíba", + "chinese_simple": "帕拉伊巴州", + "korean": "파라이바 주", + "dutch": "Paraíba", + "portuguese": "Paraíba", + "russian": "Параиба", + "chinese_traditional": "Paraíba", + "unknown1": "Paraíba", + "unknown2": "Paraíba", + "unknown3": "Paraíba", + "unknown4": "Paraíba" + }, + "coordinates": { + "latitude": -7.113648404000003, + "longitude": -34.864717641 + } + }, + { + "id": 269484032, + "name": "Paraná", + "translations": { + "japanese": "パラナ州", + "english": "Paraná", + "french": "Paraná", + "german": "Paraná", + "italian": "Paraná", + "spanish": "Paraná", + "chinese_simple": "巴拉那州", + "korean": "파라나 주", + "dutch": "Paraná", + "portuguese": "Paraná", + "russian": "Парана", + "chinese_traditional": "Paraná", + "unknown1": "Paraná", + "unknown2": "Paraná", + "unknown3": "Paraná", + "unknown4": "Paraná" + }, + "coordinates": { + "latitude": -25.411377688, + "longitude": -49.245860263 + } + }, + { + "id": 269549568, + "name": "Piauí", + "translations": { + "japanese": "ピアウイー州", + "english": "Piauí", + "french": "Piauí", + "german": "Piauí", + "italian": "Piauí", + "spanish": "Piauí", + "chinese_simple": "皮奥伊州", + "korean": "피아우이 주", + "dutch": "Piauí", + "portuguese": "Piauí", + "russian": "Пиауи", + "chinese_traditional": "Piauí", + "unknown1": "Piauí", + "unknown2": "Piauí", + "unknown3": "Piauí", + "unknown4": "Piauí" + }, + "coordinates": { + "latitude": -5.081177724, + "longitude": -42.81334765400001 + } + }, + { + "id": 269615104, + "name": "Rio de Janeiro", + "translations": { + "japanese": "リオ・デ・ジャネイロ州", + "english": "Rio de Janeiro", + "french": "État de Rio de Janeiro", + "german": "Rio de Janeiro", + "italian": "Rio de Janeiro", + "spanish": "Río de Janeiro", + "chinese_simple": "里约热内卢州", + "korean": "리우데자네이루 주", + "dutch": "Rio de Janeiro", + "portuguese": "Rio de Janeiro", + "russian": "Рио-де-Жанейро", + "chinese_traditional": "Rio de Janeiro", + "unknown1": "Rio de Janeiro", + "unknown2": "Rio de Janeiro", + "unknown3": "Rio de Janeiro", + "unknown4": "Rio de Janeiro" + }, + "coordinates": { + "latitude": -22.895508575999997, + "longitude": -43.230829258 + } + }, + { + "id": 269680640, + "name": "Rio Grande do Norte", + "translations": { + "japanese": "リオ・グランデ・ド・ノルテ州", + "english": "Rio Grande do Norte", + "french": "Rio Grande do Norte", + "german": "Rio Grande do Norte", + "italian": "Rio Grande do Norte", + "spanish": "Rio Grande do Norte", + "chinese_simple": "北里奥格兰德州", + "korean": "히우그란지두노르치 주", + "dutch": "Rio Grande do Norte", + "portuguese": "Rio Grande do Norte", + "russian": "Риу-Гранди-ду-Норти", + "chinese_traditional": "Rio Grande do Norte", + "unknown1": "Rio Grande do Norte", + "unknown2": "Rio Grande do Norte", + "unknown3": "Rio Grande do Norte", + "unknown4": "Rio Grande do Norte" + }, + "coordinates": { + "latitude": -5.7788095519999985, + "longitude": -35.210787917999994 + } + }, + { + "id": 269746176, + "name": "Rio Grande do Sul", + "translations": { + "japanese": "リオ・グランデ・ド・スル州", + "english": "Rio Grande do Sul", + "french": "Rio Grande do Sul", + "german": "Rio Grande do Sul", + "italian": "Rio Grande do Sul", + "spanish": "Rio Grande do Sul", + "chinese_simple": "南里奥格兰德州", + "korean": "히우그란지두술 주", + "dutch": "Rio Grande do Sul", + "portuguese": "Rio Grande do Sul", + "russian": "Риу-Гранди-ду-Сул", + "chinese_traditional": "Rio Grande do Sul", + "unknown1": "Rio Grande do Sul", + "unknown2": "Rio Grande do Sul", + "unknown3": "Rio Grande do Sul", + "unknown4": "Rio Grande do Sul" + }, + "coordinates": { + "latitude": -30.031128611999996, + "longitude": -51.195938807999994 + } + }, + { + "id": 269811712, + "name": "Rondônia", + "translations": { + "japanese": "ロンドニア州", + "english": "Rondônia", + "french": "Rondônia", + "german": "Rondônia", + "italian": "Rondônia", + "spanish": "Rondônia", + "chinese_simple": "朗多尼亚州", + "korean": "혼도니아 주", + "dutch": "Rondônia", + "portuguese": "Rondônia", + "russian": "Рондония", + "chinese_traditional": "Rondônia", + "unknown1": "Rondônia", + "unknown2": "Rondônia", + "unknown3": "Rondônia", + "unknown4": "Rondônia" + }, + "coordinates": { + "latitude": -8.761597604000002, + "longitude": -63.896168656 + } + }, + { + "id": 269877248, + "name": "Roraima", + "translations": { + "japanese": "ロライマ州", + "english": "Roraima", + "french": "Roraima", + "german": "Roraima", + "italian": "Roraima", + "spanish": "Roraima", + "chinese_simple": "罗赖马州", + "korean": "호라이마 주", + "dutch": "Roraima", + "portuguese": "Roraima", + "russian": "Рорайма", + "chinese_traditional": "Roraima", + "unknown1": "Roraima", + "unknown2": "Roraima", + "unknown3": "Roraima", + "unknown4": "Roraima" + }, + "coordinates": { + "latitude": 2.812499968, + "longitude": -60.666179404000005 + } + }, + { + "id": 269942784, + "name": "Santa Catarina", + "translations": { + "japanese": "サンタ・カタリーナ州", + "english": "Santa Catarina", + "french": "Santa Catarina", + "german": "Santa Catarina", + "italian": "Santa Catarina", + "spanish": "Santa Catarina", + "chinese_simple": "圣卡塔琳娜州", + "korean": "산타카타리나 주", + "dutch": "Santa Catarina", + "portuguese": "Santa Catarina", + "russian": "Санта-Катарина", + "chinese_traditional": "Santa Catarina", + "unknown1": "Santa Catarina", + "unknown2": "Santa Catarina", + "unknown3": "Santa Catarina", + "unknown4": "Santa Catarina" + }, + "coordinates": { + "latitude": -27.581177468, + "longitude": -48.564706067 + } + }, + { + "id": 270008320, + "name": "São Paulo", + "translations": { + "japanese": "サン・パウロ州", + "english": "São Paulo", + "french": "État de São Paulo", + "german": "São Paulo", + "italian": "San Paolo", + "spanish": "São Paulo", + "chinese_simple": "圣保罗州", + "korean": "상파울루 주", + "dutch": "São Paulo", + "portuguese": "São Paulo", + "russian": "Сан-Паулу", + "chinese_traditional": "São Paulo", + "unknown1": "São Paulo", + "unknown2": "São Paulo", + "unknown3": "São Paulo", + "unknown4": "São Paulo" + }, + "coordinates": { + "latitude": -23.532715600000003, + "longitude": -46.614627522000006 + } + }, + { + "id": 270073856, + "name": "Sergipe", + "translations": { + "japanese": "セルジッペ州", + "english": "Sergipe", + "french": "Sergipe", + "german": "Sergipe", + "italian": "Sergipe", + "spanish": "Sergipe", + "chinese_simple": "塞尔希培州", + "korean": "세르지피 주", + "dutch": "Sergipe", + "portuguese": "Sergipe", + "russian": "Сержипи", + "chinese_traditional": "Sergipe", + "unknown1": "Sergipe", + "unknown2": "Sergipe", + "unknown3": "Sergipe", + "unknown4": "Sergipe" + }, + "coordinates": { + "latitude": -10.914917892000005, + "longitude": -37.06198924099999 + } + }, + { + "id": 270139392, + "name": "Goiás", + "translations": { + "japanese": "ゴイアス州", + "english": "Goiás", + "french": "Goiás", + "german": "Goiás", + "italian": "Goiás", + "spanish": "Goiás", + "chinese_simple": "戈亚斯州", + "korean": "고이아스 주", + "dutch": "Goiás", + "portuguese": "Goiás", + "russian": "Гояс", + "chinese_traditional": "Goiás", + "unknown1": "Goiás", + "unknown2": "Goiás", + "unknown3": "Goiás", + "unknown4": "Goiás" + }, + "coordinates": { + "latitude": -16.6662606, + "longitude": -49.26233980000001 + } + }, + { + "id": 270204928, + "name": "Pernambuco", + "translations": { + "japanese": "ペルナンブコ州", + "english": "Pernambuco", + "french": "Pernambouc", + "german": "Pernambuco", + "italian": "Pernambuco", + "spanish": "Pernambuco", + "chinese_simple": "伯南布哥州", + "korean": "페르남부쿠 주", + "dutch": "Pernambuco", + "portuguese": "Pernambuco", + "russian": "Пернамбуку", + "chinese_traditional": "Pernambuco", + "unknown1": "Pernambuco", + "unknown2": "Pernambuco", + "unknown3": "Pernambuco", + "unknown4": "Pernambuco" + }, + "coordinates": { + "latitude": -8.047486284000001, + "longitude": -34.89767671499999 + } + }, + { + "id": 270270464, + "name": "Tocantins", + "translations": { + "japanese": "トカンティンス州", + "english": "Tocantins", + "french": "Tocantins", + "german": "Tocantins", + "italian": "Tocantins", + "spanish": "Tocantins", + "chinese_simple": "托坎廷斯州", + "korean": "토칸칭스 주", + "dutch": "Tocantins", + "portuguese": "Tocantins", + "russian": "Токантинс", + "chinese_traditional": "Tocantins", + "unknown1": "Tocantins", + "unknown2": "Tocantins", + "unknown3": "Tocantins", + "unknown4": "Tocantins" + }, + "coordinates": { + "latitude": -10.217286063999993, + "longitude": -48.27356757999999 + } + } + ] + }, + { + "id": 17, + "iso_code": "VG", + "name": "British Virgin Islands", + "translations": { + "japanese": "英領ヴァージン諸島", + "english": "British Virgin Islands", + "french": "Îles Vierges britanniques", + "german": "Britische Jungferninseln", + "italian": "Isole Vergini Britanniche", + "spanish": "Islas Vírgenes Británicas", + "chinese_simple": "英属维尔京群岛", + "korean": "영국령 버진아일랜드", + "dutch": "Britse Maagdeneilanden", + "portuguese": "Ilhas Virgens Britânicas", + "russian": "Британские Виргинские острова", + "chinese_traditional": "British Virgin Islands", + "unknown1": "British Virgin Islands", + "unknown2": "British Virgin Islands", + "unknown3": "British Virgin Islands", + "unknown4": "British Virgin Islands" + }, + "regions": [ + { + "id": 285212672, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 18.413085728, + "longitude": -64.615775105 + } + }, + { + "id": 285278208, + "name": "British Virgin Islands", + "translations": { + "japanese": "英領ヴァージン諸島", + "english": "British Virgin Islands", + "french": "Îles Vierges britanniques", + "german": "Britische Jungferninseln", + "italian": "Isole Vergini Britanniche", + "spanish": "Islas Vírgenes Británicas", + "chinese_simple": "英属维尔京群岛", + "korean": "영국령 버진아일랜드", + "dutch": "Britse Maagdeneilanden", + "portuguese": "Ilhas Virgens Britânicas", + "russian": "Британские Виргинские острова", + "chinese_traditional": "British Virgin Islands", + "unknown1": "British Virgin Islands", + "unknown2": "British Virgin Islands", + "unknown3": "British Virgin Islands", + "unknown4": "British Virgin Islands" + }, + "coordinates": { + "latitude": 18.413085728, + "longitude": -64.615775105 + } + } + ] + }, + { + "id": 18, + "iso_code": "CA", + "name": "Canada", + "translations": { + "japanese": "カナダ", + "english": "Canada", + "french": "Canada", + "german": "Kanada", + "italian": "Canada", + "spanish": "Canadá", + "chinese_simple": "加拿大", + "korean": "캐나다", + "dutch": "Canada", + "portuguese": "Canadá", + "russian": "Канада", + "chinese_traditional": "Canada", + "unknown1": "Canada", + "unknown2": "Canada", + "unknown3": "Canada", + "unknown4": "Canada" + }, + "regions": [ + { + "id": 301989888, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 45.263671360000004, + "longitude": -75.744955759 + } + }, + { + "id": 302120960, + "name": "Ontario", + "translations": { + "japanese": "オンタリオ州", + "english": "Ontario", + "french": "Ontario", + "german": "Ontario", + "italian": "Ontario", + "spanish": "Ontario", + "chinese_simple": "安大略省", + "korean": "온타리오 주", + "dutch": "Ontario", + "portuguese": "Ontário", + "russian": "Онтарио", + "chinese_traditional": "Ontario", + "unknown1": "Ontario", + "unknown2": "Ontario", + "unknown3": "Ontario", + "unknown4": "Ontario" + }, + "coordinates": { + "latitude": 45.263671360000004, + "longitude": -75.744955759 + } + }, + { + "id": 302186496, + "name": "Alberta", + "translations": { + "japanese": "アルバータ州", + "english": "Alberta", + "french": "Alberta", + "german": "Alberta", + "italian": "Alberta", + "spanish": "Alberta", + "chinese_simple": "艾伯塔省", + "korean": "앨버타 주", + "dutch": "Alberta", + "portuguese": "Alberta", + "russian": "Альберта", + "chinese_traditional": "Alberta", + "unknown1": "Alberta", + "unknown2": "Alberta", + "unknown3": "Alberta", + "unknown4": "Alberta" + }, + "coordinates": { + "latitude": 53.547362672, + "longitude": -113.466615952 + } + }, + { + "id": 302252032, + "name": "British Columbia", + "translations": { + "japanese": "ブリティッシュ・コロンビア州", + "english": "British Columbia", + "french": "Colombie-Britannique", + "german": "Britisch-Kolumbien", + "italian": "Columbia Britannica", + "spanish": "Columbia Británica", + "chinese_simple": "不列颠哥伦比亚省", + "korean": "브리티시컬럼비아 주", + "dutch": "Brits-Columbia", + "portuguese": "Colúmbia Britânica", + "russian": "Британская Колумбия", + "chinese_traditional": "British Columbia", + "unknown1": "British Columbia", + "unknown2": "British Columbia", + "unknown3": "British Columbia", + "unknown4": "British Columbia" + }, + "coordinates": { + "latitude": 48.427733824, + "longitude": -123.36532451 + } + }, + { + "id": 302317568, + "name": "Manitoba", + "translations": { + "japanese": "マニトバ州", + "english": "Manitoba", + "french": "Manitoba", + "german": "Manitoba", + "italian": "Manitoba", + "spanish": "Manitoba", + "chinese_simple": "马尼托巴省", + "korean": "매니토바 주", + "dutch": "Manitoba", + "portuguese": "Manitoba", + "russian": "Манитоба", + "chinese_traditional": "Manitoba", + "unknown1": "Manitoba", + "unknown2": "Manitoba", + "unknown3": "Manitoba", + "unknown4": "Manitoba" + }, + "coordinates": { + "latitude": 49.883422284, + "longitude": -97.146381143 + } + }, + { + "id": 302383104, + "name": "New Brunswick", + "translations": { + "japanese": "ニュー・ブランズウィック州", + "english": "New Brunswick", + "french": "Nouveau-Brunswick", + "german": "Neubraunschweig", + "italian": "Nuovo Brunswick", + "spanish": "Nuevo Brunswick", + "chinese_simple": "新不伦瑞克省", + "korean": "뉴브런즈윅 주", + "dutch": "Nieuw-Brunswijk", + "portuguese": "Nova Brunswick", + "russian": "Нью-Брансуик", + "chinese_traditional": "New Brunswick", + "unknown1": "New Brunswick", + "unknown2": "New Brunswick", + "unknown3": "New Brunswick", + "unknown4": "New Brunswick" + }, + "coordinates": { + "latitude": 45.944823696, + "longitude": -66.664730872 + } + }, + { + "id": 302448640, + "name": "Newfoundland and Labrador", + "translations": { + "japanese": "ニューファンドランド・ラブラドール州", + "english": "Newfoundland and Labrador", + "french": "Terre-Neuve et Labrador", + "german": "Neufundland und Labrador", + "italian": "Terranova e Labrador", + "spanish": "Terranova y Labrador", + "chinese_simple": "纽芬兰与拉布拉多省", + "korean": "뉴펀들랜드래브라도 주", + "dutch": "Newfoundland en Labrador", + "portuguese": "Terranova e Labrador", + "russian": "Ньюфаундленд и Лабрадор", + "chinese_traditional": "Newfoundland and Labrador", + "unknown1": "Newfoundland and Labrador", + "unknown2": "Newfoundland and Labrador", + "unknown3": "Newfoundland and Labrador", + "unknown4": "Newfoundland and Labrador" + }, + "coordinates": { + "latitude": 47.565307076, + "longitude": -52.728535749 + } + }, + { + "id": 302514176, + "name": "Nova Scotia", + "translations": { + "japanese": "ノバ・スコシア州", + "english": "Nova Scotia", + "french": "Nouvelle-Écosse", + "german": "Neuschottland", + "italian": "Nuova Scozia", + "spanish": "Nueva Escocia", + "chinese_simple": "新斯科舍省", + "korean": "노바스코샤 주", + "dutch": "Nova Scotia", + "portuguese": "Nova Escócia", + "russian": "Новая Шотландия", + "chinese_traditional": "Nova Scotia", + "unknown1": "Nova Scotia", + "unknown2": "Nova Scotia", + "unknown3": "Nova Scotia", + "unknown4": "Nova Scotia" + }, + "coordinates": { + "latitude": 44.895629372, + "longitude": -63.49516658900001 + } + }, + { + "id": 302579712, + "name": "Prince Edward Island", + "translations": { + "japanese": "プリンス・エドワード・アイランド州", + "english": "Prince Edward Island", + "french": "Île-du-Prince-Édouard", + "german": "Prinz-Edward-Insel", + "italian": "Isola del Principe Edoardo", + "spanish": "Isla del Príncipe Eduardo", + "chinese_simple": "爱德华王子岛省", + "korean": "프린스에드워드아일랜드 주", + "dutch": "Prins Edwardeiland", + "portuguese": "Ilha do Príncipe Eduardo", + "russian": "Остров Принца Эдуарда", + "chinese_traditional": "Prince Edward Island", + "unknown1": "Prince Edward Island", + "unknown2": "Prince Edward Island", + "unknown3": "Prince Edward Island", + "unknown4": "Prince Edward Island" + }, + "coordinates": { + "latitude": 46.235961388, + "longitude": -63.132616775 + } + }, + { + "id": 302645248, + "name": "Quebec", + "translations": { + "japanese": "ケベック州", + "english": "Quebec", + "french": "Québec", + "german": "Québec", + "italian": "Québec", + "spanish": "Quebec", + "chinese_simple": "魁北克省", + "korean": "퀘벡 주", + "dutch": "Québec", + "portuguese": "Quebeque", + "russian": "Квебек", + "chinese_traditional": "Quebec", + "unknown1": "Quebec", + "unknown2": "Quebec", + "unknown3": "Quebec", + "unknown4": "Quebec" + }, + "coordinates": { + "latitude": 46.80175728, + "longitude": -71.207589905 + } + }, + { + "id": 302710784, + "name": "Saskatchewan", + "translations": { + "japanese": "サスカチュワン州", + "english": "Saskatchewan", + "french": "Saskatchewan", + "german": "Saskatchewan", + "italian": "Saskatchewan", + "spanish": "Saskatchewan", + "chinese_simple": "萨斯喀彻温省", + "korean": "서스캐처원 주", + "dutch": "Saskatchewan", + "portuguese": "Saskatchewan", + "russian": "Саскачеван", + "chinese_traditional": "Saskatchewan", + "unknown1": "Saskatchewan", + "unknown2": "Saskatchewan", + "unknown3": "Saskatchewan", + "unknown4": "Saskatchewan" + }, + "coordinates": { + "latitude": 50.449218176, + "longitude": -104.617104583 + } + }, + { + "id": 302776320, + "name": "Yukon", + "translations": { + "japanese": "ユーコン準州", + "english": "Yukon", + "french": "Territoire du Yukon", + "german": "Yukon", + "italian": "Yukon", + "spanish": "Yukón", + "chinese_simple": "育空地区", + "korean": "유콘 준주", + "dutch": "Yukon", + "portuguese": "Yukon", + "russian": "Юкон", + "chinese_traditional": "Yukon", + "unknown1": "Yukon", + "unknown2": "Yukon", + "unknown3": "Yukon", + "unknown4": "Yukon" + }, + "coordinates": { + "latitude": 60.715941692, + "longitude": -135.049316243 + } + }, + { + "id": 302841856, + "name": "Northwest Territories", + "translations": { + "japanese": "ノースウェスト準州", + "english": "Northwest Territories", + "french": "Territoires du Nord-Ouest", + "german": "Nordwest-Territorien", + "italian": "Territori del Nord-Ovest", + "spanish": "Territorios del Noroeste", + "chinese_simple": "西北地区", + "korean": "노스웨스트 준주", + "dutch": "Northwest Territories", + "portuguese": "Territórios do Noroeste", + "russian": "Северо-Западные территории", + "chinese_traditional": "Northwest Territories", + "unknown1": "Northwest Territories", + "unknown2": "Northwest Territories", + "unknown3": "Northwest Territories", + "unknown4": "Northwest Territories" + }, + "coordinates": { + "latitude": 62.451781516, + "longitude": -114.351017771 + } + }, + { + "id": 302907392, + "name": "Nunavut", + "translations": { + "japanese": "ヌナブト準州", + "english": "Nunavut", + "french": "Territoire du Nunavut", + "german": "Nunavut", + "italian": "Nunavut", + "spanish": "Nunavut", + "chinese_simple": "努纳维特地区", + "korean": "누나부트 준주", + "dutch": "Nunavut", + "portuguese": "Nunavut", + "russian": "Нунавут", + "chinese_traditional": "Nunavut", + "unknown1": "Nunavut", + "unknown2": "Nunavut", + "unknown3": "Nunavut", + "unknown4": "Nunavut" + }, + "coordinates": { + "latitude": 63.748168220000004, + "longitude": -68.510439016 + } + } + ] + }, + { + "id": 19, + "iso_code": "KY", + "name": "Cayman Islands", + "translations": { + "japanese": "ケイマン諸島", + "english": "Cayman Islands", + "french": "Îles Caïmans", + "german": "Kaimaninseln", + "italian": "Isole Cayman", + "spanish": "Islas Caimán", + "chinese_simple": "开曼群岛", + "korean": "케이맨 제도", + "dutch": "Kaaimaneilanden", + "portuguese": "Ilhas Caimão", + "russian": "Каймановы острова", + "chinese_traditional": "Cayman Islands", + "unknown1": "Cayman Islands", + "unknown2": "Cayman Islands", + "unknown3": "Cayman Islands", + "unknown4": "Cayman Islands" + }, + "regions": [ + { + "id": 318767104, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 19.297485132, + "longitude": -81.380957413 + } + }, + { + "id": 318832640, + "name": "Cayman Islands", + "translations": { + "japanese": "ケイマン諸島", + "english": "Cayman Islands", + "french": "Îles Caïmans", + "german": "Kaimaninseln", + "italian": "Isole Cayman", + "spanish": "Islas Caimán", + "chinese_simple": "开曼群岛", + "korean": "케이맨 제도", + "dutch": "Kaaimaneilanden", + "portuguese": "Ilhas Caimão", + "russian": "Каймановы острова", + "chinese_traditional": "Cayman Islands", + "unknown1": "Cayman Islands", + "unknown2": "Cayman Islands", + "unknown3": "Cayman Islands", + "unknown4": "Cayman Islands" + }, + "coordinates": { + "latitude": 19.297485132, + "longitude": -81.380957413 + } + } + ] + }, + { + "id": 20, + "iso_code": "CL", + "name": "Chile", + "translations": { + "japanese": "チリ", + "english": "Chile", + "french": "Chili", + "german": "Chile", + "italian": "Cile", + "spanish": "Chile", + "chinese_simple": "智利", + "korean": "칠레", + "dutch": "Chili", + "portuguese": "Chile", + "russian": "Чили", + "chinese_traditional": "Chile", + "unknown1": "Chile", + "unknown2": "Chile", + "unknown3": "Chile", + "unknown4": "Chile" + }, + "regions": [ + { + "id": 335544320, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": -33.44787662, + "longitude": -70.663765184 + } + }, + { + "id": 335675392, + "name": "Región Metropolitana", + "translations": { + "japanese": "レジョン・メトロポリタナ州", + "english": "Región Metropolitana", + "french": "Région Métropolitaine de Santiago", + "german": "Región Metropolitana", + "italian": "Regione Metropolitana di Santiago", + "spanish": "Región Metropolitana", + "chinese_simple": "圣地亚哥首都区", + "korean": "산티아고 수도주", + "dutch": "Región Metropolitana", + "portuguese": "Região Metropolitana", + "russian": "Столичный округ", + "chinese_traditional": "Región Metropolitana", + "unknown1": "Región Metropolitana", + "unknown2": "Región Metropolitana", + "unknown3": "Región Metropolitana", + "unknown4": "Región Metropolitana" + }, + "coordinates": { + "latitude": -33.44787662, + "longitude": -70.663765184 + } + }, + { + "id": 335740928, + "name": "Valparaíso", + "translations": { + "japanese": "バルパライソ州", + "english": "Valparaíso", + "french": "Valparaiso", + "german": "Valparaíso (Region V)", + "italian": "Valparaíso", + "spanish": "Valparaíso", + "chinese_simple": "瓦尔帕莱索大区", + "korean": "발파라이소 주", + "dutch": "Valparaíso", + "portuguese": "Valparaíso", + "russian": "Вальпараисо", + "chinese_traditional": "Valparaíso", + "unknown1": "Valparaíso", + "unknown2": "Valparaíso", + "unknown3": "Valparaíso", + "unknown4": "Valparaíso" + }, + "coordinates": { + "latitude": -33.046875648, + "longitude": -71.597605614 + } + }, + { + "id": 335806464, + "name": "Aisén del General Carlos Ibáñez del Campo", + "translations": { + "japanese": "アイセン・デル・G・カルロス・イバニェス・デル・カンポ州", + "english": "Aisén del General Carlos Ibáñez del Campo", + "french": "Aisén del General Carlos Ibáñez del Campo", + "german": "Aisén (Region XI)", + "italian": "Aisén del General Carlos Ibáñez del Campo", + "spanish": "Aisén del General Carlos Ibáñez del Campo", + "chinese_simple": "伊瓦涅斯将军的艾森大区", + "korean": "아이센 주", + "dutch": "Aysén del General Carlos Ibáñez del Campo", + "portuguese": "Aisén del General Carlos Ibáñez del Campo", + "russian": "Айсен", + "chinese_traditional": "Aisén del General Carlos Ibáñez del Campo", + "unknown1": "Aisén del General Carlos Ibáñez del Campo", + "unknown2": "Aisén del General Carlos Ibáñez del Campo", + "unknown3": "Aisén del General Carlos Ibáñez del Campo", + "unknown4": "Aisén del General Carlos Ibáñez del Campo" + }, + "coordinates": { + "latitude": -45.565796404, + "longitude": -72.064525829 + } + }, + { + "id": 335872000, + "name": "Antofagasta", + "translations": { + "japanese": "アントファガスタ州", + "english": "Antofagasta", + "french": "Antofagasta", + "german": "Antofagasta (Region II)", + "italian": "Antofagasta", + "spanish": "Antofagasta", + "chinese_simple": "安托法加斯塔大区", + "korean": "안토파가스타 주", + "dutch": "Antofagasta", + "portuguese": "Antofagasta", + "russian": "Антофагаста", + "chinese_traditional": "Antofagasta", + "unknown1": "Antofagasta", + "unknown2": "Antofagasta", + "unknown3": "Antofagasta", + "unknown4": "Antofagasta" + }, + "coordinates": { + "latitude": -23.648072044000003, + "longitude": -70.394599413 + } + }, + { + "id": 335937536, + "name": "Araucanía", + "translations": { + "japanese": "アラウカニア州", + "english": "Araucanía", + "french": "Araucanie", + "german": "Araukanien (Region IX)", + "italian": "Araucanía", + "spanish": "Araucanía", + "chinese_simple": "阿劳卡尼亚大区", + "korean": "아라우카니아 주", + "dutch": "Araucanía", + "portuguese": "Araucanía", + "russian": "Араукания", + "chinese_traditional": "Araucanía", + "unknown1": "Araucanía", + "unknown2": "Araucanía", + "unknown3": "Araucanía", + "unknown4": "Araucanía" + }, + "coordinates": { + "latitude": -38.732300388, + "longitude": -72.597364192 + } + }, + { + "id": 336003072, + "name": "Atacama", + "translations": { + "japanese": "アタカマ州", + "english": "Atacama", + "french": "Atacama", + "german": "Atacama (Region III)", + "italian": "Atacama", + "spanish": "Atacama", + "chinese_simple": "阿塔卡马大区", + "korean": "아타카마 주", + "dutch": "Atacama", + "portuguese": "Atacama", + "russian": "Атакама", + "chinese_traditional": "Atacama", + "unknown1": "Atacama", + "unknown2": "Atacama", + "unknown3": "Atacama", + "unknown4": "Atacama" + }, + "coordinates": { + "latitude": -27.361450908000002, + "longitude": -70.328681265 + } + }, + { + "id": 336068608, + "name": "Bío-Bío", + "translations": { + "japanese": "ビオビオ州", + "english": "Bío-Bío", + "french": "Biobío", + "german": "Bío-Bío (Region VIII)", + "italian": "Biobío", + "spanish": "Bío-Bío", + "chinese_simple": "比奥比奥大区", + "korean": "비오비오 주", + "dutch": "Bío-Bío", + "portuguese": "Bio-Bio", + "russian": "Био-Био", + "chinese_traditional": "Bío-Bío", + "unknown1": "Bío-Bío", + "unknown2": "Bío-Bío", + "unknown3": "Bío-Bío", + "unknown4": "Bío-Bío" + }, + "coordinates": { + "latitude": -36.831665644, + "longitude": -73.04780487000001 + } + }, + { + "id": 336134144, + "name": "Coquimbo", + "translations": { + "japanese": "コキンボ州", + "english": "Coquimbo", + "french": "Coquimbo", + "german": "Coquimbo (Region IV)", + "italian": "Coquimbo", + "spanish": "Coquimbo", + "chinese_simple": "科金博大区", + "korean": "코킴보 주", + "dutch": "Coquimbo", + "portuguese": "Coquimbo", + "russian": "Кокимбо", + "chinese_traditional": "Coquimbo", + "unknown1": "Coquimbo", + "unknown2": "Coquimbo", + "unknown3": "Coquimbo", + "unknown4": "Coquimbo" + }, + "coordinates": { + "latitude": -29.948731152, + "longitude": -71.339426201 + } + }, + { + "id": 336199680, + "name": "Libertador General Bernardo O'Higgins", + "translations": { + "japanese": "L・ベルナルド・オヒギンス州", + "english": "Libertador General Bernardo O'Higgins", + "french": "Libertador General Bernardo O'Higgins", + "german": "Libertador General Bernardo O'Higgins (Region VI)", + "italian": "Libertador General Bernardo O'Higgins", + "spanish": "Libertador General Bernardo O'Higgins", + "chinese_simple": "奥伊金斯将军解放者大区", + "korean": "오이긴스 주", + "dutch": "Libertador General Bernardo O'Higgins", + "portuguese": "Libertador General Bernardo O'Higgins", + "russian": "О’Хиггинс", + "chinese_traditional": "Libertador General Bernardo O'Higgins", + "unknown1": "Libertador General Bernardo O'Higgins", + "unknown2": "Libertador General Bernardo O'Higgins", + "unknown3": "Libertador General Bernardo O'Higgins", + "unknown4": "Libertador General Bernardo O'Higgins" + }, + "coordinates": { + "latitude": -34.16198794, + "longitude": -70.746162869 + } + }, + { + "id": 336265216, + "name": "Los Lagos", + "translations": { + "japanese": "ロス・ラゴス州", + "english": "Los Lagos", + "french": "Los Lagos", + "german": "Los Lagos (Region X)", + "italian": "Los Lagos", + "spanish": "Los Lagos", + "chinese_simple": "湖大区", + "korean": "로스라고스 주", + "dutch": "Los Lagos", + "portuguese": "Los Lagos", + "russian": "Лос-Лагос", + "chinese_traditional": "Los Lagos", + "unknown1": "Los Lagos", + "unknown2": "Los Lagos", + "unknown3": "Los Lagos", + "unknown4": "Los Lagos" + }, + "coordinates": { + "latitude": -41.46789606, + "longitude": -72.932448111 + } + }, + { + "id": 336330752, + "name": "Magallanes y Antártica Chilena", + "translations": { + "japanese": "マガリャネス州", + "english": "Magallanes y Antártica Chilena", + "french": "Magellan et Antarctique Chilienne", + "german": "Magallanes (Region XII) und Chilenische Antarktis", + "italian": "Magellane e Antartide Cilena", + "spanish": "Magallanes y Antártica Chilena", + "chinese_simple": "麦哲伦-智利南极大区", + "korean": "마가야네스 주", + "dutch": "Magallanes y de la Antártica Chilena", + "portuguese": "Magalhães e Antártica Chilena", + "russian": "Магальянес и Чилийская Антарктика", + "chinese_traditional": "Magallanes y Antártica Chilena", + "unknown1": "Magallanes y Antártica Chilena", + "unknown2": "Magallanes y Antártica Chilena", + "unknown3": "Magallanes y Antártica Chilena", + "unknown4": "Magallanes y Antártica Chilena" + }, + "coordinates": { + "latitude": -53.146362724, + "longitude": -70.910958239 + } + }, + { + "id": 336396288, + "name": "Maule", + "translations": { + "japanese": "マウレ州", + "english": "Maule", + "french": "Maule", + "german": "Maule (Region VII)", + "italian": "Maule", + "spanish": "Maule", + "chinese_simple": "马乌莱大区", + "korean": "마울레 주", + "dutch": "Maule", + "portuguese": "Maule", + "russian": "Мауле", + "chinese_traditional": "Maule", + "unknown1": "Maule", + "unknown2": "Maule", + "unknown3": "Maule", + "unknown4": "Maule" + }, + "coordinates": { + "latitude": -35.430908824, + "longitude": -71.663523762 + } + }, + { + "id": 336461824, + "name": "Tarapacá", + "translations": { + "japanese": "タラパカ州", + "english": "Tarapacá", + "french": "Tarapacá", + "german": "Tarapacá (Region I)", + "italian": "Tarapacá", + "spanish": "Tarapacá", + "chinese_simple": "塔拉帕卡大区", + "korean": "타라파카 주", + "dutch": "Tarapacá", + "portuguese": "Tarapacá", + "russian": "Тарапака", + "chinese_traditional": "Tarapacá", + "unknown1": "Tarapacá", + "unknown2": "Tarapacá", + "unknown3": "Tarapacá", + "unknown4": "Tarapacá" + }, + "coordinates": { + "latitude": -20.214844544, + "longitude": -70.163885895 + } + } + ] + }, + { + "id": 21, + "iso_code": "CO", + "name": "Colombia", + "translations": { + "japanese": "コロンビア", + "english": "Colombia", + "french": "Colombie", + "german": "Kolumbien", + "italian": "Colombia", + "spanish": "Colombia", + "chinese_simple": "哥伦比亚", + "korean": "콜롬비아", + "dutch": "Colombia", + "portuguese": "Colômbia", + "russian": "Колумбия", + "chinese_traditional": "Colombia", + "unknown1": "Colombia", + "unknown2": "Colombia", + "unknown3": "Colombia", + "unknown4": "Colombia" + }, + "regions": [ + { + "id": 352321536, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 4.246215772, + "longitude": -74.179399744 + } + }, + { + "id": 352452608, + "name": "Distrito Capital", + "translations": { + "japanese": "ディストリト・キャピタル", + "english": "Distrito Capital", + "french": "District Capital de Santa Fe de Bogotá", + "german": "Bogotá D.C.", + "italian": "Distretto Capitale", + "spanish": "Distrito Capital", + "chinese_simple": "波哥大首都区", + "korean": "콜롬비아 수도주", + "dutch": "Hoofdstedelijk District", + "portuguese": "Distrito Capital", + "russian": "Столичный округ", + "chinese_traditional": "Distrito Capital", + "unknown1": "Distrito Capital", + "unknown2": "Distrito Capital", + "unknown3": "Distrito Capital", + "unknown4": "Distrito Capital" + }, + "coordinates": { + "latitude": 4.246215772, + "longitude": -74.179399744 + } + }, + { + "id": 352518144, + "name": "Cundinamarca", + "translations": { + "japanese": "クンディナマルカ県", + "english": "Cundinamarca", + "french": "Cundinamarca", + "german": "Cundinamarca", + "italian": "Cundinamarca", + "spanish": "Cundinamarca", + "chinese_simple": "昆迪纳马卡省", + "korean": "쿤디나마르카 주", + "dutch": "Cundinamarca", + "portuguese": "Cundinamarca", + "russian": "Кундинамарка", + "chinese_traditional": "Cundinamarca", + "unknown1": "Cundinamarca", + "unknown2": "Cundinamarca", + "unknown3": "Cundinamarca", + "unknown4": "Cundinamarca" + }, + "coordinates": { + "latitude": 4.597778268, + "longitude": -74.080522522 + } + }, + { + "id": 352583680, + "name": "Amazonas", + "translations": { + "japanese": "アマソナス県", + "english": "Amazonas", + "french": "Amazone", + "german": "Amazonas", + "italian": "Amazonas", + "spanish": "Amazonas", + "chinese_simple": "亚马孙省", + "korean": "아마소나스 주", + "dutch": "Amazonas", + "portuguese": "Amazonas", + "russian": "Амазонас", + "chinese_traditional": "Amazonas", + "unknown1": "Amazonas", + "unknown2": "Amazonas", + "unknown3": "Amazonas", + "unknown4": "Amazonas" + }, + "coordinates": { + "latitude": -4.213257811999995, + "longitude": -69.938665556 + } + }, + { + "id": 352649216, + "name": "Antioquia", + "translations": { + "japanese": "アンティオキア県", + "english": "Antioquia", + "french": "Antioquia", + "german": "Antioquia", + "italian": "Antioquia", + "spanish": "Antioquia", + "chinese_simple": "安提奥基亚省", + "korean": "안티오키아 주", + "dutch": "Antioquia", + "portuguese": "Antioquia", + "russian": "Антиокия", + "chinese_traditional": "Antioquia", + "unknown1": "Antioquia", + "unknown2": "Antioquia", + "unknown3": "Antioquia", + "unknown4": "Antioquia" + }, + "coordinates": { + "latitude": 6.28967278, + "longitude": -75.530721778 + } + }, + { + "id": 352714752, + "name": "Arauca", + "translations": { + "japanese": "アラウカ県", + "english": "Arauca", + "french": "Arauca", + "german": "Arauca", + "italian": "Arauca", + "spanish": "Arauca", + "chinese_simple": "阿劳卡省", + "korean": "아라우카 주", + "dutch": "Arauca", + "portuguese": "Arauca", + "russian": "Араука", + "chinese_traditional": "Arauca", + "unknown1": "Arauca", + "unknown2": "Arauca", + "unknown3": "Arauca", + "unknown4": "Arauca" + }, + "coordinates": { + "latitude": 7.08618156, + "longitude": -70.757149227 + } + }, + { + "id": 352780288, + "name": "Atlántico", + "translations": { + "japanese": "アトランティコ県", + "english": "Atlántico", + "french": "Atlantique", + "german": "Atlántico", + "italian": "Atlántico", + "spanish": "Atlántico", + "chinese_simple": "大西洋省", + "korean": "아틀란티코 주", + "dutch": "Atlántico", + "portuguese": "Atlántico", + "russian": "Атлантико", + "chinese_traditional": "Atlántico", + "unknown1": "Atlántico", + "unknown2": "Atlántico", + "unknown3": "Atlántico", + "unknown4": "Atlántico" + }, + "coordinates": { + "latitude": 10.95886218, + "longitude": -74.794635792 + } + }, + { + "id": 352845824, + "name": "Bolívar", + "translations": { + "japanese": "ボリーバル県", + "english": "Bolívar", + "french": "Bolívar", + "german": "Bolívar", + "italian": "Bolívar", + "spanish": "Bolívar", + "chinese_simple": "玻利瓦尔省", + "korean": "볼리바르 주", + "dutch": "Bolívar", + "portuguese": "Bolívar", + "russian": "Боливар", + "chinese_traditional": "Bolívar", + "unknown1": "Bolívar", + "unknown2": "Bolívar", + "unknown3": "Bolívar", + "unknown4": "Bolívar" + }, + "coordinates": { + "latitude": 10.398559452, + "longitude": -75.508749062 + } + }, + { + "id": 352911360, + "name": "Boyacá", + "translations": { + "japanese": "ボヤカ県", + "english": "Boyacá", + "french": "Boyacá", + "german": "Boyacá", + "italian": "Boyacá", + "spanish": "Boyacá", + "chinese_simple": "博亚卡省", + "korean": "보야카 주", + "dutch": "Boyacá", + "portuguese": "Boyacá", + "russian": "Бояка", + "chinese_traditional": "Boyacá", + "unknown1": "Boyacá", + "unknown2": "Boyacá", + "unknown3": "Boyacá", + "unknown4": "Boyacá" + }, + "coordinates": { + "latitude": 5.531616148, + "longitude": -73.366409252 + } + }, + { + "id": 352976896, + "name": "Caldas", + "translations": { + "japanese": "カルダス県", + "english": "Caldas", + "french": "Caldas", + "german": "Caldas", + "italian": "Caldas", + "spanish": "Caldas", + "chinese_simple": "卡尔达斯省", + "korean": "칼다스 주", + "dutch": "Caldas", + "portuguese": "Caldas", + "russian": "Калдас", + "chinese_traditional": "Caldas", + "unknown1": "Caldas", + "unknown2": "Caldas", + "unknown3": "Caldas", + "unknown4": "Caldas" + }, + "coordinates": { + "latitude": 5.064697208, + "longitude": -75.51973542 + } + }, + { + "id": 353042432, + "name": "Caquetá", + "translations": { + "japanese": "カケタ県", + "english": "Caquetá", + "french": "Caquetá", + "german": "Caquetá", + "italian": "Caquetá", + "spanish": "Caquetá", + "chinese_simple": "卡克塔省", + "korean": "카케타 주", + "dutch": "Caquetá", + "portuguese": "Caquetá", + "russian": "Какьета", + "chinese_traditional": "Caquetá", + "unknown1": "Caquetá", + "unknown2": "Caquetá", + "unknown3": "Caquetá", + "unknown4": "Caquetá" + }, + "coordinates": { + "latitude": 1.614990216, + "longitude": -75.613119463 + } + }, + { + "id": 353107968, + "name": "Cauca", + "translations": { + "japanese": "カウカ県", + "english": "Cauca", + "french": "Cauca", + "german": "Cauca", + "italian": "Cauca", + "spanish": "Cauca", + "chinese_simple": "考卡省", + "korean": "카우카 주", + "dutch": "Cauca", + "portuguese": "Cauca", + "russian": "Каука", + "chinese_traditional": "Cauca", + "unknown1": "Cauca", + "unknown2": "Cauca", + "unknown3": "Cauca", + "unknown4": "Cauca" + }, + "coordinates": { + "latitude": 2.482910128, + "longitude": -76.579918967 + } + }, + { + "id": 353173504, + "name": "Cesar", + "translations": { + "japanese": "セサル県", + "english": "Cesar", + "french": "Cesar", + "german": "Cesar", + "italian": "Cesar", + "spanish": "Cesar", + "chinese_simple": "塞萨尔省", + "korean": "세사르 주", + "dutch": "Cesar", + "portuguese": "Cesar", + "russian": "Сесар", + "chinese_traditional": "Cesar", + "unknown1": "Cesar", + "unknown2": "Cesar", + "unknown3": "Cesar", + "unknown4": "Cesar" + }, + "coordinates": { + "latitude": 10.475463748, + "longitude": -73.245559314 + } + }, + { + "id": 353239040, + "name": "Chocó", + "translations": { + "japanese": "チョコ県", + "english": "Chocó", + "french": "Chocó", + "german": "Chocó", + "italian": "Chocó", + "spanish": "Chocó", + "chinese_simple": "乔科省", + "korean": "초코 주", + "dutch": "Chocó", + "portuguese": "Chocó", + "russian": "Чоко", + "chinese_traditional": "Chocó", + "unknown1": "Chocó", + "unknown2": "Chocó", + "unknown3": "Chocó", + "unknown4": "Chocó" + }, + "coordinates": { + "latitude": 5.690917904, + "longitude": -76.656823473 + } + }, + { + "id": 353304576, + "name": "Córdoba", + "translations": { + "japanese": "コルドバ県", + "english": "Córdoba", + "french": "Córdoba", + "german": "Córdoba", + "italian": "Córdoba", + "spanish": "Córdoba", + "chinese_simple": "科尔多瓦省", + "korean": "코르도바 주", + "dutch": "Córdoba", + "portuguese": "Cordova", + "russian": "Кордоба", + "chinese_traditional": "Córdoba", + "unknown1": "Córdoba", + "unknown2": "Córdoba", + "unknown3": "Córdoba", + "unknown4": "Córdoba" + }, + "coordinates": { + "latitude": 8.756103416, + "longitude": -75.887778413 + } + }, + { + "id": 353370112, + "name": "Guaviare", + "translations": { + "japanese": "グアビアレ県", + "english": "Guaviare", + "french": "Guaviare", + "german": "Guaviare", + "italian": "Guaviare", + "spanish": "Guaviare", + "chinese_simple": "瓜维亚雷省", + "korean": "과비아레 주", + "dutch": "Guaviare", + "portuguese": "Guaviare", + "russian": "Гуавиаре", + "chinese_traditional": "Guaviare", + "unknown1": "Guaviare", + "unknown2": "Guaviare", + "unknown3": "Guaviare", + "unknown4": "Guaviare" + }, + "coordinates": { + "latitude": 2.565307588, + "longitude": -72.641309624 + } + }, + { + "id": 353435648, + "name": "Guainía", + "translations": { + "japanese": "グアイニア県", + "english": "Guainía", + "french": "Guainía", + "german": "Guainía", + "italian": "Guainía", + "spanish": "Guainía", + "chinese_simple": "瓜伊尼亚省", + "korean": "과이니아 주", + "dutch": "Guainía", + "portuguese": "Guainía", + "russian": "Гуаинья", + "chinese_traditional": "Guainía", + "unknown1": "Guainía", + "unknown2": "Guainía", + "unknown3": "Guainía", + "unknown4": "Guainía" + }, + "coordinates": { + "latitude": 3.861694292, + "longitude": -67.922668863 + } + }, + { + "id": 353501184, + "name": "Huila", + "translations": { + "japanese": "ウィラ県", + "english": "Huila", + "french": "Huila", + "german": "Huila", + "italian": "Huila", + "spanish": "Huila", + "chinese_simple": "乌伊拉省", + "korean": "우일라 주", + "dutch": "Huila", + "portuguese": "Huila", + "russian": "Уила", + "chinese_traditional": "Huila", + "unknown1": "Huila", + "unknown2": "Huila", + "unknown3": "Huila", + "unknown4": "Huila" + }, + "coordinates": { + "latitude": 2.927856412, + "longitude": -75.327474155 + } + }, + { + "id": 353566720, + "name": "La Guajira", + "translations": { + "japanese": "グアヒーラ県", + "english": "La Guajira", + "french": "La Guajira", + "german": "La Guajira", + "italian": "La Guajira", + "spanish": "La Guajira", + "chinese_simple": "瓜希拉省", + "korean": "라과히라 주", + "dutch": "Guajira", + "portuguese": "La Guajira", + "russian": "Гуахира", + "chinese_traditional": "La Guajira", + "unknown1": "La Guajira", + "unknown2": "La Guajira", + "unknown3": "La Guajira", + "unknown4": "La Guajira" + }, + "coordinates": { + "latitude": 11.541137564, + "longitude": -72.90498221600001 + } + }, + { + "id": 353632256, + "name": "Magdalena", + "translations": { + "japanese": "マグダレーナ県", + "english": "Magdalena", + "french": "Magdalena", + "german": "Magdalena", + "italian": "Magdalena", + "spanish": "Magdalena", + "chinese_simple": "马格达雷那省", + "korean": "마그달레나 주", + "dutch": "Magdalena", + "portuguese": "Magdalena", + "russian": "Магдалена", + "chinese_traditional": "Magdalena", + "unknown1": "Magdalena", + "unknown2": "Magdalena", + "unknown3": "Magdalena", + "unknown4": "Magdalena" + }, + "coordinates": { + "latitude": 11.244506708, + "longitude": -74.20137246 + } + }, + { + "id": 353697792, + "name": "Meta", + "translations": { + "japanese": "メタ県", + "english": "Meta", + "french": "Meta", + "german": "Meta", + "italian": "Meta", + "spanish": "Meta", + "chinese_simple": "梅塔省", + "korean": "메타 주", + "dutch": "Meta", + "portuguese": "Meta", + "russian": "Мета", + "chinese_traditional": "Meta", + "unknown1": "Meta", + "unknown2": "Meta", + "unknown3": "Meta", + "unknown4": "Meta" + }, + "coordinates": { + "latitude": 4.152831984, + "longitude": -73.630081844 + } + }, + { + "id": 353763328, + "name": "Nariño", + "translations": { + "japanese": "ナリーニョ県", + "english": "Nariño", + "french": "Nariño", + "german": "Nariño", + "italian": "Nariño", + "spanish": "Nariño", + "chinese_simple": "纳里尼奥省", + "korean": "나리뇨 주", + "dutch": "Nariño", + "portuguese": "Nariño", + "russian": "Нариньо", + "chinese_traditional": "Nariño", + "unknown1": "Nariño", + "unknown2": "Nariño", + "unknown3": "Nariño", + "unknown4": "Nariño" + }, + "coordinates": { + "latitude": 1.20849608, + "longitude": -77.2775527 + } + }, + { + "id": 353828864, + "name": "Norte de Santander", + "translations": { + "japanese": "ノルテ・デ・サンタンデル県", + "english": "Norte de Santander", + "french": "Norte de Santander", + "german": "Norte de Santander", + "italian": "Norte de Santander", + "spanish": "Norte de Santander", + "chinese_simple": "北桑坦德省", + "korean": "노르테데산탄데르 주", + "dutch": "Norte de Santander", + "portuguese": "Norte de Santander", + "russian": "Норте-де-Сантандер", + "chinese_traditional": "Norte de Santander", + "unknown1": "Norte de Santander", + "unknown2": "Norte de Santander", + "unknown3": "Norte de Santander", + "unknown4": "Norte de Santander" + }, + "coordinates": { + "latitude": 7.88269034, + "longitude": -72.503980149 + } + }, + { + "id": 353894400, + "name": "Putumayo", + "translations": { + "japanese": "プトゥマイオ県", + "english": "Putumayo", + "french": "Putumayo", + "german": "Putumayo", + "italian": "Putumayo", + "spanish": "Putumayo", + "chinese_simple": "普图马约省", + "korean": "푸투마요 주", + "dutch": "Putumayo", + "portuguese": "Putumayo", + "russian": "Путумайо", + "chinese_traditional": "Putumayo", + "unknown1": "Putumayo", + "unknown2": "Putumayo", + "unknown3": "Putumayo", + "unknown4": "Putumayo" + }, + "coordinates": { + "latitude": 1.148071276, + "longitude": -76.645837115 + } + }, + { + "id": 353959936, + "name": "Quindío", + "translations": { + "japanese": "キンディオ県", + "english": "Quindío", + "french": "Quindío", + "german": "Quindío", + "italian": "Quindío", + "spanish": "Quindío", + "chinese_simple": "金迪奥省", + "korean": "킨디오 주", + "dutch": "Quindío", + "portuguese": "Quindío", + "russian": "Киндио", + "chinese_traditional": "Quindío", + "unknown1": "Quindío", + "unknown2": "Quindío", + "unknown3": "Quindío", + "unknown4": "Quindío" + }, + "coordinates": { + "latitude": 4.5318603, + "longitude": -75.679037611 + } + }, + { + "id": 354025472, + "name": "Risaralda", + "translations": { + "japanese": "リサラルダ県", + "english": "Risaralda", + "french": "Risaralda", + "german": "Risaralda", + "italian": "Risaralda", + "spanish": "Risaralda", + "chinese_simple": "利萨拉尔达省", + "korean": "리사랄다 주", + "dutch": "Risaralda", + "portuguese": "Risaralda", + "russian": "Рисаральда", + "chinese_traditional": "Risaralda", + "unknown1": "Risaralda", + "unknown2": "Risaralda", + "unknown3": "Risaralda", + "unknown4": "Risaralda" + }, + "coordinates": { + "latitude": 4.812011664, + "longitude": -75.69551714800001 + } + }, + { + "id": 354091008, + "name": "Archipiélago de San Andrés, Providencia y Santa Catalina", + "translations": { + "japanese": "サン・アンドレス・イ・プロビデンシア県", + "english": "Archipiélago de San Andrés, Providencia y Santa Catalina", + "french": "Îles de San Andrés, Providencia et Santa Cataline", + "german": "San Andrés und Providencia", + "italian": "San Andrés e Providencia", + "spanish": "Archipiélago de San Andrés, Providencia y Santa Catalina", + "chinese_simple": "圣安德烈斯-普罗维登西亚省", + "korean": "산안드레스 이 프로비덴시아 주", + "dutch": "San Andrés en Providencia", + "portuguese": "Arquipélago de San Andrés, Providencia y Santa Catalina", + "russian": "Сан-Андрес-и-Провиденция", + "chinese_traditional": "Archipiélago de San Andrés, Providencia y Santa Catalina", + "unknown1": "Archipiélago de San Andrés, Providencia y Santa Catalina", + "unknown2": "Archipiélago de San Andrés, Providencia y Santa Catalina", + "unknown3": "Archipiélago de San Andrés, Providencia y Santa Catalina", + "unknown4": "Archipiélago de San Andrés, Providencia y Santa Catalina" + }, + "coordinates": { + "latitude": 12.57934556, + "longitude": -81.699561795 + } + }, + { + "id": 354156544, + "name": "Santander", + "translations": { + "japanese": "サンタンデル県", + "english": "Santander", + "french": "Santander", + "german": "Santander", + "italian": "Santander", + "spanish": "Santander", + "chinese_simple": "桑坦德省", + "korean": "산탄데르 주", + "dutch": "Santander", + "portuguese": "Santander", + "russian": "Сантандер", + "chinese_traditional": "Santander", + "unknown1": "Santander", + "unknown2": "Santander", + "unknown3": "Santander", + "unknown4": "Santander" + }, + "coordinates": { + "latitude": 7.124633708, + "longitude": -73.124709376 + } + }, + { + "id": 354222080, + "name": "Sucre", + "translations": { + "japanese": "スクレ県", + "english": "Sucre", + "french": "Sucre", + "german": "Sucre", + "italian": "Sucre", + "spanish": "Sucre", + "chinese_simple": "苏克雷省", + "korean": "수크레 주", + "dutch": "Sucre", + "portuguese": "Sucre", + "russian": "Сукре", + "chinese_traditional": "Sucre", + "unknown1": "Sucre", + "unknown2": "Sucre", + "unknown3": "Sucre", + "unknown4": "Sucre" + }, + "coordinates": { + "latitude": 9.299926652, + "longitude": -75.393392303 + } + }, + { + "id": 354287616, + "name": "Tolima", + "translations": { + "japanese": "トリマ県", + "english": "Tolima", + "french": "Tolima", + "german": "Tolima", + "italian": "Tolima", + "spanish": "Tolima", + "chinese_simple": "托利马省", + "korean": "톨리마 주", + "dutch": "Tolima", + "portuguese": "Tolima", + "russian": "Толима", + "chinese_traditional": "Tolima", + "unknown1": "Tolima", + "unknown2": "Tolima", + "unknown3": "Tolima", + "unknown4": "Tolima" + }, + "coordinates": { + "latitude": 4.438476512, + "longitude": -75.228596933 + } + }, + { + "id": 354353152, + "name": "Valle del Cauca", + "translations": { + "japanese": "バジェ・デル・カウカ県", + "english": "Valle del Cauca", + "french": "Valle del Cauca", + "german": "Valle del Cauca", + "italian": "Valle del Cauca", + "spanish": "Valle del Cauca", + "chinese_simple": "考卡山谷省", + "korean": "바예델카우카 주", + "dutch": "Valle del Cauca", + "portuguese": "Valle del Cauca", + "russian": "Валье-дель-Каука", + "chinese_traditional": "Valle del Cauca", + "unknown1": "Valle del Cauca", + "unknown2": "Valle del Cauca", + "unknown3": "Valle del Cauca", + "unknown4": "Valle del Cauca" + }, + "coordinates": { + "latitude": 3.4332275, + "longitude": -76.519493998 + } + }, + { + "id": 354418688, + "name": "Vaupés", + "translations": { + "japanese": "バウペス県", + "english": "Vaupés", + "french": "Vaupés", + "german": "Vaupés", + "italian": "Vaupés", + "spanish": "Vaupés", + "chinese_simple": "沃佩斯省", + "korean": "바우페스 주", + "dutch": "Vaupés", + "portuguese": "Vaupés", + "russian": "Ваупес", + "chinese_traditional": "Vaupés", + "unknown1": "Vaupés", + "unknown2": "Vaupés", + "unknown3": "Vaupés", + "unknown4": "Vaupés" + }, + "coordinates": { + "latitude": 1.197509752, + "longitude": -70.169379074 + } + }, + { + "id": 354484224, + "name": "Vichada", + "translations": { + "japanese": "ビチャダ県", + "english": "Vichada", + "french": "Vichada", + "german": "Vichada", + "italian": "Vichada", + "spanish": "Vichada", + "chinese_simple": "维查达省", + "korean": "비차다 주", + "dutch": "Vichada", + "portuguese": "Vichada", + "russian": "Вичада", + "chinese_traditional": "Vichada", + "unknown1": "Vichada", + "unknown2": "Vichada", + "unknown3": "Vichada", + "unknown4": "Vichada" + }, + "coordinates": { + "latitude": 6.185302664, + "longitude": -67.472228185 + } + }, + { + "id": 354549760, + "name": "Casanare", + "translations": { + "japanese": "カサナレ県", + "english": "Casanare", + "french": "Casanare", + "german": "Casanare", + "italian": "Casanare", + "spanish": "Casanare", + "chinese_simple": "卡萨纳雷省", + "korean": "카사나레 주", + "dutch": "Casanare", + "portuguese": "Casanare", + "russian": "Касанаре", + "chinese_traditional": "Casanare", + "unknown1": "Casanare", + "unknown2": "Casanare", + "unknown3": "Casanare", + "unknown4": "Casanare" + }, + "coordinates": { + "latitude": 5.339355408, + "longitude": -72.38862339 + } + } + ] + }, + { + "id": 22, + "iso_code": "CR", + "name": "Costa Rica", + "translations": { + "japanese": "コスタリカ", + "english": "Costa Rica", + "french": "Costa Rica", + "german": "Costa Rica", + "italian": "Costa Rica", + "spanish": "Costa Rica", + "chinese_simple": "哥斯达黎加", + "korean": "코스타리카", + "dutch": "Costa Rica", + "portuguese": "Costa Rica", + "russian": "Коста-Рика", + "chinese_traditional": "Costa Rica", + "unknown1": "Costa Rica", + "unknown2": "Costa Rica", + "unknown3": "Costa Rica", + "unknown4": "Costa Rica" + }, + "regions": [ + { + "id": 369098752, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 9.931640512, + "longitude": -84.078108302 + } + }, + { + "id": 369229824, + "name": "San José", + "translations": { + "japanese": "サン・ホセ州", + "english": "San José", + "french": "San José", + "german": "San José", + "italian": "San José", + "spanish": "San José", + "chinese_simple": "圣何塞省", + "korean": "산호세 주", + "dutch": "San José", + "portuguese": "San José", + "russian": "Сан-Хосе", + "chinese_traditional": "San José", + "unknown1": "San José", + "unknown2": "San José", + "unknown3": "San José", + "unknown4": "San José" + }, + "coordinates": { + "latitude": 9.931640512, + "longitude": -84.078108302 + } + }, + { + "id": 369295360, + "name": "Alajuela", + "translations": { + "japanese": "アラフエラ州", + "english": "Alajuela", + "french": "Alajuela", + "german": "Alajuela", + "italian": "Alajuela", + "spanish": "Alajuela", + "chinese_simple": "阿拉胡埃拉省", + "korean": "알라후엘라 주", + "dutch": "Alajuela", + "portuguese": "Alajuela", + "russian": "Алахуэла", + "chinese_traditional": "Alajuela", + "unknown1": "Alajuela", + "unknown2": "Alajuela", + "unknown3": "Alajuela", + "unknown4": "Alajuela" + }, + "coordinates": { + "latitude": 10.014037972, + "longitude": -84.215437777 + } + }, + { + "id": 369360896, + "name": "Cartago", + "translations": { + "japanese": "カルタゴ州", + "english": "Cartago", + "french": "Cartago", + "german": "Cartago", + "italian": "Cartago", + "spanish": "Cartago", + "chinese_simple": "卡塔戈省", + "korean": "카르타고 주", + "dutch": "Cartago", + "portuguese": "Cartago", + "russian": "Картаго", + "chinese_traditional": "Cartago", + "unknown1": "Cartago", + "unknown2": "Cartago", + "unknown3": "Cartago", + "unknown4": "Cartago" + }, + "coordinates": { + "latitude": 9.865722544, + "longitude": -83.913312932 + } + }, + { + "id": 369426432, + "name": "Guanacaste", + "translations": { + "japanese": "グアナカステ州", + "english": "Guanacaste", + "french": "Guanacaste", + "german": "Guanacaste", + "italian": "Guanacaste", + "spanish": "Guanacaste", + "chinese_simple": "瓜纳卡斯特省", + "korean": "과나카스테 주", + "dutch": "Guanacaste", + "portuguese": "Guanacaste", + "russian": "Гуанакасте", + "chinese_traditional": "Guanacaste", + "unknown1": "Guanacaste", + "unknown2": "Guanacaste", + "unknown3": "Guanacaste", + "unknown4": "Guanacaste" + }, + "coordinates": { + "latitude": 10.62927234, + "longitude": -85.429430336 + } + }, + { + "id": 369491968, + "name": "Heredia", + "translations": { + "japanese": "エレディア州", + "english": "Heredia", + "french": "Heredia", + "german": "Heredia", + "italian": "Heredia", + "spanish": "Heredia", + "chinese_simple": "埃雷迪亚省", + "korean": "에레디아 주", + "dutch": "Heredia", + "portuguese": "Heredia", + "russian": "Эредия", + "chinese_traditional": "Heredia", + "unknown1": "Heredia", + "unknown2": "Heredia", + "unknown3": "Heredia", + "unknown4": "Heredia" + }, + "coordinates": { + "latitude": 9.99755848, + "longitude": -84.111067376 + } + }, + { + "id": 369557504, + "name": "Limón", + "translations": { + "japanese": "リモン州", + "english": "Limón", + "french": "Limón", + "german": "Limón", + "italian": "Limón", + "spanish": "Limón", + "chinese_simple": "利蒙省", + "korean": "리몬 주", + "dutch": "Limón", + "portuguese": "Limón", + "russian": "Лимон", + "chinese_traditional": "Limón", + "unknown1": "Limón", + "unknown2": "Limón", + "unknown3": "Limón", + "unknown4": "Limón" + }, + "coordinates": { + "latitude": 9.99755848, + "longitude": -83.028911113 + } + }, + { + "id": 369623040, + "name": "Puntarenas", + "translations": { + "japanese": "プンタレナス州", + "english": "Puntarenas", + "french": "Puntarenas", + "german": "Puntarenas", + "italian": "Puntarenas", + "spanish": "Puntarenas", + "chinese_simple": "蓬塔雷纳斯省", + "korean": "푼타레나스 주", + "dutch": "Puntarenas", + "portuguese": "Puntarenas", + "russian": "Пунтаренас", + "chinese_traditional": "Puntarenas", + "unknown1": "Puntarenas", + "unknown2": "Puntarenas", + "unknown3": "Puntarenas", + "unknown4": "Puntarenas" + }, + "coordinates": { + "latitude": 9.964599496, + "longitude": -84.830673825 + } + } + ] + }, + { + "id": 23, + "iso_code": "DM", + "name": "Dominica", + "translations": { + "japanese": "ドミニカ国", + "english": "Dominica", + "french": "Dominique", + "german": "Dominica", + "italian": "Dominica", + "spanish": "Dominica", + "chinese_simple": "多米尼克", + "korean": "도미니카 연방", + "dutch": "Dominica", + "portuguese": "Dominica", + "russian": "Доминика", + "chinese_traditional": "Dominica", + "unknown1": "Dominica", + "unknown2": "Dominica", + "unknown3": "Dominica", + "unknown4": "Dominica" + }, + "regions": [ + { + "id": 385875968, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 15.29846174, + "longitude": -61.396772211 + } + }, + { + "id": 385941504, + "name": "Dominica", + "translations": { + "japanese": "ドミニカ国", + "english": "Dominica", + "french": "Dominique", + "german": "Dominica", + "italian": "Dominica", + "spanish": "Dominica", + "chinese_simple": "多米尼克", + "korean": "도미니카 연방", + "dutch": "Dominica", + "portuguese": "Dominica", + "russian": "Доминика", + "chinese_traditional": "Dominica", + "unknown1": "Dominica", + "unknown2": "Dominica", + "unknown3": "Dominica", + "unknown4": "Dominica" + }, + "coordinates": { + "latitude": 15.29846174, + "longitude": -61.396772211 + } + } + ] + }, + { + "id": 24, + "iso_code": "DO", + "name": "Dominican Republic", + "translations": { + "japanese": "ドミニカ共和国", + "english": "Dominican Republic", + "french": "République dominicaine", + "german": "Dominikanische Republik", + "italian": "Repubblica Dominicana", + "spanish": "República Dominicana", + "chinese_simple": "多米尼加共和国", + "korean": "도미니카 공화국", + "dutch": "Dominicaanse Republiek", + "portuguese": "República Dominicana", + "russian": "Доминиканская Республика", + "chinese_traditional": "Dominican Republic", + "unknown1": "Dominican Republic", + "unknown2": "Dominican Republic", + "unknown3": "Dominican Republic", + "unknown4": "Dominican Republic" + }, + "regions": [ + { + "id": 402653184, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 18.462524204, + "longitude": -69.894720124 + } + }, + { + "id": 402784256, + "name": "Distrito Nacional", + "translations": { + "japanese": "ディストリト・ナショナル首都圏", + "english": "Distrito Nacional", + "french": "District National", + "german": "Distrito Nacional", + "italian": "Distretto Nazionale", + "spanish": "Distrito Nacional", + "chinese_simple": "国家区", + "korean": "도미니카 행정구", + "dutch": "Distrito Nacional", + "portuguese": "Distrito Nacional", + "russian": "Национальный округ", + "chinese_traditional": "Distrito Nacional", + "unknown1": "Distrito Nacional", + "unknown2": "Distrito Nacional", + "unknown3": "Distrito Nacional", + "unknown4": "Distrito Nacional" + }, + "coordinates": { + "latitude": 18.462524204, + "longitude": -69.894720124 + } + }, + { + "id": 402849792, + "name": "Azua", + "translations": { + "japanese": "アスア", + "english": "Azua", + "french": "Azua", + "german": "Azua", + "italian": "Azua", + "spanish": "Azua", + "chinese_simple": "阿苏阿省", + "korean": "아수아", + "dutch": "Azua", + "portuguese": "Azua", + "russian": "Азуа", + "chinese_traditional": "Azua", + "unknown1": "Azua", + "unknown2": "Azua", + "unknown3": "Azua", + "unknown4": "Azua" + }, + "coordinates": { + "latitude": 18.446044712, + "longitude": -70.72968333200001 + } + }, + { + "id": 402915328, + "name": "Baoruco", + "translations": { + "japanese": "バオルコ", + "english": "Baoruco", + "french": "Baoruco", + "german": "Baoruco", + "italian": "Baoruco", + "spanish": "Baoruco", + "chinese_simple": "巴奥鲁科省", + "korean": "바오루코", + "dutch": "Baoruco", + "portuguese": "Baoruco", + "russian": "Баоруко", + "chinese_traditional": "Baoruco", + "unknown1": "Baoruco", + "unknown2": "Baoruco", + "unknown3": "Baoruco", + "unknown4": "Baoruco" + }, + "coordinates": { + "latitude": 18.462524204, + "longitude": -71.416330707 + } + }, + { + "id": 402980864, + "name": "Barahona", + "translations": { + "japanese": "バラオナ", + "english": "Barahona", + "french": "Barahona", + "german": "Barahona", + "italian": "Barahona", + "spanish": "Barahona", + "chinese_simple": "巴拉奥纳省", + "korean": "바라오나", + "dutch": "Barahona", + "portuguese": "Barahona", + "russian": "Барахона", + "chinese_traditional": "Barahona", + "unknown1": "Barahona", + "unknown2": "Barahona", + "unknown3": "Barahona", + "unknown4": "Barahona" + }, + "coordinates": { + "latitude": 18.198852332, + "longitude": -71.097726325 + } + }, + { + "id": 403046400, + "name": "Dajabón", + "translations": { + "japanese": "ダハボン", + "english": "Dajabón", + "french": "Dajabón", + "german": "Dajabón", + "italian": "Dajabón", + "spanish": "Dajabón", + "chinese_simple": "达哈朋省", + "korean": "다하본", + "dutch": "Dajabón", + "portuguese": "Dajabón", + "russian": "Даджабон", + "chinese_traditional": "Dajabón", + "unknown1": "Dajabón", + "unknown2": "Dajabón", + "unknown3": "Dajabón", + "unknown4": "Dajabón" + }, + "coordinates": { + "latitude": 19.544677512, + "longitude": -71.696482836 + } + }, + { + "id": 403111936, + "name": "Duarte", + "translations": { + "japanese": "ドゥアルテ", + "english": "Duarte", + "french": "Duarte", + "german": "Duarte", + "italian": "Duarte", + "spanish": "Duarte", + "chinese_simple": "杜华德省", + "korean": "두아르테", + "dutch": "Duarte", + "portuguese": "Duarte", + "russian": "Дуарте", + "chinese_traditional": "Duarte", + "unknown1": "Duarte", + "unknown2": "Duarte", + "unknown3": "Duarte", + "unknown4": "Duarte" + }, + "coordinates": { + "latitude": 19.297485132, + "longitude": -70.24628358 + } + }, + { + "id": 403177472, + "name": "Espaillat", + "translations": { + "japanese": "エスパイジャト", + "english": "Espaillat", + "french": "Espaillat", + "german": "Espaillat", + "italian": "Espaillat", + "spanish": "Espaillat", + "chinese_simple": "艾斯派亚省", + "korean": "에스파이야트", + "dutch": "Espaillat", + "portuguese": "Espaillat", + "russian": "Эспаиллат", + "chinese_traditional": "Espaillat", + "unknown1": "Espaillat", + "unknown2": "Espaillat", + "unknown3": "Espaillat", + "unknown4": "Espaillat" + }, + "coordinates": { + "latitude": 19.396362084, + "longitude": -70.515449351 + } + }, + { + "id": 403243008, + "name": "Independencia", + "translations": { + "japanese": "インデペンデンシア", + "english": "Independencia", + "french": "Independencia", + "german": "Independencia", + "italian": "Independencia", + "spanish": "Independencia", + "chinese_simple": "独立省", + "korean": "인데펜덴시아", + "dutch": "Independencia", + "portuguese": "Independencia", + "russian": "Индепенденсия", + "chinese_traditional": "Independencia", + "unknown1": "Independencia", + "unknown2": "Independencia", + "unknown3": "Independencia", + "unknown4": "Independencia" + }, + "coordinates": { + "latitude": 18.489990024, + "longitude": -71.850291848 + } + }, + { + "id": 403308544, + "name": "La Altagracia", + "translations": { + "japanese": "ラ・アルタグラシア", + "english": "La Altagracia", + "french": "La Altagracia", + "german": "La Altagracia", + "italian": "La Altagracia", + "spanish": "La Altagracia", + "chinese_simple": "圣母省", + "korean": "라알타그라시아", + "dutch": "La Altagracia", + "portuguese": "La Altagracia", + "russian": "Ла-Альтаграсия", + "chinese_traditional": "La Altagracia", + "unknown1": "La Altagracia", + "unknown2": "La Altagracia", + "unknown3": "La Altagracia", + "unknown4": "La Altagracia" + }, + "coordinates": { + "latitude": 18.698730256, + "longitude": -68.664248028 + } + }, + { + "id": 403374080, + "name": "Elías Piña", + "translations": { + "japanese": "エリアス・ピーニャ", + "english": "Elías Piña", + "french": "Elías Piña", + "german": "Elías Piña", + "italian": "Elías Piña", + "spanish": "Elías Piña", + "chinese_simple": "埃利亚斯皮亚省", + "korean": "엘리아스피냐", + "dutch": "Elías Piña", + "portuguese": "Elías Piña", + "russian": "Эльяс-Пина", + "chinese_traditional": "Elías Piña", + "unknown1": "Elías Piña", + "unknown2": "Elías Piña", + "unknown3": "Elías Piña", + "unknown4": "Elías Piña" + }, + "coordinates": { + "latitude": 18.874511504, + "longitude": -71.701976015 + } + }, + { + "id": 403439616, + "name": "La Romana", + "translations": { + "japanese": "ラ・ロマーナ", + "english": "La Romana", + "french": "La Romana", + "german": "La Romana", + "italian": "La Romana", + "spanish": "La Romana", + "chinese_simple": "罗马纳省", + "korean": "라로마나", + "dutch": "La Romana", + "portuguese": "La Romana", + "russian": "Ла-Романа", + "chinese_traditional": "La Romana", + "unknown1": "La Romana", + "unknown2": "La Romana", + "unknown3": "La Romana", + "unknown4": "La Romana" + }, + "coordinates": { + "latitude": 18.413085728, + "longitude": -68.960879694 + } + }, + { + "id": 403505152, + "name": "María Trinidad Sánchez", + "translations": { + "japanese": "マリア・トリニダー・サンチェス", + "english": "María Trinidad Sánchez", + "french": "María Trinidad Sánchez", + "german": "María Trinidad Sánchez", + "italian": "María Trinidad Sánchez", + "spanish": "María Trinidad Sánchez", + "chinese_simple": "玛丽亚-桑其斯省", + "korean": "마리아 트리니다드산체스", + "dutch": "María Trinidad Sánchez", + "portuguese": "María Trinidad Sánchez", + "russian": "Мария-Тринидад-Санчес", + "chinese_traditional": "María Trinidad Sánchez", + "unknown1": "María Trinidad Sánchez", + "unknown2": "María Trinidad Sánchez", + "unknown3": "María Trinidad Sánchez", + "unknown4": "María Trinidad Sánchez" + }, + "coordinates": { + "latitude": 19.379882592, + "longitude": -69.828801976 + } + }, + { + "id": 403570688, + "name": "Monte Cristi", + "translations": { + "japanese": "モンテ・クリスティ", + "english": "Monte Cristi", + "french": "Monte Cristi", + "german": "Monte Cristi", + "italian": "Monte Cristi", + "spanish": "Monte Cristi", + "chinese_simple": "基度山省", + "korean": "몬테크리스티", + "dutch": "Monte Cristi", + "portuguese": "Monte Cristi", + "russian": "Монте-Кристи", + "chinese_traditional": "Monte Cristi", + "unknown1": "Monte Cristi", + "unknown2": "Monte Cristi", + "unknown3": "Monte Cristi", + "unknown4": "Monte Cristi" + }, + "coordinates": { + "latitude": 19.66552712, + "longitude": -71.663523762 + } + }, + { + "id": 403636224, + "name": "Pedernales", + "translations": { + "japanese": "ペデルナレス", + "english": "Pedernales", + "french": "Pedernales", + "german": "Pedernales", + "italian": "Pedernales", + "spanish": "Pedernales", + "chinese_simple": "佩德纳莱斯省", + "korean": "페데르날레스", + "dutch": "Pedernales", + "portuguese": "Pedernales", + "russian": "Педерналес", + "chinese_traditional": "Pedernales", + "unknown1": "Pedernales", + "unknown2": "Pedernales", + "unknown3": "Pedernales", + "unknown4": "Pedernales" + }, + "coordinates": { + "latitude": 18.028564248, + "longitude": -71.745921447 + } + }, + { + "id": 403701760, + "name": "Peravia", + "translations": { + "japanese": "ペラビア", + "english": "Peravia", + "french": "Peravia", + "german": "Peravia", + "italian": "Peravia", + "spanish": "Peravia", + "chinese_simple": "佩拉维亚省", + "korean": "페라비아", + "dutch": "Peravia", + "portuguese": "Peravia", + "russian": "Перавия", + "chinese_traditional": "Peravia", + "unknown1": "Peravia", + "unknown2": "Peravia", + "unknown3": "Peravia", + "unknown4": "Peravia" + }, + "coordinates": { + "latitude": 18.281249792, + "longitude": -70.328681265 + } + }, + { + "id": 403767296, + "name": "Puerto Plata", + "translations": { + "japanese": "プエルト・プラタ", + "english": "Puerto Plata", + "french": "Puerto Plata", + "german": "Puerto Plata", + "italian": "Puerto Plata", + "spanish": "Puerto Plata", + "chinese_simple": "银港省", + "korean": "푸에르토 플라타", + "dutch": "Puerto Plata", + "portuguese": "Puerto Plata", + "russian": "Пуэрто-Плата", + "chinese_traditional": "Puerto Plata", + "unknown1": "Puerto Plata", + "unknown2": "Puerto Plata", + "unknown3": "Puerto Plata", + "unknown4": "Puerto Plata" + }, + "coordinates": { + "latitude": 19.797363056000002, + "longitude": -70.68024472100001 + } + }, + { + "id": 403832832, + "name": "Salcedo", + "translations": { + "japanese": "サルセド", + "english": "Salcedo", + "french": "Salcedo", + "german": "Hermanas Mirabal", + "italian": "Salcedo", + "spanish": "Salcedo", + "chinese_simple": "萨尔塞多省", + "korean": "살세도", + "dutch": "Salcedo", + "portuguese": "Salcedo", + "russian": "Салкедо", + "chinese_traditional": "Salcedo", + "unknown1": "Salcedo", + "unknown2": "Salcedo", + "unknown3": "Salcedo", + "unknown4": "Salcedo" + }, + "coordinates": { + "latitude": 19.396362084, + "longitude": -70.345160802 + } + }, + { + "id": 403898368, + "name": "Samaná", + "translations": { + "japanese": "セマナ", + "english": "Samaná", + "french": "Samaná", + "german": "Samaná", + "italian": "Samaná", + "spanish": "Samaná", + "chinese_simple": "山美纳省", + "korean": "사마나", + "dutch": "Samaná", + "portuguese": "Samaná", + "russian": "Самана", + "chinese_traditional": "Samaná", + "unknown1": "Samaná", + "unknown2": "Samaná", + "unknown3": "Samaná", + "unknown4": "Samaná" + }, + "coordinates": { + "latitude": 19.215087672, + "longitude": -69.31244315000001 + } + }, + { + "id": 403963904, + "name": "Sánchez Ramírez", + "translations": { + "japanese": "サンチェス・ラミレス", + "english": "Sánchez Ramírez", + "french": "Sánchez Ramírez", + "german": "Sánchez Ramírez", + "italian": "Sánchez Ramírez", + "spanish": "Sánchez Ramírez", + "chinese_simple": "桑切斯-拉米斯省", + "korean": "산체스라미레스", + "dutch": "Sánchez Ramírez", + "portuguese": "Sánchez Ramírez", + "russian": "Санчес-Рамирес", + "chinese_traditional": "Sánchez Ramírez", + "unknown1": "Sánchez Ramírez", + "unknown2": "Sánchez Ramírez", + "unknown3": "Sánchez Ramírez", + "unknown4": "Sánchez Ramírez" + }, + "coordinates": { + "latitude": 19.044799588, + "longitude": -70.147406358 + } + }, + { + "id": 404029440, + "name": "San Juan", + "translations": { + "japanese": "サン・フアン", + "english": "San Juan", + "french": "San Juan", + "german": "San Juan", + "italian": "San Juan", + "spanish": "San Juan", + "chinese_simple": "圣胡安省", + "korean": "산후안", + "dutch": "San Juan", + "portuguese": "San Juan", + "russian": "Сан-Хуан", + "chinese_traditional": "San Juan", + "unknown1": "San Juan", + "unknown2": "San Juan", + "unknown3": "San Juan", + "unknown4": "San Juan" + }, + "coordinates": { + "latitude": 18.797607208, + "longitude": -71.229562621 + } + }, + { + "id": 404094976, + "name": "San Pedro de Macorís", + "translations": { + "japanese": "サン・ペドロ・デ・マコリス", + "english": "San Pedro de Macorís", + "french": "San Pedro de Macorís", + "german": "San Pedro de Macorís", + "italian": "San Pedro de Macorís", + "spanish": "San Pedro de Macorís", + "chinese_simple": "圣彼德省", + "korean": "산페드로데마코리스", + "dutch": "San Pedro de Macorís", + "portuguese": "San Pedro de Macorís", + "russian": "Сан-Педро-де-Маркорис", + "chinese_traditional": "San Pedro de Macorís", + "unknown1": "San Pedro de Macorís", + "unknown2": "San Pedro de Macorís", + "unknown3": "San Pedro de Macorís", + "unknown4": "San Pedro de Macorís" + }, + "coordinates": { + "latitude": 18.446044712, + "longitude": -69.295963613 + } + }, + { + "id": 404160512, + "name": "Santiago", + "translations": { + "japanese": "サンティアゴ", + "english": "Santiago", + "french": "Santiago", + "german": "Santiago", + "italian": "Santiago", + "spanish": "Santiago", + "chinese_simple": "圣地亚哥省", + "korean": "산티아고", + "dutch": "Santiago", + "portuguese": "Santiago", + "russian": "Сантьяго", + "chinese_traditional": "Santiago", + "unknown1": "Santiago", + "unknown2": "Santiago", + "unknown3": "Santiago", + "unknown4": "Santiago" + }, + "coordinates": { + "latitude": 19.44580056, + "longitude": -70.696724258 + } + }, + { + "id": 404226048, + "name": "Santiago Rodríguez", + "translations": { + "japanese": "サンティアゴ・ロドリゲス", + "english": "Santiago Rodríguez", + "french": "Santiago Rodríguez", + "german": "Santiago Rodríguez", + "italian": "Santiago Rodríguez", + "spanish": "Santiago Rodríguez", + "chinese_simple": "圣地亚哥-罗里盖兹省", + "korean": "산티아고로드리게스", + "dutch": "Santiago Rodríguez", + "portuguese": "Santiago Rodríguez", + "russian": "Сантьяго-Родригес", + "chinese_traditional": "Santiago Rodríguez", + "unknown1": "Santiago Rodríguez", + "unknown2": "Santiago Rodríguez", + "unknown3": "Santiago Rodríguez", + "unknown4": "Santiago Rodríguez" + }, + "coordinates": { + "latitude": 19.462280052, + "longitude": -71.328439843 + } + }, + { + "id": 404291584, + "name": "Valverde", + "translations": { + "japanese": "バルベルデ", + "english": "Valverde", + "french": "Valverde", + "german": "Valverde", + "italian": "Valverde", + "spanish": "Valverde", + "chinese_simple": "巴韦德省", + "korean": "발베르데", + "dutch": "Valverde", + "portuguese": "Valverde", + "russian": "Вальверде", + "chinese_traditional": "Valverde", + "unknown1": "Valverde", + "unknown2": "Valverde", + "unknown3": "Valverde", + "unknown4": "Valverde" + }, + "coordinates": { + "latitude": 19.566650168, + "longitude": -71.081246788 + } + }, + { + "id": 404357120, + "name": "El Seíbo", + "translations": { + "japanese": "エル・セイボ", + "english": "El Seíbo", + "french": "El Seibo", + "german": "El Seíbo", + "italian": "El Seíbo", + "spanish": "El Seíbo", + "chinese_simple": "赛堡省", + "korean": "엘세이보", + "dutch": "El Seibo", + "portuguese": "El Seíbo", + "russian": "Эль-Сейбо", + "chinese_traditional": "El Seíbo", + "unknown1": "El Seíbo", + "unknown2": "El Seíbo", + "unknown3": "El Seíbo", + "unknown4": "El Seíbo" + }, + "coordinates": { + "latitude": 18.764648224000002, + "longitude": -69.032291021 + } + }, + { + "id": 404422656, + "name": "Hato Mayor", + "translations": { + "japanese": "アト・マジョール", + "english": "Hato Mayor", + "french": "Hato Mayor", + "german": "Hato Mayor", + "italian": "Hato Mayor", + "spanish": "Hato Mayor", + "chinese_simple": "阿托马约省", + "korean": "아토마요르", + "dutch": "Hato Mayor", + "portuguese": "Hato Mayor", + "russian": "Хато-Майор", + "chinese_traditional": "Hato Mayor", + "unknown1": "Hato Mayor", + "unknown2": "Hato Mayor", + "unknown3": "Hato Mayor", + "unknown4": "Hato Mayor" + }, + "coordinates": { + "latitude": 18.764648224000002, + "longitude": -69.246525002 + } + }, + { + "id": 404488192, + "name": "La Vega", + "translations": { + "japanese": "ラ・ベガ", + "english": "La Vega", + "french": "La Vega", + "german": "La Vega", + "italian": "La Vega", + "spanish": "La Vega", + "chinese_simple": "拉维加省", + "korean": "라베가", + "dutch": "La Vega", + "portuguese": "La Vega", + "russian": "Ла-Вега", + "chinese_traditional": "La Vega", + "unknown1": "La Vega", + "unknown2": "La Vega", + "unknown3": "La Vega", + "unknown4": "La Vega" + }, + "coordinates": { + "latitude": 19.215087672, + "longitude": -70.515449351 + } + }, + { + "id": 404553728, + "name": "Monseñor Nouel", + "translations": { + "japanese": "モンセニョール・ノウエル", + "english": "Monseñor Nouel", + "french": "Monseñor Nouel", + "german": "Monseñor Nouel", + "italian": "Monseñor Nouel", + "spanish": "Monseñor Nouel", + "chinese_simple": "主教-瑙黎省", + "korean": "몬세뇨르노우엘", + "dutch": "Monseñor Nouel", + "portuguese": "Monseñor Nouel", + "russian": "Монсенор-Нуэль", + "chinese_traditional": "Monseñor Nouel", + "unknown1": "Monseñor Nouel", + "unknown2": "Monseñor Nouel", + "unknown3": "Monseñor Nouel", + "unknown4": "Monseñor Nouel" + }, + "coordinates": { + "latitude": 18.929443144, + "longitude": -70.41107895 + } + }, + { + "id": 404619264, + "name": "Monte Plata", + "translations": { + "japanese": "モンテ・プラタ", + "english": "Monte Plata", + "french": "Monte Plata", + "german": "Monte Plata", + "italian": "Monte Plata", + "spanish": "Monte Plata", + "chinese_simple": "银山省", + "korean": "몬테플라타", + "dutch": "Monte Plata", + "portuguese": "Monte Plata", + "russian": "Монте-Плата", + "chinese_traditional": "Monte Plata", + "unknown1": "Monte Plata", + "unknown2": "Monte Plata", + "unknown3": "Monte Plata", + "unknown4": "Monte Plata" + }, + "coordinates": { + "latitude": 18.797607208, + "longitude": -69.779363365 + } + }, + { + "id": 404684800, + "name": "San Cristóbal", + "translations": { + "japanese": "サン・クリストバル", + "english": "San Cristóbal", + "french": "San Cristóbal", + "german": "San Cristóbal", + "italian": "San Cristóbal", + "spanish": "San Cristóbal", + "chinese_simple": "圣克里斯多堡省", + "korean": "산크리스토발", + "dutch": "San Cristóbal", + "portuguese": "São Cristóvão", + "russian": "Сан-Кристобаль", + "chinese_traditional": "San Cristóbal", + "unknown1": "San Cristóbal", + "unknown2": "San Cristóbal", + "unknown3": "San Cristóbal", + "unknown4": "San Cristóbal" + }, + "coordinates": { + "latitude": 18.413085728, + "longitude": -70.097967747 + } + } + ] + }, + { + "id": 25, + "iso_code": "EC", + "name": "Ecuador", + "translations": { + "japanese": "エクアドル", + "english": "Ecuador", + "french": "Équateur", + "german": "Ecuador", + "italian": "Ecuador", + "spanish": "Ecuador", + "chinese_simple": "厄瓜多尔", + "korean": "에콰도르", + "dutch": "Ecuador", + "portuguese": "Equador", + "russian": "Эквадор", + "chinese_traditional": "Ecuador", + "unknown1": "Ecuador", + "unknown2": "Ecuador", + "unknown3": "Ecuador", + "unknown4": "Ecuador" + }, + "regions": [ + { + "id": 419430400, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": -0.21423441999999682, + "longitude": -78.497038438 + } + }, + { + "id": 419561472, + "name": "Pichincha", + "translations": { + "japanese": "ピチンチャ", + "english": "Pichincha", + "french": "Pichincha", + "german": "Pichincha", + "italian": "Pichincha", + "spanish": "Pichincha", + "chinese_simple": "皮钦查省", + "korean": "피친차", + "dutch": "Pichincha", + "portuguese": "Pichincha", + "russian": "Пичинча", + "chinese_traditional": "Pichincha", + "unknown1": "Pichincha", + "unknown2": "Pichincha", + "unknown3": "Pichincha", + "unknown4": "Pichincha" + }, + "coordinates": { + "latitude": -0.21423441999999682, + "longitude": -78.497038438 + } + }, + { + "id": 419627008, + "name": "Galápagos", + "translations": { + "japanese": "ガラパゴス", + "english": "Galápagos", + "french": "Galápagos", + "german": "Galapagosinseln", + "italian": "Galápagos", + "spanish": "Galápagos", + "chinese_simple": "加拉帕戈斯省", + "korean": "갈라파고스", + "dutch": "Galápagos", + "portuguese": "Galápagos", + "russian": "Галапагос", + "chinese_traditional": "Galápagos", + "unknown1": "Galápagos", + "unknown2": "Galápagos", + "unknown3": "Galápagos", + "unknown4": "Galápagos" + }, + "coordinates": { + "latitude": -0.8953867559999935, + "longitude": -89.59875319700001 + } + }, + { + "id": 419692544, + "name": "Azuay", + "translations": { + "japanese": "アスアイ", + "english": "Azuay", + "french": "Azuay", + "german": "Azuay", + "italian": "Azuay", + "spanish": "Azuay", + "chinese_simple": "阿苏艾省", + "korean": "아수아이", + "dutch": "Azuay", + "portuguese": "Azuay", + "russian": "Асуай", + "chinese_traditional": "Azuay", + "unknown1": "Azuay", + "unknown2": "Azuay", + "unknown3": "Azuay", + "unknown4": "Azuay" + }, + "coordinates": { + "latitude": -2.8784189600000047, + "longitude": -78.98043819 + } + }, + { + "id": 419758080, + "name": "Bolívar", + "translations": { + "japanese": "ボリーバル", + "english": "Bolívar", + "french": "Bolívar", + "german": "Bolívar", + "italian": "Bolívar", + "spanish": "Bolívar", + "chinese_simple": "玻利瓦尔省", + "korean": "볼리바르", + "dutch": "Bolívar", + "portuguese": "Bolívar", + "russian": "Боливар", + "chinese_traditional": "Bolívar", + "unknown1": "Bolívar", + "unknown2": "Bolívar", + "unknown3": "Bolívar", + "unknown4": "Bolívar" + }, + "coordinates": { + "latitude": -1.5985117479999928, + "longitude": -78.996917727 + } + }, + { + "id": 419823616, + "name": "Cañar", + "translations": { + "japanese": "カニャル", + "english": "Cañar", + "french": "Cañar", + "german": "Cañar", + "italian": "Cañar", + "spanish": "Cañar", + "chinese_simple": "卡尼亚尔省", + "korean": "카냐르", + "dutch": "Cañar", + "portuguese": "Cañar", + "russian": "Каньяр", + "chinese_traditional": "Cañar", + "unknown1": "Cañar", + "unknown2": "Cañar", + "unknown3": "Cañar", + "unknown4": "Cañar" + }, + "coordinates": { + "latitude": -2.730103532000001, + "longitude": -78.832122357 + } + }, + { + "id": 419889152, + "name": "Carchi", + "translations": { + "japanese": "カルチ", + "english": "Carchi", + "french": "Carchi", + "german": "Carchi", + "italian": "Carchi", + "spanish": "Carchi", + "chinese_simple": "卡尔奇省", + "korean": "카르치", + "dutch": "Carchi", + "portuguese": "Carchi", + "russian": "Карчи", + "chinese_traditional": "Carchi", + "unknown1": "Carchi", + "unknown2": "Carchi", + "unknown3": "Carchi", + "unknown4": "Carchi" + }, + "coordinates": { + "latitude": 0.79650878, + "longitude": -77.72799337800001 + } + }, + { + "id": 419954688, + "name": "Chimborazo", + "translations": { + "japanese": "チンボラソ", + "english": "Chimborazo", + "french": "Chimborazo", + "german": "Chimborazo", + "italian": "Chimborazo", + "spanish": "Chimborazo", + "chinese_simple": "钦博拉索省", + "korean": "침보라소", + "dutch": "Chimborazo", + "portuguese": "Chimborazo", + "russian": "Чимборасо", + "chinese_traditional": "Chimborazo", + "unknown1": "Chimborazo", + "unknown2": "Chimborazo", + "unknown3": "Chimborazo", + "unknown4": "Chimborazo" + }, + "coordinates": { + "latitude": -1.6644297160000008, + "longitude": -78.62887473400001 + } + }, + { + "id": 420020224, + "name": "Cotopaxi", + "translations": { + "japanese": "コトパクシ", + "english": "Cotopaxi", + "french": "Cotopaxi", + "german": "Cotopaxi", + "italian": "Cotopaxi", + "spanish": "Cotopaxi", + "chinese_simple": "科托帕希省", + "korean": "코토팍시", + "dutch": "Cotopaxi", + "portuguese": "Cotopaxi", + "russian": "Котопакси", + "chinese_traditional": "Cotopaxi", + "unknown1": "Cotopaxi", + "unknown2": "Cotopaxi", + "unknown3": "Cotopaxi", + "unknown4": "Cotopaxi" + }, + "coordinates": { + "latitude": -0.9283457399999975, + "longitude": -78.612395197 + } + }, + { + "id": 420085760, + "name": "El Oro", + "translations": { + "japanese": "エル・オロ", + "english": "El Oro", + "french": "El Oro", + "german": "El Oro", + "italian": "El Oro", + "spanish": "El Oro", + "chinese_simple": "埃尔奥罗省", + "korean": "엘오로", + "dutch": "El Oro", + "portuguese": "El Oro", + "russian": "Эль-Оро", + "chinese_traditional": "El Oro", + "unknown1": "El Oro", + "unknown2": "El Oro", + "unknown3": "El Oro", + "unknown4": "El Oro" + }, + "coordinates": { + "latitude": -3.262940439999994, + "longitude": -79.963717231 + } + }, + { + "id": 420151296, + "name": "Esmeraldas", + "translations": { + "japanese": "エスメラルダス", + "english": "Esmeraldas", + "french": "Esmeraldas", + "german": "Esmeraldas", + "italian": "Esmeraldas", + "spanish": "Esmeraldas", + "chinese_simple": "埃斯梅拉尔达斯省", + "korean": "에스메랄다스", + "dutch": "Esmeraldas", + "portuguese": "Esmeraldas", + "russian": "Эсмеральдас", + "chinese_traditional": "Esmeraldas", + "unknown1": "Esmeraldas", + "unknown2": "Esmeraldas", + "unknown3": "Esmeraldas", + "unknown4": "Esmeraldas" + }, + "coordinates": { + "latitude": 0.983276356, + "longitude": -79.69455146 + } + }, + { + "id": 420216832, + "name": "Guayas", + "translations": { + "japanese": "グアヤス", + "english": "Guayas", + "french": "Guayas", + "german": "Guayas", + "italian": "Guayas", + "spanish": "Guayas", + "chinese_simple": "瓜亚斯省", + "korean": "과야스", + "dutch": "Guayas", + "portuguese": "Guayas", + "russian": "Гуаяс", + "chinese_traditional": "Guayas", + "unknown1": "Guayas", + "unknown2": "Guayas", + "unknown3": "Guayas", + "unknown4": "Guayas" + }, + "coordinates": { + "latitude": -2.164307640000004, + "longitude": -79.897799083 + } + }, + { + "id": 420282368, + "name": "Imbabura", + "translations": { + "japanese": "インバブラ", + "english": "Imbabura", + "french": "Imbabura", + "german": "Imbabura", + "italian": "Imbabura", + "spanish": "Imbabura", + "chinese_simple": "因巴布拉省", + "korean": "임바부라", + "dutch": "Imbabura", + "portuguese": "Imbabura", + "russian": "Имбабура", + "chinese_traditional": "Imbabura", + "unknown1": "Imbabura", + "unknown2": "Imbabura", + "unknown3": "Imbabura", + "unknown4": "Imbabura" + }, + "coordinates": { + "latitude": 0.346069332, + "longitude": -78.112515908 + } + }, + { + "id": 420347904, + "name": "Loja", + "translations": { + "japanese": "ロハ", + "english": "Loja", + "french": "Loja", + "german": "Loja", + "italian": "Loja", + "spanish": "Loja", + "chinese_simple": "洛哈省", + "korean": "로하", + "dutch": "Loja", + "portuguese": "Loja", + "russian": "Лоха", + "chinese_traditional": "Loja", + "unknown1": "Loja", + "unknown2": "Loja", + "unknown3": "Loja", + "unknown4": "Loja" + }, + "coordinates": { + "latitude": -3.9990244159999975, + "longitude": -79.211151708 + } + }, + { + "id": 420413440, + "name": "Los Ríos", + "translations": { + "japanese": "ロス・リオス", + "english": "Los Ríos", + "french": "Los Ríos", + "german": "Los Ríos", + "italian": "Los Ríos", + "spanish": "Los Ríos", + "chinese_simple": "洛斯里奥斯省", + "korean": "로스 리오스", + "dutch": "Los Ríos", + "portuguese": "Los Ríos", + "russian": "Лос-Риос", + "chinese_traditional": "Los Ríos", + "unknown1": "Los Ríos", + "unknown2": "Los Ríos", + "unknown3": "Los Ríos", + "unknown4": "Los Ríos" + }, + "coordinates": { + "latitude": -1.8127451440000044, + "longitude": -79.513276553 + } + }, + { + "id": 420478976, + "name": "Manabí", + "translations": { + "japanese": "マナビ", + "english": "Manabí", + "french": "Manabí", + "german": "Manabí", + "italian": "Manabí", + "spanish": "Manabí", + "chinese_simple": "马纳比省", + "korean": "마나비", + "dutch": "Manabí", + "portuguese": "Manabí", + "russian": "Манаби", + "chinese_traditional": "Manabí", + "unknown1": "Manabí", + "unknown2": "Manabí", + "unknown3": "Manabí", + "unknown4": "Manabí" + }, + "coordinates": { + "latitude": -1.0491953479999978, + "longitude": -80.447116983 + } + }, + { + "id": 420544512, + "name": "Morona-Santiago", + "translations": { + "japanese": "モロナ・サンティアゴ", + "english": "Morona-Santiago", + "french": "Morona-Santiago", + "german": "Morona Santiago", + "italian": "Morona Santiago", + "spanish": "Morona-Santiago", + "chinese_simple": "莫罗纳-圣地亚哥省", + "korean": "모로나 산티아고", + "dutch": "Morona-Santiago", + "portuguese": "Morona-Santiago", + "russian": "Морона-Сантьяго", + "chinese_traditional": "Morona-Santiago", + "unknown1": "Morona-Santiago", + "unknown2": "Morona-Santiago", + "unknown3": "Morona-Santiago", + "unknown4": "Morona-Santiago" + }, + "coordinates": { + "latitude": -2.3126230679999935, + "longitude": -78.112515908 + } + }, + { + "id": 420610048, + "name": "Pastaza", + "translations": { + "japanese": "パスタサ", + "english": "Pastaza", + "french": "Pastaza", + "german": "Pastaza", + "italian": "Pastaza", + "spanish": "Pastaza", + "chinese_simple": "帕斯塔萨省", + "korean": "파스타사", + "dutch": "Pastaza", + "portuguese": "Pastaza", + "russian": "Пастаса", + "chinese_traditional": "Pastaza", + "unknown1": "Pastaza", + "unknown2": "Pastaza", + "unknown3": "Pastaza", + "unknown4": "Pastaza" + }, + "coordinates": { + "latitude": -1.4611826480000047, + "longitude": -77.980679612 + } + }, + { + "id": 420675584, + "name": "Tungurahua", + "translations": { + "japanese": "トゥングラワ", + "english": "Tungurahua", + "french": "Tungurahua", + "german": "Tungurahua", + "italian": "Tungurahua", + "spanish": "Tungurahua", + "chinese_simple": "通古拉瓦省", + "korean": "퉁그라우아", + "dutch": "Tungurahua", + "portuguese": "Tungurahua", + "russian": "Тункурагуа", + "chinese_traditional": "Tungurahua", + "unknown1": "Tungurahua", + "unknown2": "Tungurahua", + "unknown3": "Tungurahua", + "unknown4": "Tungurahua" + }, + "coordinates": { + "latitude": -1.2469492519999932, + "longitude": -78.612395197 + } + }, + { + "id": 420741120, + "name": "Zamora-Chinchipe", + "translations": { + "japanese": "サモラ・チンチペ", + "english": "Zamora-Chinchipe", + "french": "Zamora-Chinchipe", + "german": "Zamora Chinchipe", + "italian": "Zamora Chinchipe", + "spanish": "Zamora-Chinchipe", + "chinese_simple": "萨莫拉-钦奇佩省", + "korean": "사모라 친치페", + "dutch": "Zamora-Chinchipe", + "portuguese": "Zamora-Chinchipe", + "russian": "Самора-Чинчипе", + "chinese_traditional": "Zamora-Chinchipe", + "unknown1": "Zamora-Chinchipe", + "unknown2": "Zamora-Chinchipe", + "unknown3": "Zamora-Chinchipe", + "unknown4": "Zamora-Chinchipe" + }, + "coordinates": { + "latitude": -4.064942384000005, + "longitude": -78.952972295 + } + }, + { + "id": 420806656, + "name": "Sucumbios", + "translations": { + "japanese": "スクンビオス", + "english": "Sucumbios", + "french": "Sucumbíos", + "german": "Sucumbíos", + "italian": "Sucumbíos", + "spanish": "Sucumbíos", + "chinese_simple": "苏昆毕奥斯省", + "korean": "스쿰비오스", + "dutch": "Sucumbíos", + "portuguese": "Sucumbíos", + "russian": "Сукумбиос", + "chinese_traditional": "Sucumbios", + "unknown1": "Sucumbios", + "unknown2": "Sucumbios", + "unknown3": "Sucumbios", + "unknown4": "Sucumbios" + }, + "coordinates": { + "latitude": 0.08239746, + "longitude": -76.882043812 + } + }, + { + "id": 420872192, + "name": "Napo", + "translations": { + "japanese": "ナポ", + "english": "Napo", + "french": "Napo", + "german": "Napo", + "italian": "Napo", + "spanish": "Napo", + "chinese_simple": "纳波省", + "korean": "나포", + "dutch": "Napo", + "portuguese": "Napo", + "russian": "Напо", + "chinese_traditional": "Napo", + "unknown1": "Napo", + "unknown2": "Napo", + "unknown3": "Napo", + "unknown4": "Napo" + }, + "coordinates": { + "latitude": -0.9832773800000041, + "longitude": -77.815884242 + } + }, + { + "id": 420937728, + "name": "Orellana", + "translations": { + "japanese": "オレリャナ", + "english": "Orellana", + "french": "Orellana", + "german": "Orellana", + "italian": "Orellana", + "spanish": "Orellana", + "chinese_simple": "奥雷利亚纳省", + "korean": "오렐라나", + "dutch": "Orellana", + "portuguese": "Orellana", + "russian": "Орельяна", + "chinese_traditional": "Orellana", + "unknown1": "Orellana", + "unknown2": "Orellana", + "unknown3": "Orellana", + "unknown4": "Orellana" + }, + "coordinates": { + "latitude": -0.7965098039999958, + "longitude": -76.365684986 + } + }, + { + "id": 421003264, + "name": "Santa Elena", + "translations": { + "japanese": "サンタ・エレーナ", + "english": "Santa Elena", + "french": "Santa Elena", + "german": "Santa Elena", + "italian": "Santa Elena", + "spanish": "Santa Elena", + "chinese_simple": "圣埃伦娜省", + "korean": "산타엘레나", + "dutch": "Santa Elena", + "portuguese": "Santa Elena", + "russian": "Санта Элена", + "chinese_traditional": "Santa Elena", + "unknown1": "Santa Elena", + "unknown2": "Santa Elena", + "unknown3": "Santa Elena", + "unknown4": "Santa Elena" + }, + "coordinates": { + "latitude": -2.224732443999997, + "longitude": -80.853612229 + } + }, + { + "id": 421068800, + "name": "Santo Domingo de los Tsáchilas", + "translations": { + "japanese": "サント・ドミンゴ・デ・ロス・ツァチラス", + "english": "Santo Domingo de los Tsáchilas", + "french": "Santo Domingo de los Tsáchilas", + "german": "Santo Domingo de los Tsáchilas", + "italian": "Santo Domingo de los Tsáchilas", + "spanish": "Santo Domingo de los Tsáchilas", + "chinese_simple": "圣多明各-德洛斯查奇拉斯省", + "korean": "산토도밍고델로스트사칠라스", + "dutch": "Santo Domingo de los Tsáchilas", + "portuguese": "Santo Domingo de los Tsáchilas", + "russian": "Санто Доминго де лос Тсачилас", + "chinese_traditional": "Santo Domingo de los Tsáchilas", + "unknown1": "Santo Domingo de los Tsáchilas", + "unknown2": "Santo Domingo de los Tsáchilas", + "unknown3": "Santo Domingo de los Tsáchilas", + "unknown4": "Santo Domingo de los Tsáchilas" + }, + "coordinates": { + "latitude": -0.24719340400000078, + "longitude": -79.14523356 + } + } + ] + }, + { + "id": 26, + "iso_code": "SV", + "name": "El Salvador", + "translations": { + "japanese": "エルサルバドル", + "english": "El Salvador", + "french": "Salvador", + "german": "El Salvador", + "italian": "El Salvador", + "spanish": "El Salvador", + "chinese_simple": "萨尔瓦多", + "korean": "엘살바도르", + "dutch": "El Salvador", + "portuguese": "El Salvador", + "russian": "Сальвадор", + "chinese_traditional": "El Salvador", + "unknown1": "El Salvador", + "unknown2": "El Salvador", + "unknown3": "El Salvador", + "unknown4": "El Salvador" + }, + "regions": [ + { + "id": 436207616, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 13.70544418, + "longitude": -89.19775113 + } + }, + { + "id": 436338688, + "name": "San Salvador", + "translations": { + "japanese": "サン・サルバドル県", + "english": "San Salvador", + "french": "San Salvador", + "german": "San Salvador", + "italian": "San Salvador", + "spanish": "San Salvador", + "chinese_simple": "圣萨尔瓦多省", + "korean": "산살바도르 주", + "dutch": "San Salvador", + "portuguese": "San Salvador", + "russian": "Сан-Сальвадор", + "chinese_traditional": "San Salvador", + "unknown1": "San Salvador", + "unknown2": "San Salvador", + "unknown3": "San Salvador", + "unknown4": "San Salvador" + }, + "coordinates": { + "latitude": 13.70544418, + "longitude": -89.19775113 + } + }, + { + "id": 436404224, + "name": "Ahuachapán", + "translations": { + "japanese": "アワチャパン県", + "english": "Ahuachapán", + "french": "Ahuachapán", + "german": "Ahuachapán", + "italian": "Ahuachapán", + "spanish": "Ahuachapán", + "chinese_simple": "阿瓦查潘省", + "korean": "아우아차판 주", + "dutch": "Ahuachapán", + "portuguese": "Ahuachapán", + "russian": "Ауачапан", + "chinese_traditional": "Ahuachapán", + "unknown1": "Ahuachapán", + "unknown2": "Ahuachapán", + "unknown3": "Ahuachapán", + "unknown4": "Ahuachapán" + }, + "coordinates": { + "latitude": 13.919677576, + "longitude": -89.840453073 + } + }, + { + "id": 436469760, + "name": "Cabañas", + "translations": { + "japanese": "カバニャス県", + "english": "Cabañas", + "french": "Cabañas", + "german": "Cabañas", + "italian": "Cabañas", + "spanish": "Cabañas", + "chinese_simple": "卡瓦尼亚斯省", + "korean": "카바냐스 주", + "dutch": "Cabañas", + "portuguese": "Cabañas", + "russian": "Кабанас", + "chinese_traditional": "Cabañas", + "unknown1": "Cabañas", + "unknown2": "Cabañas", + "unknown3": "Cabañas", + "unknown4": "Cabañas" + }, + "coordinates": { + "latitude": 13.864745936, + "longitude": -88.631953693 + } + }, + { + "id": 436535296, + "name": "Chalatenango", + "translations": { + "japanese": "チャラテナンゴ県", + "english": "Chalatenango", + "french": "Chalatenango", + "german": "Chalatenango", + "italian": "Chalatenango", + "spanish": "Chalatenango", + "chinese_simple": "查拉特南戈省", + "korean": "찰라테낭고 주", + "dutch": "Chalatenango", + "portuguese": "Chalatenango", + "russian": "Чалатенанго", + "chinese_traditional": "Chalatenango", + "unknown1": "Chalatenango", + "unknown2": "Chal얆徇᥄\udac7슃\udfd9榩", + "unknown3": "Chalatenango", + "unknown4": "Chalatenango" + }, + "coordinates": { + "latitude": 14.029540856, + "longitude": -88.928585359 + } + }, + { + "id": 436600832, + "name": "Cuscatlán", + "translations": { + "japanese": "クスカトラン県", + "english": "Cuscatlán", + "french": "Cuscatlán", + "german": "Cuscatlán", + "italian": "Cuscatlán", + "spanish": "Cuscatlán", + "chinese_simple": "库斯卡特兰省", + "korean": "쿠스카틀란 주", + "dutch": "Cuscatlán", + "portuguese": "Cuscatlán", + "russian": "Кускатлан", + "chinese_traditional": "Cuscatlán", + "unknown1": "Cuscatlán", + "unknown2": "Cuscatlán", + "unknown3": "Cuscatlán", + "unknown4": "Cuscatlán" + }, + "coordinates": { + "latitude": 13.716430508, + "longitude": -88.928585359 + } + }, + { + "id": 436666368, + "name": "La Libertad", + "translations": { + "japanese": "ラ・リベルター県", + "english": "La Libertad", + "french": "La Libertad", + "german": "La Libertad", + "italian": "La Libertad", + "spanish": "La Libertad", + "chinese_simple": "拉利伯塔德省", + "korean": "라리베르타드 주", + "dutch": "La Libertad", + "portuguese": "La Libertad", + "russian": "Ла-Либертад", + "chinese_traditional": "La Libertad", + "unknown1": "La Libertad", + "unknown2": "La Libertad", + "unknown3": "La Libertad", + "unknown4": "La Libertad" + }, + "coordinates": { + "latitude": 13.672485196, + "longitude": -89.274655636 + } + }, + { + "id": 436731904, + "name": "La Paz", + "translations": { + "japanese": "ラパス県", + "english": "La Paz", + "french": "La Paz", + "german": "La Paz", + "italian": "La Paz", + "spanish": "La Paz", + "chinese_simple": "拉巴斯省", + "korean": "라파스 주", + "dutch": "La Paz", + "portuguese": "La Paz", + "russian": "Ла-Пас", + "chinese_traditional": "La Paz", + "unknown1": "La Paz", + "unknown2": "La Paz", + "unknown3": "La Paz", + "unknown4": "La Paz" + }, + "coordinates": { + "latitude": 13.496703948, + "longitude": -88.862667211 + } + }, + { + "id": 436797440, + "name": "La Unión", + "translations": { + "japanese": "ラ・ウニオン県", + "english": "La Unión", + "french": "La Unión", + "german": "La Unión", + "italian": "La Unión", + "spanish": "La Unión", + "chinese_simple": "拉乌尼翁省", + "korean": "라우니온 주", + "dutch": "La Unión", + "portuguese": "La Unión", + "russian": "Ла-Унион", + "chinese_traditional": "La Unión", + "unknown1": "La Unión", + "unknown2": "La Unión", + "unknown3": "La Unión", + "unknown4": "La Unión" + }, + "coordinates": { + "latitude": 13.331909028, + "longitude": -87.840935917 + } + }, + { + "id": 436862976, + "name": "Morazán", + "translations": { + "japanese": "モラサン県", + "english": "Morazán", + "french": "Morazán", + "german": "Morazán", + "italian": "Morazán", + "spanish": "Morazán", + "chinese_simple": "莫拉桑省", + "korean": "모라산 주", + "dutch": "Morazán", + "portuguese": "Morazán", + "russian": "Морасан", + "chinese_traditional": "Morazán", + "unknown1": "Morazán", + "unknown2": "Morazán", + "unknown3": "Morazán", + "unknown4": "Morazán" + }, + "coordinates": { + "latitude": 13.699951016, + "longitude": -88.09911533 + } + }, + { + "id": 436928512, + "name": "San Miguel", + "translations": { + "japanese": "サン・ミゲル県", + "english": "San Miguel", + "french": "San Miguel", + "german": "San Miguel", + "italian": "San Miguel", + "spanish": "San Miguel", + "chinese_simple": "圣米格尔省", + "korean": "산미겔 주", + "dutch": "San Miguel", + "portuguese": "San Miguel", + "russian": "Сан-Мигель", + "chinese_traditional": "San Miguel", + "unknown1": "San Miguel", + "unknown2": "San Miguel", + "unknown3": "San Miguel", + "unknown4": "San Miguel" + }, + "coordinates": { + "latitude": 13.480224456, + "longitude": -88.18151301500001 + } + }, + { + "id": 436994048, + "name": "Santa Ana", + "translations": { + "japanese": "サンタ・アナ県", + "english": "Santa Ana", + "french": "Santa Ana", + "german": "Santa Ana", + "italian": "Santa Ana", + "spanish": "Santa Ana", + "chinese_simple": "圣安娜省", + "korean": "산타아나 주", + "dutch": "Santa Ana", + "portuguese": "Santa Ana", + "russian": "Санта-Ана", + "chinese_traditional": "Santa Ana", + "unknown1": "Santa Ana", + "unknown2": "Santa Ana", + "unknown3": "Santa Ana", + "unknown4": "Santa Ana" + }, + "coordinates": { + "latitude": 13.991088708, + "longitude": -89.554807765 + } + }, + { + "id": 437059584, + "name": "San Vicente", + "translations": { + "japanese": "サンビセンテ県", + "english": "San Vicente", + "french": "San Vicente", + "german": "San Vicente", + "italian": "San Vicente", + "spanish": "San Vicente", + "chinese_simple": "圣维森特省", + "korean": "산비센테 주", + "dutch": "San Vicente", + "portuguese": "San Vicente", + "russian": "Сан-Висенте", + "chinese_traditional": "San Vicente", + "unknown1": "San Vicente", + "unknown2": "San Vicente", + "unknown3": "San Vicente", + "unknown4": "San Vicente" + }, + "coordinates": { + "latitude": 13.628539884, + "longitude": -88.79674906300001 + } + }, + { + "id": 437125120, + "name": "Sonsonate", + "translations": { + "japanese": "ソンソナテ県", + "english": "Sonsonate", + "french": "Sonsonate", + "german": "Sonsonate", + "italian": "Sonsonate", + "spanish": "Sonsonate", + "chinese_simple": "松索纳特省", + "korean": "손소나테 주", + "dutch": "Sonsonate", + "portuguese": "Sonsonate", + "russian": "Сонсонате", + "chinese_traditional": "Sonsonate", + "unknown1": "Sonsonate", + "unknown2": "Sonsonate", + "unknown3": "Sonsonate", + "unknown4": "Sonsonate" + }, + "coordinates": { + "latitude": 13.716430508, + "longitude": -89.719603135 + } + }, + { + "id": 437190656, + "name": "Usulután", + "translations": { + "japanese": "ウスルタン県", + "english": "Usulután", + "french": "Usulután", + "german": "Usulután", + "italian": "Usulután", + "spanish": "Usulután", + "chinese_simple": "乌苏卢坦省", + "korean": "우술루탄 주", + "dutch": "Usulután", + "portuguese": "Usulután", + "russian": "Усулутан", + "chinese_traditional": "Usulután", + "unknown1": "Usulután", + "unknown2": "Usulután", + "unknown3": "Usulután", + "unknown4": "Usulután" + }, + "coordinates": { + "latitude": 13.34838852, + "longitude": -88.445185607 + } + } + ] + }, + { + "id": 27, + "iso_code": "GF", + "name": "French Guiana", + "translations": { + "japanese": "フランス領ギアナ", + "english": "French Guiana", + "french": "Guyane", + "german": "Französisch-Guyana", + "italian": "Guyana Francese", + "spanish": "Guayana Francesa", + "chinese_simple": "法属圭亚那", + "korean": "프랑스령 기아나", + "dutch": "Frans-Guyana", + "portuguese": "Guiana Francesa", + "russian": "Французская Гвиана", + "chinese_traditional": "French Guiana", + "unknown1": "French Guiana", + "unknown2": "French Guiana", + "unknown3": "French Guiana", + "unknown4": "French Guiana" + }, + "regions": [ + { + "id": 452984832, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 4.932861272, + "longitude": -52.327533681999995 + } + }, + { + "id": 453050368, + "name": "French Guiana", + "translations": { + "japanese": "フランス領ギアナ", + "english": "French Guiana", + "french": "Guyane", + "german": "Französisch-Guyana", + "italian": "Guyana Francese", + "spanish": "Guayana Francesa", + "chinese_simple": "法属圭亚那", + "korean": "프랑스령 기아나", + "dutch": "Frans-Guyana", + "portuguese": "Guiana Francesa", + "russian": "Французская Гвиана", + "chinese_traditional": "French Guiana", + "unknown1": "French Guiana", + "unknown2": "French Guiana", + "unknown3": "French Guiana", + "unknown4": "French Guiana" + }, + "coordinates": { + "latitude": 4.932861272, + "longitude": -52.327533681999995 + } + } + ] + }, + { + "id": 28, + "iso_code": "GD", + "name": "Grenada", + "translations": { + "japanese": "グレナダ", + "english": "Grenada", + "french": "Grenade", + "german": "Grenada", + "italian": "Grenada", + "spanish": "Granada", + "chinese_simple": "格林纳达", + "korean": "그레나다", + "dutch": "Grenada", + "portuguese": "Granada", + "russian": "Гренада", + "chinese_traditional": "Grenada", + "unknown1": "Grenada", + "unknown2": "Grenada", + "unknown3": "Grenada", + "unknown4": "Grenada" + }, + "regions": [ + { + "id": 469762048, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 12.046508652, + "longitude": -61.748335667000006 + } + }, + { + "id": 469827584, + "name": "Grenada", + "translations": { + "japanese": "グレナダ", + "english": "Grenada", + "french": "Grenade", + "german": "Grenada", + "italian": "Grenada", + "spanish": "Granada", + "chinese_simple": "格林纳达", + "korean": "그레나다", + "dutch": "Grenada", + "portuguese": "Granada", + "russian": "Гренада", + "chinese_traditional": "Grenada", + "unknown1": "Grenada", + "unknown2": "Grenada", + "unknown3": "Grenada", + "unknown4": "Grenada" + }, + "coordinates": { + "latitude": 12.046508652, + "longitude": -61.748335667000006 + } + } + ] + }, + { + "id": 29, + "iso_code": "GP", + "name": "Guadeloupe", + "translations": { + "japanese": "グアドループ", + "english": "Guadeloupe", + "french": "Guadeloupe", + "german": "Guadeloupe", + "italian": "Guadalupa", + "spanish": "Guadalupe", + "chinese_simple": "瓜德罗普", + "korean": "과들루프", + "dutch": "Guadeloupe", + "portuguese": "Guadalupe", + "russian": "Гваделупа", + "chinese_traditional": "Guadeloupe", + "unknown1": "Guadeloupe", + "unknown2": "Guadeloupe", + "unknown3": "Guadeloupe", + "unknown4": "Guadeloupe" + }, + "regions": [ + { + "id": 486539264, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 15.996093568000001, + "longitude": -61.715376593 + } + }, + { + "id": 486604800, + "name": "Guadeloupe", + "translations": { + "japanese": "グアドループ", + "english": "Guadeloupe", + "french": "Guadeloupe", + "german": "Guadeloupe", + "italian": "Guadalupa", + "spanish": "Guadalupe", + "chinese_simple": "瓜德罗普", + "korean": "과들루프", + "dutch": "Guadeloupe", + "portuguese": "Guadalupe", + "russian": "Гваделупа", + "chinese_traditional": "Guadeloupe", + "unknown1": "Guadeloupe", + "unknown2": "Guadeloupe", + "unknown3": "Guadeloupe", + "unknown4": "Guadeloupe" + }, + "coordinates": { + "latitude": 15.996093568000001, + "longitude": -61.715376593 + } + } + ] + }, + { + "id": 30, + "iso_code": "GT", + "name": "Guatemala", + "translations": { + "japanese": "グアテマラ", + "english": "Guatemala", + "french": "Guatemala", + "german": "Guatemala", + "italian": "Guatemala", + "spanish": "Guatemala", + "chinese_simple": "危地马拉", + "korean": "과테말라", + "dutch": "Guatemala", + "portuguese": "Guatemala", + "russian": "Гватемала", + "chinese_traditional": "Guatemala", + "unknown1": "Guatemala", + "unknown2": "Guatemala", + "unknown3": "Guatemala", + "unknown4": "Guatemala" + }, + "regions": [ + { + "id": 503316480, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 14.617309404, + "longitude": -90.521607269 + } + }, + { + "id": 503447552, + "name": "Guatemala", + "translations": { + "japanese": "グアテマラ県", + "english": "Guatemala", + "french": "Guatemala", + "german": "Guatemala", + "italian": "Guatemala", + "spanish": "Guatemala", + "chinese_simple": "危地马拉省", + "korean": "과테말라 주", + "dutch": "Guatemala", + "portuguese": "Guatemala", + "russian": "Гватемала", + "chinese_traditional": "Guatemala", + "unknown1": "Guatemala", + "unknown2": "Guatemala", + "unknown3": "Guatemala", + "unknown4": "Guatemala" + }, + "coordinates": { + "latitude": 14.617309404, + "longitude": -90.521607269 + } + }, + { + "id": 503513088, + "name": "Alta Verapaz", + "translations": { + "japanese": "アルタ・べラパス県", + "english": "Alta Verapaz", + "french": "Alta Verapaz", + "german": "Alta Verapaz", + "italian": "Alta Verapaz", + "spanish": "Alta Verapaz", + "chinese_simple": "上韦拉帕斯省", + "korean": "알타베라파스 주", + "dutch": "Alta Verapaz", + "portuguese": "Alta Verapaz", + "russian": "Альта-Верапас", + "chinese_traditional": "Alta Verapaz", + "unknown1": "Alta Verapaz", + "unknown2": "Alta Verapaz", + "unknown3": "Alta Verapaz", + "unknown4": "Alta Verapaz" + }, + "coordinates": { + "latitude": 15.479736152000001, + "longitude": -90.362305078 + } + }, + { + "id": 503578624, + "name": "Baja Verapaz", + "translations": { + "japanese": "バハ・べラパス県", + "english": "Baja Verapaz", + "french": "Baja Verapaz", + "german": "Baja Verapaz", + "italian": "Baja Verapaz", + "spanish": "Baja Verapaz", + "chinese_simple": "下韦拉帕斯省", + "korean": "바하베라파스 주", + "dutch": "Baja Verapaz", + "portuguese": "Baja Verapaz", + "russian": "Баха-Верапас", + "chinese_traditional": "Baja Verapaz", + "unknown1": "Baja Verapaz", + "unknown2": "Baja Verapaz", + "unknown3": "Baja Verapaz", + "unknown4": "Baja Verapaz" + }, + "coordinates": { + "latitude": 15.095214672000001, + "longitude": -90.263427856 + } + }, + { + "id": 503644160, + "name": "Chimaltenango", + "translations": { + "japanese": "チマルテナンゴ県", + "english": "Chimaltenango", + "french": "Chimaltenango", + "german": "Chimaltenango", + "italian": "Chimaltenango", + "spanish": "Chimaltenango", + "chinese_simple": "奇马尔特南戈省", + "korean": "치말테낭고 주", + "dutch": "Chimaltenango", + "portuguese": "Chimaltenango", + "russian": "Чимальтенанго", + "chinese_traditional": "Chimaltenango", + "unknown1": "Chimaltenango", + "unknown2": "Chimaltenango", + "unknown3": "Chimaltenango", + "unknown4": "Chimaltenango" + }, + "coordinates": { + "latitude": 14.66674788, + "longitude": -90.812745756 + } + }, + { + "id": 503709696, + "name": "Chiquimula", + "translations": { + "japanese": "チキムラ県", + "english": "Chiquimula", + "french": "Chiquimula", + "german": "Chiquimula", + "italian": "Chiquimula", + "spanish": "Chiquimula", + "chinese_simple": "奇基穆拉省", + "korean": "치키물라 주", + "dutch": "Chiquimula", + "portuguese": "Chiquimula", + "russian": "Чикимула", + "chinese_traditional": "Chiquimula", + "unknown1": "Chiquimula", + "unknown2": "Chiquimula", + "unknown3": "Chiquimula", + "unknown4": "Chiquimula" + }, + "coordinates": { + "latitude": 14.798583816, + "longitude": -89.549314586 + } + }, + { + "id": 503775232, + "name": "El Progreso", + "translations": { + "japanese": "エル・プログレソ県", + "english": "El Progreso", + "french": "El Progreso", + "german": "El Progreso", + "italian": "El Progreso", + "spanish": "El Progreso", + "chinese_simple": "埃尔普罗格雷索省", + "korean": "엘프로그레소 주", + "dutch": "El Progreso", + "portuguese": "El Progreso", + "russian": "Эль-Прогресо", + "chinese_traditional": "El Progreso", + "unknown1": "El Progreso", + "unknown2": "El Progreso", + "unknown3": "El Progreso", + "unknown4": "El Progreso" + }, + "coordinates": { + "latitude": 14.853515456, + "longitude": -90.060180233 + } + }, + { + "id": 503840768, + "name": "Escuintla", + "translations": { + "japanese": "エスクィントラ県", + "english": "Escuintla", + "french": "Escuintla", + "german": "Escuintla", + "italian": "Escuintla", + "spanish": "Escuintla", + "chinese_simple": "埃斯昆特拉省", + "korean": "에스쿠인틀라 주", + "dutch": "Escuintla", + "portuguese": "Escuintla", + "russian": "Эскуинтла", + "chinese_traditional": "Escuintla", + "unknown1": "Escuintla", + "unknown2": "Escuintla", + "unknown3": "Escuintla", + "unknown4": "Escuintla" + }, + "coordinates": { + "latitude": 14.304199056, + "longitude": -90.779786682 + } + }, + { + "id": 503906304, + "name": "Huehuetenango", + "translations": { + "japanese": "ウェウェテナンゴ県", + "english": "Huehuetenango", + "french": "Huehuetenango", + "german": "Huehuetenango", + "italian": "Huehuetenango", + "spanish": "Huehuetenango", + "chinese_simple": "韦韦特南戈省", + "korean": "우에우에테낭고 주", + "dutch": "Huehuetenango", + "portuguese": "Huehuetenango", + "russian": "Уэуэтенанго", + "chinese_traditional": "Huehuetenango", + "unknown1": "Huehuetenango", + "unknown2": "Huehuetenango", + "unknown3": "Huehuetenango", + "unknown4": "Huehuetenango" + }, + "coordinates": { + "latitude": 15.314941232, + "longitude": -91.466434057 + } + }, + { + "id": 503971840, + "name": "Izabal", + "translations": { + "japanese": "イザバル県", + "english": "Izabal", + "french": "Izabal", + "german": "Izabal", + "italian": "Izabal", + "spanish": "Izabal", + "chinese_simple": "伊萨瓦尔省", + "korean": "이사발 주", + "dutch": "Izabal", + "portuguese": "Izabal", + "russian": "Исабаль", + "chinese_traditional": "Izabal", + "unknown1": "Izabal", + "unknown2": "Izabal", + "unknown3": "Izabal", + "unknown4": "Izabal" + }, + "coordinates": { + "latitude": 15.715942204000001, + "longitude": -88.598994619 + } + }, + { + "id": 504037376, + "name": "Jalapa", + "translations": { + "japanese": "ハラパ県", + "english": "Jalapa", + "french": "Jalapa", + "german": "Jalapa", + "italian": "Jalapa", + "spanish": "Jalapa", + "chinese_simple": "哈拉帕省", + "korean": "할라파 주", + "dutch": "Jalapa", + "portuguese": "Jalapa", + "russian": "Халапа", + "chinese_traditional": "Jalapa", + "unknown1": "Jalapa", + "unknown2": "Jalapa", + "unknown3": "Jalapa", + "unknown4": "Jalapa" + }, + "coordinates": { + "latitude": 14.628295732, + "longitude": -89.97778254800001 + } + }, + { + "id": 504102912, + "name": "Jutiapa", + "translations": { + "japanese": "フティアパ県", + "english": "Jutiapa", + "french": "Jutiapa", + "german": "Jutiapa", + "italian": "Jutiapa", + "spanish": "Jutiapa", + "chinese_simple": "胡蒂亚帕省", + "korean": "후티아파 주", + "dutch": "Jutiapa", + "portuguese": "Jutiapa", + "russian": "Хутьяпа", + "chinese_traditional": "Jutiapa", + "unknown1": "Jutiapa", + "unknown2": "Jutiapa", + "unknown3": "Jutiapa", + "unknown4": "Jutiapa" + }, + "coordinates": { + "latitude": 14.2822264, + "longitude": -89.895384863 + } + }, + { + "id": 504168448, + "name": "Petén", + "translations": { + "japanese": "エル・ペテン県", + "english": "Petén", + "french": "El Petén", + "german": "El Petén", + "italian": "Petén", + "spanish": "Petén", + "chinese_simple": "佩滕省", + "korean": "페텐 주", + "dutch": "Petén", + "portuguese": "Petén", + "russian": "Петен", + "chinese_traditional": "Petén", + "unknown1": "Petén", + "unknown2": "Petén", + "unknown3": "Petén", + "unknown4": "Petén" + }, + "coordinates": { + "latitude": 16.929931448, + "longitude": -89.878905326 + } + }, + { + "id": 504233984, + "name": "Quetzaltenango", + "translations": { + "japanese": "ケツァルテナンゴ県", + "english": "Quetzaltenango", + "french": "Quetzaltenango", + "german": "Quetzaltenango", + "italian": "Quetzaltenango", + "spanish": "Quetzaltenango", + "chinese_simple": "克萨尔特南戈省", + "korean": "케트살테낭고 주", + "dutch": "Quetzaltenango", + "portuguese": "Quetzaltenango", + "russian": "Кецальтенанго", + "chinese_traditional": "Quetzaltenango", + "unknown1": "Quetzaltenango", + "unknown2": "Quetzaltenango", + "unknown3": "Quetzaltenango", + "unknown4": "Quetzaltenango" + }, + "coordinates": { + "latitude": 14.8315428, + "longitude": -91.515872668 + } + }, + { + "id": 504299520, + "name": "Quiché", + "translations": { + "japanese": "エル・キチェ県", + "english": "Quiché", + "french": "El Quiché", + "german": "El Quiché", + "italian": "Quiché", + "spanish": "Quiché", + "chinese_simple": "基切省", + "korean": "키체 주", + "dutch": "Quiché", + "portuguese": "Quiché", + "russian": "Киче", + "chinese_traditional": "Quiché", + "unknown1": "Quiché", + "unknown2": "Quiché", + "unknown3": "Quiché", + "unknown4": "Quiché" + }, + "coordinates": { + "latitude": 15.029296704, + "longitude": -91.147829675 + } + }, + { + "id": 504365056, + "name": "Retalhuleu", + "translations": { + "japanese": "レタルーレウ県", + "english": "Retalhuleu", + "french": "Retalhuleu", + "german": "Retalhuleu", + "italian": "Retalhuleu", + "spanish": "Retalhuleu", + "chinese_simple": "雷塔卢莱乌省", + "korean": "레탈룰레우 주", + "dutch": "Retalhuleu", + "portuguese": "Retalhuleu", + "russian": "Реталулеу", + "chinese_traditional": "Retalhuleu", + "unknown1": "Retalhuleu", + "unknown2": "Retalhuleu", + "unknown3": "Retalhuleu", + "unknown4": "Retalhuleu" + }, + "coordinates": { + "latitude": 14.52941878, + "longitude": -91.68066803800001 + } + }, + { + "id": 504430592, + "name": "Sacatepéquez", + "translations": { + "japanese": "サカテペケス県", + "english": "Sacatepéquez", + "french": "Sacatepéquez", + "german": "Sacatepéquez", + "italian": "Sacatepéquez", + "spanish": "Sacatepéquez", + "chinese_simple": "萨卡特佩克斯省", + "korean": "사카테페케스 주", + "dutch": "Sacatepéquez", + "portuguese": "Sacatepéquez", + "russian": "Сакатепекес", + "chinese_traditional": "Sacatepéquez", + "unknown1": "Sacatepéquez", + "unknown2": "Sacatepéquez", + "unknown3": "Sacatepéquez", + "unknown4": "Sacatepéquez" + }, + "coordinates": { + "latitude": 14.5568846, + "longitude": -90.730348071 + } + }, + { + "id": 504496128, + "name": "San Marcos", + "translations": { + "japanese": "サン・マルコス県", + "english": "San Marcos", + "french": "San Marcos", + "german": "San Marcos", + "italian": "San Marcos", + "spanish": "San Marcos", + "chinese_simple": "圣马科斯省", + "korean": "산마르코스 주", + "dutch": "San Marcos", + "portuguese": "San Marcos", + "russian": "Сан-Маркос", + "chinese_traditional": "San Marcos", + "unknown1": "San Marcos", + "unknown2": "San Marcos", + "unknown3": "San Marcos", + "unknown4": "San Marcos" + }, + "coordinates": { + "latitude": 14.963378736, + "longitude": -91.796024797 + } + }, + { + "id": 504561664, + "name": "Santa Rosa", + "translations": { + "japanese": "サンタ・ローサ県", + "english": "Santa Rosa", + "french": "Santa Rosa", + "german": "Santa Rosa", + "italian": "Santa Rosa", + "spanish": "Santa Rosa", + "chinese_simple": "圣罗莎省", + "korean": "산타로사 주", + "dutch": "Santa Rosa", + "portuguese": "Santa Rosa", + "russian": "Санта-Роса", + "chinese_traditional": "Santa Rosa", + "unknown1": "Santa Rosa", + "unknown2": "Santa Rosa", + "unknown3": "Santa Rosa", + "unknown4": "Santa Rosa" + }, + "coordinates": { + "latitude": 14.271240072, + "longitude": -90.29638693 + } + }, + { + "id": 504627200, + "name": "Sololá", + "translations": { + "japanese": "ソロラ県", + "english": "Sololá", + "french": "Sololá", + "german": "Sololá", + "italian": "Sololá", + "spanish": "Sololá", + "chinese_simple": "索洛拉省", + "korean": "솔롤라 주", + "dutch": "Sololá", + "portuguese": "Sololá", + "russian": "Солола", + "chinese_traditional": "Sololá", + "unknown1": "Sololá", + "unknown2": "Sololá", + "unknown3": "Sololá", + "unknown4": "Sololá" + }, + "coordinates": { + "latitude": 14.765624832, + "longitude": -91.180788749 + } + }, + { + "id": 504692736, + "name": "Suchitepéquez", + "translations": { + "japanese": "スチテペケス県", + "english": "Suchitepéquez", + "french": "Suchitepéquez", + "german": "Suchitepéquez", + "italian": "Suchitepéquez", + "spanish": "Suchitepéquez", + "chinese_simple": "苏奇特佩克斯省", + "korean": "수치테페케스 주", + "dutch": "Suchitepéquez", + "portuguese": "Suchitepéquez", + "russian": "Сучитепекес", + "chinese_traditional": "Suchitepéquez", + "unknown1": "Suchitepéquez", + "unknown2": "Suchitepéquez", + "unknown3": "Suchitepéquez", + "unknown4": "Suchitepéquez" + }, + "coordinates": { + "latitude": 14.52941878, + "longitude": -91.499393131 + } + }, + { + "id": 504758272, + "name": "Totonicapán", + "translations": { + "japanese": "トトニカパン県", + "english": "Totonicapán", + "french": "Totonicapán", + "german": "Totonicapán", + "italian": "Totonicapán", + "spanish": "Totonicapán", + "chinese_simple": "托托尼卡潘省", + "korean": "토토니카판 주", + "dutch": "Totonicapán", + "portuguese": "Totonicapán", + "russian": "Тотоникапан", + "chinese_traditional": "Totonicapán", + "unknown1": "Totonicapán", + "unknown2": "Totonicapán", + "unknown3": "Totonicapán", + "unknown4": "Totonicapán" + }, + "coordinates": { + "latitude": 14.91394026, + "longitude": -91.362063656 + } + }, + { + "id": 504823808, + "name": "Zacapa", + "translations": { + "japanese": "サカパ県", + "english": "Zacapa", + "french": "Zacapa", + "german": "Zacapa", + "italian": "Zacapa", + "spanish": "Zacapa", + "chinese_simple": "萨卡帕省", + "korean": "사카파 주", + "dutch": "Zacapa", + "portuguese": "Zacapa", + "russian": "Сакапа", + "chinese_traditional": "Zacapa", + "unknown1": "Zacapa", + "unknown2": "Zacapa", + "unknown3": "Zacapa", + "unknown4": "Zacapa" + }, + "coordinates": { + "latitude": 14.963378736, + "longitude": -89.532835049 + } + } + ] + }, + { + "id": 31, + "iso_code": "GY", + "name": "Guyana", + "translations": { + "japanese": "ガイアナ", + "english": "Guyana", + "french": "République coopérative de Guyana", + "german": "Guyana", + "italian": "Guyana", + "spanish": "Guyana", + "chinese_simple": "圭亚那", + "korean": "가이아나", + "dutch": "Guyana", + "portuguese": "Guiana", + "russian": "Гайана", + "chinese_traditional": "Guyana", + "unknown1": "Guyana", + "unknown2": "Guyana", + "unknown3": "Guyana", + "unknown4": "Guyana" + }, + "regions": [ + { + "id": 520093696, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 6.795043868, + "longitude": -58.161289780000004 + } + }, + { + "id": 520224768, + "name": "Demerara-Mahaica", + "translations": { + "japanese": "デメララ・マハイカ州", + "english": "Demerara-Mahaica", + "french": "Demerara-Mahaica", + "german": "Demerara-Mahaica", + "italian": "Demerara-Mahaica", + "spanish": "Demerara-Mahaica", + "chinese_simple": "德梅拉拉-马海卡区", + "korean": "데메라라-마하이카 주", + "dutch": "Demerara-Mahaica", + "portuguese": "Demerara-Mahaica", + "russian": "Демерара-Махаиса", + "chinese_traditional": "Demerara-Mahaica", + "unknown1": "Demerara-Mahaica", + "unknown2": "Demerara-Mahaica", + "unknown3": "Demerara-Mahaica", + "unknown4": "Demerara-Mahaica" + }, + "coordinates": { + "latitude": 6.795043868, + "longitude": -58.161289780000004 + } + }, + { + "id": 520290304, + "name": "Barima-Waini", + "translations": { + "japanese": "バリマ・ワイニ州", + "english": "Barima-Waini", + "french": "Barima-Waini", + "german": "Barima-Waini", + "italian": "Barima-Waini", + "spanish": "Barima-Waini", + "chinese_simple": "巴里马-瓦伊尼区", + "korean": "바리마-와이니 주", + "dutch": "Barima-Waini", + "portuguese": "Barima-Waini", + "russian": "Барима-Ваини", + "chinese_traditional": "Barima-Waini", + "unknown1": "Barima-Waini", + "unknown2": "Barima-Waini", + "unknown3": "Barima-Waini", + "unknown4": "Barima-Waini" + }, + "coordinates": { + "latitude": 8.195800688, + "longitude": -59.781777585 + } + }, + { + "id": 520355840, + "name": "Cuyuni-Mazaruni", + "translations": { + "japanese": "クユニ・マザルニ州", + "english": "Cuyuni-Mazaruni", + "french": "Cuyuni-Mazaruni", + "german": "Cuyuni-Mazaruni", + "italian": "Cuyuni-Mazaruni", + "spanish": "Cuyuni-Mazaruni", + "chinese_simple": "库尤尼-马扎鲁尼区", + "korean": "쿠유니-마자루니 주", + "dutch": "Cuyuni-Mazaruni", + "portuguese": "Cuyuni-Mazaruni", + "russian": "Кайуни-Мазаруни", + "chinese_traditional": "Cuyuni-Mazaruni", + "unknown1": "Cuyuni-Mazaruni", + "unknown2": "Cuyuni-Mazaruni", + "unknown3": "Cuyuni-Mazaruni", + "unknown4": "Cuyuni-Mazaruni" + }, + "coordinates": { + "latitude": 6.39953606, + "longitude": -58.611730458 + } + }, + { + "id": 520421376, + "name": "East Berbice-Corentyne", + "translations": { + "japanese": "東ベルビセ・コレンティネ州", + "english": "East Berbice-Corentyne", + "french": "Berbice Oriental-Courantyne ", + "german": "East Berbice-Corentyne", + "italian": "Berbice Orientale-Corentyne", + "spanish": "Berbice Oriental-Corentyne", + "chinese_simple": "东伯比斯-科兰太因区", + "korean": "동부 버비스-코런타인 주", + "dutch": "East Berbice-Corentyne", + "portuguese": "Berbice Oriental-Corentyne", + "russian": "Восточный Бербайс-Корентин", + "chinese_traditional": "East Berbice-Corentyne", + "unknown1": "East Berbice-Corentyne", + "unknown2": "East Berbice-Corentyne", + "unknown3": "East Berbice-Corentyne", + "unknown4": "East Berbice-Corentyne" + }, + "coordinates": { + "latitude": 6.245727468, + "longitude": -57.513094658 + } + }, + { + "id": 520486912, + "name": "Essequibo Islands-West Demerara", + "translations": { + "japanese": "エセキボ諸島・西デメララ州", + "english": "Essequibo Islands-West Demerara", + "french": "Îles Essequibo-Demerara Occidental", + "german": "Essequibo Islands-West Demerara", + "italian": "Isole Essequibo-Demerara Occidentale", + "spanish": "Islas Essequibo-Demerara Occidental", + "chinese_simple": "埃塞奎博群岛-西德梅拉拉区", + "korean": "에세퀴보 섬-서부 데메라라 주", + "dutch": "Essequibo Islands-West Demerara", + "portuguese": "Ilhas Essequibo-Demerara Ocidental", + "russian": "Эссекуибо-Айлендс-Западный Демерара", + "chinese_traditional": "Essequibo Islands-West Demerara", + "unknown1": "Essequibo Islands-West Demerara", + "unknown2": "Essequibo Islands-West Demerara", + "unknown3": "Essequibo Islands-West Demerara", + "unknown4": "Essequibo Islands-West Demerara" + }, + "coordinates": { + "latitude": 6.866455, + "longitude": -58.413976014 + } + }, + { + "id": 520552448, + "name": "Mahaica-Berbice", + "translations": { + "japanese": "マハイカ・ベルビセ州", + "english": "Mahaica-Berbice", + "french": "Mahaica-Berbice", + "german": "Mahaica-Berbice", + "italian": "Mahaica-Berbice", + "spanish": "Mahaica-Berbice", + "chinese_simple": "马海卡-伯比斯区", + "korean": "마하이카-버비스 주", + "dutch": "Mahaica-Berbice", + "portuguese": "Mahaica-Berbice", + "russian": "Махаиса-Бербайс", + "chinese_traditional": "Mahaica-Berbice", + "unknown1": "Mahaica-Berbice", + "unknown2": "Mahaica-Berbice", + "unknown3": "Mahaica-Berbice", + "unknown4": "Mahaica-Berbice" + }, + "coordinates": { + "latitude": 6.39953606, + "longitude": -57.595492343000004 + } + }, + { + "id": 520617984, + "name": "Pomeroon-Supenaam", + "translations": { + "japanese": "ポメローン・スペナーム州", + "english": "Pomeroon-Supenaam", + "french": "Pomeroon-Supenaam", + "german": "Pomeroon-Supenaam", + "italian": "Pomeroon-Supenaam", + "spanish": "Pomeroon-Supenaam", + "chinese_simple": "波默伦-苏佩纳姆区", + "korean": "포메룬-수페남 주", + "dutch": "Pomeroon-Supenaam", + "portuguese": "Pomeroon-Supenaam", + "russian": "Померун-Супенаам", + "chinese_traditional": "Pomeroon-Supenaam", + "unknown1": "Pomeroon-Supenaam", + "unknown2": "Pomeroon-Supenaam", + "unknown3": "Pomeroon-Supenaam", + "unknown4": "Pomeroon-Supenaam" + }, + "coordinates": { + "latitude": 7.261962808, + "longitude": -58.496373699 + } + }, + { + "id": 520683520, + "name": "Potaro-Siparuni", + "translations": { + "japanese": "ポタロ・シパルニ州", + "english": "Potaro-Siparuni", + "french": "Potaro-Siparuni", + "german": "Potaro-Siparuni", + "italian": "Potaro-Siparuni", + "spanish": "Potaro-Siparuni", + "chinese_simple": "波塔罗-锡帕鲁尼区", + "korean": "포타로-시파루니 주", + "dutch": "Potaro-Siparuni", + "portuguese": "Potaro-Siparuni", + "russian": "Потаро-Сипаруни", + "chinese_traditional": "Potaro-Siparuni", + "unknown1": "Potaro-Siparuni", + "unknown2": "Potaro-Siparuni", + "unknown3": "Potaro-Siparuni", + "unknown4": "Potaro-Siparuni" + }, + "coordinates": { + "latitude": 5.262451112, + "longitude": -59.14456882100001 + } + }, + { + "id": 520749056, + "name": "Upper Demerara-Berbice", + "translations": { + "japanese": "アッパー・デメララ・ベルビセ州", + "english": "Upper Demerara-Berbice", + "french": "Haut-Demerara et Berbice", + "german": "Upper Demerara-Berbice", + "italian": "Alto Demerara-Berbice", + "spanish": "Alto Demerara-Berbice", + "chinese_simple": "上德梅拉拉-伯比斯区", + "korean": "북부 데메라라-버비스 주", + "dutch": "Upper Demerara-Berbice", + "portuguese": "Alto Demerara-Berbice", + "russian": "Верхний Демерара-Бербайс", + "chinese_traditional": "Upper Demerara-Berbice", + "unknown1": "Upper Demerara-Berbice", + "unknown2": "Upper Demerara-Berbice", + "unknown3": "Upper Demerara-Berbice", + "unknown4": "Upper Demerara-Berbice" + }, + "coordinates": { + "latitude": 5.998535088, + "longitude": -58.298619255000006 + } + }, + { + "id": 520814592, + "name": "Upper Takutu-Upper Essequibo", + "translations": { + "japanese": "アッパー・タクトゥ・アッパー・エセキボ州", + "english": "Upper Takutu-Upper Essequibo", + "french": "Haut-Takutu et Haut-Essequibo", + "german": "Upper Takutu-Upper Essequibo", + "italian": "Alto Takutu-Alto Essequibo", + "spanish": "Alto Takutu-Alto Essequibo", + "chinese_simple": "上塔库图-上埃塞奎博区", + "korean": "북부 타쿠투-북부 에세퀴보 주", + "dutch": "Upper Takutu-Upper Essequibo", + "portuguese": "Alto Takutu-Alto Essequibo", + "russian": "Верхний Такуту-Верхний Эссекуибо", + "chinese_traditional": "Upper Takutu-Upper Essequibo", + "unknown1": "Upper Takutu-Upper Essequibo", + "unknown2": "Upper Takutu-Upper Essequibo", + "unknown3": "Upper Takutu-Upper Essequibo", + "unknown4": "Upper Takutu-Upper Essequibo" + }, + "coordinates": { + "latitude": 3.37829586, + "longitude": -59.798257121999995 + } + } + ] + }, + { + "id": 32, + "iso_code": "HT", + "name": "Haiti", + "translations": { + "japanese": "ハイチ", + "english": "Haiti", + "french": "Haïti", + "german": "Haiti", + "italian": "Haiti", + "spanish": "Haití", + "chinese_simple": "海地", + "korean": "아이티", + "dutch": "Haïti", + "portuguese": "Haiti", + "russian": "Гаити", + "chinese_traditional": "Haiti", + "unknown1": "Haiti", + "unknown2": "Haiti", + "unknown3": "Haiti", + "unknown4": "Haiti" + }, + "regions": [ + { + "id": 536870912, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 18.533935336, + "longitude": -72.3336916 + } + }, + { + "id": 537001984, + "name": "Ouest", + "translations": { + "japanese": "西県", + "english": "Ouest", + "french": "Ouest", + "german": "Ouest", + "italian": "Ovest", + "spanish": "Oeste", + "chinese_simple": "西部省", + "korean": "서부", + "dutch": "Ouest", + "portuguese": "Oeste", + "russian": "Западный департамент", + "chinese_traditional": "Ouest", + "unknown1": "Ouest", + "unknown2": "Ouest", + "unknown3": "Ouest", + "unknown4": "Ouest" + }, + "coordinates": { + "latitude": 18.533935336, + "longitude": -72.3336916 + } + }, + { + "id": 537067520, + "name": "Nord-Ouest", + "translations": { + "japanese": "北西県", + "english": "Nord-Ouest", + "french": "Nord-Ouest", + "german": "Nord-Ouest", + "italian": "Nord-Ovest", + "spanish": "Noroeste", + "chinese_simple": "西北省", + "korean": "북서부", + "dutch": "Nord-Ouest", + "portuguese": "Noroeste", + "russian": "Северо-Западный департамент", + "chinese_traditional": "Nord-Ouest", + "unknown1": "Nord-Ouest", + "unknown2": "Nord-Ouest", + "unknown3": "Nord-Ouest", + "unknown4": "Nord-Ouest" + }, + "coordinates": { + "latitude": 19.945678484000002, + "longitude": -72.82807771 + } + }, + { + "id": 537133056, + "name": "Artibonite", + "translations": { + "japanese": "アルティボニット県", + "english": "Artibonite", + "french": "Artibonite", + "german": "Artibonite", + "italian": "Artibonite", + "spanish": "Artibonito", + "chinese_simple": "阿蒂博尼特省", + "korean": "아르티보니트", + "dutch": "Artibonite", + "portuguese": "Artibonite", + "russian": "Артибонит", + "chinese_traditional": "Artibonite", + "unknown1": "Artibonite", + "unknown2": "Artibonite", + "unknown3": "Artibonite", + "unknown4": "Artibonite" + }, + "coordinates": { + "latitude": 19.44580056, + "longitude": -72.679761877 + } + }, + { + "id": 537198592, + "name": "Centre", + "translations": { + "japanese": "中央県", + "english": "Centre", + "french": "Centre", + "german": "Centre", + "italian": "Centro", + "spanish": "Centro", + "chinese_simple": "中部省", + "korean": "중앙부", + "dutch": "Centre", + "portuguese": "Centro", + "russian": "Центральный департамент", + "chinese_traditional": "Centre", + "unknown1": "Centre", + "unknown2": "Centre", + "unknown3": "Centre", + "unknown4": "Centre" + }, + "coordinates": { + "latitude": 19.149169704, + "longitude": -72.015087218 + } + }, + { + "id": 537264128, + "name": "Grand'Anse", + "translations": { + "japanese": "湾岸県", + "english": "Grand'Anse", + "french": "Grande-Anse", + "german": "Grand'Anse", + "italian": "Grande Anse", + "spanish": "Grand'Anse", + "chinese_simple": "大湾省", + "korean": "그랑당스", + "dutch": "Grand'Anse", + "portuguese": "Grand'Anse", + "russian": "Гранд-Анс", + "chinese_traditional": "Grand'Anse", + "unknown1": "Grand'Anse", + "unknown2": "Grand'Anse", + "unknown3": "Grand'Anse", + "unknown4": "Grand'Anse" + }, + "coordinates": { + "latitude": 18.64929178, + "longitude": -74.113481596 + } + }, + { + "id": 537329664, + "name": "Nord", + "translations": { + "japanese": "北県", + "english": "Nord", + "french": "Nord", + "german": "Nord", + "italian": "Nord", + "spanish": "Norte", + "chinese_simple": "北部省", + "korean": "북부", + "dutch": "Nord", + "portuguese": "Norte", + "russian": "Северный департамент", + "chinese_traditional": "Nord", + "unknown1": "Nord", + "unknown2": "Nord", + "unknown3": "Nord", + "unknown4": "Nord" + }, + "coordinates": { + "latitude": 19.753417744, + "longitude": -72.201855304 + } + }, + { + "id": 537395200, + "name": "Nord-Est", + "translations": { + "japanese": "北東県", + "english": "Nord-Est", + "french": "Nord-Est", + "german": "Nord-Est", + "italian": "Nord-Est", + "spanish": "Noreste", + "chinese_simple": "东北省", + "korean": "북동부", + "dutch": "Nord-Est", + "portuguese": "Nordeste", + "russian": "Северо-Восточный департамент", + "chinese_traditional": "Nord-Est", + "unknown1": "Nord-Est", + "unknown2": "Nord-Est", + "unknown3": "Nord-Est", + "unknown4": "Nord-Est" + }, + "coordinates": { + "latitude": 19.66552712, + "longitude": -71.83930549 + } + }, + { + "id": 537460736, + "name": "Sud", + "translations": { + "japanese": "南県", + "english": "Sud", + "french": "Sud", + "german": "Sud", + "italian": "Sud", + "spanish": "Sur", + "chinese_simple": "南部省", + "korean": "남부", + "dutch": "Sud", + "portuguese": "Sul", + "russian": "Южный департамент", + "chinese_traditional": "Sud", + "unknown1": "Sud", + "unknown2": "Sud", + "unknown3": "Sud", + "unknown4": "Sud" + }, + "coordinates": { + "latitude": 18.198852332, + "longitude": -73.745438603 + } + }, + { + "id": 537526272, + "name": "Sud-Est", + "translations": { + "japanese": "南東県", + "english": "Sud-Est", + "french": "Sud-Est", + "german": "Sud-Est", + "italian": "Sud-Est", + "spanish": "Sureste", + "chinese_simple": "东南省", + "korean": "남동부", + "dutch": "Sud-Est", + "portuguese": "Sudeste", + "russian": "Юго-Восточный департамент", + "chinese_traditional": "Sud-Est", + "unknown1": "Sud-Est", + "unknown2": "Sud-Est", + "unknown3": "Sud-Est", + "unknown4": "Sud-Est" + }, + "coordinates": { + "latitude": 18.231811316, + "longitude": -72.531446044 + } + }, + { + "id": 537591808, + "name": "Nippes", + "translations": { + "japanese": "ニップ県", + "english": "Nippes", + "french": "Nippes", + "german": "Nippes", + "italian": "Nippes", + "spanish": "Nippes", + "chinese_simple": "尼普斯省", + "korean": "니프", + "dutch": "Nippes", + "portuguese": "Nippes", + "russian": "Нип", + "chinese_traditional": "Nippes", + "unknown1": "Nippes", + "unknown2": "Nippes", + "unknown3": "Nippes", + "unknown4": "Nippes" + }, + "coordinates": { + "latitude": 18.440551548, + "longitude": -73.086257123 + } + } + ] + }, + { + "id": 33, + "iso_code": "HN", + "name": "Honduras", + "translations": { + "japanese": "ホンジュラス", + "english": "Honduras", + "french": "Honduras", + "german": "Honduras", + "italian": "Honduras", + "spanish": "Honduras", + "chinese_simple": "洪都拉斯", + "korean": "온두라스", + "dutch": "Honduras", + "portuguese": "Honduras", + "russian": "Гондурас", + "chinese_traditional": "Honduras", + "unknown1": "Honduras", + "unknown2": "Honduras", + "unknown3": "Honduras", + "unknown4": "Honduras" + }, + "regions": [ + { + "id": 553648128, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 14.095458824, + "longitude": -87.214713511 + } + }, + { + "id": 553779200, + "name": "Fr얆徇᥄\udac7슃\udfd9榩\ud822ﰕ\udcca䮍輝n", + "translations": { + "japanese": "フランシスコ・モラサン", + "english": "Fr얆徇᥄\udac7슃\udfd9榩\ud822ﰕ\udcca䮍輝n", + "french": "Francisco Morazán", + "german": "Francisco Morazán", + "italian": "Francisco Morazán", + "spanish": "Francisco Morazán", + "chinese_simple": "弗朗西斯科-莫拉桑省", + "korean": "프란시스코모라산", + "dutch": "Francisco Morazán", + "portuguese": "Francisco Morazán", + "russian": "Франсиско Морасан", + "chinese_traditional": "Francisco Morazán", + "unknown1": "Francisco Morazán", + "unknown2": "Francisco Morazán", + "unknown3": "Francisco Morazán", + "unknown4": "Francisco Morazán" + }, + "coordinates": { + "latitude": 14.095458824, + "longitude": -87.214713511 + } + }, + { + "id": 553844736, + "name": "Atlántida", + "translations": { + "japanese": "アトランティダ", + "english": "Atlántida", + "french": "Atlántida", + "german": "Atlántida", + "italian": "Atlántida", + "spanish": "Atlántida", + "chinese_simple": "阿特兰蒂达省", + "korean": "아틀란티다", + "dutch": "Atlántida", + "portuguese": "Atlántida", + "russian": "Атлантида", + "chinese_traditional": "Atlántida", + "unknown1": "Atlántida", + "unknown2": "Atlántida", + "unknown3": "Atlántida", + "unknown4": "Atlántida" + }, + "coordinates": { + "latitude": 15.781860172, + "longitude": -86.797231907 + } + }, + { + "id": 553910272, + "name": "Choluteca", + "translations": { + "japanese": "チョルテカ", + "english": "Choluteca", + "french": "Choluteca", + "german": "Choluteca", + "italian": "Choluteca", + "spanish": "Choluteca", + "chinese_simple": "乔卢特卡省", + "korean": "촐루테카", + "dutch": "Choluteca", + "portuguese": "Choluteca", + "russian": "Чолутека", + "chinese_traditional": "Choluteca", + "unknown1": "Choluteca", + "unknown2": "Choluteca", + "unknown3": "Choluteca", + "unknown4": "Choluteca" + }, + "coordinates": { + "latitude": 13.315429536, + "longitude": -87.214713511 + } + }, + { + "id": 553975808, + "name": "Colón", + "translations": { + "japanese": "コロン", + "english": "Colón", + "french": "Colón", + "german": "Colón", + "italian": "Colón", + "spanish": "Colón", + "chinese_simple": "科隆省", + "korean": "콜론", + "dutch": "Colón", + "portuguese": "Colón", + "russian": "Колон", + "chinese_traditional": "Colón", + "unknown1": "Colón", + "unknown2": "Colón", + "unknown3": "Colón", + "unknown4": "Colón" + }, + "coordinates": { + "latitude": 15.913696108, + "longitude": -85.995227773 + } + }, + { + "id": 554041344, + "name": "Comayagua", + "translations": { + "japanese": "コマヤグア", + "english": "Comayagua", + "french": "Comayagua", + "german": "Comayagua", + "italian": "Comayagua", + "spanish": "Comayagua", + "chinese_simple": "科马亚瓜省", + "korean": "코마야과", + "dutch": "Comayagua", + "portuguese": "Comayagua", + "russian": "Камаягуа", + "chinese_traditional": "Comayagua", + "unknown1": "Comayagua", + "unknown2": "Comayagua", + "unknown3": "Comayagua", + "unknown4": "Comayagua" + }, + "coordinates": { + "latitude": 14.44702132, + "longitude": -87.632195115 + } + }, + { + "id": 554106880, + "name": "Copán", + "translations": { + "japanese": "コパン", + "english": "Copán", + "french": "Copán", + "german": "Copán", + "italian": "Copán", + "spanish": "Copán", + "chinese_simple": "科潘省", + "korean": "코판", + "dutch": "Copán", + "portuguese": "Copán", + "russian": "Копан", + "chinese_traditional": "Copán", + "unknown1": "Copán", + "unknown2": "Copán", + "unknown3": "Copán", + "unknown4": "Copán" + }, + "coordinates": { + "latitude": 14.765624832, + "longitude": -88.780269526 + } + }, + { + "id": 554172416, + "name": "Cortés", + "translations": { + "japanese": "コルテス", + "english": "Cortés", + "french": "Cortés", + "german": "Cortés", + "italian": "Cortés", + "spanish": "Cortés", + "chinese_simple": "科尔特斯省", + "korean": "코르테스", + "dutch": "Cortés", + "portuguese": "Cortês", + "russian": "Кортес", + "chinese_traditional": "Cortés", + "unknown1": "Cortés", + "unknown2": "Cortés", + "unknown3": "Cortés", + "unknown4": "Cortés" + }, + "coordinates": { + "latitude": 15.496215644, + "longitude": -88.027704003 + } + }, + { + "id": 554237952, + "name": "El Paraíso", + "translations": { + "japanese": "エル・パライソ", + "english": "El Paraíso", + "french": "El Paraíso", + "german": "El Paraíso", + "italian": "El Paraíso", + "spanish": "El Paraíso", + "chinese_simple": "埃尔帕拉伊索省", + "korean": "엘파라이소", + "dutch": "El Paraíso", + "portuguese": "El Paraíso", + "russian": "Эль-Параисо", + "chinese_traditional": "El Paraíso", + "unknown1": "El Paraíso", + "unknown2": "El Paraíso", + "unknown3": "El Paraíso", + "unknown4": "El Paraíso" + }, + "coordinates": { + "latitude": 13.930663904, + "longitude": -86.846670518 + } + }, + { + "id": 554303488, + "name": "Gracias a Dios", + "translations": { + "japanese": "グラシアス・ア・ディオス", + "english": "Gracias a Dios", + "french": "Gracias a Dios", + "german": "Gracias a Dios", + "italian": "Gracias a Dios", + "spanish": "Gracias a Dios", + "chinese_simple": "格拉西亚斯-阿迪奥斯省", + "korean": "그라시아스아디오스", + "dutch": "Gracias a Dios", + "portuguese": "Gracias a Dios", + "russian": "Грасьяс-а-Дьос", + "chinese_traditional": "Gracias a Dios", + "unknown1": "Gracias a Dios", + "unknown2": "Gracias a Dios", + "unknown3": "Gracias a Dios", + "unknown4": "Gracias a Dios" + }, + "coordinates": { + "latitude": 15.265502756, + "longitude": -83.764997099 + } + }, + { + "id": 554369024, + "name": "Intibucá", + "translations": { + "japanese": "インティブカ", + "english": "Intibucá", + "french": "Intibucá", + "german": "Intibucá", + "italian": "Intibucá", + "spanish": "Intibucá", + "chinese_simple": "因蒂布卡省", + "korean": "인티부카", + "dutch": "Intibucá", + "portuguese": "Intibucá", + "russian": "Интибука", + "chinese_traditional": "Intibucá", + "unknown1": "Intibucá", + "unknown2": "Intibucá", + "unknown3": "Intibucá", + "unknown4": "Intibucá" + }, + "coordinates": { + "latitude": 14.298705892000001, + "longitude": -88.18151301500001 + } + }, + { + "id": 554434560, + "name": "Islas de la Bahía", + "translations": { + "japanese": "イスラス・デ・ラ・バイア", + "english": "Islas de la Bahía", + "french": "Islas de la Bahía", + "german": "Islas de la Bahía", + "italian": "Islas de la Bahía", + "spanish": "Islas de la Bahía", + "chinese_simple": "海湾群岛省", + "korean": "이슬라스데라바이아", + "dutch": "Baai Eilanden", + "portuguese": "Islas de la Bahía", + "russian": "Ислас-де-ла-Баия", + "chinese_traditional": "Islas de la Bahía", + "unknown1": "Islas de la Bahía", + "unknown2": "Islas de la Bahía", + "unknown3": "Islas de la Bahía", + "unknown4": "Islas de la Bahía" + }, + "coordinates": { + "latitude": 16.298217588, + "longitude": -86.544545673 + } + }, + { + "id": 554500096, + "name": "La Paz", + "translations": { + "japanese": "ラ・パス", + "english": "La Paz", + "french": "La Paz", + "german": "La Paz", + "italian": "La Paz", + "spanish": "La Paz", + "chinese_simple": "拉巴斯省", + "korean": "라파스", + "dutch": "La Paz", + "portuguese": "La Paz", + "russian": "Ла-Пас", + "chinese_traditional": "La Paz", + "unknown1": "La Paz", + "unknown2": "La Paz", + "unknown3": "La Paz", + "unknown4": "La Paz" + }, + "coordinates": { + "latitude": 14.315185384, + "longitude": -87.681633726 + } + }, + { + "id": 554565632, + "name": "Lempira", + "translations": { + "japanese": "レンピラ", + "english": "Lempira", + "french": "Lempira", + "german": "Lempira", + "italian": "Lempira", + "spanish": "Lempira", + "chinese_simple": "伦皮拉省", + "korean": "렘피라", + "dutch": "Lempira", + "portuguese": "Lempira", + "russian": "Лемпира", + "chinese_traditional": "Lempira", + "unknown1": "Lempira", + "unknown2": "Lempira", + "unknown3": "Lempira", + "unknown4": "Lempira" + }, + "coordinates": { + "latitude": 14.578857256000001, + "longitude": -88.582515082 + } + }, + { + "id": 554631168, + "name": "Ocotepeque", + "translations": { + "japanese": "オコテペケ", + "english": "Ocotepeque", + "french": "Ocotepeque", + "german": "Ocotepeque", + "italian": "Ocotepeque", + "spanish": "Ocotepeque", + "chinese_simple": "奥科特佩克省", + "korean": "오코테페케", + "dutch": "Ocotepeque", + "portuguese": "Ocotepeque", + "russian": "Окатепеке", + "chinese_traditional": "Ocotepeque", + "unknown1": "Ocotepeque", + "unknown2": "Ocotepeque", + "unknown3": "Ocotepeque", + "unknown4": "Ocotepeque" + }, + "coordinates": { + "latitude": 14.430541828, + "longitude": -89.181271593 + } + }, + { + "id": 554696704, + "name": "Olancho", + "translations": { + "japanese": "オランチョ", + "english": "Olancho", + "french": "Olancho", + "german": "Olancho", + "italian": "Olancho", + "spanish": "Olancho", + "chinese_simple": "奥兰乔省", + "korean": "올란초", + "dutch": "Olancho", + "portuguese": "Olancho", + "russian": "Оланхо", + "chinese_traditional": "Olancho", + "unknown1": "Olancho", + "unknown2": "Olancho", + "unknown3": "Olancho", + "unknown4": "Olancho" + }, + "coordinates": { + "latitude": 14.644775224, + "longitude": -86.198475396 + } + }, + { + "id": 554762240, + "name": "Santa Bárbara", + "translations": { + "japanese": "サンタ・バルバラ", + "english": "Santa Bárbara", + "french": "Santa Bárbara", + "german": "Santa Bárbara", + "italian": "Santa Bárbara", + "spanish": "Santa Bárbara", + "chinese_simple": "圣巴巴拉省", + "korean": "산타바르바라", + "dutch": "Santa Bárbara", + "portuguese": "Santa Bárbara", + "russian": "Санта-Барбара", + "chinese_traditional": "Santa Bárbara", + "unknown1": "Santa Bárbara", + "unknown2": "Santa Bárbara", + "unknown3": "Santa Bárbara", + "unknown4": "Santa Bárbara" + }, + "coordinates": { + "latitude": 14.91394026, + "longitude": -88.230951626 + } + }, + { + "id": 554827776, + "name": "Valle", + "translations": { + "japanese": "バジェ", + "english": "Valle", + "french": "Valle", + "german": "Valle", + "italian": "Valle", + "spanish": "Valle", + "chinese_simple": "山谷省", + "korean": "바예", + "dutch": "Valle", + "portuguese": "Valle", + "russian": "Валле", + "chinese_traditional": "Valle", + "unknown1": "Valle", + "unknown2": "Valle", + "unknown3": "Valle", + "unknown4": "Valle" + }, + "coordinates": { + "latitude": 13.535156096, + "longitude": -87.483879282 + } + }, + { + "id": 554893312, + "name": "Yoro", + "translations": { + "japanese": "ヨロ", + "english": "Yoro", + "french": "Yoro", + "german": "Yoro", + "italian": "Yoro", + "spanish": "Yoro", + "chinese_simple": "约罗省", + "korean": "요로", + "dutch": "Yoro", + "portuguese": "Yoro", + "russian": "Йоро", + "chinese_traditional": "Yoro", + "unknown1": "Yoro", + "unknown2": "Yoro", + "unknown3": "Yoro", + "unknown4": "Yoro" + }, + "coordinates": { + "latitude": 15.128173656, + "longitude": -87.132315826 + } + } + ] + }, + { + "id": 34, + "iso_code": "JM", + "name": "Jamaica", + "translations": { + "japanese": "ジャマイカ", + "english": "Jamaica", + "french": "Jamaïque", + "german": "Jamaika", + "italian": "Giamaica", + "spanish": "Jamaica", + "chinese_simple": "牙买加", + "korean": "자메이카", + "dutch": "Jamaica", + "portuguese": "Jamaica", + "russian": "Ямайка", + "chinese_traditional": "Jamaica", + "unknown1": "Jamaica", + "unknown2": "Jamaica", + "unknown3": "Jamaica", + "unknown4": "Jamaica" + }, + "regions": [ + { + "id": 570425344, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 17.995605264, + "longitude": -76.799646127 + } + }, + { + "id": 570556416, + "name": "Saint Thomas", + "translations": { + "japanese": "セント・トーマス", + "english": "Saint Thomas", + "french": "Saint-Thomas", + "german": "Saint Thomas", + "italian": "Saint Thomas", + "spanish": "Saint Thomas", + "chinese_simple": "圣托马斯区", + "korean": "세인트토머스", + "dutch": "Saint Thomas", + "portuguese": "Saint Thomas", + "russian": "Сент-Томас", + "chinese_traditional": "Saint Thomas", + "unknown1": "Saint Thomas", + "unknown2": "Saint Thomas", + "unknown3": "Saint Thomas", + "unknown4": "Saint Thomas" + }, + "coordinates": { + "latitude": 17.995605264, + "longitude": -76.799646127 + } + }, + { + "id": 570621952, + "name": "Clarendon", + "translations": { + "japanese": "クラレンドン", + "english": "Clarendon", + "french": "Clarendon", + "german": "Clarendon", + "italian": "Clarendon", + "spanish": "Clarendon", + "chinese_simple": "克拉伦登区", + "korean": "클래런던", + "dutch": "Clarendon", + "portuguese": "Clarendon", + "russian": "Клэрендон", + "chinese_traditional": "Clarendon", + "unknown1": "Clarendon", + "unknown2": "Clarendon", + "unknown3": "Clarendon", + "unknown4": "Clarendon" + }, + "coordinates": { + "latitude": 17.96264628, + "longitude": -77.228114089 + } + }, + { + "id": 570687488, + "name": "Hanover", + "translations": { + "japanese": "ハノーバー", + "english": "Hanover", + "french": "Hanover", + "german": "Hanover", + "italian": "Hanover", + "spanish": "Hanover", + "chinese_simple": "汉诺威区", + "korean": "해노버", + "dutch": "Hanover", + "portuguese": "Hanover", + "russian": "Хановер", + "chinese_traditional": "Hanover", + "unknown1": "Hanover", + "unknown2": "Hanover", + "unknown3": "Hanover", + "unknown4": "Hanover" + }, + "coordinates": { + "latitude": 18.446044712, + "longitude": -78.161954519 + } + }, + { + "id": 570753024, + "name": "Manchester", + "translations": { + "japanese": "マンチェスター", + "english": "Manchester", + "french": "Manchester", + "german": "Manchester", + "italian": "Manchester", + "spanish": "Manchester", + "chinese_simple": "曼彻斯特区", + "korean": "맨체스터", + "dutch": "Manchester", + "portuguese": "Manchester", + "russian": "Манчестер", + "chinese_traditional": "Manchester", + "unknown1": "Manchester", + "unknown2": "Manchester", + "unknown3": "Manchester", + "unknown4": "Manchester" + }, + "coordinates": { + "latitude": 18.028564248, + "longitude": -77.49727986 + } + }, + { + "id": 570818560, + "name": "Portland", + "translations": { + "japanese": "ポートランド", + "english": "Portland", + "french": "Portland", + "german": "Portland", + "italian": "Portland", + "spanish": "Portland", + "chinese_simple": "波特兰区", + "korean": "포틀랜드", + "dutch": "Portland", + "portuguese": "Portland", + "russian": "Портлэнд", + "chinese_traditional": "Portland", + "unknown1": "Portland", + "unknown2": "Portland", + "unknown3": "Portland", + "unknown4": "Portland" + }, + "coordinates": { + "latitude": 18.18237284, + "longitude": -76.464562208 + } + }, + { + "id": 570884096, + "name": "Saint Andrew", + "translations": { + "japanese": "セント・アンドリュー", + "english": "Saint Andrew", + "french": "Saint Andrew", + "german": "Saint Andrew", + "italian": "Saint Andrew", + "spanish": "Saint Andrew", + "chinese_simple": "圣安德鲁区", + "korean": "세인트앤드루", + "dutch": "Saint Andrew", + "portuguese": "Saint Andrew", + "russian": "Сент-Эндрю", + "chinese_traditional": "Saint Andrew", + "unknown1": "Saint Andrew", + "unknown2": "Saint Andrew", + "unknown3": "Saint Andrew", + "unknown4": "Saint Andrew" + }, + "coordinates": { + "latitude": 17.995605264, + "longitude": -76.799646127 + } + }, + { + "id": 570949632, + "name": "Saint Ann", + "translations": { + "japanese": "セント・アン", + "english": "Saint Ann", + "french": "Saint Ann", + "german": "Saint Ann", + "italian": "Saint Ann", + "spanish": "Saint Ann", + "chinese_simple": "圣安娜区", + "korean": "세인트앤", + "dutch": "Saint Ann", + "portuguese": "Saint Ann", + "russian": "Сент-Энн", + "chinese_traditional": "Saint Ann", + "unknown1": "Saint Ann", + "unknown2": "Saint Ann", + "unknown3": "Saint Ann", + "unknown4": "Saint Ann" + }, + "coordinates": { + "latitude": 18.42956522, + "longitude": -77.195155015 + } + }, + { + "id": 571015168, + "name": "Saint Catherine", + "translations": { + "japanese": "セント・キャサリン", + "english": "Saint Catherine", + "french": "Saint Catherine", + "german": "Saint Catherine", + "italian": "Saint Catherine", + "spanish": "Saint Catherine", + "chinese_simple": "圣凯瑟琳区", + "korean": "세인트캐서린", + "dutch": "Saint Catherine", + "portuguese": "Saint Catherine", + "russian": "Сент-Кэтрин", + "chinese_traditional": "Saint Catherine", + "unknown1": "Saint Catherine", + "unknown2": "Saint Catherine", + "unknown3": "Saint Catherine", + "unknown4": "Saint Catherine" + }, + "coordinates": { + "latitude": 17.979125772, + "longitude": -76.94796196 + } + }, + { + "id": 571080704, + "name": "Saint Elizabeth", + "translations": { + "japanese": "セント・エリザベス", + "english": "Saint Elizabeth", + "french": "Saint Elizabeth", + "german": "Saint Elizabeth", + "italian": "Saint Elizabeth", + "spanish": "Saint Elizabeth", + "chinese_simple": "圣伊丽莎白区", + "korean": "세인트엘리자베스", + "dutch": "Saint Elizabeth", + "portuguese": "Saint Elizabeth", + "russian": "Сент-Элизабет", + "chinese_traditional": "Saint Elizabeth", + "unknown1": "Saint Elizabeth", + "unknown2": "Saint Elizabeth", + "unknown3": "Saint Elizabeth", + "unknown4": "Saint Elizabeth" + }, + "coordinates": { + "latitude": 18.012084756, + "longitude": -77.848843316 + } + }, + { + "id": 571146240, + "name": "Saint James", + "translations": { + "japanese": "セント・ジェームズ", + "english": "Saint James", + "french": "Saint James", + "german": "Saint James", + "italian": "Saint James", + "spanish": "Saint James", + "chinese_simple": "圣詹姆斯区", + "korean": "세인트제임스", + "dutch": "Saint James", + "portuguese": "Saint James", + "russian": "Сент-Джэймс", + "chinese_traditional": "Saint James", + "unknown1": "Saint James", + "unknown2": "Saint James", + "unknown3": "Saint James", + "unknown4": "Saint James" + }, + "coordinates": { + "latitude": 18.462524204, + "longitude": -77.914761464 + } + }, + { + "id": 571211776, + "name": "Saint Mary", + "translations": { + "japanese": "セント・メアリー", + "english": "Saint Mary", + "french": "Saint Mary", + "german": "Saint Mary", + "italian": "Saint Mary", + "spanish": "Saint Mary", + "chinese_simple": "圣玛丽区", + "korean": "세인트메리", + "dutch": "Saint Mary", + "portuguese": "Saint Mary", + "russian": "Сент-Мэри", + "chinese_traditional": "Saint Mary", + "unknown1": "Saint Mary", + "unknown2": "Saint Mary", + "unknown3": "Saint Mary", + "unknown4": "Saint Mary" + }, + "coordinates": { + "latitude": 18.363647252, + "longitude": -76.898523349 + } + }, + { + "id": 571277312, + "name": "Trelawny", + "translations": { + "japanese": "トレローニー", + "english": "Trelawny", + "french": "Trelawny", + "german": "Trelawny", + "italian": "Trelawny", + "spanish": "Trelawny", + "chinese_simple": "特里洛尼区", + "korean": "트렐로니", + "dutch": "Trelawny", + "portuguese": "Trelawny", + "russian": "Трилони", + "chinese_traditional": "Trelawny", + "unknown1": "Trelawny", + "unknown2": "Trelawny", + "unknown3": "Trelawny", + "unknown4": "Trelawny" + }, + "coordinates": { + "latitude": 18.495483188, + "longitude": -77.645595693 + } + }, + { + "id": 571342848, + "name": "Westmoreland", + "translations": { + "japanese": "ウェストモアランド", + "english": "Westmoreland", + "french": "Westmoreland", + "german": "Westmoreland얆徇᥄\udac7", + "italian": "Westmoreland", + "spanish": "Westmoreland", + "chinese_simple": "西摩兰区", + "korean": "웨스트모얼랜드", + "dutch": "Westmoreland", + "portuguese": "Westmoreland", + "russian": "Уэстморлэнд", + "chinese_traditional": "Westmoreland", + "unknown1": "Westmoreland", + "unknown2": "Westmoreland", + "unknown3": "Westmoreland", + "unknown4": "Westmoreland" + }, + "coordinates": { + "latitude": 18.215331824, + "longitude": -78.128995445 + } + }, + { + "id": 571408384, + "name": "Kingston", + "translations": { + "japanese": "キングストン", + "english": "Kingston", + "french": "Kingston", + "german": "Kingston", + "italian": "Kingston", + "spanish": "Kingston", + "chinese_simple": "金斯敦区", + "korean": "킹스턴", + "dutch": "Kingston", + "portuguese": "Kingston", + "russian": "Кингстон", + "chinese_traditional": "Kingston", + "unknown1": "Kingston", + "unknown2": "Kingston", + "unknown3": "Kingston", + "unknown4": "Kingston" + }, + "coordinates": { + "latitude": 17.946166788, + "longitude": -76.777673411 + } + } + ] + }, + { + "id": 35, + "iso_code": "MQ", + "name": "Martinique", + "translations": { + "japanese": "マルティニーク", + "english": "Martinique", + "french": "Martinique", + "german": "Martinique", + "italian": "Martinica", + "spanish": "Martinica", + "chinese_simple": "马提尼克", + "korean": "마르티니크", + "dutch": "Martinique", + "portuguese": "Martinica", + "russian": "Мартиника", + "chinese_traditional": "Martinique", + "unknown1": "Martinique", + "unknown2": "Martinique", + "unknown3": "Martinique", + "unknown4": "Martinique" + }, + "regions": [ + { + "id": 587202560, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 14.595336748, + "longitude": -61.078167828999995 + } + }, + { + "id": 587268096, + "name": "Martinique", + "translations": { + "japanese": "マルティニーク", + "english": "Martinique", + "french": "Martinique", + "german": "Martinique", + "italian": "Martinica", + "spanish": "Martinica", + "chinese_simple": "马提尼克", + "korean": "마르티니크", + "dutch": "Martinique", + "portuguese": "Martinica", + "russian": "Мартиника", + "chinese_traditional": "Martinique", + "unknown1": "Martinique", + "unknown2": "Martinique", + "unknown3": "Martinique", + "unknown4": "Martinique" + }, + "coordinates": { + "latitude": 14.595336748, + "longitude": -61.078167828999995 + } + } + ] + }, + { + "id": 36, + "iso_code": "MX", + "name": "Mexico", + "translations": { + "japanese": "メキシコ", + "english": "Mexico", + "french": "Mexique", + "german": "Mexiko", + "italian": "Messico", + "spanish": "México", + "chinese_simple": "墨西哥", + "korean": "멕시코", + "dutch": "Mexico", + "portuguese": "México", + "russian": "Мексика", + "chinese_traditional": "Mexico", + "unknown1": "Mexico", + "unknown2": "Mexico", + "unknown3": "Mexico", + "unknown4": "Mexico" + }, + "regions": [ + { + "id": 603979776, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 19.429321068, + "longitude": -99.134911941 + } + }, + { + "id": 604110848, + "name": "Distrito Federal", + "translations": { + "japanese": "ディストリト・フェデラル連邦区", + "english": "Distrito Federal", + "french": "District Fédéral", + "german": "México D.F.", + "italian": "Distretto Federale", + "spanish": "Distrito Federal", + "chinese_simple": "联邦区", + "korean": "멕시코 연방구", + "dutch": "Federaal District", + "portuguese": "Distrito Federal", + "russian": "Федеральный округ", + "chinese_traditional": "Distrito Federal", + "unknown1": "Distrito Federal", + "unknown2": "Distrito Federal", + "unknown3": "Distrito Federal", + "unknown4": "Distrito Federal" + }, + "coordinates": { + "latitude": 19.429321068, + "longitude": -99.134911941 + } + }, + { + "id": 604176384, + "name": "Aguascalientes", + "translations": { + "japanese": "アグアスカリエンテス州", + "english": "Aguascalientes", + "french": "Aguascalientes", + "german": "Aguascalientes", + "italian": "Aguascalientes", + "spanish": "Aguascalientes", + "chinese_simple": "阿瓜斯卡连特斯州", + "korean": "아과스칼리엔테스 주", + "dutch": "Aguascalientes", + "portuguese": "Aguascalientes", + "russian": "Агуаскальентес", + "chinese_traditional": "Aguascalientes", + "unknown1": "Aguascalientes", + "unknown2": "Aguascalientes", + "unknown3": "Aguascalientes", + "unknown4": "Aguascalientes" + }, + "coordinates": { + "latitude": 21.879272212, + "longitude": -102.298983045 + } + }, + { + "id": 604241920, + "name": "Baja California", + "translations": { + "japanese": "バハ・カリフォルニア州", + "english": "Baja California", + "french": "Basse-Californie", + "german": "Niederkalifornien", + "italian": "Bassa California", + "spanish": "Baja California", + "chinese_simple": "下加里福尼亚州", + "korean": "바하칼리포르니아 주", + "dutch": "Neder-Californië", + "portuguese": "Baixa Califórnia", + "russian": "Нижняя Калифорния", + "chinese_traditional": "Baja California", + "unknown1": "Baja California", + "unknown2": "Baja California", + "unknown3": "Baja California", + "unknown4": "Baja California" + }, + "coordinates": { + "latitude": 32.651366816, + "longitude": -115.466133108 + } + }, + { + "id": 604307456, + "name": "Baja California Sur", + "translations": { + "japanese": "バハ・カリフォルニア・スル州", + "english": "Baja California Sur", + "french": "Basse-Californie du Sud", + "german": "Süd-Niederkalifornien", + "italian": "Bassa California del Sud", + "spanish": "Baja California Sur", + "chinese_simple": "南下加里福尼亚州", + "korean": "바하칼리포르니아수르 주", + "dutch": "Zuid-Neder-Californië", + "portuguese": "Baixa Califórnia do Sul", + "russian": "Южная Нижняя Калифорния", + "chinese_traditional": "Baja California Sur", + "unknown1": "Baja California Sur", + "unknown2": "Baja California Sur", + "unknown3": "Baja California Sur", + "unknown4": "Baja California Sur" + }, + "coordinates": { + "latitude": 24.164428436, + "longitude": -110.297051669 + } + }, + { + "id": 604372992, + "name": "Campeche", + "translations": { + "japanese": "カンペチェ州", + "english": "Campeche", + "french": "Campeche", + "german": "Campeche", + "italian": "Campeche", + "spanish": "Campeche", + "chinese_simple": "坎佩切州", + "korean": "캄페체 주", + "dutch": "Campeche", + "portuguese": "Campeche", + "russian": "Кампече", + "chinese_traditional": "Campeche", + "unknown1": "Campeche", + "unknown2": "Campeche", + "unknown3": "Campeche", + "unknown4": "Campeche" + }, + "coordinates": { + "latitude": 19.846801532, + "longitude": -90.532593627 + } + }, + { + "id": 604438528, + "name": "Chiapas", + "translations": { + "japanese": "チアパス州", + "english": "Chiapas", + "french": "Chiapas", + "german": "Chiapas", + "italian": "Chiapas", + "spanish": "Chiapas", + "chinese_simple": "恰帕斯州", + "korean": "치아파스 주", + "dutch": "Chiapas", + "portuguese": "Chiapas", + "russian": "Чьяпас", + "chinese_traditional": "Chiapas", + "unknown1": "Chiapas", + "unknown2": "Chiapas", + "unknown3": "Chiapas", + "unknown4": "Chiapas" + }, + "coordinates": { + "latitude": 16.748657036, + "longitude": -93.114387757 + } + }, + { + "id": 604504064, + "name": "Chihuahua", + "translations": { + "japanese": "チワワ州", + "english": "Chihuahua", + "french": "Chihuahua", + "german": "Chihuahua", + "italian": "Chihuahua", + "spanish": "Chihuahua", + "chinese_simple": "奇瓦瓦州", + "korean": "치와와 주", + "dutch": "Chihuahua", + "portuguese": "Chihuahua", + "russian": "Чиуауа", + "chinese_traditional": "Chihuahua", + "unknown1": "Chihuahua", + "unknown2": "Chihuahua", + "unknown3": "Chihuahua", + "unknown4": "Chihuahua" + }, + "coordinates": { + "latitude": 28.630370768, + "longitude": -106.078290197 + } + }, + { + "id": 604569600, + "name": "Coahuila de Zaragoza", + "translations": { + "japanese": "コアウイラ州", + "english": "Coahuila de Zaragoza", + "french": "Coahuila", + "german": "Coahuila de Zaragoza", + "italian": "Coahuila", + "spanish": "Coahuila", + "chinese_simple": "科阿韦拉州", + "korean": "코아우일라 주", + "dutch": "Coahuila de Zaragoza", + "portuguese": "Coahuila de Zaragoza", + "russian": "Коауила", + "chinese_traditional": "Coahuila de Zaragoza", + "unknown1": "Coahuila de Zaragoza", + "unknown2": "Coahuila de Zaragoza", + "unknown3": "Coahuila de Zaragoza", + "unknown4": "Coahuila de Zaragoza" + }, + "coordinates": { + "latitude": 25.411376664, + "longitude": -100.99709962200001 + } + }, + { + "id": 604635136, + "name": "Colima", + "translations": { + "japanese": "コリマ州", + "english": "Colima", + "french": "Colima", + "german": "Colima", + "italian": "Colima", + "spanish": "Colima", + "chinese_simple": "科利马州", + "korean": "콜리마 주", + "dutch": "Colima", + "portuguese": "Colima", + "russian": "Колима", + "chinese_traditional": "Colima", + "unknown1": "Colima", + "unknown2": "Colima", + "unknown3": "Colima", + "unknown4": "Colima" + }, + "coordinates": { + "latitude": 19.231567164, + "longitude": -103.716223227 + } + }, + { + "id": 604700672, + "name": "Durango", + "translations": { + "japanese": "ドゥランゴ州", + "english": "Durango", + "french": "Durango", + "german": "Durango", + "italian": "Durango", + "spanish": "Durango", + "chinese_simple": "杜兰戈州", + "korean": "두랑고 주", + "dutch": "Durango", + "portuguese": "Durango", + "russian": "Дуранго", + "chinese_traditional": "Durango", + "unknown1": "Durango", + "unknown2": "Durango", + "unknown3": "Durango", + "unknown4": "Durango" + }, + "coordinates": { + "latitude": 24.0325925, + "longitude": -104.661050015 + } + }, + { + "id": 604766208, + "name": "Guanajuato", + "translations": { + "japanese": "グアナフアト州", + "english": "Guanajuato", + "french": "Guanajuato", + "german": "Guanajuato", + "italian": "Guanajuato", + "spanish": "Guanajuato", + "chinese_simple": "瓜纳华托州", + "korean": "과나후아토 주", + "dutch": "Guanajuato", + "portuguese": "Guanajuato", + "russian": "Гуанахуато", + "chinese_traditional": "Guanajuato", + "unknown1": "Guanajuato", + "unknown2": "Guanajuato", + "unknown3": "Guanajuato", + "unknown4": "Guanajuato" + }, + "coordinates": { + "latitude": 21.0113523, + "longitude": -101.249785856 + } + }, + { + "id": 604831744, + "name": "Guerrero", + "translations": { + "japanese": "ゲレロ州", + "english": "Guerrero", + "french": "Guerrero", + "german": "Guerrero", + "italian": "Guerrero", + "spanish": "Guerrero", + "chinese_simple": "格雷罗州", + "korean": "게레로 주", + "dutch": "Guerrero", + "portuguese": "Guerrero", + "russian": "Герреро", + "chinese_traditional": "Guerrero", + "unknown1": "Guerrero", + "unknown2": "Guerrero", + "unknown3": "Guerrero", + "unknown4": "Guerrero" + }, + "coordinates": { + "latitude": 17.545165816, + "longitude": -99.497461755 + } + }, + { + "id": 604897280, + "name": "Hidalgo", + "translations": { + "japanese": "イダルゴ州", + "english": "Hidalgo", + "french": "Hidalgo", + "german": "Hidalgo", + "italian": "Hidalgo", + "spanish": "Hidalgo", + "chinese_simple": "伊达尔戈州", + "korean": "이달고 주", + "dutch": "Hidalgo", + "portuguese": "Hidalgo", + "russian": "Идальго", + "chinese_traditional": "Hidalgo", + "unknown1": "Hidalgo", + "unknown2": "Hidalgo", + "unknown3": "Hidalgo", + "unknown4": "Hidalgo" + }, + "coordinates": { + "latitude": 20.115966568, + "longitude": -98.728416695 + } + }, + { + "id": 604962816, + "name": "Jalisco", + "translations": { + "japanese": "ハリスコ州", + "english": "Jalisco", + "french": "Jalisco", + "german": "Jalisco", + "italian": "Jalisco", + "spanish": "Jalisco", + "chinese_simple": "哈利斯科州", + "korean": "할리스코 주", + "dutch": "Jalisco", + "portuguese": "Jalisco", + "russian": "Халиско", + "chinese_traditional": "Jalisco", + "unknown1": "Jalisco", + "unknown2": "Jalisco", + "unknown3": "Jalisco", + "unknown4": "Jalisco" + }, + "coordinates": { + "latitude": 20.665282968, + "longitude": -103.331700697 + } + }, + { + "id": 605028352, + "name": "México", + "translations": { + "japanese": "メヒコ州", + "english": "México", + "french": "Mexico", + "german": "México", + "italian": "Messico", + "spanish": "México", + "chinese_simple": "墨西哥州", + "korean": "메히코 주", + "dutch": "Mexico", + "portuguese": "México", + "russian": "Мехико", + "chinese_traditional": "México", + "unknown1": "México", + "unknown2": "México", + "unknown3": "México", + "unknown4": "México" + }, + "coordinates": { + "latitude": 19.286498804, + "longitude": -99.662257125 + } + }, + { + "id": 605093888, + "name": "Michoacán de Ocampo", + "translations": { + "japanese": "ミチョアカン州", + "english": "Michoacán de Ocampo", + "french": "Michoacán", + "german": "Michoacán", + "italian": "Michoacán de Ocampo", + "spanish": "Michoacán", + "chinese_simple": "米却肯州", + "korean": "미초아칸 주", + "dutch": "Michoacán de Ocampo", + "portuguese": "Michoacán de Ocampo", + "russian": "Мичоакан", + "chinese_traditional": "Michoacán de Ocampo", + "unknown1": "Michoacán de Ocampo", + "unknown2": "Michoacán de Ocampo", + "unknown3": "Michoacán de Ocampo", + "unknown4": "Michoacán de Ocampo" + }, + "coordinates": { + "latitude": 19.698486104, + "longitude": -101.112456381 + } + }, + { + "id": 605159424, + "name": "Morelos", + "translations": { + "japanese": "モレロス州", + "english": "Morelos", + "french": "Morelos", + "german": "Morelos", + "italian": "Morelos", + "spanish": "Morelos", + "chinese_simple": "莫雷洛斯州", + "korean": "모렐로스 주", + "dutch": "Morelos", + "portuguese": "Morelos", + "russian": "Морелос", + "chinese_traditional": "Morelos", + "unknown1": "Morelos", + "unknown2": "Morelos", + "unknown3": "Morelos", + "unknown4": "Morelos" + }, + "coordinates": { + "latitude": 18.912963652, + "longitude": -99.244775521 + } + }, + { + "id": 605224960, + "name": "Nayarit", + "translations": { + "japanese": "ナヤリット州", + "english": "Nayarit", + "french": "Nayarit", + "german": "Nayarit", + "italian": "Nayarit", + "spanish": "Nayarit", + "chinese_simple": "纳亚里特州", + "korean": "나야리트 주", + "dutch": "Nayarit", + "portuguese": "Nayarit", + "russian": "Наярит", + "chinese_traditional": "Nayarit", + "unknown1": "Nayarit", + "unknown2": "Nayarit", + "unknown3": "Nayarit", + "unknown4": "Nayarit" + }, + "coordinates": { + "latitude": 21.494750732, + "longitude": -104.897256712 + } + }, + { + "id": 605290496, + "name": "Nuevo León", + "translations": { + "japanese": "ヌエボ・レオン州", + "english": "Nuevo León", + "french": "Nuevo León", + "german": "Nuevo León", + "italian": "Nuevo León", + "spanish": "Nuevo León", + "chinese_simple": "新莱昂州", + "korean": "누에보레온 주", + "dutch": "Nieuw-León", + "portuguese": "Nuevo León", + "russian": "Нуэво-Леон", + "chinese_traditional": "Nuevo León", + "unknown1": "Nuevo León", + "unknown2": "Nuevo León", + "unknown3": "Nuevo León", + "unknown4": "Nuevo León" + }, + "coordinates": { + "latitude": 25.664062208, + "longitude": -100.315945426 + } + }, + { + "id": 605356032, + "name": "Oaxaca", + "translations": { + "japanese": "オアハカ州", + "english": "Oaxaca", + "french": "Oaxaca", + "german": "Oaxaca", + "italian": "Oaxaca", + "spanish": "Oaxaca", + "chinese_simple": "瓦哈卡州", + "korean": "오악사카 주", + "dutch": "Oaxaca", + "portuguese": "Oaxaca", + "russian": "Оахака", + "chinese_traditional": "Oaxaca", + "unknown1": "Oaxaca", + "unknown2": "Oaxaca", + "unknown3": "Oaxaca", + "unknown4": "Oaxaca" + }, + "coordinates": { + "latitude": 17.045287892, + "longitude": -96.712420002 + } + }, + { + "id": 605421568, + "name": "Puebla", + "translations": { + "japanese": "プエブラ州", + "english": "Puebla", + "french": "Puebla", + "german": "Puebla", + "italian": "Puebla", + "spanish": "Puebla", + "chinese_simple": "普埃布拉州", + "korean": "푸에블라 주", + "dutch": "Puebla", + "portuguese": "Puebla", + "russian": "Пуэбла", + "chinese_traditional": "Puebla", + "unknown1": "Puebla", + "unknown2": "Puebla", + "unknown3": "Puebla", + "unknown4": "Puebla" + }, + "coordinates": { + "latitude": 19.044799588, + "longitude": -98.195578332 + } + }, + { + "id": 605487104, + "name": "Querétaro de Arteaga", + "translations": { + "japanese": "ケレタロ州", + "english": "Querétaro de Arteaga", + "french": "Querétaro", + "german": "Querétaro", + "italian": "Querétaro de Arteaga", + "spanish": "Querétaro", + "chinese_simple": "克雷塔罗州", + "korean": "케레타로 주", + "dutch": "Querétaro de Arteaga", + "portuguese": "Querétaro de Arteaga", + "russian": "Керетаро", + "chinese_traditional": "Querétaro de Arteaga", + "unknown1": "Querétaro de Arteaga", + "unknown2": "Querétaro de Arteaga", + "unknown3": "Querétaro de Arteaga", + "unknown4": "Querétaro de Arteaga" + }, + "coordinates": { + "latitude": 20.599365, + "longitude": -100.38186357400001 + } + }, + { + "id": 605552640, + "name": "Quintana Roo", + "translations": { + "japanese": "キンタナ・ロー州", + "english": "Quintana Roo", + "french": "Quintana Roo", + "german": "Quintana Roo", + "italian": "Quintana Roo", + "spanish": "Quintana Roo", + "chinese_simple": "金塔纳罗奥州", + "korean": "킨타나로오 주", + "dutch": "Quintana Roo", + "portuguese": "Quintana Roo", + "russian": "Кинтана-Роо", + "chinese_traditional": "Quintana Roo", + "unknown1": "Quintana Roo", + "unknown2": "Quintana Roo", + "unknown3": "Quintana Roo", + "unknown4": "Quintana Roo" + }, + "coordinates": { + "latitude": 18.495483188, + "longitude": -88.296869774 + } + }, + { + "id": 605618176, + "name": "San Luis Potosí", + "translations": { + "japanese": "サン・ルイス・ポトシ州", + "english": "San Luis Potosí", + "french": "San Luis Potosí", + "german": "San Luis Potosí", + "italian": "San Luis Potosí", + "spanish": "San Luis Potosí", + "chinese_simple": "圣路易斯波托西州", + "korean": "산루이스포토시 주", + "dutch": "San Luis Potosí", + "portuguese": "San Luis Potosí", + "russian": "Сан-Луис-Потоси", + "chinese_traditional": "San Luis Potosí", + "unknown1": "San Luis Potosí", + "unknown2": "San Luis Potosí", + "unknown3": "San Luis Potosí", + "unknown4": "San Luis Potosí" + }, + "coordinates": { + "latitude": 22.148437248, + "longitude": -100.980620085 + } + }, + { + "id": 605683712, + "name": "Sinaloa", + "translations": { + "japanese": "シナロア州", + "english": "Sinaloa", + "french": "Sinaloa", + "german": "Sinaloa", + "italian": "Sinaloa", + "spanish": "Sinaloa", + "chinese_simple": "锡那罗亚州", + "korean": "시날로아 주", + "dutch": "Sinaloa", + "portuguese": "Sinaloa", + "russian": "Синалоа", + "chinese_traditional": "Sinaloa", + "unknown1": "Sinaloa", + "unknown2": "Sinaloa", + "unknown3": "Sinaloa", + "unknown4": "Sinaloa" + }, + "coordinates": { + "latitude": 24.796142296, + "longitude": -107.385666799 + } + }, + { + "id": 605749248, + "name": "Sonora", + "translations": { + "japanese": "ソノラ州", + "english": "Sonora", + "french": "Sonora", + "german": "Sonora", + "italian": "Sonora", + "spanish": "Sonora", + "chinese_simple": "索诺拉州", + "korean": "소노라 주", + "dutch": "Sonora", + "portuguese": "Sonora", + "russian": "Сонора", + "chinese_traditional": "Sonora", + "unknown1": "Sonora", + "unknown2": "Sonora", + "unknown3": "Sonora", + "unknown4": "Sonora" + }, + "coordinates": { + "latitude": 29.064330724, + "longitude": -110.961726328 + } + }, + { + "id": 605814784, + "name": "Tabasco", + "translations": { + "japanese": "タバスコ州", + "english": "Tabasco", + "french": "Tabasco", + "german": "Tabasco", + "italian": "Tabasco", + "spanish": "Tabasco", + "chinese_simple": "塔巴斯科州", + "korean": "타바스코 주", + "dutch": "Tabasco", + "portuguese": "Tabasco", + "russian": "Табаско", + "chinese_traditional": "Tabasco", + "unknown1": "Tabasco", + "unknown2": "Tabasco", + "unknown3": "Tabasco", + "unknown4": "Tabasco" + }, + "coordinates": { + "latitude": 17.979125772, + "longitude": -92.91114013400001 + } + }, + { + "id": 605880320, + "name": "Tamaulipas", + "translations": { + "japanese": "タマウリパス州", + "english": "Tamaulipas", + "french": "Tamaulipas", + "german": "Tamaulipas", + "italian": "Tamaulipas", + "spanish": "Tamaulipas", + "chinese_simple": "塔毛利帕斯州", + "korean": "타마울리파스 주", + "dutch": "Tamaulipas", + "portuguese": "Tamaulipas", + "russian": "Тамаулипас", + "chinese_traditional": "Tamaulipas", + "unknown1": "Tamaulipas", + "unknown2": "Tamaulipas", + "unknown3": "Tamaulipas", + "unknown4": "Tamaulipas" + }, + "coordinates": { + "latitude": 23.73046848, + "longitude": -99.129418762 + } + }, + { + "id": 605945856, + "name": "Tlaxcala", + "translations": { + "japanese": "トラスカラ州", + "english": "Tlaxcala", + "french": "Tlaxcala", + "german": "Tlaxcala", + "italian": "Tlaxcala", + "spanish": "Tlaxcala", + "chinese_simple": "特拉斯卡拉州", + "korean": "틀락스칼라 주", + "dutch": "Tlaxcala", + "portuguese": "Tlaxcala", + "russian": "Тласкала", + "chinese_traditional": "Tlaxcala", + "unknown1": "Tlaxcala", + "unknown2": "Tlaxcala", + "unknown3": "Tlaxcala", + "unknown4": "Tlaxcala" + }, + "coordinates": { + "latitude": 19.30847146, + "longitude": -98.239523764 + } + }, + { + "id": 606011392, + "name": "Veracruz-Llave", + "translations": { + "japanese": "ベラクルス州", + "english": "Veracruz-Llave", + "french": "Veracruz", + "german": "Veracruz", + "italian": "Veracruz", + "spanish": "Veracruz", + "chinese_simple": "韦拉克鲁斯州", + "korean": "베라크루스 주", + "dutch": "Veracruz", + "portuguese": "Veracruz-Llave", + "russian": "Веракрус", + "chinese_traditional": "Veracruz-Llave", + "unknown1": "Veracruz-Llave", + "unknown2": "Veracruz-Llave", + "unknown3": "Veracruz-Llave", + "unknown4": "Veracruz-Llave" + }, + "coordinates": { + "latitude": 19.52819802, + "longitude": -96.915667625 + } + }, + { + "id": 606076928, + "name": "Yucatán", + "translations": { + "japanese": "ユカタン州", + "english": "Yucatán", + "french": "Yucatán", + "german": "Yukatan", + "italian": "Yucatán", + "spanish": "Yucatán", + "chinese_simple": "尤卡坦州", + "korean": "유카탄 주", + "dutch": "Yucatán", + "portuguese": "Yucatán", + "russian": "Юкатан", + "chinese_traditional": "Yucatán", + "unknown1": "Yucatán", + "unknown2": "Yucatán", + "unknown3": "Yucatán", + "unknown4": "Yucatán" + }, + "coordinates": { + "latitude": 20.961913824, + "longitude": -89.615232734 + } + }, + { + "id": 606142464, + "name": "Zacatecas", + "translations": { + "japanese": "サカテカス州", + "english": "Zacatecas", + "french": "Zacatecas", + "german": "Zacatecas", + "italian": "Zacatecas", + "spanish": "Zacatecas", + "chinese_simple": "萨卡特卡斯州", + "korean": "사카테카스 주", + "dutch": "Zacatecas", + "portuguese": "Zacatecas", + "russian": "Сакатекас", + "chinese_traditional": "Zacatecas", + "unknown1": "Zacatecas", + "unknown2": "Zacatecas", + "unknown3": "Zacatecas", + "unknown4": "Zacatecas" + }, + "coordinates": { + "latitude": 22.780151108000002, + "longitude": -102.579135174 + } + } + ] + }, + { + "id": 37, + "iso_code": "MS", + "name": "Montserrat", + "translations": { + "japanese": "モントセラト", + "english": "Montserrat", + "french": "Montserrat", + "german": "Montserrat", + "italian": "Montserrat", + "spanish": "Montserrat", + "chinese_simple": "蒙特塞拉特", + "korean": "몬트세랫", + "dutch": "Montserrat", + "portuguese": "Montserrat", + "russian": "Монтсеррат", + "chinese_traditional": "Montserrat", + "unknown1": "Montserrat", + "unknown2": "Montserrat", + "unknown3": "Montserrat", + "unknown4": "Montserrat" + }, + "regions": [ + { + "id": 620756992, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 16.69921856, + "longitude": -62.21525588200001 + } + }, + { + "id": 620822528, + "name": "Montserrat", + "translations": { + "japanese": "モントセラト", + "english": "Montserrat", + "french": "Montserrat", + "german": "Montserrat", + "italian": "Montserrat", + "spanish": "Montserrat", + "chinese_simple": "蒙特塞拉特", + "korean": "몬트세랫", + "dutch": "Montserrat", + "portuguese": "Montserrat", + "russian": "Монтсеррат", + "chinese_traditional": "Montserrat", + "unknown1": "Montserrat", + "unknown2": "Montserrat", + "unknown3": "Montserrat", + "unknown4": "Montserrat" + }, + "coordinates": { + "latitude": 16.69921856, + "longitude": -62.21525588200001 + } + } + ] + }, + { + "id": 38, + "iso_code": "AN", + "name": "Netherlands Antilles", + "translations": { + "japanese": "オランダ領アンティル", + "english": "Netherlands Antilles", + "french": "Antilles néerlandaises", + "german": "Niederländische Antillen", + "italian": "Antille Olandesi", + "spanish": "Antillas Neerlandesas", + "chinese_simple": "荷属安的列斯", + "korean": "네덜란드령 앤틸리스", + "dutch": "Nederlandse Antillen", + "portuguese": "Antilhas Holandesas", + "russian": "Нидерландские Антильские острова", + "chinese_traditional": "Netherlands Antilles", + "unknown1": "Netherlands Antilles", + "unknown2": "Netherlands Antilles", + "unknown3": "Netherlands Antilles", + "unknown4": "Netherlands Antilles" + }, + "regions": [ + { + "id": 637534208, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 12.095947128, + "longitude": -68.911441083 + } + }, + { + "id": 637599744, + "name": "Netherlands Antilles", + "translations": { + "japanese": "オランダ領アンティル", + "english": "Netherlands Antilles", + "french": "Antilles néerlandaises", + "german": "Niederländische Antillen", + "italian": "Antille Olandesi", + "spanish": "Antillas Neerlandesas", + "chinese_simple": "荷属安的列斯", + "korean": "네덜란드령 앤틸리스", + "dutch": "Nederlandse Antillen", + "portuguese": "Antilhas Holandesas", + "russian": "Нидерландские Антильские острова", + "chinese_traditional": "Netherlands Antilles", + "unknown1": "Netherlands Antilles", + "unknown2": "Netherlands Antilles", + "unknown3": "Netherlands Antilles", + "unknown4": "Netherlands Antilles" + }, + "coordinates": { + "latitude": 12.095947128, + "longitude": -68.911441083 + } + } + ] + }, + { + "id": 39, + "iso_code": "NI", + "name": "Nicaragua", + "translations": { + "japanese": "ニカラグア", + "english": "Nicaragua", + "french": "Nicaragua", + "german": "Nicaragua", + "italian": "Nicaragua", + "spanish": "Nicaragua", + "chinese_simple": "尼加拉瓜", + "korean": "니카라과", + "dutch": "Nicaragua", + "portuguese": "Nicarágua", + "russian": "Никарагуа", + "chinese_traditional": "Nicaragua", + "unknown1": "Nicaragua", + "unknown2": "Nicaragua", + "unknown3": "Nicaragua", + "unknown4": "Nicaragua" + }, + "regions": [ + { + "id": 654311424, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 12.145385604, + "longitude": -86.264393544 + } + }, + { + "id": 654442496, + "name": "Managua", + "translations": { + "japanese": "マナグア", + "english": "Managua", + "french": "Managua", + "german": "Managua", + "italian": "Managua", + "spanish": "Managua", + "chinese_simple": "马那瓜省", + "korean": "마나과", + "dutch": "Managua", + "portuguese": "Managua", + "russian": "Манагуа", + "chinese_traditional": "Managua", + "unknown1": "Managua", + "unknown2": "Managua", + "unknown3": "Managua", + "unknown4": "Managua" + }, + "coordinates": { + "latitude": 12.145385604, + "longitude": -86.264393544 + } + }, + { + "id": 654508032, + "name": "Boaco", + "translations": { + "japanese": "ボアコ", + "english": "Boaco", + "french": "Boaco", + "german": "Boaco", + "italian": "Boaco", + "spanish": "Boaco", + "chinese_simple": "博阿科省", + "korean": "보아코", + "dutch": "Boaco", + "portuguese": "Boaco", + "russian": "Боако", + "chinese_traditional": "Boaco", + "unknown1": "Boaco", + "unknown2": "Boaco", + "unknown3": "Boaco", + "unknown4": "Boaco" + }, + "coordinates": { + "latitude": 12.463989116, + "longitude": -85.665637033 + } + }, + { + "id": 654573568, + "name": "Carazo", + "translations": { + "japanese": "カラソ", + "english": "Carazo", + "french": "Carazo", + "german": "Carazo", + "italian": "Carazo", + "spanish": "Carazo", + "chinese_simple": "卡拉索省", + "korean": "카라소", + "dutch": "Carazo", + "portuguese": "Carazo", + "russian": "Карасо", + "chinese_traditional": "Carazo", + "unknown1": "Carazo", + "unknown2": "Carazo", + "unknown3": "Carazo", + "unknown4": "Carazo" + }, + "coordinates": { + "latitude": 11.848754748, + "longitude": -86.198475396 + } + }, + { + "id": 654639104, + "name": "Chinandega", + "translations": { + "japanese": "チナンデガ", + "english": "Chinandega", + "french": "Chinandega", + "german": "Chinandega", + "italian": "Chinandega", + "spanish": "Chinandega", + "chinese_simple": "奇南德加省", + "korean": "치난데가", + "dutch": "Chinandega", + "portuguese": "Chinandega", + "russian": "Чинандега", + "chinese_traditional": "Chinandega", + "unknown1": "Chinandega", + "unknown2": "Chinandega", + "unknown3": "Chinandega", + "unknown4": "Chinandega" + }, + "coordinates": { + "latitude": 12.612304544, + "longitude": -87.148795363 + } + }, + { + "id": 654704640, + "name": "Chontales", + "translations": { + "japanese": "チョンタレス", + "english": "Chontales", + "french": "Chontales", + "german": "Chontales", + "italian": "Chontales", + "spanish": "Chontales", + "chinese_simple": "琼塔莱斯省", + "korean": "촌탈레스", + "dutch": "Chontales", + "portuguese": "Chontales", + "russian": "Чонталес", + "chinese_traditional": "Chontales", + "unknown1": "Chontales", + "unknown2": "Chontales", + "unknown3": "Chontales", + "unknown4": "Chontales" + }, + "coordinates": { + "latitude": 12.079467636, + "longitude": -85.396471262 + } + }, + { + "id": 654770176, + "name": "Estelí", + "translations": { + "japanese": "エステリ", + "english": "Estelí", + "french": "Estelí", + "german": "Estelí", + "italian": "Estelí", + "spanish": "Estelí", + "chinese_simple": "埃斯特利省", + "korean": "에스텔리", + "dutch": "Estelí", + "portuguese": "Estelí", + "russian": "Эстели", + "chinese_traditional": "Estelí", + "unknown1": "Estelí", + "unknown2": "Estelí", + "unknown3": "Estelí", + "unknown4": "Estelí" + }, + "coordinates": { + "latitude": 13.079223484, + "longitude": -86.346791229 + } + }, + { + "id": 654835712, + "name": "Granada", + "translations": { + "japanese": "グラナダ", + "english": "Granada", + "french": "Granada", + "german": "Granada", + "italian": "Granada", + "spanish": "Granada", + "chinese_simple": "格拉纳达省", + "korean": "그라나다", + "dutch": "Granada", + "portuguese": "Granada", + "russian": "Гранада", + "chinese_traditional": "Granada", + "unknown1": "Granada", + "unknown2": "Granada", + "unknown3": "Granada", + "unknown4": "Granada" + }, + "coordinates": { + "latitude": 11.931152208, + "longitude": -85.945789162 + } + }, + { + "id": 654901248, + "name": "Jinotega", + "translations": { + "japanese": "ヒノテガ", + "english": "Jinotega", + "french": "Jinotega", + "german": "Jinotega", + "italian": "Jinotega", + "spanish": "Jinotega", + "chinese_simple": "希诺特加省", + "korean": "히노테가", + "dutch": "Jinotega", + "portuguese": "Jinotega", + "russian": "Хинотега", + "chinese_traditional": "Jinotega", + "unknown1": "Jinotega", + "unknown2": "Jinotega", + "unknown3": "Jinotega", + "unknown4": "Jinotega" + }, + "coordinates": { + "latitude": 13.095702976, + "longitude": -85.995227773 + } + }, + { + "id": 654966784, + "name": "León", + "translations": { + "japanese": "レオン", + "english": "León", + "french": "León", + "german": "León", + "italian": "León", + "spanish": "León", + "chinese_simple": "莱昂省", + "korean": "레온", + "dutch": "León", + "portuguese": "León", + "russian": "Леон", + "chinese_traditional": "León", + "unknown1": "León", + "unknown2": "León", + "unknown3": "León", + "unknown4": "León" + }, + "coordinates": { + "latitude": 12.431030132, + "longitude": -86.874136413 + } + }, + { + "id": 655032320, + "name": "Madriz", + "translations": { + "japanese": "マドリス", + "english": "Madriz", + "french": "Madriz", + "german": "Madriz", + "italian": "Madriz", + "spanish": "Madriz", + "chinese_simple": "马德里斯省", + "korean": "마드리스", + "dutch": "Madriz", + "portuguese": "Madriz", + "russian": "Мадрис", + "chinese_traditional": "Madriz", + "unknown1": "Madriz", + "unknown2": "Madriz", + "unknown3": "Madriz", + "unknown4": "Madriz" + }, + "coordinates": { + "latitude": 13.480224456, + "longitude": -86.582997926 + } + }, + { + "id": 655097856, + "name": "Masaya", + "translations": { + "japanese": "マサヤ", + "english": "Masaya", + "french": "Masaya", + "german": "Masaya", + "italian": "Masaya", + "spanish": "Masaya", + "chinese_simple": "马萨亚省", + "korean": "마사야", + "dutch": "Masaya", + "portuguese": "Masaya", + "russian": "Масая", + "chinese_traditional": "Masaya", + "unknown1": "Masaya", + "unknown2": "Masaya", + "unknown3": "Masaya", + "unknown4": "Masaya" + }, + "coordinates": { + "latitude": 11.964111192, + "longitude": -86.09959817400001 + } + }, + { + "id": 655163392, + "name": "Matagalpa", + "translations": { + "japanese": "マタガルパ", + "english": "Matagalpa", + "french": "Matagalpa", + "german": "Matagalpa", + "italian": "Matagalpa", + "spanish": "Matagalpa", + "chinese_simple": "马塔加尔帕省", + "korean": "마타갈파", + "dutch": "Matagalpa", + "portuguese": "Matagalpa", + "russian": "Матагальпа", + "chinese_traditional": "Matagalpa", + "unknown1": "Matagalpa", + "unknown2": "Matagalpa", + "unknown3": "Matagalpa", + "unknown4": "Matagalpa" + }, + "coordinates": { + "latitude": 12.914428564, + "longitude": -85.912830088 + } + }, + { + "id": 655228928, + "name": "Nueva Segovia", + "translations": { + "japanese": "ヌエバ・セゴビア", + "english": "Nueva Segovia", + "french": "Nueva Segovia", + "german": "Nueva Segovia", + "italian": "Nueva Segovia", + "spanish": "Nueva Segovia", + "chinese_simple": "新塞哥维亚省", + "korean": "누에바세고비아", + "dutch": "Nueva Segovia", + "portuguese": "Nueva Segovia", + "russian": "Нуэва-Сеговия", + "chinese_traditional": "Nueva Segovia", + "unknown1": "Nueva Segovia", + "unknown2": "Nueva Segovia", + "unknown3": "Nueva Segovia", + "unknown4": "Nueva Segovia" + }, + "coordinates": { + "latitude": 13.628539884, + "longitude": -86.47862752500001 + } + }, + { + "id": 655294464, + "name": "Río San Juan", + "translations": { + "japanese": "リオ・サン・フアン", + "english": "Río San Juan", + "french": "Río San Juan", + "german": "Río San Juan", + "italian": "Río San Juan", + "spanish": "Río San Juan", + "chinese_simple": "圣胡安河省", + "korean": "리오산후안", + "dutch": "Río San Juan", + "portuguese": "Río San Juan", + "russian": "Сан-Хуан", + "chinese_traditional": "Río San Juan", + "unknown1": "Río San Juan", + "unknown2": "Río San Juan", + "unknown3": "Río San Juan", + "unknown4": "Río San Juan" + }, + "coordinates": { + "latitude": 11.112670772, + "longitude": -84.781235214 + } + }, + { + "id": 655360000, + "name": "Rivas", + "translations": { + "japanese": "リバス", + "english": "Rivas", + "french": "Rivas", + "german": "Rivas", + "italian": "Rivas", + "spanish": "Rivas", + "chinese_simple": "里瓦斯省", + "korean": "리바스", + "dutch": "Rivas", + "portuguese": "Rivas", + "russian": "Ривас", + "chinese_traditional": "Rivas", + "unknown1": "Rivas", + "unknown2": "Rivas", + "unknown3": "Rivas", + "unknown4": "Rivas" + }, + "coordinates": { + "latitude": 11.431274284, + "longitude": -85.830432403 + } + }, + { + "id": 655425536, + "name": "Atlántico Norte", + "translations": { + "japanese": "北アトランティコ自治地域", + "english": "Atlántico Norte", + "french": "Región Autónoma del Atlántico Norte", + "german": "Región Autónoma del Atlántico Norte", + "italian": "Atlantico Settentrionale", + "spanish": "Atlántico Norte", + "chinese_simple": "北大西洋自治区", + "korean": "북아틀란티코 자치구", + "dutch": "Atlántico Norte", + "portuguese": "Atlântico Norte", + "russian": "Атлантический Северный автономный регион", + "chinese_traditional": "Atlántico Norte", + "unknown1": "Atlántico Norte", + "unknown2": "Atlántico Norte", + "unknown3": "Atlántico Norte", + "unknown4": "Atlántico Norte" + }, + "coordinates": { + "latitude": 14.029540856, + "longitude": -83.380474569 + } + }, + { + "id": 655491072, + "name": "Atlántico Sur", + "translations": { + "japanese": "南アトランティコ自治地域", + "english": "Atlántico Sur", + "french": "Región Autónoma del Atlántico Sur", + "german": "Región Autónoma del Atlántico Sur", + "italian": "Atlantico Meridionale", + "spanish": "Atlántico Sur", + "chinese_simple": "南大西洋自治区", + "korean": "남아틀란티코 자치구", + "dutch": "Atlántico Sur", + "portuguese": "Atlântico Sul", + "russian": "Атлантический Южный автономный регион", + "chinese_traditional": "Atlántico Sur", + "unknown1": "Atlántico Sur", + "unknown2": "Atlántico Sur", + "unknown3": "Atlántico Sur", + "unknown4": "Atlántico Sur" + }, + "coordinates": { + "latitude": 11.997070176, + "longitude": -83.748517562 + } + } + ] + }, + { + "id": 40, + "iso_code": "PA", + "name": "Panama", + "translations": { + "japanese": "パナマ", + "english": "Panama", + "french": "Panama", + "german": "Panama", + "italian": "Panamá", + "spanish": "Panamá", + "chinese_simple": "巴拿马", + "korean": "파나마", + "dutch": "Panama", + "portuguese": "Panamá", + "russian": "Панама", + "chinese_traditional": "Panama", + "unknown1": "Panama", + "unknown2": "Panama", + "unknown3": "Panama", + "unknown4": "Panama" + }, + "regions": [ + { + "id": 671088640, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 8.964843648, + "longitude": -79.52975609 + } + }, + { + "id": 671219712, + "name": "Panamá", + "translations": { + "japanese": "パナマ", + "english": "Panamá", + "french": "Panama", + "german": "Panama", + "italian": "Panamá", + "spanish": "Panamá", + "chinese_simple": "巴拿马省", + "korean": "파나마", + "dutch": "Panama", + "portuguese": "Panamá", + "russian": "Панама", + "chinese_traditional": "Panamá", + "unknown1": "Panamá", + "unknown2": "Panamá", + "unknown3": "Panamá", + "unknown4": "Panamá" + }, + "coordinates": { + "latitude": 8.964843648, + "longitude": -79.52975609 + } + }, + { + "id": 671285248, + "name": "Bocas del Toro", + "translations": { + "japanese": "ボカズ・デル・トーロ", + "english": "Bocas del Toro", + "french": "Bocas del Toro", + "german": "Bocas del Toro", + "italian": "Bocas del Toro", + "spanish": "Bocas del Toro", + "chinese_simple": "博卡斯-德尔托罗省", + "korean": "보카스델토로", + "dutch": "Bocas del Toro", + "portuguese": "Bocas del Toro", + "russian": "Бокас-дель-Торо", + "chinese_traditional": "Bocas del Toro", + "unknown1": "Bocas del Toro", + "unknown2": "Bocas del Toro", + "unknown3": "Bocas del Toro", + "unknown4": "Bocas del Toro" + }, + "coordinates": { + "latitude": 9.332885636, + "longitude": -82.248879695 + } + }, + { + "id": 671350784, + "name": "Chiriquí", + "translations": { + "japanese": "チリキ", + "english": "Chiriquí", + "french": "Chiriquí", + "german": "Chiriquí", + "italian": "Chiriquí", + "spanish": "Chiriquí", + "chinese_simple": "奇里基省", + "korean": "치리키", + "dutch": "Chiriquí", + "portuguese": "Chiriquí", + "russian": "Чирики", + "chinese_traditional": "Chiriquí", + "unknown1": "Chiriquí", + "unknown2": "Chiriquí", + "unknown3": "Chiriquí", + "unknown4": "Chiriquí" + }, + "coordinates": { + "latitude": 8.43200674, + "longitude": -82.430154602 + } + }, + { + "id": 671416320, + "name": "Coclé", + "translations": { + "japanese": "コクレ", + "english": "Coclé", + "french": "Coclé", + "german": "Coclé", + "italian": "Coclé", + "spanish": "Coclé", + "chinese_simple": "科克莱省", + "korean": "코클레", + "dutch": "Coclé", + "portuguese": "Coclé", + "russian": "Кокле", + "chinese_traditional": "Coclé", + "unknown1": "Coclé", + "unknown2": "Coclé", + "unknown3": "Coclé", + "unknown4": "Coclé" + }, + "coordinates": { + "latitude": 8.5144042, + "longitude": -80.364719298 + } + }, + { + "id": 671481856, + "name": "Colón", + "translations": { + "japanese": "コロン", + "english": "Colón", + "french": "Colón", + "german": "Colón", + "italian": "Colón", + "spanish": "Colón", + "chinese_simple": "科隆省", + "korean": "콜론", + "dutch": "Colón", + "portuguese": "Colón", + "russian": "Колон", + "chinese_traditional": "Colón", + "unknown1": "Colón", + "unknown2": "Colón", + "unknown3": "Colón", + "unknown4": "Colón" + }, + "coordinates": { + "latitude": 9.354858292, + "longitude": -79.897799083 + } + }, + { + "id": 671547392, + "name": "Darién", + "translations": { + "japanese": "ダリエン", + "english": "Darién", + "french": "Darién", + "german": "Darién", + "italian": "Darién", + "spanish": "Darién", + "chinese_simple": "达连省", + "korean": "다리엔", + "dutch": "Darién", + "portuguese": "Darién", + "russian": "Дарьен", + "chinese_traditional": "Darién", + "unknown1": "Darién", + "unknown2": "Darién", + "unknown3": "Darién", + "unknown4": "Darién" + }, + "coordinates": { + "latitude": 8.399047756, + "longitude": -78.139981803 + } + }, + { + "id": 671612928, + "name": "Herrera", + "translations": { + "japanese": "エレーラ", + "english": "Herrera", + "french": "Herrera", + "german": "Herrera", + "italian": "Herrera", + "spanish": "Herrera", + "chinese_simple": "埃雷拉省", + "korean": "에레라", + "dutch": "Herrera", + "portuguese": "Herrera", + "russian": "Эррера", + "chinese_traditional": "Herrera", + "unknown1": "Herrera", + "unknown2": "Herrera", + "unknown3": "Herrera", + "unknown4": "Herrera" + }, + "coordinates": { + "latitude": 7.9650878, + "longitude": -80.430637446 + } + }, + { + "id": 671678464, + "name": "Los Santos", + "translations": { + "japanese": "ロス・サントス", + "english": "Los Santos", + "french": "Los Santos", + "german": "Los Santos", + "italian": "Los Santos", + "spanish": "Los Santos", + "chinese_simple": "洛斯桑托斯省", + "korean": "로스 산토스", + "dutch": "Los Santos", + "portuguese": "Los Santos", + "russian": "Лос-Сантос", + "chinese_traditional": "Los Santos", + "unknown1": "Los Santos", + "unknown2": "Los Santos", + "unknown3": "Los Santos", + "unknown4": "Los Santos" + }, + "coordinates": { + "latitude": 7.7618407320000005, + "longitude": -80.28232161300001 + } + }, + { + "id": 671744000, + "name": "Kuna Yala", + "translations": { + "japanese": "サンブラス諸島", + "english": "Kuna Yala", + "french": "Kuna Yala", + "german": "Kuna Yala", + "italian": "Kuna Yala", + "spanish": "Kuna Yala", + "chinese_simple": "圣布拉斯特区", + "korean": "산블라스 제도", + "dutch": "San Blas-eilanden", + "portuguese": "Kuna Yala", + "russian": "Куна-Яла", + "chinese_traditional": "Kuna Yala", + "unknown1": "Kuna Yala", + "unknown2": "Kuna Yala", + "unknown3": "Kuna Yala", + "unknown4": "Kuna Yala" + }, + "coordinates": { + "latitude": 9.563598524, + "longitude": -78.952972295 + } + }, + { + "id": 671809536, + "name": "Veraguas", + "translations": { + "japanese": "ベラグアス", + "english": "Veraguas", + "french": "Veraguas", + "german": "Veraguas", + "italian": "Veraguas", + "spanish": "Veraguas", + "chinese_simple": "贝拉瓜斯省", + "korean": "베라과스", + "dutch": "Veraguas", + "portuguese": "Veraguas", + "russian": "Верагуас", + "chinese_traditional": "Veraguas", + "unknown1": "Veraguas", + "unknown2": "Veraguas", + "unknown3": "Veraguas", + "unknown4": "Veraguas" + }, + "coordinates": { + "latitude": 8.096923736, + "longitude": -80.979955346 + } + } + ] + }, + { + "id": 41, + "iso_code": "PY", + "name": "Paraguay", + "translations": { + "japanese": "パラグアイ", + "english": "Paraguay", + "french": "Paraguay", + "german": "Paraguay", + "italian": "Paraguay", + "spanish": "Paraguay", + "chinese_simple": "巴拉圭", + "korean": "파라과이", + "dutch": "Paraguay", + "portuguese": "Paraguai", + "russian": "Парагвай", + "chinese_traditional": "Paraguay", + "unknown1": "Paraguay", + "unknown2": "Paraguay", + "unknown3": "Paraguay", + "unknown4": "Paraguay" + }, + "regions": [ + { + "id": 687865856, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": -25.263062259999998, + "longitude": -57.661410491 + } + }, + { + "id": 687996928, + "name": "Central", + "translations": { + "japanese": "セントラル県", + "english": "Central", + "french": "Central", + "german": "Central", + "italian": "Central", + "spanish": "Central", + "chinese_simple": "中央省", + "korean": "센트랄 주", + "dutch": "Central", + "portuguese": "Central", + "russian": "Сентраль", + "chinese_traditional": "Central", + "unknown1": "Central", + "unknown2": "Central", + "unknown3": "Central", + "unknown4": "Central" + }, + "coordinates": { + "latitude": -25.263062259999998, + "longitude": -57.661410491 + } + }, + { + "id": 688062464, + "name": "Alto Paraná", + "translations": { + "japanese": "アルト・パラナ県", + "english": "Alto Paraná", + "french": "Alto Paraná", + "german": "Alto Paraná", + "italian": "Alto Paraná", + "spanish": "Alto Paraná", + "chinese_simple": "上巴拉那省", + "korean": "알토파라나 주", + "dutch": "Alto Paraná", + "portuguese": "Alto Paraná", + "russian": "Альто-Парана", + "chinese_traditional": "Alto Paraná", + "unknown1": "Alto Paraná", + "unknown2": "Alto Paraná", + "unknown3": "Alto Paraná", + "unknown4": "Alto Paraná" + }, + "coordinates": { + "latitude": -25.499268311999998, + "longitude": -54.832423305999995 + } + }, + { + "id": 688128000, + "name": "Amambay", + "translations": { + "japanese": "アマンバイ県", + "english": "Amambay", + "french": "Amambay", + "german": "Amambay", + "italian": "Amambay", + "spanish": "Amambay", + "chinese_simple": "阿曼拜省", + "korean": "아맘바이 주", + "dutch": "Amambay", + "portuguese": "Amambay", + "russian": "Амамбай", + "chinese_traditional": "Amambay", + "unknown1": "Amambay", + "unknown2": "Amambay", + "unknown3": "Amambay", + "unknown4": "Amambay" + }, + "coordinates": { + "latitude": -22.999878691999996, + "longitude": -55.996977254 + } + }, + { + "id": 688193536, + "name": "Caaguazú", + "translations": { + "japanese": "カアグアスー県", + "english": "Caaguazú", + "french": "Caaguazú", + "german": "Caaguazú", + "italian": "Caaguazú", + "spanish": "Caaguazú", + "chinese_simple": "卡瓜苏省", + "korean": "카아과수 주", + "dutch": "Caaguazú", + "portuguese": "Caaguazú", + "russian": "Каагуасу", + "chinese_traditional": "Caaguazú", + "unknown1": "Caaguazú", + "unknown2": "Caaguazú", + "unknown3": "Caaguazú", + "unknown4": "Caaguazú" + }, + "coordinates": { + "latitude": -25.411377688, + "longitude": -56.44741793200001 + } + }, + { + "id": 688259072, + "name": "Caazapá", + "translations": { + "japanese": "カアサパ県", + "english": "Caazapá", + "french": "Caazapá", + "german": "Caazapá", + "italian": "Caazapá", + "spanish": "Caazapá", + "chinese_simple": "卡萨帕省", + "korean": "카아사파 주", + "dutch": "Caazapá", + "portuguese": "Caazapá", + "russian": "Каасапа", + "chinese_traditional": "Caazapá", + "unknown1": "Caazapá", + "unknown2": "Caazapá", + "unknown3": "Caazapá", + "unknown4": "Caazapá" + }, + "coordinates": { + "latitude": -26.163941156, + "longitude": -55.996977254 + } + }, + { + "id": 688324608, + "name": "Concepción", + "translations": { + "japanese": "コンセプシオン県", + "english": "Concepción", + "french": "Concepción", + "german": "Concepción", + "italian": "Concepción", + "spanish": "Concepción", + "chinese_simple": "康塞普西翁省", + "korean": "콘셉시온 주", + "dutch": "Concepción", + "portuguese": "Concepção", + "russian": "Консепсьон", + "chinese_traditional": "Concepción", + "unknown1": "Concepción", + "unknown2": "Concepción", + "unknown3": "Concepción", + "unknown4": "Concepción" + }, + "coordinates": { + "latitude": -23.406372828000002, + "longitude": -57.430696972999996 + } + }, + { + "id": 688390144, + "name": "Cordillera", + "translations": { + "japanese": "コルディリェラ県", + "english": "Cordillera", + "french": "Cordillera", + "german": "Cordillera", + "italian": "Cordillera", + "spanish": "Cordillera", + "chinese_simple": "科迪勒拉省", + "korean": "코르디예라 주", + "dutch": "Cordillera", + "portuguese": "Cordillera", + "russian": "Кордильера", + "chinese_traditional": "Cordillera", + "unknown1": "Cordillera", + "unknown2": "Cordillera", + "unknown3": "Cordillera", + "unknown4": "Cordillera" + }, + "coordinates": { + "latitude": -25.378418703999998, + "longitude": -57.145051665 + } + }, + { + "id": 688455680, + "name": "Guairá", + "translations": { + "japanese": "グアイラー県", + "english": "Guairá", + "french": "Guairá", + "german": "Guairá", + "italian": "Guairá", + "spanish": "Guairá", + "chinese_simple": "瓜伊拉省", + "korean": "과이라 주", + "dutch": "Guairá", + "portuguese": "Guairá", + "russian": "Гуайра", + "chinese_traditional": "Guairá", + "unknown1": "Guairá", + "unknown2": "Guairá", + "unknown3": "Guairá", + "unknown4": "Guairá" + }, + "coordinates": { + "latitude": -25.746460692, + "longitude": -56.430938395 + } + }, + { + "id": 688521216, + "name": "Itapúa", + "translations": { + "japanese": "イタプア県", + "english": "Itapúa", + "french": "Itapúa", + "german": "Itapúa", + "italian": "Itapúa", + "spanish": "Itapúa", + "chinese_simple": "伊塔普阿省", + "korean": "이타푸아 주", + "dutch": "Itapúa", + "portuguese": "Itapúa", + "russian": "Итапуа", + "chinese_traditional": "Itapúa", + "unknown1": "Itapúa", + "unknown2": "Itapúa", + "unknown3": "Itapúa", + "unknown4": "Itapúa" + }, + "coordinates": { + "latitude": -27.328491923999998, + "longitude": -55.898100032 + } + }, + { + "id": 688586752, + "name": "Misiones", + "translations": { + "japanese": "ミシオネス県", + "english": "Misiones", + "french": "Misiones", + "german": "Misiones", + "italian": "Misiones", + "spanish": "Misiones", + "chinese_simple": "米西奥内斯省", + "korean": "미시오네스 주", + "dutch": "Misiones", + "portuguese": "Misiones", + "russian": "Мисьонес", + "chinese_traditional": "Misiones", + "unknown1": "Misiones", + "unknown2": "Misiones", + "unknown3": "Misiones", + "unknown4": "Misiones" + }, + "coordinates": { + "latitude": -26.998902084, + "longitude": -56.996735832 + } + }, + { + "id": 688652288, + "name": "Ñeembucú", + "translations": { + "japanese": "ニェエンブク県", + "english": "Ñeembucú", + "french": "Ñeembucú", + "german": "Ñeembucú", + "italian": "Ñeembucú", + "spanish": "Ñeembucú", + "chinese_simple": "涅恩布库省", + "korean": "네엠부쿠 주", + "dutch": "Ñeembucú", + "portuguese": "Ñeembucú", + "russian": "Ньеэмбуку", + "chinese_traditional": "Ñeembucú", + "unknown1": "Ñeembucú", + "unknown2": "Ñeembucú", + "unknown3": "Ñeembucú", + "unknown4": "Ñeembucú" + }, + "coordinates": { + "latitude": -26.998902084, + "longitude": -57.99649441 + } + }, + { + "id": 688717824, + "name": "Paraguarí", + "translations": { + "japanese": "パラグアリ県", + "english": "Paraguarí", + "french": "Paraguarí", + "german": "Paraguarí", + "italian": "Paraguarí", + "spanish": "Paraguarí", + "chinese_simple": "巴拉瓜里省", + "korean": "파라과리 주", + "dutch": "Paraguarí", + "portuguese": "Paraguarí", + "russian": "Парагуари", + "chinese_traditional": "Paraguarí", + "unknown1": "Paraguarí", + "unknown2": "Paraguarí", + "unknown3": "Paraguarí", + "unknown4": "Paraguarí" + }, + "coordinates": { + "latitude": -25.631104248, + "longitude": -57.145051665 + } + }, + { + "id": 688783360, + "name": "Presidente Hayes", + "translations": { + "japanese": "プレジデンテ・アエス県", + "english": "Presidente Hayes", + "french": "Presidente Hayes", + "german": "Presidente Hayes", + "italian": "Presidente Hayes", + "spanish": "Presidente Hayes", + "chinese_simple": "阿耶斯总统省", + "korean": "프레시덴테아예스 주", + "dutch": "Presidente Hayes", + "portuguese": "Presidente Hayes", + "russian": "Пресиденте-Аес", + "chinese_traditional": "Presidente Hayes", + "unknown1": "Presidente Hayes", + "unknown2": "Presidente Hayes", + "unknown3": "Presidente Hayes", + "unknown4": "Presidente Hayes" + }, + "coordinates": { + "latitude": -23.499756616, + "longitude": -58.831457618 + } + }, + { + "id": 688848896, + "name": "San Pedro", + "translations": { + "japanese": "サン・ペドロ県", + "english": "San Pedro", + "french": "San Pedro", + "german": "San Pedro", + "italian": "San Pedro", + "spanish": "San Pedro", + "chinese_simple": "圣佩德罗省", + "korean": "산페드로 주", + "dutch": "San Pedro", + "portuguese": "San Pedro", + "russian": "Сан-Педро", + "chinese_traditional": "San Pedro", + "unknown1": "San Pedro", + "unknown2": "San Pedro", + "unknown3": "San Pedro", + "unknown4": "San Pedro" + }, + "coordinates": { + "latitude": -24.098511492, + "longitude": -57.079133517 + } + }, + { + "id": 688914432, + "name": "Canindeyú", + "translations": { + "japanese": "カニンデジュ県", + "english": "Canindeyú", + "french": "Canindeyú", + "german": "Canindeyú", + "italian": "Canindeyú", + "spanish": "Canindeyú", + "chinese_simple": "卡宁迪尤省", + "korean": "카넨디유 주", + "dutch": "Canindeyú", + "portuguese": "Canindeyú", + "russian": "Канендию", + "chinese_traditional": "Canindeyú", + "unknown1": "Canindeyú", + "unknown2": "Canindeyú", + "unknown3": "Canindeyú", + "unknown4": "Canindeyú" + }, + "coordinates": { + "latitude": -24.049073015999994, + "longitude": -54.349023554 + } + }, + { + "id": 688979968, + "name": "Asunción", + "translations": { + "japanese": "アスンシオン市", + "english": "Asunción", + "french": "Asunción", + "german": "Asunción D.C.", + "italian": "Asunción", + "spanish": "Asunción", + "chinese_simple": "亚松森首都特别区", + "korean": "아순시온", + "dutch": "Asunción", + "portuguese": "Assunção", + "russian": "Асунсьон", + "chinese_traditional": "Asunción", + "unknown1": "Asunción", + "unknown2": "Asunción", + "unknown3": "Asunción", + "unknown4": "Asunción" + }, + "coordinates": { + "latitude": -25.263062259999998, + "longitude": -57.661410491 + } + }, + { + "id": 689045504, + "name": "Alto Paraguay", + "translations": { + "japanese": "アルト・パラグアイ県", + "english": "Alto Paraguay", + "french": "Alto Paraguay", + "german": "Alto Paraguay", + "italian": "Alto Paraguay", + "spanish": "Alto Paraguay", + "chinese_simple": "上巴拉圭省", + "korean": "알토파라과이 주", + "dutch": "Alto Paraguay", + "portuguese": "Alto Paraguai", + "russian": "Альто-Парагвай", + "chinese_traditional": "Alto Paraguay", + "unknown1": "Alto Paraguay", + "unknown2": "Alto Paraguay", + "unknown3": "Alto Paraguay", + "unknown4": "Alto Paraguay" + }, + "coordinates": { + "latitude": -21.03332598, + "longitude": -57.897617188 + } + }, + { + "id": 689111040, + "name": "Boquerón", + "translations": { + "japanese": "ボケロン県", + "english": "Boquerón", + "french": "Boquerón", + "german": "Boquerón", + "italian": "Boquerón", + "spanish": "Boquerón", + "chinese_simple": "博克龙省", + "korean": "보케론 주", + "dutch": "Boquerón", + "portuguese": "Boquerón", + "russian": "Бокерон", + "chinese_traditional": "Boquerón", + "unknown1": "Boquerón", + "unknown2": "Boquerón", + "unknown3": "Boquerón", + "unknown4": "Boquerón" + }, + "coordinates": { + "latitude": -22.346192176000002, + "longitude": -60.02897064 + } + } + ] + }, + { + "id": 42, + "iso_code": "PE", + "name": "Peru", + "translations": { + "japanese": "ペルー", + "english": "Peru", + "french": "Pérou", + "german": "Peru", + "italian": "Perù", + "spanish": "Perú", + "chinese_simple": "秘鲁", + "korean": "페루", + "dutch": "Peru", + "portuguese": "Peru", + "russian": "Перу", + "chinese_traditional": "Peru", + "unknown1": "Peru", + "unknown2": "Peru", + "unknown3": "Peru", + "unknown4": "Peru" + }, + "regions": [ + { + "id": 704643072, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": -12.046509676, + "longitude": -77.046839182 + } + }, + { + "id": 704774144, + "name": "Lima", + "translations": { + "japanese": "リマ", + "english": "Lima", + "french": "Province de Lima", + "german": "Lima Metropolitana", + "italian": "Lima", + "spanish": "Lima", + "chinese_simple": "利马省", + "korean": "리마", + "dutch": "Lima", + "portuguese": "Lima", + "russian": "Лима", + "chinese_traditional": "Lima", + "unknown1": "Lima", + "unknown2": "Lima", + "unknown3": "Lima", + "unknown4": "Lima" + }, + "coordinates": { + "latitude": -12.046509676, + "longitude": -77.046839182 + } + }, + { + "id": 704839680, + "name": "Amazonas", + "translations": { + "japanese": "アマソナス", + "english": "Amazonas", + "french": "Amazone", + "german": "Amazonas", + "italian": "Amazonas", + "spanish": "Amazonas", + "chinese_simple": "亚马孙省", + "korean": "아마소나스", + "dutch": "Amazonas", + "portuguese": "Amazonas", + "russian": "Амасонас", + "chinese_traditional": "Amazonas", + "unknown1": "Amazonas", + "unknown2": "Amazonas", + "unknown3": "Amazonas", + "unknown4": "Amazonas" + }, + "coordinates": { + "latitude": -6.212769507999994, + "longitude": -77.848843316 + } + }, + { + "id": 704905216, + "name": "Ancash", + "translations": { + "japanese": "アンカッシュ", + "english": "Ancash", + "french": "Ancash", + "german": "Ancash", + "italian": "Ancash", + "spanish": "Ancash", + "chinese_simple": "安卡什省", + "korean": "앙카시", + "dutch": "Ancash", + "portuguese": "Ancash", + "russian": "Анкаш", + "chinese_traditional": "Ancash", + "unknown1": "Ancash", + "unknown2": "Ancash", + "unknown3": "Ancash", + "unknown4": "Ancash" + }, + "coordinates": { + "latitude": -9.530640563999995, + "longitude": -77.530238934 + } + }, + { + "id": 704970752, + "name": "Apurímac", + "translations": { + "japanese": "アプリマック", + "english": "Apurímac", + "french": "Apurímac", + "german": "Apurímac", + "italian": "Apurímac", + "spanish": "Apurímac", + "chinese_simple": "阿普里马克省", + "korean": "아푸리막", + "dutch": "Apurímac", + "portuguese": "Apurímac", + "russian": "Апуримак", + "chinese_traditional": "Apurímac", + "unknown1": "Apurímac", + "unknown2": "Apurímac", + "unknown3": "Apurímac", + "unknown4": "Apurímac" + }, + "coordinates": { + "latitude": -13.628540908000005, + "longitude": -72.877516321 + } + }, + { + "id": 705036288, + "name": "Arequipa", + "translations": { + "japanese": "アレキパ", + "english": "Arequipa", + "french": "Arequipa", + "german": "Arequipa", + "italian": "Arequipa", + "spanish": "Arequipa", + "chinese_simple": "阿雷基帕省", + "korean": "아레키파", + "dutch": "Arequipa", + "portuguese": "Arequipa", + "russian": "Арекипа", + "chinese_traditional": "Arequipa", + "unknown1": "Arequipa", + "unknown2": "Arequipa", + "unknown3": "Arequipa", + "unknown4": "Arequipa" + }, + "coordinates": { + "latitude": -16.397095563999997, + "longitude": -71.53168746600001 + } + }, + { + "id": 705101824, + "name": "Ayacucho", + "translations": { + "japanese": "アヤクーチョ", + "english": "Ayacucho", + "french": "Ayacucho", + "german": "Ayacucho", + "italian": "Ayacucho", + "spanish": "Ayacucho", + "chinese_simple": "阿亚库乔省", + "korean": "아야쿠초", + "dutch": "Ayacucho", + "portuguese": "Ayacucho", + "russian": "Аякучо", + "chinese_traditional": "Ayacucho", + "unknown1": "Ayacucho", + "unknown2": "Ayacucho", + "unknown3": "Ayacucho", + "unknown4": "Ayacucho" + }, + "coordinates": { + "latitude": -13.156128804000005, + "longitude": -74.223345176 + } + }, + { + "id": 705167360, + "name": "Cajamarca", + "translations": { + "japanese": "カハマルカ", + "english": "Cajamarca", + "french": "Cajamarca", + "german": "Cajamarca", + "italian": "Cajamarca", + "spanish": "Cajamarca", + "chinese_simple": "卡哈马卡省", + "korean": "카하마르카", + "dutch": "Cajamarca", + "portuguese": "Cajamarca", + "russian": "Кахамарка", + "chinese_traditional": "Cajamarca", + "unknown1": "Cajamarca", + "unknown2": "Cajamarca", + "unknown3": "Cajamarca", + "unknown4": "Cajamarca" + }, + "coordinates": { + "latitude": -7.1630868799999945, + "longitude": -78.513517975 + } + }, + { + "id": 705232896, + "name": "Callao", + "translations": { + "japanese": "カヤオ", + "english": "Callao", + "french": "Callao", + "german": "Callao", + "italian": "Callao", + "spanish": "Callao", + "chinese_simple": "卡亚俄区", + "korean": "카야오", + "dutch": "Callao", + "portuguese": "Callao", + "russian": "Кальяо", + "chinese_traditional": "Callao", + "unknown1": "Callao", + "unknown2": "Callao", + "unknown3": "Callao", + "unknown4": "Callao" + }, + "coordinates": { + "latitude": -12.062989168000001, + "longitude": -77.145716404 + } + }, + { + "id": 705298432, + "name": "Cuzco", + "translations": { + "japanese": "クスコ", + "english": "Cuzco", + "french": "Cuzco", + "german": "Cusco", + "italian": "Cusco", + "spanish": "Cuzco", + "chinese_simple": "库斯科省", + "korean": "쿠스코", + "dutch": "Cuzco", + "portuguese": "Cuzco", + "russian": "Куско", + "chinese_traditional": "Cuzco", + "unknown1": "Cuzco", + "unknown2": "Cuzco", + "unknown3": "Cuzco", + "unknown4": "Cuzco" + }, + "coordinates": { + "latitude": -13.513184464000005, + "longitude": -71.976634965 + } + }, + { + "id": 705363968, + "name": "Huancavelica", + "translations": { + "japanese": "ワンカベリカ", + "english": "Huancavelica", + "french": "Huancavelica", + "german": "Huancavelica", + "italian": "Huancavelica", + "spanish": "Huancavelica", + "chinese_simple": "万卡韦利卡省", + "korean": "우앙카벨리카", + "dutch": "Huancavelica", + "portuguese": "Huancavelica", + "russian": "Уанкавелика", + "chinese_traditional": "Huancavelica", + "unknown1": "Huancavelica", + "unknown2": "Huancavelica", + "unknown3": "Huancavelica", + "unknown4": "Huancavelica" + }, + "coordinates": { + "latitude": -12.76611416, + "longitude": -74.981403878 + } + }, + { + "id": 705429504, + "name": "Huánuco", + "translations": { + "japanese": "ワヌコ", + "english": "Huánuco", + "french": "Huánuco", + "german": "Huánuco", + "italian": "Huánuco", + "spanish": "Huánuco", + "chinese_simple": "瓦努科省", + "korean": "우아누코", + "dutch": "Huánuco", + "portuguese": "Huánuco", + "russian": "Уануко", + "chinese_traditional": "Huánuco", + "unknown1": "Huánuco", + "unknown2": "Huánuco", + "unknown3": "Huánuco", + "unknown4": "Huánuco" + }, + "coordinates": { + "latitude": -9.915162043999999, + "longitude": -76.228355511 + } + }, + { + "id": 705495040, + "name": "Ica", + "translations": { + "japanese": "イカ", + "english": "Ica", + "french": "Ica", + "german": "Ica", + "italian": "Ica", + "spanish": "Ica", + "chinese_simple": "伊卡省", + "korean": "이카", + "dutch": "Ica", + "portuguese": "Ica", + "russian": "Ика", + "chinese_traditional": "Ica", + "unknown1": "Ica", + "unknown2": "Ica", + "unknown3": "Ica", + "unknown4": "Ica" + }, + "coordinates": { + "latitude": -14.067994028000001, + "longitude": -75.722983043 + } + }, + { + "id": 705560576, + "name": "Junín", + "translations": { + "japanese": "フニン", + "english": "Junín", + "french": "Junín", + "german": "Junín", + "italian": "Junín", + "spanish": "Junín", + "chinese_simple": "胡宁省", + "korean": "후닌", + "dutch": "Junín", + "portuguese": "Junín", + "russian": "Хунин", + "chinese_traditional": "Junín", + "unknown1": "Junín", + "unknown2": "Junín", + "unknown3": "Junín", + "unknown4": "Junín" + }, + "coordinates": { + "latitude": -12.062989168000001, + "longitude": -75.228596933 + } + }, + { + "id": 705626112, + "name": "La Libertad", + "translations": { + "japanese": "ラ・リベルター", + "english": "La Libertad", + "french": "La Libertad", + "german": "La Libertad", + "italian": "La Libertad", + "spanish": "La Libertad", + "chinese_simple": "拉利伯塔德省", + "korean": "라리베르타드", + "dutch": "La Libertad", + "portuguese": "La Libertad", + "russian": "Ла-Либертад", + "chinese_traditional": "La Libertad", + "unknown1": "La Libertad", + "unknown2": "La Libertad", + "unknown3": "La Libertad", + "unknown4": "La Libertad" + }, + "coordinates": { + "latitude": -8.107911087999994, + "longitude": -79.024383622 + } + }, + { + "id": 705691648, + "name": "Lambayeque", + "translations": { + "japanese": "ランバイェケ", + "english": "Lambayeque", + "french": "Lambayeque", + "german": "Lambayeque", + "italian": "Lambayeque", + "spanish": "Lambayeque", + "chinese_simple": "兰巴耶克省", + "korean": "람바예케", + "dutch": "Lambayeque", + "portuguese": "Lambayeque", + "russian": "Ламбайеке", + "chinese_traditional": "Lambayeque", + "unknown1": "Lambayeque", + "unknown2": "Lambayeque", + "unknown3": "Lambayeque", + "unknown4": "Lambayeque" + }, + "coordinates": { + "latitude": -6.773072236000004, + "longitude": -79.837374114 + } + }, + { + "id": 705757184, + "name": "Loreto", + "translations": { + "japanese": "ロレト", + "english": "Loreto", + "french": "Loreto", + "german": "Loreto", + "italian": "Loreto", + "spanish": "Loreto", + "chinese_simple": "洛雷托省", + "korean": "로레토", + "dutch": "Loreto", + "portuguese": "Loreto", + "russian": "Лорето", + "chinese_traditional": "Loreto", + "unknown1": "Loreto", + "unknown2": "Loreto", + "unknown3": "Loreto", + "unknown4": "Loreto" + }, + "coordinates": { + "latitude": -3.7463388719999955, + "longitude": -73.245559314 + } + }, + { + "id": 705822720, + "name": "Madre de Dios", + "translations": { + "japanese": "マドレ・デ・ディオス", + "english": "Madre de Dios", + "french": "Madre de Dios", + "german": "Madre de Dios", + "italian": "Madre de Dios", + "spanish": "Madre de Dios", + "chinese_simple": "马德雷德迪奥斯省", + "korean": "마드레데디오스", + "dutch": "Madre de Dios", + "portuguese": "Madre de Dios", + "russian": "Мадре-де-Диос", + "chinese_traditional": "Madre de Dios", + "unknown1": "Madre de Dios", + "unknown2": "Madre de Dios", + "unknown3": "Madre de Dios", + "unknown4": "Madre de Dios" + }, + "coordinates": { + "latitude": -12.595826075999994, + "longitude": -69.180606854 + } + }, + { + "id": 705888256, + "name": "Moquegua", + "translations": { + "japanese": "モケグア", + "english": "Moquegua", + "french": "Moquegua", + "german": "Moquegua", + "italian": "Moquegua", + "spanish": "Moquegua", + "chinese_simple": "莫克瓜省", + "korean": "모케과", + "dutch": "Moquegua", + "portuguese": "Moquegua", + "russian": "Мокегуа", + "chinese_traditional": "Moquegua", + "unknown1": "Moquegua", + "unknown2": "Moquegua", + "unknown3": "Moquegua", + "unknown4": "Moquegua" + }, + "coordinates": { + "latitude": -17.193604343999993, + "longitude": -70.932930955 + } + }, + { + "id": 705953792, + "name": "Pasco", + "translations": { + "japanese": "パスコ", + "english": "Pasco", + "french": "Pasco", + "german": "Pasco", + "italian": "Pasco", + "spanish": "Pasco", + "chinese_simple": "帕斯科省", + "korean": "파스코", + "dutch": "Pasco", + "portuguese": "Pasco", + "russian": "Паско", + "chinese_traditional": "Pasco", + "unknown1": "Pasco", + "unknown2": "Pasco", + "unknown3": "Pasco", + "unknown4": "Pasco" + }, + "coordinates": { + "latitude": -10.678711840000005, + "longitude": -76.26131458500001 + } + }, + { + "id": 706019328, + "name": "Piura", + "translations": { + "japanese": "ピウラ", + "english": "Piura", + "french": "Piura", + "german": "Piura", + "italian": "Piura", + "spanish": "Piura", + "chinese_simple": "皮乌拉省", + "korean": "피우라", + "dutch": "Piura", + "portuguese": "Piura", + "russian": "Пиура", + "chinese_traditional": "Piura", + "unknown1": "Piura", + "unknown2": "Piura", + "unknown3": "Piura", + "unknown4": "Piura" + }, + "coordinates": { + "latitude": -5.1965341679999995, + "longitude": -80.62839189 + } + }, + { + "id": 706084864, + "name": "Puno", + "translations": { + "japanese": "プーノ", + "english": "Puno", + "french": "Puno", + "german": "Puno", + "italian": "Puno", + "spanish": "Puno", + "chinese_simple": "普诺省", + "korean": "푸노", + "dutch": "Puno", + "portuguese": "Puno", + "russian": "Пуно", + "chinese_traditional": "Puno", + "unknown1": "Puno", + "unknown2": "Puno", + "unknown3": "Puno", + "unknown4": "Puno" + }, + "coordinates": { + "latitude": -15.831299672, + "longitude": -70.032049599 + } + }, + { + "id": 706150400, + "name": "San Martín", + "translations": { + "japanese": "サン・マルティン", + "english": "San Martín", + "french": "San Martín", + "german": "San Martín", + "italian": "San Martín", + "spanish": "San Martín", + "chinese_simple": "圣马丁省", + "korean": "산마르틴", + "dutch": "San Martín", + "portuguese": "San Martín", + "russian": "Сан-Мартин", + "chinese_traditional": "San Martín", + "unknown1": "San Martín", + "unknown2": "San Martín", + "unknown3": "San Martín", + "unknown4": "San Martín" + }, + "coordinates": { + "latitude": -6.047974588000002, + "longitude": -76.964441497 + } + }, + { + "id": 706215936, + "name": "Tacna", + "translations": { + "japanese": "タクナ", + "english": "Tacna", + "french": "Tacna", + "german": "Tacna", + "italian": "Tacna", + "spanish": "Tacna", + "chinese_simple": "塔克纳省", + "korean": "타크나", + "dutch": "Tacna", + "portuguese": "Tacna", + "russian": "Такна", + "chinese_traditional": "Tacna", + "unknown1": "Tacna", + "unknown2": "Tacna", + "unknown3": "Tacna", + "unknown4": "Tacna" + }, + "coordinates": { + "latitude": -18.001099452000005, + "longitude": -70.24628358 + } + }, + { + "id": 706281472, + "name": "Tumbes", + "translations": { + "japanese": "トゥンベス", + "english": "Tumbes", + "french": "Tumbes", + "german": "Tumbes", + "italian": "Tumbes", + "spanish": "Tumbes", + "chinese_simple": "通贝斯省", + "korean": "툼베스", + "dutch": "Tumbes", + "portuguese": "Tumbes", + "russian": "Тумбес", + "chinese_traditional": "Tumbes", + "unknown1": "Tumbes", + "unknown2": "Tumbes", + "unknown3": "Tumbes", + "unknown4": "Tumbes" + }, + "coordinates": { + "latitude": -3.565064460000002, + "longitude": -80.436130625 + } + }, + { + "id": 706347008, + "name": "Ucayali", + "translations": { + "japanese": "ウカヤリ", + "english": "Ucayali", + "french": "Ucayali", + "german": "Ucayali", + "italian": "Ucayali", + "spanish": "Ucayali", + "chinese_simple": "乌卡亚利省", + "korean": "우카얄리", + "dutch": "Ucayali", + "portuguese": "Ucayali", + "russian": "Укаяли", + "chinese_traditional": "Ucayali", + "unknown1": "Ucayali", + "unknown2": "Ucayali", + "unknown3": "Ucayali", + "unknown4": "Ucayali" + }, + "coordinates": { + "latitude": -8.377076123999998, + "longitude": -74.536456379 + } + } + ] + }, + { + "id": 43, + "iso_code": "KN", + "name": "St. Kitts and Nevis", + "translations": { + "japanese": "セントキッツ・ネイビス", + "english": "St. Kitts and Nevis", + "french": "Saint-Christophe-et-Niévès", + "german": "St. Kitts und Nevis", + "italian": "Saint Kitts e Nevis", + "spanish": "San Cristóbal y Nieves", + "chinese_simple": "圣基茨和尼维斯", + "korean": "세인트키츠네비스", + "dutch": "Saint Kitts en Nevis", + "portuguese": "São Cristóvão e Nevis", + "russian": "Сент-Китс и Невис", + "chinese_traditional": "St. Kitts and Nevis", + "unknown1": "St. Kitts and Nevis", + "unknown2": "St. Kitts and Nevis", + "unknown3": "St. Kitts and Nevis", + "unknown4": "St. Kitts and Nevis" + }, + "regions": [ + { + "id": 721420288, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 17.297973436, + "longitude": -62.715135171 + } + }, + { + "id": 721551360, + "name": "Saint George Basseterre", + "translations": { + "japanese": "セント・ジョージ・バセテール", + "english": "Saint George Basseterre", + "french": "Saint George Basseterre", + "german": "Saint George Basseterre", + "italian": "Saint George Basseterre", + "spanish": "Saint George Basseterre", + "chinese_simple": "圣乔治巴斯特尔区", + "korean": "세인트조지바스테르", + "dutch": "Saint George Basseterre", + "portuguese": "Saint George Basseterre", + "russian": "Сент-Джордж-Бастер", + "chinese_traditional": "Saint George Basseterre", + "unknown1": "Saint George Basseterre", + "unknown2": "Saint George Basseterre", + "unknown3": "Saint George Basseterre", + "unknown4": "Saint George Basseterre" + }, + "coordinates": { + "latitude": 17.297973436, + "longitude": -62.715135171 + } + }, + { + "id": 721616896, + "name": "Christ Church Nichola Town", + "translations": { + "japanese": "クライスト・チャーチ・ニコラタウン", + "english": "Christ Church Nichola Town", + "french": "Christ Church Nichola Town", + "german": "Christ Church Nichola Town", + "italian": "Christ Church Nichola Town", + "spanish": "Christ Church Nichola Town", + "chinese_simple": "克赖斯特彻奇尼古拉镇区", + "korean": "크라이스트처치니콜라타운", + "dutch": "Christ Church Nichola Town", + "portuguese": "Christ Church Nichola Town", + "russian": "Крайст-Чёрч-Никола-Таун", + "chinese_traditional": "Christ Church Nichola Town", + "unknown1": "Christ Church Nichola Town", + "unknown2": "Christ Church Nichola Town", + "unknown3": "Christ Church Nichola Town", + "unknown4": "Christ Church Nichola Town" + }, + "coordinates": { + "latitude": 17.363891404, + "longitude": -62.748094245000004 + } + }, + { + "id": 721682432, + "name": "Saint Anne Sandy Point", + "translations": { + "japanese": "セント・アン・サンディ・ポイント", + "english": "Saint Anne Sandy Point", + "french": "Saint Anne Sandy Point", + "german": "Saint Anne Sandy Point", + "italian": "Saint Anne Sandy Point", + "spanish": "Saint Anne Sandy Point", + "chinese_simple": "圣安妮桑迪波因特区", + "korean": "세인트앤샌디포인트", + "dutch": "Saint Anne Sandy Point", + "portuguese": "Saint Anne Sandy Point", + "russian": "Сент-Энн-Сэнди-Пойнт", + "chinese_traditional": "Saint Anne Sandy Point", + "unknown1": "Saint Anne Sandy Point", + "unknown2": "Saint Anne Sandy Point", + "unknown3": "Saint Anne Sandy Point", + "unknown4": "Saint Anne Sandy Point" + }, + "coordinates": { + "latitude": 17.347411912000002, + "longitude": -62.83049193000001 + } + }, + { + "id": 721747968, + "name": "Saint George Gingerland", + "translations": { + "japanese": "セント・ジョージ・ジンジャーランド", + "english": "Saint George Gingerland", + "french": "Saint George Gingerland", + "german": "Saint George Gingerland", + "italian": "Saint George Gingerland", + "spanish": "Saint George Gingerland", + "chinese_simple": "圣乔治金杰兰区", + "korean": "세인트조지진저랜드", + "dutch": "Saint George Gingerland", + "portuguese": "Saint George Gingerland", + "russian": "Сент-Джордж-Джинджерланд", + "chinese_traditional": "Saint George Gingerland", + "unknown1": "Saint George Gingerland", + "unknown2": "Saint George Gingerland", + "unknown3": "Saint George Gingerland", + "unknown4": "Saint George Gingerland" + }, + "coordinates": { + "latitude": 17.133178516, + "longitude": -62.544846621999994 + } + }, + { + "id": 721813504, + "name": "Saint James Windward", + "translations": { + "japanese": "セント・ジェームズ・ウィンドワード", + "english": "Saint James Windward", + "french": "Saint James Windward", + "german": "Saint James Windward", + "italian": "Saint James Windward", + "spanish": "Saint James Windward", + "chinese_simple": "圣詹姆斯温德沃德区", + "korean": "세인트제임스윈드워드", + "dutch": "Saint James Windward", + "portuguese": "Saint James Windward", + "russian": "Сент-Джеймс-Уиндуорд", + "chinese_traditional": "Saint James Windward", + "unknown1": "Saint James Windward", + "unknown2": "Saint James Windward", + "unknown3": "Saint James Windward", + "unknown4": "Saint James Windward" + }, + "coordinates": { + "latitude": 17.199096484000002, + "longitude": -62.577805696 + } + }, + { + "id": 721879040, + "name": "Saint John Capesterre", + "translations": { + "japanese": "セント・ジョン・カピステール", + "english": "Saint John Capesterre", + "french": "Saint John Capesterre", + "german": "Saint John Capisterre", + "italian": "Saint John Capisterre", + "spanish": "Saint John Capesterre", + "chinese_simple": "圣约翰卡皮斯特尔区", + "korean": "세인트존카페스테르", + "dutch": "Saint John Capesterre", + "portuguese": "Saint John Capesterre", + "russian": "Сент-Джон-Капистер", + "chinese_traditional": "Saint John Capesterre", + "unknown1": "Saint John Capesterre", + "unknown2": "Saint John Capesterre", + "unknown3": "Saint John Capesterre", + "unknown4": "Saint John Capesterre" + }, + "coordinates": { + "latitude": 17.396850388, + "longitude": -62.781053318999994 + } + }, + { + "id": 721944576, + "name": "Saint John Figtree", + "translations": { + "japanese": "セント・ジョン・フィッグトリー", + "english": "Saint John Figtree", + "french": "Saint John Figtree", + "german": "Saint John Figtree", + "italian": "Saint John Figtree", + "spanish": "Saint John Figtree", + "chinese_simple": "圣约翰菲格特里区", + "korean": "세인트존피그트리", + "dutch": "Saint John Figtree", + "portuguese": "Saint John Figtree", + "russian": "Сент-Джон-Фигтри", + "chinese_traditional": "Saint John Figtree", + "unknown1": "Saint John Figtree", + "unknown2": "Saint John Figtree", + "unknown3": "Saint John Figtree", + "unknown4": "Saint John Figtree" + }, + "coordinates": { + "latitude": 17.111205860000002, + "longitude": -62.59428523300001 + } + }, + { + "id": 722010112, + "name": "Saint Mary Cayon", + "translations": { + "japanese": "セント・メリー・ケーヨン", + "english": "Saint Mary Cayon", + "french": "Saint Mary Cayon", + "german": "Saint Mary Cayon", + "italian": "Saint Mary Cayon", + "spanish": "Saint Mary Cayon", + "chinese_simple": "圣玛丽卡永区", + "korean": "세인트메리케이언", + "dutch": "Saint Mary Cayon", + "portuguese": "Saint Mary Cayon", + "russian": "Сент-Мери-Кайон", + "chinese_traditional": "Saint Mary Cayon", + "unknown1": "Saint Mary Cayon", + "unknown2": "Saint Mary Cayon", + "unknown3": "Saint Mary Cayon", + "unknown4": "Saint Mary Cayon" + }, + "coordinates": { + "latitude": 17.347411912000002, + "longitude": -62.731614707999995 + } + }, + { + "id": 722075648, + "name": "Saint Paul Capesterre", + "translations": { + "japanese": "セント・ポール・カピステール", + "english": "Saint Paul Capesterre", + "french": "Saint Paul Capesterre", + "german": "Saint Paul Capisterre", + "italian": "Saint Paul Capisterre", + "spanish": "Saint Paul Capesterre", + "chinese_simple": "圣保罗卡皮斯特尔区", + "korean": "세인트폴카페스테르", + "dutch": "Saint Paul Capesterre", + "portuguese": "Saint Paul Capesterre", + "russian": "Сент-Пол-Капистер", + "chinese_traditional": "Saint Paul Capesterre", + "unknown1": "Saint Paul Capesterre", + "unknown2": "Saint Paul Capesterre", + "unknown3": "Saint Paul Capesterre", + "unknown4": "Saint Paul Capesterre" + }, + "coordinates": { + "latitude": 17.396850388, + "longitude": -62.814012393 + } + }, + { + "id": 722141184, + "name": "Saint Paul Charlestown", + "translations": { + "japanese": "セント・ポール・チャールズタウン", + "english": "Saint Paul Charlestown", + "french": "Saint Paul Charlestown", + "german": "Saint Paul Charlestown", + "italian": "Saint Paul Charlestown", + "spanish": "Saint Paul Charlestown", + "chinese_simple": "圣保罗查尔斯敦区", + "korean": "세인트폴찰스타운", + "dutch": "Saint Paul Charlestown", + "portuguese": "Saint Paul Charlestown", + "russian": "Сент-Пол-Чарлстаун", + "chinese_traditional": "Saint Paul Charlestown", + "unknown1": "Saint Paul Charlestown", + "unknown2": "Saint Paul Charlestown", + "unknown3": "Saint Paul Charlestown", + "unknown4": "Saint Paul Charlestown" + }, + "coordinates": { + "latitude": 17.133178516, + "longitude": -62.616257949 + } + }, + { + "id": 722206720, + "name": "Saint Peter Basseterre", + "translations": { + "japanese": "セント・ピーター・バセテール", + "english": "Saint Peter Basseterre", + "french": "Saint Peter Basseterre", + "german": "Saint Peter Basseterre", + "italian": "Saint Peter Basseterre", + "spanish": "Saint Peter Basseterre", + "chinese_simple": "圣彼得巴斯特尔区", + "korean": "세인트피터바스테르", + "dutch": "Saint Peter Basseterre", + "portuguese": "Saint Peter Basseterre", + "russian": "Сент-Питер-Бастер", + "chinese_traditional": "Saint Peter Basseterre", + "unknown1": "Saint Peter Basseterre", + "unknown2": "Saint Peter Basseterre", + "unknown3": "Saint Peter Basseterre", + "unknown4": "Saint Peter Basseterre" + }, + "coordinates": { + "latitude": 17.314452928, + "longitude": -62.715135171 + } + }, + { + "id": 722272256, + "name": "Saint Thomas Lowland", + "translations": { + "japanese": "セント・トーマス・ロウランド", + "english": "Saint Thomas Lowland", + "french": "Saint Thomas Lowland", + "german": "Saint Thomas Lowland", + "italian": "Saint Thomas Lowland", + "spanish": "Saint Thomas Lowland", + "chinese_simple": "圣托马斯洛兰区", + "korean": "세인트토머스롤랜드", + "dutch": "Saint Thomas Lowland", + "portuguese": "Saint Thomas Lowland", + "russian": "Сент-Томас-Лоуленд", + "chinese_traditional": "Saint Thomas Lowland", + "unknown1": "Saint Thomas Lowland", + "unknown2": "Saint Thomas Lowland", + "unknown3": "Saint Thomas Lowland", + "unknown4": "Saint Thomas Lowland" + }, + "coordinates": { + "latitude": 17.1661375, + "longitude": -62.616257949 + } + }, + { + "id": 722337792, + "name": "Saint Thomas Middle Island", + "translations": { + "japanese": "セント・トーマス・ミドルアイランド", + "english": "Saint Thomas Middle Island", + "french": "Saint Thomas Middle Island", + "german": "Saint Thomas Middle Island", + "italian": "Saint Thomas Middle Island", + "spanish": "Saint Thomas Middle Island", + "chinese_simple": "圣托马斯米德尔艾兰区", + "korean": "세인트토머스미들아일랜드", + "dutch": "Saint Thomas Middle Island", + "portuguese": "Saint Thomas Middle Island", + "russian": "Сент-Томас-Мидл-Айленд", + "chinese_traditional": "Saint Thomas Middle Island", + "unknown1": "Saint Thomas Middle Island", + "unknown2": "Saint Thomas Middle Island", + "unknown3": "Saint Thomas Middle Island", + "unknown4": "Saint Thomas Middle Island" + }, + "coordinates": { + "latitude": 17.314452928, + "longitude": -62.814012393 + } + }, + { + "id": 722403328, + "name": "Trinity Palmetto Point", + "translations": { + "japanese": "トリニティ・パルメット・ポイント", + "english": "Trinity Palmetto Point", + "french": "Trinity Palmetto Point", + "german": "Trinity Palmetto Point", + "italian": "Trinity Palmetto Point", + "spanish": "Trinity Palmetto Point", + "chinese_simple": "特里尼蒂帕尔梅托波因特区", + "korean": "트리니티팰머토포인트", + "dutch": "Trinity Palmetto Point", + "portuguese": "Trinity Palmetto Point", + "russian": "Тринити-Палметто-Пойнт", + "chinese_traditional": "Trinity Palmetto Point", + "unknown1": "Trinity Palmetto Point", + "unknown2": "Trinity Palmetto Point", + "unknown3": "Trinity Palmetto Point", + "unknown4": "Trinity Palmetto Point" + }, + "coordinates": { + "latitude": 17.281493944, + "longitude": -62.764573782 + } + } + ] + }, + { + "id": 44, + "iso_code": "LC", + "name": "St. Lucia", + "translations": { + "japanese": "セントルシア", + "english": "St. Lucia", + "french": "Sainte-Lucie", + "german": "St. Lucia", + "italian": "Santa Lucia", + "spanish": "Santa Lucía", + "chinese_simple": "圣卢西亚", + "korean": "세인트루시아", + "dutch": "Saint Lucia", + "portuguese": "Santa Lúcia", + "russian": "Сент-Люсия", + "chinese_traditional": "St. Lucia", + "unknown1": "St. Lucia", + "unknown2": "St. Lucia", + "unknown3": "St. Lucia", + "unknown4": "St. Lucia" + }, + "regions": [ + { + "id": 738197504, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 13.996581872, + "longitude": -60.995770144000005 + } + }, + { + "id": 738263040, + "name": "St. Lucia", + "translations": { + "japanese": "セントルシア", + "english": "St. Lucia", + "french": "Sainte-Lucie", + "german": "St. Lucia", + "italian": "Santa Lucia", + "spanish": "Santa Lucía", + "chinese_simple": "圣卢西亚", + "korean": "세인트루시아", + "dutch": "Saint Lucia", + "portuguese": "Santa Lúcia", + "russian": "Сент-Люсия", + "chinese_traditional": "St. Lucia", + "unknown1": "St. Lucia", + "unknown2": "St. Lucia", + "unknown3": "St. Lucia", + "unknown4": "St. Lucia" + }, + "coordinates": { + "latitude": 13.996581872, + "longitude": -60.995770144000005 + } + } + ] + }, + { + "id": 45, + "iso_code": "VC", + "name": "St. Vincent and the Grenadines", + "translations": { + "japanese": "セントビンセント・グレナディーン", + "english": "St. Vincent and the Grenadines", + "french": "Saint-Vincent-et-les-Grenadines", + "german": "St. Vincent und die Grenadinen", + "italian": "Saint Vincent e Grenadine", + "spanish": "San Vicente y las Granadinas", + "chinese_simple": "圣文森特和格林纳丁斯", + "korean": "세인트빈센트 그레나딘", + "dutch": "Saint Vincent en de Grenadines", + "portuguese": "S. Vicente e as Granadinas", + "russian": "Сент-Винсент и Гренадины", + "chinese_traditional": "St. Vincent and the Grenadines", + "unknown1": "St. Vincent and the Grenadines", + "unknown2": "St. Vincent and the Grenadines", + "unknown3": "St. Vincent and the Grenadines", + "unknown4": "St. Vincent and the Grenadines" + }, + "regions": [ + { + "id": 754974720, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 13.12866196, + "longitude": -61.215497303999996 + } + }, + { + "id": 755040256, + "name": "St. Vincent and the Grenadines", + "translations": { + "japanese": "セントビンセント・グレナディーン", + "english": "St. Vincent and the Grenadines", + "french": "Saint-Vincent-et-les-Grenadines", + "german": "St. Vincent und die Grenadinen", + "italian": "Saint Vincent e Grenadine", + "spanish": "San Vicente y las Granadinas", + "chinese_simple": "圣文森特和格林纳丁斯", + "korean": "세인트빈센트 그레나딘", + "dutch": "Saint Vincent en de Grenadines", + "portuguese": "S. Vicente e as Granadinas", + "russian": "Сент-Винсент и Гренадины", + "chinese_traditional": "St. Vincent and the Grenadines", + "unknown1": "St. Vincent and the Grenadines", + "unknown2": "St. Vincent and the Grenadines", + "unknown3": "St. Vincent and the Grenadines", + "unknown4": "St. Vincent and the Grenadines" + }, + "coordinates": { + "latitude": 13.12866196, + "longitude": -61.215497303999996 + } + } + ] + }, + { + "id": 46, + "iso_code": "SR", + "name": "Suriname", + "translations": { + "japanese": "スリナム", + "english": "Suriname", + "french": "Suriname", + "german": "Suriname", + "italian": "Suriname", + "spanish": "Surinam", + "chinese_simple": "苏里南", + "korean": "수리남", + "dutch": "Suriname", + "portuguese": "Suriname", + "russian": "Суринам", + "chinese_traditional": "Suriname", + "unknown1": "Suriname", + "unknown2": "Suriname", + "unknown3": "Suriname", + "unknown4": "Suriname" + }, + "regions": [ + { + "id": 771751936, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 5.828247004, + "longitude": -55.162014045999996 + } + }, + { + "id": 771883008, + "name": "Paramaribo", + "translations": { + "japanese": "パラマリボ", + "english": "Paramaribo", + "french": "Paramaribo", + "german": "Paramaribo", + "italian": "Paramaribo", + "spanish": "Paramaribo", + "chinese_simple": "帕拉马里博市", + "korean": "파라마리보", + "dutch": "Paramaribo", + "portuguese": "Paramaribo", + "russian": "Парамарибо", + "chinese_traditional": "Paramaribo", + "unknown1": "Paramaribo", + "unknown2": "Paramaribo", + "unknown3": "Paramaribo", + "unknown4": "Paramaribo" + }, + "coordinates": { + "latitude": 5.828247004, + "longitude": -55.162014045999996 + } + }, + { + "id": 771948544, + "name": "Brokopondo", + "translations": { + "japanese": "ブロコポンド", + "english": "Brokopondo", + "french": "Brokopondo", + "german": "Brokopondo", + "italian": "Brokopondo", + "spanish": "Brokopondo", + "chinese_simple": "布罗科蓬多区", + "korean": "브로코폰도", + "dutch": "Brokopondo", + "portuguese": "Brokopondo", + "russian": "Брокопондо", + "chinese_traditional": "Brokopondo", + "unknown1": "Brokopondo", + "unknown2": "Brokopondo", + "unknown3": "Brokopondo", + "unknown4": "Brokopondo" + }, + "coordinates": { + "latitude": 5.064697208, + "longitude": -54.964259602 + } + }, + { + "id": 772014080, + "name": "Commewijne", + "translations": { + "japanese": "コメウィネ", + "english": "Commewijne", + "french": "Commewijne", + "german": "Commewijne", + "italian": "Commewijne", + "spanish": "Commewijne", + "chinese_simple": "科默韦讷区", + "korean": "코메베이너", + "dutch": "Commewijne", + "portuguese": "Commewijne", + "russian": "Коммевийн", + "chinese_traditional": "Commewijne", + "unknown1": "Commewijne", + "unknown2": "Commewijne", + "unknown3": "Commewijne", + "unknown4": "Commewijne" + }, + "coordinates": { + "latitude": 5.883178644, + "longitude": -55.07961636100001 + } + }, + { + "id": 772079616, + "name": "Coronie", + "translations": { + "japanese": "コロニー", + "english": "Coronie", + "french": "Coronie", + "german": "Coronie", + "italian": "Coronie", + "spanish": "Coronie", + "chinese_simple": "科罗尼区", + "korean": "코로니", + "dutch": "Coronie", + "portuguese": "Coronie", + "russian": "Корони", + "chinese_traditional": "Coronie", + "unknown1": "Coronie", + "unknown2": "Coronie", + "unknown3": "Coronie", + "unknown4": "Coronie" + }, + "coordinates": { + "latitude": 5.883178644, + "longitude": -56.315581636000005 + } + }, + { + "id": 772145152, + "name": "Marowijne", + "translations": { + "japanese": "マロウィネ", + "english": "Marowijne", + "french": "Marowijne", + "german": "Marowijne", + "italian": "Marowijne", + "spanish": "Marowijne", + "chinese_simple": "马罗韦讷区", + "korean": "마로베이너", + "dutch": "Marowijne", + "portuguese": "Marowijne", + "russian": "Маровийн", + "chinese_traditional": "Marowijne", + "unknown1": "Marowijne", + "unknown2": "Marowijne", + "unknown3": "Marowijne", + "unknown4": "Marowijne" + }, + "coordinates": { + "latitude": 5.498657164, + "longitude": -54.046898709000004 + } + }, + { + "id": 772210688, + "name": "Nickerie", + "translations": { + "japanese": "ニッケリー", + "english": "Nickerie", + "french": "Nickerie", + "german": "Nickerie", + "italian": "Nickerie", + "spanish": "Nickerie", + "chinese_simple": "尼克里区", + "korean": "니케리", + "dutch": "Nickerie", + "portuguese": "Nickerie", + "russian": "Никкери", + "chinese_traditional": "Nickerie", + "unknown1": "Nickerie", + "unknown2": "Nickerie", + "unknown3": "Nickerie", + "unknown4": "Nickerie" + }, + "coordinates": { + "latitude": 5.949096612, + "longitude": -56.980256295000004 + } + }, + { + "id": 772276224, + "name": "Para", + "translations": { + "japanese": "パラ", + "english": "Para", + "french": "Para", + "german": "Para", + "italian": "Para", + "spanish": "Para", + "chinese_simple": "帕拉区", + "korean": "파라", + "dutch": "Para", + "portuguese": "Para", + "russian": "Пара", + "chinese_traditional": "Para", + "unknown1": "Para", + "unknown2": "Para", + "unknown3": "Para", + "unknown4": "Para" + }, + "coordinates": { + "latitude": 5.581054624, + "longitude": -55.178493583000005 + } + }, + { + "id": 772341760, + "name": "Saramacca", + "translations": { + "japanese": "サラマッカ", + "english": "Saramacca", + "french": "Saramacca", + "german": "Saramacca", + "italian": "Saramacca", + "spanish": "Saramacca", + "chinese_simple": "萨拉马卡区", + "korean": "사라마카", + "dutch": "Saramacca", + "portuguese": "Saramacca", + "russian": "Сарамакка", + "chinese_traditional": "Saramacca", + "unknown1": "Saramacca", + "unknown2": "Saramacca", + "unknown3": "Saramacca", + "unknown4": "Saramacca" + }, + "coordinates": { + "latitude": 5.79528802, + "longitude": -55.464138891000005 + } + }, + { + "id": 772407296, + "name": "Sipaliwini", + "translations": { + "japanese": "シパリウィニ", + "english": "Sipaliwini", + "french": "Sipaliwini", + "german": "Sipaliwini", + "italian": "Sipaliwini", + "spanish": "Sipaliwini", + "chinese_simple": "西帕里维尼区", + "korean": "시팔리비니", + "dutch": "Sipaliwini", + "portuguese": "Sipaliwini", + "russian": "Сипалуини", + "chinese_traditional": "Sipaliwini", + "unknown1": "Sipaliwini", + "unknown2": "Sipaliwini", + "unknown3": "Sipaliwini", + "unknown4": "Sipaliwini" + }, + "coordinates": { + "latitude": 5.196533144, + "longitude": -57.161531202000006 + } + }, + { + "id": 772472832, + "name": "Wanica", + "translations": { + "japanese": "ワニカ", + "english": "Wanica", + "french": "Wanica", + "german": "Wanica", + "italian": "Wanica", + "spanish": "Wanica", + "chinese_simple": "瓦尼卡区", + "korean": "바니카", + "dutch": "Wanica", + "portuguese": "Wanica", + "russian": "Ваника", + "chinese_traditional": "Wanica", + "unknown1": "Wanica", + "unknown2": "Wanica", + "unknown3": "Wanica", + "unknown4": "Wanica" + }, + "coordinates": { + "latitude": 5.696411068, + "longitude": -55.227932194000005 + } + } + ] + }, + { + "id": 47, + "iso_code": "TT", + "name": "Trinidad and Tobago", + "translations": { + "japanese": "トリニダード・トバゴ", + "english": "Trinidad and Tobago", + "french": "Trinité-et-Tobago", + "german": "Trinidad und Tobago", + "italian": "Trinidad e Tobago", + "spanish": "Trinidad y Tobago", + "chinese_simple": "特立尼达和多巴哥", + "korean": "트리니다드토바고", + "dutch": "Trinidad en Tobago", + "portuguese": "Trinidade e Tobago", + "russian": "Тринидад и Тобаго", + "chinese_traditional": "Trinidad and Tobago", + "unknown1": "Trinidad and Tobago", + "unknown2": "Trinidad and Tobago", + "unknown3": "Trinidad and Tobago", + "unknown4": "Trinidad and Tobago" + }, + "regions": [ + { + "id": 788529152, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 10.645751832, + "longitude": -61.512128970000006 + } + }, + { + "id": 788660224, + "name": "Port-of-Spain", + "translations": { + "japanese": "ポート・オブ・スペイン", + "english": "Port-of-Spain", + "french": "Port d'Espagne", + "german": "Port-of-Spain", + "italian": "Port of Spain", + "spanish": "Puerto España", + "chinese_simple": "西班牙港市", + "korean": "포트오브스페인", + "dutch": "Port of Spain", + "portuguese": "Porto de Espanha", + "russian": "Порт-оф-Спейн", + "chinese_traditional": "Port-of-Spain", + "unknown1": "Port-of-Spain", + "unknown2": "Port-of-Spain", + "unknown3": "Port-of-Spain", + "unknown4": "Port-of-Spain" + }, + "coordinates": { + "latitude": 10.645751832, + "longitude": -61.512128970000006 + } + }, + { + "id": 788725760, + "name": "Arima", + "translations": { + "japanese": "アリマ", + "english": "Arima", + "french": "Arima", + "german": "Arima", + "italian": "Arima", + "spanish": "Arima", + "chinese_simple": "阿里马市", + "korean": "아리마", + "dutch": "Arima", + "portuguese": "Arima", + "russian": "Арима", + "chinese_traditional": "Arima", + "unknown1": "Arima", + "unknown2": "Arima", + "unknown3": "Arima", + "unknown4": "Arima" + }, + "coordinates": { + "latitude": 10.62927234, + "longitude": -61.281415452000005 + } + }, + { + "id": 788791296, + "name": "Caroni", + "translations": { + "japanese": "カロニ州", + "english": "Caroni", + "french": "Caroni", + "german": "Caroni", + "italian": "Caroni", + "spanish": "Caroni", + "chinese_simple": "卡罗尼郡", + "korean": "카로니 주", + "dutch": "Caroni", + "portuguese": "Caroni", + "russian": "Карони", + "chinese_traditional": "Caroni", + "unknown1": "Caroni", + "unknown2": "Caroni", + "unknown3": "Caroni", + "unknown4": "Caroni" + }, + "coordinates": { + "latitude": 10.513915896, + "longitude": -61.41325174800001 + } + }, + { + "id": 788856832, + "name": "Mayaro", + "translations": { + "japanese": "マジャロ州", + "english": "Mayaro", + "french": "Mayaro", + "german": "Mayaro", + "italian": "Mayaro", + "spanish": "Mayaro", + "chinese_simple": "马亚罗郡", + "korean": "마야로 주", + "dutch": "Mayaro", + "portuguese": "Mayaro", + "russian": "Майяро", + "chinese_traditional": "Mayaro", + "unknown1": "Mayaro", + "unknown2": "Mayaro", + "unknown3": "Mayaro", + "unknown4": "Mayaro" + }, + "coordinates": { + "latitude": 10.211791876, + "longitude": -60.995770144000005 + } + }, + { + "id": 788922368, + "name": "Nariva", + "translations": { + "japanese": "ナリバ州", + "english": "Nariva", + "french": "Nariva", + "german": "Nariva", + "italian": "Nariva", + "spanish": "Nariva", + "chinese_simple": "纳里瓦郡", + "korean": "나리바 주", + "dutch": "Nariva", + "portuguese": "Nariva", + "russian": "Нарива", + "chinese_traditional": "Nariva", + "unknown1": "Nariva", + "unknown2": "Nariva", + "unknown3": "Nariva", + "unknown4": "Nariva" + }, + "coordinates": { + "latitude": 10.2996825, + "longitude": -61.182538230000006 + } + }, + { + "id": 788987904, + "name": "Saint Andrew", + "translations": { + "japanese": "セント・アンドリュー州", + "english": "Saint Andrew", + "french": "Saint Andrew", + "german": "Saint Andrew", + "italian": "Saint Andrew", + "spanish": "Saint Andrew", + "chinese_simple": "圣安德鲁郡", + "korean": "세인트앤드루 주", + "dutch": "Saint Andrew", + "portuguese": "Saint Andrew", + "russian": "Сейнт Эндрю", + "chinese_traditional": "Saint Andrew", + "unknown1": "Saint Andrew", + "unknown2": "Saint Andrew", + "unknown3": "Saint Andrew", + "unknown4": "Saint Andrew" + }, + "coordinates": { + "latitude": 10.579833864, + "longitude": -61.111126903 + } + }, + { + "id": 789053440, + "name": "Saint David", + "translations": { + "japanese": "セント・デビッド州", + "english": "Saint David", + "french": "Saint David", + "german": "Saint David", + "italian": "Saint David", + "spanish": "Saint David", + "chinese_simple": "圣戴维郡", + "korean": "세인트데이비드 주", + "dutch": "Saint David", + "portuguese": "Saint David", + "russian": "Сейнт Дэвид", + "chinese_traditional": "Saint David", + "unknown1": "Saint David", + "unknown2": "Saint David", + "unknown3": "Saint David", + "unknown4": "Saint David" + }, + "coordinates": { + "latitude": 10.799560424000001, + "longitude": -61.012249681 + } + }, + { + "id": 789118976, + "name": "Saint George", + "translations": { + "japanese": "セント・ジョージ州", + "english": "Saint George", + "french": "Saint George", + "german": "Saint George", + "italian": "Saint George", + "spanish": "Saint George", + "chinese_simple": "圣乔治郡", + "korean": "세인트조지 주", + "dutch": "Saint George", + "portuguese": "Saint George", + "russian": "Сейнт Джордж", + "chinese_traditional": "Saint George", + "unknown1": "Saint George", + "unknown2": "Saint George", + "unknown3": "Saint George", + "unknown4": "Saint George" + }, + "coordinates": { + "latitude": 10.62927234, + "longitude": -61.380292674 + } + }, + { + "id": 789184512, + "name": "Saint Patrick", + "translations": { + "japanese": "セント・パトリック州", + "english": "Saint Patrick", + "french": "Saint Patrick", + "german": "Saint Patrick", + "italian": "Saint Patrick", + "spanish": "Saint Patrick", + "chinese_simple": "圣帕特里克郡", + "korean": "세인트패트릭 주", + "dutch": "Saint Patrick", + "portuguese": "Saint Patrick", + "russian": "Сейнт Патрик", + "chinese_traditional": "Saint Patrick", + "unknown1": "Saint Patrick", + "unknown2": "Saint Patrick", + "unknown3": "Saint Patrick", + "unknown4": "Saint Patrick" + }, + "coordinates": { + "latitude": 10.178832892, + "longitude": -61.682417519 + } + }, + { + "id": 789250048, + "name": "San Fernando", + "translations": { + "japanese": "サン・フェルナンド", + "english": "San Fernando", + "french": "San Fernando", + "german": "San Fernando", + "italian": "San Fernando", + "spanish": "San Fernando", + "chinese_simple": "圣费尔南多市", + "korean": "산페르난도", + "dutch": "San Fernando", + "portuguese": "San Fernando", + "russian": "Сан-Фернандо", + "chinese_traditional": "San Fernando", + "unknown1": "San Fernando", + "unknown2": "San Fernando", + "unknown3": "San Fernando", + "unknown4": "San Fernando" + }, + "coordinates": { + "latitude": 10.283203008, + "longitude": -61.46269035900001 + } + }, + { + "id": 789315584, + "name": "Tobago", + "translations": { + "japanese": "トバゴ島", + "english": "Tobago", + "french": "Tobago", + "german": "Tobago", + "italian": "Tobago", + "spanish": "Tobago", + "chinese_simple": "多巴哥岛", + "korean": "토바고 섬", + "dutch": "Tobago", + "portuguese": "Tobago", + "russian": "Тобаго", + "chinese_traditional": "Tobago", + "unknown1": "Tobago", + "unknown2": "Tobago", + "unknown3": "Tobago", + "unknown4": "Tobago" + }, + "coordinates": { + "latitude": 11.17858874, + "longitude": -60.732097552 + } + }, + { + "id": 789381120, + "name": "Victoria", + "translations": { + "japanese": "ビクトリア州", + "english": "Victoria", + "french": "Victoria", + "german": "Victoria", + "italian": "Victoria", + "spanish": "Victoria", + "chinese_simple": "维多利亚郡", + "korean": "빅토리아 주", + "dutch": "Victoria", + "portuguese": "Vitória", + "russian": "Виктория", + "chinese_traditional": "Victoria", + "unknown1": "Victoria", + "unknown2": "Victoria", + "unknown3": "Victoria", + "unknown4": "Victoria" + }, + "coordinates": { + "latitude": 10.261230352, + "longitude": -61.380292674 + } + }, + { + "id": 789446656, + "name": "Point Fortin", + "translations": { + "japanese": "ポイントフォーティン", + "english": "Point Fortin", + "french": "Point Fortin", + "german": "Point Fortin", + "italian": "Point Fortin", + "spanish": "Point Fortin", + "chinese_simple": "福廷岬市", + "korean": "포인트포르틴", + "dutch": "Point Fortin", + "portuguese": "Ponto Fortin", + "russian": "Пойнт Фортин", + "chinese_traditional": "Point Fortin", + "unknown1": "Point Fortin", + "unknown2": "Point Fortin", + "unknown3": "Point Fortin", + "unknown4": "Point Fortin" + }, + "coordinates": { + "latitude": 10.167846564, + "longitude": -61.67692434 + } + } + ] + }, + { + "id": 48, + "iso_code": "TC", + "name": "Turks and Caicos Islands", + "translations": { + "japanese": "タークス・カイコス諸島", + "english": "Turks and Caicos Islands", + "french": "Îles Turques-et-Caïques", + "german": "Turks- und Caicosinseln", + "italian": "Isole Turks e Caicos", + "spanish": "Islas Turcas y Caicos", + "chinese_simple": "特克斯和凯科斯群岛", + "korean": "터크스 케이커스 제도", + "dutch": "Turks- en Caicoseilanden", + "portuguese": "Ilhas Turcas e Caicos", + "russian": "Тёркс и Кайкос", + "chinese_traditional": "Turks and Caicos Islands", + "unknown1": "Turks and Caicos Islands", + "unknown2": "Turks and Caicos Islands", + "unknown3": "Turks and Caicos Islands", + "unknown4": "Turks and Caicos Islands" + }, + "regions": [ + { + "id": 805306368, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 21.461791748, + "longitude": -71.130685399 + } + }, + { + "id": 805371904, + "name": "Turks and Caicos Islands", + "translations": { + "japanese": "タークス・カイコス諸島", + "english": "Turks and Caicos Islands", + "french": "Îles Turques-et-Caïques", + "german": "Turks- und Caicosinseln", + "italian": "Isole Turks e Caicos", + "spanish": "Islas Turcas y Caicos", + "chinese_simple": "特克斯和凯科斯群岛", + "korean": "터크스 케이커스 제도", + "dutch": "Turks- en Caicoseilanden", + "portuguese": "Ilhas Turcas e Caicos", + "russian": "Тёркс и Кайкос", + "chinese_traditional": "Turks and Caicos Islands", + "unknown1": "Turks and Caicos Islands", + "unknown2": "Turks and Caicos Islands", + "unknown3": "Turks and Caicos Islands", + "unknown4": "Turks and Caicos Islands" + }, + "coordinates": { + "latitude": 21.461791748, + "longitude": -71.130685399 + } + } + ] + }, + { + "id": 49, + "iso_code": "US", + "name": "United States", + "translations": { + "japanese": "アメリカ", + "english": "United States", + "french": "États-Unis d’Amérique", + "german": "Vereinigte Staaten", + "italian": "Stati Uniti d'America", + "spanish": "Estados Unidos de América", + "chinese_simple": "美国", + "korean": "미국", + "dutch": "Verenigde Staten", + "portuguese": "Estados Unidos", + "russian": "Соединённые Штаты Америки", + "chinese_traditional": "United States", + "unknown1": "United States", + "unknown2": "United States", + "unknown3": "United States", + "unknown4": "United States" + }, + "regions": [ + { + "id": 822083584, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 38.89160112, + "longitude": -77.035852824 + } + }, + { + "id": 822214656, + "name": "District of Columbia", + "translations": { + "japanese": "コロンビア特別区", + "english": "District of Columbia", + "french": "Washington (District de Columbia)", + "german": "District of Columbia", + "italian": "Distretto di Columbia", + "spanish": "Distrito de Columbia", + "chinese_simple": "哥伦比亚特区", + "korean": "컬럼비아 특별구", + "dutch": "District of Columbia", + "portuguese": "Distrito de Colúmbia", + "russian": "Округ Колумбия", + "chinese_traditional": "District of Columbia", + "unknown1": "District of Columbia", + "unknown2": "District of Columbia", + "unknown3": "District of Columbia", + "unknown4": "District of Columbia" + }, + "coordinates": { + "latitude": 38.89160112, + "longitude": -77.035852824 + } + }, + { + "id": 822280192, + "name": "Alaska", + "translations": { + "japanese": "アラスカ州", + "english": "Alaska", + "french": "Alaska", + "german": "Alaska", + "italian": "Alaska", + "spanish": "Alaska", + "chinese_simple": "阿拉斯加州", + "korean": "알래스카 주", + "dutch": "Alaska", + "portuguese": "Alasca", + "russian": "Аляска", + "chinese_traditional": "Alaska", + "unknown1": "Alaska", + "unknown2": "Alaska", + "unknown3": "Alaska", + "unknown4": "Alaska" + }, + "coordinates": { + "latitude": 58.298949532, + "longitude": -134.417600658 + } + }, + { + "id": 822345728, + "name": "Alabama", + "translations": { + "japanese": "アラバマ州", + "english": "Alabama", + "french": "Alabama", + "german": "Alabama", + "italian": "Alabama", + "spanish": "Alabama", + "chinese_simple": "亚拉巴马州", + "korean": "앨라배마 주", + "dutch": "Alabama", + "portuguese": "Alabama", + "russian": "Алабама", + "chinese_traditional": "Alabama", + "unknown1": "Alabama", + "unknown2": "Alabama", + "unknown3": "Alabama", + "unknown4": "Alabama" + }, + "coordinates": { + "latitude": 32.365722288, + "longitude": -86.297352618 + } + }, + { + "id": 822411264, + "name": "Arkansas", + "translations": { + "japanese": "アーカンソー州", + "english": "Arkansas", + "french": "Arkansas", + "german": "Arkansas", + "italian": "Arkansas", + "spanish": "Arkansas", + "chinese_simple": "阿肯色州", + "korean": "아칸소 주", + "dutch": "Arkansas", + "portuguese": "Arkansas", + "russian": "Арканзас", + "chinese_traditional": "Arkansas", + "unknown1": "Arkansas", + "unknown2": "Arkansas", + "unknown3": "Arkansas", + "unknown4": "Arkansas" + }, + "coordinates": { + "latitude": 34.7442623, + "longitude": -92.284917728 + } + }, + { + "id": 822476800, + "name": "Arizona", + "translations": { + "japanese": "アリゾナ州", + "english": "Arizona", + "french": "Arizona", + "german": "Arizona", + "italian": "Arizona", + "spanish": "Arizona", + "chinese_simple": "亚利桑那州", + "korean": "애리조나 주", + "dutch": "Arizona", + "portuguese": "Arizona", + "russian": "Аризона", + "chinese_traditional": "Arizona", + "unknown1": "Arizona", + "unknown2": "Arizona", + "unknown3": "Arizona", + "unknown4": "Arizona" + }, + "coordinates": { + "latitude": 33.447875596, + "longitude": -112.071348486 + } + }, + { + "id": 822542336, + "name": "California", + "translations": { + "japanese": "カリフォルニア州", + "english": "California", + "french": "Californie", + "german": "Kalifornien", + "italian": "California", + "spanish": "California", + "chinese_simple": "加利福尼亚州", + "korean": "캘리포니아 주", + "dutch": "Californië", + "portuguese": "Califórnia", + "russian": "Калифорния", + "chinese_traditional": "California", + "unknown1": "California", + "unknown2": "California", + "unknown3": "California", + "unknown4": "California" + }, + "coordinates": { + "latitude": 38.578490772, + "longitude": -121.492150471 + } + }, + { + "id": 822607872, + "name": "Colorado", + "translations": { + "japanese": "コロラド州", + "english": "Colorado", + "french": "Colorado", + "german": "Colorado", + "italian": "Colorado", + "spanish": "Colorado", + "chinese_simple": "科罗拉多州", + "korean": "콜로라도 주", + "dutch": "Colorado", + "portuguese": "Colorado", + "russian": "Колорадо", + "chinese_traditional": "Colorado", + "unknown1": "Colorado", + "unknown2": "Colorado", + "unknown3": "Colorado", + "unknown4": "Colorado" + }, + "coordinates": { + "latitude": 39.737548376, + "longitude": -104.979654397 + } + }, + { + "id": 822673408, + "name": "Connecticut", + "translations": { + "japanese": "コネティカット州", + "english": "Connecticut", + "french": "Connecticut", + "german": "Connecticut", + "italian": "Connecticut", + "spanish": "Connecticut", + "chinese_simple": "康涅狄格州", + "korean": "코네티컷 주", + "dutch": "Connecticut", + "portuguese": "Connecticut", + "russian": "Коннектикут", + "chinese_traditional": "Connecticut", + "unknown1": "Connecticut", + "unknown2": "Connecticut", + "unknown3": "Connecticut", + "unknown4": "Connecticut" + }, + "coordinates": { + "latitude": 41.759032728, + "longitude": -72.685255056 + } + }, + { + "id": 822738944, + "name": "Delaware", + "translations": { + "japanese": "デラウェア州", + "english": "Delaware", + "french": "Delaware", + "german": "Delaware", + "italian": "Delaware", + "spanish": "Delaware", + "chinese_simple": "特拉华州", + "korean": "델라웨어 주", + "dutch": "Delaware", + "portuguese": "Delaware", + "russian": "Делавэр", + "chinese_traditional": "Delaware", + "unknown1": "Delaware", + "unknown2": "Delaware", + "unknown3": "Delaware", + "unknown4": "Delaware" + }, + "coordinates": { + "latitude": 39.155272992, + "longitude": -75.51973542 + } + }, + { + "id": 822804480, + "name": "Florida", + "translations": { + "japanese": "フロリダ州", + "english": "Florida", + "french": "Floride", + "german": "Florida", + "italian": "Florida", + "spanish": "Florida", + "chinese_simple": "佛罗里达州", + "korean": "플로리다 주", + "dutch": "Florida", + "portuguese": "Flórida", + "russian": "Флорида", + "chinese_traditional": "Florida", + "unknown1": "Florida", + "unknown2": "Florida", + "unknown3": "Florida", + "unknown4": "Florida" + }, + "coordinates": { + "latitude": 30.437621724, + "longitude": -84.275862746 + } + }, + { + "id": 822870016, + "name": "Georgia", + "translations": { + "japanese": "ジョージア州", + "english": "Georgia", + "french": "Géorgie", + "german": "Georgia", + "italian": "Georgia", + "spanish": "Georgia", + "chinese_simple": "佐治亚州", + "korean": "조지아 주", + "dutch": "Georgia", + "portuguese": "Geórgia", + "russian": "Джорджия", + "chinese_traditional": "Georgia", + "unknown1": "Georgia", + "unknown2": "Georgia", + "unknown3": "Georgia", + "unknown4": "Georgia" + }, + "coordinates": { + "latitude": 33.744506452, + "longitude": -84.385726326 + } + }, + { + "id": 822935552, + "name": "Hawaii", + "translations": { + "japanese": "ハワイ州", + "english": "Hawaii", + "french": "Hawaï", + "german": "Hawaii", + "italian": "Hawaii", + "spanish": "Hawái", + "chinese_simple": "夏威夷州", + "korean": "하와이 주", + "dutch": "Hawaï", + "portuguese": "Havaí", + "russian": "Гавайи", + "chinese_traditional": "Hawaii", + "unknown1": "Hawaii", + "unknown2": "Hawaii", + "unknown3": "Hawaii", + "unknown4": "Hawaii" + }, + "coordinates": { + "latitude": 21.302489992, + "longitude": -157.856995451 + } + }, + { + "id": 823001088, + "name": "Iowa", + "translations": { + "japanese": "アイオワ州", + "english": "Iowa", + "french": "Iowa", + "german": "Iowa", + "italian": "Iowa", + "spanish": "Iowa", + "chinese_simple": "艾奥瓦州", + "korean": "아이오와 주", + "dutch": "Iowa", + "portuguese": "Iowa", + "russian": "Айова", + "chinese_traditional": "Iowa", + "unknown1": "Iowa", + "unknown2": "Iowa", + "unknown3": "Iowa", + "unknown4": "Iowa" + }, + "coordinates": { + "latitude": 41.599730972, + "longitude": -93.603280688 + } + }, + { + "id": 823066624, + "name": "Idaho", + "translations": { + "japanese": "アイダホ州", + "english": "Idaho", + "french": "Idaho", + "german": "Idaho", + "italian": "Idaho", + "spanish": "Idaho", + "chinese_simple": "爱达荷州", + "korean": "아이다호 주", + "dutch": "Idaho", + "portuguese": "Idaho", + "russian": "Айдахо", + "chinese_traditional": "Idaho", + "unknown1": "Idaho", + "unknown2": "Idaho", + "unknown3": "Idaho", + "unknown4": "Idaho" + }, + "coordinates": { + "latitude": 43.610228996000004, + "longitude": -116.202219094 + } + }, + { + "id": 823132160, + "name": "Illinois", + "translations": { + "japanese": "イリノイ州", + "english": "Illinois", + "french": "Illinois", + "german": "Illinois", + "italian": "Illinois", + "spanish": "Illinois", + "chinese_simple": "伊利诺伊州", + "korean": "일리노이 주", + "dutch": "Illinois", + "portuguese": "Illinois", + "russian": "Иллинойс", + "chinese_traditional": "Illinois", + "unknown1": "Illinois", + "unknown2": "Illinois", + "unknown3": "Illinois", + "unknown4": "Illinois" + }, + "coordinates": { + "latitude": 39.79797318, + "longitude": -89.642698629 + } + }, + { + "id": 823197696, + "name": "Indiana", + "translations": { + "japanese": "インディアナ州", + "english": "Indiana", + "french": "Indiana", + "german": "Indiana", + "italian": "Indiana", + "spanish": "Indiana", + "chinese_simple": "印第安纳州", + "korean": "인디애나 주", + "dutch": "Indiana", + "portuguese": "Indiana", + "russian": "Индиана", + "chinese_traditional": "Indiana", + "unknown1": "Indiana", + "unknown2": "Indiana", + "unknown3": "Indiana", + "unknown4": "Indiana" + }, + "coordinates": { + "latitude": 39.765014196, + "longitude": -86.154529964 + } + }, + { + "id": 823263232, + "name": "Kansas", + "translations": { + "japanese": "カンザス州", + "english": "Kansas", + "french": "Kansas", + "german": "Kansas", + "italian": "Kansas", + "spanish": "Kansas", + "chinese_simple": "堪萨斯州", + "korean": "캔자스 주", + "dutch": "Kansas", + "portuguese": "Kansas", + "russian": "Канзас", + "chinese_traditional": "Kansas", + "unknown1": "Kansas", + "unknown2": "Kansas", + "unknown3": "Kansas", + "unknown4": "Kansas" + }, + "coordinates": { + "latitude": 39.045409712, + "longitude": -95.674209171 + } + }, + { + "id": 823328768, + "name": "Kentucky", + "translations": { + "japanese": "ケンタッキー州", + "english": "Kentucky", + "french": "Kentucky", + "german": "Kentucky", + "italian": "Kentucky", + "spanish": "Kentucky", + "chinese_simple": "肯塔基州", + "korean": "켄터키 주", + "dutch": "Kentucky", + "portuguese": "Kentucky", + "russian": "Кентукки", + "chinese_traditional": "Kentucky", + "unknown1": "Kentucky", + "unknown2": "Kentucky", + "unknown3": "Kentucky", + "unknown4": "Kentucky" + }, + "coordinates": { + "latitude": 38.199462456, + "longitude": -84.86912607800001 + } + }, + { + "id": 823394304, + "name": "Louisiana", + "translations": { + "japanese": "ルイジアナ州", + "english": "Louisiana", + "french": "Louisiane", + "german": "Louisiana", + "italian": "Luisiana", + "spanish": "Luisiana", + "chinese_simple": "路易斯安那州", + "korean": "루이지애나 주", + "dutch": "Louisiana", + "portuguese": "Luisiana", + "russian": "Луизиана", + "chinese_traditional": "Louisiana", + "unknown1": "Louisiana", + "unknown2": "Louisiana", + "unknown3": "Louisiana", + "unknown4": "Louisiana" + }, + "coordinates": { + "latitude": 30.448608052, + "longitude": -91.153322854 + } + }, + { + "id": 823459840, + "name": "Massachusetts", + "translations": { + "japanese": "マサチューセッツ州", + "english": "Massachusetts", + "french": "Massachusetts", + "german": "Massachusetts", + "italian": "Massachusetts", + "spanish": "Massachusetts", + "chinese_simple": "马萨诸塞州", + "korean": "매사추세츠 주", + "dutch": "Massachusetts", + "portuguese": "Massachusetts", + "russian": "Массачусетс", + "chinese_traditional": "Massachusetts", + "unknown1": "Massachusetts", + "unknown2": "Massachusetts", + "unknown3": "Massachusetts", + "unknown4": "Massachusetts" + }, + "coordinates": { + "latitude": 42.357787604, + "longitude": -71.05927407200001 + } + }, + { + "id": 823525376, + "name": "Maryland", + "translations": { + "japanese": "メリーランド州", + "english": "Maryland", + "french": "Maryland", + "german": "Maryland", + "italian": "Maryland", + "spanish": "Maryland", + "chinese_simple": "马里兰州", + "korean": "메릴랜드 주", + "dutch": "Maryland", + "portuguese": "Maryland", + "russian": "Мэриленд", + "chinese_traditional": "Maryland", + "unknown1": "Maryland", + "unknown2": "Maryland", + "unknown3": "Maryland", + "unknown4": "Maryland" + }, + "coordinates": { + "latitude": 38.97399858, + "longitude": -76.492028103 + } + }, + { + "id": 823590912, + "name": "Maine", + "translations": { + "japanese": "メーン州", + "english": "Maine", + "french": "Maine", + "german": "Maine", + "italian": "Maine", + "spanish": "Maine", + "chinese_simple": "缅因州", + "korean": "메인 주", + "dutch": "Maine", + "portuguese": "Maine", + "russian": "Мэн", + "chinese_traditional": "Maine", + "unknown1": "Maine", + "unknown2": "Maine", + "unknown3": "Maine", + "unknown4": "Maine" + }, + "coordinates": { + "latitude": 44.307860824, + "longitude": -69.779363365 + } + }, + { + "id": 823656448, + "name": "Michigan", + "translations": { + "japanese": "ミシガン州", + "english": "Michigan", + "french": "Michigan", + "german": "Michigan", + "italian": "Michigan", + "spanish": "Míchigan", + "chinese_simple": "密歇根州", + "korean": "미시간 주", + "dutch": "Michigan", + "portuguese": "Michigan", + "russian": "Мичиган", + "chinese_traditional": "Michigan", + "unknown1": "Michigan", + "unknown2": "Michigan", + "unknown3": "Michigan", + "unknown4": "Michigan" + }, + "coordinates": { + "latitude": 42.731322756, + "longitude": -84.550521696 + } + }, + { + "id": 823721984, + "name": "Minnesota", + "translations": { + "japanese": "ミネソタ州", + "english": "Minnesota", + "french": "Minnesota", + "german": "Minnesota", + "italian": "Minnesota", + "spanish": "Minnesota", + "chinese_simple": "明尼苏达州", + "korean": "미네소타 주", + "dutch": "Minnesota", + "portuguese": "Minnesota", + "russian": "Миннесота", + "chinese_traditional": "Minnesota", + "unknown1": "Minnesota", + "unknown2": "Minnesota", + "unknown3": "Minnesota", + "unknown4": "Minnesota" + }, + "coordinates": { + "latitude": 44.939574684, + "longitude": -93.092415041 + } + }, + { + "id": 823787520, + "name": "Missouri", + "translations": { + "japanese": "ミズーリ州", + "english": "Missouri", + "french": "Missouri", + "german": "Missouri", + "italian": "Missouri", + "spanish": "Misuri", + "chinese_simple": "密苏里州", + "korean": "미주리 주", + "dutch": "Missouri", + "portuguese": "Missouri", + "russian": "Миссури", + "chinese_traditional": "Missouri", + "unknown1": "Missouri", + "unknown2": "Missouri", + "unknown3": "Missouri", + "unknown4": "Missouri" + }, + "coordinates": { + "latitude": 38.572997608, + "longitude": -92.169560969 + } + }, + { + "id": 823853056, + "name": "Mississippi", + "translations": { + "japanese": "ミシシッピ州", + "english": "Mississippi", + "french": "Mississippi", + "german": "Mississippi", + "italian": "Mississippi", + "spanish": "Misisipi", + "chinese_simple": "密西西比州", + "korean": "미시시피 주", + "dutch": "Mississippi", + "portuguese": "Mississippi", + "russian": "Миссисипи", + "chinese_traditional": "Mississippi", + "unknown1": "Mississippi", + "unknown2": "Mississippi", + "unknown3": "Mississippi", + "unknown4": "Mississippi" + }, + "coordinates": { + "latitude": 32.294311156, + "longitude": -90.181030171 + } + }, + { + "id": 823918592, + "name": "Montana", + "translations": { + "japanese": "モンタナ州", + "english": "Montana", + "french": "Montana", + "german": "Montana", + "italian": "Montana", + "spanish": "Montana", + "chinese_simple": "蒙大拿州", + "korean": "몬태나 주", + "dutch": "Montana", + "portuguese": "Montana", + "russian": "Монтана", + "chinese_traditional": "Montana", + "unknown1": "Montana", + "unknown2": "Montana", + "unknown3": "Montana", + "unknown4": "Montana" + }, + "coordinates": { + "latitude": 46.587523884, + "longitude": -112.032896233 + } + }, + { + "id": 823984128, + "name": "North Carolina", + "translations": { + "japanese": "ノースカロライナ州", + "english": "North Carolina", + "french": "Caroline du Nord", + "german": "North Carolina", + "italian": "Carolina del Nord", + "spanish": "Carolina del Norte", + "chinese_simple": "北卡罗来纳州", + "korean": "노스캐롤라이나 주", + "dutch": "North Carolina", + "portuguese": "Carolina do Norte", + "russian": "Северная Каролина", + "chinese_traditional": "North Carolina", + "unknown1": "North Carolina", + "unknown2": "North Carolina", + "unknown3": "North Carolina", + "unknown4": "North Carolina" + }, + "coordinates": { + "latitude": 35.771483968, + "longitude": -78.634367913 + } + }, + { + "id": 824049664, + "name": "North Dakota", + "translations": { + "japanese": "ノースダコタ州", + "english": "North Dakota", + "french": "Dakota du Nord", + "german": "North Dakota", + "italian": "Dakota del Nord", + "spanish": "Dakota del Norte", + "chinese_simple": "北达科他州", + "korean": "노스다코타 주", + "dutch": "North Dakota", + "portuguese": "Dakota do Norte", + "russian": "Северная Дакота", + "chinese_traditional": "North Dakota", + "unknown1": "North Dakota", + "unknown2": "North Dakota", + "unknown3": "North Dakota", + "unknown4": "North Dakota" + }, + "coordinates": { + "latitude": 46.807250444, + "longitude": -100.782865641 + } + }, + { + "id": 824115200, + "name": "Nebraska", + "translations": { + "japanese": "ネブラスカ州", + "english": "Nebraska", + "french": "Nebraska", + "german": "Nebraska", + "italian": "Nebraska", + "spanish": "Nebraska", + "chinese_simple": "内布拉斯加州", + "korean": "네브래스카 주", + "dutch": "Nebraska", + "portuguese": "Nebrasca", + "russian": "Небраска", + "chinese_traditional": "Nebraska", + "unknown1": "Nebraska", + "unknown2": "Nebraska", + "unknown3": "Nebraska", + "unknown4": "Nebraska" + }, + "coordinates": { + "latitude": 40.797729028, + "longitude": -96.662981391 + } + }, + { + "id": 824180736, + "name": "New Hampshire", + "translations": { + "japanese": "ニューハンプシャー州", + "english": "New Hampshire", + "french": "New Hampshire", + "german": "New Hampshire", + "italian": "New Hampshire", + "spanish": "Nuevo Hampshire", + "chinese_simple": "新罕布什尔州", + "korean": "뉴햄프셔 주", + "dutch": "New Hampshire", + "portuguese": "Nova Hampshire", + "russian": "Нью-Гэмпшир", + "chinese_traditional": "New Hampshire", + "unknown1": "New Hampshire", + "unknown2": "New Hampshire", + "unknown3": "New Hampshire", + "unknown4": "New Hampshire" + }, + "coordinates": { + "latitude": 43.20373486, + "longitude": -71.537180645 + } + }, + { + "id": 824246272, + "name": "New Jersey", + "translations": { + "japanese": "ニュージャージー州", + "english": "New Jersey", + "french": "New Jersey", + "german": "New Jersey", + "italian": "New Jersey", + "spanish": "Nueva Jersey", + "chinese_simple": "新泽西州", + "korean": "뉴저지 주", + "dutch": "New Jersey", + "portuguese": "Nova Jérsei", + "russian": "Нью-Джерси", + "chinese_traditional": "New Jersey", + "unknown1": "New Jersey", + "unknown2": "New Jersey", + "unknown3": "New Jersey", + "unknown4": "New Jersey" + }, + "coordinates": { + "latitude": 40.215453644, + "longitude": -74.739704002 + } + }, + { + "id": 824311808, + "name": "New Mexico", + "translations": { + "japanese": "ニューメキシコ州", + "english": "New Mexico", + "french": "Nouveau-Mexique", + "german": "New Mexico", + "italian": "Nuovo Messico", + "spanish": "Nuevo México", + "chinese_simple": "新墨西哥州", + "korean": "뉴멕시코 주", + "dutch": "New Mexico", + "portuguese": "Novo México", + "russian": "Нью-Мексико", + "chinese_traditional": "New Mexico", + "unknown1": "New Mexico", + "unknown2": "New Mexico", + "unknown3": "New Mexico", + "unknown4": "New Mexico" + }, + "coordinates": { + "latitude": 35.683593344, + "longitude": -105.935467543 + } + }, + { + "id": 824377344, + "name": "Nevada", + "translations": { + "japanese": "ネバダ州", + "english": "Nevada", + "french": "Nevada", + "german": "Nevada", + "italian": "Nevada", + "spanish": "Nevada", + "chinese_simple": "内华达州", + "korean": "네바다 주", + "dutch": "Nevada", + "portuguese": "Nevada", + "russian": "Невада", + "chinese_traditional": "Nevada", + "unknown1": "Nevada", + "unknown2": "Nevada", + "unknown3": "Nevada", + "unknown4": "Nevada" + }, + "coordinates": { + "latitude": 39.160766156, + "longitude": -119.761799086 + } + }, + { + "id": 824442880, + "name": "New York", + "translations": { + "japanese": "ニューヨーク州", + "english": "New York", + "french": "New York", + "german": "New York", + "italian": "New York", + "spanish": "Nueva York", + "chinese_simple": "纽约州", + "korean": "뉴욕 주", + "dutch": "New York", + "portuguese": "Nova Iorque", + "russian": "Нью-Йорк", + "chinese_traditional": "New York", + "unknown1": "New York", + "unknown2": "New York", + "unknown3": "New York", + "unknown4": "New York" + }, + "coordinates": { + "latitude": 42.648925296, + "longitude": -73.750931782 + } + }, + { + "id": 824508416, + "name": "Ohio", + "translations": { + "japanese": "オハイオ州", + "english": "Ohio", + "french": "Ohio", + "german": "Ohio", + "italian": "Ohio", + "spanish": "Ohio", + "chinese_simple": "俄亥俄州", + "korean": "오하이오 주", + "dutch": "Ohio", + "portuguese": "Ohio", + "russian": "Огайо", + "chinese_traditional": "Ohio", + "unknown1": "Ohio", + "unknown2": "Ohio", + "unknown3": "Ohio", + "unknown4": "Ohio" + }, + "coordinates": { + "latitude": 39.957274936, + "longitude": -82.995952039 + } + }, + { + "id": 824573952, + "name": "Oklahoma", + "translations": { + "japanese": "オクラホマ州", + "english": "Oklahoma", + "french": "Oklahoma", + "german": "Oklahoma", + "italian": "Oklahoma", + "spanish": "Oklahoma", + "chinese_simple": "俄克拉何马州", + "korean": "오클라호마 주", + "dutch": "Oklahoma", + "portuguese": "Oklahoma", + "russian": "Оклахома", + "chinese_traditional": "Oklahoma", + "unknown1": "Oklahoma", + "unknown2": "Oklahoma", + "unknown3": "Oklahoma", + "unknown4": "Oklahoma" + }, + "coordinates": { + "latitude": 35.463866784, + "longitude": -97.514424136 + } + }, + { + "id": 824639488, + "name": "Oregon", + "translations": { + "japanese": "オレゴン州", + "english": "Oregon", + "french": "Oregon", + "german": "Oregon", + "italian": "Oregon", + "spanish": "Oregón", + "chinese_simple": "俄勒冈州", + "korean": "오리건 주", + "dutch": "Oregon", + "portuguese": "Oregon", + "russian": "Орегон", + "chinese_traditional": "Oregon", + "unknown1": "Oregon", + "unknown2": "Oregon", + "unknown3": "Oregon", + "unknown4": "Oregon" + }, + "coordinates": { + "latitude": 44.939574684, + "longitude": -123.030240591 + } + }, + { + "id": 824705024, + "name": "Pennsylvania", + "translations": { + "japanese": "ペンシルベニア州", + "english": "Pennsylvania", + "french": "Pennsylvanie", + "german": "Pennsylvania", + "italian": "Pennsylvania", + "spanish": "Pensilvania", + "chinese_simple": "宾夕法尼亚州", + "korean": "펜실베이니아 주", + "dutch": "Pennsylvania", + "portuguese": "Pensilvânia", + "russian": "Пенсильвания", + "chinese_traditional": "Pennsylvania", + "unknown1": "Pennsylvania", + "unknown2": "Pennsylvania", + "unknown3": "Pennsylvania", + "unknown4": "Pennsylvania" + }, + "coordinates": { + "latitude": 40.270385284, + "longitude": -76.882043812 + } + }, + { + "id": 824770560, + "name": "Rhode Island", + "translations": { + "japanese": "ロードアイランド州", + "english": "Rhode Island", + "french": "Rhode Island", + "german": "Rhode Island", + "italian": "Rhode Island", + "spanish": "Rhode Island", + "chinese_simple": "罗得岛州", + "korean": "로드아일랜드 주", + "dutch": "Rhode Island", + "portuguese": "Rhode Island", + "russian": "Род-Айленд", + "chinese_traditional": "Rhode Island", + "unknown1": "Rhode Island", + "unknown2": "Rhode Island", + "unknown3": "Rhode Island", + "unknown4": "Rhode Island" + }, + "coordinates": { + "latitude": 41.819457532, + "longitude": -71.410837528 + } + }, + { + "id": 824836096, + "name": "South Carolina", + "translations": { + "japanese": "サウスカロライナ州", + "english": "South Carolina", + "french": "Caroline du Sud", + "german": "South Carolina", + "italian": "Carolina del Sud", + "spanish": "Carolina del Sur", + "chinese_simple": "南卡罗来纳州", + "korean": "사우스캐롤라이나 주", + "dutch": "South Carolina", + "portuguese": "Carolina do Sul", + "russian": "Южная Каролина", + "chinese_traditional": "South Carolina", + "unknown1": "South Carolina", + "unknown2": "South Carolina", + "unknown3": "South Carolina", + "unknown4": "South Carolina" + }, + "coordinates": { + "latitude": 33.997191996, + "longitude": -81.029393957 + } + }, + { + "id": 824901632, + "name": "South Dakota", + "translations": { + "japanese": "サウスダコタ州", + "english": "South Dakota", + "french": "Dakota du Sud", + "german": "South Dakota", + "italian": "Dakota del Sud", + "spanish": "Dakota del Sur", + "chinese_simple": "南达科他州", + "korean": "사우스다코타 주", + "dutch": "South Dakota", + "portuguese": "Dakota do Sul", + "russian": "Южная Дакота", + "chinese_traditional": "South Dakota", + "unknown1": "South Dakota", + "unknown2": "South Dakota", + "unknown3": "South Dakota", + "unknown4": "South Dakota" + }, + "coordinates": { + "latitude": 44.368285628, + "longitude": -100.3489045 + } + }, + { + "id": 824967168, + "name": "Tennessee", + "translations": { + "japanese": "テネシー州", + "english": "Tennessee", + "french": "Tennessee", + "german": "Tennessee", + "italian": "Tennessee", + "spanish": "Tennessee", + "chinese_simple": "田纳西州", + "korean": "테네시 주", + "dutch": "Tennessee", + "portuguese": "Tennessee", + "russian": "Теннесси", + "chinese_traditional": "Tennessee", + "unknown1": "Tennessee", + "unknown2": "Tennessee", + "unknown3": "Tennessee", + "unknown4": "Tennessee" + }, + "coordinates": { + "latitude": 36.161498612, + "longitude": -86.78075237 + } + }, + { + "id": 825032704, + "name": "Texas", + "translations": { + "japanese": "テキサス州", + "english": "Texas", + "french": "Texas", + "german": "Texas", + "italian": "Texas", + "spanish": "Texas", + "chinese_simple": "得克萨斯州", + "korean": "텍사스 주", + "dutch": "Texas", + "portuguese": "Texas", + "russian": "Техас", + "chinese_traditional": "Texas", + "unknown1": "Texas", + "unknown2": "Texas", + "unknown3": "Texas", + "unknown4": "Texas" + }, + "coordinates": { + "latitude": 30.261840476, + "longitude": -97.739644475 + } + }, + { + "id": 825098240, + "name": "Utah", + "translations": { + "japanese": "ユタ州", + "english": "Utah", + "french": "Utah", + "german": "Utah", + "italian": "Utah", + "spanish": "Utah", + "chinese_simple": "犹他州", + "korean": "유타 주", + "dutch": "Utah", + "portuguese": "Utah", + "russian": "Юта", + "chinese_traditional": "Utah", + "unknown1": "Utah", + "unknown2": "Utah", + "unknown3": "Utah", + "unknown4": "Utah" + }, + "coordinates": { + "latitude": 40.75927688, + "longitude": -111.890073579 + } + }, + { + "id": 825163776, + "name": "Virginia", + "translations": { + "japanese": "バージニア州", + "english": "Virginia", + "french": "Virginie", + "german": "Virginia", + "italian": "Virginia", + "spanish": "Virginia", + "chinese_simple": "弗吉尼亚州", + "korean": "버지니아 주", + "dutch": "Virginia", + "portuguese": "Virgínia", + "russian": "Виргиния", + "chinese_traditional": "Virginia", + "unknown1": "Virginia", + "unknown2": "Virginia", + "unknown3": "Virginia", + "unknown4": "Virginia" + }, + "coordinates": { + "latitude": 37.551269104, + "longitude": -77.458827607 + } + }, + { + "id": 825229312, + "name": "Vermont", + "translations": { + "japanese": "バーモント州", + "english": "Vermont", + "french": "Vermont", + "german": "Vermont", + "italian": "Vermont", + "spanish": "Vermont", + "chinese_simple": "佛蒙特州", + "korean": "버몬트 주", + "dutch": "Vermont", + "portuguese": "Vermont", + "russian": "Вермонт", + "chinese_traditional": "Vermont", + "unknown1": "Vermont", + "unknown2": "Vermont", + "unknown3": "Vermont", + "unknown4": "Vermont" + }, + "coordinates": { + "latitude": 44.258422348, + "longitude": -72.57539147600001 + } + }, + { + "id": 825294848, + "name": "Washington", + "translations": { + "japanese": "ワシントン州", + "english": "Washington", + "french": "Washington", + "german": "Washington", + "italian": "Stato di Washington", + "spanish": "Washington", + "chinese_simple": "华盛顿州", + "korean": "워싱턴 주", + "dutch": "Washington", + "portuguese": "Washington", + "russian": "Вашингтон (штат)", + "chinese_traditional": "Washington", + "unknown1": "Washington", + "unknown2": "Washington", + "unknown3": "Washington", + "unknown4": "Washington" + }, + "coordinates": { + "latitude": 47.037963332, + "longitude": -122.898404295 + } + }, + { + "id": 825360384, + "name": "Wisconsin", + "translations": { + "japanese": "ウィスコンシン州", + "english": "Wisconsin", + "french": "Wisconsin", + "german": "Wisconsin", + "italian": "Wisconsin", + "spanish": "Wisconsin", + "chinese_simple": "威斯康星州", + "korean": "위스콘신 주", + "dutch": "Wisconsin", + "portuguese": "Wisconsin", + "russian": "Висконсин", + "chinese_traditional": "Wisconsin", + "unknown1": "Wisconsin", + "unknown2": "Wisconsin", + "unknown3": "Wisconsin", + "unknown4": "Wisconsin" + }, + "coordinates": { + "latitude": 43.071898924, + "longitude": -89.395505574 + } + }, + { + "id": 825425920, + "name": "West Virginia", + "translations": { + "japanese": "ウェストバージニア州", + "english": "West Virginia", + "french": "Virginie Occidentale", + "german": "West Virginia", + "italian": "Virginia Occidentale", + "spanish": "Virginia Occidental", + "chinese_simple": "西弗吉尼亚州", + "korean": "웨스트버지니아 주", + "dutch": "West Virginia", + "portuguese": "Virgínia Ocidental", + "russian": "Западная Виргиния", + "chinese_traditional": "West Virginia", + "unknown1": "West Virginia", + "unknown2": "West Virginia", + "unknown3": "West Virginia", + "unknown4": "West Virginia" + }, + "coordinates": { + "latitude": 38.347777884, + "longitude": -81.628150468 + } + }, + { + "id": 825491456, + "name": "Wyoming", + "translations": { + "japanese": "ワイオミング州", + "english": "Wyoming", + "french": "Wyoming", + "german": "Wyoming", + "italian": "Wyoming", + "spanish": "Wyoming", + "chinese_simple": "怀俄明州", + "korean": "와이오밍 주", + "dutch": "Wyoming", + "portuguese": "Wyoming", + "russian": "Вайоминг", + "chinese_traditional": "Wyoming", + "unknown1": "Wyoming", + "unknown2": "Wyoming", + "unknown3": "Wyoming", + "unknown4": "Wyoming" + }, + "coordinates": { + "latitude": 41.138305196, + "longitude": -104.814859027 + } + }, + { + "id": 825556992, + "name": "Puerto Rico", + "translations": { + "japanese": "プエルトリコ", + "english": "Puerto Rico", + "french": "Porto Rico", + "german": "Puerto Rico", + "italian": "Porto Rico", + "spanish": "Puerto Rico", + "chinese_simple": "波多黎各", + "korean": "푸에르토리코", + "dutch": "Puerto Rico", + "portuguese": "Porto Rico", + "russian": "Пуэрто-Рико", + "chinese_traditional": "Puerto Rico", + "unknown1": "Puerto Rico", + "unknown2": "Puerto Rico", + "unknown3": "Puerto Rico", + "unknown4": "Puerto Rico" + }, + "coordinates": { + "latitude": 18.468017368, + "longitude": -66.104426614 + } + } + ] + }, + { + "id": 50, + "iso_code": "UY", + "name": "Uruguay", + "translations": { + "japanese": "ウルグアイ", + "english": "Uruguay", + "french": "Uruguay", + "german": "Uruguay", + "italian": "Uruguay", + "spanish": "Uruguay", + "chinese_simple": "乌拉圭", + "korean": "우루과이", + "dutch": "Uruguay", + "portuguese": "Uruguai", + "russian": "Уругвай", + "chinese_traditional": "Uruguay", + "unknown1": "Uruguay", + "unknown2": "Uruguay", + "unknown3": "Uruguay", + "unknown4": "Uruguay" + }, + "regions": [ + { + "id": 838860800, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": -34.854126604, + "longitude": -56.16726580300001 + } + }, + { + "id": 838991872, + "name": "Montevideo", + "translations": { + "japanese": "モンテビデオ", + "english": "Montevideo", + "french": "Montevideo", + "german": "Montevideo", + "italian": "Montevideo", + "spanish": "Montevideo", + "chinese_simple": "蒙得维的亚省", + "korean": "몬테비데오", + "dutch": "Montevideo", + "portuguese": "Montevideu", + "russian": "Монтевидео", + "chinese_traditional": "Montevideo", + "unknown1": "Montevideo", + "unknown2": "Montevideo", + "unknown3": "Montevideo", + "unknown4": "Montevideo" + }, + "coordinates": { + "latitude": -34.854126604, + "longitude": -56.16726580300001 + } + }, + { + "id": 839057408, + "name": "Artigas", + "translations": { + "japanese": "アルティガス", + "english": "Artigas", + "french": "Artigas", + "german": "Artigas", + "italian": "Artigas", + "spanish": "Artigas", + "chinese_simple": "阿蒂加斯省", + "korean": "아르티가스", + "dutch": "Artigas", + "portuguese": "Artigas", + "russian": "Артигас", + "chinese_traditional": "Artigas", + "unknown1": "Artigas", + "unknown2": "Artigas", + "unknown3": "Artigas", + "unknown4": "Artigas" + }, + "coordinates": { + "latitude": -30.399170599999998, + "longitude": -56.463897469 + } + }, + { + "id": 839122944, + "name": "Canelones", + "translations": { + "japanese": "カネロネス", + "english": "Canelones", + "french": "Canelones", + "german": "Canelones", + "italian": "Canelones", + "spanish": "Canelones", + "chinese_simple": "卡内洛内斯省", + "korean": "카넬로네스", + "dutch": "Canelones", + "portuguese": "Canelones", + "russian": "Канелонес", + "chinese_traditional": "Canelones", + "unknown1": "Canelones", + "unknown2": "Canelones", + "unknown3": "Canelones", + "unknown4": "Canelones" + }, + "coordinates": { + "latitude": -34.519043599999996, + "longitude": -56.277129383 + } + }, + { + "id": 839188480, + "name": "Cerro Largo", + "translations": { + "japanese": "セロ・ラルゴ", + "english": "Cerro Largo", + "french": "Cerro Largo", + "german": "Cerro Largo", + "italian": "Cerro Largo", + "spanish": "Cerro Largo", + "chinese_simple": "塞罗拉尔戈省", + "korean": "세로라르고", + "dutch": "Cerro Largo", + "portuguese": "Cerro Largo", + "russian": "Серро-Ларго", + "chinese_traditional": "Cerro Largo", + "unknown1": "Cerro Largo", + "unknown2": "Cerro Largo", + "unknown3": "Cerro Largo", + "unknown4": "Cerro Largo" + }, + "coordinates": { + "latitude": -32.365723312, + "longitude": -54.17873500500001 + } + }, + { + "id": 839254016, + "name": "Colonia", + "translations": { + "japanese": "コロニア", + "english": "Colonia", + "french": "Colonia", + "german": "Colonia", + "italian": "Colonia", + "spanish": "Colonia", + "chinese_simple": "科洛尼亚省", + "korean": "콜로니아", + "dutch": "Colonia", + "portuguese": "Colônia", + "russian": "Колония", + "chinese_traditional": "Colonia", + "unknown1": "Colonia", + "unknown2": "Colonia", + "unknown3": "Colonia", + "unknown4": "Colonia" + }, + "coordinates": { + "latitude": -34.46411196, + "longitude": -57.848178577 + } + }, + { + "id": 839319552, + "name": "Durazno", + "translations": { + "japanese": "ドゥラスノ", + "english": "Durazno", + "french": "Durazno", + "german": "Durazno", + "italian": "Durazno", + "spanish": "Durazno", + "chinese_simple": "杜拉斯诺省", + "korean": "두라스노", + "dutch": "Durazno", + "portuguese": "Durazno", + "russian": "Дурасно", + "chinese_traditional": "Durazno", + "unknown1": "Durazno", + "unknown2": "Durazno", + "unknown3": "Durazno", + "unknown4": "Durazno" + }, + "coordinates": { + "latitude": -33.409424472, + "longitude": -56.49685654300001 + } + }, + { + "id": 839385088, + "name": "Flores", + "translations": { + "japanese": "フロレス", + "english": "Flores", + "french": "Flores", + "german": "Flores", + "italian": "Flores", + "spanish": "Flores", + "chinese_simple": "弗洛雷斯省", + "korean": "플로레스", + "dutch": "Flores", + "portuguese": "Flores", + "russian": "Флорес", + "chinese_traditional": "Flores", + "unknown1": "Flores", + "unknown2": "Flores", + "unknown3": "Flores", + "unknown4": "Flores" + }, + "coordinates": { + "latitude": -33.535767244, + "longitude": -56.886872252 + } + }, + { + "id": 839450624, + "name": "Florida", + "translations": { + "japanese": "フロリダ", + "english": "Florida", + "french": "Florida", + "german": "Florida", + "italian": "Florida", + "spanish": "Florida", + "chinese_simple": "佛罗里达省", + "korean": "플로리다", + "dutch": "Florida", + "portuguese": "Florida", + "russian": "Флорида", + "chinese_traditional": "Florida", + "unknown1": "Florida", + "unknown2": "Florida", + "unknown3": "Florida", + "unknown4": "Florida" + }, + "coordinates": { + "latitude": -34.090576808, + "longitude": -56.21121123500001 + } + }, + { + "id": 839516160, + "name": "Lavalleja", + "translations": { + "japanese": "ラバジェハ", + "english": "Lavalleja", + "french": "Lavalleja", + "german": "Lavalleja", + "italian": "Lavalleja", + "spanish": "Lavalleja", + "chinese_simple": "拉瓦耶哈省", + "korean": "라바예하", + "dutch": "Lavalleja", + "portuguese": "Lavalleja", + "russian": "Лавальеха", + "chinese_traditional": "Lavalleja", + "unknown1": "Lavalleja", + "unknown2": "Lavalleja", + "unknown3": "Lavalleja", + "unknown4": "Lavalleja" + }, + "coordinates": { + "latitude": -34.365235008, + "longitude": -55.222439015000006 + } + }, + { + "id": 839581696, + "name": "Maldonado", + "translations": { + "japanese": "マルドナド", + "english": "Maldonado", + "french": "Maldonado", + "german": "Maldonado", + "italian": "Maldonado", + "spanish": "Maldonado", + "chinese_simple": "马尔多纳多省", + "korean": "말도나도", + "dutch": "Maldonado", + "portuguese": "Maldonado", + "russian": "Мальдонадо", + "chinese_traditional": "Maldonado", + "unknown1": "Maldonado", + "unknown2": "Maldonado", + "unknown3": "Maldonado", + "unknown4": "Maldonado" + }, + "coordinates": { + "latitude": -34.898071916, + "longitude": -54.947780065 + } + }, + { + "id": 839647232, + "name": "Paysandú", + "translations": { + "japanese": "パイサンドゥ", + "english": "Paysandú", + "french": "Paysandú", + "german": "Paysandú", + "italian": "Paysandú", + "spanish": "Paysandú", + "chinese_simple": "派桑杜省", + "korean": "파이산두", + "dutch": "Paysandú", + "portuguese": "Paysandú", + "russian": "Пайсанду", + "chinese_traditional": "Paysandú", + "unknown1": "Paysandú", + "unknown2": "Paysandú", + "unknown3": "Paysandú", + "unknown4": "Paysandú" + }, + "coordinates": { + "latitude": -32.316284836, + "longitude": -58.073398916 + } + }, + { + "id": 839712768, + "name": "Río Negro", + "translations": { + "japanese": "リオ・ネグロ", + "english": "Río Negro", + "french": "Río Negro", + "german": "Río Negro", + "italian": "Río Negro", + "spanish": "Río Negro", + "chinese_simple": "内格罗河省", + "korean": "리오네그로", + "dutch": "Río Negro", + "portuguese": "Río Negro", + "russian": "Рио-Негро", + "chinese_traditional": "Río Negro", + "unknown1": "Río Negro", + "unknown2": "Río Negro", + "unknown3": "Río Negro", + "unknown4": "Río Negro" + }, + "coordinates": { + "latitude": -33.129273108, + "longitude": -58.29312607600001 + } + }, + { + "id": 839778304, + "name": "Rivera", + "translations": { + "japanese": "リベラ", + "english": "Rivera", + "french": "Rivera", + "german": "Rivera", + "italian": "Rivera", + "spanish": "Rivera", + "chinese_simple": "里韦拉省", + "korean": "리베라", + "dutch": "Rivera", + "portuguese": "Rivera", + "russian": "Ривера", + "chinese_traditional": "Rivera", + "unknown1": "Rivera", + "unknown2": "Rivera", + "unknown3": "Rivera", + "unknown4": "Rivera" + }, + "coordinates": { + "latitude": -30.899048524, + "longitude": -55.513577502000004 + } + }, + { + "id": 839843840, + "name": "Rocha", + "translations": { + "japanese": "ロチャ", + "english": "Rocha", + "french": "Rocha", + "german": "Rocha", + "italian": "Rocha", + "spanish": "Rocha", + "chinese_simple": "罗恰省", + "korean": "로차", + "dutch": "Rocha", + "portuguese": "Rocha", + "russian": "Роча", + "chinese_traditional": "Rocha", + "unknown1": "Rocha", + "unknown2": "Rocha", + "unknown3": "Rocha", + "unknown4": "Rocha" + }, + "coordinates": { + "latitude": -34.480591452, + "longitude": -54.332544017000004 + } + }, + { + "id": 839909376, + "name": "Salto", + "translations": { + "japanese": "サルト", + "english": "Salto", + "french": "Salto", + "german": "Salto", + "italian": "Salto", + "spanish": "Salto", + "chinese_simple": "萨尔托省", + "korean": "살토", + "dutch": "Salto", + "portuguese": "Salto", + "russian": "Сальто", + "chinese_traditional": "Salto", + "unknown1": "Salto", + "unknown2": "Salto", + "unknown3": "Salto", + "unknown4": "Salto" + }, + "coordinates": { + "latitude": -31.382446956000003, + "longitude": -57.96353533600001 + } + }, + { + "id": 839974912, + "name": "San José", + "translations": { + "japanese": "サン・ホセ", + "english": "San José", + "french": "San José", + "german": "San José", + "italian": "San José", + "spanish": "San José", + "chinese_simple": "圣何塞省", + "korean": "산호세", + "dutch": "San José", + "portuguese": "San José", + "russian": "Сан-Хосе", + "chinese_traditional": "San José", + "unknown1": "San José", + "unknown2": "San José", + "unknown3": "San José", + "unknown4": "San José" + }, + "coordinates": { + "latitude": -34.332276024, + "longitude": -56.711090524 + } + }, + { + "id": 840040448, + "name": "Soriano", + "translations": { + "japanese": "ソリアノ", + "english": "Soriano", + "french": "Soriano", + "german": "Soriano", + "italian": "Soriano", + "spanish": "Soriano", + "chinese_simple": "索里亚诺省", + "korean": "소리아노", + "dutch": "Soriano", + "portuguese": "Soriano", + "russian": "Сорьяно", + "chinese_traditional": "Soriano", + "unknown1": "Soriano", + "unknown2": "Soriano", + "unknown3": "Soriano", + "unknown4": "Soriano" + }, + "coordinates": { + "latitude": -33.25561588, + "longitude": -58.018467126000004 + } + }, + { + "id": 840105984, + "name": "Tacuarembó", + "translations": { + "japanese": "タクアレンボ", + "english": "Tacuarembó", + "french": "Tacuarembó", + "german": "Tacuarembó", + "italian": "Tacuarembó", + "spanish": "Tacuarembó", + "chinese_simple": "塔夸伦博省", + "korean": "타쿠아렘보", + "dutch": "Tacuarembó", + "portuguese": "Tacuarembó", + "russian": "Такуарембо", + "chinese_traditional": "Tacuarembó", + "unknown1": "Tacuarembó", + "unknown2": "Tacuarembó", + "unknown3": "Tacuarembó", + "unknown4": "Tacuarembó" + }, + "coordinates": { + "latitude": -31.728516288, + "longitude": -55.980497717000006 + } + }, + { + "id": 840171520, + "name": "Treinta y Tres", + "translations": { + "japanese": "トレインタ・イ・トレス", + "english": "Treinta y Tres", + "french": "Treinta y Tres", + "german": "Treinta y Tres", + "italian": "Treinta y Tres", + "spanish": "Treinta y Tres", + "chinese_simple": "三十三人省", + "korean": "트레인타이트레스", + "dutch": "Treinta y Tres", + "portuguese": "Treinta y Tres", + "russian": "Трейнта-и-Трес", + "chinese_traditional": "Treinta y Tres", + "unknown1": "Treinta y Tres", + "unknown2": "Treinta y Tres", + "unknown3": "Treinta y Tres", + "unknown4": "Treinta y Tres" + }, + "coordinates": { + "latitude": -33.22815006, + "longitude": -54.381982628 + } + } + ] + }, + { + "id": 51, + "iso_code": "VI", + "name": "US Virgin Islands", + "translations": { + "japanese": "米領バージン諸島", + "english": "US Virgin Islands", + "french": "Îles Vierges américaines", + "german": "Amerikanische Jungferninseln", + "italian": "Isole Vergini Statunitensi", + "spanish": "Islas Vírgenes de los EE. UU.", + "chinese_simple": "美属维尔京群岛", + "korean": "미국령 버진아일랜드", + "dutch": "Amerikaanse Maagdeneilanden", + "portuguese": "Ilhas Virgens Americanas", + "russian": "Американские Виргинские острова", + "chinese_traditional": "US Virgin Islands", + "unknown1": "US Virgin Islands", + "unknown2": "US Virgin Islands", + "unknown3": "US Virgin Islands", + "unknown4": "US Virgin Islands" + }, + "regions": [ + { + "id": 855638016, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 18.341674596, + "longitude": -64.928886308 + } + }, + { + "id": 855703552, + "name": "US Virgin Islands", + "translations": { + "japanese": "米領バージン諸島", + "english": "US Virgin Islands", + "french": "Îles Vierges américaines", + "german": "Amerikanische Jungferninseln", + "italian": "Isole Vergini Statunitensi", + "spanish": "Islas Vírgenes de los EE. UU.", + "chinese_simple": "美属维尔京群岛", + "korean": "미국령 버진아일랜드", + "dutch": "Amerikaanse Maagdeneilanden", + "portuguese": "Ilhas Virgens Americanas", + "russian": "Американские Виргинские острова", + "chinese_traditional": "US Virgin Islands", + "unknown1": "US Virgin Islands", + "unknown2": "US Virgin Islands", + "unknown3": "US Virgin Islands", + "unknown4": "US Virgin Islands" + }, + "coordinates": { + "latitude": 18.341674596, + "longitude": -64.928886308 + } + } + ] + }, + { + "id": 52, + "iso_code": "VE", + "name": "Venezuela", + "translations": { + "japanese": "ベネズエラ", + "english": "Venezuela", + "french": "Venezuela", + "german": "Venezuela", + "italian": "Venezuela", + "spanish": "Venezuela", + "chinese_simple": "委内瑞拉", + "korean": "베네수엘라", + "dutch": "Venezuela", + "portuguese": "Venezuela", + "russian": "Венесуэла", + "chinese_traditional": "Venezuela", + "unknown1": "Venezuela", + "unknown2": "Venezuela", + "unknown3": "Venezuela", + "unknown4": "Venezuela" + }, + "regions": [ + { + "id": 872415232, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 10.497436404, + "longitude": -66.911923927 + } + }, + { + "id": 872546304, + "name": "Distrito Federal", + "translations": { + "japanese": "ディストリト首都地区", + "english": "Distrito Federal", + "french": "District Fédéral", + "german": "Caracas D.F.", + "italian": "Distretto Capitale", + "spanish": "Distrito Capital", + "chinese_simple": "首都区", + "korean": "베네수엘라 연방구", + "dutch": "Hoofdstedelijk District", + "portuguese": "Distrito Federal", + "russian": "Федеральный округ", + "chinese_traditional": "Distrito Federal", + "unknown1": "Distrito Federal", + "unknown2": "Distrito Federal", + "unknown3": "Distrito Federal", + "unknown4": "Distrito Federal" + }, + "coordinates": { + "latitude": 10.497436404, + "longitude": -66.911923927 + } + }, + { + "id": 872611840, + "name": "Amazonas", + "translations": { + "japanese": "アマソナス", + "english": "Amazonas", + "french": "Amazone", + "german": "Amazonas", + "italian": "Amazonas", + "spanish": "Amazonas", + "chinese_simple": "亚马孙边疆区", + "korean": "아마소나스", + "dutch": "Amazonas", + "portuguese": "Amazonas", + "russian": "Амасонас", + "chinese_traditional": "Amazonas", + "unknown1": "Amazonas", + "unknown2": "Amazonas", + "unknown3": "Amazonas", + "unknown4": "Amazonas" + }, + "coordinates": { + "latitude": 5.663452084, + "longitude": -67.620544018 + } + }, + { + "id": 872677376, + "name": "Anzoátegui", + "translations": { + "japanese": "アンソアテギ", + "english": "Anzoátegui", + "french": "Anzoátegui", + "german": "Anzoátegui", + "italian": "Anzoátegui", + "spanish": "Anzoátegui", + "chinese_simple": "安索阿特吉州", + "korean": "안소아테기", + "dutch": "Anzoátegui", + "portuguese": "Anzoátegui", + "russian": "Ансоатеги", + "chinese_traditional": "Anzoátegui", + "unknown1": "Anzoátegui", + "unknown2": "Anzoátegui", + "unknown3": "Anzoátegui", + "unknown4": "Anzoátegui" + }, + "coordinates": { + "latitude": 10.129394416, + "longitude": -64.69817279 + } + }, + { + "id": 872742912, + "name": "Apure", + "translations": { + "japanese": "アプレ", + "english": "Apure", + "french": "Apure", + "german": "Apure", + "italian": "Apure", + "spanish": "Apure", + "chinese_simple": "阿普雷州", + "korean": "아푸레", + "dutch": "Apure", + "portuguese": "Apure", + "russian": "Апуре", + "chinese_traditional": "Apure", + "unknown1": "Apure", + "unknown2": "Apure", + "unknown3": "Apure", + "unknown4": "Apure" + }, + "coordinates": { + "latitude": 7.893676668, + "longitude": -67.46673500600001 + } + }, + { + "id": 872808448, + "name": "Aragua", + "translations": { + "japanese": "アラグア", + "english": "Aragua", + "french": "Aragua", + "german": "Aragua", + "italian": "Aragua", + "spanish": "Aragua", + "chinese_simple": "阿拉瓜州", + "korean": "아라과", + "dutch": "Aragua", + "portuguese": "Aragua", + "russian": "Арагуа", + "chinese_traditional": "Aragua", + "unknown1": "Aragua", + "unknown2": "Aragua", + "unknown3": "Aragua", + "unknown4": "Aragua" + }, + "coordinates": { + "latitude": 10.24475086, + "longitude": -67.593078123 + } + }, + { + "id": 872873984, + "name": "Barinas", + "translations": { + "japanese": "バリナス", + "english": "Barinas", + "french": "Barinas", + "german": "Barinas", + "italian": "Barinas", + "spanish": "Barinas", + "chinese_simple": "巴里纳斯州", + "korean": "바리나스", + "dutch": "Barinas", + "portuguese": "Barinas", + "russian": "Баринас", + "chinese_traditional": "Barinas", + "unknown1": "Barinas", + "unknown2": "Barinas", + "unknown3": "Barinas", + "unknown4": "Barinas" + }, + "coordinates": { + "latitude": 8.62426748, + "longitude": -70.202338148 + } + }, + { + "id": 872939520, + "name": "Bolívar", + "translations": { + "japanese": "ボリーバル", + "english": "Bolívar", + "french": "Bolívar", + "german": "Bolívar", + "italian": "Bolívar", + "spanish": "Bolívar", + "chinese_simple": "玻利瓦尔州", + "korean": "볼리바르", + "dutch": "Bolívar", + "portuguese": "Bolívar", + "russian": "Боливар", + "chinese_traditional": "Bolívar", + "unknown1": "Bolívar", + "unknown2": "Bolívar", + "unknown3": "Bolívar", + "unknown4": "Bolívar" + }, + "coordinates": { + "latitude": 8.118896392, + "longitude": -63.54460520000001 + } + }, + { + "id": 873005056, + "name": "Carabobo", + "translations": { + "japanese": "カラボボ", + "english": "Carabobo", + "french": "Carabobo", + "german": "Carabobo", + "italian": "Carabobo", + "spanish": "Carabobo", + "chinese_simple": "卡拉沃沃州", + "korean": "카라보보", + "dutch": "Carabobo", + "portuguese": "Carabobo", + "russian": "Карабобо", + "chinese_traditional": "Carabobo", + "unknown1": "Carabobo", + "unknown2": "Carabobo", + "unknown3": "Carabobo", + "unknown4": "Carabobo" + }, + "coordinates": { + "latitude": 10.178832892, + "longitude": -67.999573369 + } + }, + { + "id": 873070592, + "name": "Cojedes", + "translations": { + "japanese": "コヘデス", + "english": "Cojedes", + "french": "Cojedes", + "german": "Cojedes", + "italian": "Cojedes", + "spanish": "Cojedes", + "chinese_simple": "科赫德斯州", + "korean": "코헤데스", + "dutch": "Cojedes", + "portuguese": "Cojedes", + "russian": "Кохедес", + "chinese_traditional": "Cojedes", + "unknown1": "Cojedes", + "unknown2": "Cojedes", + "unknown3": "Cojedes", + "unknown4": "Cojedes" + }, + "coordinates": { + "latitude": 9.662475476000001, + "longitude": -68.59832988 + } + }, + { + "id": 873136128, + "name": "Delta Amacuro", + "translations": { + "japanese": "デルタ・アマクロ", + "english": "Delta Amacuro", + "french": "Delta Amacuro", + "german": "Delta Amacuro", + "italian": "Delta Amacuro", + "spanish": "Delta Amacuro", + "chinese_simple": "阿马库罗三角洲边疆区", + "korean": "델타아마쿠로", + "dutch": "Delta Amacuro", + "portuguese": "Delta Amacuro", + "russian": "Дельта-Амакуро", + "chinese_traditional": "Delta Amacuro", + "unknown1": "Delta Amacuro", + "unknown2": "Delta Amacuro", + "unknown3": "Delta Amacuro", + "unknown4": "Delta Amacuro" + }, + "coordinates": { + "latitude": 9.0637206, + "longitude": -62.044967333 + } + }, + { + "id": 873201664, + "name": "Falcón", + "translations": { + "japanese": "ファルコン", + "english": "Falcón", + "french": "Falcón", + "german": "Falcón", + "italian": "Falcón", + "spanish": "Falcón", + "chinese_simple": "法尔孔州", + "korean": "팔콘", + "dutch": "Falcón", + "portuguese": "Falcón", + "russian": "Фалькон", + "chinese_traditional": "Falcón", + "unknown1": "Falcón", + "unknown2": "Falcón", + "unknown3": "Falcón", + "unknown4": "Falcón" + }, + "coordinates": { + "latitude": 11.403808464, + "longitude": -69.664006606 + } + }, + { + "id": 873267200, + "name": "Guárico", + "translations": { + "japanese": "グアリコ", + "english": "Guárico", + "french": "Guárico", + "german": "Guárico", + "italian": "Guárico", + "spanish": "Guárico", + "chinese_simple": "瓜里科州", + "korean": "과리코", + "dutch": "Guárico", + "portuguese": "Guárico", + "russian": "Гуарико", + "chinese_traditional": "Guárico", + "unknown1": "Guárico", + "unknown2": "Guárico", + "unknown3": "Guárico", + "unknown4": "Guárico" + }, + "coordinates": { + "latitude": 9.909667856, + "longitude": -67.356871426 + } + }, + { + "id": 873332736, + "name": "Lara", + "translations": { + "japanese": "ララ", + "english": "Lara", + "french": "Lara", + "german": "Lara", + "italian": "Lara", + "spanish": "Lara", + "chinese_simple": "拉腊州", + "korean": "라라", + "dutch": "Lara", + "portuguese": "Lara", + "russian": "Лара", + "chinese_traditional": "Lara", + "unknown1": "Lara", + "unknown2": "Lara", + "unknown3": "Lara", + "unknown4": "Lara" + }, + "coordinates": { + "latitude": 10.068969612, + "longitude": -69.317936329 + } + }, + { + "id": 873398272, + "name": "Mérida", + "translations": { + "japanese": "メリダ", + "english": "Mérida", + "french": "Mérida", + "german": "Mérida", + "italian": "Mérida", + "spanish": "Mérida", + "chinese_simple": "梅里达州", + "korean": "메리다", + "dutch": "Mérida", + "portuguese": "Mérida", + "russian": "Мерида", + "chinese_traditional": "Mérida", + "unknown1": "Mérida", + "unknown2": "Mérida", + "unknown3": "Mérida", + "unknown4": "Mérida" + }, + "coordinates": { + "latitude": 8.59680166, + "longitude": -71.141671757 + } + }, + { + "id": 873463808, + "name": "Miranda", + "translations": { + "japanese": "ミランダ", + "english": "Miranda", + "french": "Miranda", + "german": "Miranda", + "italian": "Miranda", + "spanish": "Miranda", + "chinese_simple": "米兰达州", + "korean": "미란다", + "dutch": "Miranda", + "portuguese": "Miranda", + "russian": "Миранда", + "chinese_traditional": "Miranda", + "unknown1": "Miranda", + "unknown2": "Miranda", + "unknown3": "Miranda", + "unknown4": "Miranda" + }, + "coordinates": { + "latitude": 10.338134648, + "longitude": -67.038267044 + } + }, + { + "id": 873529344, + "name": "Monagas", + "translations": { + "japanese": "モナガス", + "english": "Monagas", + "french": "Monagas", + "german": "Monagas", + "italian": "Monagas", + "spanish": "Monagas", + "chinese_simple": "莫纳加斯州", + "korean": "모나가스", + "dutch": "Monagas", + "portuguese": "Monagas", + "russian": "Монагас", + "chinese_traditional": "Monagas", + "unknown1": "Monagas", + "unknown2": "Monagas", + "unknown3": "Monagas", + "unknown4": "Monagas" + }, + "coordinates": { + "latitude": 9.744872936, + "longitude": -63.171069028000005 + } + }, + { + "id": 873594880, + "name": "Nueva Esparta", + "translations": { + "japanese": "ヌエバエスパルタ", + "english": "Nueva Esparta", + "french": "Nueva Esparta", + "german": "Nueva Esparta", + "italian": "Nueva Esparta", + "spanish": "Nueva Esparta", + "chinese_simple": "新埃斯帕塔州", + "korean": "누에바에스파르타", + "dutch": "Nueva Esparta", + "portuguese": "Nova Esparta", + "russian": "Нуэва-Эспарта", + "chinese_traditional": "Nueva Esparta", + "unknown1": "Nueva Esparta", + "unknown2": "Nueva Esparta", + "unknown3": "Nueva Esparta", + "unknown4": "Nueva Esparta" + }, + "coordinates": { + "latitude": 11.030273312, + "longitude": -63.857716403 + } + }, + { + "id": 873660416, + "name": "Portuguesa", + "translations": { + "japanese": "ポルトゥゲサ", + "english": "Portuguesa", + "french": "Portuguesa", + "german": "Portuguesa", + "italian": "Portuguesa", + "spanish": "Portuguesa", + "chinese_simple": "波图格萨州", + "korean": "포르투게사", + "dutch": "Portuguesa", + "portuguese": "Portuguesa", + "russian": "Португеса", + "chinese_traditional": "Portuguesa", + "unknown1": "Portuguesa", + "unknown2": "Portuguesa", + "unknown3": "Portuguesa", + "unknown4": "Portuguesa" + }, + "coordinates": { + "latitude": 9.047241108, + "longitude": -69.746404291 + } + }, + { + "id": 873725952, + "name": "Sucre", + "translations": { + "japanese": "スクレ", + "english": "Sucre", + "french": "Sucre", + "german": "Sucre", + "italian": "Sucre", + "spanish": "Sucre", + "chinese_simple": "苏克雷州", + "korean": "수크레", + "dutch": "Sucre", + "portuguese": "Sucre", + "russian": "Сукре", + "chinese_traditional": "Sucre", + "unknown1": "Sucre", + "unknown2": "Sucre", + "unknown3": "Sucre", + "unknown4": "Sucre" + }, + "coordinates": { + "latitude": 10.46447742, + "longitude": -64.165334427 + } + }, + { + "id": 873791488, + "name": "Táchira", + "translations": { + "japanese": "タチラ", + "english": "Táchira", + "french": "Táchira", + "german": "Táchira", + "italian": "Táchira", + "spanish": "Táchira", + "chinese_simple": "塔奇拉州", + "korean": "타치라", + "dutch": "Táchira", + "portuguese": "Táchira", + "russian": "Тачира", + "chinese_traditional": "Táchira", + "unknown1": "Táchira", + "unknown2": "Táchira", + "unknown3": "Táchira", + "unknown4": "Táchira" + }, + "coordinates": { + "latitude": 7.7618407320000005, + "longitude": -72.22382802 + } + }, + { + "id": 873857024, + "name": "Trujillo", + "translations": { + "japanese": "トルヒーヨ", + "english": "Trujillo", + "french": "Trujillo", + "german": "Trujillo", + "italian": "Trujillo", + "spanish": "Trujillo", + "chinese_simple": "特鲁希略州", + "korean": "트루히요", + "dutch": "Trujillo", + "portuguese": "Trujillo", + "russian": "Трухильо", + "chinese_traditional": "Trujillo", + "unknown1": "Trujillo", + "unknown2": "Trujillo", + "unknown3": "Trujillo", + "unknown4": "Trujillo" + }, + "coordinates": { + "latitude": 9.36584462, + "longitude": -70.427558487 + } + }, + { + "id": 873922560, + "name": "Yaracuy", + "translations": { + "japanese": "ヤラクイ", + "english": "Yaracuy", + "french": "Yaracuy", + "german": "Yaracuy", + "italian": "Yaracuy", + "spanish": "Yaracuy", + "chinese_simple": "亚拉奎州", + "korean": "야라쿠이", + "dutch": "Yaracuy", + "portuguese": "Yaracuy", + "russian": "Яракуй", + "chinese_traditional": "Yaracuy", + "unknown1": "Yaracuy", + "unknown2": "Yaracuy", + "unknown3": "Yaracuy", + "unknown4": "Yaracuy" + }, + "coordinates": { + "latitude": 10.338134648, + "longitude": -68.735659355 + } + }, + { + "id": 873988096, + "name": "Zulia", + "translations": { + "japanese": "スリア", + "english": "Zulia", + "french": "Zulia", + "german": "Zulia", + "italian": "Zulia", + "spanish": "Zulia", + "chinese_simple": "苏利亚州", + "korean": "술리아", + "dutch": "Zulia", + "portuguese": "Zulia", + "russian": "Сулия", + "chinese_traditional": "Zulia", + "unknown1": "Zulia", + "unknown2": "Zulia", + "unknown3": "Zulia", + "unknown4": "Zulia" + }, + "coordinates": { + "latitude": 10.62927234, + "longitude": -71.636057867 + } + }, + { + "id": 874053632, + "name": "Dependencias Federales", + "translations": { + "japanese": "連邦保護領", + "english": "Dependencias Federales", + "french": "Dépendances Fédérales", + "german": "Dependencias Federales", + "italian": "Dipendenze Federali", + "spanish": "Dependencias Federales", + "chinese_simple": "联邦属地", + "korean": "베네수엘라 연방자치령", + "dutch": "Federale gebieden", + "portuguese": "Dependências Federais", + "russian": "Федеральное владение", + "chinese_traditional": "Dependencias Federales", + "unknown1": "Dependencias Federales", + "unknown2": "Dependencias Federales", + "unknown3": "Dependencias Federales", + "unknown4": "Dependencias Federales" + }, + "coordinates": { + "latitude": 11.997070176, + "longitude": -65.994563034 + } + }, + { + "id": 874119168, + "name": "Vargas", + "translations": { + "japanese": "バルガス", + "english": "Vargas", + "french": "Vargas", + "german": "Vargas", + "italian": "Vargas", + "spanish": "Vargas", + "chinese_simple": "巴尔加斯州", + "korean": "바르가스", + "dutch": "Vargas", + "portuguese": "Vargas", + "russian": "Варгас", + "chinese_traditional": "Vargas", + "unknown1": "Vargas", + "unknown2": "Vargas", + "unknown3": "Vargas", + "unknown4": "Vargas" + }, + "coordinates": { + "latitude": 10.596313356, + "longitude": -66.928403464 + } + } + ] + }, + { + "id": 64, + "iso_code": "AL", + "name": "Albania", + "translations": { + "japanese": "アルバニア", + "english": "Albania", + "french": "Albanie", + "german": "Albanien", + "italian": "Albania", + "spanish": "Albania", + "chinese_simple": "阿尔巴尼亚", + "korean": "알바니아", + "dutch": "Albanië", + "portuguese": "Albânia", + "russian": "Албания", + "chinese_traditional": "Albania", + "unknown1": "Albania", + "unknown2": "Albania", + "unknown3": "Albania", + "unknown4": "Albania" + }, + "regions": [ + { + "id": 1073741824, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 41.325072772, + "longitude": 19.824883011 + } + }, + { + "id": 1073872896, + "name": "Tirana", + "translations": { + "japanese": "ティラナ州", + "english": "Tirana", + "french": "Tirana", + "german": "Tirana", + "italian": "Tirana", + "spanish": "Tirana", + "chinese_simple": "地拉那州", + "korean": "티라나 주", + "dutch": "Tirana", + "portuguese": "Tirana", + "russian": "Тирана", + "chinese_traditional": "Tirana", + "unknown1": "Tirana", + "unknown2": "Tirana", + "unknown3": "Tirana", + "unknown4": "Tirana" + }, + "coordinates": { + "latitude": 41.325072772, + "longitude": 19.824883011 + } + }, + { + "id": 1073938432, + "name": "Berat", + "translations": { + "japanese": "ベラト州", + "english": "Berat", + "french": "Berat", + "german": "Berat", + "italian": "Berat", + "spanish": "Berat", + "chinese_simple": "培拉特州", + "korean": "베라트 주", + "dutch": "Berat", + "portuguese": "Berat", + "russian": "Берат", + "chinese_traditional": "Berat", + "unknown1": "Berat", + "unknown2": "Berat", + "unknown3": "Berat", + "unknown4": "Berat" + }, + "coordinates": { + "latitude": 40.70434524, + "longitude": 19.967705665 + } + }, + { + "id": 1074003968, + "name": "Dibër", + "translations": { + "japanese": "ディブラ州", + "english": "Dibër", + "french": "Dibër", + "german": "Dibra", + "italian": "Dibër", + "spanish": "Dibër", + "chinese_simple": "迪勃拉州", + "korean": "디브라 주", + "dutch": "Dibër", + "portuguese": "Dibër", + "russian": "Дибра", + "chinese_traditional": "Dibër", + "unknown1": "Dibër", + "unknown2": "Dibër", + "unknown3": "Dibër", + "unknown4": "Dibër" + }, + "coordinates": { + "latitude": 41.682128432, + "longitude": 20.440119059 + } + }, + { + "id": 1074069504, + "name": "Durrës", + "translations": { + "japanese": "デュラス州", + "english": "Durrës", + "french": "Durrës", + "german": "Durrës", + "italian": "Durazzo", + "spanish": "Durrës", + "chinese_simple": "都拉斯州", + "korean": "두러스 주", + "dutch": "Durrës", + "portuguese": "Durrës", + "russian": "Дуррес", + "chinese_traditional": "Durrës", + "unknown1": "Durrës", + "unknown2": "Durrës", + "unknown3": "Durrës", + "unknown4": "Durrës" + }, + "coordinates": { + "latitude": 41.319579608, + "longitude": 19.451346839 + } + }, + { + "id": 1074135040, + "name": "Elbasan", + "translations": { + "japanese": "エルバサン州", + "english": "Elbasan", + "french": "Elbasan", + "german": "Elbasan", + "italian": "Elbasan", + "spanish": "Elbasan", + "chinese_simple": "爱尔巴桑州", + "korean": "엘바산 주", + "dutch": "Elbasan", + "portuguese": "Elbasan", + "russian": "Эльбасан", + "chinese_traditional": "Elbasan", + "unknown1": "Elbasan", + "unknown2": "Elbasan", + "unknown3": "Elbasan", + "unknown4": "Elbasan" + }, + "coordinates": { + "latitude": 41.044921408, + "longitude": 19.99517156 + } + }, + { + "id": 1074200576, + "name": "Fier", + "translations": { + "japanese": "フィエル州", + "english": "Fier", + "french": "Fier", + "german": "Fier", + "italian": "Fier", + "spanish": "Fier", + "chinese_simple": "费里州", + "korean": "피에르 주", + "dutch": "Fier", + "portuguese": "Fier", + "russian": "Фиери", + "chinese_traditional": "Fier", + "unknown1": "Fier", + "unknown2": "Fier", + "unknown3": "Fier", + "unknown4": "Fier" + }, + "coordinates": { + "latitude": 40.720824732, + "longitude": 19.566703598 + } + }, + { + "id": 1074266112, + "name": "Gjirokastër", + "translations": { + "japanese": "ギロカストラ州", + "english": "Gjirokastër", + "french": "Gjirokastër", + "german": "Gjirokastra", + "italian": "Argirocastro", + "spanish": "Gjirokastra", + "chinese_simple": "吉诺卡斯特州", + "korean": "지로카스터르 주", + "dutch": "Gjirokastër", + "portuguese": "Gjirokastra", + "russian": "Гирокастра", + "chinese_traditional": "Gjirokastër", + "unknown1": "Gjirokastër", + "unknown2": "Gjirokastër", + "unknown3": "Gjirokastër", + "unknown4": "Gjirokastër" + }, + "coordinates": { + "latitude": 40.07263138, + "longitude": 20.143487393 + } + }, + { + "id": 1074331648, + "name": "Korçë", + "translations": { + "japanese": "コルチャ州", + "english": "Korçë", + "french": "Korçë", + "german": "Korça", + "italian": "Coriza", + "spanish": "Korçë", + "chinese_simple": "科尔察州", + "korean": "코르처 주", + "dutch": "Korçë", + "portuguese": "Korçë", + "russian": "Корча", + "chinese_traditional": "Korçë", + "unknown1": "Korçë", + "unknown2": "Korçë", + "unknown3": "Korçë", + "unknown4": "Korçë" + }, + "coordinates": { + "latitude": 40.616454616, + "longitude": 20.786189336 + } + }, + { + "id": 1074397184, + "name": "Kukës", + "translations": { + "japanese": "クケス州", + "english": "Kukës", + "french": "Kukës", + "german": "Kukës", + "italian": "Kukës", + "spanish": "Kukës", + "chinese_simple": "库克斯州", + "korean": "쿠커스 주", + "dutch": "Kukës", + "portuguese": "Kukës", + "russian": "Кукес", + "chinese_traditional": "Kukës", + "unknown1": "Kukës", + "unknown2": "Kukës", + "unknown3": "Kukës", + "unknown4": "Kukës" + }, + "coordinates": { + "latitude": 42.07763624, + "longitude": 20.429132701 + } + }, + { + "id": 1074462720, + "name": "Lezhë", + "translations": { + "japanese": "レジャ州", + "english": "Lezhë", + "french": "Lezhë", + "german": "Lezha", + "italian": "Alessio", + "spanish": "Lezhë", + "chinese_simple": "莱什州", + "korean": "레저 주", + "dutch": "Lezhë", + "portuguese": "Lezhë", + "russian": "Лежа", + "chinese_traditional": "Lezhë", + "unknown1": "Lezhë", + "unknown2": "Lezhë", + "unknown3": "Lezhë", + "unknown4": "Lezhë" + }, + "coordinates": { + "latitude": 41.781005384000004, + "longitude": 19.649101283 + } + }, + { + "id": 1074528256, + "name": "Shkodër", + "translations": { + "japanese": "シュコドラ州", + "english": "Shkodër", + "french": "Shkodër", + "german": "Shkodra", + "italian": "Scutari", + "spanish": "Shkodër", + "chinese_simple": "斯库台州", + "korean": "슈코더르 주", + "dutch": "Shkodër", + "portuguese": "Shkodër", + "russian": "Шкодер", + "chinese_traditional": "Shkodër", + "unknown1": "Shkodër", + "unknown2": "Shkodër", + "unknown3": "Shkodër", + "unknown4": "Shkodër" + }, + "coordinates": { + "latitude": 42.072143076, + "longitude": 19.522758166 + } + }, + { + "id": 1074593792, + "name": "Vlorë", + "translations": { + "japanese": "ヴロラ州", + "english": "Vlorë", + "french": "Vlorë", + "german": "Vlora", + "italian": "Valona", + "spanish": "Vlorë", + "chinese_simple": "发罗拉州", + "korean": "블로러 주", + "dutch": "Vlorë", + "portuguese": "Vlorë", + "russian": "Влёра", + "chinese_traditional": "Vlorë", + "unknown1": "Vlorë", + "unknown2": "Vlorë", + "unknown3": "Vlorë", + "unknown4": "Vlorë" + }, + "coordinates": { + "latitude": 40.468139188, + "longitude": 19.484305913 + } + } + ] + }, + { + "id": 65, + "iso_code": "AU", + "name": "Australia", + "translations": { + "japanese": "オーストラリア", + "english": "Australia", + "french": "Australie", + "german": "Australien", + "italian": "Australia", + "spanish": "Australia", + "chinese_simple": "澳大利亚", + "korean": "오스트레일리아", + "dutch": "Australië", + "portuguese": "Austrália", + "russian": "Австралия", + "chinese_traditional": "Australia", + "unknown1": "Australia", + "unknown2": "Australia", + "unknown3": "Australia", + "unknown4": "Australia" + }, + "regions": [ + { + "id": 1090519040, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": -33.88732974, + "longitude": 151.238204228 + } + }, + { + "id": 1090650112, + "name": "Australian Capital Territory", + "translations": { + "japanese": "オーストラリア首都特別地域", + "english": "Australian Capital Territory", + "french": "Territoire de la capitale australienne", + "german": "Australisches Hauptstadtterritorium", + "italian": "Territorio della Capitale Australiana", + "spanish": "Territorio de la Capital Australiana", + "chinese_simple": "澳大利亚首都直辖区", + "korean": "오스트레일리아캐피털테리토리", + "dutch": "Australisch Hoofdstedelijk Territorium", + "portuguese": "Território da Capital Australiana", + "russian": "Австралийская столичная территория", + "chinese_traditional": "Australian Capital Territory", + "unknown1": "Australian Capital Territory", + "unknown2": "Australian Capital Territory", + "unknown3": "Australian Capital Territory", + "unknown4": "Australian Capital Territory" + }, + "coordinates": { + "latitude": -35.348511364, + "longitude": 149.040932628 + } + }, + { + "id": 1090715648, + "name": "New South Wales", + "translations": { + "japanese": "ニューサウスウェールズ州", + "english": "New South Wales", + "french": "Nouvelle-Galles du Sud", + "german": "Neusüdwales", + "italian": "Nuovo Galles del Sud", + "spanish": "Nueva Gales del Sur", + "chinese_simple": "新南威尔士州", + "korean": "뉴사우스웨일스 주", + "dutch": "Nieuw-Zuid-Wales", + "portuguese": "Nova Gales do Sul", + "russian": "Новый Южный Уэльс", + "chinese_traditional": "New South Wales", + "unknown1": "New South Wales", + "unknown2": "New South Wales", + "unknown3": "New South Wales", + "unknown4": "New South Wales" + }, + "coordinates": { + "latitude": -33.88732974, + "longitude": 151.238204228 + } + }, + { + "id": 1090781184, + "name": "Northern Territory", + "translations": { + "japanese": "ノーザンテリトリー", + "english": "Northern Territory", + "french": "Territoire du Nord", + "german": "Nördliches Territorium", + "italian": "Territorio del Nord", + "spanish": "Territorio del Norte", + "chinese_simple": "北部地区", + "korean": "노던테리토리 주", + "dutch": "Noordelijk Territorium", + "portuguese": "Território do Norte", + "russian": "Северная территория", + "chinese_traditional": "Northern Territory", + "unknown1": "Northern Territory", + "unknown2": "Northern Territory", + "unknown3": "Northern Territory", + "unknown4": "Northern Territory" + }, + "coordinates": { + "latitude": -12.431031156000003, + "longitude": 130.842030601 + } + }, + { + "id": 1090846720, + "name": "Queensland", + "translations": { + "japanese": "クィーンズランド州", + "english": "Queensland", + "french": "Queensland", + "german": "Queensland", + "italian": "Queensland", + "spanish": "Queensland", + "chinese_simple": "昆士兰州", + "korean": "퀸즐랜드 주", + "dutch": "Queensland", + "portuguese": "Queensland", + "russian": "Квинсленд", + "chinese_traditional": "Queensland", + "unknown1": "Queensland", + "unknown2": "Queensland", + "unknown3": "Queensland", + "unknown4": "Queensland" + }, + "coordinates": { + "latitude": -27.449341532, + "longitude": 153.023487403 + } + }, + { + "id": 1090912256, + "name": "South Australia", + "translations": { + "japanese": "南オーストラリア州", + "english": "South Australia", + "french": "Australie-Méridionale", + "german": "Südaustralien", + "italian": "Australia Meridionale", + "spanish": "Australia Meridional", + "chinese_simple": "南澳大利亚州", + "korean": "사우스오스트레일리아 주", + "dutch": "Zuid-Australië", + "portuguese": "Austrália Meridional", + "russian": "Южная Австралия", + "chinese_traditional": "South Australia", + "unknown1": "South Australia", + "unknown2": "South Australia", + "unknown3": "South Australia", + "unknown4": "South Australia" + }, + "coordinates": { + "latitude": -34.914551408, + "longitude": 138.609385707 + } + }, + { + "id": 1090977792, + "name": "Tasmania", + "translations": { + "japanese": "タスマニア州", + "english": "Tasmania", + "french": "Tasmanie", + "german": "Tasmanien", + "italian": "Tasmania", + "spanish": "Tasmania", + "chinese_simple": "塔斯马尼亚州", + "korean": "태즈메이니아 주", + "dutch": "Tasmanië", + "portuguese": "Tasmânia", + "russian": "Тасмания", + "chinese_traditional": "Tasmania", + "unknown1": "Tasmania", + "unknown2": "Tasmania", + "unknown3": "Tasmania", + "unknown4": "Tasmania" + }, + "coordinates": { + "latitude": -42.846680223999996, + "longitude": 147.288608527 + } + }, + { + "id": 1091043328, + "name": "Victoria", + "translations": { + "japanese": "ヴィクトリア州", + "english": "Victoria", + "french": "Victoria", + "german": "Victoria", + "italian": "Victoria", + "spanish": "Victoria", + "chinese_simple": "维多利亚州", + "korean": "빅토리아 주", + "dutch": "Victoria", + "portuguese": "Victoria", + "russian": "Виктория", + "chinese_traditional": "Victoria", + "unknown1": "Victoria", + "unknown2": "Victoria", + "unknown3": "Victoria", + "unknown4": "Victoria" + }, + "coordinates": { + "latitude": -37.809448836, + "longitude": 144.96499381 + } + }, + { + "id": 1091108864, + "name": "Western Australia", + "translations": { + "japanese": "西オーストラリア州", + "english": "Western Australia", + "french": "Australie-Occidentale", + "german": "Westaustralien", + "italian": "Australia Occidentale", + "spanish": "Australia Occidental", + "chinese_simple": "西澳大利亚州", + "korean": "웨스턴오스트레일리아 주", + "dutch": "West-Australië", + "portuguese": "Austrália Ocidental", + "russian": "Западная Австралия", + "chinese_traditional": "Western Australia", + "unknown1": "Western Australia", + "unknown2": "Western Australia", + "unknown3": "Western Australia", + "unknown4": "Western Australia" + }, + "coordinates": { + "latitude": -31.931763355999998, + "longitude": 115.862131468 + } + } + ] + }, + { + "id": 66, + "iso_code": "AT", + "name": "Austria", + "translations": { + "japanese": "オーストリア", + "english": "Austria", + "french": "Autriche", + "german": "Österreich", + "italian": "Austria", + "spanish": "Austria", + "chinese_simple": "奥地利", + "korean": "오스트리아", + "dutch": "Oostenrijk", + "portuguese": "Áustria", + "russian": "Австрия", + "chinese_traditional": "Austria", + "unknown1": "Austria", + "unknown2": "Austria", + "unknown3": "Austria", + "unknown4": "Austria" + }, + "regions": [ + { + "id": 1107296256, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 48.2025141, + "longitude": 16.36967342 + } + }, + { + "id": 1107427328, + "name": "Vienna", + "translations": { + "japanese": "ウィーン", + "english": "Vienna", + "french": "Vienne", + "german": "Wien", + "italian": "Vienna", + "spanish": "Viena", + "chinese_simple": "维也纳州", + "korean": "빈", + "dutch": "Wenen", + "portuguese": "Viena", + "russian": "Вена", + "chinese_traditional": "Vienna", + "unknown1": "Vienna", + "unknown2": "Vienna", + "unknown3": "Vienna", + "unknown4": "Vienna" + }, + "coordinates": { + "latitude": 48.2025141, + "longitude": 16.36967342 + } + }, + { + "id": 1107492864, + "name": "Burgenland", + "translations": { + "japanese": "ブルゲンラント州", + "english": "Burgenland", + "french": "Burgenland", + "german": "Burgenland", + "italian": "Burgenland", + "spanish": "Burgenland", + "chinese_simple": "布尔根兰州", + "korean": "부르겐란트 주", + "dutch": "Burgenland", + "portuguese": "Burgenland", + "russian": "Бургенланд", + "chinese_traditional": "Burgenland", + "unknown1": "Burgenland", + "unknown2": "Burgenland", + "unknown3": "Burgenland", + "unknown4": "Burgenland" + }, + "coordinates": { + "latitude": 47.84545844, + "longitude": 16.512496074 + } + }, + { + "id": 1107558400, + "name": "Carinthia", + "translations": { + "japanese": "ケルンテン州", + "english": "Carinthia", + "french": "Carinthie", + "german": "Kärnten", + "italian": "Carinzia", + "spanish": "Carintia", + "chinese_simple": "克恩顿州", + "korean": "케른텐 주", + "dutch": "Karinthië", + "portuguese": "Caríntia", + "russian": "Каринтия", + "chinese_traditional": "Carinthia", + "unknown1": "Carinthia", + "unknown2": "Carinthia", + "unknown3": "Carinthia", + "unknown4": "Carinthia" + }, + "coordinates": { + "latitude": 46.614989704, + "longitude": 14.298744937 + } + }, + { + "id": 1107623936, + "name": "Lower Austria", + "translations": { + "japanese": "ニーダー・エスターライヒ州", + "english": "Lower Austria", + "french": "Basse-Autriche", + "german": "Niederösterreich", + "italian": "Bassa Austria", + "spanish": "Baja Austria", + "chinese_simple": "下奥地利州", + "korean": "니더외스터라이히 주", + "dutch": "Neder-Oostenrijk", + "portuguese": "Baixa Áustria", + "russian": "Нижняя Австрия", + "chinese_traditional": "Lower Austria", + "unknown1": "Lower Austria", + "unknown2": "Lower Austria", + "unknown3": "Lower Austria", + "unknown4": "Lower Austria" + }, + "coordinates": { + "latitude": 48.197020936, + "longitude": 15.617107897 + } + }, + { + "id": 1107689472, + "name": "Upper Austria", + "translations": { + "japanese": "オーバー・エスターライヒ州", + "english": "Upper Austria", + "french": "Haute-Autriche", + "german": "Oberösterreich", + "italian": "Alta Austria", + "spanish": "Alta Austria", + "chinese_simple": "上奥地利州", + "korean": "오버외스터라이히 주", + "dutch": "Opper-Oostenrijk", + "portuguese": "Alta Áustria", + "russian": "Верхняя Австрия", + "chinese_traditional": "Upper Austria", + "unknown1": "Upper Austria", + "unknown2": "Upper Austria", + "unknown3": "Upper Austria", + "unknown4": "Upper Austria" + }, + "coordinates": { + "latitude": 48.295897888, + "longitude": 14.287758579 + } + }, + { + "id": 1107755008, + "name": "Salzburg", + "translations": { + "japanese": "ザルツブルク州", + "english": "Salzburg", + "french": "Salzbourg", + "german": "Salzburg", + "italian": "Salisburghese", + "spanish": "Salzburgo", + "chinese_simple": "萨尔茨堡州", + "korean": "잘츠부르크 주", + "dutch": "Salzburg", + "portuguese": "Salzburgo", + "russian": "Зальцбург", + "chinese_traditional": "Salzburg", + "unknown1": "Salzburg", + "unknown2": "Salzburg", + "unknown3": "Salzburg", + "unknown4": "Salzburg" + }, + "coordinates": { + "latitude": 47.796019964, + "longitude": 13.029820588 + } + }, + { + "id": 1107820544, + "name": "Styria", + "translations": { + "japanese": "シュタイアーマルク州", + "english": "Styria", + "french": "Styrie", + "german": "Steiermark", + "italian": "Stiria", + "spanish": "Estiria", + "chinese_simple": "施蒂利亚州", + "korean": "슈타이어마르크 주", + "dutch": "Stiermarken", + "portuguese": "Estíria", + "russian": "Штирия", + "chinese_traditional": "Styria", + "unknown1": "Styria", + "unknown2": "Styria", + "unknown3": "Styria", + "unknown4": "Styria" + }, + "coordinates": { + "latitude": 47.065429152, + "longitude": 15.43583299 + } + }, + { + "id": 1107886080, + "name": "Tyrol", + "translations": { + "japanese": "ティロル州", + "english": "Tyrol", + "french": "Tyrol", + "german": "Tirol", + "italian": "Tirolo", + "spanish": "Tirol", + "chinese_simple": "蒂罗尔州", + "korean": "티롤 주", + "dutch": "Tirol", + "portuguese": "Tirol", + "russian": "Тироль", + "chinese_traditional": "Tyrol", + "unknown1": "Tyrol", + "unknown2": "Tyrol", + "unknown3": "Tyrol", + "unknown4": "Tyrol" + }, + "coordinates": { + "latitude": 47.263183056, + "longitude": 11.381866888 + } + }, + { + "id": 1107951616, + "name": "Vorarlberg", + "translations": { + "japanese": "フォアアールベルク州", + "english": "Vorarlberg", + "french": "Vorarlberg", + "german": "Vorarlberg", + "italian": "Vorarlberg", + "spanish": "Vorarlberg", + "chinese_simple": "福拉尔贝格州", + "korean": "포어아를베르크 주", + "dutch": "Vorarlberg", + "portuguese": "Vorarlberg", + "russian": "Форарльберг", + "chinese_traditional": "Vorarlberg", + "unknown1": "Vorarlberg", + "unknown2": "Vorarlberg", + "unknown3": "Vorarlberg", + "unknown4": "Vorarlberg" + }, + "coordinates": { + "latitude": 47.499389108, + "longitude": 9.744899546 + } + } + ] + }, + { + "id": 67, + "iso_code": "BE", + "name": "Belgium", + "translations": { + "japanese": "ベルギー", + "english": "Belgium", + "french": "Belgique", + "german": "Belgien", + "italian": "Belgio", + "spanish": "Bélgica", + "chinese_simple": "比利时", + "korean": "벨기에", + "dutch": "België", + "portuguese": "Bélgica", + "russian": "Бельгия", + "chinese_traditional": "Belgium", + "unknown1": "Belgium", + "unknown2": "Belgium", + "unknown3": "Belgium", + "unknown4": "Belgium" + }, + "regions": [ + { + "id": 1124073472, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 50.83923282, + "longitude": 4.367077305 + } + }, + { + "id": 1124204544, + "name": "Brussels Region", + "translations": { + "japanese": "ブリュッセル首都地域圏", + "english": "Brussels Region", + "french": "Région de Bruxelles-Capitale", + "german": "Region Brüssel-Hauptstadt", + "italian": "Regione di Bruxelles", + "spanish": "Región de Bruselas-Capital", + "chinese_simple": "布鲁塞尔首都大区", + "korean": "브뤼셀 지역", + "dutch": "Brussels Hoofdstedelijk Gewest", + "portuguese": "Região de Bruxelas - Capital", + "russian": "Брюссельский столичный округ", + "chinese_traditional": "Brussels Region", + "unknown1": "Brussels Region", + "unknown2": "Brussels Region", + "unknown3": "Brussels Region", + "unknown4": "Brussels Region" + }, + "coordinates": { + "latitude": 50.83923282, + "longitude": 4.367077305 + } + }, + { + "id": 1124270080, + "name": "Flanders", + "translations": { + "japanese": "フランデレン地域圏", + "english": "Flanders", + "french": "Région flamande", + "german": "Flandern", + "italian": "Fiandre", + "spanish": "Región de Flandes", + "chinese_simple": "佛兰德大区", + "korean": "플랑드르 지역", + "dutch": "Vlaanderen", + "portuguese": "Flandres", + "russian": "Фламандский регион", + "chinese_traditional": "Flanders", + "unknown1": "Flanders", + "unknown2": "Flanders", + "unknown3": "Flanders", + "unknown4": "Flanders" + }, + "coordinates": { + "latitude": 50.83923282, + "longitude": 4.367077305 + } + }, + { + "id": 1124335616, + "name": "Wallonia", + "translations": { + "japanese": "ワロン地域圏", + "english": "Wallonia", + "french": "Région wallonne", + "german": "Wallonien", + "italian": "Vallonia", + "spanish": "Región de Valonia", + "chinese_simple": "瓦隆大区", + "korean": "왈롱 지역", + "dutch": "Wallonië", + "portuguese": "Valónia", + "russian": "Валлонский регион", + "chinese_traditional": "Wallonia", + "unknown1": "Wallonia", + "unknown2": "Wallonia", + "unknown3": "Wallonia", + "unknown4": "Wallonia" + }, + "coordinates": { + "latitude": 50.465697668, + "longitude": 4.861463415 + } + } + ] + }, + { + "id": 68, + "iso_code": "BA", + "name": "Bosnia and Herzegovina", + "translations": { + "japanese": "ボスニア・ヘルツェゴビナ", + "english": "Bosnia and Herzegovina", + "french": "Bosnie-Herzégovine", + "german": "Bosnien-Herzegowina", + "italian": "Bosnia-Erzegovina", + "spanish": "Bosnia-Herzegovina", + "chinese_simple": "波斯尼亚和黑塞哥维那", + "korean": "보스니아헤르체고비나", + "dutch": "Bosnië en Herzegovina", + "portuguese": "Bósnia-Herzegovina", + "russian": "Босния и Герцеговина", + "chinese_traditional": "Bosnia and Herzegovina", + "unknown1": "Bosnia and Herzegovina", + "unknown2": "Bosnia and Herzegovina", + "unknown3": "Bosnia and Herzegovina", + "unknown4": "Bosnia and Herzegovina" + }, + "regions": [ + { + "id": 1140850688, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 43.851928212, + "longitude": 18.407642829 + } + }, + { + "id": 1140981760, + "name": "Federation of Bosnia and Herzegovina", + "translations": { + "japanese": "ボスニア・ヘルツェゴビナ連邦", + "english": "Federation of Bosnia and Herzegovina", + "french": "Fédération de Bosnie-Herzégovine", + "german": "Föderation Bosnien und Herzegowina", + "italian": "Federazione di Bosnia-Erzegovina", + "spanish": "Federación de Bosnia-Herzegovina", + "chinese_simple": "波黑联邦", + "korean": "보스니아헤르체고비나 연방", + "dutch": "Moslim-Kroatische Federatie", + "portuguese": "Federação da Bósnia-Herzegovina", + "russian": "Федерация Боснии и Герцеговины", + "chinese_traditional": "Federation of Bosnia and Herzegovina", + "unknown1": "Federation of Bosnia and Herzegovina", + "unknown2": "Federation of Bosnia and Herzegovina", + "unknown3": "Federation of Bosnia and Herzegovina", + "unknown4": "Federation of Bosnia and Herzegovina" + }, + "coordinates": { + "latitude": 43.851928212, + "longitude": 18.407642829 + } + }, + { + "id": 1141047296, + "name": "Republika Srpska", + "translations": { + "japanese": "セルビア人共和国", + "english": "Republika Srpska", + "french": "République serbe de Bosnie", + "german": "Serbische Republik", + "italian": "Repubblica Serba di Bosnia-Erzegovina", + "spanish": "República Srpska", + "chinese_simple": "塞族共和国", + "korean": "스릅스카 공화국", + "dutch": "Servische Republiek", + "portuguese": "República Sérvia", + "russian": "Республика Сербская", + "chinese_traditional": "Republika Srpska", + "unknown1": "Republika Srpska", + "unknown2": "Republika Srpska", + "unknown3": "Republika Srpska", + "unknown4": "Republika Srpska" + }, + "coordinates": { + "latitude": 44.7692866, + "longitude": 17.19365027 + } + }, + { + "id": 1141112832, + "name": "Brčko District", + "translations": { + "japanese": "ブルチュコ", + "english": "Brčko District", + "french": "Brčko (district)", + "german": "Brčko-Distrikt", + "italian": "Distretto di Brčko", + "spanish": "Distrito de Brčko", + "chinese_simple": "布尔奇科特区", + "korean": "브르치코", + "dutch": "Brčko", + "portuguese": "Distrito de Brčko", + "russian": "Округ Брчко", + "chinese_traditional": "Brčko District", + "unknown1": "Brčko District", + "unknown2": "Brčko District", + "unknown3": "Brčko District", + "unknown4": "Brčko District" + }, + "coordinates": { + "latitude": 44.868163552, + "longitude": 18.803151717 + } + } + ] + }, + { + "id": 69, + "iso_code": "BW", + "name": "Botswana", + "translations": { + "japanese": "ボツワナ", + "english": "Botswana", + "french": "Botswana", + "german": "Botsuana", + "italian": "Botswana", + "spanish": "Botsuana", + "chinese_simple": "博茨瓦纳", + "korean": "보츠와나", + "dutch": "Botswana", + "portuguese": "Botsuana", + "russian": "Ботсвана", + "chinese_traditional": "Botswana", + "unknown1": "Botswana", + "unknown2": "Botswana", + "unknown3": "Botswana", + "unknown4": "Botswana" + }, + "regions": [ + { + "id": 1157627904, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": -24.647827891999995, + "longitude": 25.900338985 + } + }, + { + "id": 1157693440, + "name": "Botswana", + "translations": { + "japanese": "ボツワナ", + "english": "Botswana", + "french": "Botswana", + "german": "Botsuana", + "italian": "Botswana", + "spanish": "Botsuana", + "chinese_simple": "博茨瓦纳", + "korean": "보츠와나", + "dutch": "Botswana", + "portuguese": "Botsuana", + "russian": "Ботсвана", + "chinese_traditional": "Botswana", + "unknown1": "Botswana", + "unknown2": "Botswana", + "unknown3": "Botswana", + "unknown4": "Botswana" + }, + "coordinates": { + "latitude": -24.647827891999995, + "longitude": 25.900338985 + } + } + ] + }, + { + "id": 70, + "iso_code": "BG", + "name": "Bulgaria", + "translations": { + "japanese": "ブルガリア", + "english": "Bulgaria", + "french": "Bulgarie", + "german": "Bulgarien", + "italian": "Bulgaria", + "spanish": "Bulgaria", + "chinese_simple": "保加利亚", + "korean": "불가리아", + "dutch": "Bulgarije", + "portuguese": "Bulgária", + "russian": "Болгария", + "chinese_traditional": "Bulgaria", + "unknown1": "Bulgaria", + "unknown2": "Bulgaria", + "unknown3": "Bulgaria", + "unknown4": "Bulgaria" + }, + "regions": [ + { + "id": 1174405120, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 42.703856936, + "longitude": 23.302065318 + } + }, + { + "id": 1174536192, + "name": "Sofia City", + "translations": { + "japanese": "ソフィア市", + "english": "Sofia City", + "french": "Sofia (ville)", + "german": "Sofia (Stadt)", + "italian": "Sofia", + "spanish": "Ciudad de Sofía", + "chinese_simple": "索非亚市", + "korean": "소피아", + "dutch": "Sofia (stad)", + "portuguese": "Sófia (cidade)", + "russian": "София", + "chinese_traditional": "Sofia City", + "unknown1": "Sofia City", + "unknown2": "Sofia City", + "unknown3": "Sofia City", + "unknown4": "Sofia City" + }, + "coordinates": { + "latitude": 42.703856936, + "longitude": 23.302065318 + } + }, + { + "id": 1174601728, + "name": "Sofia Province", + "translations": { + "japanese": "ソフィア州", + "english": "Sofia Province", + "french": "Sofia (oblast)", + "german": "Sofia (Region)", + "italian": "Regione di Sofia", + "spanish": "Provincia de Sofía", + "chinese_simple": "索非亚州", + "korean": "소피아 주", + "dutch": "Sofia (oblast)", + "portuguese": "Província de Sófia", + "russian": "Софийская область", + "chinese_traditional": "Sofia Province", + "unknown1": "Sofia Province", + "unknown2": "Sofia Province", + "unknown3": "Sofia Province", + "unknown4": "Sofia Province" + }, + "coordinates": { + "latitude": 42.703856936, + "longitude": 23.302065318 + } + }, + { + "id": 1174667264, + "name": "Blagoevgrad", + "translations": { + "japanese": "ブラゴエブグラト州", + "english": "Blagoevgrad", + "french": "Blagoevgrad", + "german": "Blagoewgrad", + "italian": "Blagoevgrad", + "spanish": "Blagoevgrad", + "chinese_simple": "布拉格耶夫格勒州", + "korean": "블라고예브그라드 주", + "dutch": "Blagoëvgrad", + "portuguese": "Blagoevgrad", + "russian": "Благоевград", + "chinese_traditional": "Blagoevgrad", + "unknown1": "Blagoevgrad", + "unknown2": "Blagoevgrad", + "unknown3": "Blagoevgrad", + "unknown4": "Blagoevgrad" + }, + "coordinates": { + "latitude": 42.017211436000004, + "longitude": 23.098817695 + } + }, + { + "id": 1174732800, + "name": "Pleven", + "translations": { + "japanese": "プレベン州", + "english": "Pleven", + "french": "Pleven", + "german": "Plewen", + "italian": "Pleven", + "spanish": "Pleven", + "chinese_simple": "普列文州", + "korean": "플레벤 주", + "dutch": "Pleven", + "portuguese": "Pleven", + "russian": "Плевен", + "chinese_traditional": "Pleven", + "unknown1": "Pleven", + "unknown2": "Pleven", + "unknown3": "Pleven", + "unknown4": "Pleven" + }, + "coordinates": { + "latitude": 43.417968256, + "longitude": 24.620428278 + } + }, + { + "id": 1174798336, + "name": "Vidin", + "translations": { + "japanese": "ビディン州", + "english": "Vidin", + "french": "Vidin", + "german": "Widin", + "italian": "Vidin", + "spanish": "Vidin", + "chinese_simple": "维丁州", + "korean": "비딘 주", + "dutch": "Vidin", + "portuguese": "Vidin", + "russian": "Видин", + "chinese_traditional": "Vidin", + "unknown1": "Vidin", + "unknown2": "Vidin", + "unknown3": "Vidin", + "unknown4": "Vidin" + }, + "coordinates": { + "latitude": 43.989257312, + "longitude": 22.873597356 + } + }, + { + "id": 1174863872, + "name": "Varna", + "translations": { + "japanese": "バルナ州", + "english": "Varna", + "french": "Varna", + "german": "Warna", + "italian": "Varna", + "spanish": "Varna", + "chinese_simple": "瓦尔纳州", + "korean": "바르나 주", + "dutch": "Varna", + "portuguese": "Varna", + "russian": "Варна", + "chinese_traditional": "Varna", + "unknown1": "Varna", + "unknown2": "Varna", + "unknown3": "Varna", + "unknown4": "Varna" + }, + "coordinates": { + "latitude": 43.20373486, + "longitude": 27.899856141 + } + }, + { + "id": 1174929408, + "name": "Burgas", + "translations": { + "japanese": "ブルガス州", + "english": "Burgas", + "french": "Bourgas", + "german": "Burgas", + "italian": "Burgas", + "spanish": "Burgas", + "chinese_simple": "布尔加斯州", + "korean": "부르가스 주", + "dutch": "Boergas", + "portuguese": "Burgas", + "russian": "Бургас", + "chinese_traditional": "Burgas", + "unknown1": "Burgas", + "unknown2": "Burgas", + "unknown3": "Burgas", + "unknown4": "Burgas" + }, + "coordinates": { + "latitude": 42.522582524, + "longitude": 27.454908642 + } + }, + { + "id": 1174994944, + "name": "Dobrich", + "translations": { + "japanese": "ドブリチ州", + "english": "Dobrich", + "french": "Dobritch", + "german": "Dobritsch", + "italian": "Dobrich", + "spanish": "Dobrich", + "chinese_simple": "多布里奇州", + "korean": "도브리치 주", + "dutch": "Dobritsj", + "portuguese": "Dobric", + "russian": "Добрич", + "chinese_traditional": "Dobrich", + "unknown1": "Dobrich", + "unknown2": "Dobrich", + "unknown3": "Dobrich", + "unknown4": "Dobrich" + }, + "coordinates": { + "latitude": 43.571776848, + "longitude": 27.833937993 + } + }, + { + "id": 1175060480, + "name": "Gabrovo", + "translations": { + "japanese": "ガブロボ州", + "english": "Gabrovo", + "french": "Gabrovo", + "german": "Gabrowo", + "italian": "Gabrovo", + "spanish": "Gabrovo", + "chinese_simple": "加布罗沃州", + "korean": "가브로보 주", + "dutch": "Gabrovo", + "portuguese": "Gabrovo", + "russian": "Габрово", + "chinese_traditional": "Gabrovo", + "unknown1": "Gabrovo", + "unknown2": "Gabrovo", + "unknown3": "Gabrovo", + "unknown4": "Gabrovo" + }, + "coordinates": { + "latitude": 42.890624512, + "longitude": 25.307075653 + } + }, + { + "id": 1175126016, + "name": "Haskovo", + "translations": { + "japanese": "ハスコボ州", + "english": "Haskovo", + "french": "Khaskovo", + "german": "Chaskowo", + "italian": "Haskovo", + "spanish": "Haskovo", + "chinese_simple": "哈斯科沃州", + "korean": "하스코보 주", + "dutch": "Chaskovo", + "portuguese": "Haskovo", + "russian": "Хасково", + "chinese_traditional": "Haskovo", + "unknown1": "Haskovo", + "unknown2": "Haskovo", + "unknown3": "Haskovo", + "unknown4": "Haskovo" + }, + "coordinates": { + "latitude": 41.934813976, + "longitude": 25.554268708 + } + }, + { + "id": 1175191552, + "name": "Yambol", + "translations": { + "japanese": "ヤンボル州", + "english": "Yambol", + "french": "Yambol", + "german": "Jambol", + "italian": "Jambol", + "spanish": "Yambol", + "chinese_simple": "扬博尔州", + "korean": "얌볼 주", + "dutch": "Jambol", + "portuguese": "Yambol", + "russian": "Ямбол", + "chinese_traditional": "Yambol", + "unknown1": "Yambol", + "unknown2": "Yambol", + "unknown3": "Yambol", + "unknown4": "Yambol" + }, + "coordinates": { + "latitude": 42.484130376, + "longitude": 26.515575033 + } + }, + { + "id": 1175257088, + "name": "Kardzhali", + "translations": { + "japanese": "クルジャリ州", + "english": "Kardzhali", + "french": "Kardjali", + "german": "Kardschali", + "italian": "Kardzhali", + "spanish": "Kardzhali", + "chinese_simple": "克尔贾利州", + "korean": "쿠르잘리 주", + "dutch": "Kardzjali", + "portuguese": "Kardzhali", + "russian": "Кырджали", + "chinese_traditional": "Kardzhali", + "unknown1": "Kardzhali", + "unknown2": "Kardzhali", + "unknown3": "Kardzhali", + "unknown4": "Kardzhali" + }, + "coordinates": { + "latitude": 41.63818312, + "longitude": 25.378486979999998 + } + }, + { + "id": 1175322624, + "name": "Kyustendil", + "translations": { + "japanese": "キュステンディル州", + "english": "Kyustendil", + "french": "Kyoustendil", + "german": "Kjustendil", + "italian": "Kjustendil", + "spanish": "Kyustendil", + "chinese_simple": "丘斯滕迪尔州", + "korean": "큐스텐딜 주", + "dutch": "Kjoestendil", + "portuguese": "Kyustendil", + "russian": "Кюстендил", + "chinese_traditional": "Kyustendil", + "unknown1": "Kyustendil", + "unknown2": "Kyustendil", + "unknown3": "Kyustendil", + "unknown4": "Kyustendil" + }, + "coordinates": { + "latitude": 42.286376472, + "longitude": 22.68682927 + } + }, + { + "id": 1175388160, + "name": "Lovech", + "translations": { + "japanese": "ロベチ州", + "english": "Lovech", + "french": "Lovetch", + "german": "Lowetsch", + "italian": "Lovech", + "spanish": "Lovech", + "chinese_simple": "洛维奇州", + "korean": "로베치 주", + "dutch": "Lovetsj", + "portuguese": "Lovech", + "russian": "Ловеч", + "chinese_traditional": "Lovech", + "unknown1": "Lovech", + "unknown2": "Lovech", + "unknown3": "Lovech", + "unknown4": "Lovech" + }, + "coordinates": { + "latitude": 43.132323728, + "longitude": 24.713812321 + } + }, + { + "id": 1175453696, + "name": "Montana", + "translations": { + "japanese": "モンタナ州", + "english": "Montana", + "french": "Montana", + "german": "Montana", + "italian": "Montana", + "spanish": "Montana", + "chinese_simple": "蒙塔纳州", + "korean": "몬타나 주", + "dutch": "Montana", + "portuguese": "Montana", + "russian": "Монтана", + "chinese_traditional": "Montana", + "unknown1": "Montana", + "unknown2": "Montana", + "unknown3": "Montana", + "unknown4": "Montana" + }, + "coordinates": { + "latitude": 43.412475092, + "longitude": 23.23614717 + } + }, + { + "id": 1175519232, + "name": "Pazardzhik", + "translations": { + "japanese": "パザルジク州", + "english": "Pazardzhik", + "french": "Pazardjik", + "german": "Pasardschik", + "italian": "Pazardzhik", + "spanish": "Pazardzhik", + "chinese_simple": "帕扎尔吉克州", + "korean": "파자르지크 주", + "dutch": "Pazardzjik", + "portuguese": "Pazardzhik", + "russian": "Пазарджик", + "chinese_traditional": "Pazardzhik", + "unknown1": "Pazardzhik", + "unknown2": "Pazardzhik", + "unknown3": "Pazardzhik", + "unknown4": "Pazardzhik" + }, + "coordinates": { + "latitude": 42.18749952, + "longitude": 24.33478297 + } + }, + { + "id": 1175584768, + "name": "Pernik", + "translations": { + "japanese": "ペルニク州", + "english": "Pernik", + "french": "Pernik", + "german": "Pernik", + "italian": "Pernik", + "spanish": "Pernik", + "chinese_simple": "佩尔尼克州", + "korean": "페르니크 주", + "dutch": "Pernik", + "portuguese": "Pernik", + "russian": "Перник", + "chinese_traditional": "Pernik", + "unknown1": "Pernik", + "unknown2": "Pernik", + "unknown3": "Pernik", + "unknown4": "Pernik" + }, + "coordinates": { + "latitude": 42.583007328, + "longitude": 23.005433652 + } + }, + { + "id": 1175650304, + "name": "Plovdiv", + "translations": { + "japanese": "プロブディフ州", + "english": "Plovdiv", + "french": "Plovdiv", + "german": "Plowdiw", + "italian": "Plovdiv", + "spanish": "Plovdiv", + "chinese_simple": "普罗夫迪夫州", + "korean": "플로브디브 주", + "dutch": "Plovdiv", + "portuguese": "Plovdiv", + "russian": "Пловдив", + "chinese_traditional": "Plovdiv", + "unknown1": "Plovdiv", + "unknown2": "Plovdiv", + "unknown3": "Plovdiv", + "unknown4": "Plovdiv" + }, + "coordinates": { + "latitude": 42.13256788, + "longitude": 24.757757753 + } + }, + { + "id": 1175715840, + "name": "Razgrad", + "translations": { + "japanese": "ラズグラド州", + "english": "Razgrad", + "french": "Razgrad", + "german": "Rasgrad", + "italian": "Razgrad", + "spanish": "Razgrad", + "chinese_simple": "拉兹格勒州", + "korean": "라즈그라드 주", + "dutch": "Razgrad", + "portuguese": "Razgrad", + "russian": "Разград", + "chinese_traditional": "Razgrad", + "unknown1": "Razgrad", + "unknown2": "Razgrad", + "unknown3": "Razgrad", + "unknown4": "Razgrad" + }, + "coordinates": { + "latitude": 43.5333247, + "longitude": 26.53205457 + } + }, + { + "id": 1175781376, + "name": "Ruse", + "translations": { + "japanese": "ルセ州", + "english": "Ruse", + "french": "Roussé", + "german": "Russe", + "italian": "Ruse", + "spanish": "Ruse", + "chinese_simple": "鲁塞州", + "korean": "루세 주", + "dutch": "Roese", + "portuguese": "Ruse", + "russian": "Русе", + "chinese_traditional": "Ruse", + "unknown1": "Ruse", + "unknown2": "Ruse", + "unknown3": "Ruse", + "unknown4": "Ruse" + }, + "coordinates": { + "latitude": 43.846435048000004, + "longitude": 25.966257133 + } + }, + { + "id": 1175846912, + "name": "Silistra", + "translations": { + "japanese": "シリストラ州", + "english": "Silistra", + "french": "Silistra", + "german": "Silistra", + "italian": "Silistra", + "spanish": "Silistra", + "chinese_simple": "锡利斯特拉州", + "korean": "실리스트라 주", + "dutch": "Silistra", + "portuguese": "Silistra", + "russian": "Силистра", + "chinese_traditional": "Silistra", + "unknown1": "Silistra", + "unknown2": "Silistra", + "unknown3": "Silistra", + "unknown4": "Silistra" + }, + "coordinates": { + "latitude": 44.082641100000004, + "longitude": 27.251661019 + } + }, + { + "id": 1175912448, + "name": "Sliven", + "translations": { + "japanese": "スリベン州", + "english": "Sliven", + "french": "Sliven", + "german": "Sliwen", + "italian": "Sliven", + "spanish": "Sliven", + "chinese_simple": "斯利文州", + "korean": "슬리벤 주", + "dutch": "Sliven", + "portuguese": "Sliven", + "russian": "Сливен", + "chinese_traditional": "Sliven", + "unknown1": "Sliven", + "unknown2": "Sliven", + "unknown3": "Sliven", + "unknown4": "Sliven" + }, + "coordinates": { + "latitude": 42.687377444, + "longitude": 26.328806947 + } + }, + { + "id": 1175977984, + "name": "Smolyan", + "translations": { + "japanese": "スモリャン州", + "english": "Smolyan", + "french": "Smolyan", + "german": "Smoljan", + "italian": "Smoljan", + "spanish": "Smolyan", + "chinese_simple": "斯莫梁州", + "korean": "스몰랸 주", + "dutch": "Smoljan", + "portuguese": "Smolyan", + "russian": "Смолян", + "chinese_traditional": "Smolyan", + "unknown1": "Smolyan", + "unknown2": "Smolyan", + "unknown3": "Smolyan", + "unknown4": "Smolyan" + }, + "coordinates": { + "latitude": 41.58325148, + "longitude": 24.697332784 + } + }, + { + "id": 1176043520, + "name": "Stara Zagora", + "translations": { + "japanese": "スタラ・ザゴラ州", + "english": "Stara Zagora", + "french": "Stara Zagora", + "german": "Stara Sagora", + "italian": "Stara Zagora", + "spanish": "Stara Zagora", + "chinese_simple": "旧扎戈拉州", + "korean": "스타라자고라 주", + "dutch": "Stara Zagora", + "portuguese": "Stara Zagora", + "russian": "Стара-Загора", + "chinese_traditional": "Stara Zagora", + "unknown1": "Stara Zagora", + "unknown2": "Stara Zagora", + "unknown3": "Stara Zagora", + "unknown4": "Stara Zagora" + }, + "coordinates": { + "latitude": 42.423705572, + "longitude": 25.636666393 + } + }, + { + "id": 1176109056, + "name": "Shumen", + "translations": { + "japanese": "シュメン州", + "english": "Shumen", + "french": "Choumen", + "german": "Schumen", + "italian": "Shumen", + "spanish": "Shumen", + "chinese_simple": "舒门州", + "korean": "슈멘 주", + "dutch": "Sjoemen", + "portuguese": "Shumen", + "russian": "Шумен", + "chinese_traditional": "Shumen", + "unknown1": "Shumen", + "unknown2": "Shumen", + "unknown3": "Shumen", + "unknown4": "Shumen" + }, + "coordinates": { + "latitude": 43.269652828, + "longitude": 26.922070279 + } + }, + { + "id": 1176174592, + "name": "Targovishte", + "translations": { + "japanese": "トゥルゴビシュテ州", + "english": "Targovishte", + "french": "Targovichte", + "german": "Targowischte", + "italian": "Targovishte", + "spanish": "Targovishte", + "chinese_simple": "特尔戈维什特州", + "korean": "투르고비슈테 주", + "dutch": "Targovisjte", + "portuguese": "Targovishte", + "russian": "Тырговиште", + "chinese_traditional": "Targovishte", + "unknown1": "Targovishte", + "unknown2": "Targovishte", + "unknown3": "Targovishte", + "unknown4": "Targovishte" + }, + "coordinates": { + "latitude": 43.247680172, + "longitude": 26.570506823 + } + }, + { + "id": 1176240128, + "name": "Veliko Tarnovo", + "translations": { + "japanese": "ベリコ・トゥルノボ州", + "english": "Veliko Tarnovo", + "french": "Veliko Tarnovo", + "german": "Weliko Tarnowo", + "italian": "Veliko Tarnovo", + "spanish": "Veliko Tarnovo", + "chinese_simple": "大特尔诺沃州", + "korean": "벨리코투르노보 주", + "dutch": "Veliko Tarnovo", + "portuguese": "Veliko Tarnovo", + "russian": "Велико-Тырново", + "chinese_traditional": "Veliko Tarnovo", + "unknown1": "Veliko Tarnovo", + "unknown2": "Veliko Tarnovo", + "unknown3": "Veliko Tarnovo", + "unknown4": "Veliko Tarnovo" + }, + "coordinates": { + "latitude": 43.082885252, + "longitude": 25.631173214 + } + }, + { + "id": 1176305664, + "name": "Vratsa", + "translations": { + "japanese": "ブラツァ州", + "english": "Vratsa", + "french": "Vratsa", + "german": "Wraza", + "italian": "Vratsa", + "spanish": "Vratsa", + "chinese_simple": "弗拉察州", + "korean": "브라차 주", + "dutch": "Vratsa", + "portuguese": "Vratsa", + "russian": "Враца", + "chinese_traditional": "Vratsa", + "unknown1": "Vratsa", + "unknown2": "Vratsa", + "unknown3": "Vratsa", + "unknown4": "Vratsa" + }, + "coordinates": { + "latitude": 43.20373486, + "longitude": 23.549258373 + } + } + ] + }, + { + "id": 71, + "iso_code": "HR", + "name": "Croatia", + "translations": { + "japanese": "クロアチア", + "english": "Croatia", + "french": "Croatie", + "german": "Kroatien", + "italian": "Croazia", + "spanish": "Croacia", + "chinese_simple": "克罗地亚", + "korean": "크로아티아", + "dutch": "Kroatië", + "portuguese": "Croácia", + "russian": "Хорватия", + "chinese_traditional": "Croatia", + "unknown1": "Croatia", + "unknown2": "Croatia", + "unknown3": "Croatia", + "unknown4": "Croatia" + }, + "regions": [ + { + "id": 1191182336, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 45.81298776, + "longitude": 15.979657711 + } + }, + { + "id": 1191575552, + "name": "Zagreb", + "translations": { + "japanese": "ザグレブ直轄市", + "english": "Zagreb", + "french": "Zagreb (ville)", + "german": "Zagreb (Stadt)", + "italian": "Zagabria", + "spanish": "Ciudad de Zagreb", + "chinese_simple": "萨格勒布市", + "korean": "자그레브", + "dutch": "Zagreb (stad)", + "portuguese": "Zagreb (cidade)", + "russian": "Загреб", + "chinese_traditional": "Zagreb", + "unknown1": "Zagreb", + "unknown2": "Zagreb", + "unknown3": "Zagreb", + "unknown4": "Zagreb" + }, + "coordinates": { + "latitude": 45.81298776, + "longitude": 15.979657711 + } + }, + { + "id": 1191641088, + "name": "Bjelovar-Bilogora County", + "translations": { + "japanese": "ビェロヴァル=ビロゴラ郡", + "english": "Bjelovar-Bilogora County", + "french": "Bjelovar-Bilogora", + "german": "Bjelovar-Bilogora", + "italian": "Regione di Bjelovar e della Bilogora", + "spanish": "Condado de Bjelovar-Bilogora", + "chinese_simple": "别洛瓦尔-比洛戈拉县", + "korean": "벨로바르-빌로고라 군", + "dutch": "Bjelovar-Bilogora", + "portuguese": "Bjelovar-Bilogora (condado)", + "russian": "Беловарско-Билогорская жупания", + "chinese_traditional": "Bjelovar-Bilogora County", + "unknown1": "Bjelovar-Bilogora County", + "unknown2": "Bjelovar-Bilogora County", + "unknown3": "Bjelovar-Bilogora County", + "unknown4": "Bjelovar-Bilogora County" + }, + "coordinates": { + "latitude": 45.89538522, + "longitude": 16.831100456 + } + }, + { + "id": 1191706624, + "name": "Brod-Posavina County", + "translations": { + "japanese": "ブロド=ポサヴィナ郡", + "english": "Brod-Posavina County", + "french": "Brod-Posavina", + "german": "Brod-Posavina", + "italian": "Regione di Brod e della Posavina", + "spanish": "Condado de Brod-Posavina", + "chinese_simple": "布罗德-波萨维纳县", + "korean": "브로드-포사비나 군", + "dutch": "Brod-Posavina", + "portuguese": "Brod-Posavina (condado)", + "russian": "Бродско-Посавская жупания", + "chinese_traditional": "Brod-Posavina County", + "unknown1": "Brod-Posavina County", + "unknown2": "Brod-Posavina County", + "unknown3": "Brod-Posavina County", + "unknown4": "Brod-Posavina County" + }, + "coordinates": { + "latitude": 45.164794408, + "longitude": 18.012133941 + } + }, + { + "id": 1191772160, + "name": "Dubrovnik-Neretva County", + "translations": { + "japanese": "ドゥブロヴニク=ネレトヴァ郡", + "english": "Dubrovnik-Neretva County", + "french": "Dubrovnik-Neretva", + "german": "Dubrovnik-Neretva", + "italian": "Regione Raguseo-Narentana", + "spanish": "Condado de Dubrovnik-Neretva", + "chinese_simple": "杜布罗夫斯克-内雷特瓦县", + "korean": "두브로브니크-네레트바 군", + "dutch": "Dubrovnik-Neretva", + "portuguese": "Dubrovnik-Neretva (condado)", + "russian": "Дубровницко-Неретванская жупания", + "chinese_traditional": "Dubrovnik-Neretva County", + "unknown1": "Dubrovnik-Neretva County", + "unknown2": "Dubrovnik-Neretva County", + "unknown3": "Dubrovnik-Neretva County", + "unknown4": "Dubrovnik-Neretva County" + }, + "coordinates": { + "latitude": 42.637938968, + "longitude": 18.105517984 + } + }, + { + "id": 1191837696, + "name": "Istria County", + "translations": { + "japanese": "イストラ郡", + "english": "Istria County", + "french": "Istrie", + "german": "Istrien", + "italian": "Regione Istriana", + "spanish": "Condado de Istria", + "chinese_simple": "伊斯特拉县", + "korean": "이스트라 군", + "dutch": "Istrië", + "portuguese": "Istria (condado)", + "russian": "Истрийская жупания", + "chinese_traditional": "Istria County", + "unknown1": "Istria County", + "unknown2": "Istria County", + "unknown3": "Istria County", + "unknown4": "Istria County" + }, + "coordinates": { + "latitude": 45.230712376, + "longitude": 13.930701943999999 + } + }, + { + "id": 1191903232, + "name": "Karlovac County", + "translations": { + "japanese": "カルロヴァツ郡", + "english": "Karlovac County", + "french": "Karlovac", + "german": "Karlovac", + "italian": "Regione di Karlovac", + "spanish": "Condado de Karlovac", + "chinese_simple": "卡尔洛瓦茨县", + "korean": "카를로바츠 군", + "dutch": "Karlovac", + "portuguese": "Karlovac (condado)", + "russian": "Карловацкая жупания", + "chinese_traditional": "Karlovac County", + "unknown1": "Karlovac County", + "unknown2": "Karlovac County", + "unknown3": "Karlovac County", + "unknown4": "Karlovac County" + }, + "coordinates": { + "latitude": 45.477904756, + "longitude": 15.54569657 + } + }, + { + "id": 1191968768, + "name": "Koprivnica-Križevci County", + "translations": { + "japanese": "コプリヴニツァ=クリジェヴツィ郡", + "english": "Koprivnica-Križevci County", + "french": "Koprivnica-Križevci", + "german": "Koprivnica-Križevci", + "italian": "Regione di Koprivnica e Križevci", + "spanish": "Condado de Koprivnica-Križevci", + "chinese_simple": "科普里夫尼察-克里热夫齐县", + "korean": "코프리브니차-크리제브치 군", + "dutch": "Koprivnica-Križevci", + "portuguese": "Koprivnica-Križevci (condado)", + "russian": "Копривницко-Крижевацкая жупания", + "chinese_traditional": "Koprivnica-Križevci County", + "unknown1": "Koprivnica-Križevci County", + "unknown2": "Koprivnica-Križevci County", + "unknown3": "Koprivnica-Križevci County", + "unknown4": "Koprivnica-Križevci County" + }, + "coordinates": { + "latitude": 46.148070764, + "longitude": 16.814620919 + } + }, + { + "id": 1192034304, + "name": "Krapina-Zagorje County", + "translations": { + "japanese": "クラピナ=ザゴリエ郡", + "english": "Krapina-Zagorje County", + "french": "Krapina-Zagorje", + "german": "Krapina-Zagorje", + "italian": "Regione di Krapina e dello Zagorje", + "spanish": "Condado de Krapina-Zagorje", + "chinese_simple": "克拉皮纳-扎戈列县", + "korean": "크라피나-자고례 군", + "dutch": "Krapina-Zagorje", + "portuguese": "Krapina-Zagorje (condado)", + "russian": "Крапинско-Загорская жупания", + "chinese_traditional": "Krapina-Zagorje County", + "unknown1": "Krapina-Zagorje County", + "unknown2": "Krapina-Zagorje County", + "unknown3": "Krapina-Zagorje County", + "unknown4": "Krapina-Zagorje County" + }, + "coordinates": { + "latitude": 46.164550256, + "longitude": 15.880780489 + } + }, + { + "id": 1192099840, + "name": "Lika-Senj County", + "translations": { + "japanese": "リカ=セニ郡", + "english": "Lika-Senj County", + "french": "Lika-Senj", + "german": "Lika-Senj", + "italian": "Regione della Lika e di Segna", + "spanish": "Condado de Lika-Senj", + "chinese_simple": "利卡-塞尼县", + "korean": "리카-센 군", + "dutch": "Lika-Senj", + "portuguese": "Lika-Senj (condado)", + "russian": "Лицко-Сеньская жупания", + "chinese_traditional": "Lika-Senj County", + "unknown1": "Lika-Senj County", + "unknown2": "Lika-Senj County", + "unknown3": "Lika-Senj County", + "unknown4": "Lika-Senj County" + }, + "coordinates": { + "latitude": 44.538573712, + "longitude": 15.369914842 + } + }, + { + "id": 1192165376, + "name": "Međimurje County", + "translations": { + "japanese": "メジムリェ郡", + "english": "Međimurje County", + "french": "Međimurje", + "german": "Medimurje", + "italian": "Regione del Medjimurje", + "spanish": "Condado de Medimurje", + "chinese_simple": "梅吉穆列县", + "korean": "메지무례 군", + "dutch": "Medimurje", + "portuguese": "Medimurje (condado)", + "russian": "Меджимурская жупания", + "chinese_traditional": "Međimurje County", + "unknown1": "Međimurje County", + "unknown2": "Međimurje County", + "unknown3": "Međimurje County", + "unknown4": "Međimurje County" + }, + "coordinates": { + "latitude": 46.384276816, + "longitude": 16.430098389 + } + }, + { + "id": 1192230912, + "name": "Osijek-Baranja County", + "translations": { + "japanese": "オシエク=バラニャ郡", + "english": "Osijek-Baranja County", + "french": "Osijek-Baranja", + "german": "Osijek-Baranja", + "italian": "Regione di Osijek e della Baranja", + "spanish": "Condado de Osijek-Baranja", + "chinese_simple": "奥西耶克-巴拉尼亚县", + "korean": "오시예크-바라냐 군", + "dutch": "Osijek-Baranja", + "portuguese": "Osijek-Baranja (condado)", + "russian": "Осиецко-Бараньская жупания", + "chinese_traditional": "Osijek-Baranja County", + "unknown1": "Osijek-Baranja County", + "unknown2": "Osijek-Baranja County", + "unknown3": "Osijek-Baranja County", + "unknown4": "Osijek-Baranja County" + }, + "coordinates": { + "latitude": 45.554809052, + "longitude": 18.6768086 + } + }, + { + "id": 1192296448, + "name": "Požega-Slavonia County", + "translations": { + "japanese": "ポジェガ=スラヴォニア郡", + "english": "Požega-Slavonia County", + "french": "Požega-Slavonie", + "german": "Požega-Slawonien", + "italian": "Regione di Požega e della Slavonia", + "spanish": "Condado de Požega-Eslavonia", + "chinese_simple": "波热加-斯拉沃尼亚县", + "korean": "포제가-슬라보니아 군", + "dutch": "Požega-Slavonië", + "portuguese": "Pozega-Slavonia (condado)", + "russian": "Пожежско-Славонская жупания", + "chinese_traditional": "Požega-Slavonia County", + "unknown1": "Požega-Slavonia County", + "unknown2": "Požega-Slavonia County", + "unknown3": "Požega-Slavonia County", + "unknown4": "Požega-Slavonia County" + }, + "coordinates": { + "latitude": 45.335082492, + "longitude": 17.68803638 + } + }, + { + "id": 1192361984, + "name": "Primorje-Gorski Kotar County", + "translations": { + "japanese": "プリモリェ=ゴルスキ・コタル郡", + "english": "Primorje-Gorski Kotar County", + "french": "Primorje-Gorski Kotar", + "german": "Primorje-Gorski kotar", + "italian": "Regione Litoraneo-Montana", + "spanish": "Condado de Primorje-Gorski Kotar", + "chinese_simple": "滨海和山区县", + "korean": "프리모례-고르스키코타르 군", + "dutch": "Primorje-Gorski Kotar", + "portuguese": "Primorje-Gorski Kotar (condado)", + "russian": "Приморско-Горанская жупания", + "chinese_traditional": "Primorje-Gorski Kotar County", + "unknown1": "Primorje-Gorski Kotar County", + "unknown2": "Primorje-Gorski Kotar County", + "unknown3": "Primorje-Gorski Kotar County", + "unknown4": "Primorje-Gorski Kotar County" + }, + "coordinates": { + "latitude": 45.313109836, + "longitude": 14.414101696 + } + }, + { + "id": 1192427520, + "name": "Sisak-Moslavina County", + "translations": { + "japanese": "シサク=モスラヴィナ郡", + "english": "Sisak-Moslavina County", + "french": "Sisak-Moslavina", + "german": "Sisak-Moslavina", + "italian": "Regione di Sisak e della Moslavina", + "spanish": "Condado de Sisak-Moslavina", + "chinese_simple": "锡萨克-莫斯拉维纳县", + "korean": "시사크-모슬라비나 군", + "dutch": "Sisak-Moslavina", + "portuguese": "Sisak-Moslavina (condado)", + "russian": "Сисацко-Мославинская жупания", + "chinese_traditional": "Sisak-Moslavina County", + "unknown1": "Sisak-Moslavina County", + "unknown2": "ᑻ۱埣ἴk-Moslavina County", + "unknown3": "Sisak-Moslavina County", + "unknown4": "Sisak-Moslavina County" + }, + "coordinates": { + "latitude": 45.461425264, + "longitude": 16.380659778 + } + }, + { + "id": 1192493056, + "name": "Split-Dalmatia County", + "translations": { + "japanese": "スプリト=ダルマチア郡", + "english": "Split-Dalmatia County", + "french": "Split-Dalmatie", + "german": "Split-Dalmatien", + "italian": "Regione Spalatino-Dalmata", + "spanish": "Condado de Split-Dalmacia", + "chinese_simple": "斯普利特-达尔马提亚县", + "korean": "스플리트-달마티아 군", + "dutch": "Split-Dalmatië", + "portuguese": "Split-Dalmácia (condado)", + "russian": "Сплитско-Далматинская жупания", + "chinese_traditional": "Split-Dalmatia County", + "unknown1": "Split-Dalmatia County", + "unknown2": "Split-Dalmatia County", + "unknown3": "Split-Dalmatia County", + "unknown4": "Split-Dalmatia County" + }, + "coordinates": { + "latitude": 43.494872552, + "longitude": 16.430098389 + } + }, + { + "id": 1192558592, + "name": "Šibenik-Knin County", + "translations": { + "japanese": "シベニク=クニン郡", + "english": "Šibenik-Knin County", + "french": "Šibenik-Knin", + "german": "Šibenik-Knin", + "italian": "Regione di Sebenico e Tenin", + "spanish": "Condado de Šibenik-Knin", + "chinese_simple": "希贝尼克-克宁县", + "korean": "시베니크-크닌 군", + "dutch": "Šibenik-Knin", + "portuguese": "Šibenik-Knin (condado)", + "russian": "Шибенско-Книнская жупания", + "chinese_traditional": "Šibenik-Knin County", + "unknown1": "Šibenik-Knin County", + "unknown2": "Šibenik-Knin County", + "unknown3": "Šibenik-Knin County", + "unknown4": "Šibenik-Knin County" + }, + "coordinates": { + "latitude": 43.731078604, + "longitude": 15.886273668 + } + }, + { + "id": 1192624128, + "name": "Varaždin County", + "translations": { + "japanese": "ヴァラジュディン郡", + "english": "Varaždin County", + "french": "Varaždin", + "german": "Varaždin", + "italian": "Regione di Varasdino", + "spanish": "Condado de Varaždin", + "chinese_simple": "瓦拉日丁县", + "korean": "바라주딘 군", + "dutch": "Varaždin", + "portuguese": "Varaždin (condado)", + "russian": "Вараждинская жупания", + "chinese_traditional": "Varaždin County", + "unknown1": "Varaždin County", + "unknown2": "Varaždin County", + "unknown3": "Varaždin County", + "unknown4": "Varaždin County" + }, + "coordinates": { + "latitude": 46.296386192, + "longitude": 16.331221167 + } + }, + { + "id": 1192689664, + "name": "Virovitica-Podravina County", + "translations": { + "japanese": "ヴィロヴィティツァ=ポドラヴィナ郡", + "english": "Virovitica-Podravina County", + "french": "Virovitica-Podravina", + "german": "Virovitica-Podravina", + "italian": "Regione di Virovitica e della Podravina", + "spanish": "Condado de Virovitica-Podravina", + "chinese_simple": "维罗维蒂察-波德拉维纳县", + "korean": "비로비티차-포드라비나 군", + "dutch": "Virovitica-Podravina", + "portuguese": "Virovitica-Podravina (condado)", + "russian": "Вировитицко-Подравская жупания", + "chinese_traditional": "Virovitica-Podravina County", + "unknown1": "Virovitica-Podravina County", + "unknown2": "Virovitica-Podravina County", + "unknown3": "Virovitica-Podravina County", + "unknown4": "Virovitica-Podravina County" + }, + "coordinates": { + "latitude": 45.829467252, + "longitude": 17.380418356 + } + }, + { + "id": 1192755200, + "name": "Vukovar-Syrmia County", + "translations": { + "japanese": "ヴコヴァル=スリイェム郡", + "english": "Vukovar-Syrmia County", + "french": "Vukovar-Syrmie", + "german": "Vukovar-Srijem", + "italian": "Regione di Vukovar e della Sirmia", + "spanish": "Condado de Vukovar-Srijem", + "chinese_simple": "武科瓦尔-斯里耶姆县", + "korean": "부코바르-시르미아 군", + "dutch": "Vukovar-Srijem", + "portuguese": "Vukovar-Srijem (condado)", + "russian": "Вуковарско-Сремская жупания", + "chinese_traditional": "Vukovar-Syrmia County", + "unknown1": "Vukovar-Syrmia County", + "unknown2": "Vukovar-Syrmia County", + "unknown3": "Vukovar-Syrmia County", + "unknown4": "Vukovar-Syrmia County" + }, + "coordinates": { + "latitude": 45.34606882, + "longitude": 18.995412982 + } + }, + { + "id": 1192820736, + "name": "Zadar County", + "translations": { + "japanese": "ザダル郡", + "english": "Zadar County", + "french": "Zadar", + "german": "Zadar", + "italian": "Regione Zaratina", + "spanish": "Condado de Zadar", + "chinese_simple": "扎达尔县", + "korean": "자다르 군", + "dutch": "Zadar", + "portuguese": "Zadar (condado)", + "russian": "Задарская жупания", + "chinese_traditional": "Zadar County", + "unknown1": "Zadar County", + "unknown2": "Zadar County", + "unknown3": "Zadar County", + "unknown4": "Zadar County" + }, + "coordinates": { + "latitude": 44.11010692, + "longitude": 15.227092188 + } + }, + { + "id": 1192886272, + "name": "Zagreb County", + "translations": { + "japanese": "ザグレブ郡", + "english": "Zagreb County", + "french": "Zagreb (comitat)", + "german": "Zagreb", + "italian": "Regione Zagabrese", + "spanish": "Condado de Zagreb", + "chinese_simple": "萨格勒布县", + "korean": "자그레브 군", + "dutch": "Zagreb (provincie)", + "portuguese": "Zagrebe (condado)", + "russian": "Загребская жупания", + "chinese_traditional": "Zagreb County", + "unknown1": "Zagreb County", + "unknown2": "Zagreb County", + "unknown3": "Zagreb County", + "unknown4": "Zagreb County" + }, + "coordinates": { + "latitude": 45.81298776, + "longitude": 15.979657711 + } + } + ] + }, + { + "id": 72, + "iso_code": "CY", + "name": "Cyprus", + "translations": { + "japanese": "キプロス", + "english": "Cyprus", + "french": "Chypre", + "german": "Zypern", + "italian": "Cipro", + "spanish": "Chipre", + "chinese_simple": "塞浦路斯", + "korean": "키프로스", + "dutch": "Cyprus", + "portuguese": "Chipre", + "russian": "Кипр", + "chinese_traditional": "Cyprus", + "unknown1": "Cyprus", + "unknown2": "Cyprus", + "unknown3": "Cyprus", + "unknown4": "Cyprus" + }, + "regions": [ + { + "id": 1207959552, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 35.161742764, + "longitude": 33.371062425 + } + }, + { + "id": 1208025088, + "name": "Cyprus", + "translations": { + "japanese": "キプロス", + "english": "Cyprus", + "french": "Chypre", + "german": "Zypern", + "italian": "Cipro", + "spanish": "Chipre", + "chinese_simple": "塞浦路斯", + "korean": "키프로스", + "dutch": "Cyprus", + "portuguese": "Chipre", + "russian": "Кипр", + "chinese_traditional": "Cyprus", + "unknown1": "Cyprus", + "unknown2": "Cyprus", + "unknown3": "Cyprus", + "unknown4": "Cyprus" + }, + "coordinates": { + "latitude": 35.161742764, + "longitude": 33.371062425 + } + } + ] + }, + { + "id": 73, + "iso_code": "CZ", + "name": "Czech Republic", + "translations": { + "japanese": "チェコ", + "english": "Czech Republic", + "french": "République tchèque", + "german": "Tschechische Republik", + "italian": "Repubblica Ceca", + "spanish": "República Checa", + "chinese_simple": "捷克共和国", + "korean": "체코", + "dutch": "Tsjechië", + "portuguese": "República Checa", + "russian": "Чешская Республика", + "chinese_traditional": "Czech Republic", + "unknown1": "Czech Republic", + "unknown2": "Czech Republic", + "unknown3": "Czech Republic", + "unknown4": "Czech Republic" + }, + "regions": [ + { + "id": 1224736768, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 50.07018986, + "longitude": 14.430581233 + } + }, + { + "id": 1224867840, + "name": "Prague", + "translations": { + "japanese": "プラハ", + "english": "Prague", + "french": "Prague", + "german": "Prag", + "italian": "Praga", + "spanish": "Praga", + "chinese_simple": "布拉格市", + "korean": "프라하", + "dutch": "Praag", + "portuguese": "Praga", + "russian": "Прага", + "chinese_traditional": "Prague", + "unknown1": "Prague", + "unknown2": "Prague", + "unknown3": "Prague", + "unknown4": "Prague" + }, + "coordinates": { + "latitude": 50.07018986, + "longitude": 14.430581233 + } + }, + { + "id": 1224933376, + "name": "Central Bohemian Region", + "translations": { + "japanese": "中部ボヘミア地方", + "english": "Central Bohemian Region", + "french": "Bohême centrale", + "german": "Mittelböhmische Region", + "italian": "Boemia Centrale", + "spanish": "Región de Bohemia Central", + "chinese_simple": "中捷克州", + "korean": "스트르제도체스키 지방", + "dutch": "Midden-Bohemen", + "portuguese": "Boémia Central (região)", + "russian": "Среднечешский край", + "chinese_traditional": "Central Bohemian Region", + "unknown1": "Central Bohemian Region", + "unknown2": "Central Bohemian Region", + "unknown3": "Central Bohemian Region", + "unknown4": "Central Bohemian Region" + }, + "coordinates": { + "latitude": 50.07018986, + "longitude": 14.430581233 + } + }, + { + "id": 1224998912, + "name": "South Bohemian Region", + "translations": { + "japanese": "南ボヘミア地方", + "english": "South Bohemian Region", + "french": "Bohême du Sud", + "german": "Südböhmische Region", + "italian": "Boemia Meridionale", + "spanish": "Región de Bohemia Meridional", + "chinese_simple": "南捷克州", + "korean": "이호체스키 지방", + "dutch": "Zuid-Bohemen", + "portuguese": "Boémia do Sul (região)", + "russian": "Южночешский край", + "chinese_traditional": "South Bohemian Region", + "unknown1": "South Bohemian Region", + "unknown2": "South Bohemian Region", + "unknown3": "South Bohemian Region", + "unknown4": "South Bohemian Region" + }, + "coordinates": { + "latitude": 48.97155706, + "longitude": 14.469033486 + } + }, + { + "id": 1225064448, + "name": "Plzeň Region", + "translations": { + "japanese": "プルゼニ地方", + "english": "Plzeň Region", + "french": "Région de Pilsen", + "german": "Region Pilsen", + "italian": "Regione di Plseň", + "spanish": "Región de Pilsen", + "chinese_simple": "比尔森州", + "korean": "플젠 지방", + "dutch": "Pilsen", + "portuguese": "Plzen (região)", + "russian": "Пльзенский край", + "chinese_traditional": "Plzeň Region", + "unknown1": "Plzeň Region", + "unknown2": "Plzeň Region", + "unknown3": "Plzeň Region", + "unknown4": "Plzeň Region" + }, + "coordinates": { + "latitude": 49.735106856, + "longitude": 13.370397686 + } + }, + { + "id": 1225129984, + "name": "Karlovy Vary Region", + "translations": { + "japanese": "カールスバート地方", + "english": "Karlovy Vary Region", + "french": "Région de Karlovy Vary", + "german": "Region Karlsbad", + "italian": "Regione di Karlovy Vary", + "spanish": "Región de Karlovy Vary", + "chinese_simple": "卡罗维发利州", + "korean": "카를로비바리 지방", + "dutch": "Karlsbad", + "portuguese": "Karlovy Vary (região)", + "russian": "Карловарский край", + "chinese_traditional": "Karlovy Vary Region", + "unknown1": "Karlovy Vary Region", + "unknown2": "Karlovy Vary Region", + "unknown3": "Karlovy Vary Region", + "unknown4": "Karlovy Vary Region" + }, + "coordinates": { + "latitude": 50.223998452000004, + "longitude": 12.870518397 + } + }, + { + "id": 1225195520, + "name": "Ústí nad Labem Region", + "translations": { + "japanese": "ウースチー・ナド・ラベム地方", + "english": "Ústí nad Labem Region", + "french": "Région d'Ústí nad Labem", + "german": "Region Ústí", + "italian": "Regione di Ústí nad Labem", + "spanish": "Región de Ústí nad Labem", + "chinese_simple": "拉贝河畔乌斯季州", + "korean": "우스티나트라벰 지방", + "dutch": "Ústí nad Labem", + "portuguese": "Ústí nad Labem (região)", + "russian": "Устецкий край", + "chinese_traditional": "Ústí nad Labem Region", + "unknown1": "Ústí nad Labem Region", + "unknown2": "Ústí nad Labem Region", + "unknown3": "Ústí nad Labem Region", + "unknown4": "Ústí nad Labem Region" + }, + "coordinates": { + "latitude": 50.668944736, + "longitude": 14.084510955999999 + } + }, + { + "id": 1225261056, + "name": "Liberec Region", + "translations": { + "japanese": "リベレツ地方", + "english": "Liberec Region", + "french": "Région de Liberec", + "german": "Region Liberec", + "italian": "Regione di Liberec", + "spanish": "Región de Liberec", + "chinese_simple": "利贝雷克州", + "korean": "리베레츠 지방", + "dutch": "Liberec", + "portuguese": "Liberec (região)", + "russian": "Либерецкий край", + "chinese_traditional": "Liberec Region", + "unknown1": "Liberec Region", + "unknown2": "Liberec Region", + "unknown3": "Liberec Region", + "unknown4": "Liberec Region" + }, + "coordinates": { + "latitude": 50.756835360000004, + "longitude": 15.040324102 + } + }, + { + "id": 1225326592, + "name": "Hradec Králové Region", + "translations": { + "japanese": "フラデツ・クラロベ地方", + "english": "Hradec Králové Region", + "french": "Région de Hradec Králové", + "german": "Region Hradec Králové", + "italian": "Regione di Hradec Králové", + "spanish": "Región de Hradec Králové", + "chinese_simple": "赫拉德茨-克拉洛韦州", + "korean": "흐라데츠크랄로베 지방", + "dutch": "Hradec Králové", + "portuguese": "Hradec Králové (região)", + "russian": "Краловеградецкий край", + "chinese_traditional": "Hradec Králové Region", + "unknown1": "Hradec Králové Region", + "unknown2": "Hradec Králové Region", + "unknown3": "Hradec Králové Region", + "unknown4": "Hradec Králové Region" + }, + "coordinates": { + "latitude": 50.202025796, + "longitude": 15.803875983 + } + }, + { + "id": 1225392128, + "name": "Pardubice Region", + "translations": { + "japanese": "パルドゥビツェ地方", + "english": "Pardubice Region", + "french": "Région de Pardubice", + "german": "Region Pardubice", + "italian": "Regione di Pardubice", + "spanish": "Región de Pardubice", + "chinese_simple": "帕尔杜比采州", + "korean": "파르두비체 지방", + "dutch": "Pardubice", + "portuguese": "Pardubice (região)", + "russian": "Пардубицкий край", + "chinese_traditional": "Pardubice Region", + "unknown1": "Pardubice Region", + "unknown2": "Pardubice Region", + "unknown3": "Pardubice Region", + "unknown4": "Pardubice Region" + }, + "coordinates": { + "latitude": 50.020751384, + "longitude": 15.76542373 + } + }, + { + "id": 1225457664, + "name": "Olomouc Region", + "translations": { + "japanese": "オロモウツ地方", + "english": "Olomouc Region", + "french": "Région d'Olomouc", + "german": "Region Olmütz", + "italian": "Regione di Olomouc", + "spanish": "Región de Olomouc", + "chinese_simple": "奥洛穆茨州", + "korean": "올로모우츠 지방", + "dutch": "Olomouc", + "portuguese": "Olomouc (região)", + "russian": "Оломоуцкий край", + "chinese_traditional": "Olomouc Region", + "unknown1": "Olomouc Region", + "unknown2": "Olomouc Region", + "unknown3": "Olomouc Region", + "unknown4": "Olomouc Region" + }, + "coordinates": { + "latitude": 49.586791428, + "longitude": 17.254075239 + } + }, + { + "id": 1225523200, + "name": "Moravian-Silesian Region", + "translations": { + "japanese": "モラビア・シレジア地方", + "english": "Moravian-Silesian Region", + "french": "Moravie-Silésie", + "german": "Region Mährisch-Schlesien", + "italian": "Regione di Moravia-Slesia", + "spanish": "Región de Moravia-Silesia", + "chinese_simple": "摩拉维亚-西里西亚州", + "korean": "모라비아실레지아 지방", + "dutch": "Moravië-Silezië", + "portuguese": "Morávia-Silésia (região)", + "russian": "Моравскосилезский край", + "chinese_traditional": "Moravian-Silesian Region", + "unknown1": "Moravian-Silesian Region", + "unknown2": "Moravian-Silesian Region", + "unknown3": "Moravian-Silesian Region", + "unknown4": "Moravian-Silesian Region" + }, + "coordinates": { + "latitude": 49.817504316, + "longitude": 18.253833817 + } + }, + { + "id": 1225588736, + "name": "South Moravian Region", + "translations": { + "japanese": "南モラビア地方", + "english": "South Moravian Region", + "french": "Moravie du Sud", + "german": "Südmährische Region", + "italian": "Moravia Meridionale", + "spanish": "Región de Moravia Meridional", + "chinese_simple": "南摩拉维亚州", + "korean": "이호모라프스키 지방", + "dutch": "Zuid-Moravië", + "portuguese": "Morávia do Sul (região)", + "russian": "Южноморавский край", + "chinese_traditional": "South Moravian Region", + "unknown1": "South Moravian Region", + "unknown2": "South Moravian Region", + "unknown3": "South Moravian Region", + "unknown4": "South Moravian Region" + }, + "coordinates": { + "latitude": 49.196776784, + "longitude": 16.605880116999998 + } + }, + { + "id": 1225654272, + "name": "Zlín Region", + "translations": { + "japanese": "ズリン地方", + "english": "Zlín Region", + "french": "Région de Zlín", + "german": "Region Zlin", + "italian": "Regione di Zlín", + "spanish": "Región de Zlín", + "chinese_simple": "兹林州", + "korean": "즐린 지방", + "dutch": "Zlín", + "portuguese": "Zlín (região)", + "russian": "Злинский край", + "chinese_traditional": "Zlín Region", + "unknown1": "Zlín Region", + "unknown2": "Zlín Region", + "unknown3": "Zlín Region", + "unknown4": "Zlín Region" + }, + "coordinates": { + "latitude": 49.21874944, + "longitude": 17.649584127 + } + }, + { + "id": 1225719808, + "name": "Vysočina Region", + "translations": { + "japanese": "ヴィソチナ地方", + "english": "Vysočina Region", + "french": "Vysočina", + "german": "Region Vysočina", + "italian": "Regione di Vysočina", + "spanish": "Región de Vysočina", + "chinese_simple": "维索基纳州", + "korean": "비소치나 지방", + "dutch": "Vysočina", + "portuguese": "Vysočina (região)", + "russian": "Край Высочина", + "chinese_traditional": "Vysočina Region", + "unknown1": "Vysočina Region", + "unknown2": "Vysočina Region", + "unknown3": "Vysočina Region", + "unknown4": "Vysočina Region" + }, + "coordinates": { + "latitude": 49.389037524, + "longitude": 15.584148823 + } + } + ] + }, + { + "id": 74, + "iso_code": "DK", + "name": "Denmark (Kingdom of)", + "translations": { + "japanese": "デンマーク", + "english": "Denmark (Kingdom of)", + "french": "Danemark (Royaume)", + "german": "Dänemark (Königreich)", + "italian": "Danimarca (Regno di)", + "spanish": "Dinamarca (Reino)", + "chinese_simple": "丹麦", + "korean": "덴마크", + "dutch": "Denemarken (koninkrijk)", + "portuguese": "Dinamarca (Reino)", + "russian": "Дания (Королевство)", + "chinese_traditional": "Denmark (Kingdom of)", + "unknown1": "Denmark (Kingdom of)", + "unknown2": "Denmark (Kingdom of)", + "unknown3": "Denmark (Kingdom of)", + "unknown4": "Denmark (Kingdom of)" + }, + "regions": [ + { + "id": 1241513984, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 55.931395848, + "longitude": 12.315707318 + } + }, + { + "id": 1242693632, + "name": "Greenland", + "translations": { + "japanese": "グリーンランド", + "english": "Greenland", + "french": "Groenland", + "german": "Grönland", + "italian": "Groenlandia", + "spanish": "Groenlandia", + "chinese_simple": "格陵兰", + "korean": "그린란드", + "dutch": "Groenland", + "portuguese": "Gronelândia", + "russian": "Гренландия", + "chinese_traditional": "Greenland", + "unknown1": "Greenland", + "unknown2": "Greenland", + "unknown3": "Greenland", + "unknown4": "Greenland" + }, + "coordinates": { + "latitude": 64.182128176, + "longitude": -51.71779081299999 + } + }, + { + "id": 1242759168, + "name": "Capital Region of Denmark", + "translations": { + "japanese": "デンマーク首都地域", + "english": "Capital Region of Denmark", + "french": "Hovedstaden", + "german": "Hauptstadtregion", + "italian": "Hovedstaden", + "spanish": "Hovedstaden", + "chinese_simple": "首都大区", + "korean": "덴마크 수도권 지역", + "dutch": "Hovedstaden", + "portuguese": "Hovedstaden", + "russian": "Столичная область", + "chinese_traditional": "Capital Region of Denmark", + "unknown1": "Capital Region of Denmark", + "unknown2": "Capital Region of Denmark", + "unknown3": "Capital Region of Denmark", + "unknown4": "Capital Region of Denmark" + }, + "coordinates": { + "latitude": 55.931395848, + "longitude": 12.315707318 + } + }, + { + "id": 1242824704, + "name": "Central Denmark Region", + "translations": { + "japanese": "中央ユラン地域", + "english": "Central Denmark Region", + "french": "Jutland-Central", + "german": "Mitteljütland", + "italian": "Jutland Centrale", + "spanish": "Jutlandia Central", + "chinese_simple": "中日德兰大区", + "korean": "중부 덴마크 지역", + "dutch": "Midden-Jutland", + "portuguese": "Jutlândia Central", + "russian": "Центральная Ютландия", + "chinese_traditional": "Central Denmark Region", + "unknown1": "Central Denmark Region", + "unknown2": "Central Denmark Region", + "unknown3": "Central Denmark Region", + "unknown4": "Central Denmark Region" + }, + "coordinates": { + "latitude": 56.447753264, + "longitude": 9.398829269 + } + }, + { + "id": 1242890240, + "name": "North Denmark Region", + "translations": { + "japanese": "北ユラン地域", + "english": "North Denmark Region", + "french": "Jutland-du-Nord", + "german": "Nordjütland", + "italian": "Jutland Settentrionale", + "spanish": "Jutlandia Septentrional", + "chinese_simple": "北日德兰大区", + "korean": "북부 덴마크 지역", + "dutch": "Noord-Jutland", + "portuguese": "Jutlândia do Norte", + "russian": "Северная Ютландия", + "chinese_traditional": "North Denmark Region", + "unknown1": "North Denmark Region", + "unknown2": "North Denmark Region", + "unknown3": "North Denmark Region", + "unknown4": "North Denmark Region" + }, + "coordinates": { + "latitude": 57.04650814, + "longitude": 9.915188095 + } + }, + { + "id": 1242955776, + "name": "Region Zealand", + "translations": { + "japanese": "シェラン地域", + "english": "Region Zealand", + "french": "Zélande-du-Nord", + "german": "Seeland", + "italian": "Sjælland", + "spanish": "Selandia", + "chinese_simple": "西兰大区", + "korean": "셸란 지역", + "dutch": "Seeland", + "portuguese": "Zelândia", + "russian": "Зеландия", + "chinese_traditional": "Region Zealand", + "unknown1": "Region Zealand", + "unknown2": "Region Zealand", + "unknown3": "Region Zealand", + "unknown4": "Region Zealand" + }, + "coordinates": { + "latitude": 55.431517924, + "longitude": 11.563141795 + } + }, + { + "id": 1243021312, + "name": "Region of Southern Denmark", + "translations": { + "japanese": "南デンマーク地域", + "english": "Region of Southern Denmark", + "french": "Danemark-du-Sud", + "german": "Süddänemark", + "italian": "Syddanmark", + "spanish": "Dinamarca Meridional", + "chinese_simple": "南丹麦大区", + "korean": "남부 덴마크 지역", + "dutch": "Zuid-Denemarken", + "portuguese": "Dinamarca do Sul", + "russian": "Южная Дания", + "chinese_traditional": "Region of Southern Denmark", + "unknown1": "Region of Southern Denmark", + "unknown2": "Region of Southern Denmark", + "unknown3": "Region of Southern Denmark", + "unknown4": "씒⭤ꥠ軷on of Southern Denmark" + }, + "coordinates": { + "latitude": 55.711669288, + "longitude": 9.530665565 + } + }, + { + "id": 1243086848, + "name": "Faroe Islands", + "translations": { + "japanese": "フェロー諸島", + "english": "Faroe Islands", + "french": "Îles Féroé", + "german": "Färöer", + "italian": "Isole Fær Øer", + "spanish": "Islas Feroe", + "chinese_simple": "法罗群岛", + "korean": "페로 제도", + "dutch": "Faeröer", + "portuguese": "Ilhas Faroé", + "russian": "Фарерские острова", + "chinese_traditional": "Faroe Islands", + "unknown1": "Faroe Islands", + "unknown2": "Faroe Islands", + "unknown3": "Faroe Islands", + "unknown4": "Faroe Islands" + }, + "coordinates": { + "latitude": 62.006835232, + "longitude": -6.761613877000002 + } + } + ] + }, + { + "id": 75, + "iso_code": "EE", + "name": "Estonia", + "translations": { + "japanese": "エストニア", + "english": "Estonia", + "french": "Estonie", + "german": "Estland", + "italian": "Estonia", + "spanish": "Estonia", + "chinese_simple": "爱沙尼亚", + "korean": "에스토니아", + "dutch": "Estland", + "portuguese": "Estónia", + "russian": "Эстония", + "chinese_traditional": "Estonia", + "unknown1": "Estonia", + "unknown2": "Estonia", + "unknown3": "Estonia", + "unknown4": "Estonia" + }, + "regions": [ + { + "id": 1258291200, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 59.430541316, + "longitude": 24.730291858 + } + }, + { + "id": 1258356736, + "name": "Estonia", + "translations": { + "japanese": "エストニア", + "english": "Estonia", + "french": "Estonie", + "german": "Estland", + "italian": "Estonia", + "spanish": "Estonia", + "chinese_simple": "爱沙尼亚", + "korean": "에스토니아", + "dutch": "Estland", + "portuguese": "Estónia", + "russian": "Эстония", + "chinese_traditional": "Estonia", + "unknown1": "Estonia", + "unknown2": "Estonia", + "unknown3": "Estonia", + "unknown4": "Estonia" + }, + "coordinates": { + "latitude": 59.430541316, + "longitude": 24.730291858 + } + } + ] + }, + { + "id": 76, + "iso_code": "FI", + "name": "Finland", + "translations": { + "japanese": "フィンランド", + "english": "Finland", + "french": "Finlande", + "german": "Finnland", + "italian": "Finlandia", + "spanish": "Finlandia", + "chinese_simple": "芬兰", + "korean": "핀란드", + "dutch": "Finland", + "portuguese": "Finlândia", + "russian": "Финляндия", + "chinese_traditional": "Finland", + "unknown1": "Finland", + "unknown2": "Finland", + "unknown3": "Finland", + "unknown4": "Finland" + }, + "regions": [ + { + "id": 1275068416, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 60.166625292, + "longitude": 24.933539481 + } + }, + { + "id": 1275592704, + "name": "Uusimaa / Nyland", + "translations": { + "japanese": "ウーシマー県", + "english": "Uusimaa / Nyland", + "french": "Uusimaa", + "german": "Uusimaa", + "italian": "Uusimaa", + "spanish": "Uusimaa", + "chinese_simple": "新地区", + "korean": "우시마 주", + "dutch": "Uusimaa", + "portuguese": "Uusimaa", + "russian": "Уусимаа", + "chinese_traditional": "Uusimaa / Nyland", + "unknown1": "Uusimaa / Nyland", + "unknown2": "Uusimaa / Nyland", + "unknown3": "Uusimaa / Nyland", + "unknown4": "Uusimaa / Nyland" + }, + "coordinates": { + "latitude": 60.166625292, + "longitude": 24.933539481 + } + }, + { + "id": 1275658240, + "name": "Lappi / Lapland", + "translations": { + "japanese": "ラッピ州", + "english": "Lappi / Lapland", + "french": "Laponie", + "german": "Lappland", + "italian": "Lapponia", + "spanish": "Laponia finlandesa", + "chinese_simple": "拉普兰省", + "korean": "라피 주", + "dutch": "Lapland", + "portuguese": "Lapónia", + "russian": "Лапландия", + "chinese_traditional": "Lappi / Lapland", + "unknown1": "Lappi / Lapland", + "unknown2": "Lappi / Lapland", + "unknown3": "Lappi / Lapland", + "unknown4": "Lappi / Lapland" + }, + "coordinates": { + "latitude": 66.49475022, + "longitude": 25.730050436 + } + }, + { + "id": 1275723776, + "name": "Pohjois-Pohjanmaa / Norra Österbotten", + "translations": { + "japanese": "北ポフヤンマー県", + "english": "Pohjois-Pohjanmaa / Norra Österbotten", + "french": "Ostrobotnie du Nord", + "german": "Nordösterbotten", + "italian": "Ostrobotnia Settentrionale", + "spanish": "Ostrobothnia del Norte", + "chinese_simple": "北博滕区", + "korean": "북오스트로보트니아 주", + "dutch": "Noord-Österbotten", + "portuguese": "Ostrobótnia do Norte", + "russian": "Северная Остроботния", + "chinese_traditional": "Pohjois-Pohjanmaa / Norra Österbotten", + "unknown1": "Pohjois-Pohjanmaa / Norra Österbotten", + "unknown2": "Pohjois-Pohjanmaa / Norra Österbotten", + "unknown3": "Pohjois-Pohjanmaa / Norra Österbotten", + "unknown4": "Pohjois-Pohjanmaa / Norra Österbotten" + }, + "coordinates": { + "latitude": 65.01159594, + "longitude": 25.466377844 + } + }, + { + "id": 1275789312, + "name": "Kainuu / Kajanaland", + "translations": { + "japanese": "カイヌー県", + "english": "Kainuu / Kajanaland", + "french": "Kainuu", + "german": "Kainuu", + "italian": "Kainuu", + "spanish": "Kainuu", + "chinese_simple": "凯努区", + "korean": "카이누 주", + "dutch": "Kainuu", + "portuguese": "Kainuu", + "russian": "Кайнуу", + "chinese_traditional": "Kainuu / Kajanaland", + "unknown1": "Kainuu / Kajanaland", + "unknown2": "Kainuu / Kajanaland", + "unknown3": "Kainuu / Kajanaland", + "unknown4": "Kainuu / Kajanaland" + }, + "coordinates": { + "latitude": 64.220580324, + "longitude": 27.729567592 + } + }, + { + "id": 1275854848, + "name": "Pohjois-Karjala / Norra Karelen", + "translations": { + "japanese": "北カレリア県", + "english": "Pohjois-Karjala / Norra Karelen", + "french": "Carélie du Nord", + "german": "Nordkarelien", + "italian": "Carelia Settentrionale", + "spanish": "Karelia del Norte", + "chinese_simple": "北卡累利阿区", + "korean": "북카렐리아 주", + "dutch": "Noord-Karelië", + "portuguese": "Carélia do Norte", + "russian": "Северная Карелия", + "chinese_traditional": "Pohjois-Karjala / Norra Karelen", + "unknown1": "Pohjois-Karjala / Norra Karelen", + "unknown2": "Pohjois-Karjala / Norra Karelen", + "unknown3": "Pohjois-Karjala / Norra Karelen", + "unknown4": "Pohjois-Karjala / Norra Karelen" + }, + "coordinates": { + "latitude": 62.59460378, + "longitude": 29.745564285 + } + }, + { + "id": 1275920384, + "name": "Pohjois-Savo / Norra Savolax", + "translations": { + "japanese": "北サヴォ県", + "english": "Pohjois-Savo / Norra Savolax", + "french": "Savonie du Nord", + "german": "Nordsavo", + "italian": "Savo Settentrionale", + "spanish": "Savonia del Norte", + "chinese_simple": "北萨沃区", + "korean": "북사보 주", + "dutch": "Noord-Savo", + "portuguese": "Savónia do Norte", + "russian": "Северное Саво", + "chinese_traditional": "Pohjois-Savo / Norra Savolax", + "unknown1": "Pohjois-Savo / Norra Savolax", + "unknown2": "Pohjois-Savo / Norra Savolax", + "unknown3": "Pohjois-Savo / Norra Savolax", + "unknown4": "Pohjois-Savo / Norra Savolax" + }, + "coordinates": { + "latitude": 62.891234636, + "longitude": 27.674635802 + } + }, + { + "id": 1275985920, + "name": "Etelä-Savo / Södra Savolax", + "translations": { + "japanese": "南サヴォ県", + "english": "Etelä-Savo / Södra Savolax", + "french": "Savonie du Sud", + "german": "Südsavo", + "italian": "Savo Meridionale", + "spanish": "Savonia del Sur", + "chinese_simple": "南萨沃区", + "korean": "남사보 주", + "dutch": "Zuid-Savo", + "portuguese": "Savónia do Sul", + "russian": "Южное Саво", + "chinese_traditional": "Etelä-Savo / Södra Savolax", + "unknown1": "Etelä-Savo / Södra Savolax", + "unknown2": "Etelä-Savo / Södra Savolax", + "unknown3": "Etelä-Savo / Södra Savolax", + "unknown4": "Etelä-Savo / Södra Savolax" + }, + "coordinates": { + "latitude": 61.682738556000004, + "longitude": 27.262647377 + } + }, + { + "id": 1276051456, + "name": "Etelä-Pohjanmaa / Södra Österbotten", + "translations": { + "japanese": "南ポフヤンマー県", + "english": "Etelä-Pohjanmaa / Södra Österbotten", + "french": "Ostrobotnie du Sud", + "german": "Südösterbotten", + "italian": "Ostrobotnia Meridionale", + "spanish": "Ostrobothnia del Sur", + "chinese_simple": "南博滕区", + "korean": "남오스트로보트니아 주", + "dutch": "Zuid-Österbotten", + "portuguese": "Ostrobótnia do Sul", + "russian": "Южная Остроботния", + "chinese_traditional": "Etelä-Pohjanmaa / Södra Österbotten", + "unknown1": "Etelä-Pohjanmaa / Södra Österbotten", + "unknown2": "Etelä-Pohjanmaa / Södra Österbotten", + "unknown3": "Etelä-Pohjanmaa / Södra Österbotten", + "unknown4": "Etelä-Pohjanmaa / Södra Österbotten" + }, + "coordinates": { + "latitude": 62.78686452, + "longitude": 22.840638282 + } + }, + { + "id": 1276116992, + "name": "Pohjanmaa / Österbotten", + "translations": { + "japanese": "ポフヤンマー県", + "english": "Pohjanmaa / Österbotten", + "french": "Ostrobotnie", + "german": "Österbotten", + "italian": "Ostrobotnia", + "spanish": "Ostrobothnia", + "chinese_simple": "博滕区", + "korean": "오스트로보트니아 주", + "dutch": "Österbotten", + "portuguese": "Ostrobótnia", + "russian": "Остроботния", + "chinese_traditional": "Pohjanmaa / Österbotten", + "unknown1": "Pohjanmaa / Österbotten", + "unknown2": "Pohjanmaa / Österbotten", + "unknown3": "Pohjanmaa / Österbotten", + "unknown4": "Pohjanmaa / Österbotten" + }, + "coordinates": { + "latitude": 63.08898854, + "longitude": 21.308041341 + } + }, + { + "id": 1276182528, + "name": "Pirkanmaa / Birkaland", + "translations": { + "japanese": "ピルカンマー県", + "english": "Pirkanmaa / Birkaland", + "french": "Pirkanmaa", + "german": "Pirkanmaa", + "italian": "Pirkanmaa", + "spanish": "Pirkanmaa", + "chinese_simple": "皮尔卡区", + "korean": "피르칸마 주", + "dutch": "Pirkanmaa", + "portuguese": "Pirkanmaa", + "russian": "Пирканмаа", + "chinese_traditional": "Pirkanmaa / Birkaland", + "unknown1": "Pirkanmaa / Birkaland", + "unknown2": "Pirkanmaa / Birkaland", + "unknown3": "Pirkanmaa / Birkaland", + "unknown4": "Pirkanmaa / Birkaland" + }, + "coordinates": { + "latitude": 61.49597098, + "longitude": 23.763492354 + } + }, + { + "id": 1276248064, + "name": "Satakunta / Satakunda", + "translations": { + "japanese": "サタクンタ県", + "english": "Satakunta / Satakunda", + "french": "Satakunta", + "german": "Satakunta", + "italian": "Satakunta", + "spanish": "Satakunta", + "chinese_simple": "萨塔昆塔区", + "korean": "사타쿤타 주", + "dutch": "Satakunta", + "portuguese": "Satakunta", + "russian": "Сатакунта", + "chinese_traditional": "Satakunta / Satakunda", + "unknown1": "Satakunta / Satakunda", + "unknown2": "Satakunta / Satakunda", + "unknown3": "Satakunta / Satakunda", + "unknown4": "Satakunta / Satakunda" + }, + "coordinates": { + "latitude": 61.479491488, + "longitude": 21.796934272 + } + }, + { + "id": 1276313600, + "name": "Keski-Pohjanmaa / Mellersta Österbotten", + "translations": { + "japanese": "中部ポフヤンマー県", + "english": "Keski-Pohjanmaa / Mellersta Österbotten", + "french": "Ostrobotnie-Centrale", + "german": "Mittelösterbotten", + "italian": "Ostrobotnia Centrale", + "spanish": "Ostrobothnia Central", + "chinese_simple": "中博滕区", + "korean": "중앙오스트로보트니아 주", + "dutch": "Centraal-Österbotten", + "portuguese": "Ostrobótnia Central", + "russian": "Центральная Остроботния", + "chinese_traditional": "Keski-Pohjanmaa / Mellersta Österbotten", + "unknown1": "Keski-Pohjanmaa / Mellersta Österbotten", + "unknown2": "Keski-Pohjanmaa / Mellersta Österbotten", + "unknown3": "Keski-Pohjanmaa / Mellersta Österbotten", + "unknown4": "Keski-Pohjanmaa / Mellersta Österbotten" + }, + "coordinates": { + "latitude": 63.836058844, + "longitude": 23.131776769 + } + }, + { + "id": 1276379136, + "name": "Keski-Suomi / Mellersta Finland", + "translations": { + "japanese": "中央スオミ県", + "english": "Keski-Suomi / Mellersta Finland", + "french": "Finlande-Centrale", + "german": "Mittelfinnland", + "italian": "Finlandia Centrale", + "spanish": "Finlandia Central", + "chinese_simple": "中芬兰区", + "korean": "케스키수오미 주", + "dutch": "Centraal-Finland", + "portuguese": "Finlândia Central", + "russian": "Центральная Финляндия", + "chinese_traditional": "Keski-Suomi / Mellersta Finland", + "unknown1": "Keski-Suomi / Mellersta Finland", + "unknown2": "Keski-Suomi / Mellersta Finland", + "unknown3": "Keski-Suomi / Mellersta Finland", + "unknown4": "Keski-Suomi / Mellersta Finland" + }, + "coordinates": { + "latitude": 62.23754812, + "longitude": 25.741036794 + } + }, + { + "id": 1276444672, + "name": "Varsinais-Suomi / Egentliga Finland", + "translations": { + "japanese": "ヴァルシナイス=スオミ県", + "english": "Varsinais-Suomi / Egentliga Finland", + "french": "Finlande propre", + "german": "Varsinais-Suomi", + "italian": "Finlandia Sud-Occidentale", + "spanish": "Finlandia Propia", + "chinese_simple": "西南芬兰区", + "korean": "바르시나이스수오미 주", + "dutch": "Varsinais-Suomi", + "portuguese": "Finlândia Própria", + "russian": "Собственно Финляндия", + "chinese_traditional": "Varsinais-Suomi / Egentliga Finland", + "unknown1": "Varsinais-Suomi / Egentliga Finland", + "unknown2": "Varsinais-Suomi / Egentliga Finland", + "unknown3": "Varsinais-Suomi / Egentliga Finland", + "unknown4": "Varsinais-Suomi / Egentliga Finland" + }, + "coordinates": { + "latitude": 60.446776656, + "longitude": 22.263854487 + } + }, + { + "id": 1276510208, + "name": "Etelä-Karjala / Södra Karelen", + "translations": { + "japanese": "南カレリア県", + "english": "Etelä-Karjala / Södra Karelen", + "french": "Carélie du Sud", + "german": "Südkarelien", + "italian": "Carelia Meridionale", + "spanish": "Karelia del Sur", + "chinese_simple": "南卡累利阿区", + "korean": "남카렐리아 주", + "dutch": "Zuid-Karelië", + "portuguese": "Carélia do Sul", + "russian": "Южная Карелия", + "chinese_traditional": "Etelä-Karjala / Södra Karelen", + "unknown1": "Etelä-Karjala / Södra Karelen", + "unknown2": "Etelä-Karjala / Södra Karelen", + "unknown3": "Etelä-Karjala / Södra Karelen", + "unknown4": "Etelä-Karjala / Södra Karelen" + }, + "coordinates": { + "latitude": 61.062011024, + "longitude": 28.18000827 + } + }, + { + "id": 1276575744, + "name": "Päijät-Häme / Päijänne Tavastland", + "translations": { + "japanese": "パイヤト=ハメ県", + "english": "Päijät-Häme / Päijänne Tavastland", + "french": "Päijät-Häme", + "german": "Päijät-Häme", + "italian": "Päijät-Häme", + "spanish": "Päijänne Tavastia", + "chinese_simple": "派亚特海梅区", + "korean": "파이얏하메 주", + "dutch": "Päijät-Häme", + "portuguese": "Päijänne Tavastia", + "russian": "Пяйят-Хяме", + "chinese_traditional": "Päijät-Häme / Päijänne Tavastland", + "unknown1": "Päijät-Häme / Päijänne Tavastland", + "unknown2": "Päijät-Häme / Päijänne Tavastland", + "unknown3": "Päijät-Häme / Päijänne Tavastland", + "unknown4": "Päijät-Häme / Päijänne Tavastland" + }, + "coordinates": { + "latitude": 60.979613564, + "longitude": 25.647652751 + } + }, + { + "id": 1276641280, + "name": "Kanta-Häme / Egentliga Tavastland", + "translations": { + "japanese": "カンタ=ハメ県", + "english": "Kanta-Häme / Egentliga Tavastland", + "french": "Kanta-Häme", + "german": "Kanta-Häme", + "italian": "Kanta-Häme", + "spanish": "Tavastia Propia", + "chinese_simple": "坎塔海梅区", + "korean": "칸타하메 주", + "dutch": "Kanta-Häme", + "portuguese": "Tavastia Própria", + "russian": "Канта-Хяме", + "chinese_traditional": "Kanta-Häme / Egentliga Tavastland", + "unknown1": "Kanta-Häme / Egentliga Tavastland", + "unknown2": "Kanta-Häme / Egentliga Tavastland", + "unknown3": "Kanta-Häme / Egentliga Tavastland", + "unknown4": "Kanta-Häme / Egentliga Tavastland" + }, + "coordinates": { + "latitude": 60.996093056, + "longitude": 24.466619266 + } + }, + { + "id": 1276772352, + "name": "Kymenlaakso / Kymmenedalen", + "translations": { + "japanese": "キュメンラークソ県", + "english": "Kymenlaakso / Kymmenedalen", + "french": "Vallée de la Kymi", + "german": "Kymenlaakso", + "italian": "Kymenlaakso", + "spanish": "Kymenlaakso", + "chinese_simple": "屈米区", + "korean": "퀴멘락소 주", + "dutch": "Kymenlaakso", + "portuguese": "Kymenlaakso", + "russian": "Кюменлааксо", + "chinese_traditional": "Kymenlaakso / Kymmenedalen", + "unknown1": "Kymenlaakso / Kymmenedalen", + "unknown2": "Kymenlaakso / Kymmenedalen", + "unknown3": "Kymenlaakso / Kymmenedalen", + "unknown4": "Kymenlaakso / Kymmenedalen" + }, + "coordinates": { + "latitude": 60.86425712, + "longitude": 26.702343119 + } + }, + { + "id": 1276837888, + "name": "Ahvenanmaa / Åland", + "translations": { + "japanese": "アハベナンマー州", + "english": "Ahvenanmaa / Åland", + "french": "Åland", + "german": "Åland", + "italian": "Isole Åland", + "spanish": "Islas de Åland", + "chinese_simple": "奥兰岛自治区", + "korean": "아베난마 주", + "dutch": "Åland", + "portuguese": "Ilhas de Åland", + "russian": "Аландские острова", + "chinese_traditional": "Ahvenanmaa / Åland", + "unknown1": "Ahvenanmaa / Åland", + "unknown2": "Ahvenanmaa / Åland", + "unknown3": "Ahvenanmaa / Åland", + "unknown4": "Ahvenanmaa / Åland" + }, + "coordinates": { + "latitude": 60.089720996, + "longitude": 19.934746591 + } + } + ] + }, + { + "id": 77, + "iso_code": "FR", + "name": "France", + "translations": { + "japanese": "フランス", + "english": "France", + "french": "France", + "german": "Frankreich", + "italian": "Francia", + "spanish": "Francia", + "chinese_simple": "法国", + "korean": "프랑스", + "dutch": "Frankrijk", + "portuguese": "França", + "russian": "Франция", + "chinese_traditional": "France", + "unknown1": "France", + "unknown2": "France", + "unknown3": "France", + "unknown4": "France" + }, + "regions": [ + { + "id": 1291845632, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 48.850707452, + "longitude": 2.345587433 + } + }, + { + "id": 1291976704, + "name": "Île-de-France", + "translations": { + "japanese": "イール・ド・フランス", + "english": "Île-de-France", + "french": "Île-de-France", + "german": "Île-de-France", + "italian": "Île-de-France", + "spanish": "Isla de Francia", + "chinese_simple": "法兰西岛大区", + "korean": "일드프랑스", + "dutch": "Île-de-France", + "portuguese": "Ilha de França", + "russian": "Иль-де-Франс", + "chinese_traditional": "Île-de-France", + "unknown1": "Île-de-France", + "unknown2": "Île-de-France", + "unknown3": "Île-de-France", + "unknown4": "Île-de-France" + }, + "coordinates": { + "latitude": 48.850707452, + "longitude": 2.345587433 + } + }, + { + "id": 1292042240, + "name": "Alsace", + "translations": { + "japanese": "アルザス", + "english": "Alsace", + "french": "Alsace", + "german": "Elsass", + "italian": "Alsazia", + "spanish": "Alsacia", + "chinese_simple": "阿尔萨斯大区", + "korean": "알자스", + "dutch": "Elzas", + "portuguese": "Alsácia", + "russian": "Эльзас", + "chinese_traditional": "Alsace", + "unknown1": "Alsace", + "unknown2": "Alsace", + "unknown3": "Alsace", + "unknown4": "Alsace" + }, + "coordinates": { + "latitude": 48.581542416, + "longitude": 7.7398892109999995 + } + }, + { + "id": 1292107776, + "name": "Aquitaine", + "translations": { + "japanese": "アキテーヌ", + "english": "Aquitaine", + "french": "Aquitaine", + "german": "Aquitanien", + "italian": "Aquitania", + "spanish": "Aquitania", + "chinese_simple": "阿基坦大区", + "korean": "아키텐", + "dutch": "Aquitanië", + "portuguese": "Aquitânia", + "russian": "Аквитания", + "chinese_traditional": "Aquitaine", + "unknown1": "Aquitaine", + "unknown2": "Aquitaine", + "unknown3": "Aquitaine", + "unknown4": "Aquitaine" + }, + "coordinates": { + "latitude": 44.835204568, + "longitude": -0.5817875019999974 + } + }, + { + "id": 1292173312, + "name": "Auvergne", + "translations": { + "japanese": "オーベルニュ", + "english": "Auvergne", + "french": "Auvergne", + "german": "Auvergne", + "italian": "Alvernia", + "spanish": "Auvernia", + "chinese_simple": "奥弗涅大区", + "korean": "오베르뉴", + "dutch": "Auvergne", + "portuguese": "Auvérnia", + "russian": "Овернь", + "chinese_traditional": "Auvergne", + "unknown1": "Auvergne", + "unknown2": "Auvergne", + "unknown3": "Auvergne", + "unknown4": "Auvergne" + }, + "coordinates": { + "latitude": 45.774535612, + "longitude": 3.081673419 + } + }, + { + "id": 1292238848, + "name": "Lower Normandy", + "translations": { + "japanese": "バス・ノルマンディ", + "english": "Lower Normandy", + "french": "Basse-Normandie", + "german": "Basse-Normandie", + "italian": "Bassa Normandia", + "spanish": "Baja Normandía", + "chinese_simple": "下诺曼底大区", + "korean": "바스노르망디", + "dutch": "Laag-Normandië", + "portuguese": "Baixa Normandia", + "russian": "Нижняя Нормандия", + "chinese_traditional": "Lower Normandy", + "unknown1": "Lower Normandy", + "unknown2": "Lower Normandy", + "unknown3": "Lower Normandy", + "unknown4": "Lower Normandy" + }, + "coordinates": { + "latitude": 49.180297292, + "longitude": -0.356567162999994 + } + }, + { + "id": 1292304384, + "name": "Burgundy", + "translations": { + "japanese": "ブルゴーニュ", + "english": "Burgundy", + "french": "Bourgogne", + "german": "Burgund", + "italian": "Borgogna", + "spanish": "Borgoña", + "chinese_simple": "勃艮第大区", + "korean": "부르고뉴", + "dutch": "Bourgondië", + "portuguese": "Borgonha", + "russian": "Бургундия", + "chinese_traditional": "Burgundy", + "unknown1": "Burgundy", + "unknown2": "Burgundy", + "unknown3": "Burgundy", + "unknown4": "Burgundy" + }, + "coordinates": { + "latitude": 47.318114696, + "longitude": 5.037245143 + } + }, + { + "id": 1292369920, + "name": "Brittany", + "translations": { + "japanese": "ブルターニュ", + "english": "Brittany", + "french": "Bretagne", + "german": "Bretagne", + "italian": "Bretagna", + "spanish": "Bretaña", + "chinese_simple": "布列塔尼大区", + "korean": "브르타뉴", + "dutch": "Bretagne", + "portuguese": "Bretanha", + "russian": "Бретань", + "chinese_traditional": "Brittany", + "unknown1": "Brittany", + "unknown2": "Brittany", + "unknown3": "Brittany", + "unknown4": "Brittany" + }, + "coordinates": { + "latitude": 48.109130312, + "longitude": -1.6804233020000083 + } + }, + { + "id": 1292435456, + "name": "Centre", + "translations": { + "japanese": "サントル", + "english": "Centre", + "french": "Centre", + "german": "Centre", + "italian": "Centro", + "spanish": "Centro", + "chinese_simple": "中央大区", + "korean": "상트르", + "dutch": "Centre", + "portuguese": "Centro", + "russian": "Центр", + "chinese_traditional": "Centre", + "unknown1": "Centre", + "unknown2": "Centre", + "unknown3": "Centre", + "unknown4": "Centre" + }, + "coordinates": { + "latitude": 47.90039008, + "longitude": 1.900639934 + } + }, + { + "id": 1292500992, + "name": "Champagne-Ardenne", + "translations": { + "japanese": "シャンパーニュ・アルデンヌ", + "english": "Champagne-Ardenne", + "french": "Champagne-Ardenne", + "german": "Champagne-Ardenne", + "italian": "Champagne-Ardenne", + "spanish": "Champaña-Ardenas", + "chinese_simple": "香槟-阿登大区", + "korean": "샹파뉴아르덴", + "dutch": "Champagne-Ardennen", + "portuguese": "Champanha-Ardenas", + "russian": "Шампань-Арденны", + "chinese_traditional": "Champagne-Ardenne", + "unknown1": "Champagne-Ardenne", + "unknown2": "Champagne-Ardenne", + "unknown3": "Champagne-Ardenne", + "unknown4": "Champagne-Ardenne" + }, + "coordinates": { + "latitude": 48.960570732, + "longitude": 4.361584126 + } + }, + { + "id": 1292566528, + "name": "Corsica", + "translations": { + "japanese": "コルシカ", + "english": "Corsica", + "french": "Corse", + "german": "Korsika", + "italian": "Corsica", + "spanish": "Córcega", + "chinese_simple": "科西嘉大区", + "korean": "코르스", + "dutch": "Corsica", + "portuguese": "Córsega", + "russian": "Корсика", + "chinese_traditional": "Corsica", + "unknown1": "Corsica", + "unknown2": "Corsica", + "unknown3": "Corsica", + "unknown4": "Corsica" + }, + "coordinates": { + "latitude": 41.918334484, + "longitude": 8.73415461 + } + }, + { + "id": 1292632064, + "name": "Franche-Comté", + "translations": { + "japanese": "フランシュ・コンテ", + "english": "Franche-Comté", + "french": "Franche-Comté", + "german": "Franche-Comté", + "italian": "Franca Contea", + "spanish": "Franco Condado", + "chinese_simple": "弗朗什孔泰大区", + "korean": "프랑슈콩테", + "dutch": "Franche-Comté", + "portuguese": "Franco Condado", + "russian": "Франш-Конте", + "chinese_traditional": "Franche-Comté", + "unknown1": "Franche-Comté", + "unknown2": "Franche-Comté", + "unknown3": "Franche-Comté", + "unknown4": "Franche-Comté" + }, + "coordinates": { + "latitude": 47.235717236, + "longitude": 6.015031005 + } + }, + { + "id": 1292697600, + "name": "Upper Normandy", + "translations": { + "japanese": "オート・ノルマンディ", + "english": "Upper Normandy", + "french": "Haute-Normandie", + "german": "Haute-Normandie", + "italian": "Alta Normandia", + "spanish": "Alta Normandía", + "chinese_simple": "上诺曼底大区", + "korean": "오트노르망디", + "dutch": "Hoog-Normandië", + "portuguese": "Alta Normandia", + "russian": "Верхняя Нормандия", + "chinese_traditional": "Upper Normandy", + "unknown1": "Upper Normandy", + "unknown2": "Upper Normandy", + "unknown3": "Upper Normandy", + "unknown4": "Upper Normandy" + }, + "coordinates": { + "latitude": 49.438476, + "longitude": 1.0986358 + } + }, + { + "id": 1292763136, + "name": "Languedoc-Roussillon", + "translations": { + "japanese": "ラングドック・ルシヨン", + "english": "Languedoc-Roussillon", + "french": "Languedoc-Roussillon", + "german": "Languedoc-Roussillon", + "italian": "Linguadoca-Rossiglione", + "spanish": "Languedoc-Rosellón", + "chinese_simple": "朗格多克-鲁西永大区", + "korean": "랑그도크루시용", + "dutch": "Languedoc-Roussillon", + "portuguese": "Languedoque-Rossilhão", + "russian": "Лангедок-Руссильон", + "chinese_traditional": "Languedoc-Roussillon", + "unknown1": "Languedoc-Roussillon", + "unknown2": "Languedoc-Roussillon", + "unknown3": "Languedoc-Roussillon", + "unknown4": "Languedoc-Roussillon" + }, + "coordinates": { + "latitude": 43.604735832, + "longitude": 3.872691195 + } + }, + { + "id": 1292828672, + "name": "Limousin", + "translations": { + "japanese": "リムーザン", + "english": "Limousin", + "french": "Limousin", + "german": "Limousin", + "italian": "Limosino", + "spanish": "Lemosín", + "chinese_simple": "利穆赞大区", + "korean": "리무쟁", + "dutch": "Limousin", + "portuguese": "Limusino", + "russian": "Лимузен", + "chinese_traditional": "Limousin", + "unknown1": "Limousin", + "unknown2": "Limousin", + "unknown3": "Limousin", + "unknown4": "Limousin" + }, + "coordinates": { + "latitude": 45.829467252, + "longitude": 1.252444812 + } + }, + { + "id": 1292894208, + "name": "Lorraine", + "translations": { + "japanese": "ロレーヌ", + "english": "Lorraine", + "french": "Lorraine", + "german": "Lothringen", + "italian": "Lorena", + "spanish": "Lorena", + "chinese_simple": "洛林大区", + "korean": "로렌", + "dutch": "Lotharingen", + "portuguese": "Lorena", + "russian": "Лотарингия", + "chinese_traditional": "Lorraine", + "unknown1": "Lorraine", + "unknown2": "Lorraine", + "unknown3": "Lorraine", + "unknown4": "Lorraine" + }, + "coordinates": { + "latitude": 49.114379324, + "longitude": 6.168840017 + } + }, + { + "id": 1292959744, + "name": "Midi-Pyrénées", + "translations": { + "japanese": "ミディ・ピレネー", + "english": "Midi-Pyrénées", + "french": "Midi-Pyrénées", + "german": "Midi-Pyrénées", + "italian": "Mezzogiorno-Pirenei", + "spanish": "Mediodía-Pirineos", + "chinese_simple": "南部-比利牛斯大区", + "korean": "미디피레네", + "dutch": "Zuid-Frankrijk-Pyreneeën", + "portuguese": "Médio Pirenéus", + "russian": "Юг-Пиренеи", + "chinese_traditional": "Midi-Pyrénées", + "unknown1": "Midi-Pyrénées", + "unknown2": "Midi-Pyrénées", + "unknown3": "Midi-Pyrénées", + "unknown4": "Midi-Pyrénées" + }, + "coordinates": { + "latitude": 43.599242668, + "longitude": 1.433719719 + } + }, + { + "id": 1293025280, + "name": "Nord-Pas-de-Calais", + "translations": { + "japanese": "ノール・パ・ド・カレー", + "english": "Nord-Pas-de-Calais", + "french": "Nord-Pas de Calais", + "german": "Nord-Pas-de-Calais", + "italian": "Nord-Passo di Calais", + "spanish": "Norte-Paso de Calais", + "chinese_simple": "北部-加来海峡大区", + "korean": "노르파드칼레", + "dutch": "Noord-Nauw van Calais", + "portuguese": "Norte Pas de Calais", + "russian": "Нор-Па-де-Кале", + "chinese_traditional": "Nord-Pas-de-Calais", + "unknown1": "Nord-Pas-de-Calais", + "unknown2": "Nord-Pas-de-Calais", + "unknown3": "Nord-Pas-de-Calais", + "unknown4": "Nord-Pas-de-Calais" + }, + "coordinates": { + "latitude": 50.630492588, + "longitude": 3.059700703 + } + }, + { + "id": 1293090816, + "name": "Pays de la Loire", + "translations": { + "japanese": "ペイ・ド・ラ・ロワール", + "english": "Pays de la Loire", + "french": "Pays de la Loire", + "german": "Pays de la Loire", + "italian": "Paesi della Loira", + "spanish": "Países del Loira", + "chinese_simple": "卢瓦尔河地区", + "korean": "페이드라루아르", + "dutch": "Landen van de Loire", + "portuguese": "País do Loire", + "russian": "Земли Луары", + "chinese_traditional": "Pays de la Loire", + "unknown1": "Pays de la Loire", + "unknown2": "Pays de la Loire", + "unknown3": "Pays de la Loire", + "unknown4": "Pays de la Loire" + }, + "coordinates": { + "latitude": 47.213744580000004, + "longitude": -1.548587005999991 + } + }, + { + "id": 1293156352, + "name": "Picardy", + "translations": { + "japanese": "ピカルディー", + "english": "Picardy", + "french": "Picardie", + "german": "Picardie", + "italian": "Piccardia", + "spanish": "Picardía", + "chinese_simple": "皮卡第大区", + "korean": "피카르디", + "dutch": "Picardië", + "portuguese": "Picardia", + "russian": "Пикардия", + "chinese_traditional": "Picardy", + "unknown1": "Picardy", + "unknown2": "Picardy", + "unknown3": "Picardy", + "unknown4": "Picardy" + }, + "coordinates": { + "latitude": 49.883422284, + "longitude": 2.290655643 + } + }, + { + "id": 1293221888, + "name": "Poitou-Charentes", + "translations": { + "japanese": "ポワトゥー・シャラント", + "english": "Poitou-Charentes", + "french": "Poitou-Charentes", + "german": "Poitou-Charentes", + "italian": "Poitou-Charentes", + "spanish": "Poitou-Charentes", + "chinese_simple": "普瓦图-夏朗德大区", + "korean": "푸아투샤랑트", + "dutch": "Poitou-Charentes", + "portuguese": "Poitou-Charentes", + "russian": "Пуату-Шаранта", + "chinese_traditional": "Poitou-Charentes", + "unknown1": "Poitou-Charentes", + "unknown2": "Poitou-Charentes", + "unknown3": "Poitou-Charentes", + "unknown4": "Poitou-Charentes" + }, + "coordinates": { + "latitude": 46.58203072, + "longitude": 0.335083919 + } + }, + { + "id": 1293287424, + "name": "Provence-Alpes-Côte d'Azur", + "translations": { + "japanese": "プロヴァンス・アルプ・コート・ダジュール", + "english": "Provence-Alpes-Côte d'Azur", + "french": "Provence-Alpes-Côte d'Azur", + "german": "Provence-Alpes-Côte d'Azur", + "italian": "Provenza-Alpi-Costa Azzurra", + "spanish": "Provenza-Alpes-Costa Azul", + "chinese_simple": "普罗旺斯-阿尔卑斯-蓝色海岸大区", + "korean": "프로방스알프코트다쥐르", + "dutch": "Provence-Alpen-Côte d'Azur", + "portuguese": "Provença-Alpes-Costa Azul", + "russian": "Прованс-Альпы-Лазурный Берег", + "chinese_traditional": "Provence-Alpes-Côte d'Azur", + "unknown1": "Provence-Alpes-Côte d'Azur", + "unknown2": "Provence-Alpes-Côte d'Azur", + "unknown3": "Provence-Alpes-Côte d'Azur", + "unknown4": "Provence-Alpes-Côte d'Azur" + }, + "coordinates": { + "latitude": 43.291625484, + "longitude": 5.372329062 + } + }, + { + "id": 1293352960, + "name": "Rhône-Alpes", + "translations": { + "japanese": "ローヌ・アルプ", + "english": "Rhône-Alpes", + "french": "Rhône-Alpes", + "german": "Rhône-Alpes", + "italian": "Rodano-Alpi", + "spanish": "Ródano-Alpes", + "chinese_simple": "罗讷-阿尔卑斯大区", + "korean": "론알프", + "dutch": "Rhône-Alpen", + "portuguese": "Ródano-Alpes", + "russian": "Рона-Альпы", + "chinese_traditional": "Rhône-Alpes", + "unknown1": "Rhône-Alpes", + "unknown2": "Rhône-Alpes", + "unknown3": "Rhône-Alpes", + "unknown4": "Rhône-Alpes" + }, + "coordinates": { + "latitude": 45.752562956, + "longitude": 4.828504341 + } + }, + { + "id": 1293418496, + "name": "Guadeloupe", + "translations": { + "japanese": "グアドループ", + "english": "Guadeloupe", + "french": "Guadeloupe", + "german": "Guadeloupe", + "italian": "Guadalupa", + "spanish": "Guadalupe", + "chinese_simple": "瓜德罗普省", + "korean": "과들루프", + "dutch": "Guadeloupe", + "portuguese": "Guadalupe", + "russian": "Гваделупа", + "chinese_traditional": "Guadeloupe", + "unknown1": "Guadeloupe", + "unknown2": "Guadeloupe", + "unknown3": "Guadeloupe", + "unknown4": "Guadeloupe" + }, + "coordinates": { + "latitude": 15.996093568000001, + "longitude": -61.715376593 + } + }, + { + "id": 1293484032, + "name": "Martinique", + "translations": { + "japanese": "マルチニーク", + "english": "Martinique", + "french": "Martinique", + "german": "Martinique", + "italian": "Martinica", + "spanish": "Martinica", + "chinese_simple": "马提尼克省", + "korean": "마르티니크", + "dutch": "Martinique", + "portuguese": "Martinica", + "russian": "Мартиника", + "chinese_traditional": "Martinique", + "unknown1": "Martinique", + "unknown2": "Martinique", + "unknown3": "Martinique", + "unknown4": "Martinique" + }, + "coordinates": { + "latitude": 14.600829912, + "longitude": -61.072674649999996 + } + }, + { + "id": 1293549568, + "name": "French Guiana", + "translations": { + "japanese": "フランス領ギアナ", + "english": "French Guiana", + "french": "Guyane", + "german": "Französisch-Guayana", + "italian": "Guyana Francese", + "spanish": "Guayana Francesa", + "chinese_simple": "法属圭亚那省", + "korean": "프랑스령 기아나", + "dutch": "Frans-Guyana", + "portuguese": "Guiana Francesa", + "russian": "Французская Гвиана", + "chinese_traditional": "French Guiana", + "unknown1": "French Guiana", + "unknown2": "French Guiana", + "unknown3": "French Guiana", + "unknown4": "French Guiana" + }, + "coordinates": { + "latitude": 4.932861272, + "longitude": -52.327533681999995 + } + }, + { + "id": 1293615104, + "name": "Réunion", + "translations": { + "japanese": "レユニオン", + "english": "Réunion", + "french": "Réunion", + "german": "Réunion", + "italian": "Riunione", + "spanish": "Reunión", + "chinese_simple": "留尼汪省", + "korean": "레위니옹", + "dutch": "Réunion", + "portuguese": "Reunião", + "russian": "Реюньон", + "chinese_traditional": "Réunion", + "unknown1": "Réunion", + "unknown2": "Réunion", + "unknown3": "Réunion", + "unknown4": "Réunion" + }, + "coordinates": { + "latitude": -20.874024223999996, + "longitude": 55.448148826 + } + }, + { + "id": 1293680640, + "name": "Mayotte", + "translations": { + "japanese": "マヨット島", + "english": "Mayotte", + "french": "Mayotte", + "german": "Mayotte", + "italian": "Mayotte", + "spanish": "Mayotte", + "chinese_simple": "马约特省", + "korean": "마요트", + "dutch": "Mayotte", + "portuguese": "Maiote", + "russian": "Майотта", + "chinese_traditional": "Mayotte", + "unknown1": "Mayotte", + "unknown2": "Mayotte", + "unknown3": "Mayotte", + "unknown4": "Mayotte" + }, + "coordinates": { + "latitude": -12.777100488000002, + "longitude": 45.225342707 + } + } + ] + }, + { + "id": 78, + "iso_code": "DE", + "name": "Germany", + "translations": { + "japanese": "ドイツ", + "english": "Germany", + "french": "Allemagne", + "german": "Deutschland", + "italian": "Germania", + "spanish": "Alemania", + "chinese_simple": "德国", + "korean": "독일", + "dutch": "Duitsland", + "portuguese": "Alemanha", + "russian": "Германия", + "chinese_traditional": "Germany", + "unknown1": "Germany", + "unknown2": "Germany", + "unknown3": "Germany", + "unknown4": "Germany" + }, + "regions": [ + { + "id": 1308622848, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 52.520141004, + "longitude": 13.40335676 + } + }, + { + "id": 1308753920, + "name": "Berlin", + "translations": { + "japanese": "ベルリン", + "english": "Berlin", + "french": "Berlin", + "german": "Berlin", + "italian": "Berlino", + "spanish": "Berlín", + "chinese_simple": "柏林市", + "korean": "베를린", + "dutch": "Berlijn", + "portuguese": "Berlim", + "russian": "Берлин", + "chinese_traditional": "Berlin", + "unknown1": "Berlin", + "unknown2": "Berlin", + "unknown3": "Berlin", + "unknown4": "Berlin" + }, + "coordinates": { + "latitude": 52.520141004, + "longitude": 13.40335676 + } + }, + { + "id": 1308819456, + "name": "Hesse", + "translations": { + "japanese": "ヘッセン州", + "english": "Hesse", + "french": "Hesse", + "german": "Hessen", + "italian": "Assia", + "spanish": "Hesse", + "chinese_simple": "黑森州", + "korean": "헤센 주", + "dutch": "Hessen", + "portuguese": "Hesse", + "russian": "Гессен", + "chinese_traditional": "Hesse", + "unknown1": "Hesse", + "unknown2": "Hesse", + "unknown3": "Hesse", + "unknown4": "Hesse" + }, + "coordinates": { + "latitude": 50.07018986, + "longitude": 8.234275321 + } + }, + { + "id": 1308884992, + "name": "Baden-Württemberg", + "translations": { + "japanese": "バーデン・ビュルテンベルク州", + "english": "Baden-Württemberg", + "french": "Bade-Wurtemberg", + "german": "Baden-Württemberg", + "italian": "Baden-Württemberg", + "spanish": "Baden-Wurtemberg", + "chinese_simple": "巴登-符腾堡州", + "korean": "바덴뷔르템베르크 주", + "dutch": "Baden-Württemberg", + "portuguese": "Baden-Württemberg", + "russian": "Баден-Вюртемберг", + "chinese_traditional": "Baden-Württemberg", + "unknown1": "Baden-Württemberg", + "unknown2": "Baden-Württemberg", + "unknown3": "Baden-Württemberg", + "unknown4": "Baden-Württemberg" + }, + "coordinates": { + "latitude": 48.768309992, + "longitude": 9.17360893 + } + }, + { + "id": 1308950528, + "name": "Bavaria", + "translations": { + "japanese": "バイエルン州", + "english": "Bavaria", + "french": "Bavière", + "german": "Bayern", + "italian": "Baviera", + "spanish": "Baviera", + "chinese_simple": "巴伐利亚州", + "korean": "바이에른 주", + "dutch": "Beieren", + "portuguese": "Baviera", + "russian": "Бавария", + "chinese_traditional": "Bavaria", + "unknown1": "Bavaria", + "unknown2": "Bavaria", + "unknown3": "Bavaria", + "unknown4": "Bavaria" + }, + "coordinates": { + "latitude": 48.131102968, + "longitude": 11.552155437 + } + }, + { + "id": 1309016064, + "name": "Brandenburg", + "translations": { + "japanese": "ブランデンブルク州", + "english": "Brandenburg", + "french": "Brandebourg", + "german": "Brandenburg", + "italian": "Brandeburgo", + "spanish": "Brandeburgo", + "chinese_simple": "勃兰登堡州", + "korean": "브란덴부르크 주", + "dutch": "Brandenburg", + "portuguese": "Brandeburgo", + "russian": "Бранденбург", + "chinese_traditional": "Brandenburg", + "unknown1": "Brandenburg", + "unknown2": "Brandenburg", + "unknown3": "Brandenburg", + "unknown4": "Brandenburg" + }, + "coordinates": { + "latitude": 52.388305068, + "longitude": 13.035313767 + } + }, + { + "id": 1309081600, + "name": "Bremen", + "translations": { + "japanese": "ブレーメン", + "english": "Bremen", + "french": "Brême", + "german": "Bremen", + "italian": "Brema", + "spanish": "Bremen", + "chinese_simple": "不来梅市", + "korean": "브레멘 주", + "dutch": "Bremen", + "portuguese": "Bremen", + "russian": "Бремен", + "chinese_traditional": "Bremen", + "unknown1": "Bremen", + "unknown2": "Bremen", + "unknown3": "Bremen", + "unknown4": "Bremen" + }, + "coordinates": { + "latitude": 53.06396424, + "longitude": 8.805565937 + } + }, + { + "id": 1309147136, + "name": "Hamburg", + "translations": { + "japanese": "ハンブルク", + "english": "Hamburg", + "french": "Hambourg", + "german": "Hamburg", + "italian": "Amburgo", + "spanish": "Hamburgo", + "chinese_simple": "汉堡市", + "korean": "함부르크 주", + "dutch": "Hamburg", + "portuguese": "Hamburgo", + "russian": "Гамбург", + "chinese_traditional": "Hamburg", + "unknown1": "Hamburg", + "unknown2": "Hamburg", + "unknown3": "Hamburg", + "unknown4": "Hamburg" + }, + "coordinates": { + "latitude": 53.547362672, + "longitude": 9.986599422 + } + }, + { + "id": 1309212672, + "name": "Mecklenburg-Vorpommern", + "translations": { + "japanese": "メクレンブルク・フォアポンメルン州", + "english": "Mecklenburg-Vorpommern", + "french": "Mecklembourg-Poméranie antérieure", + "german": "Mecklenburg-Vorpommern", + "italian": "Meclemburgo-Pomerania Anteriore", + "spanish": "Mecklemburgo-Pomerania Occidental", + "chinese_simple": "梅克伦堡-前波莫瑞州", + "korean": "메클렌부르크포어포메른 주", + "dutch": "Mecklenburg-Voor-Pommeren", + "portuguese": "Mecklemburgo-Pomerânia Ocidental", + "russian": "Мекленбург-Передняя Померания", + "chinese_traditional": "Mecklenburg-Vorpommern", + "unknown1": "Mecklenburg-Vorpommern", + "unknown2": "Mecklenburg-Vorpommern", + "unknown3": "Mecklenburg-Vorpommern", + "unknown4": "Mecklenburg-Vorpommern" + }, + "coordinates": { + "latitude": 53.61328064, + "longitude": 11.414825962 + } + }, + { + "id": 1309278208, + "name": "Lower Saxony", + "translations": { + "japanese": "ニーダーザクセン州", + "english": "Lower Saxony", + "french": "Basse-Saxe", + "german": "Niedersachsen", + "italian": "Bassa Sassonia", + "spanish": "Baja Sajonia", + "chinese_simple": "下萨克森州", + "korean": "니더작센 주", + "dutch": "Nedersaksen", + "portuguese": "Baixa Saxónia", + "russian": "Нижняя Саксония", + "chinese_traditional": "Lower Saxony", + "unknown1": "Lower Saxony", + "unknown2": "Lower Saxony", + "unknown3": "Lower Saxony", + "unknown4": "Lower Saxony" + }, + "coordinates": { + "latitude": 52.366332412, + "longitude": 9.733913188 + } + }, + { + "id": 1309343744, + "name": "North Rhine-Westphalia", + "translations": { + "japanese": "ノルトライン・ウェストファーレン州", + "english": "North Rhine-Westphalia", + "french": "Rhénanie-du-Nord-Westphalie", + "german": "Nordrhein-Westfalen", + "italian": "Renania Settentrionale-Vestfalia", + "spanish": "Renania del Norte-Westfalia", + "chinese_simple": "北莱茵-威斯特法伦州", + "korean": "노르트라인베스트팔렌 주", + "dutch": "Noord-Rijnland-Westfalen", + "portuguese": "Renânia do Norte-Vestefália", + "russian": "Северный Рейн-Вестфалия", + "chinese_traditional": "North Rhine-Westphalia", + "unknown1": "North Rhine-Westphalia", + "unknown2": "North Rhine-Westphalia", + "unknown3": "North Rhine-Westphalia", + "unknown4": "North Rhine-Westphalia" + }, + "coordinates": { + "latitude": 51.240233792, + "longitude": 6.773089707 + } + }, + { + "id": 1309409280, + "name": "Rhineland-Palatinate", + "translations": { + "japanese": "ラインラント・ファルツ州", + "english": "Rhineland-Palatinate", + "french": "Rhénanie-Palatinat", + "german": "Rh쳐歮覀㞂ʮ∎d-Pfalz", + "italian": "Renania-Palatinato", + "spanish": "Renania-Palatinado", + "chinese_simple": "莱茵兰-普法尔茨州", + "korean": "라인란트팔츠 주", + "dutch": "Rijnland-Palts", + "portuguese": "Renânia-Palatinado", + "russian": "Рейнланд-Пфальц", + "chinese_traditional": "Rhineland-Palatinate", + "unknown1": "Rhineland-Palatinate", + "unknown2": "Rhineland-Palatinate", + "unknown3": "Rhineland-Palatinate", + "unknown4": "Rhineland-Palatinate" + }, + "coordinates": { + "latitude": 49.998778728, + "longitude": 8.256248037 + } + }, + { + "id": 1309474816, + "name": "Saarland", + "translations": { + "japanese": "ザールラント州", + "english": "Saarland", + "french": "Sarre", + "german": "Saarland", + "italian": "Saarland", + "spanish": "Sarre", + "chinese_simple": "萨尔州", + "korean": "자를란트 주", + "dutch": "Saarland", + "portuguese": "Sarre", + "russian": "Саар", + "chinese_traditional": "Saarland", + "unknown1": "Saarland", + "unknown2": "Saarland", + "unknown3": "Saarland", + "unknown4": "Saarland" + }, + "coordinates": { + "latitude": 49.229735768, + "longitude": 6.998310046 + } + }, + { + "id": 1309540352, + "name": "Saxony", + "translations": { + "japanese": "ザクセン州", + "english": "Saxony", + "french": "Saxe", + "german": "Sachsen", + "italian": "Sassonia", + "spanish": "Sajonia", + "chinese_simple": "萨克森州", + "korean": "작센 주", + "dutch": "Saksen", + "portuguese": "Saxónia", + "russian": "Саксония", + "chinese_traditional": "Saxony", + "unknown1": "Saxony", + "unknown2": "Saxony", + "unknown3": "Saxony", + "unknown4": "Saxony" + }, + "coordinates": { + "latitude": 51.03149356, + "longitude": 13.7329475 + } + }, + { + "id": 1309605888, + "name": "Saxony-Anhalt", + "translations": { + "japanese": "ザクセン・アンハルト州", + "english": "Saxony-Anhalt", + "french": "Saxe-Anhalt", + "german": "Sachsen-Anhalt", + "italian": "Sassonia-Anhalt", + "spanish": "Sajonia-Anhalt", + "chinese_simple": "萨克森-安哈特州", + "korean": "작센안할트 주", + "dutch": "Saksen-Anhalt", + "portuguese": "Saxónia-Anhalt", + "russian": "Саксония-Анхальт", + "chinese_traditional": "Saxony-Anhalt", + "unknown1": "Saxony-Anhalt", + "unknown2": "Saxony-Anhalt", + "unknown3": "Saxony-Anhalt", + "unknown4": "Saxony-Anhalt" + }, + "coordinates": { + "latitude": 52.124633196, + "longitude": 11.612580406 + } + }, + { + "id": 1309671424, + "name": "Schleswig-Holstein", + "translations": { + "japanese": "シュレスビヒ・ホルシュタイン州", + "english": "Schleswig-Holstein", + "french": "Schleswig-Holstein", + "german": "Schleswig-Holstein", + "italian": "Schleswig-Holstein", + "spanish": "Schleswig-Holstein", + "chinese_simple": "石勒苏益格-荷尔斯泰因州", + "korean": "슐레스비히홀슈타인 주", + "dutch": "Sleeswijk-Holstein", + "portuguese": "Schleswig-Holstein", + "russian": "Шлезвиг-Гольштейн", + "chinese_traditional": "Schleswig-Holstein", + "unknown1": "Schleswig-Holstein", + "unknown2": "Schleswig-Holstein", + "unknown3": "Schleswig-Holstein", + "unknown4": "Schleswig-Holstein" + }, + "coordinates": { + "latitude": 54.316405632, + "longitude": 10.118435718 + } + }, + { + "id": 1309736960, + "name": "Thuringia", + "translations": { + "japanese": "テューリンゲン州", + "english": "Thuringia", + "french": "Thuringe", + "german": "Thüringen", + "italian": "Turingia", + "spanish": "Turingia", + "chinese_simple": "图林根州", + "korean": "튀링겐 주", + "dutch": "Thüringen", + "portuguese": "Turíngia", + "russian": "Тюрингия", + "chinese_traditional": "Thuringia", + "unknown1": "Thuringia", + "unknown2": "Thuringia", + "unknown3": "Thuringia", + "unknown4": "Thuringia" + }, + "coordinates": { + "latitude": 50.971068756, + "longitude": 11.019317074 + } + } + ] + }, + { + "id": 79, + "iso_code": "GR", + "name": "Greece", + "translations": { + "japanese": "ギリシャ", + "english": "Greece", + "french": "Grèce", + "german": "Griechenland", + "italian": "Grecia", + "spanish": "Grecia", + "chinese_simple": "希腊", + "korean": "그리스", + "dutch": "Griekenland", + "portuguese": "Grécia", + "russian": "Греция", + "chinese_traditional": "Greece", + "unknown1": "Greece", + "unknown2": "Greece", + "unknown3": "Greece", + "unknown4": "Greece" + }, + "regions": [ + { + "id": 1325400064, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 37.974242732, + "longitude": 23.719546922 + } + }, + { + "id": 1325531136, + "name": "Attica", + "translations": { + "japanese": "アッティカ", + "english": "Attica", + "french": "Attique", + "german": "Attika", + "italian": "Attica", + "spanish": "Ática", + "chinese_simple": "阿提卡大区", + "korean": "아티카", + "dutch": "Attika", + "portuguese": "Ática", + "russian": "Аттика", + "chinese_traditional": "Attica", + "unknown1": "Attica", + "unknown2": "Attica", + "unknown3": "Attica", + "unknown4": "Attica" + }, + "coordinates": { + "latitude": 37.974242732, + "longitude": 23.719546922 + } + }, + { + "id": 1325596672, + "name": "Central Greece", + "translations": { + "japanese": "中央ギリシャ", + "english": "Central Greece", + "french": "Grèce-Centrale", + "german": "Mittelgriechenland", + "italian": "Grecia Centrale", + "spanish": "Grecia Central", + "chinese_simple": "中希腊大区", + "korean": "중부 그리스", + "dutch": "Centraal-Griekenland", + "portuguese": "Grécia Central", + "russian": "Центральная Греция", + "chinese_traditional": "Central Greece", + "unknown1": "Central Greece", + "unknown2": "Central Greece", + "unknown3": "Central Greece", + "unknown4": "Central Greece" + }, + "coordinates": { + "latitude": 38.89160112, + "longitude": 22.428649857 + } + }, + { + "id": 1325662208, + "name": "Central Macedonia", + "translations": { + "japanese": "中央マケドニア", + "english": "Central Macedonia", + "french": "Macédoine-Centrale", + "german": "Zentralmakedonien", + "italian": "Macedonia Centrale", + "spanish": "Macedonia Central", + "chinese_simple": "中马其顿大区", + "korean": "중부 마케도니아", + "dutch": "Centraal-Macedonië", + "portuguese": "Macedónia Central", + "russian": "Центральная Македония", + "chinese_traditional": "Central Macedonia", + "unknown1": "Central Macedonia", + "unknown2": "Central Macedonia", + "unknown3": "Central Macedonia", + "unknown4": "Central Macedonia" + }, + "coordinates": { + "latitude": 40.616454616, + "longitude": 22.966981398999998 + } + }, + { + "id": 1325727744, + "name": "Crete", + "translations": { + "japanese": "クレタ", + "english": "Crete", + "french": "Crète", + "german": "Kreta", + "italian": "Creta", + "spanish": "Creta", + "chinese_simple": "克里特大区", + "korean": "크레타", + "dutch": "Kreta", + "portuguese": "Creta", + "russian": "Крит", + "chinese_traditional": "Crete", + "unknown1": "Crete", + "unknown2": "Crete", + "unknown3": "Crete", + "unknown4": "Crete" + }, + "coordinates": { + "latitude": 35.332030848, + "longitude": 25.131293925 + } + }, + { + "id": 1325793280, + "name": "East Macedonia and Thrace", + "translations": { + "japanese": "東マケドニア・トラキア", + "english": "East Macedonia and Thrace", + "french": "Macédoine-Orientale-et-Thrace", + "german": "Ostmakedonien und Thrakien", + "italian": "Macedonia Orientale e Tracia", + "spanish": "Macedonia Oriental y Tracia", + "chinese_simple": "东马其顿和色雷斯大区", + "korean": "동부 마케도니아트라키아", + "dutch": "Oost-Macedonië en Thracië", + "portuguese": "Macedónia Oriental e Trácia", + "russian": "Восточная Македония и Фракия", + "chinese_traditional": "East Macedonia and Thrace", + "unknown1": "East Macedonia and Thrace", + "unknown2": "East Macedonia and Thrace", + "unknown3": "East Macedonia and Thrace", + "unknown4": "East Macedonia and Thrace" + }, + "coordinates": { + "latitude": 41.121825704, + "longitude": 25.416939233 + } + }, + { + "id": 1325858816, + "name": "Epirus", + "translations": { + "japanese": "イピロス", + "english": "Epirus", + "french": "Épire", + "german": "Epirus", + "italian": "Epiro", + "spanish": "Epiro", + "chinese_simple": "伊庇鲁斯大区", + "korean": "에피루스", + "dutch": "Epirus", + "portuguese": "Epiro", + "russian": "Эпир", + "chinese_traditional": "Epirus", + "unknown1": "Epirus", + "unknown2": "Epirus", + "unknown3": "Epirus", + "unknown4": "Epirus" + }, + "coordinates": { + "latitude": 39.649657752, + "longitude": 20.846614305 + } + }, + { + "id": 1325924352, + "name": "Ionian Islands", + "translations": { + "japanese": "イオニア", + "english": "Ionian Islands", + "french": "Îles Ioniennes", + "german": "Ionische Inseln", + "italian": "Isole Ionie", + "spanish": "Islas Jónicas", + "chinese_simple": "爱奥尼亚群岛大区", + "korean": "이오니아 제도", + "dutch": "Ionische Eilanden", + "portuguese": "Ilhas Jónicas", + "russian": "Ионические острова", + "chinese_traditional": "Ionian Islands", + "unknown1": "Ionian Islands", + "unknown2": "Ionian Islands", + "unknown3": "Ionian Islands", + "unknown4": "Ionian Islands" + }, + "coordinates": { + "latitude": 39.616698768, + "longitude": 19.912773875 + } + }, + { + "id": 1325989888, + "name": "North Aegean", + "translations": { + "japanese": "北エーゲ", + "english": "North Aegean", + "french": "Égée-Septentrionale", + "german": "Nördliche Ägäis", + "italian": "Egeo Settentrionale", + "spanish": "Egeo Septentrional", + "chinese_simple": "北爱琴海大区", + "korean": "북부 에게", + "dutch": "Noord-Egeïsche Eilanden", + "portuguese": "Egeu Setentrional", + "russian": "Северные Эгейские острова", + "chinese_traditional": "North Aegean", + "unknown1": "North Aegean", + "unknown2": "North Aegean", + "unknown3": "North Aegean", + "unknown4": "North Aegean" + }, + "coordinates": { + "latitude": 39.100341352, + "longitude": 26.548534107 + } + }, + { + "id": 1326055424, + "name": "Peloponnese", + "translations": { + "japanese": "ペロポネソス", + "english": "Peloponnese", + "french": "Péloponnèse", + "german": "Peloponnes", + "italian": "Peloponneso", + "spanish": "Peloponeso", + "chinese_simple": "伯罗奔尼撒大区", + "korean": "펠로폰네소스", + "dutch": "Peloponnesos", + "portuguese": "Peloponeso", + "russian": "Пелопоннес", + "chinese_traditional": "Peloponnese", + "unknown1": "Peloponnese", + "unknown2": "Peloponnese", + "unknown3": "Peloponnese", + "unknown4": "Peloponnese" + }, + "coordinates": { + "latitude": 37.501830628, + "longitude": 22.362731709 + } + }, + { + "id": 1326120960, + "name": "South Aegean", + "translations": { + "japanese": "南エーゲ", + "english": "South Aegean", + "french": "Égée-Méridionale", + "german": "Südliche Ägäis", + "italian": "Egeo Meridionale", + "spanish": "Egeo Meridional", + "chinese_simple": "南爱琴海大区", + "korean": "남부 에게", + "dutch": "Zuid-Egeïsche Eilanden", + "portuguese": "Egeu Meridional", + "russian": "Южные Эгейские острова", + "chinese_traditional": "South Aegean", + "unknown1": "South Aegean", + "unknown2": "South Aegean", + "unknown3": "South Aegean", + "unknown4": "South Aegean" + }, + "coordinates": { + "latitude": 36.436156812, + "longitude": 28.218460523 + } + }, + { + "id": 1326186496, + "name": "Thessaly", + "translations": { + "japanese": "テッサリーア", + "english": "Thessaly", + "french": "Thessalie", + "german": "Thessalien", + "italian": "Tessaglia", + "spanish": "Tesalia", + "chinese_simple": "色萨利大区", + "korean": "테살리아", + "dutch": "Thessalië", + "portuguese": "Tessália", + "russian": "Фессалия", + "chinese_traditional": "Thessaly", + "unknown1": "Thessaly", + "unknown2": "Thessaly", + "unknown3": "Thessaly", + "unknown4": "Thessaly" + }, + "coordinates": { + "latitude": 39.63317826, + "longitude": 22.417663499 + } + }, + { + "id": 1326252032, + "name": "West Greece", + "translations": { + "japanese": "西ギリシャ", + "english": "West Greece", + "french": "Grèce-Occidentale", + "german": "Westgriechenland", + "italian": "Grecia Occidentale", + "spanish": "Grecia Occidental", + "chinese_simple": "西希腊大区", + "korean": "서부 그리스", + "dutch": "West-Griekenland", + "portuguese": "Grécia Ocidental", + "russian": "Западная Греция", + "chinese_traditional": "West Greece", + "unknown1": "West Greece", + "unknown2": "West Greece", + "unknown3": "West Greece", + "unknown4": "West Greece" + }, + "coordinates": { + "latitude": 38.23242144, + "longitude": 21.736509303 + } + }, + { + "id": 1326317568, + "name": "West Macedonia", + "translations": { + "japanese": "西マケドニア", + "english": "West Macedonia", + "french": "Macédoine-Occidentale", + "german": "Westmakedonien", + "italian": "Macedonia Occidentale", + "spanish": "Macedonia Occidental", + "chinese_simple": "西马其顿大区", + "korean": "서부 마케도니아", + "dutch": "West-Macedonië", + "portuguese": "Macedónia Ocidental", + "russian": "Западная Македония", + "chinese_traditional": "West Macedonia", + "unknown1": "West Macedonia", + "unknown2": "West Macedonia", + "unknown3": "West Macedonia", + "unknown4": "West Macedonia" + }, + "coordinates": { + "latitude": 40.308837432, + "longitude": 21.796934272 + } + } + ] + }, + { + "id": 80, + "iso_code": "HU", + "name": "Hungary", + "translations": { + "japanese": "ハンガリー", + "english": "Hungary", + "french": "Hongrie", + "german": "Ungarn", + "italian": "Ungheria", + "spanish": "Hungría", + "chinese_simple": "匈牙利", + "korean": "헝가리", + "dutch": "Hongarije", + "portuguese": "Hungria", + "russian": "Венгрия", + "chinese_traditional": "Hungary", + "unknown1": "Hungary", + "unknown2": "Hungary", + "unknown3": "Hungary", + "unknown4": "Hungary" + }, + "regions": [ + { + "id": 1342177280, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 47.48840278, + "longitude": 19.077810667 + } + }, + { + "id": 1342308352, + "name": "Budapest", + "translations": { + "japanese": "ブダペスト", + "english": "Budapest", + "french": "Budapest", + "german": "Budapest", + "italian": "Budapest", + "spanish": "Budapest", + "chinese_simple": "布达佩斯市", + "korean": "부다페스트", + "dutch": "Boedapest", + "portuguese": "Budapeste", + "russian": "Будапешт", + "chinese_traditional": "Budapest", + "unknown1": "Budapest", + "unknown2": "Budapest", + "unknown3": "Budapest", + "unknown4": "Budapest" + }, + "coordinates": { + "latitude": 47.48840278, + "longitude": 19.077810667 + } + }, + { + "id": 1342373888, + "name": "Bács-Kiskun County", + "translations": { + "japanese": "バーチ・キシュクン州", + "english": "Bács-Kiskun County", + "french": "Bács-Kiskun", + "german": "Bács-Kiskun", + "italian": "Bács-Kiskun", + "spanish": "Bács-Kiskun", + "chinese_simple": "巴奇-基什孔州", + "korean": "바치키슈쿤 주", + "dutch": "Bács-Kiskun", + "portuguese": "Bács-Kiskun (condado)", + "russian": "Бач-Кишкун", + "chinese_traditional": "Bács-Kiskun County", + "unknown1": "Bács-Kiskun County", + "unknown2": "Bács-Kiskun County", + "unknown3": "Bács-Kiskun County", + "unknown4": "Bács-Kiskun County" + }, + "coordinates": { + "latitude": 46.900634232, + "longitude": 19.687553536 + } + }, + { + "id": 1342439424, + "name": "Baranya County", + "translations": { + "japanese": "バラニャ州", + "english": "Baranya County", + "french": "Baranya", + "german": "Baranya", + "italian": "Baranya", + "spanish": "Baranya", + "chinese_simple": "巴兰尼亚州", + "korean": "버러녀 주", + "dutch": "Baranya", + "portuguese": "Baranya (condado)", + "russian": "Баранья", + "chinese_traditional": "Baranya County", + "unknown1": "Baranya County", + "unknown2": "Baranya County", + "unknown3": "Baranya County", + "unknown4": "Baranya County" + }, + "coordinates": { + "latitude": 46.071166468, + "longitude": 18.215381564 + } + }, + { + "id": 1342504960, + "name": "Békés County", + "translations": { + "japanese": "ベーケーシュ州", + "english": "Békés County", + "french": "Békés", + "german": "Békés", + "italian": "Békés", + "spanish": "Békés", + "chinese_simple": "贝凯什州", + "korean": "베케시 주", + "dutch": "Békés", + "portuguese": "Békés (condado)", + "russian": "Бекеш", + "chinese_traditional": "Békés County", + "unknown1": "Békés County", + "unknown2": "Békés County", + "unknown3": "Békés County", + "unknown4": "Békés County" + }, + "coordinates": { + "latitude": 46.669921344, + "longitude": 21.099300539 + } + }, + { + "id": 1342570496, + "name": "Borsod-Abaúj-Zemplén County", + "translations": { + "japanese": "ボルショド・アバウーイ・ゼンプレーン州", + "english": "Borsod-Abaúj-Zemplén County", + "french": "Borsod-Abaúj-Zemplén", + "german": "Borsod-Abaúj-Zemplén", + "italian": "Borsod-Abaúj-Zemplén", + "spanish": "Borsod-Abaúj-Zemplén", + "chinese_simple": "包尔绍德-奥包乌伊-曾普伦州", + "korean": "보르쇼드어버우이젬플렌 주", + "dutch": "Borsod-Abaúj-Zemplén", + "portuguese": "Borsod-Abaúj-Zemplén (condado)", + "russian": "Боршод-Абауй-Земплен", + "chinese_traditional": "Borsod-Abaúj-Zemplén County", + "unknown1": "Borsod-Abaúj-Zemplén County", + "unknown2": "Borsod-Abaúj-Zemplén County", + "unknown3": "Borsod-Abaúj-Zemplén County", + "unknown4": "Borsod-Abaúj-Zemplén County" + }, + "coordinates": { + "latitude": 48.098143984000004, + "longitude": 20.786189336 + } + }, + { + "id": 1342636032, + "name": "Csongrád County", + "translations": { + "japanese": "チョングラード州", + "english": "Csongrád County", + "french": "Csongrád", + "german": "Csongrád", + "italian": "Csongrád", + "spanish": "Csongrád", + "chinese_simple": "琼格拉德州", + "korean": "촌그라드 주", + "dutch": "Csongrád", + "portuguese": "Csongrád (condado)", + "russian": "Чонград", + "chinese_traditional": "Csongrád County", + "unknown1": "Csongrád County", + "unknown2": "Csongrád County", + "unknown3": "Csongrád County", + "unknown4": "Csongrád County" + }, + "coordinates": { + "latitude": 46.25244088, + "longitude": 20.154473751 + } + }, + { + "id": 1342701568, + "name": "Fejér County", + "translations": { + "japanese": "フェイェール州", + "english": "Fejér County", + "french": "Fejér", + "german": "Fejér", + "italian": "Fejér", + "spanish": "Fejér", + "chinese_simple": "费耶尔州", + "korean": "페예르 주", + "dutch": "Fejér", + "portuguese": "Fejér (condado)", + "russian": "Фейер", + "chinese_traditional": "Fejér County", + "unknown1": "Fejér County", + "unknown2": "Fejér County", + "unknown3": "Fejér County", + "unknown4": "Fejér County" + }, + "coordinates": { + "latitude": 47.197265088, + "longitude": 18.40214965 + } + }, + { + "id": 1342767104, + "name": "Győr-Moson-Sopron County", + "translations": { + "japanese": "ジェール・モション・ショプロン州", + "english": "Győr-Moson-Sopron County", + "french": "Győr-Moson-Sopron", + "german": "Győr-Moson-Sopron", + "italian": "Győr-Moson-Sopron", + "spanish": "Győr-Moson-Sopron", + "chinese_simple": "杰尔-莫松-肖普朗州", + "korean": "죄르모숀쇼프론 주", + "dutch": "Győr-Moson-Sopron", + "portuguese": "Gyor-Moson-Sopron (condado)", + "russian": "Дьёр-Мошон-Шопрон", + "chinese_traditional": "Győr-Moson-Sopron County", + "unknown1": "Győr-Moson-Sopron County", + "unknown2": "Győr-Moson-Sopron County", + "unknown3": "Győr-Moson-Sopron County", + "unknown4": "Győr-Moson-Sopron County" + }, + "coordinates": { + "latitude": 47.675170356, + "longitude": 17.63310459 + } + }, + { + "id": 1342832640, + "name": "Hajdú-Bihar County", + "translations": { + "japanese": "ハイドゥー・ヒバル州", + "english": "Hajdú-Bihar County", + "french": "Hajdú-Bihar", + "german": "Hajdú-Bihar", + "italian": "Hajdú-Bihar", + "spanish": "Hajdú-Bihar", + "chinese_simple": "豪伊杜-比豪尔州", + "korean": "허이두 비허르 주", + "dutch": "Hajdú-Bihar", + "portuguese": "Hajdú-Bihar (condado)", + "russian": "Хайду-Бихар", + "chinese_traditional": "Hajdú-Bihar County", + "unknown1": "Hajdú-Bihar County", + "unknown2": "Hajdú-Bihar County", + "unknown3": "Hajdú-Bihar County", + "unknown4": "Hajdú-Bihar County" + }, + "coordinates": { + "latitude": 47.532348092, + "longitude": 21.621152544 + } + }, + { + "id": 1342898176, + "name": "Heves County", + "translations": { + "japanese": "ヘヴェシュ州", + "english": "Heves County", + "french": "Heves", + "german": "Heves", + "italian": "Heves", + "spanish": "Heves", + "chinese_simple": "赫维什州", + "korean": "헤베시 주", + "dutch": "Heves", + "portuguese": "Heves (condado)", + "russian": "Хевеш", + "chinese_traditional": "Heves County", + "unknown1": "Heves County", + "unknown2": "Heves County", + "unknown3": "Heves County", + "unknown4": "Heves County" + }, + "coordinates": { + "latitude": 47.894896916, + "longitude": 20.37969409 + } + }, + { + "id": 1342963712, + "name": "Jász-Nagykun-Szolnok County", + "translations": { + "japanese": "ヤース・ナチクン・ソルノク州", + "english": "Jász-Nagykun-Szolnok County", + "french": "Jász-Nagykun-Szolnok", + "german": "Jász-Nagykun-Szolnok", + "italian": "Jász-Nagykun-Szolnok", + "spanish": "Jász-Nagyk쳐歮覀㞂ʮ∎辝硂旱✑櫙᰺͖ﻩ", + "chinese_simple": "加兹-纳杰孔-索尔诺克州", + "korean": "야스너지쿤솔노크 주", + "dutch": "Jász-Nagykun-Szolnok", + "portuguese": "Jász-Nagykun-Szolnok (condado)", + "russian": "Яс-Надькун-Сольнок", + "chinese_traditional": "Jász-Nagykun-Szolnok County", + "unknown1": "Jász-Nagykun-Szolnok County", + "unknown2": "Jász-Nagykun-Szolnok County", + "unknown3": "Jász-Nagykun-Szolnok County", + "unknown4": "Jász-Nagykun-Szolnok County" + }, + "coordinates": { + "latitude": 47.169799268, + "longitude": 20.181939646 + } + }, + { + "id": 1343029248, + "name": "Komárom-Esztergom County", + "translations": { + "japanese": "コマーロム・エステルゴム州", + "english": "Komárom-Esztergom County", + "french": "Komárom-Esztergom", + "german": "Komárom-Esztergom", + "italian": "Komárom-Esztergom", + "spanish": "Komárom-Esztergom", + "chinese_simple": "科马罗姆-埃斯泰尔戈姆州", + "korean": "코마롬에스테르곰 주", + "dutch": "Komárom-Esztergom", + "portuguese": "Komárom-Esztergom (condado)", + "russian": "Комаром-Эстергом", + "chinese_traditional": "Komárom-Esztergom County", + "unknown1": "Komárom-Esztergom County", + "unknown2": "Komárom-Esztergom County", + "unknown3": "Komárom-Esztergom County", + "unknown4": "Komárom-Esztergom County" + }, + "coordinates": { + "latitude": 47.548827584, + "longitude": 18.435108724 + } + }, + { + "id": 1343094784, + "name": "Nógrád County", + "translations": { + "japanese": "ノーグラード州", + "english": "Nógrád County", + "french": "Nógrád", + "german": "Nógrád", + "italian": "Nógrád", + "spanish": "Nógrád", + "chinese_simple": "诺格拉德州", + "korean": "노그라드 주", + "dutch": "Nógrád", + "portuguese": "Nógrád (condado)", + "russian": "Ноград", + "chinese_traditional": "Nógrád County", + "unknown1": "Nógrád County", + "unknown2": "Nógrád County", + "unknown3": "Nógrád County", + "unknown4": "Nógrád County" + }, + "coordinates": { + "latitude": 48.103637148, + "longitude": 19.813896653 + } + }, + { + "id": 1343160320, + "name": "Pest County", + "translations": { + "japanese": "ペシュト州", + "english": "Pest County", + "french": "Pest", + "german": "Pest", + "italian": "Pest", + "spanish": "Pest", + "chinese_simple": "佩斯州", + "korean": "페슈트 주", + "dutch": "Pest", + "portuguese": "Pest (condado)", + "russian": "Пешт", + "chinese_traditional": "Pest County", + "unknown1": "Pest County", + "unknown2": "Pest County", + "unknown3": "Pest County", + "unknown4": "Pest County" + }, + "coordinates": { + "latitude": 47.48840278, + "longitude": 19.077810667 + } + }, + { + "id": 1343225856, + "name": "Somogy County", + "translations": { + "japanese": "ショモジ州", + "english": "Somogy County", + "french": "Somogy", + "german": "Somogy", + "italian": "Somogy", + "spanish": "Somogy", + "chinese_simple": "绍莫吉州", + "korean": "쇼모지 주", + "dutch": "Somogy", + "portuguese": "Somogy (condado)", + "russian": "Шомодь", + "chinese_traditional": "Somogy County", + "unknown1": "Somogy County", + "unknown2": "Somogy County", + "unknown3": "Somogy County", + "unknown4": "Somogy County" + }, + "coordinates": { + "latitude": 46.351317832, + "longitude": 17.786913602 + } + }, + { + "id": 1343291392, + "name": "Szabolcs-Szatmár-Bereg County", + "translations": { + "japanese": "サボルチ・サトマール・ベレグ州", + "english": "Szabolcs-Szatmár-Bereg County", + "french": "Szabolcs-Szatmár-Bereg", + "german": "Szabolcs-Szatmár-Bereg", + "italian": "Szabolcs-Szatmár-Bereg", + "spanish": "Szabolcs-Szatmár-Bereg", + "chinese_simple": "索博尔奇-索特马尔-贝拉格州", + "korean": "서볼츠서트마르베레그 주", + "dutch": "Szabolcs-Szatmár-Bereg", + "portuguese": "Szabolcs-Szatmár-Bereg (condado)", + "russian": "Сабольч-Сатмар-Берег", + "chinese_traditional": "Szabolcs-Szatmár-Bereg County", + "unknown1": "Szabolcs-Szatmár-Bereg County", + "unknown2": "Szabolcs-Szatmár-Bereg County", + "unknown3": "Szabolcs-Szatmár-Bereg County", + "unknown4": "Szabolcs-Szatmár-Bereg County" + }, + "coordinates": { + "latitude": 47.95532172, + "longitude": 21.720029766 + } + }, + { + "id": 1343356928, + "name": "Tolna County", + "translations": { + "japanese": "トルナ州", + "english": "Tolna County", + "french": "Tolna", + "german": "Tolna", + "italian": "Tolna", + "spanish": "Tolna", + "chinese_simple": "托尔瑙州", + "korean": "톨너 주", + "dutch": "Tolna", + "portuguese": "Tolna (condado)", + "russian": "Тольна", + "chinese_traditional": "Tolna County", + "unknown1": "Tolna County", + "unknown2": "Tolna County", + "unknown3": "Tolna County", + "unknown4": "Tolna County" + }, + "coordinates": { + "latitude": 46.345824668, + "longitude": 18.704274495 + } + }, + { + "id": 1343422464, + "name": "Vas County", + "translations": { + "japanese": "ヴァシュ州", + "english": "Vas County", + "french": "Vas", + "german": "Vas", + "italian": "Vas", + "spanish": "Vas", + "chinese_simple": "沃什州", + "korean": "버시 주", + "dutch": "Vas", + "portuguese": "Vas (condado)", + "russian": "Ваш", + "chinese_traditional": "Vas County", + "unknown1": "Vas County", + "unknown2": "Vas County", + "unknown3": "Vas County", + "unknown4": "Vas County" + }, + "coordinates": { + "latitude": 47.230224072, + "longitude": 16.622359654 + } + }, + { + "id": 1343488000, + "name": "Veszprém County", + "translations": { + "japanese": "ベスプレーム州", + "english": "Veszprém County", + "french": "Veszprém", + "german": "Veszprém", + "italian": "Veszprém", + "spanish": "Veszprém", + "chinese_simple": "维斯普雷姆州", + "korean": "베스프렘 주", + "dutch": "Veszprém", + "portuguese": "Veszprém (condado)", + "russian": "Веспрем", + "chinese_traditional": "Veszprém County", + "unknown1": "Veszprém County", + "unknown2": "Veszprém County", + "unknown3": "Veszprém County", + "unknown4": "Veszprém County" + }, + "coordinates": { + "latitude": 47.098388136, + "longitude": 17.913256719 + } + }, + { + "id": 1343553536, + "name": "Zala County", + "translations": { + "japanese": "ザラ州", + "english": "Zala County", + "french": "Zala", + "german": "Zala", + "italian": "Zala", + "spanish": "Zala", + "chinese_simple": "佐洛州", + "korean": "절러 주", + "dutch": "Zala", + "portuguese": "Zala (condado)", + "russian": "Зала", + "chinese_traditional": "Zala County", + "unknown1": "Zala County", + "unknown2": "Zala County", + "unknown3": "Zala County", + "unknown4": "Zala County" + }, + "coordinates": { + "latitude": 46.840209428, + "longitude": 16.836593635 + } + } + ] + }, + { + "id": 81, + "iso_code": "IS", + "name": "Iceland", + "translations": { + "japanese": "アイスランド", + "english": "Iceland", + "french": "Islande", + "german": "Island", + "italian": "Islanda", + "spanish": "Islandia", + "chinese_simple": "冰岛", + "korean": "아이슬란드", + "dutch": "IJsland", + "portuguese": "Islândia", + "russian": "Исландия", + "chinese_traditional": "Iceland", + "unknown1": "Iceland", + "unknown2": "Iceland", + "unknown3": "Iceland", + "unknown4": "Iceland" + }, + "regions": [ + { + "id": 1358954496, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 64.1326897, + "longitude": -21.889828843000004 + } + }, + { + "id": 1359020032, + "name": "Iceland", + "translations": { + "japanese": "アイスランド", + "english": "Iceland", + "french": "Islande", + "german": "Island", + "italian": "Islanda", + "spanish": "Islandia", + "chinese_simple": "冰岛", + "korean": "아이슬란드", + "dutch": "IJsland", + "portuguese": "Islândia", + "russian": "Исландия", + "chinese_traditional": "Iceland", + "unknown1": "Iceland", + "unknown2": "Iceland", + "unknown3": "Iceland", + "unknown4": "Iceland" + }, + "coordinates": { + "latitude": 64.1326897, + "longitude": -21.889828843000004 + } + } + ] + }, + { + "id": 82, + "iso_code": "IE", + "name": "Ireland", + "translations": { + "japanese": "アイルランド", + "english": "Ireland", + "french": "Irlande", + "german": "Irland", + "italian": "Irlanda", + "spanish": "Irlanda", + "chinese_simple": "爱尔兰", + "korean": "아일랜드", + "dutch": "Ierland", + "portuguese": "Irlanda", + "russian": "Ирландия", + "chinese_traditional": "Ireland", + "unknown1": "Ireland", + "unknown2": "Ireland", + "unknown3": "Ireland", + "unknown4": "Ireland" + }, + "regions": [ + { + "id": 1375731712, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 53.33862244, + "longitude": -6.256241409000012 + } + }, + { + "id": 1375862784, + "name": "Dublin", + "translations": { + "japanese": "ダブリン州", + "english": "Dublin", + "french": "Dublin", + "german": "Dublin", + "italian": "Dublino", + "spanish": "Dublín", + "chinese_simple": "都柏林地区", + "korean": "더블린", + "dutch": "Dublin", + "portuguese": "Dublin", + "russian": "Дублин", + "chinese_traditional": "Dublin", + "unknown1": "Dublin", + "unknown2": "Dublin", + "unknown3": "Dublin", + "unknown4": "Dublin" + }, + "coordinates": { + "latitude": 53.33862244, + "longitude": -6.256241409000012 + } + }, + { + "id": 1376387072, + "name": "County Carlow", + "translations": { + "japanese": "カーロウ州", + "english": "County Carlow", + "french": "Carlow", + "german": "Carlow", + "italian": "Carlow", + "spanish": "Carlow", + "chinese_simple": "卡洛郡", + "korean": "칼로우 주", + "dutch": "Carlow", + "portuguese": "Carlow (condado)", + "russian": "Карлоу", + "chinese_traditional": "County Carlow", + "unknown1": "County Carlow", + "unknown2": "County Carlow", + "unknown3": "County Carlow", + "unknown4": "County Carlow" + }, + "coordinates": { + "latitude": 52.827758188, + "longitude": -6.926409247000009 + } + }, + { + "id": 1376452608, + "name": "County Cavan", + "translations": { + "japanese": "キャバン州", + "english": "County Cavan", + "french": "Cavan", + "german": "Cavan", + "italian": "Cavan", + "spanish": "Cavan", + "chinese_simple": "卡文郡", + "korean": "캐번 주", + "dutch": "Cavan", + "portuguese": "Cavan (condado)", + "russian": "Каван", + "chinese_traditional": "County Cavan", + "unknown1": "County Cavan", + "unknown2": "County Cavan", + "unknown3": "County Cavan", + "unknown4": "County Cavan" + }, + "coordinates": { + "latitude": 53.986815792, + "longitude": -7.354877208999994 + } + }, + { + "id": 1376518144, + "name": "County Clare", + "translations": { + "japanese": "クレア州", + "english": "County Clare", + "french": "Clare", + "german": "Clare", + "italian": "Clare", + "spanish": "Clare", + "chinese_simple": "克莱尔郡", + "korean": "클레어 주", + "dutch": "Clare", + "portuguese": "Clare (condado)", + "russian": "Клэр", + "chinese_traditional": "County Clare", + "unknown1": "County Clare", + "unknown2": "County Clare", + "unknown3": "County Clare", + "unknown4": "County Clare" + }, + "coordinates": { + "latitude": 52.84423768, + "longitude": -8.975365014000005 + } + }, + { + "id": 1376583680, + "name": "County Cork", + "translations": { + "japanese": "コーク州", + "english": "County Cork", + "french": "Cork", + "german": "Cork", + "italian": "Cork", + "spanish": "Cork", + "chinese_simple": "科克郡", + "korean": "코크 주", + "dutch": "Cork", + "portuguese": "Cork (condado)", + "russian": "Корк", + "chinese_traditional": "County Cork", + "unknown1": "County Cork", + "unknown2": "County Cork", + "unknown3": "County Cork", + "unknown4": "County Cork" + }, + "coordinates": { + "latitude": 51.893920308, + "longitude": -8.464499367000002 + } + }, + { + "id": 1376649216, + "name": "County Donegal", + "translations": { + "japanese": "ドニゴール州", + "english": "County Donegal", + "french": "Donegal", + "german": "Donegal", + "italian": "Donegal", + "spanish": "Donegal", + "chinese_simple": "多内加尔郡", + "korean": "도니골 주", + "dutch": "Donegal", + "portuguese": "Donegal (condado)", + "russian": "Донегол", + "chinese_traditional": "County Donegal", + "unknown1": "County Donegal", + "unknown2": "County Donegal", + "unknown3": "County Donegal", + "unknown4": "County Donegal" + }, + "coordinates": { + "latitude": 54.832763048, + "longitude": -7.475727147000015 + } + }, + { + "id": 1376714752, + "name": "County Galway", + "translations": { + "japanese": "ゴールウェイ州", + "english": "County Galway", + "french": "Galway", + "german": "Galway", + "italian": "Galway", + "spanish": "Galway", + "chinese_simple": "戈尔韦郡", + "korean": "골웨이 주", + "dutch": "Galway", + "portuguese": "Galway (condado)", + "russian": "Голуэй", + "chinese_traditional": "County Galway", + "unknown1": "County Galway", + "unknown2": "County Galway", + "unknown3": "County Galway", + "unknown4": "County Galway" + }, + "coordinates": { + "latitude": 53.272704472, + "longitude": -9.041283162000013 + } + }, + { + "id": 1376780288, + "name": "County Kerry", + "translations": { + "japanese": "ケリー州", + "english": "County Kerry", + "french": "Kerry", + "german": "Kerry", + "italian": "Kerry", + "spanish": "Kerry", + "chinese_simple": "凯里郡", + "korean": "케리 주", + "dutch": "Kerry", + "portuguese": "Kerry (condado)", + "russian": "Керри", + "chinese_traditional": "County Kerry", + "unknown1": "County Kerry", + "unknown2": "County Kerry", + "unknown3": "County Kerry", + "unknown4": "County Kerry" + }, + "coordinates": { + "latitude": 52.26745546, + "longitude": -9.694971463000002 + } + }, + { + "id": 1376845824, + "name": "County Kildare", + "translations": { + "japanese": "キルデア州", + "english": "County Kildare", + "french": "Kildare", + "german": "Kildare", + "italian": "Kildare", + "spanish": "Kildare", + "chinese_simple": "基尔代尔郡", + "korean": "킬데어 주", + "dutch": "Kildare", + "portuguese": "Kildare (condado)", + "russian": "Килдэр", + "chinese_traditional": "County Kildare", + "unknown1": "County Kildare", + "unknown2": "County Kildare", + "unknown3": "County Kildare", + "unknown4": "County Kildare" + }, + "coordinates": { + "latitude": 53.212279668, + "longitude": -6.662736655000003 + } + }, + { + "id": 1376911360, + "name": "County Kilkenny", + "translations": { + "japanese": "キルケニー州", + "english": "County Kilkenny", + "french": "Kilkenny", + "german": "Kilkenny", + "italian": "Kilkenny", + "spanish": "Kilkenny", + "chinese_simple": "基尔肯尼郡", + "korean": "킬케니 주", + "dutch": "Kilkenny", + "portuguese": "Kilkenny (condado)", + "russian": "Килкенни", + "chinese_traditional": "County Kilkenny", + "unknown1": "County Kilkenny", + "unknown2": "County Kilkenny", + "unknown3": "County Kilkenny", + "unknown4": "County Kilkenny" + }, + "coordinates": { + "latitude": 52.646483776000004, + "longitude": -7.2505068080000115 + } + }, + { + "id": 1376976896, + "name": "County Laois", + "translations": { + "japanese": "リーシュ州", + "english": "County Laois", + "french": "Laois", + "german": "Laois", + "italian": "Laois", + "spanish": "Laois", + "chinese_simple": "莱伊什郡", + "korean": "리시 주", + "dutch": "Laois", + "portuguese": "Laois (condado)", + "russian": "Лиишь", + "chinese_traditional": "County Laois", + "unknown1": "County Laois", + "unknown2": "County Laois", + "unknown3": "County Laois", + "unknown4": "County Laois" + }, + "coordinates": { + "latitude": 53.025512092, + "longitude": -7.299945419000011 + } + }, + { + "id": 1377042432, + "name": "County Leitrim", + "translations": { + "japanese": "リートリム州", + "english": "County Leitrim", + "french": "Leitrim", + "german": "Leitrim", + "italian": "Leitrim", + "spanish": "Leitrim", + "chinese_simple": "利特里姆郡", + "korean": "리트림 주", + "dutch": "Leitrim", + "portuguese": "Leitrim (condado)", + "russian": "Литрим", + "chinese_traditional": "County Leitrim", + "unknown1": "County Leitrim", + "unknown2": "County Leitrim", + "unknown3": "County Leitrim", + "unknown4": "County Leitrim" + }, + "coordinates": { + "latitude": 53.94287048, + "longitude": -8.085470015999988 + } + }, + { + "id": 1377107968, + "name": "County Limerick", + "translations": { + "japanese": "リムリック州", + "english": "County Limerick", + "french": "Limerick", + "german": "Limerick", + "italian": "Limerick", + "spanish": "Limerick", + "chinese_simple": "利默里克郡", + "korean": "리머릭 주", + "dutch": "Limerick", + "portuguese": "Limerick (condado)", + "russian": "Лимерик", + "chinese_traditional": "County Limerick", + "unknown1": "County Limerick", + "unknown2": "County Limerick", + "unknown3": "County Limerick", + "unknown4": "County Limerick" + }, + "coordinates": { + "latitude": 52.662963268, + "longitude": -8.618308379000013 + } + }, + { + "id": 1377173504, + "name": "County Longford", + "translations": { + "japanese": "ロングフォード州", + "english": "County Longford", + "french": "Longford", + "german": "Longford", + "italian": "Longford", + "spanish": "Longford", + "chinese_simple": "朗福德郡", + "korean": "롱퍼드 주", + "dutch": "Longford", + "portuguese": "Longford (condado)", + "russian": "Лонгфорд", + "chinese_traditional": "County Longford", + "unknown1": "County Longford", + "unknown2": "County Longford", + "unknown3": "County Longford", + "unknown4": "County Longford" + }, + "coordinates": { + "latitude": 53.72314392, + "longitude": -7.794331529000004 + } + }, + { + "id": 1377239040, + "name": "County Louth", + "translations": { + "japanese": "ラウス州", + "english": "County Louth", + "french": "Louth", + "german": "Louth", + "italian": "Louth", + "spanish": "Louth", + "chinese_simple": "劳斯郡", + "korean": "라우스 주", + "dutch": "Louth", + "portuguese": "Louth (condado)", + "russian": "Лаут", + "chinese_traditional": "County Louth", + "unknown1": "County Louth", + "unknown2": "County Louth", + "unknown3": "County Louth", + "unknown4": "County Louth" + }, + "coordinates": { + "latitude": 54.008788448, + "longitude": -6.399064062999997 + } + }, + { + "id": 1377304576, + "name": "County Mayo", + "translations": { + "japanese": "メイヨー州", + "english": "County Mayo", + "french": "Mayo", + "german": "Mayo", + "italian": "Mayo", + "spanish": "Mayo", + "chinese_simple": "梅奥郡", + "korean": "메이오 주", + "dutch": "Mayo", + "portuguese": "Mayo (condado)", + "russian": "Мейо", + "chinese_traditional": "County Mayo", + "unknown1": "County Mayo", + "unknown2": "County Mayo", + "unknown3": "County Mayo", + "unknown4": "County Mayo" + }, + "coordinates": { + "latitude": 53.86047302, + "longitude": -9.293969395999994 + } + }, + { + "id": 1377370112, + "name": "County Meath", + "translations": { + "japanese": "ミース州", + "english": "County Meath", + "french": "Meath", + "german": "Meath", + "italian": "Meath", + "spanish": "Meath", + "chinese_simple": "米斯郡", + "korean": "미스 주", + "dutch": "Meath", + "portuguese": "Meath (condado)", + "russian": "Мит", + "chinese_traditional": "County Meath", + "unknown1": "County Meath", + "unknown2": "County Meath", + "unknown3": "County Meath", + "unknown4": "County Meath" + }, + "coordinates": { + "latitude": 53.651732788, + "longitude": -6.679216192000013 + } + }, + { + "id": 1377435648, + "name": "County Monaghan", + "translations": { + "japanese": "モナハン州", + "english": "County Monaghan", + "french": "Monaghan", + "german": "Monaghan", + "italian": "Monaghan", + "spanish": "Monaghan", + "chinese_simple": "莫纳亨郡", + "korean": "모너핸 주", + "dutch": "Monaghan", + "portuguese": "Monaghan (condado)", + "russian": "Монахан", + "chinese_traditional": "County Monaghan", + "unknown1": "County Monaghan", + "unknown2": "County Monaghan", + "unknown3": "County Monaghan", + "unknown4": "County Monaghan" + }, + "coordinates": { + "latitude": 54.2449945, + "longitude": -6.964861500000012 + } + }, + { + "id": 1377501184, + "name": "County Offaly", + "translations": { + "japanese": "オファリー州", + "english": "County Offaly", + "french": "Offaly", + "german": "Offaly", + "italian": "Offaly", + "spanish": "Offaly", + "chinese_simple": "奥法利郡", + "korean": "오펄리 주", + "dutch": "Offaly", + "portuguese": "Offaly (condado)", + "russian": "Оффали", + "chinese_traditional": "County Offaly", + "unknown1": "County Offaly", + "unknown2": "County Offaly", + "unknown3": "County Offaly", + "unknown4": "County Offaly" + }, + "coordinates": { + "latitude": 53.261718144, + "longitude": -7.497699863000008 + } + }, + { + "id": 1377566720, + "name": "County Roscommon", + "translations": { + "japanese": "ロスコモン州", + "english": "County Roscommon", + "french": "Roscommon", + "german": "Roscommon", + "italian": "Roscommon", + "spanish": "Roscommon", + "chinese_simple": "罗斯康芒郡", + "korean": "로스코먼 주", + "dutch": "Roscommon", + "portuguese": "Roscommon (condado)", + "russian": "Роскоммон", + "chinese_traditional": "County Roscommon", + "unknown1": "County Roscommon", + "unknown2": "County Roscommon", + "unknown3": "County Roscommon", + "unknown4": "County Roscommon" + }, + "coordinates": { + "latitude": 53.629760132, + "longitude": -8.178854059000003 + } + }, + { + "id": 1377632256, + "name": "County Sligo", + "translations": { + "japanese": "スライゴ州", + "english": "County Sligo", + "french": "Sligo", + "german": "Sligo", + "italian": "Sligo", + "spanish": "Sligo", + "chinese_simple": "斯莱戈郡", + "korean": "슬라이고 주", + "dutch": "Sligo", + "portuguese": "Sligo (condado)", + "russian": "Слайго", + "chinese_traditional": "County Sligo", + "unknown1": "County Sligo", + "unknown2": "County Sligo", + "unknown3": "County Sligo", + "unknown4": "County Sligo" + }, + "coordinates": { + "latitude": 54.261473992, + "longitude": -8.480978904000011 + } + }, + { + "id": 1377697792, + "name": "County Tipperary", + "translations": { + "japanese": "ティペラリー州", + "english": "County Tipperary", + "french": "Tipperary", + "german": "Tipperary", + "italian": "Tipperary", + "spanish": "Tipperary", + "chinese_simple": "蒂珀雷里郡", + "korean": "티퍼레리 주", + "dutch": "Tipperary", + "portuguese": "Tipperary (condado)", + "russian": "Типперэри", + "chinese_traditional": "County Tipperary", + "unknown1": "County Tipperary", + "unknown2": "County Tipperary", + "unknown3": "County Tipperary", + "unknown4": "County Tipperary" + }, + "coordinates": { + "latitude": 52.662963268, + "longitude": -7.832783782000007 + } + }, + { + "id": 1377763328, + "name": "County Waterford", + "translations": { + "japanese": "ウォーターフォード州", + "english": "County Waterford", + "french": "Waterford", + "german": "Waterford", + "italian": "Waterford", + "spanish": "Waterford", + "chinese_simple": "沃特福德郡", + "korean": "워터퍼드 주", + "dutch": "Waterford", + "portuguese": "Waterford (condado)", + "russian": "Уотерфорд", + "chinese_traditional": "County Waterford", + "unknown1": "County Waterford", + "unknown2": "County Waterford", + "unknown3": "County Waterford", + "unknown4": "County Waterford" + }, + "coordinates": { + "latitude": 52.080687884, + "longitude": -7.63502933800001 + } + }, + { + "id": 1377828864, + "name": "County Westmeath", + "translations": { + "japanese": "ウェストミース州", + "english": "County Westmeath", + "french": "Westmeath", + "german": "Westmeath", + "italian": "Westmeath", + "spanish": "Westmeath", + "chinese_simple": "西米斯郡", + "korean": "웨스트미스 주", + "dutch": "Westmeath", + "portuguese": "Westmeath (condado)", + "russian": "Уэстмит", + "chinese_traditional": "County Westmeath", + "unknown1": "County Westmeath", + "unknown2": "County Westmeath", + "unknown3": "County Westmeath", + "unknown4": "County Westmeath" + }, + "coordinates": { + "latitude": 53.519896852, + "longitude": -7.332904493000001 + } + }, + { + "id": 1377894400, + "name": "County Wexford", + "translations": { + "japanese": "ウェックスフォード州", + "english": "County Wexford", + "french": "Wexford", + "german": "Wexford", + "italian": "Wexford", + "spanish": "Wexford", + "chinese_simple": "韦克斯福德郡", + "korean": "웩스퍼드 주", + "dutch": "Wexford", + "portuguese": "Wexford (condado)", + "russian": "Уэксфорд", + "chinese_traditional": "County Wexford", + "unknown1": "County Wexford", + "unknown2": "County Wexford", + "unknown3": "County Wexford", + "unknown4": "County Wexford" + }, + "coordinates": { + "latitude": 52.333373428, + "longitude": -6.453995853000009 + } + }, + { + "id": 1377959936, + "name": "County Wicklow", + "translations": { + "japanese": "ウィックロー州", + "english": "County Wicklow", + "french": "Wicklow", + "german": "Wicklow", + "italian": "Wicklow", + "spanish": "Wicklow", + "chinese_simple": "威克洛郡", + "korean": "위클로 주", + "dutch": "Wicklow", + "portuguese": "Wicklow (condado)", + "russian": "Уиклоу", + "chinese_traditional": "County Wicklow", + "unknown1": "County Wicklow", + "unknown2": "County Wicklow", + "unknown3": "County Wicklow", + "unknown4": "County Wicklow" + }, + "coordinates": { + "latitude": 52.976073616, + "longitude": -6.036514248999993 + } + } + ] + }, + { + "id": 83, + "iso_code": "IT", + "name": "Italy", + "translations": { + "japanese": "イタリア", + "english": "Italy", + "french": "Italie", + "german": "Italien", + "italian": "Italia", + "spanish": "Italia", + "chinese_simple": "意大利", + "korean": "이탈리아", + "dutch": "Italië", + "portuguese": "Itália", + "russian": "Италия", + "chinese_traditional": "Italy", + "unknown1": "Italy", + "unknown2": "Italy", + "unknown3": "Italy", + "unknown4": "Italy" + }, + "regions": [ + { + "id": 1392508928, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 41.890868664, + "longitude": 12.485995867 + } + }, + { + "id": 1392640000, + "name": "Lazio", + "translations": { + "japanese": "ラツィオ州", + "english": "Lazio", + "french": "Latium", + "german": "Latium", + "italian": "Lazio", + "spanish": "Lacio", + "chinese_simple": "拉齐奥大区", + "korean": "라치오 주", + "dutch": "Lazio", + "portuguese": "Lácio", + "russian": "Лацио", + "chinese_traditional": "Lazio", + "unknown1": "Lazio", + "unknown2": "Lazio", + "unknown3": "Lazio", + "unknown4": "Lazio" + }, + "coordinates": { + "latitude": 41.890868664, + "longitude": 12.485995867 + } + }, + { + "id": 1392705536, + "name": "Aosta Valley", + "translations": { + "japanese": "バッレ・ダオスタ州", + "english": "Aosta Valley", + "french": "Vallée d'Aoste", + "german": "Aostatal", + "italian": "Valle d'Aosta", + "spanish": "Valle de Aosta", + "chinese_simple": "瓦莱-达奥斯塔大区", + "korean": "발레다오스타 주", + "dutch": "Valle d'Aosta", + "portuguese": "Vale de Aosta", + "russian": "Валле-д’Аоста", + "chinese_traditional": "Aosta Valley", + "unknown1": "Aosta Valley", + "unknown2": "Aosta Valley", + "unknown3": "Aosta Valley", + "unknown4": "Aosta Valley" + }, + "coordinates": { + "latitude": 45.7305903, + "longitude": 7.311421249 + } + }, + { + "id": 1392771072, + "name": "Piedmont", + "translations": { + "japanese": "ピエモンテ州", + "english": "Piedmont", + "french": "Piémont", + "german": "Piemont", + "italian": "Piemonte", + "spanish": "Piamonte", + "chinese_simple": "皮埃蒙特大区", + "korean": "피에몬테 주", + "dutch": "Piëmont", + "portuguese": "Piemonte", + "russian": "Пьемонт", + "chinese_traditional": "Piedmont", + "unknown1": "Piedmont", + "unknown2": "Piedmont", + "unknown3": "Piedmont", + "unknown4": "Piedmont" + }, + "coordinates": { + "latitude": 45.07141062, + "longitude": 7.673971063 + } + }, + { + "id": 1392836608, + "name": "Liguria", + "translations": { + "japanese": "リグリア州", + "english": "Liguria", + "french": "Ligurie", + "german": "Ligurien", + "italian": "Liguria", + "spanish": "Liguria", + "chinese_simple": "利古里亚大区", + "korean": "리구리아 주", + "dutch": "Ligurië", + "portuguese": "Ligúria", + "russian": "Лигурия", + "chinese_traditional": "Liguria", + "unknown1": "Liguria", + "unknown2": "Liguria", + "unknown3": "Liguria", + "unknown4": "Liguria" + }, + "coordinates": { + "latitude": 44.401244612, + "longitude": 8.931909054 + } + }, + { + "id": 1392902144, + "name": "Lombardy", + "translations": { + "japanese": "ロンバルディア州", + "english": "Lombardy", + "french": "Lombardie", + "german": "Lombardei", + "italian": "Lombardia", + "spanish": "Lombardía", + "chinese_simple": "伦巴第大区", + "korean": "롬바르디아 주", + "dutch": "Lombardije", + "portuguese": "Lombardia", + "russian": "Ломбардия", + "chinese_traditional": "Lombardy", + "unknown1": "Lombardy", + "unknown2": "Lombardy", + "unknown3": "Lombardy", + "unknown4": "Lombardy" + }, + "coordinates": { + "latitude": 45.466918428, + "longitude": 9.184595288 + } + }, + { + "id": 1392967680, + "name": "Trentino-Alto Adige", + "translations": { + "japanese": "トレンティノ・アルト・アディジェ州", + "english": "Trentino-Alto Adige", + "french": "Trentin-Haut-Adige", + "german": "Trentino-Südtirol", + "italian": "Trentino-Alto Adige", + "spanish": "Trentino-Alto Adigio", + "chinese_simple": "特伦蒂诺-上阿迪杰大区", + "korean": "트렌티노알토아디제 주", + "dutch": "Trentino-Zuid-Tirol", + "portuguese": "Trentino-Alto Ádige", + "russian": "Трентино-Альто-Адидже", + "chinese_traditional": "Trentino-Alto Adige", + "unknown1": "Trentino-Alto Adige", + "unknown2": "Trentino-Alto Adige", + "unknown3": "Trentino-Alto Adige", + "unknown4": "Trentino-Alto Adige" + }, + "coordinates": { + "latitude": 46.065673304, + "longitude": 11.118194296 + } + }, + { + "id": 1393033216, + "name": "Veneto", + "translations": { + "japanese": "ベネト州", + "english": "Veneto", + "french": "Vénétie", + "german": "Venetien", + "italian": "Veneto", + "spanish": "Véneto", + "chinese_simple": "威尼托大区", + "korean": "베네토 주", + "dutch": "Veneto", + "portuguese": "Veneto", + "russian": "Венето", + "chinese_traditional": "Veneto", + "unknown1": "Veneto", + "unknown2": "Veneto", + "unknown3": "Veneto", + "unknown4": "Veneto" + }, + "coordinates": { + "latitude": 45.42846628, + "longitude": 12.332186855 + } + }, + { + "id": 1393098752, + "name": "Friuli Venezia Giulia", + "translations": { + "japanese": "フリウリ・ベネチア・ジュリア州", + "english": "Friuli Venezia Giulia", + "french": "Frioul-Vénétie julienne", + "german": "Friaul-Julisch Venetien", + "italian": "Friuli-Venezia Giulia", + "spanish": "Friuli-Venecia Julia", + "chinese_simple": "弗留利-威尼斯朱利亚大区", + "korean": "프리울리베네치아줄리아 주", + "dutch": "Friuli-Venezia Giulia", + "portuguese": "Friul-Venécia Juliana", + "russian": "Фриули-Венеция-Джулия", + "chinese_traditional": "Friuli Venezia Giulia", + "unknown1": "Friuli Venezia Giulia", + "unknown2": "Friuli Venezia Giulia", + "unknown3": "Friuli Venezia Giulia", + "unknown4": "Friuli Venezia Giulia" + }, + "coordinates": { + "latitude": 45.637206512, + "longitude": 13.765906574 + } + }, + { + "id": 1393164288, + "name": "Emilia-Romagna", + "translations": { + "japanese": "エミリア・ロマーニャ州", + "english": "Emilia-Romagna", + "french": "Émilie-Romagne", + "german": "Emilia-Romagna", + "italian": "Emilia-Romagna", + "spanish": "Emilia-Romaña", + "chinese_simple": "艾米利亚-罗马涅大区", + "korean": "에밀리아로마냐 주", + "dutch": "Emilia-Romagna", + "portuguese": "Emília-Romana", + "russian": "Эмилия-Романья", + "chinese_traditional": "Emilia-Romagna", + "unknown1": "Emilia-Romagna", + "unknown2": "Emilia-Romagna", + "unknown3": "Emilia-Romagna", + "unknown4": "Emilia-Romagna" + }, + "coordinates": { + "latitude": 44.500121564, + "longitude": 11.332428277 + } + }, + { + "id": 1393229824, + "name": "Tuscany", + "translations": { + "japanese": "トスカナ州", + "english": "Tuscany", + "french": "Toscane", + "german": "Toskana", + "italian": "Toscana", + "spanish": "Toscana", + "chinese_simple": "托斯卡纳大区", + "korean": "토스카나 주", + "dutch": "Toscane", + "portuguese": "Toscânia", + "russian": "Тоскана", + "chinese_traditional": "Tuscany", + "unknown1": "Tuscany", + "unknown2": "Tuscany", + "unknown3": "Tuscany", + "unknown4": "Tuscany" + }, + "coordinates": { + "latitude": 43.775023916, + "longitude": 11.250030592 + } + }, + { + "id": 1393295360, + "name": "Umbria", + "translations": { + "japanese": "ウンブリア州", + "english": "Umbria", + "french": "Ombrie", + "german": "Umbrien", + "italian": "Umbria", + "spanish": "Umbría", + "chinese_simple": "翁布里亚大区", + "korean": "움브리아 주", + "dutch": "Umbrië", + "portuguese": "Úmbria", + "russian": "Умбрия", + "chinese_traditional": "Umbria", + "unknown1": "Umbria", + "unknown2": "Umbria", + "unknown3": "Umbria", + "unknown4": "Umbria" + }, + "coordinates": { + "latitude": 43.110351072, + "longitude": 12.381625466 + } + }, + { + "id": 1393360896, + "name": "Marche", + "translations": { + "japanese": "マルケ州", + "english": "Marche", + "french": "Marches", + "german": "Marken", + "italian": "Marche", + "spanish": "Las Marcas", + "chinese_simple": "马尔凯大区", + "korean": "마르케 주", + "dutch": "Marche", + "portuguese": "Marche", + "russian": "Марке", + "chinese_traditional": "Marche", + "unknown1": "Marche", + "unknown2": "Marche", + "unknown3": "Marche", + "unknown4": "Marche" + }, + "coordinates": { + "latitude": 43.61572216, + "longitude": 13.507727161 + } + }, + { + "id": 1393426432, + "name": "Abruzzo", + "translations": { + "japanese": "アブルッツィ州", + "english": "Abruzzo", + "french": "Abruzzes", + "german": "Abruzzen", + "italian": "Abruzzo", + "spanish": "Abruzos", + "chinese_simple": "阿布鲁佐大区", + "korean": "아브루초 주", + "dutch": "Abruzzen", + "portuguese": "Abruzo", + "russian": "Абруццо", + "chinese_traditional": "Abruzzo", + "unknown1": "Abruzzo", + "unknown2": "Abruzzo", + "unknown3": "Abruzzo", + "unknown4": "Abruzzo" + }, + "coordinates": { + "latitude": 42.346801276, + "longitude": 13.386877222999999 + } + }, + { + "id": 1393491968, + "name": "Molise", + "translations": { + "japanese": "モリーゼ州", + "english": "Molise", + "french": "Molise", + "german": "Molise", + "italian": "Molise", + "spanish": "Molise", + "chinese_simple": "莫利塞大区", + "korean": "몰리세 주", + "dutch": "Molise", + "portuguese": "Molise", + "russian": "Молизе", + "chinese_traditional": "Molise", + "unknown1": "Molise", + "unknown2": "Molise", + "unknown3": "Molise", + "unknown4": "Molise" + }, + "coordinates": { + "latitude": 41.55578566, + "longitude": 14.655801572 + } + }, + { + "id": 1393557504, + "name": "Campania", + "translations": { + "japanese": "カンパニア州", + "english": "Campania", + "french": "Campanie", + "german": "Kampanien", + "italian": "Campania", + "spanish": "Campania", + "chinese_simple": "坎帕尼亚大区", + "korean": "캄파니아 주", + "dutch": "Campanië", + "portuguese": "Campânia", + "russian": "Кампания", + "chinese_traditional": "Campania", + "unknown1": "Campania", + "unknown2": "Campania", + "unknown3": "Campania", + "unknown4": "Campania" + }, + "coordinates": { + "latitude": 40.836181176000004, + "longitude": 14.249306326 + } + }, + { + "id": 1393623040, + "name": "Apulia", + "translations": { + "japanese": "プーリア州", + "english": "Apulia", + "french": "Pouilles", + "german": "Apulien", + "italian": "Puglia", + "spanish": "Apulia", + "chinese_simple": "普利亚大区", + "korean": "풀리아 주", + "dutch": "Apulië", + "portuguese": "Apúlia", + "russian": "Апулия", + "chinese_traditional": "Apulia", + "unknown1": "Apulia", + "unknown2": "Apulia", + "unknown3": "Apulia", + "unknown4": "Apulia" + }, + "coordinates": { + "latitude": 41.11633254, + "longitude": 16.858566351 + } + }, + { + "id": 1393688576, + "name": "Basilicata", + "translations": { + "japanese": "バジリカータ州", + "english": "Basilicata", + "french": "Basilicate", + "german": "Basilikata", + "italian": "Basilicata", + "spanish": "Basilicata", + "chinese_simple": "巴西利卡塔大区", + "korean": "바실리카타 주", + "dutch": "Basilicata", + "portuguese": "Basilicata", + "russian": "Базиликата", + "chinese_traditional": "Basilicata", + "unknown1": "Basilicata", + "unknown2": "Basilicata", + "unknown3": "Basilicata", + "unknown4": "Basilicata" + }, + "coordinates": { + "latitude": 40.632934108, + "longitude": 15.787396446 + } + }, + { + "id": 1393754112, + "name": "Calabria", + "translations": { + "japanese": "カラブリア州", + "english": "Calabria", + "french": "Calabre", + "german": "Kalabrien", + "italian": "Calabria", + "spanish": "Calabria", + "chinese_simple": "卡拉布里亚大区", + "korean": "칼라브리아 주", + "dutch": "Calabrië", + "portuguese": "Calábria", + "russian": "Калабрия", + "chinese_traditional": "Calabria", + "unknown1": "Calabria", + "unknown2": "Calabria", + "unknown3": "Calabria", + "unknown4": "Calabria" + }, + "coordinates": { + "latitude": 38.897094284, + "longitude": 16.58940058 + } + }, + { + "id": 1393819648, + "name": "Sicily", + "translations": { + "japanese": "シチリア州", + "english": "Sicily", + "french": "Sicile", + "german": "Sizilien", + "italian": "Sicilia", + "spanish": "Sicilia", + "chinese_simple": "西西里大区", + "korean": "시칠리아 주", + "dutch": "Sicilië", + "portuguese": "Sicília", + "russian": "Сицилия", + "chinese_traditional": "Sicily", + "unknown1": "Sicily", + "unknown2": "Sicily", + "unknown3": "Sicily", + "unknown4": "Sicily" + }, + "coordinates": { + "latitude": 38.117064996, + "longitude": 13.353918149 + } + }, + { + "id": 1393885184, + "name": "Sardinia", + "translations": { + "japanese": "サルデーニャ州", + "english": "Sardinia", + "french": "Sardaigne", + "german": "Sardinien", + "italian": "Sardegna", + "spanish": "Cerdeña", + "chinese_simple": "撒丁大区", + "korean": "사르데냐 주", + "dutch": "Sardinië", + "portuguese": "Sardenha", + "russian": "Сардиния", + "chinese_traditional": "Sardinia", + "unknown1": "Sardinia", + "unknown2": "Sardinia", + "unknown3": "Sardinia", + "unknown4": "Sardinia" + }, + "coordinates": { + "latitude": 39.215697796, + "longitude": 9.102197603 + } + } + ] + }, + { + "id": 84, + "iso_code": "LV", + "name": "Latvia", + "translations": { + "japanese": "ラトビア", + "english": "Latvia", + "french": "Lettonie", + "german": "Lettland", + "italian": "Lettonia", + "spanish": "Letonia", + "chinese_simple": "拉脱维亚", + "korean": "라트비아", + "dutch": "Letland", + "portuguese": "Letónia", + "russian": "Латвия", + "chinese_traditional": "Latvia", + "unknown1": "Latvia", + "unknown2": "Latvia", + "unknown3": "Latvia", + "unknown4": "Latvia" + }, + "regions": [ + { + "id": 1409286144, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 56.947631188, + "longitude": 24.082096736 + } + }, + { + "id": 1409351680, + "name": "Latvia", + "translations": { + "japanese": "ラトビア", + "english": "Latvia", + "french": "Lettonie", + "german": "Lettland", + "italian": "Lettonia", + "spanish": "Letonia", + "chinese_simple": "拉脱维亚", + "korean": "라트비아", + "dutch": "Letland", + "portuguese": "Letónia", + "russian": "Латвия", + "chinese_traditional": "Latvia", + "unknown1": "Latvia", + "unknown2": "Latvia", + "unknown3": "Latvia", + "unknown4": "Latvia" + }, + "coordinates": { + "latitude": 56.947631188, + "longitude": 24.082096736 + } + } + ] + }, + { + "id": 85, + "iso_code": "LS", + "name": "Lesotho", + "translations": { + "japanese": "レソト", + "english": "Lesotho", + "french": "Lesotho", + "german": "Lesotho", + "italian": "Lesotho", + "spanish": "Lesoto", + "chinese_simple": "莱索托", + "korean": "레소토", + "dutch": "Lesotho", + "portuguese": "Lesoto", + "russian": "Лесото", + "chinese_traditional": "Lesotho", + "unknown1": "Lesotho", + "unknown2": "Lesotho", + "unknown3": "Lesotho", + "unknown4": "Lesotho" + }, + "regions": [ + { + "id": 1426063360, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": -29.317017292000003, + "longitude": 27.465895 + } + }, + { + "id": 1426194432, + "name": "Maseru", + "translations": { + "japanese": "マセル県", + "english": "Maseru", + "french": "Maseru", + "german": "Maseru", + "italian": "Maseru", + "spanish": "Maseru", + "chinese_simple": "马塞卢区", + "korean": "마세루 주", + "dutch": "Maseru", + "portuguese": "Maseru", + "russian": "Масеру", + "chinese_traditional": "Maseru", + "unknown1": "Maseru", + "unknown2": "Maseru", + "unknown3": "Maseru", + "unknown4": "Maseru" + }, + "coordinates": { + "latitude": -29.317017292000003, + "longitude": 27.465895 + } + }, + { + "id": 1426259968, + "name": "Berea", + "translations": { + "japanese": "べレア県", + "english": "Berea", + "french": "Berea", + "german": "Berea", + "italian": "Berea", + "spanish": "Berea", + "chinese_simple": "伯里亚区", + "korean": "베레아 주", + "dutch": "Berea", + "portuguese": "Berea", + "russian": "Береа", + "chinese_traditional": "Berea", + "unknown1": "Berea", + "unknown2": "Berea", + "unknown3": "Berea", + "unknown4": "Berea" + }, + "coordinates": { + "latitude": -29.146729207999996, + "longitude": 27.74055395 + } + }, + { + "id": 1426325504, + "name": "Butha-Buthe", + "translations": { + "japanese": "ブータ・ブーテ県", + "english": "Butha-Buthe", + "french": "Butha-Buthe", + "german": "Butha-Buthe", + "italian": "Butha-Buthe", + "spanish": "Butha-Buthe", + "chinese_simple": "布塔布泰区", + "korean": "부타부테 주", + "dutch": "Butha-Buthe", + "portuguese": "Butha-Buthe", + "russian": "Бута-Буте", + "chinese_traditional": "Butha-Buthe", + "unknown1": "Butha-Buthe", + "unknown2": "Butha-Buthe", + "unknown3": "Butha-Buthe", + "unknown4": "Butha-Buthe" + }, + "coordinates": { + "latitude": -28.767700892, + "longitude": 28.256912776 + } + }, + { + "id": 1426391040, + "name": "Leribe", + "translations": { + "japanese": "レリベ県", + "english": "Leribe", + "french": "Leribe", + "german": "Leribe", + "italian": "Leribe", + "spanish": "Leribe", + "chinese_simple": "莱里贝区", + "korean": "레리베 주", + "dutch": "Leribe", + "portuguese": "Leribe", + "russian": "Лерибе", + "chinese_traditional": "Leribe", + "unknown1": "Leribe", + "unknown2": "Leribe", + "unknown3": "Leribe", + "unknown4": "Leribe" + }, + "coordinates": { + "latitude": -28.877564172, + "longitude": 28.053665153 + } + }, + { + "id": 1426456576, + "name": "Mafeteng", + "translations": { + "japanese": "マフェテング県", + "english": "Mafeteng", + "french": "Mafeteng", + "german": "Mafeteng", + "italian": "Mafeteng", + "spanish": "Mafeteng", + "chinese_simple": "马费滕区", + "korean": "마페텡 주", + "dutch": "Mafeteng", + "portuguese": "Mafeteng", + "russian": "Мафетенг", + "chinese_traditional": "Mafeteng", + "unknown1": "Mafeteng", + "unknown2": "Mafeteng", + "unknown3": "Mafeteng", + "unknown4": "Mafeteng" + }, + "coordinates": { + "latitude": -29.816895216, + "longitude": 27.235181481999998 + } + }, + { + "id": 1426522112, + "name": "Mohale's Hoek", + "translations": { + "japanese": "モハーレスフーク県", + "english": "Mohale's Hoek", + "french": "Mohale's Hoek", + "german": "Mohale's Hoek", + "italian": "Mohale's Hoek", + "spanish": "Mohale's Hoek", + "chinese_simple": "莫哈莱斯胡克区", + "korean": "모할레스후크 주", + "dutch": "Mohale's Hoek", + "portuguese": "Mohale's Hoek", + "russian": "Мохалес-Хук", + "chinese_traditional": "Mohale's Hoek", + "unknown1": "Mohale's Hoek", + "unknown2": "Mohale's Hoek", + "unknown3": "Mohale's Hoek", + "unknown4": "Mohale's Hoek" + }, + "coordinates": { + "latitude": -30.151978219999997, + "longitude": 27.465895 + } + }, + { + "id": 1426587648, + "name": "Mokhotlong", + "translations": { + "japanese": "モコトロング県", + "english": "Mokhotlong", + "french": "Mokhotlong", + "german": "Mokhotlong", + "italian": "Mokhotlong", + "spanish": "Mokhotlong", + "chinese_simple": "莫霍特隆区", + "korean": "모코틀롱 주", + "dutch": "Mokhotlong", + "portuguese": "Mokhotlong", + "russian": "Мокхотлонг", + "chinese_traditional": "Mokhotlong", + "unknown1": "Mokhotlong", + "unknown2": "Mokhotlong", + "unknown3": "Mokhotlong", + "unknown4": "Mokhotlong" + }, + "coordinates": { + "latitude": -29.284058308, + "longitude": 29.064410089 + } + }, + { + "id": 1426653184, + "name": "Qacha's Nek", + "translations": { + "japanese": "クァクハスネック県", + "english": "Qacha's Nek", + "french": "Qacha's Nek", + "german": "Qacha's Nek", + "italian": "Qacha's Nek", + "spanish": "Qacha's Nek", + "chinese_simple": "加查斯内克区", + "korean": "카차스넥 주", + "dutch": "Qacha's Nek", + "portuguese": "Qacha's Nek", + "russian": "Цгачас-Нек", + "chinese_traditional": "Qacha's Nek", + "unknown1": "Qacha's Nek", + "unknown2": "Qacha's Nek", + "unknown3": "Qacha's Nek", + "unknown4": "Qacha's Nek" + }, + "coordinates": { + "latitude": -30.1245124, + "longitude": 28.701860275 + } + }, + { + "id": 1426718720, + "name": "Quthing", + "translations": { + "japanese": "クティング県", + "english": "Quthing", + "french": "Quthing", + "german": "Quthing", + "italian": "Quthing", + "spanish": "Quthing", + "chinese_simple": "古廷区", + "korean": "쿠팅 주", + "dutch": "Quthing", + "portuguese": "Quthing", + "russian": "Цгутинг", + "chinese_traditional": "Quthing", + "unknown1": "Quthing", + "unknown2": "Quthing", + "unknown3": "Quthing", + "unknown4": "Quthing" + }, + "coordinates": { + "latitude": -30.404663764, + "longitude": 27.707594875999998 + } + }, + { + "id": 1426784256, + "name": "Thaba-Tseka", + "translations": { + "japanese": "ターバ・ツェーカ県", + "english": "Thaba-Tseka", + "french": "Thaba-Tseka", + "german": "Thaba-Tseka", + "italian": "Thaba-Tseka", + "spanish": "Thaba-Tseka", + "chinese_simple": "塔巴采卡区", + "korean": "타바체카 주", + "dutch": "Thaba-Tseka", + "portuguese": "Thaba-Tseka", + "russian": "Таба-Цека", + "chinese_traditional": "Thaba-Tseka", + "unknown1": "Thaba-Tseka", + "unknown2": "Thaba-Tseka", + "unknown3": "Thaba-Tseka", + "unknown4": "Thaba-Tseka" + }, + "coordinates": { + "latitude": -29.514771195999998, + "longitude": 28.602983053 + } + } + ] + }, + { + "id": 86, + "iso_code": "LI", + "name": "Liechtenstein", + "translations": { + "japanese": "リヒテンシュタイン", + "english": "Liechtenstein", + "french": "Liechtenstein", + "german": "Liechtenstein", + "italian": "Liechtenstein", + "spanish": "Liechtenstein", + "chinese_simple": "列支敦士登", + "korean": "리히텐슈타인", + "dutch": "Liechtenstein", + "portuguese": "Liechtenstein", + "russian": "Лихтенштейн", + "chinese_traditional": "Liechtenstein", + "unknown1": "Liechtenstein", + "unknown2": "Liechtenstein", + "unknown3": "Liechtenstein", + "unknown4": "Liechtenstein" + }, + "regions": [ + { + "id": 1442840576, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 47.136840284, + "longitude": 9.519679207 + } + }, + { + "id": 1442906112, + "name": "Liechtenstein", + "translations": { + "japanese": "リヒテンシュタイン", + "english": "Liechtenstein", + "french": "Liechtenstein", + "german": "Liechtenstein", + "italian": "Liechtenstein", + "spanish": "Liechtenstein", + "chinese_simple": "列支敦士登", + "korean": "리히텐슈타인", + "dutch": "Liechtenstein", + "portuguese": "Liechtenstein", + "russian": "Лихтенштейн", + "chinese_traditional": "Liechtenstein", + "unknown1": "Liechtenstein", + "unknown2": "Liechtenstein", + "unknown3": "Liechtenstein", + "unknown4": "Liechtenstein" + }, + "coordinates": { + "latitude": 47.136840284, + "longitude": 9.519679207 + } + } + ] + }, + { + "id": 87, + "iso_code": "LT", + "name": "Lithuania", + "translations": { + "japanese": "リトアニア", + "english": "Lithuania", + "french": "Lituanie", + "german": "Litauen", + "italian": "Lituania", + "spanish": "Lituania", + "chinese_simple": "立陶宛", + "korean": "리투아니아", + "dutch": "Litouwen", + "portuguese": "Lituânia", + "russian": "Литва", + "chinese_traditional": "Lithuania", + "unknown1": "Lithuania", + "unknown2": "Lithuania", + "unknown3": "Lithuania", + "unknown4": "Lithuania" + }, + "regions": [ + { + "id": 1459617792, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 54.678954456, + "longitude": 25.279609758 + } + }, + { + "id": 1459748864, + "name": "Vilnius", + "translations": { + "japanese": "ヴィリニュス州", + "english": "Vilnius", + "french": "Vilnius", + "german": "Vilnius", + "italian": "Vilnius", + "spanish": "Condado de Vilna", + "chinese_simple": "维尔纽斯县", + "korean": "빌뉴스 주", + "dutch": "Vilnius", + "portuguese": "Vilna", + "russian": "Вильнюс", + "chinese_traditional": "Vilnius", + "unknown1": "Vilnius", + "unknown2": "Vilnius", + "unknown3": "Vilnius", + "unknown4": "Vilnius" + }, + "coordinates": { + "latitude": 54.678954456, + "longitude": 25.279609758 + } + }, + { + "id": 1459814400, + "name": "Alytus", + "translations": { + "japanese": "アリートゥス州", + "english": "Alytus", + "french": "Alytus", + "german": "Alytus", + "italian": "Alytus", + "spanish": "Condado de Alytus", + "chinese_simple": "阿利图斯县", + "korean": "알리투스 주", + "dutch": "Alytus", + "portuguese": "Alytus", + "russian": "Алитус", + "chinese_traditional": "Alytus", + "unknown1": "Alytus", + "unknown2": "Alytus", + "unknown3": "Alytus", + "unknown4": "Alytus" + }, + "coordinates": { + "latitude": 54.3823236, + "longitude": 24.049137662 + } + }, + { + "id": 1459879936, + "name": "Kaunas", + "translations": { + "japanese": "カウナス州", + "english": "Kaunas", + "french": "Kaunas", + "german": "Kaunas", + "italian": "Kaunas", + "spanish": "Condado de Kaunas", + "chinese_simple": "考纳斯县", + "korean": "카우나스 주", + "dutch": "Kaunas", + "portuguese": "Kaunas", + "russian": "Каунас", + "chinese_traditional": "Kaunas", + "unknown1": "Kaunas", + "unknown2": "Kaunas", + "unknown3": "Kaunas", + "unknown4": "Kaunas" + }, + "coordinates": { + "latitude": 54.887694688, + "longitude": 23.917301366 + } + }, + { + "id": 1459945472, + "name": "Klaipėda", + "translations": { + "japanese": "クライペダ州", + "english": "Klaipėda", + "french": "Klaipėda", + "german": "Klaipėda", + "italian": "Klaipėda", + "spanish": "Condado de Klaipėda", + "chinese_simple": "克莱佩达县", + "korean": "클라이페다 주", + "dutch": "Klaipėda", + "portuguese": "Klaipėda", + "russian": "Клайпеда", + "chinese_traditional": "Klaipėda", + "unknown1": "Klaipėda", + "unknown2": "Klaipėda", + "unknown3": "Klaipėda", + "unknown4": "Klaipėda" + }, + "coordinates": { + "latitude": 55.711669288, + "longitude": 21.132259613 + } + }, + { + "id": 1460011008, + "name": "Marijampolė", + "translations": { + "japanese": "マリヤンポレ州", + "english": "Marijampolė", + "french": "Marijampolė", + "german": "Marijampolė", + "italian": "Marijampolė", + "spanish": "Condado de Marijampolė", + "chinese_simple": "马里扬泊列县", + "korean": "마리얌폴레 주", + "dutch": "Marijampolė", + "portuguese": "Marijampolė", + "russian": "Мариямполе", + "chinese_traditional": "Marijampolė", + "unknown1": "Marijampolė", + "unknown2": "Marijampolė", + "unknown3": "Marijampolė", + "unknown4": "Marijampolė" + }, + "coordinates": { + "latitude": 54.54711852, + "longitude": 23.351503929 + } + }, + { + "id": 1460076544, + "name": "Panevėžys", + "translations": { + "japanese": "パネベジス州", + "english": "Panevėžys", + "french": "Panevėžys", + "german": "Panevėžys", + "italian": "Panevėžys", + "spanish": "Condado de Panevėžys", + "chinese_simple": "帕涅韦日斯县", + "korean": "파네베지스 주", + "dutch": "Panevėžys", + "portuguese": "Panevėžys", + "russian": "Паневежис", + "chinese_traditional": "Panevėžys", + "unknown1": "Panevėžys", + "unknown2": "Panevėžys", + "unknown3": "Panevėžys", + "unknown4": "Panevėžys" + }, + "coordinates": { + "latitude": 55.72814878, + "longitude": 24.367742044 + } + }, + { + "id": 1460142080, + "name": "Šiauliai", + "translations": { + "japanese": "シャウレイ州", + "english": "Šiauliai", + "french": "Šiauliai", + "german": "Šiauliai", + "italian": "Šiauliai", + "spanish": "Condado de Šiauliai", + "chinese_simple": "希奥利艾县", + "korean": "샤울랴이 주", + "dutch": "Šiauliai", + "portuguese": "Šiauliai", + "russian": "Шяуляй", + "chinese_traditional": "Šiauliai", + "unknown1": "Šiauliai", + "unknown2": "Šiauliai", + "unknown3": "Šiauliai", + "unknown4": "Šiauliai" + }, + "coordinates": { + "latitude": 55.931395848, + "longitude": 23.307558497 + } + }, + { + "id": 1460207616, + "name": "Taurage", + "translations": { + "japanese": "タウラゲ州", + "english": "Taurage", + "french": "Tauragė", + "german": "Tauragė", + "italian": "Tauragė", + "spanish": "Condado de Tauragė", + "chinese_simple": "陶拉格县", + "korean": "타우라게 주", + "dutch": "Tauragė", + "portuguese": "Tauragė", + "russian": "Таураге", + "chinese_traditional": "Taurage", + "unknown1": "Taurage", + "unknown2": "Taurage", + "unknown3": "Taurage", + "unknown4": "Taurage" + }, + "coordinates": { + "latitude": 55.244750348000004, + "longitude": 22.285827203 + } + }, + { + "id": 1460273152, + "name": "Telšiai", + "translations": { + "japanese": "テルシェイ州", + "english": "Telšiai", + "french": "Telšiai", + "german": "Telšiai", + "italian": "Telšiai", + "spanish": "Condado de Telšiai", + "chinese_simple": "特尔希艾县", + "korean": "텔샤이 주", + "dutch": "Telšiai", + "portuguese": "Telšiai", + "russian": "Тельшяй", + "chinese_traditional": "Telšiai", + "unknown1": "Telšiai", + "unknown2": "Telšiai", + "unknown3": "Telšiai", + "unknown4": "Telšiai" + }, + "coordinates": { + "latitude": 55.980834324, + "longitude": 22.24737495 + } + }, + { + "id": 1460338688, + "name": "Utena", + "translations": { + "japanese": "ウテナ州", + "english": "Utena", + "french": "Utena", + "german": "Utena", + "italian": "Utena", + "spanish": "Condado de Utena", + "chinese_simple": "乌田纳县", + "korean": "우테나 주", + "dutch": "Utena", + "portuguese": "Utena", + "russian": "Утена", + "chinese_traditional": "Utena", + "unknown1": "Utena", + "unknown2": "Utena", + "unknown3": "Utena", + "unknown4": "Utena" + }, + "coordinates": { + "latitude": 55.491942728, + "longitude": 25.603707318999998 + } + } + ] + }, + { + "id": 88, + "iso_code": "LU", + "name": "Luxembourg", + "translations": { + "japanese": "ルクセンブルク", + "english": "Luxembourg", + "french": "Luxembourg", + "german": "Luxemburg", + "italian": "Lussemburgo", + "spanish": "Luxemburgo", + "chinese_simple": "卢森堡", + "korean": "룩셈부르크", + "dutch": "Luxemburg", + "portuguese": "Luxemburgo", + "russian": "Люксембург", + "chinese_traditional": "Luxembourg", + "unknown1": "Luxembourg", + "unknown2": "Luxembourg", + "unknown3": "Luxembourg", + "unknown4": "Luxembourg" + }, + "regions": [ + { + "id": 1476395008, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 49.608764084, + "longitude": 6.124894585 + } + }, + { + "id": 1476460544, + "name": "Luxembourg", + "translations": { + "japanese": "ルクセンブルク", + "english": "Luxembourg", + "french": "Luxembourg", + "german": "Luxemburg", + "italian": "Lussemburgo", + "spanish": "Luxemburgo", + "chinese_simple": "卢森堡", + "korean": "룩셈부르크", + "dutch": "Luxemburg", + "portuguese": "Luxemburgo", + "russian": "Люксембург", + "chinese_traditional": "Luxembourg", + "unknown1": "Luxembourg", + "unknown2": "Luxembourg", + "unknown3": "Luxembourg", + "unknown4": "Luxembourg" + }, + "coordinates": { + "latitude": 49.608764084, + "longitude": 6.124894585 + } + } + ] + }, + { + "id": 89, + "iso_code": "MK", + "name": "Macedonia (Republic of)", + "translations": { + "japanese": "マケドニア", + "english": "Macedonia (Republic of)", + "french": "Macédoine (République)", + "german": "Mazedonien (Republik)", + "italian": "Macedonia (Repubblica di)", + "spanish": "Macedonia (República)", + "chinese_simple": "马其顿", + "korean": "마케도니아 공화국", + "dutch": "Macedonië", + "portuguese": "Macedónia (República)", + "russian": "Македония (Республика)", + "chinese_traditional": "Macedonia (Republic of)", + "unknown1": "Macedonia (Republic of)", + "unknown2": "Macedonia (Republic of)", + "unknown3": "Macedonia (Republic of)", + "unknown4": "Macedonia (Republic of)" + }, + "regions": [ + { + "id": 1493172224, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 41.99523878, + "longitude": 21.428891279 + } + }, + { + "id": 1493237760, + "name": "Macedonia (Republic of)", + "translations": { + "japanese": "マケドニア", + "english": "Macedonia (Republic of)", + "french": "Macédoine (République)", + "german": "Mazedonien (Republik)", + "italian": "Macedonia (Repubblica di)", + "spanish": "Macedonia (República)", + "chinese_simple": "马其顿", + "korean": "마케도니아 공화국", + "dutch": "Macedonië", + "portuguese": "Macedónia (República)", + "russian": "Македония (Республика)", + "chinese_traditional": "Macedonia (Republic of)", + "unknown1": "Macedonia (Republic of)", + "unknown2": "Macedonia (Republic of)", + "unknown3": "Macedonia (Republic of)", + "unknown4": "Macedonia (Republic of)" + }, + "coordinates": { + "latitude": 41.99523878, + "longitude": 21.428891279 + } + } + ] + }, + { + "id": 90, + "iso_code": "MT", + "name": "Malta", + "translations": { + "japanese": "マルタ", + "english": "Malta", + "french": "Malte", + "german": "Malta", + "italian": "Malta", + "spanish": "Malta", + "chinese_simple": "马耳他", + "korean": "몰타", + "dutch": "Malta", + "portuguese": "Malta", + "russian": "Мальта", + "chinese_traditional": "Malta", + "unknown1": "Malta", + "unknown2": "Malta", + "unknown3": "Malta", + "unknown4": "Malta" + }, + "regions": [ + { + "id": 1509949440, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 35.89782674, + "longitude": 14.512978918 + } + }, + { + "id": 1510014976, + "name": "Malta", + "translations": { + "japanese": "マルタ", + "english": "Malta", + "french": "Malte", + "german": "Malta", + "italian": "Malta", + "spanish": "Malta", + "chinese_simple": "马耳他", + "korean": "몰타", + "dutch": "Malta", + "portuguese": "Malta", + "russian": "Мальта", + "chinese_traditional": "Malta", + "unknown1": "Malta", + "unknown2": "Malta", + "unknown3": "Malta", + "unknown4": "Malta" + }, + "coordinates": { + "latitude": 35.89782674, + "longitude": 14.512978918 + } + } + ] + }, + { + "id": 91, + "iso_code": "ME", + "name": "Montenegro", + "translations": { + "japanese": "モンテネグロ", + "english": "Montenegro", + "french": "Monténégro", + "german": "Montenegro", + "italian": "Montenegro", + "spanish": "Montenegro", + "chinese_simple": "黑山", + "korean": "몬테네그로", + "dutch": "Montenegro", + "portuguese": "Montenegro", + "russian": "Черногория", + "chinese_traditional": "Montenegro", + "unknown1": "Montenegro", + "unknown2": "Montenegro", + "unknown3": "Montenegro", + "unknown4": "Montenegro" + }, + "regions": [ + { + "id": 1526726656, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 42.4346919, + "longitude": 19.264578753 + } + }, + { + "id": 1526792192, + "name": "Montenegro", + "translations": { + "japanese": "モンテネグロ", + "english": "Montenegro", + "french": "Monténégro", + "german": "Montenegro", + "italian": "Montenegro", + "spanish": "Montenegro", + "chinese_simple": "黑山", + "korean": "몬테네그로", + "dutch": "Montenegro", + "portuguese": "Montenegro", + "russian": "Черногория", + "chinese_traditional": "Montenegro", + "unknown1": "Montenegro", + "unknown2": "Montenegro", + "unknown3": "Montenegro", + "unknown4": "Montenegro" + }, + "coordinates": { + "latitude": 42.4346919, + "longitude": 19.264578753 + } + } + ] + }, + { + "id": 92, + "iso_code": "MZ", + "name": "Mozambique", + "translations": { + "japanese": "モザンビーク", + "english": "Mozambique", + "french": "Mozambique", + "german": "Mosambik", + "italian": "Mozambico", + "spanish": "Mozambique", + "chinese_simple": "莫桑比克", + "korean": "모잠비크", + "dutch": "Mozambique", + "portuguese": "Moçambique", + "russian": "Мозамбик", + "chinese_traditional": "Mozambique", + "unknown1": "Mozambique", + "unknown2": "Mozambique", + "unknown3": "Mozambique", + "unknown4": "Mozambique" + }, + "regions": [ + { + "id": 1543503872, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": -25.966187251999997, + "longitude": 32.563565112 + } + }, + { + "id": 1543569408, + "name": "Mozambique", + "translations": { + "japanese": "モザンビーク", + "english": "Mozambique", + "french": "Mozambique", + "german": "Mosambik", + "italian": "Mozambico", + "spanish": "Mozambique", + "chinese_simple": "莫桑比克", + "korean": "모잠비크", + "dutch": "Mozambique", + "portuguese": "Moçambique", + "russian": "Мозамбик", + "chinese_traditional": "Mozambique", + "unknown1": "Mozambique", + "unknown2": "Mozambique", + "unknown3": "Mozambique", + "unknown4": "Mozambique" + }, + "coordinates": { + "latitude": -25.966187251999997, + "longitude": 32.563565112 + } + } + ] + }, + { + "id": 93, + "iso_code": "NA", + "name": "Namibia", + "translations": { + "japanese": "ナミビア", + "english": "Namibia", + "french": "Namibie", + "german": "Namibia", + "italian": "Namibia", + "spanish": "Namibia", + "chinese_simple": "纳米比亚", + "korean": "나미비아", + "dutch": "Namibië", + "portuguese": "Namíbia", + "russian": "Намибия", + "chinese_traditional": "Namibia", + "unknown1": "Namibia", + "unknown2": "Namibia", + "unknown3": "Namibia", + "unknown4": "Namibia" + }, + "regions": [ + { + "id": 1560281088, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": -22.549439244, + "longitude": 17.078293511 + } + }, + { + "id": 1560346624, + "name": "Namibia", + "translations": { + "japanese": "ナミビア", + "english": "Namibia", + "french": "Namibie", + "german": "Namibia", + "italian": "Namibia", + "spanish": "Namibia", + "chinese_simple": "纳米比亚", + "korean": "나미비아", + "dutch": "Namibië", + "portuguese": "Namíbia", + "russian": "Намибия", + "chinese_traditional": "Namibia", + "unknown1": "Namibia", + "unknown2": "Namibia", + "unknown3": "Namibia", + "unknown4": "Namibia" + }, + "coordinates": { + "latitude": -22.549439244, + "longitude": 17.078293511 + } + } + ] + }, + { + "id": 94, + "iso_code": "NL", + "name": "Netherlands", + "translations": { + "japanese": "オランダ", + "english": "Netherlands", + "french": "Pays-Bas", + "german": "Niederlande", + "italian": "Paesi Bassi", + "spanish": "Países Bajos", + "chinese_simple": "荷兰", + "korean": "네덜란드", + "dutch": "Nederland", + "portuguese": "Países Baixos", + "russian": "Нидерланды", + "chinese_traditional": "Netherlands", + "unknown1": "Netherlands", + "unknown2": "Netherlands", + "unknown3": "Netherlands", + "unknown4": "Netherlands" + }, + "regions": [ + { + "id": 1577058304, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 52.366332412, + "longitude": 4.883436131 + } + }, + { + "id": 1577189376, + "name": "North Holland", + "translations": { + "japanese": "ノールト・ホラント州", + "english": "North Holland", + "french": "Hollande-Septentrionale", + "german": "Nordholland", + "italian": "Olanda Settentrionale", + "spanish": "Holanda Septentrional", + "chinese_simple": "北荷兰省", + "korean": "노르트홀란트 주", + "dutch": "Noord-Holland", + "portuguese": "Holanda Setentrional", + "russian": "Северная Голландия", + "chinese_traditional": "North Holland", + "unknown1": "North Holland", + "unknown2": "North Holland", + "unknown3": "North Holland", + "unknown4": "North Holland" + }, + "coordinates": { + "latitude": 52.366332412, + "longitude": 4.883436131 + } + }, + { + "id": 1577254912, + "name": "Drenthe", + "translations": { + "japanese": "ドレンテ州", + "english": "Drenthe", + "french": "Drenthe", + "german": "Drenthe", + "italian": "Drenthe", + "spanish": "Drente", + "chinese_simple": "德伦特省", + "korean": "드렌터 주", + "dutch": "Drenthe", + "portuguese": "Drente", + "russian": "Дренте", + "chinese_traditional": "Drenthe", + "unknown1": "Drenthe", + "unknown2": "Drenthe", + "unknown3": "Drenthe", + "unknown4": "Drenthe" + }, + "coordinates": { + "latitude": 52.987059944, + "longitude": 6.553362547 + } + }, + { + "id": 1577320448, + "name": "Flevoland", + "translations": { + "japanese": "フレボラント州", + "english": "Flevoland", + "french": "Flevoland", + "german": "Flevoland", + "italian": "Flevoland", + "spanish": "Flevoland", + "chinese_simple": "弗莱福兰省", + "korean": "플레볼란트 주", + "dutch": "Flevoland", + "portuguese": "Flevoland", + "russian": "Флеволанд", + "chinese_traditional": "Flevoland", + "unknown1": "Flevoland", + "unknown2": "Flevoland", + "unknown3": "Flevoland", + "unknown4": "Flevoland" + }, + "coordinates": { + "latitude": 52.503661512, + "longitude": 5.465713105 + } + }, + { + "id": 1577385984, + "name": "Friesland", + "translations": { + "japanese": "フリースラント州", + "english": "Friesland", + "french": "Frise", + "german": "Friesland", + "italian": "Frisia", + "spanish": "Frisia", + "chinese_simple": "弗里斯兰省", + "korean": "프리슬란트 주", + "dutch": "Friesland", + "portuguese": "Frísia", + "russian": "Фрисландия", + "chinese_traditional": "Friesland", + "unknown1": "Friesland", + "unknown2": "Friesland", + "unknown3": "Friesland", + "unknown4": "Friesland" + }, + "coordinates": { + "latitude": 53.190307012, + "longitude": 5.784317487 + } + }, + { + "id": 1577451520, + "name": "Gelderland", + "translations": { + "japanese": "ヘルデンラント州", + "english": "Gelderland", + "french": "Gueldre", + "german": "Gelderland", + "italian": "Gheldria", + "spanish": "Güeldres", + "chinese_simple": "海尔德兰省", + "korean": "헬데를란트 주", + "dutch": "Gelderland", + "portuguese": "Gueldres", + "russian": "Гелдерланд", + "chinese_traditional": "Gelderland", + "unknown1": "Gelderland", + "unknown2": "Gelderland", + "unknown3": "Gelderland", + "unknown4": "Gelderland" + }, + "coordinates": { + "latitude": 51.981810932, + "longitude": 5.905167425 + } + }, + { + "id": 1577517056, + "name": "Groningen", + "translations": { + "japanese": "フローニンゲン州", + "english": "Groningen", + "french": "Groningue", + "german": "Groningen", + "italian": "Groninga", + "spanish": "Groninga", + "chinese_simple": "格罗宁根省", + "korean": "흐로닝언 주", + "dutch": "Groningen", + "portuguese": "Groninga", + "russian": "Гронинген", + "chinese_traditional": "Groningen", + "unknown1": "Groningen", + "unknown2": "Groningen", + "unknown3": "Groningen", + "unknown4": "Groningen" + }, + "coordinates": { + "latitude": 53.217772832, + "longitude": 6.569842084 + } + }, + { + "id": 1577582592, + "name": "Limburg", + "translations": { + "japanese": "リンビュルフ州", + "english": "Limburg", + "french": "Limbourg", + "german": "Limburg", + "italian": "Limburgo", + "spanish": "Limburgo", + "chinese_simple": "林堡省", + "korean": "림뷔르흐 주", + "dutch": "Limburg", + "portuguese": "Limburgo", + "russian": "Лимбург", + "chinese_traditional": "Limburg", + "unknown1": "Limburg", + "unknown2": "Limburg", + "unknown3": "Limburg", + "unknown4": "Limburg" + }, + "coordinates": { + "latitude": 50.850219148, + "longitude": 5.674453907 + } + }, + { + "id": 1577648128, + "name": "North Brabant", + "translations": { + "japanese": "ノールト・ブラバント州", + "english": "North Brabant", + "french": "Brabant-Septentrional", + "german": "Nordbrabant", + "italian": "Brabante Settentrionale", + "spanish": "Brabante Septentrional", + "chinese_simple": "北布拉班特省", + "korean": "노르트브라반트 주", + "dutch": "Noord-Brabant", + "portuguese": "Brabante Setentrional", + "russian": "Северный Брабант", + "chinese_traditional": "North Brabant", + "unknown1": "North Brabant", + "unknown2": "North Brabant", + "unknown3": "North Brabant", + "unknown4": "North Brabant" + }, + "coordinates": { + "latitude": 51.69067324, + "longitude": 5.311904093 + } + }, + { + "id": 1577713664, + "name": "Overijssel", + "translations": { + "japanese": "オーベルアイセル州", + "english": "Overijssel", + "french": "Overijssel", + "german": "Overijssel", + "italian": "Overijssel", + "spanish": "Overijssel", + "chinese_simple": "上艾瑟尔省", + "korean": "오버레이설 주", + "dutch": "Overijssel", + "portuguese": "Overijssel", + "russian": "Оверэйсел", + "chinese_traditional": "Overijssel", + "unknown1": "Overijssel", + "unknown2": "Overijssel", + "unknown3": "Overijssel", + "unknown4": "Overijssel" + }, + "coordinates": { + "latitude": 52.509154676, + "longitude": 6.086442332 + } + }, + { + "id": 1577779200, + "name": "South Holland", + "translations": { + "japanese": "ゾイト・ホラント州", + "english": "South Holland", + "french": "Hollande-Méridionale", + "german": "Südholland", + "italian": "Olanda Meridionale", + "spanish": "Holanda Meridional", + "chinese_simple": "南荷兰省", + "korean": "자위트홀란트 주", + "dutch": "Zuid-Holland", + "portuguese": "Holanda Meridional", + "russian": "Южная Голландия", + "chinese_traditional": "South Holland", + "unknown1": "South Holland", + "unknown2": "South Holland", + "unknown3": "South Holland", + "unknown4": "South Holland" + }, + "coordinates": { + "latitude": 52.080687884, + "longitude": 4.312145515 + } + }, + { + "id": 1577844736, + "name": "Utrecht", + "translations": { + "japanese": "ユトレヒト州", + "english": "Utrecht", + "french": "Utrecht", + "german": "Utrecht", + "italian": "Utrecht", + "spanish": "Utrecht", + "chinese_simple": "乌得勒支省", + "korean": "위트레흐트 주", + "dutch": "Utrecht", + "portuguese": "Utrecht", + "russian": "Утрехт", + "chinese_traditional": "Utrecht", + "unknown1": "Utrecht", + "unknown2": "Utrecht", + "unknown3": "Utrecht", + "unknown4": "Utrecht" + }, + "coordinates": { + "latitude": 52.086181048, + "longitude": 5.10865647 + } + }, + { + "id": 1577910272, + "name": "Zeeland", + "translations": { + "japanese": "ゼーラント州", + "english": "Zeeland", + "french": "Zélande", + "german": "Zeeland", + "italian": "Zelanda", + "spanish": "Zelanda", + "chinese_simple": "泽兰省", + "korean": "제일란트 주", + "dutch": "Zeeland", + "portuguese": "Zelândia", + "russian": "Зеландия", + "chinese_traditional": "Zeeland", + "unknown1": "Zeeland", + "unknown2": "Zeeland", + "unknown3": "Zeeland", + "unknown4": "Zeeland" + }, + "coordinates": { + "latitude": 51.4984125, + "longitude": 3.609018603 + } + } + ] + }, + { + "id": 95, + "iso_code": "NZ", + "name": "New Zealand", + "translations": { + "japanese": "ニュージーランド", + "english": "New Zealand", + "french": "Nouvelle-Zélande", + "german": "Neuseeland", + "italian": "Nuova Zelanda", + "spanish": "Nueva Zelanda", + "chinese_simple": "新西兰", + "korean": "뉴질랜드", + "dutch": "Nieuw-Zeeland", + "portuguese": "Nova Zelândia", + "russian": "Новая Зеландия", + "chinese_traditional": "New Zealand", + "unknown1": "New Zealand", + "unknown2": "New Zealand", + "unknown3": "New Zealand", + "unknown4": "New Zealand" + }, + "regions": [ + { + "id": 1593835520, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": -36.892090448, + "longitude": 174.759996706 + } + }, + { + "id": 1593966592, + "name": "Wellington", + "translations": { + "japanese": "ウェリントン", + "english": "Wellington", + "french": "Wellington", + "german": "Wellington", + "italian": "Wellington", + "spanish": "Región de Wellington", + "chinese_simple": "惠灵顿大区", + "korean": "웰링턴", + "dutch": "Wellington", + "portuguese": "Wellington", + "russian": "Веллингтон", + "chinese_traditional": "Wellington", + "unknown1": "Wellington", + "unknown2": "Wellington", + "unknown3": "Wellington", + "unknown4": "Wellington" + }, + "coordinates": { + "latitude": -41.314087468, + "longitude": 174.781969422 + } + }, + { + "id": 1594032128, + "name": "Auckland", + "translations": { + "japanese": "オークランド", + "english": "Auckland", + "french": "Auckland", + "german": "Auckland", + "italian": "Auckland", + "spanish": "Región de Auckland", + "chinese_simple": "奥克兰大区", + "korean": "오클랜드", + "dutch": "Auckland", + "portuguese": "Auckland", + "russian": "Окленд", + "chinese_traditional": "Auckland", + "unknown1": "Auckland", + "unknown2": "Auckland", + "unknown3": "Auckland", + "unknown4": "Auckland" + }, + "coordinates": { + "latitude": -36.892090448, + "longitude": 174.759996706 + } + }, + { + "id": 1594097664, + "name": "Bay of Plenty", + "translations": { + "japanese": "ベイ・オブ・プレンティ", + "english": "Bay of Plenty", + "french": "Bay of Plenty", + "german": "Bay of Plenty", + "italian": "Bay of Plenty", + "spanish": "Bahía de Plenty", + "chinese_simple": "普伦蒂湾大区", + "korean": "베이오브플렌티", + "dutch": "Bay of Plenty", + "portuguese": "Bay of Plenty", + "russian": "Бей-оф-Пленти", + "chinese_traditional": "Bay of Plenty", + "unknown1": "Bay of Plenty", + "unknown2": "Bay of Plenty", + "unknown3": "Bay of Plenty", + "unknown4": "Bay of Plenty" + }, + "coordinates": { + "latitude": -37.6776129, + "longitude": 176.16625052999999 + } + }, + { + "id": 1594163200, + "name": "Canterbury", + "translations": { + "japanese": "カンタベリー", + "english": "Canterbury", + "french": "Canterbury", + "german": "Canterbury", + "italian": "Canterbury", + "spanish": "Canterbury", + "chinese_simple": "坎特伯雷大区", + "korean": "캔터베리", + "dutch": "Canterbury", + "portuguese": "Canterbury", + "russian": "Кентербери", + "chinese_traditional": "Canterbury", + "unknown1": "Canterbury", + "unknown2": "Canterbury", + "unknown3": "Canterbury", + "unknown4": "Canterbury" + }, + "coordinates": { + "latitude": -43.52783256, + "longitude": 172.639629612 + } + }, + { + "id": 1594228736, + "name": "Otago", + "translations": { + "japanese": "ダニーデン", + "english": "Otago", + "french": "Otago", + "german": "Otago", + "italian": "Otago", + "spanish": "Otago", + "chinese_simple": "奥塔戈大区", + "korean": "오타고", + "dutch": "Otago", + "portuguese": "Otago", + "russian": "Отаго", + "chinese_traditional": "Otago", + "unknown1": "Otago", + "unknown2": "Otago", + "unknown3": "Otago", + "unknown4": "Otago" + }, + "coordinates": { + "latitude": -45.878906752, + "longitude": 170.469823907 + } + }, + { + "id": 1594294272, + "name": "Hawke's Bay", + "translations": { + "japanese": "ホークスベイ", + "english": "Hawke's Bay", + "french": "Hawke's Bay", + "german": "Hawke's Bay", + "italian": "Hawke's Bay", + "spanish": "Bahía de Hawke", + "chinese_simple": "霍克湾大区", + "korean": "호크스베이", + "dutch": "Hawke's Bay", + "portuguese": "Hawke's Bay", + "russian": "Хокс-Бей", + "chinese_traditional": "Hawke's Bay", + "unknown1": "Hawke's Bay", + "unknown2": "Hawke's Bay", + "unknown3": "Hawke's Bay", + "unknown4": "Hawke's Bay" + }, + "coordinates": { + "latitude": -39.495850184, + "longitude": 176.885856979 + } + }, + { + "id": 1594359808, + "name": "Manawatu-Wanganui", + "translations": { + "japanese": "マナワツ・ワンガヌイ", + "english": "Manawatu-Wanganui", + "french": "Manawatu-Wanganui", + "german": "Manawatu-Wanganui", + "italian": "Manawatu-Wanganui", + "spanish": "Manawatu-Wanganui", + "chinese_simple": "玛纳瓦图-旺格努伊大区", + "korean": "마너와투-왕거누이", + "dutch": "Manawatu-Wanganui", + "portuguese": "Manawatu-Wanganui", + "russian": "Манавату-Уангануи", + "chinese_traditional": "Manawatu-Wanganui", + "unknown1": "Manawatu-Wanganui", + "unknown2": "Manawatu-Wanganui", + "unknown3": "Manawatu-Wanganui", + "unknown4": "Manawatu-Wanganui" + }, + "coordinates": { + "latitude": -40.358276932, + "longitude": 175.61693263 + } + }, + { + "id": 1594425344, + "name": "Nelson", + "translations": { + "japanese": "ネルソン・マールボロ", + "english": "Nelson", + "french": "Nelson", + "german": "Nelson", + "italian": "Nelson", + "spanish": "Región de Nelson", + "chinese_simple": "纳尔逊区", + "korean": "넬슨-말버러", + "dutch": "Nelson", + "portuguese": "Nelson", + "russian": "Нельсон", + "chinese_traditional": "Nelson", + "unknown1": "Nelson", + "unknown2": "Nelson", + "unknown3": "Nelson", + "unknown4": "Nelson" + }, + "coordinates": { + "latitude": -41.292114812, + "longitude": 173.243879302 + } + }, + { + "id": 1594490880, + "name": "Northland", + "translations": { + "japanese": "ノースランド", + "english": "Northland", + "french": "Northland", + "german": "Northland", + "italian": "Northland", + "spanish": "Northland", + "chinese_simple": "北地大区", + "korean": "노스랜드", + "dutch": "Northland", + "portuguese": "Northland", + "russian": "Нортленд", + "chinese_traditional": "Northland", + "unknown1": "Northland", + "unknown2": "Northland", + "unknown3": "Northland", + "unknown4": "Northland" + }, + "coordinates": { + "latitude": -35.716553352, + "longitude": 174.315049207 + } + }, + { + "id": 1594621952, + "name": "Southland", + "translations": { + "japanese": "サウスランド", + "english": "Southland", + "french": "Southland", + "german": "Southland", + "italian": "Southland", + "spanish": "Southland", + "chinese_simple": "南地大区", + "korean": "사우스랜드", + "dutch": "Southland", + "portuguese": "Southland", + "russian": "Саутленд", + "chinese_traditional": "Southland", + "unknown1": "Southland", + "unknown2": "Southland", + "unknown3": "Southland", + "unknown4": "Southland" + }, + "coordinates": { + "latitude": -46.41174366, + "longitude": 168.371429529 + } + }, + { + "id": 1594687488, + "name": "Taranaki", + "translations": { + "japanese": "タラナキ", + "english": "Taranaki", + "french": "Taranaki", + "german": "Taranaki", + "italian": "Taranaki", + "spanish": "Taranaki", + "chinese_simple": "塔拉纳基大区", + "korean": "타라나키", + "dutch": "Taranaki", + "portuguese": "Taranaki", + "russian": "Таранаки", + "chinese_traditional": "Taranaki", + "unknown1": "Taranaki", + "unknown2": "Taranaki", + "unknown3": "Taranaki", + "unknown4": "Taranaki" + }, + "coordinates": { + "latitude": -39.067383391999996, + "longitude": 174.073349331 + } + }, + { + "id": 1594753024, + "name": "Waikato", + "translations": { + "japanese": "ワイカト", + "english": "Waikato", + "french": "Waikato", + "german": "Waikato", + "italian": "Waikato", + "spanish": "Waikato", + "chinese_simple": "怀卡托大区", + "korean": "와이카토", + "dutch": "Waikato", + "portuguese": "Waikato", + "russian": "Уаикато", + "chinese_traditional": "Waikato", + "unknown1": "Waikato", + "unknown2": "Waikato", + "unknown3": "Waikato", + "unknown4": "Waikato" + }, + "coordinates": { + "latitude": -37.776489852, + "longitude": 175.265369174 + } + }, + { + "id": 1594818560, + "name": "Gisborne", + "translations": { + "japanese": "ギズボーン", + "english": "Gisborne", + "french": "Gisborne", + "german": "Gisborne", + "italian": "Gisborne", + "spanish": "Gisborne", + "chinese_simple": "吉斯伯恩大区", + "korean": "기즈번", + "dutch": "Gisborne", + "portuguese": "Gisborne", + "russian": "Гисборн", + "chinese_traditional": "Gisborne", + "unknown1": "Gisborne", + "unknown2": "Gisborne", + "unknown3": "Gisborne", + "unknown4": "Gisborne" + }, + "coordinates": { + "latitude": -38.66638242, + "longitude": 178.017451853 + } + }, + { + "id": 1594884096, + "name": "West Coast", + "translations": { + "japanese": "ウェストコースト", + "english": "West Coast", + "french": "West Coast", + "german": "West Coast", + "italian": "West Coast", + "spanish": "Costa Oeste", + "chinese_simple": "西岸大区", + "korean": "웨스트코스트", + "dutch": "West Coast", + "portuguese": "Costa Oeste", + "russian": "Уэст-Кост", + "chinese_traditional": "West Coast", + "unknown1": "West Coast", + "unknown2": "West Coast", + "unknown3": "West Coast", + "unknown4": "West Coast" + }, + "coordinates": { + "latitude": -42.445679252, + "longitude": 171.211403072 + } + }, + { + "id": 1594949632, + "name": "Marlborough", + "translations": { + "japanese": "マールボロ", + "english": "Marlborough", + "french": "Marlborough", + "german": "Marlborough", + "italian": "Marlborough", + "spanish": "Marlborough", + "chinese_simple": "马尔伯勒大区", + "korean": "말버러", + "dutch": "Marlborough", + "portuguese": "Marlborough", + "russian": "Мальборо", + "chinese_traditional": "Marlborough", + "unknown1": "Marlborough", + "unknown2": "Marlborough", + "unknown3": "Marlborough", + "unknown4": "Marlborough" + }, + "coordinates": { + "latitude": -41.511841372, + "longitude": 173.957992572 + } + }, + { + "id": 1595015168, + "name": "Tasman", + "translations": { + "japanese": "タスマン", + "english": "Tasman", + "french": "Tasman", + "german": "Tasman", + "italian": "Tasman", + "spanish": "Tasman", + "chinese_simple": "塔斯曼大区", + "korean": "태즈먼", + "dutch": "Tasman", + "portuguese": "Tasman", + "russian": "Тасман", + "chinese_traditional": "Tasman", + "unknown1": "Tasman", + "unknown2": "Tasman", + "unknown3": "Tasman", + "unknown4": "Tasman" + }, + "coordinates": { + "latitude": -41.341553288, + "longitude": 173.183454333 + } + } + ] + }, + { + "id": 96, + "iso_code": "NO", + "name": "Norway", + "translations": { + "japanese": "ノルウェー", + "english": "Norway", + "french": "Norvège", + "german": "Norwegen", + "italian": "Norvegia", + "spanish": "Noruega", + "chinese_simple": "挪威", + "korean": "노르웨이", + "dutch": "Noorwegen", + "portuguese": "Noruega", + "russian": "Норвегия", + "chinese_traditional": "Norway", + "unknown1": "Norway", + "unknown2": "Norway", + "unknown3": "Norway", + "unknown4": "Norway" + }, + "regions": [ + { + "id": 1610612736, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 59.935912404, + "longitude": 10.706205871 + } + }, + { + "id": 1611071488, + "name": "Oslo", + "translations": { + "japanese": "オスロ", + "english": "Oslo", + "french": "Oslo", + "german": "Oslo", + "italian": "Oslo", + "spanish": "Oslo", + "chinese_simple": "奥斯陆", + "korean": "오슬로", + "dutch": "Oslo", + "portuguese": "Oslo", + "russian": "Осло", + "chinese_traditional": "Oslo", + "unknown1": "Oslo", + "unknown2": "Oslo", + "unknown3": "Oslo", + "unknown4": "Oslo" + }, + "coordinates": { + "latitude": 59.935912404, + "longitude": 10.706205871 + } + }, + { + "id": 1611137024, + "name": "Akershus", + "translations": { + "japanese": "アーケシュフース県", + "english": "Akershus", + "french": "Akershus", + "german": "Akershus", + "italian": "Akershus", + "spanish": "Akershus", + "chinese_simple": "阿克什胡斯郡", + "korean": "아케르스후스 주", + "dutch": "Akershus", + "portuguese": "Akershus", + "russian": "Акерсхус", + "chinese_traditional": "Akershus", + "unknown1": "Akershus", + "unknown2": "Akershus", + "unknown3": "Akershus", + "unknown4": "Akershus" + }, + "coordinates": { + "latitude": 59.935912404, + "longitude": 10.706205871 + } + }, + { + "id": 1611202560, + "name": "Aust-Agder", + "translations": { + "japanese": "アウスト・アグデル県", + "english": "Aust-Agder", + "french": "Aust-Agder", + "german": "Aust-Agder", + "italian": "Aust-Agder", + "spanish": "Aust-Agder", + "chinese_simple": "东阿格德尔郡", + "korean": "에우스트아그데르 주", + "dutch": "Aust-Agder", + "portuguese": "Aust-Agder", + "russian": "Эуст-Агдер", + "chinese_traditional": "Aust-Agder", + "unknown1": "Aust-Agder", + "unknown2": "Aust-Agder", + "unknown3": "Aust-Agder", + "unknown4": "Aust-Agder" + }, + "coordinates": { + "latitude": 58.480223944, + "longitude": 8.778100042 + } + }, + { + "id": 1611268096, + "name": "Buskerud", + "translations": { + "japanese": "ブスケルー県", + "english": "Buskerud", + "french": "Buskerud", + "german": "Buskerud", + "italian": "Buskerud", + "spanish": "Buskerud", + "chinese_simple": "布斯克吕郡", + "korean": "부스케루 주", + "dutch": "Buskerud", + "portuguese": "Buskerud", + "russian": "Бускеруд", + "chinese_traditional": "Buskerud", + "unknown1": "Buskerud", + "unknown2": "Buskerud", + "unknown3": "Buskerud", + "unknown4": "Buskerud" + }, + "coordinates": { + "latitude": 59.732665336000004, + "longitude": 10.200833403 + } + }, + { + "id": 1611333632, + "name": "Finnmark", + "translations": { + "japanese": "フィンマルク県", + "english": "Finnmark", + "french": "Finnmark", + "german": "Finnmark", + "italian": "Finnmark", + "spanish": "Finnmark", + "chinese_simple": "芬马克郡", + "korean": "핀마르크 주", + "dutch": "Finnmark", + "portuguese": "Finnmark", + "russian": "Финнмарк", + "chinese_traditional": "Finnmark", + "unknown1": "Finnmark", + "unknown2": "Finnmark", + "unknown3": "Finnmark", + "unknown4": "Finnmark" + }, + "coordinates": { + "latitude": 70.076293148, + "longitude": 29.745564285 + } + }, + { + "id": 1611399168, + "name": "Hedmark", + "translations": { + "japanese": "ヘードマルク県", + "english": "Hedmark", + "french": "Hedmark", + "german": "Hedmark", + "italian": "Hedmark", + "spanish": "Hedmark", + "chinese_simple": "海德马克郡", + "korean": "헤드마르크 주", + "dutch": "Hedmark", + "portuguese": "Hedmark", + "russian": "Хедмарк", + "chinese_traditional": "Hedmark", + "unknown1": "Hedmark", + "unknown2": "Hedmark", + "unknown3": "Hedmark", + "unknown4": "Hedmark" + }, + "coordinates": { + "latitude": 60.798339152, + "longitude": 11.052276148 + } + }, + { + "id": 1611464704, + "name": "Hordaland", + "translations": { + "japanese": "ホルダラン県", + "english": "Hordaland", + "french": "Hordaland", + "german": "Hordaland", + "italian": "Hordaland", + "spanish": "Hordaland", + "chinese_simple": "霍达兰郡", + "korean": "호르달란 주", + "dutch": "Hordaland", + "portuguese": "Hordaland", + "russian": "Хордаланн", + "chinese_traditional": "Hordaland", + "unknown1": "Hordaland", + "unknown2": "Hordaland", + "unknown3": "Hordaland", + "unknown4": "Hordaland" + }, + "coordinates": { + "latitude": 60.386351852, + "longitude": 5.32838363 + } + }, + { + "id": 1611530240, + "name": "Møre og Romsdal", + "translations": { + "japanese": "ムーレ・オ・ロムスダール県", + "english": "Møre og Romsdal", + "french": "Møre og Romsdal", + "german": "Møre og Romsdal", + "italian": "Møre og Romsdal", + "spanish": "Møre og Romsdal", + "chinese_simple": "默勒-鲁姆斯达尔郡", + "korean": "뫼레오그롬스달 주", + "dutch": "Møre og Romsdal", + "portuguese": "Møre og Romsdal", + "russian": "Мёре-ог-Румсдал", + "chinese_traditional": "Møre og Romsdal", + "unknown1": "Møre og Romsdal", + "unknown2": "Møre og Romsdal", + "unknown3": "Møre og Romsdal", + "unknown4": "Møre og Romsdal" + }, + "coordinates": { + "latitude": 62.753905536, + "longitude": 7.234516743 + } + }, + { + "id": 1611595776, + "name": "Nordland", + "translations": { + "japanese": "ヌールラン県", + "english": "Nordland", + "french": "Nordland", + "german": "Nordland", + "italian": "Nordland", + "spanish": "Nordland", + "chinese_simple": "诺尔兰郡", + "korean": "노를란 주", + "dutch": "Nordland", + "portuguese": "Nordland", + "russian": "Нурланн", + "chinese_traditional": "Nordland", + "unknown1": "Nordland", + "unknown2": "Nordland", + "unknown3": "Nordland", + "unknown4": "Nordland" + }, + "coordinates": { + "latitude": 67.274779508, + "longitude": 14.403115338 + } + }, + { + "id": 1611661312, + "name": "Nord-Trøndelag", + "translations": { + "japanese": "ヌール・トロンデラーグ県", + "english": "Nord-Trøndelag", + "french": "Nord-Trøndelag", + "german": "Nord-Trøndelag", + "italian": "Nord-Trøndelag", + "spanish": "Nord-Trøndelag", + "chinese_simple": "北特伦德拉格郡", + "korean": "노르트뢰넬라그 주", + "dutch": "Nord-Trøndelag", + "portuguese": "Nord-Trøndelag", + "russian": "Нур-Трёнделаг", + "chinese_traditional": "Nord-Trøndelag", + "unknown1": "Nord-Trøndelag", + "unknown2": "Nord-Trøndelag", + "unknown3": "Nord-Trøndelag", + "unknown4": "Nord-Trøndelag" + }, + "coordinates": { + "latitude": 64.055785404, + "longitude": 11.716950807 + } + }, + { + "id": 1611726848, + "name": "Oppland", + "translations": { + "japanese": "オップラン県", + "english": "Oppland", + "french": "Oppland", + "german": "Oppland", + "italian": "Oppland", + "spanish": "Oppland", + "chinese_simple": "奥普兰郡", + "korean": "오플란 주", + "dutch": "Oppland", + "portuguese": "Oppland", + "russian": "Оппланн", + "chinese_traditional": "Oppland", + "unknown1": "Oppland", + "unknown2": "Oppland", + "unknown3": "Oppland", + "unknown4": "Oppland" + }, + "coordinates": { + "latitude": 61.127928992, + "longitude": 10.431546921 + } + }, + { + "id": 1611792384, + "name": "Rogaland", + "translations": { + "japanese": "ローガラン県", + "english": "Rogaland", + "french": "Rogaland", + "german": "Rogaland", + "italian": "Rogaland", + "spanish": "Rogaland", + "chinese_simple": "罗加兰郡", + "korean": "로갈란 주", + "dutch": "Rogaland", + "portuguese": "Rogaland", + "russian": "Ругаланн", + "chinese_traditional": "Rogaland", + "unknown1": "Rogaland", + "unknown2": "Rogaland", + "unknown3": "Rogaland", + "unknown4": "Rogaland" + }, + "coordinates": { + "latitude": 58.958129212, + "longitude": 5.718399339 + } + }, + { + "id": 1611857920, + "name": "Sogn og Fjordane", + "translations": { + "japanese": "ソグン・オ・フィヨーラネ県", + "english": "Sogn og Fjordane", + "french": "Sogn og Fjordane", + "german": "Sogn og Fjordane", + "italian": "Sogn og Fjordane", + "spanish": "Sogn og Fjordane", + "chinese_simple": "松恩-菲尤拉讷郡", + "korean": "송노피오라네 주", + "dutch": "Sogn og Fjordane", + "portuguese": "Sogn og Fjordane", + "russian": "Согн-ог-Фьюране", + "chinese_traditional": "Sogn og Fjordane", + "unknown1": "Sogn og Fjordane", + "unknown2": "Sogn og Fjordane", + "unknown3": "Sogn og Fjordane", + "unknown4": "Sogn og Fjordane" + }, + "coordinates": { + "latitude": 61.226805944, + "longitude": 6.789569244 + } + }, + { + "id": 1611923456, + "name": "Sør-Trøndelag", + "translations": { + "japanese": "ソール・トロンデラーグ県", + "english": "Sør-Trøndelag", + "french": "Sør-Trøndelag", + "german": "Sør-Trøndelag", + "italian": "Sør-Trøndelag", + "spanish": "Sør-Trøndelag", + "chinese_simple": "南特伦德拉格郡", + "korean": "쇠르트뢰넬라그 주", + "dutch": "Sør-Trøndelag", + "portuguese": "Sør-Trøndelag", + "russian": "Сёр-Трёнделаг", + "chinese_traditional": "Sør-Trøndelag", + "unknown1": "Sør-Trøndelag", + "unknown2": "Sør-Trøndelag", + "unknown3": "Sør-Trøndelag", + "unknown4": "Sør-Trøndelag" + }, + "coordinates": { + "latitude": 63.429564708, + "longitude": 10.393094668 + } + }, + { + "id": 1611988992, + "name": "Telemark", + "translations": { + "japanese": "テレマルク県", + "english": "Telemark", + "french": "Telemark", + "german": "Telemark", + "italian": "Telemark", + "spanish": "Telemark", + "chinese_simple": "泰勒马克郡", + "korean": "텔레마르크 주", + "dutch": "Telemark", + "portuguese": "Telemark", + "russian": "Телемарк", + "chinese_traditional": "Telemark", + "unknown1": "Telemark", + "unknown2": "Telemark", + "unknown3": "Telemark", + "unknown4": "Telemark" + }, + "coordinates": { + "latitude": 59.205321592, + "longitude": 9.552638281 + } + }, + { + "id": 1612054528, + "name": "Troms", + "translations": { + "japanese": "トロムス県", + "english": "Troms", + "french": "Troms", + "german": "Troms", + "italian": "Troms", + "spanish": "Troms", + "chinese_simple": "特罗姆斯郡", + "korean": "트롬스 주", + "dutch": "Troms", + "portuguese": "Troms", + "russian": "Тромс", + "chinese_traditional": "Troms", + "unknown1": "Troms", + "unknown2": "Troms", + "unknown3": "Troms", + "unknown4": "Troms" + }, + "coordinates": { + "latitude": 69.68078534, + "longitude": 18.940481192 + } + }, + { + "id": 1612120064, + "name": "Vest-Agder", + "translations": { + "japanese": "ヴェスト・アグデル県", + "english": "Vest-Agder", + "french": "Vest-Agder", + "german": "Vest-Agder", + "italian": "Vest-Agder", + "spanish": "Vest-Agder", + "chinese_simple": "西阿格德尔郡", + "korean": "베스트아그데르 주", + "dutch": "Vest-Agder", + "portuguese": "Vest-Agder", + "russian": "Вест-Агдер", + "chinese_traditional": "Vest-Agder", + "unknown1": "Vest-Agder", + "unknown2": "Vest-Agder", + "unknown3": "Vest-Agder", + "unknown4": "Vest-Agder" + }, + "coordinates": { + "latitude": 58.167113596, + "longitude": 8.003561803 + } + }, + { + "id": 1612185600, + "name": "Vestfold", + "translations": { + "japanese": "ヴェストフォル県", + "english": "Vestfold", + "french": "Vestfold", + "german": "Vestfold", + "italian": "Vestfold", + "spanish": "Vestfold", + "chinese_simple": "西福尔郡", + "korean": "베스트폴 주", + "dutch": "Vestfold", + "portuguese": "Vestfold", + "russian": "Вестфолл", + "chinese_traditional": "Vestfold", + "unknown1": "Vestfold", + "unknown2": "Vestfold", + "unknown3": "Vestfold", + "unknown4": "Vestfold" + }, + "coordinates": { + "latitude": 59.293212216, + "longitude": 10.420560563 + } + }, + { + "id": 1612251136, + "name": "Østfold", + "translations": { + "japanese": "エストフォル県", + "english": "Østfold", + "french": "Østfold", + "german": "Østfold", + "italian": "Østfold", + "spanish": "Østfold", + "chinese_simple": "东福尔郡", + "korean": "외스트폴 주", + "dutch": "Østfold", + "portuguese": "Østfold", + "russian": "Эстфолл", + "chinese_traditional": "Østfold", + "unknown1": "Østfold", + "unknown2": "Østfold", + "unknown3": "Østfold", + "unknown4": "Østfold" + }, + "coordinates": { + "latitude": 59.287719052, + "longitude": 11.101714759 + } + }, + { + "id": 1612316672, + "name": "Svalbard", + "translations": { + "japanese": "スヴァールバル諸島", + "english": "Svalbard", + "french": "Svalbard", + "german": "Svalbard", + "italian": "Isole Svalbard", + "spanish": "Svalbard", + "chinese_simple": "斯瓦尔巴群岛", + "korean": "스발바르 제도", + "dutch": "Spitsbergen", + "portuguese": "Svalbard", + "russian": "Шпицберген", + "chinese_traditional": "Svalbard", + "unknown1": "Svalbard", + "unknown2": "Svalbard", + "unknown3": "Svalbard", + "unknown4": "Svalbard" + }, + "coordinates": { + "latitude": 78.211669032, + "longitude": 15.54569657 + } + } + ] + }, + { + "id": 97, + "iso_code": "PL", + "name": "Poland", + "translations": { + "japanese": "ポーランド", + "english": "Poland", + "french": "Pologne", + "german": "Polen", + "italian": "Polonia", + "spanish": "Polonia", + "chinese_simple": "波兰", + "korean": "폴란드", + "dutch": "Polen", + "portuguese": "Polónia", + "russian": "Польша", + "chinese_traditional": "Poland", + "unknown1": "Poland", + "unknown2": "Poland", + "unknown3": "Poland", + "unknown4": "Poland" + }, + "regions": [ + { + "id": 1627389952, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 52.23998964, + "longitude": 21.005916496 + } + }, + { + "id": 1627521024, + "name": "Masovia", + "translations": { + "japanese": "マゾフシェ", + "english": "Masovia", + "french": "Mazovie", + "german": "Masowien", + "italian": "Masovia", + "spanish": "Mazovia", + "chinese_simple": "马佐夫舍省", + "korean": "마조프셰", + "dutch": "Mazovië", + "portuguese": "Masóvia", + "russian": "Мазовецкое воеводство", + "chinese_traditional": "Masovia", + "unknown1": "Masovia", + "unknown2": "Masovia", + "unknown3": "Masovia", + "unknown4": "Masovia" + }, + "coordinates": { + "latitude": 52.23998964, + "longitude": 21.005916496 + } + }, + { + "id": 1627586560, + "name": "Lower Silesia", + "translations": { + "japanese": "ドルヌィ・シロンスク", + "english": "Lower Silesia", + "french": "Basse-Silésie", + "german": "Niederschlesien", + "italian": "Bassa Slesia", + "spanish": "Baja Silesia", + "chinese_simple": "下西里西亚省", + "korean": "하슐레지엔", + "dutch": "Neder-Silezië", + "portuguese": "Baixa Silésia", + "russian": "Нижнесилезское воеводство", + "chinese_traditional": "Lower Silesia", + "unknown1": "Lower Silesia", + "unknown2": "Lower Silesia", + "unknown3": "Lower Silesia", + "unknown4": "Lower Silesia" + }, + "coordinates": { + "latitude": 51.11389102, + "longitude": 17.0288549 + } + }, + { + "id": 1627652096, + "name": "Kuyavian-Pomeranian Voivodeship", + "translations": { + "japanese": "クヤヴィ・ポモージェ", + "english": "Kuyavian-Pomeranian Voivodeship", + "french": "Cujavie-Poméranie", + "german": "Kujawien-Pommern", + "italian": "Cuiavia-Pomerania", + "spanish": "Cuyavia y Pomerania", + "chinese_simple": "库亚瓦滨海省", + "korean": "쿠야비아포메라니아", + "dutch": "Kujavië-Pommeren", + "portuguese": "Cujávia-Pomerânia", + "russian": "Куявско-Поморское воеводство", + "chinese_traditional": "Kuyavian-Pomeranian Voivodeship", + "unknown1": "Kuyavian-Pomeranian Voivodeship", + "unknown2": "Kuyavian-Pomeranian Voivodeship", + "unknown3": "Kuyavian-Pomeranian Voivodeship", + "unknown4": "Kuyavian-Pomeranian Voivodeship" + }, + "coordinates": { + "latitude": 53.113402716, + "longitude": 18.028613478 + } + }, + { + "id": 1627717632, + "name": "Lodz", + "translations": { + "japanese": "ウッジ", + "english": "Lodz", + "french": "Łódź", + "german": "Lodsch", + "italian": "Łódź", + "spanish": "Lodz", + "chinese_simple": "罗兹省", + "korean": "우치", + "dutch": "Łódź", + "portuguese": "Lodz", + "russian": "Лодзинское воеводство", + "chinese_traditional": "Lodz", + "unknown1": "Lodz", + "unknown2": "Lodz", + "unknown3": "Lodz", + "unknown4": "Lodz" + }, + "coordinates": { + "latitude": 51.7730707, + "longitude": 19.467826376 + } + }, + { + "id": 1627783168, + "name": "Lublin", + "translations": { + "japanese": "ルブリン", + "english": "Lublin", + "french": "Lublin", + "german": "Lublin", + "italian": "Lublino", + "spanish": "Lublin", + "chinese_simple": "卢布林省", + "korean": "루블린", + "dutch": "Lublin", + "portuguese": "Lublin", + "russian": "Люблинское воеводство", + "chinese_traditional": "Lublin", + "unknown1": "Lublin", + "unknown2": "Lublin", + "unknown3": "Lublin", + "unknown4": "Lublin" + }, + "coordinates": { + "latitude": 51.234740628, + "longitude": 22.571472511 + } + }, + { + "id": 1627848704, + "name": "Lubusz", + "translations": { + "japanese": "ルブシュ", + "english": "Lubusz", + "french": "Lubusz", + "german": "Lebus", + "italian": "Lebus", + "spanish": "Lubus", + "chinese_simple": "鲁布斯卡省", + "korean": "루부쉬", + "dutch": "Lubusz", + "portuguese": "Lubusz", + "russian": "Любушское воеводство", + "chinese_traditional": "Lubusz", + "unknown1": "Lubusz", + "unknown2": "Lubusz", + "unknown3": "Lubusz", + "unknown4": "Lubusz" + }, + "coordinates": { + "latitude": 52.7343744, + "longitude": 15.232585367 + } + }, + { + "id": 1627914240, + "name": "Lesser Poland", + "translations": { + "japanese": "マウォポルスカ", + "english": "Lesser Poland", + "french": "Petite-Pologne", + "german": "Kleinpolen", + "italian": "Piccola Polonia", + "spanish": "Pequeña Polonia", + "chinese_simple": "小波兰省", + "korean": "소폴란드", + "dutch": "Klein-Polen", + "portuguese": "Pequena Polónia", + "russian": "Малопольское воеводство", + "chinese_traditional": "Lesser Poland", + "unknown1": "Lesser Poland", + "unknown2": "Lesser Poland", + "unknown3": "Lesser Poland", + "unknown4": "Lesser Poland" + }, + "coordinates": { + "latitude": 50.053710368, + "longitude": 19.940239769999998 + } + }, + { + "id": 1627979776, + "name": "Opole", + "translations": { + "japanese": "オポーレ", + "english": "Opole", + "french": "Opole", + "german": "Oppeln", + "italian": "Opole", + "spanish": "Opole", + "chinese_simple": "奥波莱省", + "korean": "오폴레", + "dutch": "Opole", + "portuguese": "Opole", + "russian": "Опольское воеводство", + "chinese_traditional": "Opole", + "unknown1": "Opole", + "unknown2": "Opole", + "unknown3": "Opole", + "unknown4": "Opole" + }, + "coordinates": { + "latitude": 50.663451572, + "longitude": 17.918749898 + } + }, + { + "id": 1628045312, + "name": "Subcarpathia", + "translations": { + "japanese": "ポトカルパチェ", + "english": "Subcarpathia", + "french": "Basses-Carpates", + "german": "Karpatenvorland", + "italian": "Precarpazia", + "spanish": "Subcarpacia", + "chinese_simple": "喀尔巴阡山省", + "korean": "카르파티아", + "dutch": "Subkarpaten", + "portuguese": "Subcarpácia", + "russian": "Подкарпатское воеводство", + "chinese_traditional": "Subcarpathia", + "unknown1": "Subcarpathia", + "unknown2": "Subcarpathia", + "unknown3": "Subcarpathia", + "unknown4": "Subcarpathia" + }, + "coordinates": { + "latitude": 50.037230876, + "longitude": 22.005675074 + } + }, + { + "id": 1628110848, + "name": "Podlachia", + "translations": { + "japanese": "ポドラシェ", + "english": "Podlachia", + "french": "Podlachie", + "german": "Podlachien", + "italian": "Podlachia", + "spanish": "Podlaquia", + "chinese_simple": "波德拉斯省", + "korean": "포들라셰", + "dutch": "Podlachië", + "portuguese": "Podláquia", + "russian": "Подляское воеводство", + "chinese_traditional": "Podlachia", + "unknown1": "Podlachia", + "unknown2": "Podlachia", + "unknown3": "Podlachia", + "unknown4": "Podlachia" + }, + "coordinates": { + "latitude": 53.135375372, + "longitude": 23.153749485 + } + }, + { + "id": 1628176384, + "name": "Pomerania", + "translations": { + "japanese": "ポモージェ", + "english": "Pomerania", + "french": "Poméranie", + "german": "Pommern", + "italian": "Pomerania", + "spanish": "Pomerania", + "chinese_simple": "滨海省", + "korean": "포메라니아", + "dutch": "Pommeren", + "portuguese": "Pomerânia", + "russian": "Поморское воеводство", + "chinese_traditional": "Pomerania", + "unknown1": "Pomerania", + "unknown2": "Pomerania", + "unknown3": "Pomerania", + "unknown4": "Pomerania" + }, + "coordinates": { + "latitude": 54.35485778, + "longitude": 18.632863168 + } + }, + { + "id": 1628241920, + "name": "Silesia", + "translations": { + "japanese": "シュレジエン", + "english": "Silesia", + "french": "Silésie", + "german": "Schlesien", + "italian": "Slesia", + "spanish": "Silesia", + "chinese_simple": "西里西亚省", + "korean": "슐레지엔", + "dutch": "Silezië", + "portuguese": "Silésia", + "russian": "Силезское воеводство", + "chinese_traditional": "Silesia", + "unknown1": "Silesia", + "unknown2": "Silesia", + "unknown3": "Silesia", + "unknown4": "Silesia" + }, + "coordinates": { + "latitude": 50.267943764, + "longitude": 19.011892519 + } + }, + { + "id": 1628307456, + "name": "Świętokrzyskie", + "translations": { + "japanese": "シフィェンティクシシュ", + "english": "Świętokrzyskie", + "french": "Sainte-Croix", + "german": "Heiligkreuz", + "italian": "Santacroce", + "spanish": "Santa Cruz", + "chinese_simple": "圣十字省", + "korean": "시비엥토크시스키에", + "dutch": "Święty Krzyż", + "portuguese": "Santa Cruz", + "russian": "Свентокшиское воеводство", + "chinese_traditional": "Świętokrzyskie", + "unknown1": "Świętokrzyskie", + "unknown2": "Świętokrzyskie", + "unknown3": "Świętokrzyskie", + "unknown4": "Świętokrzyskie" + }, + "coordinates": { + "latitude": 50.86669864, + "longitude": 20.621393966 + } + }, + { + "id": 1628372992, + "name": "Warmian-Masurian Voivodeship", + "translations": { + "japanese": "ヴァルミア・マスールィ", + "english": "Warmian-Masurian Voivodeship", + "french": "Warmie-Mazurie", + "german": "Ermland-Masuren", + "italian": "Varmia-Masuria", + "spanish": "Varmia y Masuria", + "chinese_simple": "瓦尔米亚马祖尔省", + "korean": "바르미아 마수리아", + "dutch": "Ermland-Mazurië", + "portuguese": "Vármia-Masúria", + "russian": "Варминско-Мазурское воеводство", + "chinese_traditional": "Warmian-Masurian Voivodeship", + "unknown1": "Warmian-Masurian Voivodeship", + "unknown2": "Warmian-Masurian Voivodeship", + "unknown3": "Warmian-Masurian Voivodeship", + "unknown4": "Warmian-Masurian Voivodeship" + }, + "coordinates": { + "latitude": 53.772582396, + "longitude": 20.484064490999998 + } + }, + { + "id": 1628438528, + "name": "Greater Poland", + "translations": { + "japanese": "ヴィェルコポルスカ", + "english": "Greater Poland", + "french": "Grande-Pologne", + "german": "Großpolen", + "italian": "Grande Polonia", + "spanish": "Gran Polonia", + "chinese_simple": "大波兰省", + "korean": "대폴란드", + "dutch": "Groot-Polen", + "portuguese": "Grande Polónia", + "russian": "Великопольское воеводство", + "chinese_traditional": "Greater Poland", + "unknown1": "Greater Poland", + "unknown2": "Greater Poland", + "unknown3": "Greater Poland", + "unknown4": "Greater Poland" + }, + "coordinates": { + "latitude": 52.388305068, + "longitude": 16.880539067 + } + }, + { + "id": 1628504064, + "name": "Western Pomerania", + "translations": { + "japanese": "西ポモージェ", + "english": "Western Pomerania", + "french": "Poméranie occidentale", + "german": "Westpommern", + "italian": "Pomerania Occidentale", + "spanish": "Pomerania Occidental", + "chinese_simple": "西滨海省", + "korean": "서포메라니아", + "dutch": "West-Pommeren", + "portuguese": "Pomerânia Ocidental", + "russian": "Западно-Поморское воеводство", + "chinese_traditional": "Western Pomerania", + "unknown1": "Western Pomerania", + "unknown2": "Western Pomerania", + "unknown3": "Western Pomerania", + "unknown4": "Western Pomerania" + }, + "coordinates": { + "latitude": 53.426513064, + "longitude": 14.551431170999999 + } + } + ] + }, + { + "id": 98, + "iso_code": "PT", + "name": "Portugal", + "translations": { + "japanese": "ポルトガル", + "english": "Portugal", + "french": "Portugal", + "german": "Portugal", + "italian": "Portogallo", + "spanish": "Portugal", + "chinese_simple": "葡萄牙", + "korean": "포르투갈", + "dutch": "Portugal", + "portuguese": "Portugal", + "russian": "Португалия", + "chinese_traditional": "Portugal", + "unknown1": "Portugal", + "unknown2": "Portugal", + "unknown3": "Portugal", + "unknown4": "Portugal" + }, + "regions": [ + { + "id": 1644167168, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 38.721313036, + "longitude": -9.140160384000012 + } + }, + { + "id": 1644298240, + "name": "Lisbon", + "translations": { + "japanese": "リスボン県", + "english": "Lisbon", + "french": "Lisbonne", + "german": "Lissabon", + "italian": "Lisbona", + "spanish": "Distrito de Lisboa", + "chinese_simple": "里斯本区", + "korean": "리스보아 주", + "dutch": "Lissabon", + "portuguese": "Lisboa", + "russian": "Лиссабон", + "chinese_traditional": "Lisbon", + "unknown1": "Lisbon", + "unknown2": "Lisbon", + "unknown3": "Lisbon", + "unknown4": "Lisbon" + }, + "coordinates": { + "latitude": 38.721313036, + "longitude": -9.140160384000012 + } + }, + { + "id": 1644625920, + "name": "Madeira", + "translations": { + "japanese": "マディラ自治州", + "english": "Madeira", + "french": "Madère", + "german": "Madeira", + "italian": "Madera", + "spanish": "Madeira", + "chinese_simple": "马德拉自治区", + "korean": "마데이라 주", + "dutch": "Madeira", + "portuguese": "Madeira", + "russian": "Мадейра", + "chinese_traditional": "Madeira", + "unknown1": "Madeira", + "unknown2": "Madeira", + "unknown3": "Madeira", + "unknown4": "Madeira" + }, + "coordinates": { + "latitude": 32.640380488, + "longitude": -16.90751549000001 + } + }, + { + "id": 1644691456, + "name": "Azores", + "translations": { + "japanese": "アソレス自治州", + "english": "Azores", + "french": "Açores", + "german": "Azoren", + "italian": "Azzorre", + "spanish": "Azores", + "chinese_simple": "亚速尔自治区", + "korean": "아소르스 주", + "dutch": "Azoren", + "portuguese": "Açores", + "russian": "Азорские острова", + "chinese_traditional": "Azores", + "unknown1": "Azores", + "unknown2": "Azores", + "unknown3": "Azores", + "unknown4": "Azores" + }, + "coordinates": { + "latitude": 37.73803668, + "longitude": -25.663642815999992 + } + }, + { + "id": 1644756992, + "name": "Aveiro", + "translations": { + "japanese": "アヴェイロ県", + "english": "Aveiro", + "french": "Aveiro", + "german": "Aveiro", + "italian": "Aveiro", + "spanish": "Distrito de Aveiro", + "chinese_simple": "阿威罗区", + "korean": "아베이루 주", + "dutch": "Aveiro", + "portuguese": "Aveiro", + "russian": "Авейру", + "chinese_traditional": "Aveiro", + "unknown1": "Aveiro", + "unknown2": "Aveiro", + "unknown3": "Aveiro", + "unknown4": "Aveiro" + }, + "coordinates": { + "latitude": 40.638427272, + "longitude": -8.651267453000003 + } + }, + { + "id": 1644822528, + "name": "Beja", + "translations": { + "japanese": "ベージャ県", + "english": "Beja", + "french": "Beja", + "german": "Beja", + "italian": "Beja", + "spanish": "Distrito de Beja", + "chinese_simple": "贝雅区", + "korean": "베자 주", + "dutch": "Beja", + "portuguese": "Beja", + "russian": "Бежа", + "chinese_traditional": "Beja", + "unknown1": "Beja", + "unknown2": "Beja", + "unknown3": "Beja", + "unknown4": "Beja" + }, + "coordinates": { + "latitude": 38.01269488, + "longitude": -7.860249677000013 + } + }, + { + "id": 1644888064, + "name": "Braga", + "translations": { + "japanese": "ブラガ県", + "english": "Braga", + "french": "Braga", + "german": "Braga", + "italian": "Braga", + "spanish": "Distrito de Braga", + "chinese_simple": "布拉加区", + "korean": "브라가 주", + "dutch": "Braga", + "portuguese": "Braga", + "russian": "Брага", + "chinese_traditional": "Braga", + "unknown1": "Braga", + "unknown2": "Braga", + "unknown3": "Braga", + "unknown4": "Braga" + }, + "coordinates": { + "latitude": 41.550292496, + "longitude": -8.420553935000015 + } + }, + { + "id": 1644953600, + "name": "Bragança", + "translations": { + "japanese": "ブラガンサ県", + "english": "Bragança", + "french": "Bragança", + "german": "Bragança", + "italian": "Bragança", + "spanish": "Distrito de Braganza", + "chinese_simple": "布拉甘萨区", + "korean": "브라간사 주", + "dutch": "Bragança", + "portuguese": "Bragança", + "russian": "Браганса", + "chinese_traditional": "Bragança", + "unknown1": "Bragança", + "unknown2": "Bragança", + "unknown3": "Bragança", + "unknown4": "Bragança" + }, + "coordinates": { + "latitude": 41.80297804, + "longitude": -6.7561206979999895 + } + }, + { + "id": 1645019136, + "name": "Castelo Branco", + "translations": { + "japanese": "カステロ・ブランコ県", + "english": "Castelo Branco", + "french": "Castelo Branco", + "german": "Castelo Branco", + "italian": "Castelo Branco", + "spanish": "Distrito de Castelo Branco", + "chinese_simple": "布朗库堡区", + "korean": "카스텔루브랑쿠 주", + "dutch": "Castelo Branco", + "portuguese": "Castelo Branco", + "russian": "Каштелу-Бранку", + "chinese_traditional": "Castelo Branco", + "unknown1": "Castelo Branco", + "unknown2": "Castelo Branco", + "unknown3": "Castelo Branco", + "unknown4": "Castelo Branco" + }, + "coordinates": { + "latitude": 39.819945836, + "longitude": -7.4867135050000115 + } + }, + { + "id": 1645084672, + "name": "Coimbra", + "translations": { + "japanese": "コインブラ県", + "english": "Coimbra", + "french": "Coimbra", + "german": "Coimbra", + "italian": "Coimbra", + "spanish": "Distrito de Coímbra", + "chinese_simple": "科英布拉区", + "korean": "코임브라 주", + "dutch": "Coimbra", + "portuguese": "Coimbra", + "russian": "Коимбра", + "chinese_traditional": "Coimbra", + "unknown1": "Coimbra", + "unknown2": "Coimbra", + "unknown3": "Coimbra", + "unknown4": "Coimbra" + }, + "coordinates": { + "latitude": 40.20996048, + "longitude": -8.426047114 + } + }, + { + "id": 1645150208, + "name": "Évora", + "translations": { + "japanese": "エヴォラ県", + "english": "Évora", + "french": "Évora", + "german": "Évora", + "italian": "Évora", + "spanish": "Distrito de Évora", + "chinese_simple": "埃武拉区", + "korean": "에보라 주", + "dutch": "Évora", + "portuguese": "Évora", + "russian": "Эвора", + "chinese_traditional": "Évora", + "unknown1": "Évora", + "unknown2": "Évora", + "unknown3": "Évora", + "unknown4": "Évora" + }, + "coordinates": { + "latitude": 38.567504444, + "longitude": -7.904195109 + } + }, + { + "id": 1645215744, + "name": "Faro", + "translations": { + "japanese": "ファーロ県", + "english": "Faro", + "french": "Faro", + "german": "Faro", + "italian": "Faro", + "spanish": "Distrito de Faro", + "chinese_simple": "法鲁区", + "korean": "파로 주", + "dutch": "Faro", + "portuguese": "Faro", + "russian": "Фару", + "chinese_traditional": "Faro", + "unknown1": "Faro", + "unknown2": "Faro", + "unknown3": "Faro", + "unknown4": "Faro" + }, + "coordinates": { + "latitude": 37.012939032, + "longitude": -7.931661004000006 + } + }, + { + "id": 1645281280, + "name": "Guarda", + "translations": { + "japanese": "グアルダ県", + "english": "Guarda", + "french": "Guarda", + "german": "Guarda", + "italian": "Guarda", + "spanish": "Distrito de Guarda", + "chinese_simple": "瓜达区", + "korean": "구아르다 주", + "dutch": "Guarda", + "portuguese": "Guarda", + "russian": "Гуарда", + "chinese_traditional": "Guarda", + "unknown1": "Guarda", + "unknown2": "Guarda", + "unknown3": "Guarda", + "unknown4": "Guarda" + }, + "coordinates": { + "latitude": 40.534057156, + "longitude": -7.266986344999992 + } + }, + { + "id": 1645346816, + "name": "Leiria", + "translations": { + "japanese": "レイリア県", + "english": "Leiria", + "french": "Leiria", + "german": "Leiria", + "italian": "Leiria", + "spanish": "Distrito de Leiria", + "chinese_simple": "莱里亚区", + "korean": "레이리아 주", + "dutch": "Leiria", + "portuguese": "Leiria", + "russian": "Лейрия", + "chinese_traditional": "Leiria", + "unknown1": "Leiria", + "unknown2": "Leiria", + "unknown3": "Leiria", + "unknown4": "Leiria" + }, + "coordinates": { + "latitude": 39.74304154, + "longitude": -8.805076465000013 + } + }, + { + "id": 1645412352, + "name": "Portalegre", + "translations": { + "japanese": "ポルタレグレ県", + "english": "Portalegre", + "french": "Portalegre", + "german": "Portalegre", + "italian": "Portalegre", + "spanish": "Distrito de Portalegre", + "chinese_simple": "波塔莱格里区", + "korean": "포르탈레그르 주", + "dutch": "Portalegre", + "portuguese": "Portalegre", + "russian": "Порталегре", + "chinese_traditional": "Portalegre", + "unknown1": "Portalegre", + "unknown2": "Portalegre", + "unknown3": "Portalegre", + "unknown4": "Portalegre" + }, + "coordinates": { + "latitude": 39.287108928, + "longitude": -7.431781715 + } + }, + { + "id": 1645477888, + "name": "Porto", + "translations": { + "japanese": "ポルト県", + "english": "Porto", + "french": "Porto", + "german": "Porto", + "italian": "Porto", + "spanish": "Distrito de Oporto", + "chinese_simple": "波尔图区", + "korean": "포르투 주", + "dutch": "Porto", + "portuguese": "Porto", + "russian": "Порту", + "chinese_traditional": "Porto", + "unknown1": "Porto", + "unknown2": "Porto", + "unknown3": "Porto", + "unknown4": "Porto" + }, + "coordinates": { + "latitude": 41.149291524, + "longitude": -8.607322021000016 + } + }, + { + "id": 1645543424, + "name": "Santarém", + "translations": { + "japanese": "サンタレン県", + "english": "Santarém", + "french": "Santarém", + "german": "Santarém", + "italian": "Santarém", + "spanish": "Distrito de Santarém", + "chinese_simple": "圣塔伦区", + "korean": "산타렝 주", + "dutch": "Santarém", + "portuguese": "Santarém", + "russian": "Сантарен", + "chinese_traditional": "Santarém", + "unknown1": "Santarém", + "unknown2": "Santarém", + "unknown3": "Santarém", + "unknown4": "Santarém" + }, + "coordinates": { + "latitude": 39.232177288, + "longitude": -8.684226526999993 + } + }, + { + "id": 1645608960, + "name": "Setúbal", + "translations": { + "japanese": "セトゥーバル県", + "english": "Setúbal", + "french": "Setúbal", + "german": "Setúbal", + "italian": "Setúbal", + "spanish": "Distrito de Setúbal", + "chinese_simple": "塞图巴尔区", + "korean": "세투발 주", + "dutch": "Setúbal", + "portuguese": "Setúbal", + "russian": "Сетубал", + "chinese_traditional": "Setúbal", + "unknown1": "Setúbal", + "unknown2": "Setúbal", + "unknown3": "Setúbal", + "unknown4": "Setúbal" + }, + "coordinates": { + "latitude": 38.523559132, + "longitude": -8.887474150000003 + } + }, + { + "id": 1645674496, + "name": "Viana do Castelo", + "translations": { + "japanese": "ヴィアナ・ド・カステロ県", + "english": "Viana do Castelo", + "french": "Viana do Castelo", + "german": "Viana do Castelo", + "italian": "Viana do Castelo", + "spanish": "Distrito de Viana do Castelo", + "chinese_simple": "维亚纳堡区", + "korean": "비아나두카스텔루 주", + "dutch": "Viana do Castelo", + "portuguese": "Viana do Castelo", + "russian": "Виана-ду-Каштелу", + "chinese_traditional": "Viana do Castelo", + "unknown1": "Viana do Castelo", + "unknown2": "Viana do Castelo", + "unknown3": "Viana do Castelo", + "unknown4": "Viana do Castelo" + }, + "coordinates": { + "latitude": 41.69311476, + "longitude": -8.827049181000007 + } + }, + { + "id": 1645740032, + "name": "Vila Real", + "translations": { + "japanese": "ヴィラ・レアル県", + "english": "Vila Real", + "french": "Vila Real", + "german": "Vila Real", + "italian": "Vila Real", + "spanish": "Distrito de Vila Real", + "chinese_simple": "雷阿尔城区", + "korean": "빌라헤알 주", + "dutch": "Vila Real", + "portuguese": "Vila Real", + "russian": "Вила-Реал", + "chinese_traditional": "Vila Real", + "unknown1": "Vila Real", + "unknown2": "Vila Real", + "unknown3": "Vila Real", + "unknown4": "Vila Real" + }, + "coordinates": { + "latitude": 41.292113788, + "longitude": -7.744892918000005 + } + }, + { + "id": 1645805568, + "name": "Viseu", + "translations": { + "japanese": "ヴィゼウ県", + "english": "Viseu", + "french": "Viseu", + "german": "Viseu", + "italian": "Viseu", + "spanish": "Distrito de Viseu", + "chinese_simple": "维塞乌区", + "korean": "비제우 주", + "dutch": "Viseu", + "portuguese": "Viseu", + "russian": "Визеу", + "chinese_traditional": "Viseu", + "unknown1": "Viseu", + "unknown2": "Viseu", + "unknown3": "Viseu", + "unknown4": "Viseu" + }, + "coordinates": { + "latitude": 40.654906764, + "longitude": -7.909688288000012 + } + } + ] + }, + { + "id": 99, + "iso_code": "RO", + "name": "Romania", + "translations": { + "japanese": "ルーマニア", + "english": "Romania", + "french": "Roumanie", + "german": "Rumänien", + "italian": "Romania", + "spanish": "Rumanía", + "chinese_simple": "罗马尼亚", + "korean": "루마니아", + "dutch": "Roemenië", + "portuguese": "Roménia", + "russian": "Румыния", + "chinese_traditional": "Romania", + "unknown1": "Romania", + "unknown2": "Romania", + "unknown3": "Romania", + "unknown4": "Romania" + }, + "regions": [ + { + "id": 1660944384, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 44.428710432, + "longitude": 26.081613892 + } + }, + { + "id": 1661075456, + "name": "Bucharest", + "translations": { + "japanese": "ブカレスト州", + "english": "Bucharest", + "french": "Bucarest", + "german": "Bukarest", + "italian": "Bucarest", + "spanish": "Bucarest", + "chinese_simple": "布加勒斯特市", + "korean": "부쿠레슈티 주", + "dutch": "Boekarest", + "portuguese": "Bucareste", + "russian": "Бухарест", + "chinese_traditional": "Bucharest", + "unknown1": "Bucharest", + "unknown2": "Bucharest", + "unknown3": "Bucharest", + "unknown4": "Bucharest" + }, + "coordinates": { + "latitude": 44.428710432, + "longitude": 26.081613892 + } + }, + { + "id": 1661140992, + "name": "Alba", + "translations": { + "japanese": "アルバ州", + "english": "Alba", + "french": "Alba", + "german": "Alba", + "italian": "Alba", + "spanish": "Alba", + "chinese_simple": "阿尔巴县", + "korean": "알바 주", + "dutch": "Alba", + "portuguese": "Alba", + "russian": "Алба", + "chinese_traditional": "Alba", + "unknown1": "Alba", + "unknown2": "Alba", + "unknown3": "Alba", + "unknown4": "Alba" + }, + "coordinates": { + "latitude": 46.065673304, + "longitude": 23.56573791 + } + }, + { + "id": 1661206528, + "name": "Arad", + "translations": { + "japanese": "アラド州", + "english": "Arad", + "french": "Arad", + "german": "Arad", + "italian": "Arad", + "spanish": "Arad", + "chinese_simple": "阿拉德县", + "korean": "아라드 주", + "dutch": "Arad", + "portuguese": "Arad", + "russian": "Арад", + "chinese_traditional": "Arad", + "unknown1": "Arad", + "unknown2": "Arad", + "unknown3": "Arad", + "unknown4": "Arad" + }, + "coordinates": { + "latitude": 46.181029748, + "longitude": 21.31353452 + } + }, + { + "id": 1661272064, + "name": "Arges", + "translations": { + "japanese": "アルジェシュ州", + "english": "Arges", + "french": "Argeş", + "german": "Argeş", + "italian": "Argeş", + "spanish": "Argeş", + "chinese_simple": "阿尔杰什县", + "korean": "아르제슈 주", + "dutch": "Argeş", + "portuguese": "Arges", + "russian": "Арджеш", + "chinese_traditional": "Arges", + "unknown1": "Arges", + "unknown2": "Arges", + "unknown3": "Arges", + "unknown4": "Arges" + }, + "coordinates": { + "latitude": 44.846190896, + "longitude": 24.878607691 + } + }, + { + "id": 1661337600, + "name": "Bacau", + "translations": { + "japanese": "バカウ州", + "english": "Bacau", + "french": "Bacău", + "german": "Bacău", + "italian": "Bacău", + "spanish": "Bacău", + "chinese_simple": "巴克乌县", + "korean": "바커우 주", + "dutch": "Bacău", + "portuguese": "Bacău", + "russian": "Бакэу", + "chinese_traditional": "Bacau", + "unknown1": "Bacau", + "unknown2": "Bacau", + "unknown3": "Bacau", + "unknown4": "Bacau" + }, + "coordinates": { + "latitude": 46.565551228, + "longitude": 26.9165771 + } + }, + { + "id": 1661403136, + "name": "Bihor", + "translations": { + "japanese": "ビホル州", + "english": "Bihor", + "french": "Bihor", + "german": "Bihor", + "italian": "Bihor", + "spanish": "Bihor", + "chinese_simple": "比霍尔县", + "korean": "비호르 주", + "dutch": "Bihor", + "portuguese": "Bihor", + "russian": "Бихор", + "chinese_traditional": "Bihor", + "unknown1": "Bihor", + "unknown2": "Bihor", + "unknown3": "Bihor", + "unknown4": "Bihor" + }, + "coordinates": { + "latitude": 47.065429152, + "longitude": 21.912291031 + } + }, + { + "id": 1661468672, + "name": "Bistrita-Nasaud", + "translations": { + "japanese": "ビストリツァ・ナサウド州", + "english": "Bistrita-Nasaud", + "french": "Bistrita-Năsăud", + "german": "Bistrita-Năsăud", + "italian": "Bistrita-Năsăud", + "spanish": "Bistrita-Năsăud", + "chinese_simple": "比斯特里察-讷瑟乌德县", + "korean": "비스트리차너서우드 주", + "dutch": "Bistrita-Năsăud", + "portuguese": "Bistrita-Năsăud", + "russian": "Бистрица-Нэсэуд", + "chinese_traditional": "Bistrita-Nasaud", + "unknown1": "Bistrita-Nasaud", + "unknown2": "Bistrita-Nasaud", + "unknown3": "Bistrita-Nasaud", + "unknown4": "Bistrita-Nasaud" + }, + "coordinates": { + "latitude": 47.13134712, + "longitude": 24.49957834 + } + }, + { + "id": 1661534208, + "name": "Botosani", + "translations": { + "japanese": "ボトシャニ州", + "english": "Botosani", + "french": "Botoşani", + "german": "Botoşani", + "italian": "Botoşani", + "spanish": "Botoşani", + "chinese_simple": "博托沙尼县", + "korean": "보토샤니 주", + "dutch": "Botoşani", + "portuguese": "Botoşani", + "russian": "Ботошани", + "chinese_traditional": "Botosani", + "unknown1": "Botosani", + "unknown2": "Botosani", + "unknown3": "Botosani", + "unknown4": "Botosani" + }, + "coordinates": { + "latitude": 47.746581488, + "longitude": 26.663890866 + } + }, + { + "id": 1661599744, + "name": "Braila", + "translations": { + "japanese": "ブライラ州", + "english": "Braila", + "french": "Brăila", + "german": "Brăila", + "italian": "Brăila", + "spanish": "Brăila", + "chinese_simple": "布勒伊拉县", + "korean": "브러일라 주", + "dutch": "Brăila", + "portuguese": "Brăila", + "russian": "Брэила", + "chinese_traditional": "Braila", + "unknown1": "Braila", + "unknown2": "Braila", + "unknown3": "Braila", + "unknown4": "Braila" + }, + "coordinates": { + "latitude": 45.280150852, + "longitude": 27.965774289 + } + }, + { + "id": 1661665280, + "name": "Brasov", + "translations": { + "japanese": "ブラショヴ州", + "english": "Brasov", + "french": "Braşov", + "german": "Braşov", + "italian": "Braşov", + "spanish": "Braşov", + "chinese_simple": "布拉索夫县", + "korean": "브라쇼브 주", + "dutch": "Braşov", + "portuguese": "Braşov", + "russian": "Брашов", + "chinese_traditional": "Brasov", + "unknown1": "Brasov", + "unknown2": "Brasov", + "unknown3": "Brasov", + "unknown4": "Brasov" + }, + "coordinates": { + "latitude": 45.64819284, + "longitude": 25.614693676999998 + } + }, + { + "id": 1661730816, + "name": "Buzau", + "translations": { + "japanese": "ブザウ州", + "english": "Buzau", + "french": "Buzău", + "german": "Buzău", + "italian": "Buzău", + "spanish": "Buzău", + "chinese_simple": "布泽乌县", + "korean": "부저우 주", + "dutch": "Buzău", + "portuguese": "Buzău", + "russian": "Бузэу", + "chinese_traditional": "Buzau", + "unknown1": "Buzau", + "unknown2": "Buzau", + "unknown3": "Buzau", + "unknown4": "Buzau" + }, + "coordinates": { + "latitude": 45.148314916, + "longitude": 26.812206699 + } + }, + { + "id": 1661796352, + "name": "Calarasi", + "translations": { + "japanese": "カララシ州", + "english": "Calarasi", + "french": "Călăraşi", + "german": "Călăraşi", + "italian": "Călăraşi", + "spanish": "Călăraşi", + "chinese_simple": "克勒拉希县", + "korean": "컬러라시 주", + "dutch": "Călăraşi", + "portuguese": "Călăraşi", + "russian": "Кэлэраши", + "chinese_traditional": "Calarasi", + "unknown1": "Calarasi", + "unknown2": "Calarasi", + "unknown3": "Calarasi", + "unknown4": "Calarasi" + }, + "coordinates": { + "latitude": 44.197997544, + "longitude": 27.328565525 + } + }, + { + "id": 1661861888, + "name": "Caras-Severin", + "translations": { + "japanese": "カラシュ・セヴェリン州", + "english": "Caras-Severin", + "french": "Caraş-Severin", + "german": "Caraş-Severin", + "italian": "Caraş-Severin", + "spanish": "Caraş-Severin", + "chinese_simple": "卡拉什-塞维林县", + "korean": "카라슈세베린 주", + "dutch": "Caraş-Severin", + "portuguese": "Caraş-Severin", + "russian": "Караш-Северин", + "chinese_traditional": "Caras-Severin", + "unknown1": "Caras-Severin", + "unknown2": "Caras-Severin", + "unknown3": "Caras-Severin", + "unknown4": "Caras-Severin" + }, + "coordinates": { + "latitude": 45.296630344, + "longitude": 21.879331957 + } + }, + { + "id": 1661927424, + "name": "Cluj", + "translations": { + "japanese": "クルージュ州", + "english": "Cluj", + "french": "Cluj", + "german": "Cluj", + "italian": "Cluj", + "spanish": "Cluj", + "chinese_simple": "克卢日县", + "korean": "클루지 주", + "dutch": "Cluj", + "portuguese": "Cluj", + "russian": "Клуж", + "chinese_traditional": "Cluj", + "unknown1": "Cluj", + "unknown2": "Cluj", + "unknown3": "Cluj", + "unknown4": "Cluj" + }, + "coordinates": { + "latitude": 46.779784624, + "longitude": 23.582217447 + } + }, + { + "id": 1661992960, + "name": "Constanta", + "translations": { + "japanese": "コンスタンツァ州", + "english": "Constanta", + "french": "Constanta", + "german": "Constanta", + "italian": "Costanza", + "spanish": "Constanza", + "chinese_simple": "康斯坦察县", + "korean": "콘스탄차 주", + "dutch": "Constanta", + "portuguese": "Constanta", + "russian": "Констанца", + "chinese_traditional": "Constanta", + "unknown1": "Constanta", + "unknown2": "Constanta", + "unknown3": "Constanta", + "unknown4": "Constanta" + }, + "coordinates": { + "latitude": 44.181518052, + "longitude": 28.630448947999998 + } + }, + { + "id": 1662058496, + "name": "Covasna", + "translations": { + "japanese": "コヴァスナ州", + "english": "Covasna", + "french": "Covasna", + "german": "Covasna", + "italian": "Covasna", + "spanish": "Covasna", + "chinese_simple": "科瓦斯纳县", + "korean": "코바스나 주", + "dutch": "Covasna", + "portuguese": "Covasna", + "russian": "Ковасна", + "chinese_traditional": "Covasna", + "unknown1": "Covasna", + "unknown2": "Covasna", + "unknown3": "Covasna", + "unknown4": "Covasna" + }, + "coordinates": { + "latitude": 45.862426236, + "longitude": 25.795968584 + } + }, + { + "id": 1662124032, + "name": "Dâmbovita", + "translations": { + "japanese": "ドゥンボビツァ州", + "english": "Dâmbovita", + "french": "Dâmbovita", + "german": "Dâmbovita", + "italian": "Dâmbovita", + "spanish": "Dâmbovita", + "chinese_simple": "登博维察县", + "korean": "듬보비차 주", + "dutch": "Dâmbovita", + "portuguese": "Dâmbovita", + "russian": "Дымбовица", + "chinese_traditional": "Dâmbovita", + "unknown1": "Dâmbovita", + "unknown2": "Dâmbovita", + "unknown3": "Dâmbovita", + "unknown4": "Dâmbovita" + }, + "coordinates": { + "latitude": 44.93408152, + "longitude": 25.455391486 + } + }, + { + "id": 1662189568, + "name": "Dolj", + "translations": { + "japanese": "ドルジュ州", + "english": "Dolj", + "french": "Dolj", + "german": "Dolj", + "italian": "Dolj", + "spanish": "Dolj", + "chinese_simple": "多尔日县", + "korean": "돌지 주", + "dutch": "Dolj", + "portuguese": "Dolj", + "russian": "Долж", + "chinese_traditional": "Dolj", + "unknown1": "Dolj", + "unknown2": "Dolj", + "unknown3": "Dolj", + "unknown4": "Dolj" + }, + "coordinates": { + "latitude": 44.313353988, + "longitude": 23.812930965 + } + }, + { + "id": 1662255104, + "name": "Galati", + "translations": { + "japanese": "ガラツィ州", + "english": "Galati", + "french": "Galati", + "german": "Galati", + "italian": "Galati", + "spanish": "Galati", + "chinese_simple": "加拉茨县", + "korean": "갈라치 주", + "dutch": "Galati", + "portuguese": "Galati", + "russian": "Галац", + "chinese_traditional": "Galati", + "unknown1": "Galati", + "unknown2": "Galati", + "unknown3": "Galati", + "unknown4": "Galati" + }, + "coordinates": { + "latitude": 45.42846628, + "longitude": 28.031692437 + } + }, + { + "id": 1662320640, + "name": "Giurgiu", + "translations": { + "japanese": "ジュルジュ州", + "english": "Giurgiu", + "french": "Giurgiu", + "german": "Giurgiu", + "italian": "Giurgiu", + "spanish": "Giurgiu", + "chinese_simple": "久尔久县", + "korean": "지우르지우 주", + "dutch": "Giurgiu", + "portuguese": "Giurgiu", + "russian": "Джурджу", + "chinese_traditional": "Giurgiu", + "unknown1": "Giurgiu", + "unknown2": "Giurgiu", + "unknown3": "Giurgiu", + "unknown4": "Giurgiu" + }, + "coordinates": { + "latitude": 43.895873524, + "longitude": 25.966257133 + } + }, + { + "id": 1662386176, + "name": "Gorj", + "translations": { + "japanese": "ゴルジュ州", + "english": "Gorj", + "french": "Gorj", + "german": "Gorj", + "italian": "Gorj", + "spanish": "Gorj", + "chinese_simple": "戈尔日县", + "korean": "고르지 주", + "dutch": "Gorj", + "portuguese": "Gorj", + "russian": "Горж", + "chinese_traditional": "Gorj", + "unknown1": "Gorj", + "unknown2": "Gorj", + "unknown3": "Gorj", + "unknown4": "Gorj" + }, + "coordinates": { + "latitude": 45.049437964, + "longitude": 23.263613065 + } + }, + { + "id": 1662451712, + "name": "Harghita", + "translations": { + "japanese": "ハルギタ州", + "english": "Harghita", + "french": "Harghita", + "german": "Harghita", + "italian": "Harghita", + "spanish": "Harghita", + "chinese_simple": "哈尔吉塔县", + "korean": "하르기타 주", + "dutch": "Harghita", + "portuguese": "Harghita", + "russian": "Харгита", + "chinese_traditional": "Harghita", + "unknown1": "Harghita", + "unknown2": "Harghita", + "unknown3": "Harghita", + "unknown4": "Harghita" + }, + "coordinates": { + "latitude": 46.36230416, + "longitude": 25.795968584 + } + }, + { + "id": 1662517248, + "name": "Hunedoara", + "translations": { + "japanese": "フネドアラ州", + "english": "Hunedoara", + "french": "Hunedoara", + "german": "Hunedoara", + "italian": "Hunedoara", + "spanish": "Hunedoara", + "chinese_simple": "胡内多阿拉县", + "korean": "후네도아라 주", + "dutch": "Hunedoara", + "portuguese": "Hunedoara", + "russian": "Хунедоара", + "chinese_traditional": "Hunedoara", + "unknown1": "Hunedoara", + "unknown2": "Hunedoara", + "unknown3": "Hunedoara", + "unknown4": "Hunedoara" + }, + "coordinates": { + "latitude": 45.878905728, + "longitude": 22.901063251 + } + }, + { + "id": 1662582784, + "name": "Ialomita", + "translations": { + "japanese": "ヤロミツァ州", + "english": "Ialomita", + "french": "Ialomita", + "german": "Ialomita", + "italian": "Ialomita", + "spanish": "Ialomita", + "chinese_simple": "雅洛米察县", + "korean": "이알로미차 주", + "dutch": "Ialomita", + "portuguese": "Ialomita", + "russian": "Яломица", + "chinese_traditional": "Ialomita", + "unknown1": "Ialomita", + "unknown2": "Ialomita", + "unknown3": "Ialomita", + "unknown4": "Ialomita" + }, + "coordinates": { + "latitude": 44.566039532, + "longitude": 27.378004136 + } + }, + { + "id": 1662648320, + "name": "Iasi", + "translations": { + "japanese": "ヤシ州", + "english": "Iasi", + "french": "Iaşi", + "german": "Iaşi", + "italian": "Iaşi", + "spanish": "Iaşi", + "chinese_simple": "雅西县", + "korean": "이아시 주", + "dutch": "Iaşi", + "portuguese": "Iasi", + "russian": "Яссы", + "chinese_traditional": "Iasi", + "unknown1": "Iasi", + "unknown2": "Iasi", + "unknown3": "Iasi", + "unknown4": "Iasi" + }, + "coordinates": { + "latitude": 47.164306104, + "longitude": 27.564772222 + } + }, + { + "id": 1662713856, + "name": "Ilfov", + "translations": { + "japanese": "イルホヴ州", + "english": "Ilfov", + "french": "Ilfov", + "german": "Ilfov", + "italian": "Ilfov", + "spanish": "Ilfov", + "chinese_simple": "伊尔福夫县", + "korean": "일포브 주", + "dutch": "Ilfov", + "portuguese": "Ilfov", + "russian": "Илфов", + "chinese_traditional": "Ilfov", + "unknown1": "Ilfov", + "unknown2": "Ilfov", + "unknown3": "Ilfov", + "unknown4": "Ilfov" + }, + "coordinates": { + "latitude": 44.566039532, + "longitude": 25.949777596 + } + }, + { + "id": 1662779392, + "name": "Maramures", + "translations": { + "japanese": "マラムレシュ州", + "english": "Maramures", + "french": "Maramureş", + "german": "Maramureş", + "italian": "Maramureş", + "spanish": "Maramureş", + "chinese_simple": "马拉穆列什县", + "korean": "마라무레슈 주", + "dutch": "Maramureş", + "portuguese": "Maramures", + "russian": "Марамуреш", + "chinese_traditional": "Maramures", + "unknown1": "Maramures", + "unknown2": "Maramures", + "unknown3": "Maramures", + "unknown4": "Maramures" + }, + "coordinates": { + "latitude": 47.647704536, + "longitude": 23.582217447 + } + }, + { + "id": 1662844928, + "name": "Mehedinti", + "translations": { + "japanese": "メヘディンツィ州", + "english": "Mehedinti", + "french": "Mehedinti", + "german": "Mehedinti", + "italian": "Mehedinti", + "spanish": "Mehedinti", + "chinese_simple": "梅赫丁茨县", + "korean": "메헤딘치 주", + "dutch": "Mehedinti", + "portuguese": "Mehedinti", + "russian": "Мехединци", + "chinese_traditional": "Mehedinti", + "unknown1": "Mehedinti", + "unknown2": "Mehedinti", + "unknown3": "Mehedinti", + "unknown4": "Mehedinti" + }, + "coordinates": { + "latitude": 44.6319575, + "longitude": 22.648377017 + } + }, + { + "id": 1662910464, + "name": "Mures", + "translations": { + "japanese": "ムレシュ州", + "english": "Mures", + "french": "Mureş", + "german": "Mureş", + "italian": "Mureş", + "spanish": "Mureş", + "chinese_simple": "穆列什县", + "korean": "무레슈 주", + "dutch": "Mureş", + "portuguese": "Mures", + "russian": "Муреш", + "chinese_traditional": "Mures", + "unknown1": "Mures", + "unknown2": "Mures", + "unknown3": "Mures", + "unknown4": "Mures" + }, + "coordinates": { + "latitude": 46.538085408, + "longitude": 24.549016951 + } + }, + { + "id": 1662976000, + "name": "Neamt", + "translations": { + "japanese": "ネアムツ州", + "english": "Neamt", + "french": "Neamt", + "german": "Neamt", + "italian": "Neamt", + "spanish": "Neamt", + "chinese_simple": "尼亚姆茨县", + "korean": "네암츠 주", + "dutch": "Neamt", + "portuguese": "Neamt", + "russian": "Нямц", + "chinese_traditional": "Neamt", + "unknown1": "Neamt", + "unknown2": "Neamt", + "unknown3": "Neamt", + "unknown4": "Neamt" + }, + "coordinates": { + "latitude": 46.928100052, + "longitude": 26.361766021 + } + }, + { + "id": 1663041536, + "name": "Olt", + "translations": { + "japanese": "オルト州", + "english": "Olt", + "french": "Olt", + "german": "Olt", + "italian": "Olt", + "spanish": "Olt", + "chinese_simple": "奥尔特县", + "korean": "올트 주", + "dutch": "Olt", + "portuguese": "Olt", + "russian": "Олт", + "chinese_traditional": "Olt", + "unknown1": "Olt", + "unknown2": "Olt", + "unknown3": "Olt", + "unknown4": "Olt" + }, + "coordinates": { + "latitude": 44.428710432, + "longitude": 24.345769328 + } + }, + { + "id": 1663107072, + "name": "Prahova", + "translations": { + "japanese": "プラホヴァ州", + "english": "Prahova", + "french": "Prahova", + "german": "Prahova", + "italian": "Prahova", + "spanish": "Prahova", + "chinese_simple": "普拉霍瓦县", + "korean": "프라호바 주", + "dutch": "Prahova", + "portuguese": "Prahova", + "russian": "Прахова", + "chinese_traditional": "Prahova", + "unknown1": "Prahova", + "unknown2": "Prahova", + "unknown3": "Prahova", + "unknown4": "Prahova" + }, + "coordinates": { + "latitude": 44.928588356, + "longitude": 26.015695744 + } + }, + { + "id": 1663172608, + "name": "Salaj", + "translations": { + "japanese": "サラージュ州", + "english": "Salaj", + "french": "Sălaj", + "german": "Sălaj", + "italian": "Sălaj", + "spanish": "Sălaj", + "chinese_simple": "瑟拉日县", + "korean": "설라지 주", + "dutch": "Sălaj", + "portuguese": "Salaj", + "russian": "Сэлаж", + "chinese_traditional": "Salaj", + "unknown1": "Salaj", + "unknown2": "Salaj", + "unknown3": "Salaj", + "unknown4": "Salaj" + }, + "coordinates": { + "latitude": 47.180785596, + "longitude": 23.054872263 + } + }, + { + "id": 1663238144, + "name": "Satu Mare", + "translations": { + "japanese": "サトゥ・マーレ州", + "english": "Satu Mare", + "french": "Satu Mare", + "german": "Satu Mare", + "italian": "Satu Mare", + "spanish": "Satu Mare", + "chinese_simple": "萨图-马雷县", + "korean": "사투마레 주", + "dutch": "Satu Mare", + "portuguese": "Satu Mare", + "russian": "Сату-Маре", + "chinese_traditional": "Satu Mare", + "unknown1": "Satu Mare", + "unknown2": "Satu Mare", + "unknown3": "Satu Mare", + "unknown4": "Satu Mare" + }, + "coordinates": { + "latitude": 47.785033636, + "longitude": 22.879090535 + } + }, + { + "id": 1663303680, + "name": "Sibiu", + "translations": { + "japanese": "シビウ州", + "english": "Sibiu", + "french": "Sibiu", + "german": "Sibiu", + "italian": "Sibiu", + "spanish": "Sibiu", + "chinese_simple": "锡比乌县", + "korean": "시비우 주", + "dutch": "Sibiu", + "portuguese": "Sibiu", + "russian": "Сибиу", + "chinese_traditional": "Sibiu", + "unknown1": "Sibiu", + "unknown2": "Sibiu", + "unknown3": "Sibiu", + "unknown4": "Sibiu" + }, + "coordinates": { + "latitude": 45.780028776, + "longitude": 24.148014884 + } + }, + { + "id": 1663369216, + "name": "Suceava", + "translations": { + "japanese": "スチャヴァ州", + "english": "Suceava", + "french": "Suceava", + "german": "Suceava", + "italian": "Suceava", + "spanish": "Suceava", + "chinese_simple": "苏恰瓦县", + "korean": "수체아바 주", + "dutch": "Suceava", + "portuguese": "Suceava", + "russian": "Сучава", + "chinese_traditional": "Suceava", + "unknown1": "Suceava", + "unknown2": "Suceava", + "unknown3": "Suceava", + "unknown4": "Suceava" + }, + "coordinates": { + "latitude": 47.647704536, + "longitude": 26.246409262 + } + }, + { + "id": 1663434752, + "name": "Teleorman", + "translations": { + "japanese": "テレオルマン州", + "english": "Teleorman", + "french": "Teleorman", + "german": "Teleorman", + "italian": "Teleorman", + "spanish": "Teleorman", + "chinese_simple": "特列奥尔曼县", + "korean": "텔레오르만 주", + "dutch": "Teleorman", + "portuguese": "Teleorman", + "russian": "Телеорман", + "chinese_traditional": "Teleorman", + "unknown1": "Teleorman", + "unknown2": "Teleorman", + "unknown3": "Teleorman", + "unknown4": "Teleorman" + }, + "coordinates": { + "latitude": 43.961791492, + "longitude": 25.329048369 + } + }, + { + "id": 1663500288, + "name": "Timis", + "translations": { + "japanese": "ティミシュ州", + "english": "Timis", + "french": "Timiş", + "german": "Timiş", + "italian": "Timiş", + "spanish": "Timiş", + "chinese_simple": "蒂米什县", + "korean": "티미슈 주", + "dutch": "Timiş", + "portuguese": "Timis", + "russian": "Тимиш", + "chinese_traditional": "Timis", + "unknown1": "Timis", + "unknown2": "Timis", + "unknown3": "Timis", + "unknown4": "Timis" + }, + "coordinates": { + "latitude": 45.752562956, + "longitude": 21.220150477 + } + }, + { + "id": 1663565824, + "name": "Tulcea", + "translations": { + "japanese": "トゥルチャ州", + "english": "Tulcea", + "french": "Tulcea", + "german": "Tulcea", + "italian": "Tulcea", + "spanish": "Tulcea", + "chinese_simple": "图尔恰县", + "korean": "툴체아 주", + "dutch": "Tulcea", + "portuguese": "Tulcea", + "russian": "Тулча", + "chinese_traditional": "Tulcea", + "unknown1": "Tulcea", + "unknown2": "Tulcea", + "unknown3": "Tulcea", + "unknown4": "Tulcea" + }, + "coordinates": { + "latitude": 45.164794408, + "longitude": 28.795244317999998 + } + }, + { + "id": 1663631360, + "name": "Vâlcea", + "translations": { + "japanese": "ヴルチャ州", + "english": "Vâlcea", + "french": "Vâlcea", + "german": "Vâlcea", + "italian": "Vâlcea", + "spanish": "Vâlcea", + "chinese_simple": "沃尔恰县", + "korean": "블체아 주", + "dutch": "Vâlcea", + "portuguese": "Vâlcea", + "russian": "Вылча", + "chinese_traditional": "Vâlcea", + "unknown1": "Vâlcea", + "unknown2": "Vâlcea", + "unknown3": "Vâlcea", + "unknown4": "Vâlcea" + }, + "coordinates": { + "latitude": 45.104369604, + "longitude": 24.373235223 + } + }, + { + "id": 1663696896, + "name": "Vaslui", + "translations": { + "japanese": "ヴァスルイ州", + "english": "Vaslui", + "french": "Vaslui", + "german": "Vaslui", + "italian": "Vaslui", + "spanish": "Vaslui", + "chinese_simple": "瓦斯卢伊县", + "korean": "바슬루이 주", + "dutch": "Vaslui", + "portuguese": "Vaslui", + "russian": "Васлуй", + "chinese_traditional": "Vaslui", + "unknown1": "Vaslui", + "unknown2": "Vaslui", + "unknown3": "Vaslui", + "unknown4": "Vaslui" + }, + "coordinates": { + "latitude": 46.63696236, + "longitude": 27.718581234 + } + }, + { + "id": 1663762432, + "name": "Vrancea", + "translations": { + "japanese": "フランチェア州", + "english": "Vrancea", + "french": "Vrancea", + "german": "Vrancea", + "italian": "Vrancea", + "spanish": "Vrancea", + "chinese_simple": "弗朗恰县", + "korean": "브란체아 주", + "dutch": "Vrancea", + "portuguese": "Vrancea", + "russian": "Вранча", + "chinese_traditional": "Vrancea", + "unknown1": "Vrancea", + "unknown2": "Vrancea", + "unknown3": "Vrancea", + "unknown4": "Vrancea" + }, + "coordinates": { + "latitude": 45.697631316, + "longitude": 27.180249692 + } + } + ] + }, + { + "id": 100, + "iso_code": "RU", + "name": "Russia", + "translations": { + "japanese": "ロシア", + "english": "Russia", + "french": "Russie", + "german": "Russland", + "italian": "Russia", + "spanish": "Rusia", + "chinese_simple": "俄罗斯", + "korean": "러시아", + "dutch": "Rusland", + "portuguese": "Rússia", + "russian": "Россия", + "chinese_traditional": "Russia", + "unknown1": "Russia", + "unknown2": "Russia", + "unknown3": "Russia", + "unknown4": "Russia" + }, + "regions": [ + { + "id": 1677721600, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 55.766600928, + "longitude": 37.611796613 + } + }, + { + "id": 1678311424, + "name": "Moscow City", + "translations": { + "japanese": "モスクワ市", + "english": "Moscow City", + "french": "Moscou (ville)", + "german": "Moskau (Stadt)", + "italian": "Mosca", + "spanish": "Ciudad de Moscú", + "chinese_simple": "莫斯科市", + "korean": "모스크바", + "dutch": "Moskou (stad)", + "portuguese": "Moscovo (cidade)", + "russian": "Москва", + "chinese_traditional": "Moscow City", + "unknown1": "Moscow City", + "unknown2": "Moscow City", + "unknown3": "Moscow City", + "unknown4": "Moscow City" + }, + "coordinates": { + "latitude": 55.766600928, + "longitude": 37.611796613 + } + }, + { + "id": 1678376960, + "name": "Adygey", + "translations": { + "japanese": "アディゲ共和国", + "english": "Adygey", + "french": "Adyguée", + "german": "Republik Adygeja", + "italian": "Repubblica di Adighezia", + "spanish": "República de Adigueya", + "chinese_simple": "阿迪格共和国", + "korean": "아디게야 공화국", + "dutch": "Adygië", + "portuguese": "Adiguésia (república)", + "russian": "Республика Адыгея", + "chinese_traditional": "Adygey", + "unknown1": "Adygey", + "unknown2": "Adygey", + "unknown3": "Adygey", + "unknown4": "Adygey" + }, + "coordinates": { + "latitude": 44.598998516, + "longitude": 40.078233984 + } + }, + { + "id": 1678442496, + "name": "Gorno-Altay", + "translations": { + "japanese": "アルタイ共和国", + "english": "Gorno-Altay", + "french": "Altaï (république)", + "german": "Republik Altai", + "italian": "Repubblica dell'Altaj", + "spanish": "República de Altái", + "chinese_simple": "阿尔泰共和国", + "korean": "고르노알타이 공화국", + "dutch": "Altaj (republiek)", + "portuguese": "Altai (república)", + "russian": "Республика Алтай", + "chinese_traditional": "Gorno-Altay", + "unknown1": "Gorno-Altay", + "unknown2": "Gorno-Altay", + "unknown3": "Gorno-Altay", + "unknown4": "Gorno-Altay" + }, + "coordinates": { + "latitude": 51.948851948, + "longitude": 85.962758171 + } + }, + { + "id": 1678508032, + "name": "Altay", + "translations": { + "japanese": "アルタイ地方", + "english": "Altay", + "french": "Altaï (kraï)", + "german": "Region Altai", + "italian": "Territorio dell'Altaj", + "spanish": "Territorio de Altái", + "chinese_simple": "阿尔泰边疆区", + "korean": "알타이 지방", + "dutch": "Altaj (kraj)", + "portuguese": "Altai (território)", + "russian": "Алтайский край", + "chinese_traditional": "Altay", + "unknown1": "Altay", + "unknown2": "Altay", + "unknown3": "Altay", + "unknown4": "Altay" + }, + "coordinates": { + "latitude": 53.349608768, + "longitude": 83.749007034 + } + }, + { + "id": 1678573568, + "name": "Amur", + "translations": { + "japanese": "アムール州", + "english": "Amur", + "french": "Amour", + "german": "Oblast Amur", + "italian": "Regione dell'Amur", + "spanish": "Región de Amur", + "chinese_simple": "阿穆尔州", + "korean": "아무르 주", + "dutch": "Amoer", + "portuguese": "Amur (região)", + "russian": "Амурская область", + "chinese_traditional": "Amur", + "unknown1": "Amur", + "unknown2": "Amur", + "unknown3": "Amur", + "unknown4": "Amur" + }, + "coordinates": { + "latitude": 50.361327552, + "longitude": 127.513164127 + } + }, + { + "id": 1678639104, + "name": "Arkhangel'sk", + "translations": { + "japanese": "アルハンゲリスク州", + "english": "Arkhangel'sk", + "french": "Arkhangelsk", + "german": "Oblast Archangelsk", + "italian": "Regione di Arcangelo", + "spanish": "Región de Arjánguelsk", + "chinese_simple": "阿尔汉格尔斯克州", + "korean": "아르한겔스크 주", + "dutch": "Archangelsk", + "portuguese": "Arkhangelsk (região)", + "russian": "Архангельская область", + "chinese_traditional": "Arkhangel'sk", + "unknown1": "Arkhangel'sk", + "unknown2": "Arkhangel'sk", + "unknown3": "Arkhangel'sk", + "unknown4": "Arkhangel'sk" + }, + "coordinates": { + "latitude": 64.528197508, + "longitude": 40.528674662 + } + }, + { + "id": 1678704640, + "name": "Astrakhan'", + "translations": { + "japanese": "アストラハン州", + "english": "Astrakhan'", + "french": "Astrakhan", + "german": "Oblast Astrachan", + "italian": "Regione di Astrachan'", + "spanish": "Región de Astracán", + "chinese_simple": "阿斯特拉罕州", + "korean": "아스트라한 주", + "dutch": "Astrachan", + "portuguese": "Astracã (região)", + "russian": "Астраханская область", + "chinese_traditional": "Astrakhan'", + "unknown1": "Astrakhan'", + "unknown2": "Astrakhan'", + "unknown3": "Astrakhan'", + "unknown4": "Astrakhan'" + }, + "coordinates": { + "latitude": 46.345824668, + "longitude": 48.048836713 + } + }, + { + "id": 1678770176, + "name": "Bashkortostan", + "translations": { + "japanese": "バシコルトスタン共和国", + "english": "Bashkortostan", + "french": "Bachkirie", + "german": "Republik Baschkortostan", + "italian": "Repubblica del Baškortostan", + "spanish": "República de Baskortostán", + "chinese_simple": "巴什科尔托斯坦共和国", + "korean": "바시키르 공화국", + "dutch": "Basjkirostan", + "portuguese": "Basquíria (república)", + "russian": "Республика Башкортостан", + "chinese_traditional": "Bashkortostan", + "unknown1": "Bashkortostan", + "unknown2": "Bashkortostan", + "unknown3": "Bashkortostan", + "unknown4": "Bashkortostan" + }, + "coordinates": { + "latitude": 54.744872424, + "longitude": 55.964507652 + } + }, + { + "id": 1678835712, + "name": "Belgorod", + "translations": { + "japanese": "ベルゴロド州", + "english": "Belgorod", + "french": "Belgorod", + "german": "Oblast Belgorod", + "italian": "Regione di Belgorod", + "spanish": "Región de Bélgorod", + "chinese_simple": "别尔哥罗德州", + "korean": "벨고로트 주", + "dutch": "Belgorod", + "portuguese": "Belgorod (região)", + "russian": "Белгородская область", + "chinese_traditional": "Belgorod", + "unknown1": "Belgorod", + "unknown2": "Belgorod", + "unknown3": "Belgorod", + "unknown4": "Belgorod" + }, + "coordinates": { + "latitude": 50.597533604, + "longitude": 36.595558498 + } + }, + { + "id": 1678901248, + "name": "Bryansk", + "translations": { + "japanese": "ブリャンスク州", + "english": "Bryansk", + "french": "Briansk", + "german": "Oblast Brjansk", + "italian": "Regione di Brjansk", + "spanish": "Región de Briansk", + "chinese_simple": "布良斯克州", + "korean": "브랸스크 주", + "dutch": "Brjansk", + "portuguese": "Briansk (região)", + "russian": "Брянская область", + "chinese_traditional": "Bryansk", + "unknown1": "Bryansk", + "unknown2": "Bryansk", + "unknown3": "Bryansk", + "unknown4": "Bryansk" + }, + "coordinates": { + "latitude": 53.245238652, + "longitude": 34.365327824 + } + }, + { + "id": 1678966784, + "name": "Buryat", + "translations": { + "japanese": "ブリヤート共和国", + "english": "Buryat", + "french": "Bouriatie", + "german": "Republik Burjatien", + "italian": "Repubblica di Buriazia", + "spanish": "República de Buriatia", + "chinese_simple": "布里亚特共和国", + "korean": "부랴트 공화국", + "dutch": "Boerjatië", + "portuguese": "Buriácia (república)", + "russian": "Республика Бурятия", + "chinese_traditional": "Buryat", + "unknown1": "Buryat", + "unknown2": "Buryat", + "unknown3": "Buryat", + "unknown4": "Buryat" + }, + "coordinates": { + "latitude": 51.82800234, + "longitude": 107.594897073 + } + }, + { + "id": 1679032320, + "name": "Chechnya", + "translations": { + "japanese": "チェチェン共和国", + "english": "Chechnya", + "french": "Tchétchénie", + "german": "Republik Tschetschenien", + "italian": "Repubblica Cecena", + "spanish": "República de Chechenia", + "chinese_simple": "车臣共和国", + "korean": "체첸 공화국", + "dutch": "Tsjetsjenië", + "portuguese": "Chechénia (república)", + "russian": "Чеченская республика", + "chinese_traditional": "Chechnya", + "unknown1": "Chechnya", + "unknown2": "Chechnya", + "unknown3": "Chechnya", + "unknown4": "Chechnya" + }, + "coordinates": { + "latitude": 43.31359814, + "longitude": 45.681276564 + } + }, + { + "id": 1679097856, + "name": "Chelyabinsk", + "translations": { + "japanese": "チェリャビンスク州", + "english": "Chelyabinsk", + "french": "Tcheliabinsk", + "german": "Oblast Tscheljabinsk", + "italian": "Regione di Čeljabinsk", + "spanish": "Región de Cheliábinsk", + "chinese_simple": "车里雅宾斯克州", + "korean": "첼랴빈스크 주", + "dutch": "Tsjeljabinsk", + "portuguese": "Chelyabinsk (região)", + "russian": "Челябинская область", + "chinese_traditional": "Chelyabinsk", + "unknown1": "Chelyabinsk", + "unknown2": "Chelyabinsk", + "unknown3": "Chelyabinsk", + "unknown4": "Chelyabinsk" + }, + "coordinates": { + "latitude": 55.162352888, + "longitude": 61.397261682999996 + } + }, + { + "id": 1679163392, + "name": "Chukot", + "translations": { + "japanese": "チュクチ自治管区", + "english": "Chukot", + "french": "Tchoukotka", + "german": "Autonomer Kreis der Tschuktschen", + "italian": "Circondario Autonomo di Čukotka", + "spanish": "Distrito autónomo de Chukotka", + "chinese_simple": "楚科奇自治区", + "korean": "축치 자치구", + "dutch": "Tsjoekotka", + "portuguese": "Chukotka (distrito)", + "russian": "Чукотский автономный округ", + "chinese_traditional": "Chukot", + "unknown1": "Chukot", + "unknown2": "Chukot", + "unknown3": "Chukot", + "unknown4": "Chukot" + }, + "coordinates": { + "latitude": 64.731444576, + "longitude": 177.512079385 + } + }, + { + "id": 1679228928, + "name": "Chuvash", + "translations": { + "japanese": "チュヴァシ共和国", + "english": "Chuvash", + "french": "Tchouvachie", + "german": "Republik Tschuwaschien", + "italian": "Repubblica Ciuvascia", + "spanish": "República de Chuvasia", + "chinese_simple": "楚瓦什共和国", + "korean": "추바시 공화국", + "dutch": "Tsjoevasjië", + "portuguese": "Chuváchia (república)", + "russian": "Чувашская республика", + "chinese_traditional": "Chuvash", + "unknown1": "Chuvash", + "unknown2": "Chuvash", + "unknown3": "Chuvash", + "unknown4": "Chuvash" + }, + "coordinates": { + "latitude": 56.129149752000004, + "longitude": 47.230353042 + } + }, + { + "id": 1679294464, + "name": "Dagestan", + "translations": { + "japanese": "ダゲスタン共和国", + "english": "Dagestan", + "french": "Daguestan", + "german": "Republik Dagestan", + "italian": "Repubblica del Dagestan", + "spanish": "República de Daguestán", + "chinese_simple": "达吉斯坦共和国", + "korean": "다게스탄 공화국", + "dutch": "Dagestan", + "portuguese": "Daguestão (república)", + "russian": "Республика Дагестан", + "chinese_traditional": "Dagestan", + "unknown1": "Dagestan", + "unknown2": "Dagestan", + "unknown3": "Dagestan", + "unknown4": "Dagestan" + }, + "coordinates": { + "latitude": 42.962035644000004, + "longitude": 47.499518813 + } + }, + { + "id": 1679360000, + "name": "Ingushetia", + "translations": { + "japanese": "イングーシ共和国", + "english": "Ingushetia", + "french": "Ingouchie", + "german": "Republik Inguschetien", + "italian": "Repubblica di Inguscezia", + "spanish": "República de Ingusetia", + "chinese_simple": "印古什共和国", + "korean": "인구시 공화국", + "dutch": "Ingoesjetië", + "portuguese": "Ingúchia (república)", + "russian": "Республика Ингушетия", + "chinese_traditional": "Ingushetia", + "unknown1": "Ingushetia", + "unknown2": "Ingushetia", + "unknown3": "Ingushetia", + "unknown4": "Ingushetia" + }, + "coordinates": { + "latitude": 43.165282712, + "longitude": 44.813354282 + } + }, + { + "id": 1679425536, + "name": "Irkutsk", + "translations": { + "japanese": "イルクーツク州", + "english": "Irkutsk", + "french": "Irkoutsk", + "german": "Oblast Irkutsk", + "italian": "Regione di Irkutsk", + "spanish": "Región de Irkutsk", + "chinese_simple": "伊尔库茨克州", + "korean": "이르쿠츠크 주", + "dutch": "Irkoetsk", + "portuguese": "Irkutsk (região)", + "russian": "Иркутская область", + "chinese_traditional": "Irkutsk", + "unknown1": "Irkutsk", + "unknown2": "Irkutsk", + "unknown3": "Irkutsk", + "unknown4": "Irkutsk" + }, + "coordinates": { + "latitude": 52.278441788, + "longitude": 104.298989673 + } + }, + { + "id": 1679491072, + "name": "Ivanovo", + "translations": { + "japanese": "イヴァノヴォ州", + "english": "Ivanovo", + "french": "Ivanovo", + "german": "Oblast Iwanowo", + "italian": "Regione di Ivanovo", + "spanish": "Región de Ivánovo", + "chinese_simple": "伊万诺沃州", + "korean": "이바노보 주", + "dutch": "Ivanovo", + "portuguese": "Ivanovo (região)", + "russian": "Ивановская область", + "chinese_traditional": "Ivanovo", + "unknown1": "Ivanovo", + "unknown2": "Ivanovo", + "unknown3": "Ivanovo", + "unknown4": "Ivanovo" + }, + "coordinates": { + "latitude": 56.9915765, + "longitude": 40.97911534 + } + }, + { + "id": 1679556608, + "name": "Kabardin-Balkar", + "translations": { + "japanese": "カバルダ・バルカル共和国", + "english": "Kabardin-Balkar", + "french": "Kabardino-Balkarie", + "german": "Republik Kabardino-Balkarien", + "italian": "Repubblica di Cabardino-Balcaria", + "spanish": "República de Kabardino-Balkaria", + "chinese_simple": "卡巴尔达-巴尔卡尔共和国", + "korean": "카바르디노발카르 공화국", + "dutch": "Kabardië-Balkarië", + "portuguese": "Cabárdia-Balcária (república)", + "russian": "Кабардино-Балкарская республика", + "chinese_traditional": "Kabardin-Balkar", + "unknown1": "Kabardin-Balkar", + "unknown2": "Kabardin-Balkar", + "unknown3": "Kabardin-Balkar", + "unknown4": "Kabardin-Balkar" + }, + "coordinates": { + "latitude": 43.47839306, + "longitude": 43.615841259999996 + } + }, + { + "id": 1679622144, + "name": "Kaliningrad", + "translations": { + "japanese": "カリーニングラード州", + "english": "Kaliningrad", + "french": "Kaliningrad", + "german": "Oblast Kaliningrad", + "italian": "Regione di Kaliningrad", + "spanish": "Región de Kaliningrado", + "chinese_simple": "加里宁格勒州", + "korean": "칼리닌그라드 주", + "dutch": "Kaliningrad", + "portuguese": "Kaliningrado (região)", + "russian": "Калининградская область", + "chinese_traditional": "Kaliningrad", + "unknown1": "Kaliningrad", + "unknown2": "Kaliningrad", + "unknown3": "Kaliningrad", + "unknown4": "Kaliningrad" + }, + "coordinates": { + "latitude": 54.711913440000004, + "longitude": 20.511530386 + } + }, + { + "id": 1679687680, + "name": "Kalmyk", + "translations": { + "japanese": "カルムイク共和国", + "english": "Kalmyk", + "french": "Kalmoukie", + "german": "Republik Kalmückien", + "italian": "Repubblica di Calmucchia", + "spanish": "República de Kalmukia", + "chinese_simple": "卡尔梅克共和国", + "korean": "칼미크 공화국", + "dutch": "Kalmukkië", + "portuguese": "Calmúquia (república)", + "russian": "Республика Калмыкия", + "chinese_traditional": "Kalmyk", + "unknown1": "Kalmyk", + "unknown2": "Kalmyk", + "unknown3": "Kalmyk", + "unknown4": "Kalmyk" + }, + "coordinates": { + "latitude": 46.312865684, + "longitude": 44.264036382 + } + }, + { + "id": 1679753216, + "name": "Kaluga", + "translations": { + "japanese": "カルーガ州", + "english": "Kaluga", + "french": "Kalouga", + "german": "Oblast Kaluga", + "italian": "Regione di Kaluga", + "spanish": "Región de Kaluga", + "chinese_simple": "卡卢加州", + "korean": "칼루가 주", + "dutch": "Kaloega", + "portuguese": "Kaluga (região)", + "russian": "Калужская область", + "chinese_traditional": "Kaluga", + "unknown1": "Kaluga", + "unknown2": "Kaluga", + "unknown3": "Kaluga", + "unknown4": "Kaluga" + }, + "coordinates": { + "latitude": 54.54711852, + "longitude": 36.282447295 + } + }, + { + "id": 1679818752, + "name": "Kamchatka", + "translations": { + "japanese": "カムチャツカ地方", + "english": "Kamchatka", + "french": "Kamtchatka", + "german": "Region Kamtschatka", + "italian": "Territorio della Kamčatka", + "spanish": "Territorio de Kamchatka", + "chinese_simple": "勘察加边疆区", + "korean": "캄차카 지방", + "dutch": "Kamtsjatka", + "portuguese": "Kamchatka (território)", + "russian": "Камчатский край", + "chinese_traditional": "Kamchatka", + "unknown1": "Kamchatka", + "unknown2": "Kamchatka", + "unknown3": "Kamchatka", + "unknown4": "Kamchatka" + }, + "coordinates": { + "latitude": 53.014525764, + "longitude": 158.648502699 + } + }, + { + "id": 1679884288, + "name": "Karachay-Cherkess", + "translations": { + "japanese": "カラチャイ・チェルケス共和国", + "english": "Karachay-Cherkess", + "french": "Karatchaïévo-Tcherkessie", + "german": "Republik Karatschai-Tscherkessien", + "italian": "Repubblica Karačajevo-Čerkessia", + "spanish": "República de Karacháyevo-Cherkesia", + "chinese_simple": "卡拉恰耶夫-切尔克斯共和国", + "korean": "카라차예보체르케스카야 공화국", + "dutch": "Karatsjaj-Tsjerkessië", + "portuguese": "Karachay-Cherkess (república)", + "russian": "Карачаево-Черкесская республика", + "chinese_traditional": "Karachay-Cherkess", + "unknown1": "Karachay-Cherkess", + "unknown2": "Karachay-Cherkess", + "unknown3": "Karachay-Cherkess", + "unknown4": "Karachay-Cherkess" + }, + "coordinates": { + "latitude": 44.214477036, + "longitude": 42.044792066 + } + }, + { + "id": 1679949824, + "name": "Karelia", + "translations": { + "japanese": "カレリア共和国", + "english": "Karelia", + "french": "Carélie", + "german": "Republik Karelien", + "italian": "씒⭤ꥠ軷bblica di Carelia", + "spanish": "República de Carelia", + "chinese_simple": "卡累利阿共和国", + "korean": "카렐리야 공화국", + "dutch": "Karelië", + "portuguese": "Carélia (república)", + "russian": "Республика Карелия", + "chinese_traditional": "Karelia", + "unknown1": "Karelia", + "unknown2": "Karelia", + "unknown3": "Karelia", + "unknown4": "Karelia" + }, + "coordinates": { + "latitude": 61.781615508, + "longitude": 34.33236875 + } + }, + { + "id": 1680015360, + "name": "Kemerovo", + "translations": { + "japanese": "ケメロヴォ州", + "english": "Kemerovo", + "french": "Kemerovo", + "german": "Oblast Kemerowo", + "italian": "Regione di Kemerovo", + "spanish": "Región de Kémerovo", + "chinese_simple": "克麦罗沃州", + "korean": "케메로보 주", + "dutch": "Kemerovo", + "portuguese": "Kemerovo (região)", + "russian": "Кемеровская область", + "chinese_traditional": "Kemerovo", + "unknown1": "Kemerovo", + "unknown2": "Kemerovo", + "unknown3": "Kemerovo", + "unknown4": "Kemerovo" + }, + "coordinates": { + "latitude": 55.360106792, + "longitude": 86.089101288 + } + }, + { + "id": 1680080896, + "name": "Khabarovsk", + "translations": { + "japanese": "ハバロフスク地方", + "english": "Khabarovsk", + "french": "Khabarovsk", + "german": "Region Chabarowsk", + "italian": "Territorio di Chabarovsk", + "spanish": "Territorio de Jabárovsk", + "chinese_simple": "哈巴罗夫斯克边疆区", + "korean": "하바롭스크 지방", + "dutch": "Chabarovsk", + "portuguese": "Khabarovsk (território)", + "russian": "Хабаровский край", + "chinese_traditional": "Khabarovsk", + "unknown1": "Khabarovsk", + "unknown2": "Khabarovsk", + "unknown3": "Khabarovsk", + "unknown4": "Khabarovsk" + }, + "coordinates": { + "latitude": 48.482665464, + "longitude": 135.066285252 + } + }, + { + "id": 1680146432, + "name": "Khakassia", + "translations": { + "japanese": "ハカス共和国", + "english": "Khakassia", + "french": "Khakassie", + "german": "Republik Chakassien", + "italian": "Repubblica di Khakassia", + "spanish": "República de Jakasia", + "chinese_simple": "哈卡斯共和国", + "korean": "하카스 공화국", + "dutch": "Chakassië", + "portuguese": "Cacássia (república)", + "russian": "Республика Хакасия", + "chinese_traditional": "Khakassia", + "unknown1": "Khakassia", + "unknown2": "Khakassia", + "unknown3": "Khakassia", + "unknown4": "Khakassia" + }, + "coordinates": { + "latitude": 53.712157592, + "longitude": 91.411991739 + } + }, + { + "id": 1680211968, + "name": "Khanty-Mansiy", + "translations": { + "japanese": "ハンティ・マンシ自治管区", + "english": "Khanty-Mansiy", + "french": "Khantys-Mansis", + "german": "Autonomer Kreis der Chanten und Mansen", + "italian": "Circondario Autonomo di Chantia-Mansia", + "spanish": "Distrito autónomo de Janti-Mansi", + "chinese_simple": "汉特-曼西自治区", + "korean": "한티만시 자치구", + "dutch": "Chanto-Mansië", + "portuguese": "Khanty-Mansiy", + "russian": "Ханты-Мансийский автономный округ", + "chinese_traditional": "Khanty-Mansiy", + "unknown1": "Khanty-Mansiy", + "unknown2": "Khanty-Mansiy", + "unknown3": "Khanty-Mansiy", + "unknown4": "Khanty-Mansiy" + }, + "coordinates": { + "latitude": 60.996093056, + "longitude": 68.999821419 + } + }, + { + "id": 1680277504, + "name": "Kirov", + "translations": { + "japanese": "キーロフ州", + "english": "Kirov", + "french": "Kirov", + "german": "Oblast Kirow", + "italian": "Regione di Kirov", + "spanish": "Región de Kírov", + "chinese_simple": "基洛夫州", + "korean": "키로프 주", + "dutch": "Kírov", + "portuguese": "Kirov (região)", + "russian": "Кировская область", + "chinese_traditional": "Kirov", + "unknown1": "Kirov", + "unknown2": "Kirov", + "unknown3": "Kirov", + "unknown4": "Kirov" + }, + "coordinates": { + "latitude": 58.595580388, + "longitude": 49.647351802 + } + }, + { + "id": 1680343040, + "name": "Komi", + "translations": { + "japanese": "コミ共和国", + "english": "Komi", + "french": "Komis", + "german": "Republik Komi", + "italian": "Repubblica di Komi", + "spanish": "República de Komi", + "chinese_simple": "科米共和国", + "korean": "코미 공화국", + "dutch": "Komi", + "portuguese": "Komi (república)", + "russian": "Республика Коми", + "chinese_traditional": "Komi", + "unknown1": "Komi", + "unknown2": "Komi", + "unknown3": "Komi", + "unknown4": "Komi" + }, + "coordinates": { + "latitude": 61.666259064, + "longitude": 50.81190575 + } + }, + { + "id": 1680408576, + "name": "Kostroma", + "translations": { + "japanese": "コストロマ州", + "english": "Kostroma", + "french": "Kostroma", + "german": "Oblast Kostroma", + "italian": "Regione di Kostroma", + "spanish": "Región de Kostromá", + "chinese_simple": "科斯特罗马州", + "korean": "코스트로마 주", + "dutch": "Kostroma", + "portuguese": "Kostroma (região)", + "russian": "Костромская область", + "chinese_traditional": "Kostroma", + "unknown1": "Kostroma", + "unknown2": "Kostroma", + "unknown3": "Kostroma", + "unknown4": "Kostroma" + }, + "coordinates": { + "latitude": 57.766112624, + "longitude": 40.929676729 + } + }, + { + "id": 1680474112, + "name": "Krasnodar", + "translations": { + "japanese": "クラスノダール地方", + "english": "Krasnodar", + "french": "Krasnodar", + "german": "Region Krasnodar", + "italian": "Territorio di Krasnodar", + "spanish": "Territorio de Krasnodar", + "chinese_simple": "克拉斯诺达尔边疆区", + "korean": "크라스노다르 지방", + "dutch": "Krasnodar", + "portuguese": "Krasnodar (território)", + "russian": "Краснодарский край", + "chinese_traditional": "Krasnodar", + "unknown1": "Krasnodar", + "unknown2": "Krasnodar", + "unknown3": "Krasnodar", + "unknown4": "Krasnodar" + }, + "coordinates": { + "latitude": 45.032958472, + "longitude": 38.963118647 + } + }, + { + "id": 1680539648, + "name": "Krasnoyarsk", + "translations": { + "japanese": "クラスノヤルスク地方", + "english": "Krasnoyarsk", + "french": "Krasnoïarsk", + "german": "Region Krasnojarsk", + "italian": "Territorio di Krasnojarsk", + "spanish": "Territorio de Krasnoyarsk", + "chinese_simple": "克拉斯诺亚尔斯克边疆区", + "korean": "크라스노야르스크 지방", + "dutch": "Krasnojarsk", + "portuguese": "Krasnoyarsk (território)", + "russian": "Красноярский край", + "chinese_traditional": "Krasnoyarsk", + "unknown1": "Krasnoyarsk", + "unknown2": "Krasnoyarsk", + "unknown3": "Krasnoyarsk", + "unknown4": "Krasnoyarsk" + }, + "coordinates": { + "latitude": 55.997313816, + "longitude": 92.884163711 + } + }, + { + "id": 1680605184, + "name": "Kurgan", + "translations": { + "japanese": "クルガン州", + "english": "Kurgan", + "french": "Kourgan", + "german": "Oblast Kurgan", + "italian": "Regione di Kurgan", + "spanish": "Región de Kurgán", + "chinese_simple": "库尔干州", + "korean": "쿠르간 주", + "dutch": "Koergan", + "portuguese": "Kurgan (região)", + "russian": "Курганская область", + "chinese_traditional": "Kurgan", + "unknown1": "Kurgan", + "unknown2": "Kurgan", + "unknown3": "Kurgan", + "unknown4": "Kurgan" + }, + "coordinates": { + "latitude": 55.464476908, + "longitude": 65.346857384 + } + }, + { + "id": 1680670720, + "name": "Kursk", + "translations": { + "japanese": "クルスク州", + "english": "Kursk", + "french": "Koursk", + "german": "Oblast Kursk", + "italian": "Regione di Kursk", + "spanish": "Región de Kursk", + "chinese_simple": "库尔斯克州", + "korean": "쿠르스크 주", + "dutch": "Koersk", + "portuguese": "Kursk (região)", + "russian": "Курская область", + "chinese_traditional": "Kursk", + "unknown1": "Kursk", + "unknown2": "Kursk", + "unknown3": "Kursk", + "unknown4": "Kursk" + }, + "coordinates": { + "latitude": 51.712645896, + "longitude": 36.178076894 + } + }, + { + "id": 1680736256, + "name": "Leningrad", + "translations": { + "japanese": "レニングラード州", + "english": "Leningrad", + "french": "Léningrad", + "german": "Oblast Leningrad", + "italian": "Regione di Leningrado", + "spanish": "Región de Leningrado", + "chinese_simple": "列宁格勒州", + "korean": "레닌그라드 주", + "dutch": "Leningrad", + "portuguese": "Leninegrado (região)", + "russian": "Ленинградская область", + "chinese_traditional": "Leningrad", + "unknown1": "Leningrad", + "unknown2": "Leningrad", + "unknown3": "Leningrad", + "unknown4": "Leningrad" + }, + "coordinates": { + "latitude": 59.946898732, + "longitude": 30.311361722 + } + }, + { + "id": 1680801792, + "name": "Lipetsk", + "translations": { + "japanese": "リペツク州", + "english": "Lipetsk", + "french": "Lipetsk", + "german": "Oblast Lipezk", + "italian": "Regione di Lipeck", + "spanish": "Región de Lípetsk", + "chinese_simple": "利佩茨克州", + "korean": "리페츠크 주", + "dutch": "Lipetsk", + "portuguese": "Lipetsk (região)", + "russian": "Липецкая область", + "chinese_traditional": "Lipetsk", + "unknown1": "Lipetsk", + "unknown2": "Lipetsk", + "unknown3": "Lipetsk", + "unknown4": "Lipetsk" + }, + "coordinates": { + "latitude": 52.613524792, + "longitude": 39.594834232 + } + }, + { + "id": 1680867328, + "name": "Magadan", + "translations": { + "japanese": "マガダン州", + "english": "Magadan", + "french": "Magadan", + "german": "Oblast Magadan", + "italian": "Regione di Magadan", + "spanish": "Región de Magadán", + "chinese_simple": "马加丹州", + "korean": "마가단 주", + "dutch": "Magadan", + "portuguese": "Magadão (região)", + "russian": "Магаданская область", + "chinese_traditional": "Magadan", + "unknown1": "Magadan", + "unknown2": "Magadan", + "unknown3": "Magadan", + "unknown4": "Magadan" + }, + "coordinates": { + "latitude": 59.562377252, + "longitude": 150.798749908 + } + }, + { + "id": 1680932864, + "name": "Mariy-El", + "translations": { + "japanese": "マリ・エル共和国", + "english": "Mariy-El", + "french": "Maris", + "german": "Republik Mari El", + "italian": "Repubblica di Mari-El", + "spanish": "República de Mari-El", + "chinese_simple": "马里-埃尔共和国", + "korean": "마리옐 공화국", + "dutch": "Mari El", + "portuguese": "Mari El (república)", + "russian": "Республика Марий Эл", + "chinese_traditional": "Mariy-El", + "unknown1": "Mariy-El", + "unknown2": "Mariy-El", + "unknown3": "Mariy-El", + "unknown4": "Mariy-El" + }, + "coordinates": { + "latitude": 56.629027676, + "longitude": 47.862068627 + } + }, + { + "id": 1680998400, + "name": "Mordovia", + "translations": { + "japanese": "モルドヴィア共和国", + "english": "Mordovia", + "french": "Mordovie", + "german": "Republik Mordwinien", + "italian": "Repubblica di Mordovia", + "spanish": "República de Mordovia", + "chinese_simple": "莫尔多瓦社会主义共和国", + "korean": "모르도바 공화국", + "dutch": "Mordovië", + "portuguese": "Mordóvia (república)", + "russian": "Республика Мордовия", + "chinese_traditional": "Mordovia", + "unknown1": "Mordovia", + "unknown2": "Mordovia", + "unknown3": "Mordovia", + "unknown4": "Mordovia" + }, + "coordinates": { + "latitude": 54.179076532, + "longitude": 45.181397275 + } + }, + { + "id": 1681063936, + "name": "Moscow", + "translations": { + "japanese": "モスクワ州", + "english": "Moscow", + "french": "Moscou (oblast)", + "german": "Oblast Moskau", + "italian": "Regione di Mosca", + "spanish": "Región de Moscú", + "chinese_simple": "莫斯科州", + "korean": "모스크바 주", + "dutch": "Moskou (oblast)", + "portuguese": "Moscovo (região)", + "russian": "Московская область", + "chinese_traditional": "Moscow", + "unknown1": "Moscow", + "unknown2": "Moscow", + "unknown3": "Moscow", + "unknown4": "Moscow" + }, + "coordinates": { + "latitude": 55.766600928, + "longitude": 37.611796613 + } + }, + { + "id": 1681129472, + "name": "Murmansk", + "translations": { + "japanese": "ムルマンスク州", + "english": "Murmansk", + "french": "Mourmansk", + "german": "Oblast Murmansk", + "italian": "Regione di Murmansk", + "spanish": "Región de Múrmansk", + "chinese_simple": "摩尔曼斯克州", + "korean": "무르만스크 주", + "dutch": "Moermansk", + "portuguese": "Murmansk (região)", + "russian": "Мурманская область", + "chinese_traditional": "Murmansk", + "unknown1": "Murmansk", + "unknown2": "Murmansk", + "unknown3": "Murmansk", + "unknown4": "Murmansk" + }, + "coordinates": { + "latitude": 68.961180856, + "longitude": 33.079923938 + } + }, + { + "id": 1681195008, + "name": "Nenets", + "translations": { + "japanese": "ネネツ自治管区", + "english": "Nenets", + "french": "Nénétsie", + "german": "Autonomer Kreis der Nenzen", + "italian": "Circondario Autonomo di Nenec", + "spanish": "Distrito autónomo de Nenetsia", + "chinese_simple": "涅涅茨自治区", + "korean": "네네츠 자치구", + "dutch": "Nenetsië", + "portuguese": "Nenetsia (distrito)", + "russian": "Ненецкий автономный округ", + "chinese_traditional": "Nenets", + "unknown1": "Nenets", + "unknown2": "Nenets", + "unknown3": "Nenets", + "unknown4": "Nenets" + }, + "coordinates": { + "latitude": 67.631835168, + "longitude": 53.047629603 + } + }, + { + "id": 1681260544, + "name": "Nizhegorod", + "translations": { + "japanese": "ニジニ・ノヴゴロド州", + "english": "Nizhegorod", + "french": "Nijni Novgorod", + "german": "Oblast Nischni Nowgorod", + "italian": "Regione di Nižnij Novgorod", + "spanish": "Región de Nizhni Nóvgorod", + "chinese_simple": "下诺夫哥罗德州", + "korean": "니제고로드 주", + "dutch": "Nizjni Novgorod", + "portuguese": "Nizhegorod (região)", + "russian": "Нижегородская область", + "chinese_traditional": "Nizhegorod", + "unknown1": "Nizhegorod", + "unknown2": "Nizhegorod", + "unknown3": "Nizhegorod", + "unknown4": "Nizhegorod" + }, + "coordinates": { + "latitude": 56.33239682, + "longitude": 43.994870610999996 + } + }, + { + "id": 1681326080, + "name": "Novgorod", + "translations": { + "japanese": "ノヴゴロド州", + "english": "Novgorod", + "french": "Novgorod", + "german": "Oblast Nowgorod", + "italian": "Regione di Novgorod", + "spanish": "Región de Nóvgorod", + "chinese_simple": "诺夫哥罗德州", + "korean": "노브고로드 주", + "dutch": "Novgorod", + "portuguese": "Novgorod (região)", + "russian": "Новгородская область", + "chinese_traditional": "Novgorod", + "unknown1": "Novgorod", + "unknown2": "Novgorod", + "unknown3": "Novgorod", + "unknown4": "Novgorod" + }, + "coordinates": { + "latitude": 58.546141912, + "longitude": 31.278161225999998 + } + }, + { + "id": 1681391616, + "name": "Novosibirsk", + "translations": { + "japanese": "ノヴォシビルスク州", + "english": "Novosibirsk", + "french": "Novossibirsk", + "german": "Oblast Nowosibirsk", + "italian": "Regione di Novosibirsk", + "spanish": "Región de Novosibirsk", + "chinese_simple": "新西伯利亚州", + "korean": "노보시비르스크 주", + "dutch": "Novosibirsk", + "portuguese": "Novosibirsk (região)", + "russian": "Новосибирская область", + "chinese_traditional": "Novosibirsk", + "unknown1": "Novosibirsk", + "unknown2": "Novosibirsk", + "unknown3": "Novosibirsk", + "unknown4": "Novosibirsk" + }, + "coordinates": { + "latitude": 55.01403746, + "longitude": 82.930523363 + } + }, + { + "id": 1681457152, + "name": "Omsk", + "translations": { + "japanese": "オムスク州", + "english": "Omsk", + "french": "Omsk", + "german": "Oblast Omsk", + "italian": "Regione di Omsk", + "spanish": "Región de Omsk", + "chinese_simple": "鄂木斯克州", + "korean": "옴스크 주", + "dutch": "Omsk", + "portuguese": "Omsk (região)", + "russian": "Омская область", + "chinese_traditional": "Omsk", + "unknown1": "Omsk", + "unknown2": "Omsk", + "unknown3": "Omsk", + "unknown4": "Omsk" + }, + "coordinates": { + "latitude": 54.981078476, + "longitude": 73.361405545 + } + }, + { + "id": 1681522688, + "name": "Orenburg", + "translations": { + "japanese": "オレンブルク州", + "english": "Orenburg", + "french": "Orenbourg", + "german": "Oblast Orenburg", + "italian": "Regione di Orenburg", + "spanish": "Región de Oremburgo", + "chinese_simple": "奥伦堡州", + "korean": "오렌부르크 주", + "dutch": "Orenburg", + "portuguese": "Oremburgo (região)", + "russian": "Оренбургская область", + "chinese_traditional": "Orenburg", + "unknown1": "Orenburg", + "unknown2": "Orenburg", + "unknown3": "Orenburg", + "unknown4": "Orenburg" + }, + "coordinates": { + "latitude": 51.778563864, + "longitude": 55.09658537 + } + }, + { + "id": 1681588224, + "name": "Orel", + "translations": { + "japanese": "オリョール州", + "english": "Orel", + "french": "Orel", + "german": "Oblast Orjol", + "italian": "Regione di Orël", + "spanish": "Región de Oriol", + "chinese_simple": "奥廖尔州", + "korean": "오룔 주", + "dutch": "Orjol", + "portuguese": "Orel (região)", + "russian": "Орловская область", + "chinese_traditional": "Orel", + "unknown1": "Orel", + "unknown2": "Orel", + "unknown3": "Orel", + "unknown4": "Orel" + }, + "coordinates": { + "latitude": 52.965087288, + "longitude": 36.062720135 + } + }, + { + "id": 1681653760, + "name": "Penza", + "translations": { + "japanese": "ペンザ州", + "english": "Penza", + "french": "Penza", + "german": "Oblast Pensa", + "italian": "Regione di Penza", + "spanish": "Región de Penza", + "chinese_simple": "奔萨州", + "korean": "펜자 주", + "dutch": "Penza", + "portuguese": "Penza (região)", + "russian": "Пензенская область", + "chinese_traditional": "Penza", + "unknown1": "Penza", + "unknown2": "Penza", + "unknown3": "Penza", + "unknown4": "Penza" + }, + "coordinates": { + "latitude": 53.195800176, + "longitude": 45.016601905 + } + }, + { + "id": 1681719296, + "name": "Perm'", + "translations": { + "japanese": "ペルミ地方", + "english": "Perm'", + "french": "Perm", + "german": "Region Perm", + "italian": "Territorio di Perm'", + "spanish": "Territorio de Perm", + "chinese_simple": "彼尔姆边疆区", + "korean": "페름 지방", + "dutch": "Perm", + "portuguese": "Perm (território)", + "russian": "Пермский край", + "chinese_traditional": "Perm'", + "unknown1": "Perm'", + "unknown2": "Perm'", + "unknown3": "Perm'", + "unknown4": "Perm'" + }, + "coordinates": { + "latitude": 57.996825512, + "longitude": 56.316071108 + } + }, + { + "id": 1681784832, + "name": "Primor'ye", + "translations": { + "japanese": "沿海地方", + "english": "Primor'ye", + "french": "Primorie", + "german": "Region Primorje", + "italian": "Territorio del Litorale", + "spanish": "Territorio de Primorie", + "chinese_simple": "滨海边疆区", + "korean": "프리모르스키 지방", + "dutch": "Primorski", + "portuguese": "Primorie (território)", + "russian": "Приморский край", + "chinese_traditional": "Primor'ye", + "unknown1": "Primor'ye", + "unknown2": "Primor'ye", + "unknown3": "Primor'ye", + "unknown4": "Primor'ye" + }, + "coordinates": { + "latitude": 43.132323728, + "longitude": 131.896720969 + } + }, + { + "id": 1681850368, + "name": "Pskov", + "translations": { + "japanese": "プスコフ州", + "english": "Pskov", + "french": "Pskov", + "german": "Oblast Pskow", + "italian": "Regione di Pskov", + "spanish": "Región de Pskov", + "chinese_simple": "普斯科夫州", + "korean": "프스코프 부", + "dutch": "Pskov", + "portuguese": "Pskov (região)", + "russian": "Псковская область", + "chinese_traditional": "Pskov", + "unknown1": "Pskov", + "unknown2": "Pskov", + "unknown3": "Pskov", + "unknown4": "Pskov" + }, + "coordinates": { + "latitude": 57.8155511, + "longitude": 28.328324103 + } + }, + { + "id": 1681915904, + "name": "Rostov", + "translations": { + "japanese": "ロストフ州", + "english": "Rostov", + "french": "Rostov", + "german": "Oblast Rostow", + "italian": "Regione di Rostov", + "spanish": "Región de Rostov", + "chinese_simple": "罗斯托夫州", + "korean": "로스토프 주", + "dutch": "Rostov", + "portuguese": "Rostov (região)", + "russian": "Ростовская область", + "chinese_traditional": "Rostov", + "unknown1": "Rostov", + "unknown2": "Rostov", + "unknown3": "Rostov", + "unknown4": "Rostov" + }, + "coordinates": { + "latitude": 47.230224072, + "longitude": 39.699204633 + } + }, + { + "id": 1681981440, + "name": "Ryazan'", + "translations": { + "japanese": "リャザン州", + "english": "Ryazan'", + "french": "Riazan", + "german": "Oblast Rjasan", + "italian": "Regione di Rjazan'", + "spanish": "Región de Riazán", + "chinese_simple": "梁赞州", + "korean": "랴잔 주", + "dutch": "Rjazan", + "portuguese": "Riazan (região)", + "russian": "Рязанская область", + "chinese_traditional": "Ryazan'", + "unknown1": "Ryazan'", + "unknown2": "Ryazan'", + "unknown3": "Ryazan'", + "unknown4": "Ryazan'" + }, + "coordinates": { + "latitude": 54.596556996, + "longitude": 39.699204633 + } + }, + { + "id": 1682046976, + "name": "Sakha", + "translations": { + "japanese": "サハ共和国", + "english": "Sakha", + "french": "Sakha (Iakoutie)", + "german": "Republik Sacha (Jakutien)", + "italian": "Repubblica di Sacha (Jacuzia)", + "spanish": "República de Sajá (Yakutia)", + "chinese_simple": "萨哈共和国", + "korean": "사하 공화국", + "dutch": "Jakoetië", + "portuguese": "Iacútia (república)", + "russian": "Республика Саха (Якутия)", + "chinese_traditional": "Sakha", + "unknown1": "Sakha", + "unknown2": "Sakha", + "unknown3": "Sakha", + "unknown4": "Sakha" + }, + "coordinates": { + "latitude": 62.028807888, + "longitude": 129.732408443 + } + }, + { + "id": 1682112512, + "name": "Sakhalin", + "translations": { + "japanese": "サハリン州", + "english": "Sakhalin", + "french": "Sakhaline", + "german": "Oblast Sachalin", + "italian": "Regione di Sachalin", + "spanish": "Región de Sajalín", + "chinese_simple": "萨哈林州", + "korean": "사할린 주", + "dutch": "Sachalin", + "portuguese": "Sacalina (região)", + "russian": "Сахалинская область", + "chinese_traditional": "Sakhalin", + "unknown1": "Sakhalin", + "unknown2": "Sakhalin", + "unknown3": "Sakhalin", + "unknown4": "Sakhalin" + }, + "coordinates": { + "latitude": 50.218505288, + "longitude": 142.998435728 + } + }, + { + "id": 1682178048, + "name": "Samara", + "translations": { + "japanese": "サマラ州", + "english": "Samara", + "french": "Samara", + "german": "Oblast Samara", + "italian": "Regione di Samara", + "spanish": "Región de Samara", + "chinese_simple": "萨马拉州", + "korean": "사마라 주", + "dutch": "Samara", + "portuguese": "Samara (região)", + "russian": "Самарская область", + "chinese_traditional": "Samara", + "unknown1": "Samara", + "unknown2": "Samara", + "unknown3": "Samara", + "unknown4": "Samara" + }, + "coordinates": { + "latitude": 53.22875916, + "longitude": 50.163710628 + } + }, + { + "id": 1682243584, + "name": "St. Petersburg", + "translations": { + "japanese": "サンクトペテルブルク市", + "english": "St. Petersburg", + "french": "Saint-Pétersbourg", + "german": "Sankt Petersburg", + "italian": "San Pietroburgo", + "spanish": "San Petersburgo", + "chinese_simple": "圣彼得堡市", + "korean": "상트페테르부르크 주", + "dutch": "Sint-Petersburg", + "portuguese": "São Petersburgo", + "russian": "Санкт-Петербург", + "chinese_traditional": "St. Petersburg", + "unknown1": "St. Petersburg", + "unknown2": "St. Petersburg", + "unknown3": "St. Petersburg", + "unknown4": "St. Petersburg" + }, + "coordinates": { + "latitude": 59.946898732, + "longitude": 30.311361722 + } + }, + { + "id": 1682309120, + "name": "Saratov", + "translations": { + "japanese": "サラトフ州", + "english": "Saratov", + "french": "Saratov", + "german": "Oblast Saratow", + "italian": "Regione di Saratov", + "spanish": "Región de Sarátov", + "chinese_simple": "萨拉托夫州", + "korean": "사라토프 주", + "dutch": "Saratov", + "portuguese": "Saratov (região)", + "russian": "Саратовская область", + "chinese_traditional": "Saratov", + "unknown1": "Saratov", + "unknown2": "Saratov", + "unknown3": "Saratov", + "unknown4": "Saratov" + }, + "coordinates": { + "latitude": 51.531371484, + "longitude": 46.016360483 + } + }, + { + "id": 1682374656, + "name": "North Ossetia", + "translations": { + "japanese": "北オセチア共和国", + "english": "North Ossetia", + "french": "Ossétie-du-Nord-Alanie", + "german": "Republik Nordossetien-Alanien", + "italian": "Repubblica dell'Ossezia Settentrionale-Alania", + "spanish": "República de Osetia del Norte-Alania", + "chinese_simple": "北奥塞梯-阿兰社会主义共和国", + "korean": "북오세티야 공화국", + "dutch": "Noord-Ossetië", + "portuguese": "Ossétia-Alânia do Norte (república)", + "russian": "Республика Северная Осетия-Алания", + "chinese_traditional": "North Ossetia", + "unknown1": "North Ossetia", + "unknown2": "North Ossetia", + "unknown3": "North Ossetia", + "unknown4": "North Ossetia" + }, + "coordinates": { + "latitude": 43.01147412, + "longitude": 44.648558912 + } + }, + { + "id": 1682440192, + "name": "Smolensk", + "translations": { + "japanese": "スモレンスク州", + "english": "Smolensk", + "french": "Smolensk", + "german": "Oblast Smolensk", + "italian": "Regione di Smolensk", + "spanish": "Región de Smolensk", + "chinese_simple": "斯摩棱斯克州", + "korean": "스몰렌스크 주", + "dutch": "Smolensk", + "portuguese": "Smolensk (região)", + "russian": "Смоленская область", + "chinese_traditional": "Smolensk", + "unknown1": "Smolensk", + "unknown2": "Smolensk", + "unknown3": "Smolensk", + "unknown4": "Smolensk" + }, + "coordinates": { + "latitude": 54.783324572, + "longitude": 32.047206286 + } + }, + { + "id": 1682505728, + "name": "Stavropol'", + "translations": { + "japanese": "スタヴロポリ地方", + "english": "Stavropol'", + "french": "Stavropol", + "german": "Region Stawropol", + "italian": "Territorio di Stavropol'", + "spanish": "Territorio de Stávropol", + "chinese_simple": "斯塔夫罗波尔边疆区", + "korean": "스타브로폴 지방", + "dutch": "Stavropol", + "portuguese": "Stavropol (território)", + "russian": "Ставропольский край", + "chinese_traditional": "Stavropol'", + "unknown1": "Stavropol'", + "unknown2": "Stavropol'", + "unknown3": "Stavropol'", + "unknown4": "Stavropol'" + }, + "coordinates": { + "latitude": 45.049437964, + "longitude": 41.978873918 + } + }, + { + "id": 1682571264, + "name": "Sverdlovsk", + "translations": { + "japanese": "スヴェルドロフスク州", + "english": "Sverdlovsk", + "french": "Sverdlovsk", + "german": "Oblast Swerdlowsk", + "italian": "Regione di Sverdlovsk", + "spanish": "Región de Sverdlovsk", + "chinese_simple": "斯维尔德洛夫斯克州", + "korean": "스베르들롭스크 주", + "dutch": "Sverdlovsk", + "portuguese": "Sverdlovsk (região)", + "russian": "Свердловская область", + "chinese_traditional": "Sverdlovsk", + "unknown1": "Sverdlovsk", + "unknown2": "Sverdlovsk", + "unknown3": "Sverdlovsk", + "unknown4": "Sverdlovsk" + }, + "coordinates": { + "latitude": 56.832274744, + "longitude": 60.578778012 + } + }, + { + "id": 1682636800, + "name": "Tambov", + "translations": { + "japanese": "タンボフ州", + "english": "Tambov", + "french": "Tambov", + "german": "Oblast Tambow", + "italian": "Regione di Tambov", + "spanish": "Región de Tambov", + "chinese_simple": "坦波夫州", + "korean": "탐보프 주", + "dutch": "Tambov", + "portuguese": "Tambov (região)", + "russian": "Тамбовская область", + "chinese_traditional": "Tambov", + "unknown1": "Tambov", + "unknown2": "Tambov", + "unknown3": "Tambov", + "unknown4": "Tambov" + }, + "coordinates": { + "latitude": 52.712401744, + "longitude": 41.429556018 + } + }, + { + "id": 1682702336, + "name": "Tatarstan", + "translations": { + "japanese": "タタールスタン共和国", + "english": "Tatarstan", + "french": "Tatarstan", + "german": "Republik Tatarstan", + "italian": "Repubblica del Tatarstan", + "spanish": "República de Tartaristán", + "chinese_simple": "鞑靼斯坦共和国", + "korean": "타타르 공화국", + "dutch": "Tatarije", + "portuguese": "Tartária (república)", + "russian": "Республика Татарстан", + "chinese_traditional": "Tatarstan", + "unknown1": "Tatarstan", + "unknown2": "Tatarstan", + "unknown3": "Tatarstan", + "unknown4": "Tatarstan" + }, + "coordinates": { + "latitude": 55.78308042, + "longitude": 49.16395205 + } + }, + { + "id": 1682767872, + "name": "Tomsk", + "translations": { + "japanese": "トムスク州", + "english": "Tomsk", + "french": "Tomsk", + "german": "Oblast Tomsk", + "italian": "Regione di Tomsk", + "spanish": "Región de Tomsk", + "chinese_simple": "托木斯克州", + "korean": "톰스크 주", + "dutch": "Tomsk", + "portuguese": "Tomsk (região)", + "russian": "Томская область", + "chinese_traditional": "Tomsk", + "unknown1": "Tomsk", + "unknown2": "Tomsk", + "unknown3": "Tomsk", + "unknown4": "Tomsk" + }, + "coordinates": { + "latitude": 56.49719174, + "longitude": 84.96299959299999 + } + }, + { + "id": 1682833408, + "name": "Tula", + "translations": { + "japanese": "トゥーラ州", + "english": "Tula", + "french": "Toula", + "german": "Oblast Tula", + "italian": "Regione di Tula", + "spanish": "Región de Tula", + "chinese_simple": "图拉州", + "korean": "툴라 주", + "dutch": "Toela", + "portuguese": "Tula (região)", + "russian": "Тульская область", + "chinese_traditional": "Tula", + "unknown1": "Tula", + "unknown2": "Tula", + "unknown3": "Tula", + "unknown4": "Tula" + }, + "coordinates": { + "latitude": 54.195556024, + "longitude": 37.611796613 + } + }, + { + "id": 1682898944, + "name": "Tver'", + "translations": { + "japanese": "トヴェリ州", + "english": "Tver'", + "french": "Tver", + "german": "Oblast Twer", + "italian": "Regione di Tver", + "spanish": "Región de Tver", + "chinese_simple": "特维尔州", + "korean": "트베리 주", + "dutch": "Tver", + "portuguese": "Tver (região)", + "russian": "Тверская область", + "chinese_traditional": "Tver'", + "unknown1": "Tver'", + "unknown2": "Tver'", + "unknown3": "Tver'", + "unknown4": "Tver'" + }, + "coordinates": { + "latitude": 56.8542474, + "longitude": 35.914404302 + } + }, + { + "id": 1682964480, + "name": "Tyumen'", + "translations": { + "japanese": "チュメニ州", + "english": "Tyumen'", + "french": "Tioumen", + "german": "Oblast Tjumen", + "italian": "Regione di Tjumen'", + "spanish": "Región de Tiumén", + "chinese_simple": "秋明州", + "korean": "튜멘 주", + "dutch": "Tjoemen", + "portuguese": "Tiumen (região)", + "russian": "Тюменская область", + "chinese_traditional": "Tyumen'", + "unknown1": "Tyumen'", + "unknown2": "Tyumen'", + "unknown3": "Tyumen'", + "unknown4": "Tyumen'" + }, + "coordinates": { + "latitude": 57.145385092, + "longitude": 65.528132291 + } + }, + { + "id": 1683030016, + "name": "Tuva", + "translations": { + "japanese": "トゥヴァ共和国", + "english": "Tuva", + "french": "Touva", + "german": "Republik Tuwa", + "italian": "Repubblica di Tuva", + "spanish": "República de Tuvá", + "chinese_simple": "特瓦共和国", + "korean": "투바 공화국", + "dutch": "Toeva", + "portuguese": "Tuva (república)", + "russian": "Республика Тыва", + "chinese_traditional": "Tuva", + "unknown1": "Tuva", + "unknown2": "Tuva", + "unknown3": "Tuva", + "unknown4": "Tuva" + }, + "coordinates": { + "latitude": 51.712645896, + "longitude": 94.449719726 + } + }, + { + "id": 1683095552, + "name": "Udmurt", + "translations": { + "japanese": "ウドムルト共和国", + "english": "Udmurt", + "french": "Oudmourtie", + "german": "Republik Udmurtien", + "italian": "Repubblica Udmurta", + "spanish": "República de Udmurtia", + "chinese_simple": "乌德穆尔特共和国", + "korean": "우드무르트 공화국", + "dutch": "Oedmoertië", + "portuguese": "Udmúrtia (república)", + "russian": "Удмуртская республика", + "chinese_traditional": "Udmurt", + "unknown1": "Udmurt", + "unknown2": "Udmurt", + "unknown3": "Udmurt", + "unknown4": "Udmurt" + }, + "coordinates": { + "latitude": 56.832274744, + "longitude": 53.179465899 + } + }, + { + "id": 1683161088, + "name": "Ul'yanovsk", + "translations": { + "japanese": "ウリヤノフスク州", + "english": "Ul'yanovsk", + "french": "Oulianovsk", + "german": "Oblast Uljanowsk", + "italian": "Regione di Ul'janovsk", + "spanish": "Región de Uliánovsk", + "chinese_simple": "乌里扬诺夫斯克州", + "korean": "울리야놉스크 주", + "dutch": "Oeljanovsk", + "portuguese": "Ulianovsk (região)", + "russian": "Ульяновская область", + "chinese_traditional": "Ul'yanovsk", + "unknown1": "Ul'yanovsk", + "unknown2": "Ul'yanovsk", + "unknown3": "Ul'yanovsk", + "unknown4": "Ul'yanovsk" + }, + "coordinates": { + "latitude": 54.316405632, + "longitude": 48.361947916 + } + }, + { + "id": 1683226624, + "name": "Vladimir", + "translations": { + "japanese": "ヴラジーミル州", + "english": "Vladimir", + "french": "Vladimir", + "german": "Oblast Wladimir", + "italian": "Regione di Vladimir", + "spanish": "Región de Vladímir", + "chinese_simple": "弗拉基米尔州", + "korean": "블라디미르 주", + "dutch": "Vladimir", + "portuguese": "Vladimir (região)", + "russian": "Владимирская область", + "chinese_traditional": "Vladimir", + "unknown1": "Vladimir", + "unknown2": "Vladimir", + "unknown3": "Vladimir", + "unknown4": "Vladimir" + }, + "coordinates": { + "latitude": 56.145629244, + "longitude": 40.413317903 + } + }, + { + "id": 1683292160, + "name": "Volgograd", + "translations": { + "japanese": "ヴォルゴグラード州", + "english": "Volgograd", + "french": "Volgograd", + "german": "Oblast Wolgograd", + "italian": "Regione di Volgograd", + "spanish": "Región de Volgogrado", + "chinese_simple": "伏尔加格勒州", + "korean": "볼고그라드 주", + "dutch": "Wolgograd", + "portuguese": "Volgogrado (região)", + "russian": "Волгоградская область", + "chinese_traditional": "Volgograd", + "unknown1": "Volgograd", + "unknown2": "Volgograd", + "unknown3": "Volgograd", + "unknown4": "Volgograd" + }, + "coordinates": { + "latitude": 48.69689886, + "longitude": 44.516722616 + } + }, + { + "id": 1683357696, + "name": "Vologda", + "translations": { + "japanese": "ヴォログダ州", + "english": "Vologda", + "french": "Vologda", + "german": "Oblast Wologda", + "italian": "Regione di Vologda", + "spanish": "Región de Vólogda", + "chinese_simple": "沃洛格达州", + "korean": "볼로그다 주", + "dutch": "Vologda", + "portuguese": "Vologda (região)", + "russian": "Вологодская область", + "chinese_traditional": "Vologda", + "unknown1": "Vologda", + "unknown2": "Vologda", + "unknown3": "Vologda", + "unknown4": "Vologda" + }, + "coordinates": { + "latitude": 59.21630792, + "longitude": 39.896959077 + } + }, + { + "id": 1683423232, + "name": "Voronezh", + "translations": { + "japanese": "ヴォロネジ州", + "english": "Voronezh", + "french": "Voronej", + "german": "Oblast Woronesch", + "italian": "Regione di Voronež", + "spanish": "Región de Vorónezh", + "chinese_simple": "沃罗涅什州", + "korean": "보로네시 주", + "dutch": "Voronezj", + "portuguese": "Voronezh (região)", + "russian": "Воронежская область", + "chinese_traditional": "Voronezh", + "unknown1": "Voronezh", + "unknown2": "Voronezh", + "unknown3": "Voronezh", + "unknown4": "Voronezh" + }, + "coordinates": { + "latitude": 51.668700584, + "longitude": 39.210311702 + } + }, + { + "id": 1683488768, + "name": "Yamal-Nenets", + "translations": { + "japanese": "ヤマロ・ネネツ自治管区", + "english": "Yamal-Nenets", + "french": "Iamalie", + "german": "Autonomer Kreis der Jamal-Nenzen", + "italian": "Circondario Autonomo Jamalo-Nenec", + "spanish": "Distrito autónomo de Yamalo-Nénets", + "chinese_simple": "亚马尔-涅涅茨自治区", + "korean": "야말로네네츠 자치구", + "dutch": "Jamalië", + "portuguese": "Yamal-Nenets", + "russian": "Ямало-Ненецкий автономный округ", + "chinese_traditional": "Yamal-Nenets", + "unknown1": "Yamal-Nenets", + "unknown2": "Yamal-Nenets", + "unknown3": "Yamal-Nenets", + "unknown4": "Yamal-Nenets" + }, + "coordinates": { + "latitude": 66.533202368, + "longitude": 66.599302196 + } + }, + { + "id": 1683554304, + "name": "Yaroslavl'", + "translations": { + "japanese": "ヤロスラヴリ州", + "english": "Yaroslavl'", + "french": "Iaroslavl", + "german": "Oblast Jaroslawl", + "italian": "Regione di Jaroslavl'", + "spanish": "Región de Yaroslavl", + "chinese_simple": "雅罗斯拉夫尔州", + "korean": "야로슬라블 주", + "dutch": "Jaroslavl", + "portuguese": "Yaroslavl (região)", + "russian": "Ярославская область", + "chinese_traditional": "Yaroslavl'", + "unknown1": "Yaroslavl'", + "unknown2": "Yaroslavl'", + "unknown3": "Yaroslavl'", + "unknown4": "Yaroslavl'" + }, + "coordinates": { + "latitude": 57.612304032, + "longitude": 39.847520466 + } + }, + { + "id": 1683619840, + "name": "Yevrey", + "translations": { + "japanese": "ユダヤ自治州", + "english": "Yevrey", + "french": "Oblast autonome juif", + "german": "Jüdisches Autonomes Gebiet", + "italian": "Regione Autonoma Ebraica", + "spanish": "Región Autónoma Hebrea", + "chinese_simple": "犹太自治州", + "korean": "유태인 자치주", + "dutch": "Joodse Autonome Oblast", + "portuguese": "Região Autónoma Judaica", + "russian": "Еврейская автономная область", + "chinese_traditional": "Yevrey", + "unknown1": "Yevrey", + "unknown2": "Yevrey", + "unknown3": "Yevrey", + "unknown4": "Yevrey" + }, + "coordinates": { + "latitude": 48.77929632, + "longitude": 132.929438621 + } + }, + { + "id": 1683685376, + "name": "Zabaykal'ye", + "translations": { + "japanese": "ザバイカリエ地方", + "english": "Zabaykal'ye", + "french": "Transbaïkalie", + "german": "Region Transbaikalien", + "italian": "Territorio della Transbajkalia", + "spanish": "Territorio de Zabaikalie", + "chinese_simple": "外贝加尔边疆区", + "korean": "자바이칼 지방", + "dutch": "Transbaikal", + "portuguese": "Transbaikalia (território)", + "russian": "Забайкальский край", + "chinese_traditional": "Zabaykal'ye", + "unknown1": "Zabaykal'ye", + "unknown2": "Zabaykal'ye", + "unknown3": "Zabaykal'ye", + "unknown4": "Zabaykal'ye" + }, + "coordinates": { + "latitude": 52.0477289, + "longitude": 113.500064498 + } + } + ] + }, + { + "id": 101, + "iso_code": "RS", + "name": "Serbia and Kosovo", + "translations": { + "japanese": "セルビア・コソヴォ", + "english": "Serbia and Kosovo", + "french": "Serbie et Kosovo", + "german": "Serbien und Kosovo", + "italian": "Serbia e Kosovo", + "spanish": "Serbia y Kosovo", + "chinese_simple": "塞尔维亚及科索沃", + "korean": "세르비아 코소보", + "dutch": "Servië en Kosovo", + "portuguese": "Sérvia e Kosovo", + "russian": "Сербия и Косово", + "chinese_traditional": "Serbia and Kosovo", + "unknown1": "Serbia and Kosovo", + "unknown2": "Serbia and Kosovo", + "unknown3": "Serbia and Kosovo", + "unknown4": "Serbia and Kosovo" + }, + "regions": [ + { + "id": 1694498816, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 44.829711404, + "longitude": 20.484064490999998 + } + }, + { + "id": 1694564352, + "name": "Serbia and Kosovo", + "translations": { + "japanese": "セルビア・コソヴォ", + "english": "Serbia and Kosovo", + "french": "Serbie et Kosovo", + "german": "Serbien und Kosovo", + "italian": "Serbia e Kosovo", + "spanish": "Serbia y Kosovo", + "chinese_simple": "塞尔维亚及科索沃", + "korean": "세르비아 코소보", + "dutch": "Servië en Kosovo", + "portuguese": "Sérvia e Kosovo", + "russian": "Сербия и Косово", + "chinese_traditional": "Serbia and Kosovo", + "unknown1": "Serbia and Kosovo", + "unknown2": "Serbia and Kosovo", + "unknown3": "Serbia and Kosovo", + "unknown4": "Serbia and Kosovo" + }, + "coordinates": { + "latitude": 44.829711404, + "longitude": 20.484064490999998 + } + } + ] + }, + { + "id": 102, + "iso_code": "SK", + "name": "Slovakia", + "translations": { + "japanese": "スロバキア", + "english": "Slovakia", + "french": "Slovaquie", + "german": "Slowakei", + "italian": "Slovacchia", + "spanish": "Eslovaquia", + "chinese_simple": "斯洛伐克", + "korean": "슬로바키아", + "dutch": "Slowakije", + "portuguese": "Eslováquia", + "russian": "Словакия", + "chinese_traditional": "Slovakia", + "unknown1": "Slovakia", + "unknown2": "Slovakia", + "unknown3": "Slovakia", + "unknown4": "Slovakia" + }, + "regions": [ + { + "id": 1711276032, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 48.14758246, + "longitude": 17.122238943 + } + }, + { + "id": 1711407104, + "name": "Bratislava", + "translations": { + "japanese": "ブラティスラバ", + "english": "Bratislava", + "french": "Bratislava", + "german": "Bratislava", + "italian": "Bratislava", + "spanish": "Bratislava", + "chinese_simple": "布拉迪斯拉发州", + "korean": "브라티슬라바", + "dutch": "Bratislava", + "portuguese": "Bratislava", + "russian": "Братиславский край", + "chinese_traditional": "Bratislava", + "unknown1": "Bratislava", + "unknown2": "Bratislava", + "unknown3": "Bratislava", + "unknown4": "Bratislava" + }, + "coordinates": { + "latitude": 48.14758246, + "longitude": 17.122238943 + } + }, + { + "id": 1711472640, + "name": "Banská Bystrica", + "translations": { + "japanese": "バンスカ・ビストリツァ", + "english": "Banská Bystrica", + "french": "Banská Bystrica", + "german": "Banská Bystrica", + "italian": "Banská Bystrica", + "spanish": "Banská Bystrica", + "chinese_simple": "班斯卡-比斯特里察州", + "korean": "반스카비스트리차", + "dutch": "Banská Bystrica", + "portuguese": "Banská Bystrica", + "russian": "Банскобистрицкий край", + "chinese_traditional": "Banská Bystrica", + "unknown1": "Banská Bystrica", + "unknown2": "Banská Bystrica", + "unknown3": "Banská Bystrica", + "unknown4": "Banská Bystrica" + }, + "coordinates": { + "latitude": 48.72436468, + "longitude": 19.143728815 + } + }, + { + "id": 1711538176, + "name": "Košice", + "translations": { + "japanese": "コシツェ", + "english": "Košice", + "french": "Košice", + "german": "Košice", + "italian": "Košice", + "spanish": "Košice", + "chinese_simple": "科希策州", + "korean": "코시체", + "dutch": "Košice", + "portuguese": "Košice", + "russian": "Кошицкий край", + "chinese_traditional": "Košice", + "unknown1": "Košice", + "unknown2": "Košice", + "unknown3": "Košice", + "unknown4": "Košice" + }, + "coordinates": { + "latitude": 48.718871516, + "longitude": 21.253109551 + } + }, + { + "id": 1711603712, + "name": "Nitra", + "translations": { + "japanese": "二トラ", + "english": "Nitra", + "french": "Nitra", + "german": "Nitra", + "italian": "Nitra", + "spanish": "Nitra", + "chinese_simple": "尼特拉州", + "korean": "니트라", + "dutch": "Nitra", + "portuguese": "Nitra", + "russian": "Нитранский край", + "chinese_traditional": "Nitra", + "unknown1": "Nitra", + "unknown2": "Nitra", + "unknown3": "Nitra", + "unknown4": "Nitra" + }, + "coordinates": { + "latitude": 48.301391052, + "longitude": 18.07255891 + } + }, + { + "id": 1711669248, + "name": "Prešov", + "translations": { + "japanese": "プレショフ", + "english": "Prešov", + "french": "Prešov", + "german": "Prešov", + "italian": "Prešov", + "spanish": "Prešov", + "chinese_simple": "普雷绍夫州", + "korean": "프레쇼프", + "dutch": "Prešov", + "portuguese": "Prešov", + "russian": "Прешовский край", + "chinese_traditional": "Prešov", + "unknown1": "Prešov", + "unknown2": "Prešov", + "unknown3": "Prešov", + "unknown4": "Prešov" + }, + "coordinates": { + "latitude": 48.966063896, + "longitude": 21.253109551 + } + }, + { + "id": 1711734784, + "name": "Trencín", + "translations": { + "japanese": "トレンチーン", + "english": "Trencín", + "french": "Trenčín", + "german": "Trenčín", + "italian": "Trenčín", + "spanish": "Trenčín", + "chinese_simple": "特伦钦州", + "korean": "트렌친", + "dutch": "Trenčín", + "portuguese": "Trencin", + "russian": "Тренчинский край", + "chinese_traditional": "Trencín", + "unknown1": "Trencín", + "unknown2": "Trencín", + "unknown3": "Trencín", + "unknown4": "Trencín" + }, + "coordinates": { + "latitude": 48.8891596, + "longitude": 18.050586194 + } + }, + { + "id": 1711800320, + "name": "Trnava", + "translations": { + "japanese": "トルナバ", + "english": "Trnava", + "french": "Trnava", + "german": "Trnava", + "italian": "Trnava", + "spanish": "Trnava", + "chinese_simple": "特尔纳瓦州", + "korean": "트르나바", + "dutch": "Trnava", + "portuguese": "Trnava", + "russian": "Трнавский край", + "chinese_traditional": "Trnava", + "unknown1": "Trnava", + "unknown2": "Trnava", + "unknown3": "Trnava", + "unknown4": "Trnava" + }, + "coordinates": { + "latitude": 48.372802184, + "longitude": 17.572679621 + } + }, + { + "id": 1711865856, + "name": "Žilina", + "translations": { + "japanese": "ジリナ", + "english": "Žilina", + "french": "Žilina", + "german": "Žilina", + "italian": "Žilina", + "spanish": "Žilina", + "chinese_simple": "日利纳州", + "korean": "질리나", + "dutch": "Žilina", + "portuguese": "Zilina", + "russian": "Жилинский край", + "chinese_traditional": "Žilina", + "unknown1": "Žilina", + "unknown2": "Žilina", + "unknown3": "Žilina", + "unknown4": "Žilina" + }, + "coordinates": { + "latitude": 49.21874944, + "longitude": 18.726247211 + } + } + ] + }, + { + "id": 103, + "iso_code": "SI", + "name": "Slovenia", + "translations": { + "japanese": "スロベニア", + "english": "Slovenia", + "french": "Slovénie", + "german": "Slowenien", + "italian": "Slovenia", + "spanish": "Eslovenia", + "chinese_simple": "斯洛文尼亚", + "korean": "슬로베니아", + "dutch": "Slovenië", + "portuguese": "Eslovénia", + "russian": "Словения", + "chinese_traditional": "Slovenia", + "unknown1": "Slovenia", + "unknown2": "Slovenia", + "unknown3": "Slovenia", + "unknown4": "Slovenia" + }, + "regions": [ + { + "id": 1728053248, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 46.049193812, + "longitude": 14.50199256 + } + }, + { + "id": 1728118784, + "name": "Slovenia", + "translations": { + "japanese": "スロベニア", + "english": "Slovenia", + "french": "Slovénie", + "german": "Slowenien", + "italian": "Slovenia", + "spanish": "Eslovenia", + "chinese_simple": "斯洛文尼亚", + "korean": "슬로베니아", + "dutch": "Slovenië", + "portuguese": "Eslovénia", + "russian": "Словения", + "chinese_traditional": "Slovenia", + "unknown1": "Slovenia", + "unknown2": "Slovenia", + "unknown3": "Slovenia", + "unknown4": "Slovenia" + }, + "coordinates": { + "latitude": 46.049193812, + "longitude": 14.50199256 + } + } + ] + }, + { + "id": 104, + "iso_code": "ZA", + "name": "South Africa", + "translations": { + "japanese": "南アフリカ", + "english": "South Africa", + "french": "Afrique du Sud", + "german": "Südafrika", + "italian": "Sudafrica", + "spanish": "Sudáfrica", + "chinese_simple": "南非", + "korean": "남아프리카 공화국", + "dutch": "Zuid-Afrika", + "portuguese": "África do Sul", + "russian": "ЮАР", + "chinese_traditional": "South Africa", + "unknown1": "South Africa", + "unknown2": "South Africa", + "unknown3": "South Africa", + "unknown4": "South Africa" + }, + "regions": [ + { + "id": 1744830464, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": -26.141968499999997, + "longitude": 28.048171974 + } + }, + { + "id": 1744961536, + "name": "Gauteng", + "translations": { + "japanese": "ハウテン州", + "english": "Gauteng", + "french": "Gauteng", + "german": "Gauteng", + "italian": "Gauteng", + "spanish": "Gauteng", + "chinese_simple": "豪登省", + "korean": "하우텡 주", + "dutch": "Gauteng", + "portuguese": "Gauteng", + "russian": "Гаутенг ", + "chinese_traditional": "Gauteng", + "unknown1": "Gauteng", + "unknown2": "Gauteng", + "unknown3": "Gauteng", + "unknown4": "Gauteng" + }, + "coordinates": { + "latitude": -26.141968499999997, + "longitude": 28.048171974 + } + }, + { + "id": 1745027072, + "name": "Western Cape", + "translations": { + "japanese": "ウェスタン・ケープ州", + "english": "Western Cape", + "french": "Cap-Occidental", + "german": "Westkap", + "italian": "Capo Occidentale", + "spanish": "Cabo Occidental", + "chinese_simple": "西开普省", + "korean": "웨스턴케이프 주", + "dutch": "West-Kaap", + "portuguese": "Cabo Ocidental", + "russian": "Западно-Капская провинция", + "chinese_traditional": "Western Cape", + "unknown1": "Western Cape", + "unknown2": "Western Cape", + "unknown3": "Western Cape", + "unknown4": "Western Cape" + }, + "coordinates": { + "latitude": -33.920288724, + "longitude": 18.424122366 + } + }, + { + "id": 1745092608, + "name": "Northern Cape", + "translations": { + "japanese": "ノーザン・ケープ州", + "english": "Northern Cape", + "french": "Cap-du-Nord", + "german": "Nordkap", + "italian": "Capo Settentrionale", + "spanish": "Cabo Septentrional", + "chinese_simple": "北开普省", + "korean": "노던케이프 주", + "dutch": "Noord-Kaap", + "portuguese": "Cabo do Norte", + "russian": "Северо-Капская провинция", + "chinese_traditional": "Northern Cape", + "unknown1": "Northern Cape", + "unknown2": "Northern Cape", + "unknown3": "Northern Cape", + "unknown4": "Northern Cape" + }, + "coordinates": { + "latitude": -28.740235071999997, + "longitude": 24.77423729 + } + }, + { + "id": 1745158144, + "name": "Eastern Cape", + "translations": { + "japanese": "イースタン・ケープ州", + "english": "Eastern Cape", + "french": "Cap-Oriental", + "german": "Ostkap", + "italian": "Capo Orientale", + "spanish": "Cabo Oriental", + "chinese_simple": "东开普省", + "korean": "이스턴케이프 주", + "dutch": "Oost-Kaap", + "portuguese": "Cabo Oriental", + "russian": "Восточно-Капская провинция", + "chinese_traditional": "Eastern Cape", + "unknown1": "Eastern Cape", + "unknown2": "Eastern Cape", + "unknown3": "Eastern Cape", + "unknown4": "Eastern Cape" + }, + "coordinates": { + "latitude": -32.8710944, + "longitude": 27.383497315 + } + }, + { + "id": 1745223680, + "name": "KwaZulu-Natal", + "translations": { + "japanese": "クワズールー・ナタール州", + "english": "KwaZulu-Natal", + "french": "KwaZulu-Natal", + "german": "KwaZulu-Natal", + "italian": "KwaZulu-Natal", + "spanish": "KwaZulu-Natal", + "chinese_simple": "夸祖鲁-纳塔尔省", + "korean": "콰줄루나탈 주", + "dutch": "KwaZoeloe-Natal", + "portuguese": "KwaZulu-Natal", + "russian": "Квазулу-Натал", + "chinese_traditional": "KwaZulu-Natal", + "unknown1": "KwaZulu-Natal", + "unknown2": "KwaZulu-Natal", + "unknown3": "KwaZulu-Natal", + "unknown4": "KwaZulu-Natal" + }, + "coordinates": { + "latitude": -29.597168656, + "longitude": 30.382773049 + } + }, + { + "id": 1745289216, + "name": "Free State", + "translations": { + "japanese": "フリー・ステート州", + "english": "Free State", + "french": "État-Libre", + "german": "Freistaat", + "italian": "Stato Libero", + "spanish": "Estado Libre", + "chinese_simple": "自由邦省", + "korean": "프리스테이트 주", + "dutch": "Vrijstaat", + "portuguese": "Estado Livre", + "russian": "Фри-Стейт", + "chinese_traditional": "Free State", + "unknown1": "Free State", + "unknown2": "Free State", + "unknown3": "Free State", + "unknown4": "Free State" + }, + "coordinates": { + "latitude": -29.113770224, + "longitude": 26.218943367 + } + }, + { + "id": 1745354752, + "name": "North West", + "translations": { + "japanese": "ノース・ウェスト州", + "english": "North West", + "french": "Nord-Ouest", + "german": "Nordwest", + "italian": "Provincia del Nordovest", + "spanish": "Noroeste", + "chinese_simple": "西北省", + "korean": "노스웨스트 주", + "dutch": "Noordwest", + "portuguese": "Noroeste", + "russian": "Северо-Западная провинция", + "chinese_traditional": "North West", + "unknown1": "North West", + "unknown2": "North West", + "unknown3": "North West", + "unknown4": "North West" + }, + "coordinates": { + "latitude": -25.850830807999998, + "longitude": 25.647652751 + } + }, + { + "id": 1745420288, + "name": "Mpumalanga", + "translations": { + "japanese": "ムプマランガ州", + "english": "Mpumalanga", + "french": "Mpumalanga", + "german": "Mpumalanga", + "italian": "Mpumalanga", + "spanish": "Mpumalanga", + "chinese_simple": "普马兰加省", + "korean": "음푸말랑가 주", + "dutch": "Mpumalanga", + "portuguese": "Mpumalanga", + "russian": "Мпумаланга", + "chinese_traditional": "Mpumalanga", + "unknown1": "Mpumalanga", + "unknown2": "Mpumalanga", + "unknown3": "Mpumalanga", + "unknown4": "Mpumalanga" + }, + "coordinates": { + "latitude": -25.460816163999993, + "longitude": 30.98152956 + } + }, + { + "id": 1745485824, + "name": "Limpopo", + "translations": { + "japanese": "リンポポ州", + "english": "Limpopo", + "french": "Limpopo", + "german": "Limpopo", + "italian": "Limpopo", + "spanish": "Limpopo", + "chinese_simple": "林波波省", + "korean": "림포푸 주", + "dutch": "Limpopo", + "portuguese": "Limpopo", + "russian": "Лимпопо", + "chinese_traditional": "Limpopo", + "unknown1": "Limpopo", + "unknown2": "Limpopo", + "unknown3": "Limpopo", + "unknown4": "Limpopo" + }, + "coordinates": { + "latitude": -23.889771260000003, + "longitude": 29.437946261 + } + } + ] + }, + { + "id": 105, + "iso_code": "ES", + "name": "Spain", + "translations": { + "japanese": "スペイン", + "english": "Spain", + "french": "Espagne", + "german": "Spanien", + "italian": "Spagna", + "spanish": "España", + "chinese_simple": "西班牙", + "korean": "스페인", + "dutch": "Spanje", + "portuguese": "Espanha", + "russian": "Испания", + "chinese_traditional": "Spain", + "unknown1": "Spain", + "unknown2": "Spain", + "unknown3": "Spain", + "unknown4": "Spain" + }, + "regions": [ + { + "id": 1761607680, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 40.413207548, + "longitude": -3.7019131739999978 + } + }, + { + "id": 1761738752, + "name": "Madrid", + "translations": { + "japanese": "マドリード州", + "english": "Madrid", + "french": "Madrid", + "german": "Madrid", + "italian": "Madrid", + "spanish": "Madrid", + "chinese_simple": "马德里自治区", + "korean": "마드리드 주", + "dutch": "Madrid", + "portuguese": "Madrid", + "russian": "Мадрид", + "chinese_traditional": "Madrid", + "unknown1": "Madrid", + "unknown2": "Madrid", + "unknown3": "Madrid", + "unknown4": "Madrid" + }, + "coordinates": { + "latitude": 40.413207548, + "longitude": -3.7019131739999978 + } + }, + { + "id": 1761804288, + "name": "Andalusia", + "translations": { + "japanese": "アンダルシーア州", + "english": "Andalusia", + "french": "Andalousie", + "german": "Andalusien", + "italian": "Andalusia", + "spanish": "Andalucía", + "chinese_simple": "安达卢西亚自治区", + "korean": "안달루시아 주", + "dutch": "Andalusië", + "portuguese": "Andaluzia", + "russian": "Андалусия", + "chinese_traditional": "Andalusia", + "unknown1": "Andalusia", + "unknown2": "Andalusia", + "unknown3": "Andalusia", + "unknown4": "Andalusia" + }, + "coordinates": { + "latitude": 37.38098102, + "longitude": -5.99806199599999 + } + }, + { + "id": 1761869824, + "name": "Aragon", + "translations": { + "japanese": "アラゴン州", + "english": "Aragon", + "french": "Aragon", + "german": "Aragonien", + "italian": "Aragona", + "spanish": "Aragón", + "chinese_simple": "阿拉贡自治区", + "korean": "아라곤 주", + "dutch": "Aragón", + "portuguese": "Aragão", + "russian": "Арагон", + "chinese_traditional": "Aragon", + "unknown1": "Aragon", + "unknown2": "Aragon", + "unknown3": "Aragon", + "unknown4": "Aragon" + }, + "coordinates": { + "latitude": 41.649169448, + "longitude": -0.8674328099999968 + } + }, + { + "id": 1761935360, + "name": "Principality of Asturias", + "translations": { + "japanese": "アストゥーリアス州", + "english": "Principality of Asturias", + "french": "Asturies", + "german": "Asturien", + "italian": "Principato delle Asturie", + "spanish": "Asturias", + "chinese_simple": "阿斯图利亚斯自治区", + "korean": "아스투리아스 주", + "dutch": "Asturië", + "portuguese": "Astúrias", + "russian": "Астурия", + "chinese_traditional": "Principality of Asturias", + "unknown1": "Principality of Asturias", + "unknown2": "Principality of Asturias", + "unknown3": "Principality of Asturias", + "unknown4": "Principality of Asturias" + }, + "coordinates": { + "latitude": 43.363036616, + "longitude": -5.833266626000011 + } + }, + { + "id": 1762000896, + "name": "Balearic Islands", + "translations": { + "japanese": "バレアーレス諸島", + "english": "Balearic Islands", + "french": "Îles Baléares", + "german": "Balearische Inseln", + "italian": "Baleari", + "spanish": "Illes Balears", + "chinese_simple": "巴利阿里自治区", + "korean": "발레아레스 제도", + "dutch": "Balearen", + "portuguese": "Ilhas Baleares", + "russian": "Балеарские острова", + "chinese_traditional": "Balearic Islands", + "unknown1": "Balearic Islands", + "unknown2": "Balearic Islands", + "unknown3": "Balearic Islands", + "unknown4": "Balearic Islands" + }, + "coordinates": { + "latitude": 39.567260292, + "longitude": 2.63672592 + } + }, + { + "id": 1762066432, + "name": "Canary Islands", + "translations": { + "japanese": "カナリア諸島", + "english": "Canary Islands", + "french": "Îles Canaries", + "german": "Kanarische Inseln", + "italian": "Canarie", + "spanish": "Canarias", + "chinese_simple": "加那利自治区", + "korean": "카나리아 제도", + "dutch": "Canarische Eilanden", + "portuguese": "Canárias", + "russian": "Канарские острова", + "chinese_traditional": "Canary Islands", + "unknown1": "Canary Islands", + "unknown2": "Canary Islands", + "unknown3": "Canary Islands", + "unknown4": "Canary Islands" + }, + "coordinates": { + "latitude": 28.119506516, + "longitude": -15.429850339000012 + } + }, + { + "id": 1762131968, + "name": "Cantabria", + "translations": { + "japanese": "カンタブリア州", + "english": "Cantabria", + "french": "Cantabrie", + "german": "Kantabrien", + "italian": "Cantabria", + "spanish": "Cantabria", + "chinese_simple": "坎塔布利亚自治区", + "korean": "칸타브리아 주", + "dutch": "Cantabrië", + "portuguese": "Cantábria", + "russian": "Кантабрия", + "chinese_traditional": "Cantabria", + "unknown1": "Cantabria", + "unknown2": "Cantabria", + "unknown3": "Cantabria", + "unknown4": "Cantabria" + }, + "coordinates": { + "latitude": 43.461913568, + "longitude": -3.8007903959999965 + } + }, + { + "id": 1762197504, + "name": "Castile-La Mancha", + "translations": { + "japanese": "カスティーリャ・ラ・マンチャ", + "english": "Castile-La Mancha", + "french": "Castille-La Manche", + "german": "Kastilien-La Mancha", + "italian": "Castiglia-La Mancha", + "spanish": "Castilla-La Mancha", + "chinese_simple": "卡斯蒂利亚-拉曼恰自治区", + "korean": "카스티야라만차", + "dutch": "Castilië-La Mancha", + "portuguese": "Castela-La Mancha", + "russian": "Кастилия-Ла-Манча", + "chinese_traditional": "Castile-La Mancha", + "unknown1": "Castile-La Mancha", + "unknown2": "Castile-La Mancha", + "unknown3": "Castile-La Mancha", + "unknown4": "Castile-La Mancha" + }, + "coordinates": { + "latitude": 39.85290482, + "longitude": -4.020517556000016 + } + }, + { + "id": 1762263040, + "name": "Castilla y León", + "translations": { + "japanese": "カスティーリャ・レオン", + "english": "Castilla y León", + "french": "Castille-et-León", + "german": "Kastilien-León", + "italian": "Castiglia e León", + "spanish": "Castilla y León", + "chinese_simple": "卡斯蒂利亚-莱昂自治区", + "korean": "카스티야이레온", + "dutch": "Castilië en León", + "portuguese": "Castela e Leão", + "russian": "Кастилия и Леон", + "chinese_traditional": "Castilla y León", + "unknown1": "Castilla y León", + "unknown2": "Castilla y León", + "unknown3": "Castilla y León", + "unknown4": "Castilla y León" + }, + "coordinates": { + "latitude": 41.63818312, + "longitude": -4.718151288999991 + } + }, + { + "id": 1762328576, + "name": "Catalonia", + "translations": { + "japanese": "カタルーニャ", + "english": "Catalonia", + "french": "Catalogne", + "german": "Katalonien", + "italian": "Catalogna", + "spanish": "Cataluña", + "chinese_simple": "加泰罗尼亚自治区", + "korean": "카탈루냐", + "dutch": "Catalonië", + "portuguese": "Catalunha", + "russian": "Каталония", + "chinese_traditional": "Catalonia", + "unknown1": "Catalonia", + "unknown2": "Catalonia", + "unknown3": "Catalonia", + "unknown4": "Catalonia" + }, + "coordinates": { + "latitude": 41.380004412, + "longitude": 2.169805705 + } + }, + { + "id": 1762394112, + "name": "Valencia", + "translations": { + "japanese": "バレンシア州", + "english": "Valencia", + "french": "Valence", + "german": "Valencia", + "italian": "Comunità Valenciana", + "spanish": "Comunitat Valenciana", + "chinese_simple": "巴伦西亚自治区", + "korean": "발렌시아 주", + "dutch": "Valencia", + "portuguese": "Valência", + "russian": "Валенсия", + "chinese_traditional": "Valencia", + "unknown1": "Valencia", + "unknown2": "Valencia", + "unknown3": "Valencia", + "unknown4": "Valencia" + }, + "coordinates": { + "latitude": 39.46838334, + "longitude": -0.3620603420000066 + } + }, + { + "id": 1762459648, + "name": "Extremadura", + "translations": { + "japanese": "エストレマドゥーラ", + "english": "Extremadura", + "french": "Estrémadure", + "german": "Extremadura", + "italian": "Estremadura", + "spanish": "Extremadura", + "chinese_simple": "埃斯特雷马杜拉自治区", + "korean": "에스트레마두라", + "dutch": "Extremadura", + "portuguese": "Estremadura", + "russian": "Эстремадура", + "chinese_traditional": "Extremadura", + "unknown1": "Extremadura", + "unknown2": "Extremadura", + "unknown3": "Extremadura", + "unknown4": "Extremadura" + }, + "coordinates": { + "latitude": 38.913573776, + "longitude": -6.338639094000001 + } + }, + { + "id": 1762525184, + "name": "Galicia", + "translations": { + "japanese": "ガリーシア", + "english": "Galicia", + "french": "Galice", + "german": "Galicien", + "italian": "Galizia", + "spanish": "Galicia", + "chinese_simple": "加利西亚自治区", + "korean": "갈리시아", + "dutch": "Galicië", + "portuguese": "Galiza", + "russian": "Галисия", + "chinese_traditional": "Galicia", + "unknown1": "Galicia", + "unknown2": "Galicia", + "unknown3": "Galicia", + "unknown4": "Galicia" + }, + "coordinates": { + "latitude": 42.87414502, + "longitude": -8.541403873000007 + } + }, + { + "id": 1762590720, + "name": "Murcia", + "translations": { + "japanese": "ムルシア州", + "english": "Murcia", + "french": "Murcie", + "german": "Murcia", + "italian": "Murcia", + "spanish": "Murcia", + "chinese_simple": "穆尔西亚自治区", + "korean": "무르시아 주", + "dutch": "Murcia", + "portuguese": "Múrcia", + "russian": "Мурсия", + "chinese_traditional": "Murcia", + "unknown1": "Murcia", + "unknown2": "Murcia", + "unknown3": "Murcia", + "unknown4": "Murcia" + }, + "coordinates": { + "latitude": 37.979735896, + "longitude": -1.1201190440000062 + } + }, + { + "id": 1762656256, + "name": "Navarre", + "translations": { + "japanese": "ナバーラ州", + "english": "Navarre", + "french": "Navarre", + "german": "Navarra", + "italian": "Navarra", + "spanish": "Navarra", + "chinese_simple": "纳瓦拉自治区", + "korean": "나바라 주", + "dutch": "Navarra", + "portuguese": "Navarra", + "russian": "Наварра", + "chinese_traditional": "Navarre", + "unknown1": "Navarre", + "unknown2": "Navarre", + "unknown3": "Navarre", + "unknown4": "Navarre" + }, + "coordinates": { + "latitude": 42.813720216, + "longitude": -1.6474642279999898 + } + }, + { + "id": 1762721792, + "name": "Basque Country", + "translations": { + "japanese": "バスク", + "english": "Basque Country", + "french": "Pays basque", + "german": "Baskenland", + "italian": "Paesi Baschi", + "spanish": "País Vasco", + "chinese_simple": "巴斯克自治区", + "korean": "바스크", + "dutch": "Baskenland", + "portuguese": "País Basco", + "russian": "Страна Басков", + "chinese_traditional": "Basque Country", + "unknown1": "Basque Country", + "unknown2": "Basque Country", + "unknown3": "Basque Country", + "unknown4": "Basque Country" + }, + "coordinates": { + "latitude": 42.8466792, + "longitude": -2.6691955219999954 + } + }, + { + "id": 1762787328, + "name": "La Rioja", + "translations": { + "japanese": "ラ・リオハ州", + "english": "La Rioja", + "french": "La Rioja", + "german": "La Rioja", + "italian": "La Rioja", + "spanish": "La Rioja", + "chinese_simple": "拉里奥哈自治区", + "korean": "라리오하", + "dutch": "La Rioja", + "portuguese": "La Rioja", + "russian": "Риоха", + "chinese_traditional": "La Rioja", + "unknown1": "La Rioja", + "unknown2": "La Rioja", + "unknown3": "La Rioja", + "unknown4": "La Rioja" + }, + "coordinates": { + "latitude": 42.46215772, + "longitude": -2.4494683620000046 + } + }, + { + "id": 1762852864, + "name": "Ceuta", + "translations": { + "japanese": "セウタ", + "english": "Ceuta", + "french": "Ceuta", + "german": "Ceuta", + "italian": "Ceuta", + "spanish": "Ceuta", + "chinese_simple": "休达", + "korean": "세우타", + "dutch": "Ceuta", + "portuguese": "Ceuta", + "russian": "Сеута", + "chinese_traditional": "Ceuta", + "unknown1": "Ceuta", + "unknown2": "Ceuta", + "unknown3": "Ceuta", + "unknown4": "Ceuta" + }, + "coordinates": { + "latitude": 35.881347248, + "longitude": -5.3114146210000115 + } + }, + { + "id": 1762918400, + "name": "Melilla", + "translations": { + "japanese": "メリラ", + "english": "Melilla", + "french": "Melilla", + "german": "Melilla", + "italian": "Melilla", + "spanish": "Melilla", + "chinese_simple": "梅利利亚", + "korean": "멜리야", + "dutch": "Melilla", + "portuguese": "Melilla", + "russian": "Мелилья", + "chinese_traditional": "Melilla", + "unknown1": "Melilla", + "unknown2": "Melilla", + "unknown3": "Melilla", + "unknown4": "Melilla" + }, + "coordinates": { + "latitude": 35.299071864, + "longitude": -2.9493476510000107 + } + } + ] + }, + { + "id": 106, + "iso_code": "SZ", + "name": "Swaziland", + "translations": { + "japanese": "スワジランド", + "english": "Swaziland", + "french": "Swaziland", + "german": "Swasiland", + "italian": "Swaziland", + "spanish": "Suazilandia", + "chinese_simple": "斯威士兰", + "korean": "스와질란드", + "dutch": "Swaziland", + "portuguese": "Suazilândia", + "russian": "Свазиленд", + "chinese_traditional": "Swaziland", + "unknown1": "Swaziland", + "unknown2": "Swaziland", + "unknown3": "Swaziland", + "unknown4": "Swaziland" + }, + "regions": [ + { + "id": 1778384896, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": -26.317749747999997, + "longitude": 31.135338572 + } + }, + { + "id": 1778515968, + "name": "Hhohho", + "translations": { + "japanese": "ホホ", + "english": "Hhohho", + "french": "Hhohho", + "german": "Hhohho", + "italian": "Hhohho", + "spanish": "Hhohho", + "chinese_simple": "霍霍区", + "korean": "호호", + "dutch": "Hhohho", + "portuguese": "Hhohho", + "russian": "Хохо", + "chinese_traditional": "Hhohho", + "unknown1": "Hhohho", + "unknown2": "Hhohho", + "unknown3": "Hhohho", + "unknown4": "Hhohho" + }, + "coordinates": { + "latitude": -26.317749747999997, + "longitude": 31.135338572 + } + }, + { + "id": 1778581504, + "name": "Lubombo", + "translations": { + "japanese": "ルボンボ", + "english": "Lubombo", + "french": "Lubombo", + "german": "Lubombo", + "italian": "Lubombo", + "spanish": "Lubombo", + "chinese_simple": "卢邦博区", + "korean": "로밤바", + "dutch": "Lubombo", + "portuguese": "Lubombo", + "russian": "Лубомбо", + "chinese_traditional": "Lubombo", + "unknown1": "Lubombo", + "unknown2": "Lubombo", + "unknown3": "Lubombo", + "unknown4": "Lubombo" + }, + "coordinates": { + "latitude": -26.449585684, + "longitude": 31.948329064 + } + }, + { + "id": 1778647040, + "name": "Manzini", + "translations": { + "japanese": "マンジニ", + "english": "Manzini", + "french": "Manzini", + "german": "Manzini", + "italian": "Manzini", + "spanish": "Manzini", + "chinese_simple": "曼齐尼区", + "korean": "만지니", + "dutch": "Manzini", + "portuguese": "Manzini", + "russian": "Манзини", + "chinese_traditional": "Manzini", + "unknown1": "Manzini", + "unknown2": "Manzini", + "unknown3": "Manzini", + "unknown4": "Manzini" + }, + "coordinates": { + "latitude": -26.488037831999996, + "longitude": 31.382531627 + } + }, + { + "id": 1778712576, + "name": "Shiselweni", + "translations": { + "japanese": "シセルウェニ", + "english": "Shiselweni", + "french": "Shiselweni", + "german": "Shiselweni", + "italian": "Shiselweni", + "spanish": "Shiselweni", + "chinese_simple": "希塞卢韦尼区", + "korean": "시셀웨니", + "dutch": "Shiselweni", + "portuguese": "Shiselweni", + "russian": "Шиселвени", + "chinese_traditional": "Shiselweni", + "unknown1": "Shiselweni", + "unknown2": "Shiselweni", + "unknown3": "Shiselweni", + "unknown4": "Shiselweni" + }, + "coordinates": { + "latitude": -27.1032722, + "longitude": 31.20125672 + } + } + ] + }, + { + "id": 107, + "iso_code": "SE", + "name": "Sweden", + "translations": { + "japanese": "スウェーデン", + "english": "Sweden", + "french": "Suède", + "german": "Schweden", + "italian": "Svezia", + "spanish": "Suecia", + "chinese_simple": "瑞典", + "korean": "스웨덴", + "dutch": "Zweden", + "portuguese": "Suécia", + "russian": "Швеция", + "chinese_traditional": "Sweden", + "unknown1": "Sweden", + "unknown2": "Sweden", + "unknown3": "Sweden", + "unknown4": "Sweden" + }, + "regions": [ + { + "id": 1795162112, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 59.282225888, + "longitude": 18.07255891 + } + }, + { + "id": 1795293184, + "name": "Stockholm County", + "translations": { + "japanese": "ストックホルム州", + "english": "Stockholm County", + "french": "Stockholm", + "german": "Stockholms län", + "italian": "Stoccolma", + "spanish": "Estocolmo", + "chinese_simple": "斯德哥尔摩省", + "korean": "스톡홀름 주", + "dutch": "Stockholms län", + "portuguese": "Estocolmo", + "russian": "Лен Стокгольм", + "chinese_traditional": "Stockholm County", + "unknown1": "Stockholm County", + "unknown2": "Stockholm County", + "unknown3": "Stockholm County", + "unknown4": "Stockholm County" + }, + "coordinates": { + "latitude": 59.282225888, + "longitude": 18.07255891 + } + }, + { + "id": 1795358720, + "name": "Skåne County", + "translations": { + "japanese": "スコーネ州", + "english": "Skåne County", + "french": "Skåne", + "german": "Skåne län", + "italian": "Scania", + "spanish": "Escania", + "chinese_simple": "斯科耐省", + "korean": "스코네 주", + "dutch": "Skåne län", + "portuguese": "Escânia", + "russian": "Лен Сконе", + "chinese_traditional": "Skåne County", + "unknown1": "Skåne County", + "unknown2": "Skåne County", + "unknown3": "Skåne County", + "unknown4": "Skåne County" + }, + "coordinates": { + "latitude": 55.596312844, + "longitude": 12.996861513999999 + } + }, + { + "id": 1795424256, + "name": "Västra Götaland County", + "translations": { + "japanese": "ヴェストラ・イェータランド州", + "english": "Västra Götaland County", + "french": "Västra Götaland", + "german": "Västra Götalands län", + "italian": "Västra Götaland", + "spanish": "Västra Götaland", + "chinese_simple": "西约特兰省", + "korean": "베스트라예탈란드 주", + "dutch": "Västra Götalands län", + "portuguese": "Västra Götaland", + "russian": "Лен Вестра-Гёталанд", + "chinese_traditional": "Västra Götaland County", + "unknown1": "Västra Götaland County", + "unknown2": "Västra Götaland County", + "unknown3": "Västra Götaland County", + "unknown4": "Västra Götaland County" + }, + "coordinates": { + "latitude": 57.70568782, + "longitude": 11.969637041 + } + }, + { + "id": 1795489792, + "name": "Östergötland County", + "translations": { + "japanese": "エステルイェトランド州", + "english": "Östergötland County", + "french": "Östergötland", + "german": "Östergötlands län", + "italian": "Östergötland", + "spanish": "Östergötland", + "chinese_simple": "东约特兰省", + "korean": "외스테르예틀란드 주", + "dutch": "Östergötlands län", + "portuguese": "Östergötland", + "russian": "Лен Эстергётланд", + "chinese_traditional": "Östergötland County", + "unknown1": "Östergötland County", + "unknown2": "Östergötland County", + "unknown3": "Östergötland County", + "unknown4": "Östergötland County" + }, + "coordinates": { + "latitude": 58.397826484, + "longitude": 15.633587434 + } + }, + { + "id": 1795555328, + "name": "Södermanland County", + "translations": { + "japanese": "セーデルマンランド州", + "english": "Södermanland County", + "french": "Södermanland", + "german": "Södermanlands län", + "italian": "Södermanland", + "spanish": "Södermanland", + "chinese_simple": "南曼兰省", + "korean": "쇠데르만란드 주", + "dutch": "Södermanlands län", + "portuguese": "Södermanland", + "russian": "Лен Сёдерманланд", + "chinese_traditional": "Södermanland County", + "unknown1": "Södermanland County", + "unknown2": "Södermanland County", + "unknown3": "Södermanland County", + "unknown4": "Södermanland County" + }, + "coordinates": { + "latitude": 58.754882144, + "longitude": 17.012375363 + } + }, + { + "id": 1795620864, + "name": "Värmland County", + "translations": { + "japanese": "ベルムランド州", + "english": "Värmland County", + "french": "Värmland", + "german": "Värmlands län", + "italian": "Värmland", + "spanish": "Värmland", + "chinese_simple": "韦姆兰省", + "korean": "베름란드 주", + "dutch": "Värmlands län", + "portuguese": "Värmland", + "russian": "Лен Вермланд", + "chinese_traditional": "Värmland County", + "unknown1": "Värmland County", + "unknown2": "Värmland County", + "unknown3": "Värmland County", + "unknown4": "Värmland County" + }, + "coordinates": { + "latitude": 59.386596004, + "longitude": 13.502233982 + } + }, + { + "id": 1795686400, + "name": "Uppsala County", + "translations": { + "japanese": "ウプサラ州", + "english": "Uppsala County", + "french": "Uppsala", + "german": "Uppsala län", + "italian": "Uppsala", + "spanish": "Uppsala", + "chinese_simple": "乌普萨拉省", + "korean": "웁살라 주", + "dutch": "Uppsala län", + "portuguese": "Uppsala", + "russian": "Лен Уппсала", + "chinese_traditional": "Uppsala County", + "unknown1": "Uppsala County", + "unknown2": "Uppsala County", + "unknown3": "Uppsala County", + "unknown4": "Uppsala County" + }, + "coordinates": { + "latitude": 59.853514944, + "longitude": 17.63310459 + } + }, + { + "id": 1795751936, + "name": "Gävleborg County", + "translations": { + "japanese": "イェーブレボリ州", + "english": "Gävleborg County", + "french": "Gävleborg", + "german": "Gävleborgs län", + "italian": "Gävleborg", + "spanish": "Gävleborg", + "chinese_simple": "耶夫勒堡省", + "korean": "예블레보리 주", + "dutch": "Gävleborgs län", + "portuguese": "Gävleborg", + "russian": "Лен Евлеборг", + "chinese_traditional": "Gävleborg County", + "unknown1": "Gävleborg County", + "unknown2": "Gävleborg County", + "unknown3": "Gävleborg County", + "unknown4": "Gävleborg County" + }, + "coordinates": { + "latitude": 60.67199638, + "longitude": 17.182663912 + } + }, + { + "id": 1795817472, + "name": "Västerbotten County", + "translations": { + "japanese": "ベステルボッテン州", + "english": "Västerbotten County", + "french": "Västerbotten", + "german": "Västerbottens län", + "italian": "Västerbotten", + "spanish": "Västerbotten", + "chinese_simple": "西博滕省", + "korean": "베스테르보텐 주", + "dutch": "Västerbottens län", + "portuguese": "Västerbotten", + "russian": "Лен Вестерботтен", + "chinese_traditional": "Västerbotten County", + "unknown1": "Västerbotten County", + "unknown2": "Västerbotten County", + "unknown3": "Västerbotten County", + "unknown4": "Västerbotten County" + }, + "coordinates": { + "latitude": 63.819579352, + "longitude": 20.247857794 + } + }, + { + "id": 1795883008, + "name": "Norrbotten County", + "translations": { + "japanese": "ノルボッテン州", + "english": "Norrbotten County", + "french": "Norrbotten", + "german": "Norrbottens län", + "italian": "Norrbotten", + "spanish": "Norrbotten", + "chinese_simple": "北博滕省", + "korean": "노르보텐 주", + "dutch": "Norrbottens län", + "portuguese": "Norrbotten", + "russian": "Лен Норрботтен", + "chinese_traditional": "Norrbotten County", + "unknown1": "Norrbotten County", + "unknown2": "Norrbotten County", + "unknown3": "Norrbotten County", + "unknown4": "Norrbotten County" + }, + "coordinates": { + "latitude": 65.577391832, + "longitude": 22.214415876 + } + }, + { + "id": 1795948544, + "name": "Gotland Island", + "translations": { + "japanese": "ゴトランド州", + "english": "Gotland Island", + "french": "Gotland", + "german": "Gotlands Iän", + "italian": "Gotland", + "spanish": "Gotland", + "chinese_simple": "哥得兰省", + "korean": "고틀란드 주", + "dutch": "Gotlands län", + "portuguese": "Gotland", + "russian": "Готланд", + "chinese_traditional": "Gotland Island", + "unknown1": "Gotland Island", + "unknown2": "Gotland Island", + "unknown3": "Gotland Island", + "unknown4": "Gotland Island" + }, + "coordinates": { + "latitude": 57.634276688, + "longitude": 18.286792891 + } + }, + { + "id": 1796014080, + "name": "Jämtland County", + "translations": { + "japanese": "イェムトランド州", + "english": "Jämtland County", + "french": "Jämtland", + "german": "Jämtlands län", + "italian": "Jämtland", + "spanish": "Jämtland", + "chinese_simple": "耶姆特兰省", + "korean": "옘틀란드 주", + "dutch": "Jämtlands län", + "portuguese": "Jämtland", + "russian": "Лен Емтланд", + "chinese_traditional": "Jämtland County", + "unknown1": "Jämtland County", + "unknown2": "Jämtland County", + "unknown3": "Jämtland County", + "unknown4": "Jämtland County" + }, + "coordinates": { + "latitude": 63.165892836, + "longitude": 14.650308393 + } + }, + { + "id": 1796079616, + "name": "Dalarna County", + "translations": { + "japanese": "ダーラナ州", + "english": "Dalarna County", + "french": "Dalarna", + "german": "Dalarnas län", + "italian": "Dalarna", + "spanish": "Dalarna", + "chinese_simple": "达拉纳省", + "korean": "달라르나 주", + "dutch": "Dalarnas län", + "portuguese": "Dalecarlia", + "russian": "Лен Даларна", + "chinese_traditional": "Dalarna County", + "unknown1": "Dalarna County", + "unknown2": "Dalarna County", + "unknown3": "Dalarna County", + "unknown4": "Dalarna County" + }, + "coordinates": { + "latitude": 60.611571576, + "longitude": 15.644573792 + } + }, + { + "id": 1796145152, + "name": "Blekinge County", + "translations": { + "japanese": "ブレーキンゲ州", + "english": "Blekinge County", + "french": "Blekinge", + "german": "Blekinge län", + "italian": "Blekinge", + "spanish": "Blekinge", + "chinese_simple": "布莱金厄省", + "korean": "블레킹에 주", + "dutch": "Blekinge län", + "portuguese": "Blekinge", + "russian": "Лен Блекинге", + "chinese_traditional": "Blekinge County", + "unknown1": "Blekinge County", + "unknown2": "Blekinge County", + "unknown3": "Blekinge County", + "unknown4": "Blekinge County" + }, + "coordinates": { + "latitude": 56.1676019, + "longitude": 15.584148823 + } + }, + { + "id": 1796210688, + "name": "Örebro County", + "translations": { + "japanese": "エレブルー州", + "english": "Örebro County", + "french": "Örebro", + "german": "Örebro län", + "italian": "Örebro", + "spanish": "Örebro", + "chinese_simple": "厄勒布鲁省", + "korean": "외레브로 주", + "dutch": "Örebro län", + "portuguese": "Örebro", + "russian": "Лен Эребру", + "chinese_traditional": "Örebro County", + "unknown1": "Örebro County", + "unknown2": "Örebro County", + "unknown3": "Örebro County", + "unknown4": "Örebro County" + }, + "coordinates": { + "latitude": 59.27123956, + "longitude": 15.221599009 + } + }, + { + "id": 1796276224, + "name": "Västernorrland County", + "translations": { + "japanese": "ベステルノルランド州", + "english": "Västernorrland County", + "french": "Västernorrland", + "german": "Västernorrlands län", + "italian": "Västernorrland", + "spanish": "Västernorrland", + "chinese_simple": "西诺尔兰省", + "korean": "베스테르노를란드 주", + "dutch": "Västernorrlands län", + "portuguese": "Västernorrland", + "russian": "Лен Вестерноррланд", + "chinese_traditional": "Västernorrland County", + "unknown1": "Västernorrland County", + "unknown2": "Västernorrland County", + "unknown3": "Västernorrland County", + "unknown4": "Västernorrland County" + }, + "coordinates": { + "latitude": 62.627562764000004, + "longitude": 17.929736255999998 + } + }, + { + "id": 1796341760, + "name": "Jönköping County", + "translations": { + "japanese": "イェンチェピング州", + "english": "Jönköping County", + "french": "Jönköping", + "german": "Jönköpings län", + "italian": "Jönköping", + "spanish": "Jönköping", + "chinese_simple": "延雪平省", + "korean": "옌셰핑 주", + "dutch": "Jönköpings län", + "portuguese": "Jönköping", + "russian": "Лен Йёнчёпинг", + "chinese_traditional": "Jönköping County", + "unknown1": "Jönköping County", + "unknown2": "Jönköping County", + "unknown3": "Jönköping County", + "unknown4": "Jönköping County" + }, + "coordinates": { + "latitude": 57.771605788, + "longitude": 14.166908641 + } + }, + { + "id": 1796407296, + "name": "Kronoberg County", + "translations": { + "japanese": "クロノベリ州", + "english": "Kronoberg County", + "french": "Kronoberg", + "german": "Kronobergs län", + "italian": "Kronoberg", + "spanish": "Kronoberg", + "chinese_simple": "克鲁努贝里省", + "korean": "크로노베리 주", + "dutch": "Kronobergs län", + "portuguese": "Kronoberg", + "russian": "Лен Крунуберг", + "chinese_traditional": "Kronoberg County", + "unknown1": "Kronoberg County", + "unknown2": "Kronoberg County", + "unknown3": "Kronoberg County", + "unknown4": "Kronoberg County" + }, + "coordinates": { + "latitude": 56.88171322, + "longitude": 14.815103763 + } + }, + { + "id": 1796472832, + "name": "Kalmar County", + "translations": { + "japanese": "カルマル州", + "english": "Kalmar County", + "french": "Kalmar", + "german": "Kalmar län", + "italian": "Kalmar", + "spanish": "Kalmar", + "chinese_simple": "卡尔马省", + "korean": "칼마르 주", + "dutch": "Kalmar län", + "portuguese": "Kalmar", + "russian": "Лен Кальмар", + "chinese_traditional": "Kalmar County", + "unknown1": "Kalmar County", + "unknown2": "Kalmar County", + "unknown3": "Kalmar County", + "unknown4": "Kalmar County" + }, + "coordinates": { + "latitude": 56.661986660000004, + "longitude": 16.364180241 + } + }, + { + "id": 1796538368, + "name": "Västmanland County", + "translations": { + "japanese": "ベストマンランド州", + "english": "Västmanland County", + "french": "Västmanland", + "german": "Västmanlands län", + "italian": "Västmanland", + "spanish": "Västmanland", + "chinese_simple": "西曼兰省", + "korean": "베스트만란드 주", + "dutch": "Västmanlands län", + "portuguese": "Västmanland", + "russian": "Лен Вестманланд", + "chinese_traditional": "Västmanland County", + "unknown1": "Västmanland County", + "unknown2": "Västmanland County", + "unknown3": "Västmanland County", + "unknown4": "Västmanland County" + }, + "coordinates": { + "latitude": 59.611815728, + "longitude": 16.550948327 + } + }, + { + "id": 1796603904, + "name": "Halland County", + "translations": { + "japanese": "ハランド州", + "english": "Halland County", + "french": "Halland", + "german": "Hallands län", + "italian": "Halland", + "spanish": "Halland", + "chinese_simple": "哈兰省", + "korean": "할란드 주", + "dutch": "Hallands län", + "portuguese": "Halland", + "russian": "Лен Халланд", + "chinese_traditional": "Halland County", + "unknown1": "Halland County", + "unknown2": "Halland County", + "unknown3": "Halland County", + "unknown4": "Halland County" + }, + "coordinates": { + "latitude": 56.656493496, + "longitude": 12.859532039 + } + } + ] + }, + { + "id": 108, + "iso_code": "CH", + "name": "Switzerland", + "translations": { + "japanese": "スイス", + "english": "Switzerland", + "french": "Suisse", + "german": "Schweiz", + "italian": "Svizzera", + "spanish": "Suiza", + "chinese_simple": "瑞士", + "korean": "스위스", + "dutch": "Zwitserland", + "portuguese": "Suíça", + "russian": "Швейцария", + "chinese_traditional": "Switzerland", + "unknown1": "Switzerland", + "unknown2": "Switzerland", + "unknown3": "Switzerland", + "unknown4": "Switzerland" + }, + "regions": [ + { + "id": 1811939328, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 46.950072708, + "longitude": 7.41579165 + } + }, + { + "id": 1812070400, + "name": "Bern", + "translations": { + "japanese": "ベルン州", + "english": "Bern", + "french": "Berne", + "german": "Bern", + "italian": "Berna", + "spanish": "Berna", + "chinese_simple": "伯尔尼州", + "korean": "베른 주", + "dutch": "Bern", + "portuguese": "Berna", + "russian": "Берн", + "chinese_traditional": "Bern", + "unknown1": "Bern", + "unknown2": "Bern", + "unknown3": "Bern", + "unknown4": "Bern" + }, + "coordinates": { + "latitude": 46.950072708, + "longitude": 7.41579165 + } + }, + { + "id": 1812201472, + "name": "Aargau", + "translations": { + "japanese": "アールガウ州", + "english": "Aargau", + "french": "Argovie", + "german": "Aargau", + "italian": "Argovia", + "spanish": "Argovia", + "chinese_simple": "阿尔高州", + "korean": "아르가우 주", + "dutch": "Aargau", + "portuguese": "Argóvia", + "russian": "Ааргау", + "chinese_traditional": "Aargau", + "unknown1": "Aargau", + "unknown2": "Aargau", + "unknown3": "Aargau", + "unknown4": "Aargau" + }, + "coordinates": { + "latitude": 47.389525828000004, + "longitude": 8.042014056 + } + }, + { + "id": 1812267008, + "name": "Basel-City", + "translations": { + "japanese": "バーゼル=シュタット準州", + "english": "Basel-City", + "french": "Bâle-Ville", + "german": "Basel-Stadt", + "italian": "Basilea Città", + "spanish": "Ciudad de Basilea", + "chinese_simple": "巴塞尔州", + "korean": "바젤", + "dutch": "Bazel-Stad", + "portuguese": "Basileia", + "russian": "Базель", + "chinese_traditional": "Basel-City", + "unknown1": "Basel-City", + "unknown2": "Basel-City", + "unknown3": "Basel-City", + "unknown4": "Basel-City" + }, + "coordinates": { + "latitude": 47.537841256, + "longitude": 7.5860801989999995 + } + }, + { + "id": 1812332544, + "name": "Fribourg", + "translations": { + "japanese": "フリブール州", + "english": "Fribourg", + "french": "Fribourg", + "german": "Freiburg", + "italian": "Friburgo", + "spanish": "Friburgo", + "chinese_simple": "弗里堡州", + "korean": "프리부르 주", + "dutch": "Fribourg", + "portuguese": "Friburgo", + "russian": "Фрибур", + "chinese_traditional": "Fribourg", + "unknown1": "Fribourg", + "unknown2": "Fribourg", + "unknown3": "Fribourg", + "unknown4": "Fribourg" + }, + "coordinates": { + "latitude": 46.80175728, + "longitude": 7.1576122369999995 + } + }, + { + "id": 1812398080, + "name": "Geneva", + "translations": { + "japanese": "ジュネーヴ州", + "english": "Geneva", + "french": "Genève", + "german": "Genf", + "italian": "Ginevra", + "spanish": "Ginebra", + "chinese_simple": "日内瓦州", + "korean": "제네바 주", + "dutch": "Genève", + "portuguese": "Genebra", + "russian": "Женева", + "chinese_traditional": "Geneva", + "unknown1": "Geneva", + "unknown2": "Geneva", + "unknown3": "Geneva", + "unknown4": "Geneva" + }, + "coordinates": { + "latitude": 46.19750924, + "longitude": 6.168840017 + } + }, + { + "id": 1812463616, + "name": "Glarus", + "translations": { + "japanese": "グラールス州", + "english": "Glarus", + "french": "Glaris", + "german": "Glarus", + "italian": "Glarona", + "spanish": "Glaris", + "chinese_simple": "格拉鲁斯州", + "korean": "글라루스 주", + "dutch": "Glarus", + "portuguese": "Glaris", + "russian": "Гларус", + "chinese_traditional": "Glarus", + "unknown1": "Glarus", + "unknown2": "Glarus", + "unknown3": "Glarus", + "unknown4": "Glarus" + }, + "coordinates": { + "latitude": 47.032470168, + "longitude": 9.069238529 + } + }, + { + "id": 1812529152, + "name": "Graubünden", + "translations": { + "japanese": "グラウビュンデン州", + "english": "Graubünden", + "french": "Grisons", + "german": "Graubünden", + "italian": "Grigioni", + "spanish": "Grisones", + "chinese_simple": "格劳宾登州", + "korean": "그라우뷘덴 주", + "dutch": "Graubünden", + "portuguese": "Grisons", + "russian": "Граубюнден", + "chinese_traditional": "Graubünden", + "unknown1": "Graubünden", + "unknown2": "Graubünden", + "unknown3": "Graubünden", + "unknown4": "Graubünden" + }, + "coordinates": { + "latitude": 46.85668892, + "longitude": 9.536158744 + } + }, + { + "id": 1812594688, + "name": "Jura", + "translations": { + "japanese": "ジュラ州", + "english": "Jura", + "french": "Jura", + "german": "Jura", + "italian": "Giura", + "spanish": "Jura", + "chinese_simple": "汝拉州", + "korean": "쥐라 주", + "dutch": "Jura", + "portuguese": "Jura", + "russian": "Юра", + "chinese_traditional": "Jura", + "unknown1": "Jura", + "unknown2": "Jura", + "unknown3": "Jura", + "unknown4": "Jura" + }, + "coordinates": { + "latitude": 47.362060008, + "longitude": 7.344380323 + } + }, + { + "id": 1812660224, + "name": "Luzern", + "translations": { + "japanese": "ルツェルン州", + "english": "Luzern", + "french": "Lucerne", + "german": "Luzern", + "italian": "Lucerna", + "spanish": "Lucerna", + "chinese_simple": "卢塞恩州", + "korean": "루체른 주", + "dutch": "Luzern", + "portuguese": "Lucerna", + "russian": "Люцерн", + "chinese_traditional": "Luzern", + "unknown1": "Luzern", + "unknown2": "Luzern", + "unknown3": "Luzern", + "unknown4": "Luzern" + }, + "coordinates": { + "latitude": 47.04894966, + "longitude": 8.305686648 + } + }, + { + "id": 1812725760, + "name": "Neuchâtel", + "translations": { + "japanese": "ヌシャテル州", + "english": "Neuchâtel", + "french": "Neuchâtel", + "german": "Neuenburg", + "italian": "Neuchâtel", + "spanish": "Neuchâtel", + "chinese_simple": "纳沙泰尔州", + "korean": "뇌샤텔 주", + "dutch": "Neuchâtel", + "portuguese": "Neuchâtel", + "russian": "Нёвшатель", + "chinese_traditional": "Neuchâtel", + "unknown1": "Neuchâtel", + "unknown2": "Neuchâtel", + "unknown3": "Neuchâtel", + "unknown4": "Neuchâtel" + }, + "coordinates": { + "latitude": 46.950072708, + "longitude": 6.932391898 + } + }, + { + "id": 1812791296, + "name": "Obwalden", + "translations": { + "japanese": "オプバルデン準州", + "english": "Obwalden", + "french": "Obwald", + "german": "Obwalden", + "italian": "Obvaldo", + "spanish": "Obwalden", + "chinese_simple": "上瓦尔登半州", + "korean": "옵발덴 주", + "dutch": "Obwalden", + "portuguese": "Obwald", + "russian": "Обвальден", + "chinese_traditional": "Obwalden", + "unknown1": "Obwalden", + "unknown2": "Obwalden", + "unknown3": "Obwalden", + "unknown4": "Obwalden" + }, + "coordinates": { + "latitude": 46.88415474, + "longitude": 8.234275321 + } + }, + { + "id": 1812856832, + "name": "St. Gallen", + "translations": { + "japanese": "ザンクト・ガレン州", + "english": "St. Gallen", + "french": "Saint-Gall", + "german": "Sankt Gallen", + "italian": "San Gallo", + "spanish": "Sankt Gallen", + "chinese_simple": "圣加仑州", + "korean": "장크트갈렌 주", + "dutch": "Sankt Gallen", + "portuguese": "Saint-Gall", + "russian": "Санкт-Галлен", + "chinese_traditional": "St. Gallen", + "unknown1": "St. Gallen", + "unknown2": "St. Gallen", + "unknown3": "St. Gallen", + "unknown4": "St. Gallen" + }, + "coordinates": { + "latitude": 47.422484812, + "longitude": 9.371363374 + } + }, + { + "id": 1812922368, + "name": "Schaffhausen", + "translations": { + "japanese": "シャフハウゼン州", + "english": "Schaffhausen", + "french": "Schaffhouse", + "german": "Schaffhausen", + "italian": "Sciaffusa", + "spanish": "Schaffhausen", + "chinese_simple": "沙夫豪森州", + "korean": "샤프하우젠 주", + "dutch": "Schaffhausen", + "portuguese": "Schaffhausen", + "russian": "Шаффхаузен", + "chinese_traditional": "Schaffhausen", + "unknown1": "Schaffhausen", + "unknown2": "Schaffhausen", + "unknown3": "Schaffhausen", + "unknown4": "Schaffhausen" + }, + "coordinates": { + "latitude": 47.697143012, + "longitude": 8.629784209 + } + }, + { + "id": 1812987904, + "name": "Schwyz", + "translations": { + "japanese": "シュビーツ州", + "english": "Schwyz", + "french": "Schwytz", + "german": "Schwyz", + "italian": "Svitto", + "spanish": "Schwyz", + "chinese_simple": "施维茨州", + "korean": "슈비츠 주", + "dutch": "Schwyz", + "portuguese": "Schwyz", + "russian": "Швиц", + "chinese_traditional": "Schwyz", + "unknown1": "Schwyz", + "unknown2": "Schwyz", + "unknown3": "Schwyz", + "unknown4": "Schwyz" + }, + "coordinates": { + "latitude": 47.04894966, + "longitude": 8.613304672 + } + }, + { + "id": 1813053440, + "name": "Solothurn", + "translations": { + "japanese": "ゾーロトゥルン州", + "english": "Solothurn", + "french": "Soleure", + "german": "Solothurn", + "italian": "Soletta", + "spanish": "Soleura", + "chinese_simple": "索洛图恩州", + "korean": "졸로투른 주", + "dutch": "Solothurn", + "portuguese": "Soleura", + "russian": "Золотурн", + "chinese_traditional": "Solothurn", + "unknown1": "Solothurn", + "unknown2": "Solothurn", + "unknown3": "Solothurn", + "unknown4": "Solothurn" + }, + "coordinates": { + "latitude": 47.208251416, + "longitude": 7.536641588 + } + }, + { + "id": 1813118976, + "name": "Thurgau", + "translations": { + "japanese": "トゥールガウ州", + "english": "Thurgau", + "french": "Thurgovie", + "german": "Thurgau", + "italian": "Turgovia", + "spanish": "Turgovia", + "chinese_simple": "图尔高州", + "korean": "투르가우 주", + "dutch": "Thurgau", + "portuguese": "Turgóvia", + "russian": "Тургау", + "chinese_traditional": "Thurgau", + "unknown1": "Thurgau", + "unknown2": "Thurgau", + "unknown3": "Thurgau", + "unknown4": "Thurgau" + }, + "coordinates": { + "latitude": 47.554320748, + "longitude": 8.887963622 + } + }, + { + "id": 1813184512, + "name": "Ticino", + "translations": { + "japanese": "ティチーノ州", + "english": "Ticino", + "french": "Tessin", + "german": "Tessin", + "italian": "Ticino", + "spanish": "Tesino", + "chinese_simple": "提契诺州", + "korean": "티치노 주", + "dutch": "Ticino", + "portuguese": "Tessino", + "russian": "Тичино", + "chinese_traditional": "Ticino", + "unknown1": "Ticino", + "unknown2": "Ticino", + "unknown3": "Ticino", + "unknown4": "Ticino" + }, + "coordinates": { + "latitude": 46.192016076, + "longitude": 9.019799918 + } + }, + { + "id": 1813250048, + "name": "Uri", + "translations": { + "japanese": "ウーリ州", + "english": "Uri", + "french": "Uri", + "german": "Uri", + "italian": "Uri", + "spanish": "Uri", + "chinese_simple": "乌里州", + "korean": "우리 주", + "dutch": "Uri", + "portuguese": "Uri", + "russian": "Ури", + "chinese_traditional": "Uri", + "unknown1": "Uri", + "unknown2": "Uri", + "unknown3": "Uri", + "unknown4": "Uri" + }, + "coordinates": { + "latitude": 46.862182084, + "longitude": 8.635277388 + } + }, + { + "id": 1813315584, + "name": "Valais", + "translations": { + "japanese": "バレー州", + "english": "Valais", + "french": "Valais", + "german": "Wallis", + "italian": "Vallese", + "spanish": "Valais", + "chinese_simple": "瓦莱州", + "korean": "발레 주", + "dutch": "Wallis", + "portuguese": "Valais", + "russian": "Вале", + "chinese_traditional": "Valais", + "unknown1": "Valais", + "unknown2": "Valais", + "unknown3": "Valais", + "unknown4": "Valais" + }, + "coordinates": { + "latitude": 46.235961388, + "longitude": 7.355366681 + } + }, + { + "id": 1813381120, + "name": "Vaud", + "translations": { + "japanese": "ボー州", + "english": "Vaud", + "french": "Vaud", + "german": "Waadt", + "italian": "Vaud", + "spanish": "Vaud", + "chinese_simple": "沃州", + "korean": "보 주", + "dutch": "Vaud", + "portuguese": "Vaud", + "russian": "Во", + "chinese_traditional": "Vaud", + "unknown1": "Vaud", + "unknown2": "Vaud", + "unknown3": "Vaud", + "unknown4": "Vaud" + }, + "coordinates": { + "latitude": 46.521605916, + "longitude": 6.624773874 + } + }, + { + "id": 1813446656, + "name": "Zug", + "translations": { + "japanese": "ツーク州", + "english": "Zug", + "french": "Zoug", + "german": "Zug", + "italian": "Zugo", + "spanish": "Zug", + "chinese_simple": "楚格州", + "korean": "추크 주", + "dutch": "Zug", + "portuguese": "Zug", + "russian": "Цуг", + "chinese_traditional": "Zug", + "unknown1": "Zug", + "unknown2": "Zug", + "unknown3": "Zug", + "unknown4": "Zug" + }, + "coordinates": { + "latitude": 47.175292432, + "longitude": 8.503441092 + } + }, + { + "id": 1813512192, + "name": "Zurich", + "translations": { + "japanese": "チューリヒ州", + "english": "Zurich", + "french": "Zurich", + "german": "Zürich", + "italian": "Zurigo", + "spanish": "Zúrich", + "chinese_simple": "苏黎世州", + "korean": "취리히 주", + "dutch": "Zürich", + "portuguese": "Zurique", + "russian": "Цюрих", + "chinese_traditional": "Zurich", + "unknown1": "Zurich", + "unknown2": "Zurich", + "unknown3": "Zurich", + "unknown4": "Zurich" + }, + "coordinates": { + "latitude": 47.389525828000004, + "longitude": 8.536400166 + } + }, + { + "id": 1813577728, + "name": "Appenzell Outer Rhodes", + "translations": { + "japanese": "アッペンツェル・アウサーローデン準州", + "english": "Appenzell Outer Rhodes", + "french": "Appenzell Rhodes-Extérieures", + "german": "Appenzell Ausserrhoden", + "italian": "Appenzello Esterno", + "spanish": "Appenzell Rodas Exteriores", + "chinese_simple": "外阿彭策尔半州", + "korean": "아펜첼아우서로덴 주", + "dutch": "Appenzell Ausserrhoden", + "portuguese": "Appenzell Rodas Exteriores", + "russian": "Аппенцелль-Ауссерроден", + "chinese_traditional": "Appenzell Outer Rhodes", + "unknown1": "Appenzell Outer Rhodes", + "unknown2": "Appenzell Outer Rhodes", + "unknown3": "Appenzell Outer Rhodes", + "unknown4": "Appenzell Outer Rhodes" + }, + "coordinates": { + "latitude": 47.3785395, + "longitude": 9.261499794 + } + }, + { + "id": 1813643264, + "name": "Appenzell Inner Rhodes", + "translations": { + "japanese": "アッペンツェル・インナーローデン準州", + "english": "Appenzell Inner Rhodes", + "french": "Appenzell Rhodes-Intérieures", + "german": "Appenzell Innerrhoden", + "italian": "Appenzello Interno", + "spanish": "Appenzell Rodas Interiores", + "chinese_simple": "内阿彭策尔半州", + "korean": "아펜첼이너로덴 주", + "dutch": "Appenzell Innerrhoden", + "portuguese": "Appenzell Rodas Interiores", + "russian": "Аппенцелль-Иннерроден", + "chinese_traditional": "Appenzell Inner Rhodes", + "unknown1": "Appenzell Inner Rhodes", + "unknown2": "Appenzell Inner Rhodes", + "unknown3": "Appenzell Inner Rhodes", + "unknown4": "Appenzell Inner Rhodes" + }, + "coordinates": { + "latitude": 47.329101024, + "longitude": 9.415308806 + } + }, + { + "id": 1813708800, + "name": "Basel-Landschaft", + "translations": { + "japanese": "バーゼル=ラント準州", + "english": "Basel-Landschaft", + "french": "Bâle-Campagne", + "german": "Basel-Landschaft", + "italian": "Basilea Campagna", + "spanish": "Basilea-Campiña", + "chinese_simple": "巴塞尔乡村半州", + "korean": "바젤란트 주", + "dutch": "Basel-Landschaft", + "portuguese": "Basileia (cidade)", + "russian": "Базель-Ланд", + "chinese_traditional": "Basel-Landschaft", + "unknown1": "Basel-Landschaft", + "unknown2": "Basel-Landschaft", + "unknown3": "Basel-Landschaft", + "unknown4": "Basel-Landschaft" + }, + "coordinates": { + "latitude": 47.466430124, + "longitude": 7.728902853 + } + }, + { + "id": 1813774336, + "name": "Nidwalden", + "translations": { + "japanese": "ニトバルデン準州", + "english": "Nidwalden", + "french": "Nidwald", + "german": "Nidwalden", + "italian": "Nidvaldo", + "spanish": "Nidwalden", + "chinese_simple": "下瓦尔登半州", + "korean": "니트발덴 주", + "dutch": "Nidwalden", + "portuguese": "Nidwald", + "russian": "Нидвальден", + "chinese_traditional": "Nidwalden", + "unknown1": "Nidwalden", + "unknown2": "Nidwalden", + "unknown3": "Nidwalden", + "unknown4": "Nidwalden" + }, + "coordinates": { + "latitude": 46.944579544, + "longitude": 8.34963208 + } + } + ] + }, + { + "id": 109, + "iso_code": "TR", + "name": "Turkey", + "translations": { + "japanese": "トルコ", + "english": "Turkey", + "french": "Turquie", + "german": "Türkei", + "italian": "Turchia", + "spanish": "Turquía", + "chinese_simple": "土耳其", + "korean": "터키", + "dutch": "Turkije", + "portuguese": "Turquia", + "russian": "Турция", + "chinese_traditional": "Turkey", + "unknown1": "Turkey", + "unknown2": "Turkey", + "unknown3": "Turkey", + "unknown4": "Turkey" + }, + "regions": [ + { + "id": 1828716544, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 39.924315952, + "longitude": 32.84921042 + } + }, + { + "id": 1828847616, + "name": "Ankara", + "translations": { + "japanese": "アンカラ県", + "english": "Ankara", + "french": "Ankara", + "german": "Ankara", + "italian": "Ankara", + "spanish": "Ankara", + "chinese_simple": "安卡拉省", + "korean": "앙카라 주", + "dutch": "Ankara", + "portuguese": "Ancara", + "russian": "Анкара", + "chinese_traditional": "Ankara", + "unknown1": "Ankara", + "unknown2": "Ankara", + "unknown3": "Ankara", + "unknown4": "Ankara" + }, + "coordinates": { + "latitude": 39.924315952, + "longitude": 32.84921042 + } + }, + { + "id": 1828913152, + "name": "İstanbul", + "translations": { + "japanese": "イスタンブル県", + "english": "İstanbul", + "french": "İstanbul", + "german": "İstanbul", + "italian": "Istanbul", + "spanish": "Estambul", + "chinese_simple": "伊斯坦布尔省", + "korean": "이스탄불 주", + "dutch": "Istanboel", + "portuguese": "Istambul", + "russian": "Стамбул", + "chinese_traditional": "İstanbul", + "unknown1": "İstanbul", + "unknown2": "İstanbul", + "unknown3": "İstanbul", + "unknown4": "İstanbul" + }, + "coordinates": { + "latitude": 41.011962424000004, + "longitude": 28.971026046 + } + }, + { + "id": 1828978688, + "name": "İzmir", + "translations": { + "japanese": "イズミル県", + "english": "İzmir", + "french": "İzmir", + "german": "İzmir", + "italian": "Smirne", + "spanish": "İzmir", + "chinese_simple": "伊兹密尔省", + "korean": "이즈미르 주", + "dutch": "İzmir", + "portuguese": "İzmir", + "russian": "Измир", + "chinese_traditional": "İzmir", + "unknown1": "İzmir", + "unknown2": "İzmir", + "unknown3": "İzmir", + "unknown4": "İzmir" + }, + "coordinates": { + "latitude": 38.419189016, + "longitude": 27.125317902 + } + }, + { + "id": 1829044224, + "name": "Bursa", + "translations": { + "japanese": "ブルサ県", + "english": "Bursa", + "french": "Bursa", + "german": "Bursa", + "italian": "Bursa", + "spanish": "Bursa", + "chinese_simple": "布尔萨省", + "korean": "부르사 주", + "dutch": "Bursa", + "portuguese": "Bursa", + "russian": "Бурса", + "chinese_traditional": "Bursa", + "unknown1": "Bursa", + "unknown2": "Bursa", + "unknown3": "Bursa", + "unknown4": "Bursa" + }, + "coordinates": { + "latitude": 40.18249466, + "longitude": 29.064410089 + } + }, + { + "id": 1829109760, + "name": "Adana", + "translations": { + "japanese": "アダナ県", + "english": "Adana", + "french": "Adana", + "german": "Adana", + "italian": "Adana", + "spanish": "Adana", + "chinese_simple": "阿达纳省", + "korean": "아다나 주", + "dutch": "Adana", + "portuguese": "Adana", + "russian": "Адана", + "chinese_traditional": "Adana", + "unknown1": "Adana", + "unknown2": "Adana", + "unknown3": "Adana", + "unknown4": "Adana" + }, + "coordinates": { + "latitude": 36.996459540000004, + "longitude": 35.32114097 + } + }, + { + "id": 1829175296, + "name": "Gaziantep", + "translations": { + "japanese": "ガジアンテプ県", + "english": "Gaziantep", + "french": "Gaziantep", + "german": "Gaziantep", + "italian": "Gaziantep", + "spanish": "Gaziantep", + "chinese_simple": "加济安泰普省", + "korean": "가지안테프 주", + "dutch": "Gaziantep", + "portuguese": "Gaziantep", + "russian": "Газиантеп", + "chinese_traditional": "Gaziantep", + "unknown1": "Gaziantep", + "unknown2": "Gaziantep", + "unknown3": "Gaziantep", + "unknown4": "Gaziantep" + }, + "coordinates": { + "latitude": 37.062377508, + "longitude": 37.381083095 + } + }, + { + "id": 1829240832, + "name": "Konya", + "translations": { + "japanese": "コニヤ県", + "english": "Konya", + "french": "Konya", + "german": "Konya", + "italian": "Konya", + "spanish": "Konya", + "chinese_simple": "科尼亚省", + "korean": "코니아 주", + "dutch": "Konya", + "portuguese": "Konya", + "russian": "Конья", + "chinese_traditional": "Konya", + "unknown1": "Konya", + "unknown2": "Konya", + "unknown3": "Konya", + "unknown4": "Konya" + }, + "coordinates": { + "latitude": 37.864379452, + "longitude": 32.481167427 + } + }, + { + "id": 1829306368, + "name": "Antalya", + "translations": { + "japanese": "アンタリヤ県", + "english": "Antalya", + "french": "Antalya", + "german": "Antalya", + "italian": "Adalia", + "spanish": "Antalya", + "chinese_simple": "安塔利亚省", + "korean": "안탈리아 주", + "dutch": "Antalya", + "portuguese": "Antalya", + "russian": "Анталья", + "chinese_traditional": "Antalya", + "unknown1": "Antalya", + "unknown2": "Antalya", + "unknown3": "Antalya", + "unknown4": "Antalya" + }, + "coordinates": { + "latitude": 36.897582588, + "longitude": 30.679404715 + } + }, + { + "id": 1829371904, + "name": "Diyarbakır", + "translations": { + "japanese": "ディヤルバクル県", + "english": "Diyarbakır", + "french": "Diyarbakır", + "german": "Diyarbakır", + "italian": "Diyarbakır", + "spanish": "Diyarbakır", + "chinese_simple": "迪亚巴克尔省", + "korean": "디야르바키르 주", + "dutch": "Diyarbakır", + "portuguese": "Diyarbakır", + "russian": "Диярбакыр", + "chinese_traditional": "Diyarbakır", + "unknown1": "Diyarbakır", + "unknown2": "Diyarbakır", + "unknown3": "Diyarbakır", + "unknown4": "Diyarbakır" + }, + "coordinates": { + "latitude": 37.979735896, + "longitude": 40.21007028 + } + }, + { + "id": 1829437440, + "name": "Mersin", + "translations": { + "japanese": "メルシン県", + "english": "Mersin", + "french": "Mersin", + "german": "Mersin", + "italian": "Mersin", + "spanish": "Mersin", + "chinese_simple": "梅尔辛省", + "korean": "메르신 주", + "dutch": "Mersin", + "portuguese": "Mersin", + "russian": "Мерсин", + "chinese_traditional": "Mersin", + "unknown1": "Mersin", + "unknown2": "Mersin", + "unknown3": "Mersin", + "unknown4": "Mersin" + }, + "coordinates": { + "latitude": 36.798705636, + "longitude": 34.629000416 + } + }, + { + "id": 1829502976, + "name": "Kayseri", + "translations": { + "japanese": "カイセリ県", + "english": "Kayseri", + "french": "Kayseri", + "german": "Kayseri", + "italian": "Kayseri", + "spanish": "Kayseri", + "chinese_simple": "开塞利省", + "korean": "카이세리 주", + "dutch": "Kayseri", + "portuguese": "Kayseri", + "russian": "Кайсери", + "chinese_traditional": "Kayseri", + "unknown1": "Kayseri", + "unknown2": "Kayseri", + "unknown3": "Kayseri", + "unknown4": "Kayseri" + }, + "coordinates": { + "latitude": 38.732299364, + "longitude": 35.480443161 + } + }, + { + "id": 1829634048, + "name": "Şanlıurfa", + "translations": { + "japanese": "シャンルウルファ県", + "english": "Şanlıurfa", + "french": "Şanlıurfa", + "german": "Şanlıurfa", + "italian": "Şanlıurfa", + "spanish": "Şanlıurfa", + "chinese_simple": "尚利乌尔法省", + "korean": "샨리우르파 주", + "dutch": "Şanlıurfa", + "portuguese": "Şanlıurfa", + "russian": "Шанлыурфа", + "chinese_traditional": "Şanlıurfa", + "unknown1": "Şanlıurfa", + "unknown2": "Şanlıurfa", + "unknown3": "Şanlıurfa", + "unknown4": "Şanlıurfa" + }, + "coordinates": { + "latitude": 37.144774968, + "longitude": 38.798323277 + } + }, + { + "id": 1829699584, + "name": "Malatya", + "translations": { + "japanese": "マラティヤ県", + "english": "Malatya", + "french": "Malatya", + "german": "Malatya", + "italian": "Malatya", + "spanish": "Malatya", + "chinese_simple": "马拉蒂亚省", + "korean": "말라티아 주", + "dutch": "Malatya", + "portuguese": "Malatya", + "russian": "Малатья", + "chinese_traditional": "Malatya", + "unknown1": "Malatya", + "unknown2": "Malatya", + "unknown3": "Malatya", + "unknown4": "Malatya" + }, + "coordinates": { + "latitude": 38.347777884, + "longitude": 38.309430346 + } + }, + { + "id": 1829765120, + "name": "Erzurum", + "translations": { + "japanese": "エルズルム県", + "english": "Erzurum", + "french": "Erzurum", + "german": "Erzurum", + "italian": "Erzurum", + "spanish": "Erzurum", + "chinese_simple": "埃尔祖鲁姆省", + "korean": "에르주룸 주", + "dutch": "Erzurum", + "portuguese": "Erzurum", + "russian": "Эрзурум", + "chinese_traditional": "Erzurum", + "unknown1": "Erzurum", + "unknown2": "Erzurum", + "unknown3": "Erzurum", + "unknown4": "Erzurum" + }, + "coordinates": { + "latitude": 39.896850132, + "longitude": 41.264760648 + } + }, + { + "id": 1829830656, + "name": "Samsun", + "translations": { + "japanese": "サムスン県", + "english": "Samsun", + "french": "Samsun", + "german": "Samsun", + "italian": "Samsun", + "spanish": "Samsun", + "chinese_simple": "萨姆松省", + "korean": "삼순 주", + "dutch": "Samsun", + "portuguese": "Samsun", + "russian": "Самсун", + "chinese_traditional": "Samsun", + "unknown1": "Samsun", + "unknown2": "Samsun", + "unknown3": "Samsun", + "unknown4": "Samsun" + }, + "coordinates": { + "latitude": 41.286620624, + "longitude": 36.331885906 + } + }, + { + "id": 1829896192, + "name": "Van", + "translations": { + "japanese": "ワン県", + "english": "Van", + "french": "Van", + "german": "Van", + "italian": "Van", + "spanish": "Van", + "chinese_simple": "凡省", + "korean": "반 주", + "dutch": "Van", + "portuguese": "Van", + "russian": "Ван", + "chinese_traditional": "Van", + "unknown1": "Van", + "unknown2": "Van", + "unknown3": "Van", + "unknown4": "Van" + }, + "coordinates": { + "latitude": 38.490600148, + "longitude": 43.379634562999996 + } + }, + { + "id": 1829961728, + "name": "Kahramanmaraş", + "translations": { + "japanese": "カフラマンマラシュ県", + "english": "Kahramanmaraş", + "french": "Kahramanmaraş", + "german": "Kahramanmaraş", + "italian": "Kahramanmaraş", + "spanish": "Kahramanmaraş", + "chinese_simple": "卡赫拉曼马拉什省", + "korean": "카라만마라슈 주", + "dutch": "Kahramanmaraş", + "portuguese": "Kahramanmaraş", + "russian": "Кахраманмараш", + "chinese_traditional": "Kahramanmaraş", + "unknown1": "Kahramanmaraş", + "unknown2": "Kahramanmaraş", + "unknown3": "Kahramanmaraş", + "unknown4": "Kahramanmaraş" + }, + "coordinates": { + "latitude": 37.578734924, + "longitude": 36.930642417 + } + }, + { + "id": 1830027264, + "name": "Denizli", + "translations": { + "japanese": "デニズリ県", + "english": "Denizli", + "french": "Denizli", + "german": "Denizli", + "italian": "Denizli", + "spanish": "Denizli", + "chinese_simple": "代尼兹利省", + "korean": "데니즐리 주", + "dutch": "Denizli", + "portuguese": "Denizli", + "russian": "Денизли", + "chinese_traditional": "Denizli", + "unknown1": "Denizli", + "unknown2": "Denizli", + "unknown3": "Denizli", + "unknown4": "Denizli" + }, + "coordinates": { + "latitude": 37.765502500000004, + "longitude": 29.080889626 + } + }, + { + "id": 1830092800, + "name": "Batman", + "translations": { + "japanese": "バトマン県", + "english": "Batman", + "french": "Batman", + "german": "Batman", + "italian": "Batman", + "spanish": "Batman", + "chinese_simple": "巴特曼省", + "korean": "바트만 주", + "dutch": "Batman", + "portuguese": "Batman", + "russian": "Батман", + "chinese_traditional": "Batman", + "unknown1": "Batman", + "unknown2": "Batman", + "unknown3": "Batman", + "unknown4": "Batman" + }, + "coordinates": { + "latitude": 37.880858944, + "longitude": 41.116444815 + } + }, + { + "id": 1830158336, + "name": "Elazığ", + "translations": { + "japanese": "エラズー県", + "english": "Elazığ", + "french": "Elazığ", + "german": "Elazığ", + "italian": "Elâzığ", + "spanish": "Elazığ", + "chinese_simple": "埃拉泽省", + "korean": "엘라지 주", + "dutch": "Elazığ", + "portuguese": "Elazığ", + "russian": "Элязыг", + "chinese_traditional": "Elazığ", + "unknown1": "Elazığ", + "unknown2": "Elazığ", + "unknown3": "Elazığ", + "unknown4": "Elazığ" + }, + "coordinates": { + "latitude": 38.682860888, + "longitude": 39.215804881 + } + }, + { + "id": 1830223872, + "name": "Sakarya", + "translations": { + "japanese": "サカリヤ県", + "english": "Sakarya", + "french": "Sakarya", + "german": "Sakarya", + "italian": "Sakarya", + "spanish": "Sakarya", + "chinese_simple": "萨卡里亚省", + "korean": "사카리아 주", + "dutch": "Sakarya", + "portuguese": "Sakarya", + "russian": "Сакарья", + "chinese_traditional": "Sakarya", + "unknown1": "Sakarya", + "unknown2": "Sakarya", + "unknown3": "Sakarya", + "unknown4": "Sakarya" + }, + "coordinates": { + "latitude": 40.781249536, + "longitude": 30.399252586 + } + }, + { + "id": 1830289408, + "name": "Kocaeli", + "translations": { + "japanese": "コジャエリ県", + "english": "Kocaeli", + "french": "Kocaeli", + "german": "Kocaeli", + "italian": "Kocaeli", + "spanish": "Kocaeli", + "chinese_simple": "科贾埃利省", + "korean": "코자엘리 주", + "dutch": "Kocaeli", + "portuguese": "Kocaeli", + "russian": "Коджаэли", + "chinese_traditional": "Kocaeli", + "unknown1": "Kocaeli", + "unknown2": "Kocaeli", + "unknown3": "Kocaeli", + "unknown4": "Kocaeli" + }, + "coordinates": { + "latitude": 40.764770044, + "longitude": 29.915852834 + } + }, + { + "id": 1830354944, + "name": "Sivas", + "translations": { + "japanese": "シワス県", + "english": "Sivas", + "french": "Sivas", + "german": "Sivas", + "italian": "Sivas", + "spanish": "Sivas", + "chinese_simple": "锡瓦斯省", + "korean": "시바스 주", + "dutch": "Sivas", + "portuguese": "Sivas", + "russian": "Сивас", + "chinese_traditional": "Sivas", + "unknown1": "Sivas", + "unknown2": "Sivas", + "unknown3": "Sivas", + "unknown4": "Sivas" + }, + "coordinates": { + "latitude": 39.748534704, + "longitude": 37.013040102 + } + }, + { + "id": 1830420480, + "name": "Manisa", + "translations": { + "japanese": "マニサ県", + "english": "Manisa", + "french": "Manisa", + "german": "Manisa", + "italian": "Manisa", + "spanish": "Manisa", + "chinese_simple": "马尼萨省", + "korean": "마니사 주", + "dutch": "Manisa", + "portuguese": "Manisa", + "russian": "Маниса", + "chinese_traditional": "Manisa", + "unknown1": "Manisa", + "unknown2": "Manisa", + "unknown3": "Manisa", + "unknown4": "Manisa" + }, + "coordinates": { + "latitude": 38.611449756, + "longitude": 27.421949568 + } + }, + { + "id": 1830486016, + "name": "Trabzon", + "translations": { + "japanese": "トラブゾン県", + "english": "Trabzon", + "french": "Trabzon", + "german": "Trabzon", + "italian": "Trebisonda", + "spanish": "Trabzon", + "chinese_simple": "特拉布宗省", + "korean": "트라브존 주", + "dutch": "Trabzon", + "portuguese": "Trabzon", + "russian": "Трабзон", + "chinese_traditional": "Trabzon", + "unknown1": "Trabzon", + "unknown2": "Trabzon", + "unknown3": "Trabzon", + "unknown4": "Trabzon" + }, + "coordinates": { + "latitude": 40.995482932, + "longitude": 39.732163707 + } + }, + { + "id": 1830551552, + "name": "Balıkesir", + "translations": { + "japanese": "バルケシル県", + "english": "Balıkesir", + "french": "Balıkesir", + "german": "Balıkesir", + "italian": "Balıkesir", + "spanish": "Balıkesir", + "chinese_simple": "巴勒克埃西尔省", + "korean": "발리케시르 주", + "dutch": "Balıkesir", + "portuguese": "Balıkesir", + "russian": "Балыкесир", + "chinese_traditional": "Balıkesir", + "unknown1": "Balıkesir", + "unknown2": "Balıkesir", + "unknown3": "Balıkesir", + "unknown4": "Balıkesir" + }, + "coordinates": { + "latitude": 39.644164588, + "longitude": 27.877883425 + } + }, + { + "id": 1830617088, + "name": "Adıyaman", + "translations": { + "japanese": "アディヤマン県", + "english": "Adıyaman", + "french": "Adıyaman", + "german": "Adıyaman", + "italian": "Adıyaman", + "spanish": "Adıyaman", + "chinese_simple": "阿德亚曼省", + "korean": "아디야만 주", + "dutch": "Adıyaman", + "portuguese": "Adıyaman", + "russian": "Адыяман", + "chinese_traditional": "Adıyaman", + "unknown1": "Adıyaman", + "unknown2": "Adıyaman", + "unknown3": "Adıyaman", + "unknown4": "Adıyaman" + }, + "coordinates": { + "latitude": 37.760009336, + "longitude": 38.270978093 + } + }, + { + "id": 1830682624, + "name": "Tekirdağ", + "translations": { + "japanese": "テキルダー県", + "english": "Tekirdağ", + "french": "Tekirdağ", + "german": "Tekirdağ", + "italian": "Tekirdağ", + "spanish": "Tekirdağ", + "chinese_simple": "泰基尔达省", + "korean": "테키르다 주", + "dutch": "Tekirdağ", + "portuguese": "Tekirdağ", + "russian": "Текирдаг", + "chinese_traditional": "Tekirdağ", + "unknown1": "Tekirdağ", + "unknown2": "Tekirdağ", + "unknown3": "Tekirdağ", + "unknown4": "Tekirdağ" + }, + "coordinates": { + "latitude": 40.97900344, + "longitude": 27.515333611 + } + }, + { + "id": 1830748160, + "name": "Kırıkkale", + "translations": { + "japanese": "クルッカレ県", + "english": "Kırıkkale", + "french": "Kırıkkale", + "german": "Kırıkkale", + "italian": "Kırıkkale", + "spanish": "Kırıkkale", + "chinese_simple": "克勒克卡莱省", + "korean": "키리칼레 주", + "dutch": "Kırıkkale", + "portuguese": "Kırıkkale", + "russian": "Кырыккале", + "chinese_traditional": "Kırıkkale", + "unknown1": "Kırıkkale", + "unknown2": "Kırıkkale", + "unknown3": "Kırıkkale", + "unknown4": "Kırıkkale" + }, + "coordinates": { + "latitude": 39.847411656, + "longitude": 33.497405542 + } + }, + { + "id": 1830813696, + "name": "Osmaniye", + "translations": { + "japanese": "オスマニエ県", + "english": "Osmaniye", + "french": "Osmaniye", + "german": "Osmaniye", + "italian": "Osmaniye", + "spanish": "Osmaniye", + "chinese_simple": "奥斯曼尼菲省", + "korean": "오스마니예 주", + "dutch": "Osmaniye", + "portuguese": "Osmaniye", + "russian": "Османие", + "chinese_traditional": "Osmaniye", + "unknown1": "Osmaniye", + "unknown2": "Osmaniye", + "unknown3": "Osmaniye", + "unknown4": "Osmaniye" + }, + "coordinates": { + "latitude": 37.078857, + "longitude": 36.249488221 + } + }, + { + "id": 1830879232, + "name": "Kütahya", + "translations": { + "japanese": "キュターヤ県", + "english": "Kütahya", + "french": "Kütahya", + "german": "Kütahya", + "italian": "Kütahya", + "spanish": "Kütahya", + "chinese_simple": "屈塔希亚省", + "korean": "퀴타히아 주", + "dutch": "Kütahya", + "portuguese": "Kütahya", + "russian": "Кютахья", + "chinese_traditional": "Kütahya", + "unknown1": "Kütahya", + "unknown2": "Kütahya", + "unknown3": "Kütahya", + "unknown4": "Kütahya" + }, + "coordinates": { + "latitude": 39.4134517, + "longitude": 29.981770982 + } + }, + { + "id": 1830944768, + "name": "Çorum", + "translations": { + "japanese": "チョルム県", + "english": "Çorum", + "french": "Çorum", + "german": "Çorum", + "italian": "Çorum", + "spanish": "Çorum", + "chinese_simple": "乔鲁姆省", + "korean": "초룸 주", + "dutch": "Çorum", + "portuguese": "Çorum", + "russian": "Чорум", + "chinese_traditional": "Çorum", + "unknown1": "Çorum", + "unknown2": "Çorum", + "unknown3": "Çorum", + "unknown4": "Çorum" + }, + "coordinates": { + "latitude": 40.550536648, + "longitude": 34.953097977 + } + }, + { + "id": 1831010304, + "name": "Isparta", + "translations": { + "japanese": "イスパルタ県", + "english": "Isparta", + "french": "Isparta", + "german": "Isparta", + "italian": "Isparta", + "spanish": "Isparta", + "chinese_simple": "伊斯帕尔塔省", + "korean": "이스파르타 주", + "dutch": "Isparta", + "portuguese": "Isparta", + "russian": "Ыспарта", + "chinese_traditional": "Isparta", + "unknown1": "Isparta", + "unknown2": "Isparta", + "unknown3": "Isparta", + "unknown4": "Isparta" + }, + "coordinates": { + "latitude": 37.765502500000004, + "longitude": 30.547568419 + } + }, + { + "id": 1831075840, + "name": "Aydın", + "translations": { + "japanese": "アイドゥン県", + "english": "Aydın", + "french": "Aydın", + "german": "Aydın", + "italian": "Aydın", + "spanish": "Aydın", + "chinese_simple": "艾登省", + "korean": "아이딘 주", + "dutch": "Aydın", + "portuguese": "Aydın", + "russian": "Айдын", + "chinese_traditional": "Aydın", + "unknown1": "Aydın", + "unknown2": "Aydın", + "unknown3": "Aydın", + "unknown4": "Aydın" + }, + "coordinates": { + "latitude": 37.842406796, + "longitude": 27.844924351 + } + }, + { + "id": 1831141376, + "name": "Hatay", + "translations": { + "japanese": "ハタイ県", + "english": "Hatay", + "french": "Hatay", + "german": "Hatay", + "italian": "Hatay", + "spanish": "Hatay", + "chinese_simple": "哈塔伊省", + "korean": "하타이 주", + "dutch": "Hatay", + "portuguese": "Hatay", + "russian": "Хатай", + "chinese_traditional": "Hatay", + "unknown1": "Hatay", + "unknown2": "Hatay", + "unknown3": "Hatay", + "unknown4": "Hatay" + }, + "coordinates": { + "latitude": 36.19995076, + "longitude": 36.14511782 + } + }, + { + "id": 1831206912, + "name": "Mardin", + "translations": { + "japanese": "マルディン県", + "english": "Mardin", + "french": "Mardin", + "german": "Mardin", + "italian": "Mardin", + "spanish": "Mardin", + "chinese_simple": "马尔丁省", + "korean": "마르딘 주", + "dutch": "Mardin", + "portuguese": "Mardin", + "russian": "Мардин", + "chinese_traditional": "Mardin", + "unknown1": "Mardin", + "unknown2": "Mardin", + "unknown3": "Mardin", + "unknown4": "Mardin" + }, + "coordinates": { + "latitude": 37.315063052, + "longitude": 40.737415464 + } + }, + { + "id": 1831272448, + "name": "Aksaray", + "translations": { + "japanese": "アクサライ県", + "english": "Aksaray", + "french": "Aksaray", + "german": "Aksaray", + "italian": "Aksaray", + "spanish": "Aksaray", + "chinese_simple": "阿克萨赖省", + "korean": "악사라이 주", + "dutch": "Aksaray", + "portuguese": "Aksaray", + "russian": "Аксарай", + "chinese_traditional": "Aksaray", + "unknown1": "Aksaray", + "unknown2": "Aksaray", + "unknown3": "Aksaray", + "unknown4": "Aksaray" + }, + "coordinates": { + "latitude": 38.36975054, + "longitude": 34.024750726 + } + }, + { + "id": 1831337984, + "name": "Afyonkarahisar", + "translations": { + "japanese": "アフィヨンカラヒサール県", + "english": "Afyonkarahisar", + "french": "Afyonkarahisar", + "german": "Afyonkarahisar", + "italian": "Afyonkarahisar", + "spanish": "Afyonkarahisar", + "chinese_simple": "阿菲永卡拉希萨尔省", + "korean": "아피온카라히사르 주", + "dutch": "Afyonkarahisar", + "portuguese": "Afyonkarahisar", + "russian": "Афьонкарахисар", + "chinese_traditional": "Afyonkarahisar", + "unknown1": "Afyonkarahisar", + "unknown2": "Afyonkarahisar", + "unknown3": "Afyonkarahisar", + "unknown4": "Afyonkarahisar" + }, + "coordinates": { + "latitude": 38.75427202, + "longitude": 30.536582061 + } + }, + { + "id": 1831403520, + "name": "Tokat", + "translations": { + "japanese": "トカト県", + "english": "Tokat", + "french": "Tokat", + "german": "Tokat", + "italian": "Tokat", + "spanish": "Tokat", + "chinese_simple": "托卡特省", + "korean": "토카트 주", + "dutch": "Tokat", + "portuguese": "Tokat", + "russian": "Токат", + "chinese_traditional": "Tokat", + "unknown1": "Tokat", + "unknown2": "Tokat", + "unknown3": "Tokat", + "unknown4": "Tokat" + }, + "coordinates": { + "latitude": 40.314330596, + "longitude": 36.546119886999996 + } + }, + { + "id": 1831469056, + "name": "Edirne", + "translations": { + "japanese": "エディルネ県", + "english": "Edirne", + "french": "Edirne", + "german": "Edirne", + "italian": "Edirne", + "spanish": "Edirne", + "chinese_simple": "埃迪尔内省", + "korean": "에디르네 주", + "dutch": "Edirne", + "portuguese": "Edirne", + "russian": "Эдирне", + "chinese_traditional": "Edirne", + "unknown1": "Edirne", + "unknown2": "Edirne", + "unknown3": "Edirne", + "unknown4": "Edirne" + }, + "coordinates": { + "latitude": 41.66564894, + "longitude": 26.565013644 + } + }, + { + "id": 1831534592, + "name": "Karaman", + "translations": { + "japanese": "カラマン県", + "english": "Karaman", + "french": "Karaman", + "german": "Karaman", + "italian": "Karaman", + "spanish": "Karaman", + "chinese_simple": "卡拉曼省", + "korean": "카라만 주", + "dutch": "Karaman", + "portuguese": "Karaman", + "russian": "Караман", + "chinese_traditional": "Karaman", + "unknown1": "Karaman", + "unknown2": "Karaman", + "unknown3": "Karaman", + "unknown4": "Karaman" + }, + "coordinates": { + "latitude": 37.177733952, + "longitude": 33.211760233999996 + } + }, + { + "id": 1831600128, + "name": "Ordu", + "translations": { + "japanese": "オルドゥ県", + "english": "Ordu", + "french": "Ordu", + "german": "Ordu", + "italian": "Ordu", + "spanish": "Ordu", + "chinese_simple": "奥尔杜省", + "korean": "오르두 주", + "dutch": "Ordu", + "portuguese": "Ordu", + "russian": "Орду", + "chinese_traditional": "Ordu", + "unknown1": "Ordu", + "unknown2": "Ordu", + "unknown3": "Ordu", + "unknown4": "Ordu" + }, + "coordinates": { + "latitude": 40.97900344, + "longitude": 37.880962384 + } + }, + { + "id": 1831665664, + "name": "Siirt", + "translations": { + "japanese": "シイルト県", + "english": "Siirt", + "french": "Siirt", + "german": "Siirt", + "italian": "Siirt", + "spanish": "Siirt", + "chinese_simple": "锡尔特省", + "korean": "시이르트 주", + "dutch": "Siirt", + "portuguese": "Siirt", + "russian": "Сиирт", + "chinese_traditional": "Siirt", + "unknown1": "Siirt", + "unknown2": "Siirt", + "unknown3": "Siirt", + "unknown4": "Siirt" + }, + "coordinates": { + "latitude": 37.93029742, + "longitude": 41.945914844 + } + }, + { + "id": 1831731200, + "name": "Erzincan", + "translations": { + "japanese": "エルジンジャン県", + "english": "Erzincan", + "french": "Erzincan", + "german": "Erzincan", + "italian": "Erzincan", + "spanish": "Erzincan", + "chinese_simple": "埃尔津詹省", + "korean": "에르진잔 주", + "dutch": "Erzincan", + "portuguese": "Erzincan", + "russian": "Эрзинджан", + "chinese_traditional": "Erzincan", + "unknown1": "Erzincan", + "unknown2": "Erzincan", + "unknown3": "Erzincan", + "unknown4": "Erzincan" + }, + "coordinates": { + "latitude": 39.748534704, + "longitude": 39.49595701 + } + }, + { + "id": 1831796736, + "name": "Çankırı", + "translations": { + "japanese": "チャンクル県", + "english": "Çankırı", + "french": "Çankırı", + "german": "Çankırı", + "italian": "Çankırı", + "spanish": "Çankırı", + "chinese_simple": "昌克勒省", + "korean": "창키리 주", + "dutch": "Çankırı", + "portuguese": "Çankırı", + "russian": "Чанкыры", + "chinese_traditional": "Çankırı", + "unknown1": "Çankırı", + "unknown2": "Çankırı", + "unknown3": "Çankırı", + "unknown4": "Çankırı" + }, + "coordinates": { + "latitude": 40.599975124000004, + "longitude": 33.612762301 + } + }, + { + "id": 1831862272, + "name": "Zonguldak", + "translations": { + "japanese": "ゾングルダク県", + "english": "Zonguldak", + "french": "Zonguldak", + "german": "Zonguldak", + "italian": "Zonguldak", + "spanish": "Zonguldak", + "chinese_simple": "宗古尔达克省", + "korean": "종굴다크 주", + "dutch": "Zonguldak", + "portuguese": "Zonguldak", + "russian": "Зонгулдак", + "chinese_traditional": "Zonguldak", + "unknown1": "Zonguldak", + "unknown2": "Zonguldak", + "unknown3": "Zonguldak", + "unknown4": "Zonguldak" + }, + "coordinates": { + "latitude": 41.44592238, + "longitude": 31.778040515 + } + }, + { + "id": 1831927808, + "name": "Yozgat", + "translations": { + "japanese": "ヨズガト県", + "english": "Yozgat", + "french": "Yozgat", + "german": "Yozgat", + "italian": "Yozgat", + "spanish": "Yozgat", + "chinese_simple": "约兹加特省", + "korean": "요즈가트 주", + "dutch": "Yozgat", + "portuguese": "Yozgat", + "russian": "Йозгат", + "chinese_traditional": "Yozgat", + "unknown1": "Yozgat", + "unknown2": "Yozgat", + "unknown3": "Yozgat", + "unknown4": "Yozgat" + }, + "coordinates": { + "latitude": 39.819945836, + "longitude": 34.799288965 + } + }, + { + "id": 1831993344, + "name": "Uşak", + "translations": { + "japanese": "ウシャク県", + "english": "Uşak", + "french": "Uşak", + "german": "Uşak", + "italian": "Uşak", + "spanish": "Uşak", + "chinese_simple": "乌萨克省", + "korean": "우샤크 주", + "dutch": "Uşak", + "portuguese": "Uşak", + "russian": "Ушак", + "chinese_traditional": "Uşak", + "unknown1": "Uşak", + "unknown2": "Uşak", + "unknown3": "Uşak", + "unknown4": "Uşak" + }, + "coordinates": { + "latitude": 38.682860888, + "longitude": 29.399494008 + } + }, + { + "id": 1832058880, + "name": "Ağrı", + "translations": { + "japanese": "アール県", + "english": "Ağrı", + "french": "Ağrı", + "german": "Ağrı", + "italian": "Ağrı", + "spanish": "Ağrı", + "chinese_simple": "阿勒省", + "korean": "아리 주", + "dutch": "Ağrı", + "portuguese": "Ağrı", + "russian": "Агры", + "chinese_traditional": "Ağrı", + "unknown1": "Ağrı", + "unknown2": "Ağrı", + "unknown3": "Ağrı", + "unknown4": "Ağrı" + }, + "coordinates": { + "latitude": 39.721068884, + "longitude": 43.055537002 + } + }, + { + "id": 1832124416, + "name": "Amasya", + "translations": { + "japanese": "アマシヤ県", + "english": "Amasya", + "french": "Amasya", + "german": "Amasya", + "italian": "Amasya", + "spanish": "Amasya", + "chinese_simple": "阿马西亚省", + "korean": "아마시아 주", + "dutch": "Amasya", + "portuguese": "Amasya", + "russian": "Амасья", + "chinese_traditional": "Amasya", + "unknown1": "Amasya", + "unknown2": "Amasya", + "unknown3": "Amasya", + "unknown4": "Amasya" + }, + "coordinates": { + "latitude": 40.6494136, + "longitude": 35.832006617 + } + }, + { + "id": 1832189952, + "name": "Ardahan", + "translations": { + "japanese": "アルダハン県", + "english": "Ardahan", + "french": "Ardahan", + "german": "Ardahan", + "italian": "Ardahan", + "spanish": "Ardahan", + "chinese_simple": "阿尔达罕省", + "korean": "아르다한 주", + "dutch": "Ardahan", + "portuguese": "Ardahan", + "russian": "Ардахан", + "chinese_traditional": "Ardahan", + "unknown1": "Ardahan", + "unknown2": "Ardahan", + "unknown3": "Ardahan", + "unknown4": "Ardahan" + }, + "coordinates": { + "latitude": 41.11633254, + "longitude": 42.698480367 + } + }, + { + "id": 1832255488, + "name": "Artvin", + "translations": { + "japanese": "アルトウィン県", + "english": "Artvin", + "french": "Artvin", + "german": "Artvin", + "italian": "Artvin", + "spanish": "Artvin", + "chinese_simple": "阿尔特温省", + "korean": "아르트빈 주", + "dutch": "Artvin", + "portuguese": "Artvin", + "russian": "Артвин", + "chinese_traditional": "Artvin", + "unknown1": "Artvin", + "unknown2": "Artvin", + "unknown3": "Artvin", + "unknown4": "Artvin" + }, + "coordinates": { + "latitude": 41.182250508, + "longitude": 41.814078548 + } + }, + { + "id": 1832321024, + "name": "Bartın", + "translations": { + "japanese": "バルトゥン県", + "english": "Bartın", + "french": "Bartın", + "german": "Bartın", + "italian": "Bartın", + "spanish": "Bartın", + "chinese_simple": "巴尔腾省", + "korean": "바르틴 주", + "dutch": "Bartın", + "portuguese": "Bartın", + "russian": "Бартын", + "chinese_traditional": "Bartın", + "unknown1": "Bartın", + "unknown2": "Bartın", + "unknown3": "Bartın", + "unknown4": "Bartın" + }, + "coordinates": { + "latitude": 41.632689956, + "longitude": 32.332851594 + } + }, + { + "id": 1832386560, + "name": "Bayburt", + "translations": { + "japanese": "バイブルト県", + "english": "Bayburt", + "french": "Bayburt", + "german": "Bayburt", + "italian": "Bayburt", + "spanish": "Bayburt", + "chinese_simple": "巴伊布尔特省", + "korean": "바이부르트 주", + "dutch": "Bayburt", + "portuguese": "Bayburt", + "russian": "Байбурт", + "chinese_traditional": "Bayburt", + "unknown1": "Bayburt", + "unknown2": "Bayburt", + "unknown3": "Bayburt", + "unknown4": "Bayburt" + }, + "coordinates": { + "latitude": 40.248412628, + "longitude": 40.215563459 + } + }, + { + "id": 1832452096, + "name": "Bilecik", + "translations": { + "japanese": "ビレジク県", + "english": "Bilecik", + "french": "Bilecik", + "german": "Bilecik", + "italian": "Bilecik", + "spanish": "Bilecik", + "chinese_simple": "比莱吉克省", + "korean": "빌레지크 주", + "dutch": "Bilecik", + "portuguese": "Bilecik", + "russian": "Биледжик", + "chinese_traditional": "Bilecik", + "unknown1": "Bilecik", + "unknown2": "Bilecik", + "unknown3": "Bilecik", + "unknown4": "Bilecik" + }, + "coordinates": { + "latitude": 40.138549348, + "longitude": 29.976277803 + } + }, + { + "id": 1832517632, + "name": "Bingöl", + "translations": { + "japanese": "ビンギョル県", + "english": "Bingöl", + "french": "Bingöl", + "german": "Bingöl", + "italian": "Bingöl", + "spanish": "Bingöl", + "chinese_simple": "宾格尔省", + "korean": "빙괼 주", + "dutch": "Bingöl", + "portuguese": "Bingöl", + "russian": "Бингёль", + "chinese_traditional": "Bingöl", + "unknown1": "Bingöl", + "unknown2": "Bingöl", + "unknown3": "Bingöl", + "unknown4": "Bingöl" + }, + "coordinates": { + "latitude": 38.880614792, + "longitude": 40.495715588 + } + }, + { + "id": 1832583168, + "name": "Bitlis", + "translations": { + "japanese": "ビトリス県", + "english": "Bitlis", + "french": "Bitlis", + "german": "Bitlis", + "italian": "Bitlis", + "spanish": "Bitlis", + "chinese_simple": "比特利斯省", + "korean": "비틀리스 주", + "dutch": "Bitlis", + "portuguese": "Bitlis", + "russian": "Битлис", + "chinese_traditional": "Bitlis", + "unknown1": "Bitlis", + "unknown2": "Bitlis", + "unknown3": "Bitlis", + "unknown4": "Bitlis" + }, + "coordinates": { + "latitude": 38.39721636, + "longitude": 42.116203393 + } + }, + { + "id": 1832648704, + "name": "Bolu", + "translations": { + "japanese": "ボル県", + "english": "Bolu", + "french": "Bolu", + "german": "Bolu", + "italian": "Bolu", + "spanish": "Bolu", + "chinese_simple": "博卢省", + "korean": "볼루 주", + "dutch": "Bolu", + "portuguese": "Bolu", + "russian": "Болу", + "chinese_traditional": "Bolu", + "unknown1": "Bolu", + "unknown2": "Bolu", + "unknown3": "Bolu", + "unknown4": "Bolu" + }, + "coordinates": { + "latitude": 40.73181106, + "longitude": 31.596765608 + } + }, + { + "id": 1832714240, + "name": "Burdur", + "translations": { + "japanese": "ブルドゥル県", + "english": "Burdur", + "french": "Burdur", + "german": "Burdur", + "italian": "Burdur", + "spanish": "Burdur", + "chinese_simple": "布尔杜尔省", + "korean": "부르두르 주", + "dutch": "Burdur", + "portuguese": "Burdur", + "russian": "Бурдур", + "chinese_traditional": "Burdur", + "unknown1": "Burdur", + "unknown2": "Burdur", + "unknown3": "Burdur", + "unknown4": "Burdur" + }, + "coordinates": { + "latitude": 37.716064024, + "longitude": 30.289389006 + } + }, + { + "id": 1832779776, + "name": "Çanakkale", + "translations": { + "japanese": "チャナッカレ県", + "english": "Çanakkale", + "french": "Çanakkale", + "german": "Çanakkale", + "italian": "Çanakkale", + "spanish": "Çanakkale", + "chinese_simple": "恰纳卡莱省", + "korean": "차나칼레 주", + "dutch": "Çanakkale", + "portuguese": "Çanakkale", + "russian": "Чанаккале", + "chinese_traditional": "Çanakkale", + "unknown1": "Çanakkale", + "unknown2": "Çanakkale", + "unknown3": "Çanakkale", + "unknown4": "Çanakkale" + }, + "coordinates": { + "latitude": 40.149535676, + "longitude": 26.394725095 + } + }, + { + "id": 1832845312, + "name": "Düzce", + "translations": { + "japanese": "デュズジェ県", + "english": "Düzce", + "french": "Düzce", + "german": "Düzce", + "italian": "Düzce", + "spanish": "Düzce", + "chinese_simple": "迪兹杰省", + "korean": "뒤즈제 주", + "dutch": "Düzce", + "portuguese": "Düzce", + "russian": "Дюздже", + "chinese_traditional": "Düzce", + "unknown1": "Düzce", + "unknown2": "Düzce", + "unknown3": "Düzce", + "unknown4": "Düzce" + }, + "coordinates": { + "latitude": 40.830688012, + "longitude": 31.14632493 + } + }, + { + "id": 1832910848, + "name": "Eskişehir", + "translations": { + "japanese": "エスキシェヒル県", + "english": "Eskişehir", + "french": "Eskişehir", + "german": "Eskişehir", + "italian": "Eskişehir", + "spanish": "Eskişehir", + "chinese_simple": "埃斯基谢希尔省", + "korean": "에스키셰히르 주", + "dutch": "Eskişehir", + "portuguese": "Eskişehir", + "russian": "Эскишехир", + "chinese_traditional": "Eskişehir", + "unknown1": "Eskişehir", + "unknown2": "Eskişehir", + "unknown3": "Eskişehir", + "unknown4": "Eskişehir" + }, + "coordinates": { + "latitude": 39.776000524, + "longitude": 30.520102524 + } + }, + { + "id": 1832976384, + "name": "Giresun", + "translations": { + "japanese": "ギレスン県", + "english": "Giresun", + "french": "Giresun", + "german": "Giresun", + "italian": "Giresun", + "spanish": "Giresun", + "chinese_simple": "吉雷松省", + "korean": "기레순 주", + "dutch": "Giresun", + "portuguese": "Giresun", + "russian": "Гиресун", + "chinese_traditional": "Giresun", + "unknown1": "Giresun", + "unknown2": "Giresun", + "unknown3": "Giresun", + "unknown4": "Giresun" + }, + "coordinates": { + "latitude": 40.89660598, + "longitude": 38.413800746999996 + } + }, + { + "id": 1833041920, + "name": "Gümüşhane", + "translations": { + "japanese": "ギュミュシュハーネ県", + "english": "Gümüşhane", + "french": "Gümüşhane", + "german": "Gümüşhane", + "italian": "Gümüşhane", + "spanish": "Gümüşhane", + "chinese_simple": "居米什哈内省", + "korean": "귀뮈샤네 주", + "dutch": "Gümüşhane", + "portuguese": "Gümüşhane", + "russian": "Гюмюшхане", + "chinese_traditional": "Gümüşhane", + "unknown1": "Gümüşhane", + "unknown2": "Gümüşhane", + "unknown3": "Gümüşhane", + "unknown4": "Gümüşhane" + }, + "coordinates": { + "latitude": 40.45715286, + "longitude": 39.479477473 + } + }, + { + "id": 1833107456, + "name": "Hakkari", + "translations": { + "japanese": "ハッキャリ県", + "english": "Hakkari", + "french": "Hakkari", + "german": "Hakkâri", + "italian": "Hakkâri", + "spanish": "Hakkari", + "chinese_simple": "哈卡里省", + "korean": "하카리 주", + "dutch": "Hakkâri", + "portuguese": "Hakkari", + "russian": "Хаккяри", + "chinese_traditional": "Hakkari", + "unknown1": "Hakkari", + "unknown2": "Hakkari", + "unknown3": "Hakkari", + "unknown4": "Hakkari" + }, + "coordinates": { + "latitude": 37.578734924, + "longitude": 43.731198019 + } + }, + { + "id": 1833172992, + "name": "Iğdır", + "translations": { + "japanese": "ウードゥル県", + "english": "Iğdır", + "french": "Iğdır", + "german": "Iğdır", + "italian": "Iğdır", + "spanish": "Iğdır", + "chinese_simple": "伊迪尔省", + "korean": "이디르 주", + "dutch": "Iğdır", + "portuguese": "Iğdır", + "russian": "Ыгдыр", + "chinese_traditional": "Iğdır", + "unknown1": "Iğdır", + "unknown2": "Iğdır", + "unknown3": "Iğdır", + "unknown4": "Iğdır" + }, + "coordinates": { + "latitude": 39.913329624, + "longitude": 44.033322864 + } + }, + { + "id": 1833238528, + "name": "Karabük", + "translations": { + "japanese": "カラビュック県", + "english": "Karabük", + "french": "Karabük", + "german": "Karabük", + "italian": "Karabük", + "spanish": "Karabük", + "chinese_simple": "卡拉比克省", + "korean": "카라뷔크 주", + "dutch": "Karabük", + "portuguese": "Karabük", + "russian": "Карабюк", + "chinese_traditional": "Karabük", + "unknown1": "Karabük", + "unknown2": "Karabük", + "unknown3": "Karabük", + "unknown4": "Karabük" + }, + "coordinates": { + "latitude": 41.19873, + "longitude": 32.62948326 + } + }, + { + "id": 1833304064, + "name": "Kars", + "translations": { + "japanese": "カルス県", + "english": "Kars", + "french": "Kars", + "german": "Kars", + "italian": "Kars", + "spanish": "Kars", + "chinese_simple": "卡尔斯省", + "korean": "카르스 주", + "dutch": "Kars", + "portuguese": "Kars", + "russian": "Карс", + "chinese_traditional": "Kars", + "unknown1": "Kars", + "unknown2": "Kars", + "unknown3": "Kars", + "unknown4": "Kars" + }, + "coordinates": { + "latitude": 40.616454616, + "longitude": 43.099482434 + } + }, + { + "id": 1833369600, + "name": "Kastamonu", + "translations": { + "japanese": "カスタモヌ県", + "english": "Kastamonu", + "french": "Kastamonu", + "german": "Kastamonu", + "italian": "Kastamonu", + "spanish": "Kastamonu", + "chinese_simple": "卡斯塔莫努省", + "korean": "카스타모누 주", + "dutch": "Kastamonu", + "portuguese": "Kastamonu", + "russian": "Кастамону", + "chinese_traditional": "Kastamonu", + "unknown1": "Kastamonu", + "unknown2": "Kastamonu", + "unknown3": "Kastamonu", + "unknown4": "Kastamonu" + }, + "coordinates": { + "latitude": 41.369018084, + "longitude": 33.766571313 + } + }, + { + "id": 1833435136, + "name": "Kilis", + "translations": { + "japanese": "キリス県", + "english": "Kilis", + "french": "Kilis", + "german": "Kilis", + "italian": "Kilis", + "spanish": "Kilis", + "chinese_simple": "基利斯省", + "korean": "킬리스 주", + "dutch": "Kilis", + "portuguese": "Kilis", + "russian": "Килис", + "chinese_traditional": "Kilis", + "unknown1": "Kilis", + "unknown2": "Kilis", + "unknown3": "Kilis", + "unknown4": "Kilis" + }, + "coordinates": { + "latitude": 36.710815012, + "longitude": 37.111917324 + } + }, + { + "id": 1833500672, + "name": "Kırklareli", + "translations": { + "japanese": "クルクラーレリ県", + "english": "Kırklareli", + "french": "Kırklareli", + "german": "Kırklareli", + "italian": "Kırklareli", + "spanish": "Kırklareli", + "chinese_simple": "柯克拉雷利省", + "korean": "키르클라렐리 주", + "dutch": "Kırklareli", + "portuguese": "Kırklareli", + "russian": "Кыркларели", + "chinese_traditional": "Kırklareli", + "unknown1": "Kırklareli", + "unknown2": "Kırklareli", + "unknown3": "Kırklareli", + "unknown4": "Kırklareli" + }, + "coordinates": { + "latitude": 41.731566908, + "longitude": 27.213208766 + } + }, + { + "id": 1833566208, + "name": "Kırşehir", + "translations": { + "japanese": "クルシェヒル県", + "english": "Kırşehir", + "french": "Kırşehir", + "german": "Kırşehir", + "italian": "Kırşehir", + "spanish": "Kırşehir", + "chinese_simple": "克尔谢希尔省", + "korean": "키르셰히르 주", + "dutch": "Kırşehir", + "portuguese": "Kırşehir", + "russian": "Кыршехир", + "chinese_traditional": "Kırşehir", + "unknown1": "Kırşehir", + "unknown2": "Kırşehir", + "unknown3": "Kırşehir", + "unknown4": "Kırşehir" + }, + "coordinates": { + "latitude": 39.149779828, + "longitude": 34.162080201 + } + }, + { + "id": 1833631744, + "name": "Muğla", + "translations": { + "japanese": "ムーラ県", + "english": "Muğla", + "french": "Muğla", + "german": "Muğla", + "italian": "Muğla", + "spanish": "Muğla", + "chinese_simple": "穆拉省", + "korean": "물라 주", + "dutch": "Muğla", + "portuguese": "Muğla", + "russian": "Мугла", + "chinese_traditional": "Muğla", + "unknown1": "Muğla", + "unknown2": "Muğla", + "unknown3": "Muğla", + "unknown4": "Muğla" + }, + "coordinates": { + "latitude": 37.210692936, + "longitude": 28.361283177 + } + }, + { + "id": 1833697280, + "name": "Muş", + "translations": { + "japanese": "ムシュ県", + "english": "Muş", + "french": "Muş", + "german": "Muş", + "italian": "Muş", + "spanish": "Muş", + "chinese_simple": "穆什省", + "korean": "무슈 주", + "dutch": "Muş", + "portuguese": "Muş", + "russian": "Муш", + "chinese_traditional": "Muş", + "unknown1": "Muş", + "unknown2": "Muş", + "unknown3": "Muş", + "unknown4": "Muş" + }, + "coordinates": { + "latitude": 38.748778856, + "longitude": 41.495474166 + } + }, + { + "id": 1833762816, + "name": "Nevşehir", + "translations": { + "japanese": "ネヴシェヒル県", + "english": "Nevşehir", + "french": "Nevşehir", + "german": "Nevşehir", + "italian": "Nevşehir", + "spanish": "Nevşehir", + "chinese_simple": "内夫谢希尔省", + "korean": "네브셰히르 주", + "dutch": "Nevşehir", + "portuguese": "Nevşehir", + "russian": "Невшехир", + "chinese_traditional": "Nevşehir", + "unknown1": "Nevşehir", + "unknown2": "Nevşehir", + "unknown3": "Nevşehir", + "unknown4": "Nevşehir" + }, + "coordinates": { + "latitude": 38.622436084, + "longitude": 34.711398101 + } + }, + { + "id": 1833828352, + "name": "Niğde", + "translations": { + "japanese": "ニーデ県", + "english": "Niğde", + "french": "Niğde", + "german": "Niğde", + "italian": "Niğde", + "spanish": "Niğde", + "chinese_simple": "尼代省", + "korean": "니데 주", + "dutch": "Niğde", + "portuguese": "Niğde", + "russian": "Нигде", + "chinese_traditional": "Niğde", + "unknown1": "Niğde", + "unknown2": "Niğde", + "unknown3": "Niğde", + "unknown4": "Niğde" + }, + "coordinates": { + "latitude": 37.963256404, + "longitude": 34.678439027 + } + }, + { + "id": 1833893888, + "name": "Rize", + "translations": { + "japanese": "リゼ県", + "english": "Rize", + "french": "Rize", + "german": "Rize", + "italian": "Rize", + "spanish": "Rize", + "chinese_simple": "里泽省", + "korean": "리제 주", + "dutch": "Rize", + "portuguese": "Rize", + "russian": "Ризе", + "chinese_traditional": "Rize", + "unknown1": "Rize", + "unknown2": "Rize", + "unknown3": "Rize", + "unknown4": "Rize" + }, + "coordinates": { + "latitude": 41.011962424000004, + "longitude": 40.512195125 + } + }, + { + "id": 1833959424, + "name": "Sinop", + "translations": { + "japanese": "シノプ県", + "english": "Sinop", + "french": "Sinop", + "german": "Sinop", + "italian": "Sinope", + "spanish": "Sinop", + "chinese_simple": "锡诺普省", + "korean": "시노프 주", + "dutch": "Sinop", + "portuguese": "Sinop", + "russian": "Синоп", + "chinese_traditional": "Sinop", + "unknown1": "Sinop", + "unknown2": "Sinop", + "unknown3": "Sinop", + "unknown4": "Sinop" + }, + "coordinates": { + "latitude": 42.028197764, + "longitude": 35.145359242 + } + }, + { + "id": 1834024960, + "name": "Şırnak", + "translations": { + "japanese": "シュルナク県", + "english": "Şırnak", + "french": "Şırnak", + "german": "Şırnak", + "italian": "Şırnak", + "spanish": "Şırnak", + "chinese_simple": "锡尔纳克省", + "korean": "시르나크 주", + "dutch": "Şırnak", + "portuguese": "Şırnak", + "russian": "Ширнак", + "chinese_traditional": "Şırnak", + "unknown1": "Şırnak", + "unknown2": "Şırnak", + "unknown3": "Şırnak", + "unknown4": "Şırnak" + }, + "coordinates": { + "latitude": 37.512816956, + "longitude": 42.456780490999996 + } + }, + { + "id": 1834090496, + "name": "Tunceli", + "translations": { + "japanese": "トゥンジェリ県", + "english": "Tunceli", + "french": "Tunceli", + "german": "Tunceli", + "italian": "Tunceli", + "spanish": "Tunceli", + "chinese_simple": "通杰利省", + "korean": "툰젤리 주", + "dutch": "Tunceli", + "portuguese": "Tunceli", + "russian": "Тунджели", + "chinese_traditional": "Tunceli", + "unknown1": "Tunceli", + "unknown2": "Tunceli", + "unknown3": "Tunceli", + "unknown4": "Tunceli" + }, + "coordinates": { + "latitude": 39.11132768, + "longitude": 39.545395621 + } + }, + { + "id": 1834156032, + "name": "Yalova", + "translations": { + "japanese": "ヤロワ県", + "english": "Yalova", + "french": "Yalova", + "german": "Yalova", + "italian": "Yalova", + "spanish": "Yalova", + "chinese_simple": "亚罗法省", + "korean": "얄로바 주", + "dutch": "Yalova", + "portuguese": "Yalova", + "russian": "Ялова", + "chinese_traditional": "Yalova", + "unknown1": "Yalova", + "unknown2": "Yalova", + "unknown3": "Yalova", + "unknown4": "Yalova" + }, + "coordinates": { + "latitude": 40.6494136, + "longitude": 29.262164533 + } + } + ] + }, + { + "id": 110, + "iso_code": "GB", + "name": "United Kingdom", + "translations": { + "japanese": "イギリス", + "english": "United Kingdom", + "french": "Royaume-Uni", + "german": "Vereinigtes Königreich", + "italian": "Regno Unito", + "spanish": "Reino Unido", + "chinese_simple": "英国", + "korean": "영국", + "dutch": "Verenigd Koninkrijk", + "portuguese": "Reino Unido", + "russian": "Великобритания", + "chinese_traditional": "United Kingdom", + "unknown1": "United Kingdom", + "unknown2": "United Kingdom", + "unknown3": "United Kingdom", + "unknown4": "United Kingdom" + }, + "regions": [ + { + "id": 1845493760, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 51.503905664, + "longitude": -0.11486728700000981 + } + }, + { + "id": 1845690368, + "name": "London", + "translations": { + "japanese": "ロンドン", + "english": "London", + "french": "Londres", + "german": "London", + "italian": "Londra", + "spanish": "Londres", + "chinese_simple": "伦敦", + "korean": "런던", + "dutch": "Londen", + "portuguese": "Londres", + "russian": "Лондон", + "chinese_traditional": "London", + "unknown1": "London", + "unknown2": "London", + "unknown3": "London", + "unknown4": "London" + }, + "coordinates": { + "latitude": 51.503905664, + "longitude": -0.11486728700000981 + } + }, + { + "id": 1845821440, + "name": "Scotland", + "translations": { + "japanese": "スコットランド", + "english": "Scotland", + "french": "Écosse", + "german": "Schottland", + "italian": "Scozia", + "spanish": "Escocia", + "chinese_simple": "苏格兰", + "korean": "스코틀랜드", + "dutch": "Schotland", + "portuguese": "Escócia", + "russian": "Шотландия", + "chinese_traditional": "Scotland", + "unknown1": "Scotland", + "unknown2": "Scotland", + "unknown3": "Scotland", + "unknown4": "Scotland" + }, + "coordinates": { + "latitude": 55.953368504000004, + "longitude": -3.2020338849999916 + } + }, + { + "id": 1845886976, + "name": "Wales", + "translations": { + "japanese": "ウェールズ", + "english": "Wales", + "french": "Pays de Galles", + "german": "Wales", + "italian": "Galles", + "spanish": "Gales", + "chinese_simple": "威尔士", + "korean": "웨일즈", + "dutch": "Wales", + "portuguese": "País de Gales", + "russian": "Уэльс", + "chinese_traditional": "Wales", + "unknown1": "Wales", + "unknown2": "Wales", + "unknown3": "Wales", + "unknown4": "Wales" + }, + "coordinates": { + "latitude": 51.476439844, + "longitude": -3.174567990000014 + } + }, + { + "id": 1845952512, + "name": "Northern Ireland", + "translations": { + "japanese": "北アイルランド", + "english": "Northern Ireland", + "french": "Irlande du Nord", + "german": "Nordirland", + "italian": "Irlanda del Nord", + "spanish": "Irlanda del Norte", + "chinese_simple": "北爱尔兰", + "korean": "북아일랜드", + "dutch": "Noord-Ierland", + "portuguese": "Irlanda do Norte", + "russian": "Северная Ирландия", + "chinese_traditional": "Northern Ireland", + "unknown1": "Northern Ireland", + "unknown2": "Northern Ireland", + "unknown3": "Northern Ireland", + "unknown4": "Northern Ireland" + }, + "coordinates": { + "latitude": 54.585570668, + "longitude": -5.904677953000004 + } + }, + { + "id": 1846018048, + "name": "South West", + "translations": { + "japanese": "南西部地方", + "english": "South West", + "french": "Sud-Ouest", + "german": "South West", + "italian": "Sud Ovest", + "spanish": "Suroeste", + "chinese_simple": "西南英格兰", + "korean": "사우스웨스트", + "dutch": "South West", + "portuguese": "Sudoeste", + "russian": "Юго-Западный регион", + "chinese_traditional": "South West", + "unknown1": "South West", + "unknown2": "South West", + "unknown3": "South West", + "unknown4": "South West" + }, + "coordinates": { + "latitude": 51.448974024, + "longitude": -2.5813046579999934 + } + }, + { + "id": 1846083584, + "name": "West Midlands", + "translations": { + "japanese": "ウェスト・ミッドランド地方", + "english": "West Midlands", + "french": "Midlands de l'Ouest", + "german": "West Midlands", + "italian": "Midlands Occidentali", + "spanish": "Midlands Occidentales", + "chinese_simple": "西米德兰兹", + "korean": "웨스트미들랜즈", + "dutch": "West Midlands", + "portuguese": "Midlands Ocidentais", + "russian": "Западный Мидленд", + "chinese_traditional": "West Midlands", + "unknown1": "West Midlands", + "unknown2": "West Midlands", + "unknown3": "West Midlands", + "unknown4": "West Midlands" + }, + "coordinates": { + "latitude": 52.481688856, + "longitude": -1.8891641040000025 + } + }, + { + "id": 1846149120, + "name": "North West", + "translations": { + "japanese": "北西部地方", + "english": "North West", + "french": "Nord-Ouest", + "german": "North West", + "italian": "Nord Ovest", + "spanish": "Noroeste", + "chinese_simple": "西北英格兰", + "korean": "노스웨스트", + "dutch": "North West", + "portuguese": "Noroeste", + "russian": "Северо-Западный регион", + "chinese_traditional": "North West", + "unknown1": "North West", + "unknown2": "North West", + "unknown3": "North West", + "unknown4": "North West" + }, + "coordinates": { + "latitude": 53.464965212, + "longitude": -2.229741202000014 + } + }, + { + "id": 1846214656, + "name": "North East", + "translations": { + "japanese": "北東部地方", + "english": "North East", + "french": "Nord-Est", + "german": "North East", + "italian": "Nord Est", + "spanish": "Noreste", + "chinese_simple": "东北英格兰", + "korean": "노스이스트", + "dutch": "North East", + "portuguese": "Nordeste", + "russian": "Северо-Восточный регион", + "chinese_traditional": "North East", + "unknown1": "North East", + "unknown2": "North East", + "unknown3": "North East", + "unknown4": "North East" + }, + "coordinates": { + "latitude": 54.970092148, + "longitude": -1.6090119750000156 + } + }, + { + "id": 1846280192, + "name": "Yorkshire and the Humber", + "translations": { + "japanese": "ヨークシャー・アンド・ザ・ハンバー地方", + "english": "Yorkshire and the Humber", + "french": "Yorkshire et Humber", + "german": "Yorkshire and the Humber", + "italian": "Yorkshire e Humber", + "spanish": "Yorkshire y Humber", + "chinese_simple": "约克郡-亨伯", + "korean": "요크셔-험버", + "dutch": "Yorkshire and the Humber", + "portuguese": "Yorkshire e Humber", + "russian": "Йоркшир и Хамбер", + "chinese_traditional": "Yorkshire and the Humber", + "unknown1": "Yorkshire and the Humber", + "unknown2": "Yorkshire and the Humber", + "unknown3": "Yorkshire and the Humber", + "unknown4": "Yorkshire and the Humber" + }, + "coordinates": { + "latitude": 53.794555052, + "longitude": -1.548587005999991 + } + }, + { + "id": 1846345728, + "name": "East Midlands", + "translations": { + "japanese": "イースト・ミッドランド地方", + "english": "East Midlands", + "french": "Midlands de l'Est", + "german": "East Midlands", + "italian": "Midlands Orientali", + "spanish": "Midlands Orientales", + "chinese_simple": "东米德兰兹", + "korean": "이스트미들랜즈", + "dutch": "East Midlands", + "portuguese": "Midlands Orientais", + "russian": "Восточный Мидленд", + "chinese_traditional": "East Midlands", + "unknown1": "East Midlands", + "unknown2": "East Midlands", + "unknown3": "East Midlands", + "unknown4": "East Midlands" + }, + "coordinates": { + "latitude": 52.630004284, + "longitude": -1.1365985810000154 + } + }, + { + "id": 1846411264, + "name": "East of England", + "translations": { + "japanese": "イングランド東部地方", + "english": "East of England", + "french": "Est", + "german": "East of England", + "italian": "Est dell'Inghilterra", + "spanish": "Este de Inglaterra", + "chinese_simple": "东英格兰", + "korean": "이스트오브잉글랜드", + "dutch": "East of England", + "portuguese": "Este de Inglaterra", + "russian": "Восточный регион", + "chinese_traditional": "East of England", + "unknown1": "East of England", + "unknown2": "East of England", + "unknown3": "East of England", + "unknown4": "East of England" + }, + "coordinates": { + "latitude": 52.62451112, + "longitude": 1.296390244 + } + }, + { + "id": 1846476800, + "name": "South East", + "translations": { + "japanese": "南東部地方", + "english": "South East", + "french": "Sud-Est", + "german": "South East", + "italian": "Sud Est", + "spanish": "씒⭤ꥠ軷됎矙ᑻ۱埣ἴឦ", + "chinese_simple": "东南英格兰", + "korean": "사우스이스트", + "dutch": "South East", + "portuguese": "Sudeste", + "russian": "Юго-Восточный регион", + "chinese_traditional": "South East", + "unknown1": "South East", + "unknown2": "South East", + "unknown3": "South East", + "unknown4": "South East" + }, + "coordinates": { + "latitude": 50.83923282, + "longitude": -0.1258536450000065 + } + } + ] + }, + { + "id": 111, + "iso_code": "ZM", + "name": "Zambia", + "translations": { + "japanese": "ザンビア", + "english": "Zambia", + "french": "Zambie", + "german": "Sambia", + "italian": "Zambia", + "spanish": "Zambia", + "chinese_simple": "赞比亚", + "korean": "잠비아", + "dutch": "Zambia", + "portuguese": "Zâmbia", + "russian": "Замбия", + "chinese_traditional": "Zambia", + "unknown1": "Zambia", + "unknown2": "Zambia", + "unknown3": "Zambia", + "unknown4": "Zambia" + }, + "regions": [ + { + "id": 1862270976, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": -15.413819207999992, + "longitude": 28.278885492 + } + }, + { + "id": 1862336512, + "name": "Zambia", + "translations": { + "japanese": "ザンビア", + "english": "Zambia", + "french": "Zambie", + "german": "Sambia", + "italian": "Zambia", + "spanish": "Zambia", + "chinese_simple": "赞比亚", + "korean": "잠비아", + "dutch": "Zambia", + "portuguese": "Zâmbia", + "russian": "Замбия", + "chinese_traditional": "Zambia", + "unknown1": "Zambia", + "unknown2": "Zambia", + "unknown3": "Zambia", + "unknown4": "Zambia" + }, + "coordinates": { + "latitude": -15.413819207999992, + "longitude": 28.278885492 + } + } + ] + }, + { + "id": 112, + "iso_code": "ZW", + "name": "Zimbabwe", + "translations": { + "japanese": "ジンバブエ", + "english": "Zimbabwe", + "french": "Zimbabwe", + "german": "Simbabwe", + "italian": "Zimbabwe", + "spanish": "Zimbabue", + "chinese_simple": "津巴布韦", + "korean": "짐바브웨", + "dutch": "Zimbabwe", + "portuguese": "Zimbabué", + "russian": "Зимбабве", + "chinese_traditional": "Zimbabwe", + "unknown1": "Zimbabwe", + "unknown2": "Zimbabwe", + "unknown3": "Zimbabwe", + "unknown4": "Zimbabwe" + }, + "regions": [ + { + "id": 1879048192, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": -17.819825039999998, + "longitude": 31.047447708 + } + }, + { + "id": 1879113728, + "name": "Zimbabwe", + "translations": { + "japanese": "ジンバブエ", + "english": "Zimbabwe", + "french": "Zimbabwe", + "german": "Simbabwe", + "italian": "Zimbabwe", + "spanish": "Zimbabue", + "chinese_simple": "津巴布韦", + "korean": "짐바브웨", + "dutch": "Zimbabwe", + "portuguese": "Zimbabué", + "russian": "Зимбабве", + "chinese_traditional": "Zimbabwe", + "unknown1": "Zimbabwe", + "unknown2": "Zimbabwe", + "unknown3": "Zimbabwe", + "unknown4": "Zimbabwe" + }, + "coordinates": { + "latitude": -17.819825039999998, + "longitude": 31.047447708 + } + } + ] + }, + { + "id": 113, + "iso_code": "AZ", + "name": "Azerbaijan", + "translations": { + "japanese": "アゼルバイジャン", + "english": "Azerbaijan", + "french": "Azerbaïdjan", + "german": "Aserbaidschan", + "italian": "Azerbaigian", + "spanish": "Azerbaiyán", + "chinese_simple": "阿塞拜疆", + "korean": "아제르바이잔", + "dutch": "Azerbeidzjan", + "portuguese": "Azerbaijão", + "russian": "Азербайджан", + "chinese_traditional": "Azerbaijan", + "unknown1": "Azerbaijan", + "unknown2": "Azerbaijan", + "unknown3": "Azerbaijan", + "unknown4": "Azerbaijan" + }, + "regions": [ + { + "id": 1895825408, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 40.3747554, + "longitude": 49.889051678 + } + }, + { + "id": 1895890944, + "name": "Azerbaijan", + "translations": { + "japanese": "アゼルバイジャン", + "english": "Azerbaijan", + "french": "Azerbaïdjan", + "german": "Aserbaidschan", + "italian": "Azerbaigian", + "spanish": "Azerbaiyán", + "chinese_simple": "阿塞拜疆", + "korean": "아제르바이잔", + "dutch": "Azerbeidzjan", + "portuguese": "Azerbaijão", + "russian": "Азербайджан", + "chinese_traditional": "Azerbaijan", + "unknown1": "Azerbaijan", + "unknown2": "Azerbaijan", + "unknown3": "Azerbaijan", + "unknown4": "Azerbaijan" + }, + "coordinates": { + "latitude": 40.3747554, + "longitude": 49.889051678 + } + } + ] + }, + { + "id": 114, + "iso_code": "MR", + "name": "Mauritania", + "translations": { + "japanese": "モーリタニア", + "english": "Mauritania", + "french": "Mauritanie", + "german": "Mauretanien", + "italian": "Mauritania", + "spanish": "Mauritania", + "chinese_simple": "毛里塔尼亚", + "korean": "모리타니", + "dutch": "Mauritanië", + "portuguese": "Mauritânia", + "russian": "Мавритания", + "chinese_traditional": "Mauritania", + "unknown1": "Mauritania", + "unknown2": "Mauritania", + "unknown3": "Mauritania", + "unknown4": "Mauritania" + }, + "regions": [ + { + "id": 1912602624, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 18.09997538, + "longitude": -15.946209164999999 + } + }, + { + "id": 1912668160, + "name": "Mauritania", + "translations": { + "japanese": "モーリタニア", + "english": "Mauritania", + "french": "Mauritanie", + "german": "Mauretanien", + "italian": "Mauritania", + "spanish": "Mauritania", + "chinese_simple": "毛里塔尼亚", + "korean": "모리타니", + "dutch": "Mauritanië", + "portuguese": "Mauritânia", + "russian": "Мавритания", + "chinese_traditional": "Mauritania", + "unknown1": "Mauritania", + "unknown2": "Mauritania", + "unknown3": "Mauritania", + "unknown4": "Mauritania" + }, + "coordinates": { + "latitude": 18.09997538, + "longitude": -15.946209164999999 + } + } + ] + }, + { + "id": 115, + "iso_code": "ML", + "name": "Mali", + "translations": { + "japanese": "マリ", + "english": "Mali", + "french": "Mali", + "german": "Mali", + "italian": "Mali", + "spanish": "Malí", + "chinese_simple": "马里", + "korean": "말리", + "dutch": "Mali", + "portuguese": "Mali", + "russian": "Мали", + "chinese_traditional": "Mali", + "unknown1": "Mali", + "unknown2": "Mali", + "unknown3": "Mali", + "unknown4": "Mali" + }, + "regions": [ + { + "id": 1929379840, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 12.645263528, + "longitude": -7.997579152000014 + } + }, + { + "id": 1929445376, + "name": "Mali", + "translations": { + "japanese": "マリ", + "english": "Mali", + "french": "Mali", + "german": "Mali", + "italian": "Mali", + "spanish": "Malí", + "chinese_simple": "马里", + "korean": "말리", + "dutch": "Mali", + "portuguese": "Mali", + "russian": "Мали", + "chinese_traditional": "Mali", + "unknown1": "Mali", + "unknown2": "Mali", + "unknown3": "Mali", + "unknown4": "Mali" + }, + "coordinates": { + "latitude": 12.645263528, + "longitude": -7.997579152000014 + } + } + ] + }, + { + "id": 116, + "iso_code": "NE", + "name": "Niger", + "translations": { + "japanese": "ニジェール", + "english": "Niger", + "french": "Niger", + "german": "Niger", + "italian": "Niger", + "spanish": "Níger", + "chinese_simple": "尼日尔", + "korean": "니제르", + "dutch": "Niger", + "portuguese": "Níger", + "russian": "Нигер", + "chinese_traditional": "Niger", + "unknown1": "Niger", + "unknown2": "Niger", + "unknown3": "Niger", + "unknown4": "Niger" + }, + "regions": [ + { + "id": 1946157056, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 13.518676604, + "longitude": 2.103887557 + } + }, + { + "id": 1946222592, + "name": "Niger", + "translations": { + "japanese": "ニジェール", + "english": "Niger", + "french": "Niger", + "german": "Niger", + "italian": "Niger", + "spanish": "Níger", + "chinese_simple": "尼日尔", + "korean": "니제르", + "dutch": "Niger", + "portuguese": "Níger", + "russian": "Нигер", + "chinese_traditional": "Niger", + "unknown1": "Niger", + "unknown2": "Niger", + "unknown3": "Niger", + "unknown4": "Niger" + }, + "coordinates": { + "latitude": 13.518676604, + "longitude": 2.103887557 + } + } + ] + }, + { + "id": 117, + "iso_code": "TD", + "name": "Chad", + "translations": { + "japanese": "チャド", + "english": "Chad", + "french": "Tchad", + "german": "Tschad", + "italian": "Ciad", + "spanish": "Chad", + "chinese_simple": "乍得", + "korean": "차드", + "dutch": "Tsjaad", + "portuguese": "Chade", + "russian": "Чад", + "chinese_traditional": "Chad", + "unknown1": "Chad", + "unknown2": "Chad", + "unknown3": "Chad", + "unknown4": "Chad" + }, + "regions": [ + { + "id": 1962934272, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 12.106933456, + "longitude": 15.034830923 + } + }, + { + "id": 1962999808, + "name": "Chad", + "translations": { + "japanese": "チャド", + "english": "Chad", + "french": "Tchad", + "german": "Tschad", + "italian": "Ciad", + "spanish": "Chad", + "chinese_simple": "乍得", + "korean": "차드", + "dutch": "Tsjaad", + "portuguese": "Chade", + "russian": "Чад", + "chinese_traditional": "Chad", + "unknown1": "Chad", + "unknown2": "Chad", + "unknown3": "Chad", + "unknown4": "Chad" + }, + "coordinates": { + "latitude": 12.106933456, + "longitude": 15.034830923 + } + } + ] + }, + { + "id": 118, + "iso_code": "SD", + "name": "Sudan", + "translations": { + "japanese": "スーダン", + "english": "Sudan", + "french": "Soudan", + "german": "Sudan", + "italian": "Sudan", + "spanish": "Sudán", + "chinese_simple": "苏丹", + "korean": "수단", + "dutch": "Soedan", + "portuguese": "Sudão", + "russian": "Судан", + "chinese_traditional": "Sudan", + "unknown1": "Sudan", + "unknown2": "Sudan", + "unknown3": "Sudan", + "unknown4": "Sudan" + }, + "regions": [ + { + "id": 1979711488, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 15.62805158, + "longitude": 32.530606038 + } + }, + { + "id": 1979777024, + "name": "Sudan", + "translations": { + "japanese": "スーダン", + "english": "Sudan", + "french": "Soudan", + "german": "Sudan", + "italian": "Sudan", + "spanish": "Sudán", + "chinese_simple": "苏丹", + "korean": "수단", + "dutch": "Soedan", + "portuguese": "Sudão", + "russian": "Судан", + "chinese_traditional": "Sudan", + "unknown1": "Sudan", + "unknown2": "Sudan", + "unknown3": "Sudan", + "unknown4": "Sudan" + }, + "coordinates": { + "latitude": 15.62805158, + "longitude": 32.530606038 + } + } + ] + }, + { + "id": 119, + "iso_code": "ER", + "name": "Eritrea", + "translations": { + "japanese": "エリトリア", + "english": "Eritrea", + "french": "Érythrée", + "german": "Eritrea", + "italian": "Eritrea", + "spanish": "Eritrea", + "chinese_simple": "厄立特里亚", + "korean": "에리트레아", + "dutch": "Eritrea", + "portuguese": "Eritreia", + "russian": "Эритрея", + "chinese_traditional": "Eritrea", + "unknown1": "Eritrea", + "unknown2": "Eritrea", + "unknown3": "Eritrea", + "unknown4": "Eritrea" + }, + "regions": [ + { + "id": 1996488704, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 15.331420724, + "longitude": 38.930159573 + } + }, + { + "id": 1996554240, + "name": "Eritrea", + "translations": { + "japanese": "エリトリア", + "english": "Eritrea", + "french": "Érythrée", + "german": "Eritrea", + "italian": "Eritrea", + "spanish": "Eritrea", + "chinese_simple": "厄立特里亚", + "korean": "에리트레아", + "dutch": "Eritrea", + "portuguese": "Eritreia", + "russian": "Эритрея", + "chinese_traditional": "Eritrea", + "unknown1": "Eritrea", + "unknown2": "Eritrea", + "unknown3": "Eritrea", + "unknown4": "Eritrea" + }, + "coordinates": { + "latitude": 15.331420724, + "longitude": 38.930159573 + } + } + ] + }, + { + "id": 120, + "iso_code": "DJ", + "name": "Djibouti", + "translations": { + "japanese": "ジブチ", + "english": "Djibouti", + "french": "Djibouti", + "german": "Dschibuti", + "italian": "Gibuti", + "spanish": "Yibuti", + "chinese_simple": "吉布提", + "korean": "지부티", + "dutch": "Djibouti", + "portuguese": "Djibouti", + "russian": "Джибути", + "chinese_traditional": "Djibouti", + "unknown1": "Djibouti", + "unknown2": "Djibouti", + "unknown3": "Djibouti", + "unknown4": "Djibouti" + }, + "regions": [ + { + "id": 2013265920, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 11.585082876, + "longitude": 43.143427865999996 + } + }, + { + "id": 2013331456, + "name": "Djibouti", + "translations": { + "japanese": "ジブチ", + "english": "Djibouti", + "french": "Djibouti", + "german": "Dschibuti", + "italian": "Gibuti", + "spanish": "Yibuti", + "chinese_simple": "吉布提", + "korean": "지부티", + "dutch": "Djibouti", + "portuguese": "Djibouti", + "russian": "Джибути", + "chinese_traditional": "Djibouti", + "unknown1": "Djibouti", + "unknown2": "Djibouti", + "unknown3": "Djibouti", + "unknown4": "Djibouti" + }, + "coordinates": { + "latitude": 11.585082876, + "longitude": 43.143427865999996 + } + } + ] + }, + { + "id": 121, + "iso_code": "SO", + "name": "Somalia", + "translations": { + "japanese": "ソマリア", + "english": "Somalia", + "french": "Somalie", + "german": "Somalia", + "italian": "Somalia", + "spanish": "Somalia", + "chinese_simple": "索马里", + "korean": "소말리아", + "dutch": "Somalië", + "portuguese": "Somália", + "russian": "Сомали", + "chinese_traditional": "Somalia", + "unknown1": "Somalia", + "unknown2": "Somalia", + "unknown3": "Somalia", + "unknown4": "Somalia" + }, + "regions": [ + { + "id": 2030043136, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 2.03247068, + "longitude": 45.346192645 + } + }, + { + "id": 2030108672, + "name": "Somalia", + "translations": { + "japanese": "ソマリア", + "english": "Somalia", + "french": "Somalie", + "german": "Somalia", + "italian": "Somalia", + "spanish": "Somalia", + "chinese_simple": "索马里", + "korean": "소말리아", + "dutch": "Somalië", + "portuguese": "Somália", + "russian": "Сомали", + "chinese_traditional": "Somalia", + "unknown1": "Somalia", + "unknown2": "Somalia", + "unknown3": "Somalia", + "unknown4": "Somalia" + }, + "coordinates": { + "latitude": 2.03247068, + "longitude": 45.346192645 + } + } + ] + }, + { + "id": 122, + "iso_code": "AD", + "name": "Andorra", + "translations": { + "japanese": "アンドラ", + "english": "Andorra", + "french": "Andorre", + "german": "Andorra", + "italian": "Andorra", + "spanish": "Andorra", + "chinese_simple": "安道尔", + "korean": "안도라", + "dutch": "Andorra", + "portuguese": "Andorra", + "russian": "Андорра", + "chinese_traditional": "Andorra", + "unknown1": "Andorra", + "unknown2": "Andorra", + "unknown3": "Andorra", + "unknown4": "Andorra" + }, + "regions": [ + { + "id": 2046820352, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 42.495116704, + "longitude": 1.499637867 + } + }, + { + "id": 2046885888, + "name": "Andorra", + "translations": { + "japanese": "アンドラ", + "english": "Andorra", + "french": "Andorre", + "german": "Andorra", + "italian": "Andorra", + "spanish": "Andorra", + "chinese_simple": "安道尔", + "korean": "안도라", + "dutch": "Andorra", + "portuguese": "Andorra", + "russian": "Андорра", + "chinese_traditional": "Andorra", + "unknown1": "Andorra", + "unknown2": "Andorra", + "unknown3": "Andorra", + "unknown4": "Andorra" + }, + "coordinates": { + "latitude": 42.495116704, + "longitude": 1.499637867 + } + } + ] + }, + { + "id": 123, + "iso_code": "GI", + "name": "Gibraltar", + "translations": { + "japanese": "ジブラルタル", + "english": "Gibraltar", + "french": "Gibraltar", + "german": "Gibraltar", + "italian": "Gibilterra", + "spanish": "Gibraltar", + "chinese_simple": "直布罗陀", + "korean": "지브롤터", + "dutch": "Gibraltar", + "portuguese": "Gibraltar", + "russian": "Гибралтар", + "chinese_traditional": "Gibraltar", + "unknown1": "Gibraltar", + "unknown2": "Gibraltar", + "unknown3": "Gibraltar", + "unknown4": "Gibraltar" + }, + "regions": [ + { + "id": 2063597568, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 36.128539628, + "longitude": -5.344373695000002 + } + }, + { + "id": 2063663104, + "name": "Gibraltar", + "translations": { + "japanese": "ジブラルタル", + "english": "Gibraltar", + "french": "Gibraltar", + "german": "Gibraltar", + "italian": "Gibilterra", + "spanish": "Gibraltar", + "chinese_simple": "直布罗陀", + "korean": "지브롤터", + "dutch": "Gibraltar", + "portuguese": "Gibraltar", + "russian": "Гибралтар", + "chinese_traditional": "Gibraltar", + "unknown1": "Gibraltar", + "unknown2": "Gibraltar", + "unknown3": "Gibraltar", + "unknown4": "Gibraltar" + }, + "coordinates": { + "latitude": 36.128539628, + "longitude": -5.344373695000002 + } + } + ] + }, + { + "id": 124, + "iso_code": "GG", + "name": "Guernsey", + "translations": { + "japanese": "ガーンジー島", + "english": "Guernsey", + "french": "Guernesey", + "german": "Guernsey", + "italian": "Guernsey", + "spanish": "Guernsey", + "chinese_simple": "根西", + "korean": "건지 섬", + "dutch": "Guernsey", + "portuguese": "Guernsey", + "russian": "Гернси", + "chinese_traditional": "Guernsey", + "unknown1": "Guernsey", + "unknown2": "Guernsey", + "unknown3": "Guernsey", + "unknown4": "Guernsey" + }, + "regions": [ + { + "id": 2080374784, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 49.449462328, + "longitude": -2.5483455840000033 + } + }, + { + "id": 2080440320, + "name": "Guernsey", + "translations": { + "japanese": "ガーンジー島", + "english": "Guernsey", + "french": "Guernesey", + "german": "Guernsey", + "italian": "Guernsey", + "spanish": "Guernsey", + "chinese_simple": "根西", + "korean": "건지 섬", + "dutch": "Guernsey", + "portuguese": "Guernsey", + "russian": "Гернси", + "chinese_traditional": "Guernsey", + "unknown1": "Guernsey", + "unknown2": "Guernsey", + "unknown3": "Guernsey", + "unknown4": "Guernsey" + }, + "coordinates": { + "latitude": 49.449462328, + "longitude": -2.5483455840000033 + } + } + ] + }, + { + "id": 125, + "iso_code": "IM", + "name": "Isle of Man", + "translations": { + "japanese": "マン島", + "english": "Isle of Man", + "french": "Île de Man", + "german": "Isle of Man", + "italian": "Isola di Man", + "spanish": "Isla de Man", + "chinese_simple": "马恩岛", + "korean": "맨 섬", + "dutch": "Man", + "portuguese": "Ilha de Man", + "russian": "Мэн (остров)", + "chinese_traditional": "Isle of Man", + "unknown1": "Isle of Man", + "unknown2": "Isle of Man", + "unknown3": "Isle of Man", + "unknown4": "Isle of Man" + }, + "regions": [ + { + "id": 2097152000, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 54.16259704, + "longitude": -4.481944591999991 + } + }, + { + "id": 2097217536, + "name": "Isle of Man", + "translations": { + "japanese": "マン島", + "english": "Isle of Man", + "french": "Île de Man", + "german": "Isle of Man", + "italian": "Isola di Man", + "spanish": "Isla de Man", + "chinese_simple": "马恩岛", + "korean": "맨 섬", + "dutch": "Man", + "portuguese": "Ilha de Man", + "russian": "Мэн (остров)", + "chinese_traditional": "Isle of Man", + "unknown1": "Isle of Man", + "unknown2": "Isle of Man", + "unknown3": "Isle of Man", + "unknown4": "Isle of Man" + }, + "coordinates": { + "latitude": 54.16259704, + "longitude": -4.481944591999991 + } + } + ] + }, + { + "id": 126, + "iso_code": "JE", + "name": "Jersey", + "translations": { + "japanese": "ジャージー島", + "english": "Jersey", + "french": "Jersey", + "german": "Jersey", + "italian": "Jersey", + "spanish": "Jersey", + "chinese_simple": "泽西", + "korean": "저지 섬", + "dutch": "Jersey", + "portuguese": "Jérsia", + "russian": "Джерси", + "chinese_traditional": "Jersey", + "unknown1": "Jersey", + "unknown2": "Jersey", + "unknown3": "Jersey", + "unknown4": "Jersey" + }, + "regions": [ + { + "id": 2113929216, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 49.185790456, + "longitude": -2.1088912639999933 + } + }, + { + "id": 2113994752, + "name": "Jersey", + "translations": { + "japanese": "ジャージー島", + "english": "Jersey", + "french": "Jersey", + "german": "Jersey", + "italian": "Jersey", + "spanish": "Jersey", + "chinese_simple": "泽西", + "korean": "저지 섬", + "dutch": "Jersey", + "portuguese": "Jérsia", + "russian": "Джерси", + "chinese_traditional": "Jersey", + "unknown1": "Jersey", + "unknown2": "Jersey", + "unknown3": "Jersey", + "unknown4": "Jersey" + }, + "coordinates": { + "latitude": 49.185790456, + "longitude": -2.1088912639999933 + } + } + ] + }, + { + "id": 127, + "iso_code": "MC", + "name": "Monaco", + "translations": { + "japanese": "モナコ", + "english": "Monaco", + "french": "Monaco", + "german": "Monaco", + "italian": "Monaco (Principato di)", + "spanish": "Mónaco", + "chinese_simple": "摩纳哥", + "korean": "모나코", + "dutch": "Monaco", + "portuguese": "Mónaco", + "russian": "Монако", + "chinese_traditional": "Monaco", + "unknown1": "Monaco", + "unknown2": "Monaco", + "unknown3": "Monaco", + "unknown4": "Monaco" + }, + "regions": [ + { + "id": 2130706432, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 43.714599112, + "longitude": 7.41579165 + } + }, + { + "id": 2130771968, + "name": "Monaco", + "translations": { + "japanese": "モナコ", + "english": "Monaco", + "french": "Monaco", + "german": "Monaco", + "italian": "Monaco (Principato di)", + "spanish": "Mónaco", + "chinese_simple": "摩纳哥", + "korean": "모나코", + "dutch": "Monaco", + "portuguese": "Mónaco", + "russian": "Монако", + "chinese_traditional": "Monaco", + "unknown1": "Monaco", + "unknown2": "Monaco", + "unknown3": "Monaco", + "unknown4": "Monaco" + }, + "coordinates": { + "latitude": 43.714599112, + "longitude": 7.41579165 + } + } + ] + }, + { + "id": 128, + "iso_code": "TW", + "name": "Taiwan", + "translations": { + "japanese": "台湾", + "english": "Taiwan", + "french": "Taïwan", + "german": "Taiwan", + "italian": "Taiwan", + "spanish": "Taiwán", + "chinese_simple": "中国 台湾", + "korean": "타이완", + "dutch": "Taiwan", + "portuguese": "Taiwan", + "russian": "Тайвань", + "chinese_traditional": "臺灣", + "unknown1": "Taiwan", + "unknown2": "Taiwan", + "unknown3": "Taiwan", + "unknown4": "Taiwan" + }, + "regions": [ + { + "id": 2147483648, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 25.032348348, + "longitude": 121.503626301 + } + }, + { + "id": 2147614720, + "name": "Taipei City", + "translations": { + "japanese": "台北市", + "english": "Taipei City", + "french": "Taipei", + "german": "Taipeh", + "italian": "Taipei", + "spanish": "Taipéi", + "chinese_simple": "-", + "korean": "타이베이", + "dutch": "Taipei", + "portuguese": "Taipei", + "russian": "Тайбэй", + "chinese_traditional": "臺北市", + "unknown1": "Taipei City", + "unknown2": "Taipei City", + "unknown3": "Taipei City", + "unknown4": "Taipei City" + }, + "coordinates": { + "latitude": 25.032348348, + "longitude": 121.503626301 + } + }, + { + "id": 2147680256, + "name": "Kaohsiung City", + "translations": { + "japanese": "高雄市", + "english": "Kaohsiung City", + "french": "Kaohsiung", + "german": "Kaohsiung", + "italian": "Kaohsiung", + "spanish": "Condado de Kaohsiung", + "chinese_simple": "-", + "korean": "가오슝", + "dutch": "Kaohsiung", + "portuguese": "Condado de Kaohsiung", + "russian": "Гаосюн", + "chinese_traditional": "高雄市", + "unknown1": "Kaohsiung City", + "unknown2": "Kaohsiung City", + "unknown3": "Kaohsiung City", + "unknown4": "Kaohsiung City" + }, + "coordinates": { + "latitude": 22.598876696, + "longitude": 120.278647384 + } + }, + { + "id": 2147745792, + "name": "Keelung City", + "translations": { + "japanese": "基隆市", + "english": "Keelung City", + "french": "Keelung", + "german": "Keelung", + "italian": "Keelung", + "spanish": "Keelung", + "chinese_simple": "-", + "korean": "지룽", + "dutch": "Chilung", + "portuguese": "Keelung", + "russian": "Килунг", + "chinese_traditional": "基隆市", + "unknown1": "Keelung City", + "unknown2": "Keelung City", + "unknown3": "Keelung City", + "unknown4": "Keelung City" + }, + "coordinates": { + "latitude": 25.120238972, + "longitude": 121.734339819 + } + }, + { + "id": 2147811328, + "name": "Hsinchu City", + "translations": { + "japanese": "新竹市", + "english": "Hsinchu City", + "french": "Hsinchu", + "german": "Hsinchu", + "italian": "Hsinchu", + "spanish": "Hsinchu", + "chinese_simple": "-", + "korean": "신주", + "dutch": "Hsinchu", + "portuguese": "Hsinchu", + "russian": "Синьчжу", + "chinese_traditional": "新竹市", + "unknown1": "Hsinchu City", + "unknown2": "Hsinchu City", + "unknown3": "Hsinchu City", + "unknown4": "Hsinchu City" + }, + "coordinates": { + "latitude": 24.724731164, + "longitude": 120.954308401 + } + }, + { + "id": 2147876864, + "name": "Taichung City", + "translations": { + "japanese": "台中市", + "english": "Taichung City", + "french": "Taichung", + "german": "Taichung", + "italian": "Taichung", + "spanish": "Taichung", + "chinese_simple": "-", + "korean": "타이중", + "dutch": "Taichung", + "portuguese": "Taichung", + "russian": "Тайчжун", + "chinese_traditional": "臺中市", + "unknown1": "Taichung City", + "unknown2": "Taichung City", + "unknown3": "Taichung City", + "unknown4": "Taichung City" + }, + "coordinates": { + "latitude": 24.131469452, + "longitude": 120.646690377 + } + }, + { + "id": 2147942400, + "name": "Chiayi City", + "translations": { + "japanese": "嘉義市", + "english": "Chiayi City", + "french": "Chiayi", + "german": "Chiayi", + "italian": "Chiayi", + "spanish": "Chiayi", + "chinese_simple": "-", + "korean": "자이", + "dutch": "Chiayi", + "portuguese": "Chiayi", + "russian": "Цзяи", + "chinese_traditional": "嘉義市", + "unknown1": "Chiayi City", + "unknown2": "Chiayi City", + "unknown3": "Chiayi City", + "unknown4": "Chiayi City" + }, + "coordinates": { + "latitude": 23.461303444, + "longitude": 120.448935933 + } + }, + { + "id": 2148007936, + "name": "Tainan City", + "translations": { + "japanese": "台南市", + "english": "Tainan City", + "french": "Tainan", + "german": "Tainan", + "italian": "Tainan", + "spanish": "Tainan", + "chinese_simple": "-", + "korean": "타이난", + "dutch": "Tainan", + "portuguese": "Tainan", + "russian": "Тайнань", + "chinese_traditional": "臺南市", + "unknown1": "Tainan City", + "unknown2": "Tainan City", + "unknown3": "Tainan City", + "unknown4": "Tainan City" + }, + "coordinates": { + "latitude": 22.98889134, + "longitude": 120.19075652 + } + }, + { + "id": 2148073472, + "name": "New Taipei City", + "translations": { + "japanese": "新北市", + "english": "New Taipei City", + "french": "Nouveau Taipei", + "german": "Xinbei", + "italian": "New Taipei", + "spanish": "Nuevo Taipéi", + "chinese_simple": "-", + "korean": "신베이", + "dutch": "Nieuw Taipei", + "portuguese": "Nova Taipei", + "russian": "Новый Тайбэй", + "chinese_traditional": "新北市", + "unknown1": "New Taipei City", + "unknown2": "New Taipei City", + "unknown3": "New Taipei City", + "unknown4": "New Taipei City" + }, + "coordinates": { + "latitude": 24.977416708, + "longitude": 121.448694511 + } + }, + { + "id": 2148139008, + "name": "Taoyuan City", + "translations": { + "japanese": "桃園市", + "english": "Taoyuan City", + "french": "Taoyuan", + "german": "Taoyuan", + "italian": "Taoyuan", + "spanish": "Ciudad de Taoyuan", + "chinese_simple": "-", + "korean": "타오위안", + "dutch": "Taoyuan", + "portuguese": "Cidade de Taoyuan", + "russian": "Таоюань", + "chinese_traditional": "桃園市", + "unknown1": "Taoyuan City", + "unknown2": "Taoyuan City", + "unknown3": "Taoyuan City", + "unknown4": "Taoyuan City" + }, + "coordinates": { + "latitude": 24.971923544, + "longitude": 121.28939232 + } + }, + { + "id": 2148204544, + "name": "HsinChu County", + "translations": { + "japanese": "新竹県", + "english": "HsinChu County", + "french": "Hsinchu (comté de)", + "german": "Kreis Hsinchu", + "italian": "Contea di HsinChu", + "spanish": "Condado de Hsinchu", + "chinese_simple": "-", + "korean": "신주 현", + "dutch": "HsinChu", + "portuguese": "Condado de Hsinchu", + "russian": "Синьчжу (уезд)", + "chinese_traditional": "新竹縣", + "unknown1": "HsinChu County", + "unknown2": "HsinChu County", + "unknown3": "HsinChu County", + "unknown4": "HsinChu County" + }, + "coordinates": { + "latitude": 24.82910128, + "longitude": 120.99825383299999 + } + }, + { + "id": 2148270080, + "name": "Miaoli County", + "translations": { + "japanese": "苗栗県", + "english": "Miaoli County", + "french": "Miaoli (comté de)", + "german": "Kreis Miaoli", + "italian": "Contea di Miaoli", + "spanish": "Distrito de Miaoli", + "chinese_simple": "-", + "korean": "먀오리 현", + "dutch": "Miaoli", + "portuguese": "Distrito de Miaoli", + "russian": "Мяоли (уезд)", + "chinese_traditional": "苗栗縣", + "unknown1": "Miaoli County", + "unknown2": "Miaoli County", + "unknown3": "Miaoli County", + "unknown4": "Miaoli County" + }, + "coordinates": { + "latitude": 24.532470424, + "longitude": 120.79500621 + } + }, + { + "id": 2148335616, + "name": "Taichung County", + "translations": { + "japanese": "台中県", + "english": "Taichung County", + "french": "Taichung (comté de)", + "german": "Kreis Taichung", + "italian": "Contea di Taichung", + "spanish": "Condado de Taichung", + "chinese_simple": "-", + "korean": "타이중 현", + "dutch": "Taichung", + "portuguese": "Condado de Taichung", + "russian": "Тайчжун (уезд)", + "chinese_traditional": "Taichung County", + "unknown1": "Taichung County", + "unknown2": "Taichung County", + "unknown3": "Taichung County", + "unknown4": "Taichung County" + }, + "coordinates": { + "latitude": 24.219360076, + "longitude": 120.701622167 + } + }, + { + "id": 2148401152, + "name": "Changhua County", + "translations": { + "japanese": "彰化県", + "english": "Changhua County", + "french": "Changhua (comté de)", + "german": "Kreis Changhua", + "italian": "Contea di Changhua", + "spanish": "Condado de Changhua", + "chinese_simple": "-", + "korean": "장화 현", + "dutch": "Changhua", + "portuguese": "Condado de Changhua", + "russian": "Чжанхуа (уезд)", + "chinese_traditional": "彰化縣", + "unknown1": "Changhua County", + "unknown2": "Changhua County", + "unknown3": "Changhua County", + "unknown4": "Changhua County" + }, + "coordinates": { + "latitude": 24.065551484, + "longitude": 120.531333618 + } + }, + { + "id": 2148466688, + "name": "Nantou County", + "translations": { + "japanese": "南投県", + "english": "Nantou County", + "french": "Nantou (comté de)", + "german": "Kreis Nantou", + "italian": "Contea di Nantou", + "spanish": "Condado de Nantou", + "chinese_simple": "-", + "korean": "난터우 현", + "dutch": "Nantou", + "portuguese": "Condado de Nantou", + "russian": "Наньтоу (уезд)", + "chinese_traditional": "南投縣", + "unknown1": "Nantou County", + "unknown2": "Nantou County", + "unknown3": "Nantou County", + "unknown4": "Nantou County" + }, + "coordinates": { + "latitude": 23.8952634, + "longitude": 120.696128988 + } + }, + { + "id": 2148532224, + "name": "Yunlin County", + "translations": { + "japanese": "雲林県", + "english": "Yunlin County", + "french": "Yunlin (comté de)", + "german": "Kreis Yunlin", + "italian": "Contea di Yunlin", + "spanish": "Condado de Yunlin", + "chinese_simple": "-", + "korean": "윈린 현", + "dutch": "Yunlin", + "portuguese": "Condado de Yunlin", + "russian": "Юньлинь (уезд)", + "chinese_traditional": "雲林縣", + "unknown1": "Yunlin County", + "unknown2": "Yunlin County", + "unknown3": "Yunlin County", + "unknown4": "Yunlin County" + }, + "coordinates": { + "latitude": 23.686523168, + "longitude": 120.52584043899999 + } + }, + { + "id": 2148597760, + "name": "Chiayi County", + "translations": { + "japanese": "嘉義県", + "english": "Chiayi County", + "french": "Chiayi (comté de)", + "german": "Kreis Chiayi", + "italian": "Contea di Chiayi", + "spanish": "Condado de Chiayi", + "chinese_simple": "-", + "korean": "자이 현", + "dutch": "Chiayi", + "portuguese": "Condado de Chiayi", + "russian": "Цзяи (уезд)", + "chinese_traditional": "嘉義縣", + "unknown1": "Chiayi County", + "unknown2": "Chiayi County", + "unknown3": "Chiayi County", + "unknown4": "Chiayi County" + }, + "coordinates": { + "latitude": 23.461303444, + "longitude": 120.448935933 + } + }, + { + "id": 2148663296, + "name": "Tainan County", + "translations": { + "japanese": "台南県", + "english": "Tainan County", + "french": "Tainan (comté de)", + "german": "Kreis Tainan", + "italian": "Contea di Tainan", + "spanish": "Condado de Tainan", + "chinese_simple": "-", + "korean": "타이난 현", + "dutch": "Tainan", + "portuguese": "Condado de Tainan", + "russian": "Тайнань (уезд)", + "chinese_traditional": "Tainan County", + "unknown1": "Tainan County", + "unknown2": "Tainan County", + "unknown3": "Tainan County", + "unknown4": "Tainan County" + }, + "coordinates": { + "latitude": 23.049316144, + "longitude": 120.333579174 + } + }, + { + "id": 2148728832, + "name": "Kaohsiung County", + "translations": { + "japanese": "高雄県", + "english": "Kaohsiung County", + "french": "Kaohsiung (comté de)", + "german": "Kreis Kaohsiung", + "italian": "Contea di Kaohsiung", + "spanish": "Distrito de Kaohsiung", + "chinese_simple": "-", + "korean": "가오슝 현", + "dutch": "Kaohsiung", + "portuguese": "Distrito de Kaohsiung", + "russian": "Гаосюн (уезд)", + "chinese_traditional": "Kaohsiung County", + "unknown1": "Kaohsiung County", + "unknown2": "Kaohsiung County", + "unknown3": "Kaohsiung County", + "unknown4": "Kaohsiung County" + }, + "coordinates": { + "latitude": 22.620849352, + "longitude": 120.350058711 + } + }, + { + "id": 2148794368, + "name": "Pingtung County", + "translations": { + "japanese": "屏東県", + "english": "Pingtung County", + "french": "Pingtung (comté de)", + "german": "Kreis Pingtung", + "italian": "Contea di Pingtung", + "spanish": "Condado de Pingtung", + "chinese_simple": "-", + "korean": "핑둥 현", + "dutch": "Pingtung", + "portuguese": "Condado de Pingtung", + "russian": "Пиндун (уезд)", + "chinese_traditional": "屏東縣", + "unknown1": "Pingtung County", + "unknown2": "Pingtung County", + "unknown3": "Pingtung County", + "unknown4": "Pingtung County" + }, + "coordinates": { + "latitude": 22.664794664, + "longitude": 120.498374544 + } + }, + { + "id": 2148859904, + "name": "Yilan County", + "translations": { + "japanese": "宜蘭県", + "english": "Yilan County", + "french": "Ilan (comté de)", + "german": "Kreis Yilan", + "italian": "Contea di Yilan", + "spanish": "Condado de Yilan", + "chinese_simple": "-", + "korean": "이란 현", + "dutch": "Yilan", + "portuguese": "Condado de Yilan", + "russian": "Илань (уезд)", + "chinese_traditional": "宜蘭縣", + "unknown1": "Yilan County", + "unknown2": "Yilan County", + "unknown3": "Yilan County", + "unknown4": "Yilan County" + }, + "coordinates": { + "latitude": 24.763183312, + "longitude": 121.745326177 + } + }, + { + "id": 2148925440, + "name": "Hualien County", + "translations": { + "japanese": "花蓮県", + "english": "Hualien County", + "french": "Hualien (comté de)", + "german": "Kreis Hualien", + "italian": "Contea di Hualien", + "spanish": "Condado de Hualien", + "chinese_simple": "-", + "korean": "화롄 현", + "dutch": "Hualien", + "portuguese": "Condado de Hualien", + "russian": "Хуалянь (уезд)", + "chinese_traditional": "花蓮縣", + "unknown1": "Hualien County", + "unknown2": "Hualien County", + "unknown3": "Hualien County", + "unknown4": "Hualien County" + }, + "coordinates": { + "latitude": 23.983154024, + "longitude": 121.629969418 + } + }, + { + "id": 2148990976, + "name": "Taitung County", + "translations": { + "japanese": "台東県", + "english": "Taitung County", + "french": "Taitung (comté de)", + "german": "Kreis Taitung", + "italian": "Contea di Taitung", + "spanish": "Condado de Taitung", + "chinese_simple": "-", + "korean": "타이둥 현", + "dutch": "Taitung", + "portuguese": "Condado de Taitung", + "russian": "Тайдун (уезд)", + "chinese_traditional": "臺東縣", + "unknown1": "Taitung County", + "unknown2": "Taitung County", + "unknown3": "Taitung County", + "unknown4": "Taitung County" + }, + "coordinates": { + "latitude": 22.752685288, + "longitude": 121.14107648699999 + } + }, + { + "id": 2149056512, + "name": "Penghu County", + "translations": { + "japanese": "澎湖県", + "english": "Penghu County", + "french": "Penghu (comté de)", + "german": "Kreis Penghu", + "italian": "Contea di Penghu", + "spanish": "Islas Pescadores", + "chinese_simple": "-", + "korean": "펑후 현", + "dutch": "Penghu", + "portuguese": "Ilhas Pescadores", + "russian": "Пэнху (уезд)", + "chinese_traditional": "澎湖縣", + "unknown1": "Penghu County", + "unknown2": "Penghu County", + "unknown3": "Penghu County", + "unknown4": "Penghu County" + }, + "coordinates": { + "latitude": 23.56567356, + "longitude": 119.58101365099999 + } + }, + { + "id": 2149122048, + "name": "Kinmen County", + "translations": { + "japanese": "金門県", + "english": "Kinmen County", + "french": "Kinmen (comté de)", + "german": "Kreis Kinmen", + "italian": "Contea di Kinmen", + "spanish": "Condado de Kinmen", + "chinese_simple": "-", + "korean": "진먼 현", + "dutch": "Kinmen", + "portuguese": "Condado de Kinmen", + "russian": "Цзиньмэн (уезд)", + "chinese_traditional": "金門縣", + "unknown1": "Kinmen County", + "unknown2": "Kinmen County", + "unknown3": "Kinmen County", + "unknown4": "Kinmen County" + }, + "coordinates": { + "latitude": 24.428100308, + "longitude": 118.328568839 + } + }, + { + "id": 2149187584, + "name": "Lienchiang County", + "translations": { + "japanese": "連江県", + "english": "Lienchiang County", + "french": "Lienchiang (comté de)", + "german": "Kreis Lienchiang", + "italian": "Contea di Lienchiang", + "spanish": "Condado de Lienchiang", + "chinese_simple": "-", + "korean": "롄장 현", + "dutch": "Lienchiang", + "portuguese": "Condado de Lienchiang", + "russian": "Ляньцзян (уезд)", + "chinese_traditional": "連江縣", + "unknown1": "Lienchiang County", + "unknown2": "Lienchiang County", + "unknown3": "Lienchiang County", + "unknown4": "Lienchiang County" + }, + "coordinates": { + "latitude": 26.14746064, + "longitude": 119.927083928 + } + } + ] + }, + { + "id": 136, + "iso_code": "KR", + "name": "South Korea", + "translations": { + "japanese": "韓国", + "english": "South Korea", + "french": "Corée du Sud", + "german": "Südkorea", + "italian": "Corea del Sud", + "spanish": "Corea del Sur", + "chinese_simple": "韩国", + "korean": "대한민국", + "dutch": "Zuid-Korea", + "portuguese": "Coreia do Sul", + "russian": "Южная Корея", + "chinese_traditional": "韓國", + "unknown1": "South Korea", + "unknown2": "South Korea", + "unknown3": "South Korea", + "unknown4": "South Korea" + }, + "regions": [ + { + "id": 2281701376, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 37.496337464, + "longitude": 126.996805301 + } + }, + { + "id": 2281832448, + "name": "Seoul-teukbyeolsi", + "translations": { + "japanese": "ソウル特別市", + "english": "Seoul-teukbyeolsi", + "french": "Séoul", + "german": "Seoul", + "italian": "Seoul", + "spanish": "Seúl", + "chinese_simple": "首尔特别市", + "korean": "서울특별시", + "dutch": "Seoul", + "portuguese": "Seul", + "russian": "Сеул", + "chinese_traditional": "首爾特別市", + "unknown1": "Seoul-teukbyeolsi", + "unknown2": "Seoul-teukbyeolsi", + "unknown3": "Seoul-teukbyeolsi", + "unknown4": "Seoul-teukbyeolsi" + }, + "coordinates": { + "latitude": 37.496337464, + "longitude": 126.996805301 + } + }, + { + "id": 2281897984, + "name": "Busan-gwangyeoksi", + "translations": { + "japanese": "プサン広域市", + "english": "Busan-gwangyeoksi", + "french": "Pusan", + "german": "Busan", + "italian": "Busan", + "spanish": "Busán", + "chinese_simple": "釜山广域市", + "korean": "부산광역시", + "dutch": "Busan", + "portuguese": "Busan", + "russian": "Пусан", + "chinese_traditional": "釜山廣域市", + "unknown1": "Busan-gwangyeoksi", + "unknown2": "Busan-gwangyeoksi", + "unknown3": "Busan-gwangyeoksi", + "unknown4": "Busan-gwangyeoksi" + }, + "coordinates": { + "latitude": 35.079345304, + "longitude": 129.029281531 + } + }, + { + "id": 2281963520, + "name": "Daegu-gwangyeoksi", + "translations": { + "japanese": "テグ広域市", + "english": "Daegu-gwangyeoksi", + "french": "Daegu", + "german": "Daegu", + "italian": "Daegu", + "spanish": "Daegu", + "chinese_simple": "大邱广域市", + "korean": "대구광역시", + "dutch": "Daegu", + "portuguese": "Daegu", + "russian": "Тэгу", + "chinese_traditional": "大邱廣域市", + "unknown1": "Daegu-gwangyeoksi", + "unknown2": "Daegu-gwangyeoksi", + "unknown3": "Daegu-gwangyeoksi", + "unknown4": "Daegu-gwangyeoksi" + }, + "coordinates": { + "latitude": 35.848388264, + "longitude": 128.578840853 + } + }, + { + "id": 2282029056, + "name": "Incheon-gwangyeoksi", + "translations": { + "japanese": "インチョン広域市", + "english": "Incheon-gwangyeoksi", + "french": "Incheon", + "german": "Incheon", + "italian": "Incheon", + "spanish": "Incheon", + "chinese_simple": "仁川广域市", + "korean": "인천광역시", + "dutch": "Incheon", + "portuguese": "Incheon", + "russian": "Инчхон", + "chinese_traditional": "仁川廣域市", + "unknown1": "Incheon-gwangyeoksi", + "unknown2": "Incheon-gwangyeoksi", + "unknown3": "Incheon-gwangyeoksi", + "unknown4": "Incheon-gwangyeoksi" + }, + "coordinates": { + "latitude": 37.496337464, + "longitude": 126.62876230799999 + } + }, + { + "id": 2282094592, + "name": "Gwangju-gwangyeoksi", + "translations": { + "japanese": "クァンジュ広域市", + "english": "Gwangju-gwangyeoksi", + "french": "Gwangju", + "german": "Gwangju", + "italian": "Gwangju", + "spanish": "Gwangju", + "chinese_simple": "光州广域市", + "korean": "광주광역시", + "dutch": "Gwangju", + "portuguese": "Gwangju", + "russian": "Кванджу", + "chinese_traditional": "光州廣域市", + "unknown1": "Gwangju-gwangyeoksi", + "unknown2": "Gwangju-gwangyeoksi", + "unknown3": "Gwangju-gwangyeoksi", + "unknown4": "Gwangju-gwangyeoksi" + }, + "coordinates": { + "latitude": 35.112304288, + "longitude": 126.86496900499999 + } + }, + { + "id": 2282160128, + "name": "Daejeon-gwangyeoksi", + "translations": { + "japanese": "テジョン広域市", + "english": "Daejeon-gwangyeoksi", + "french": "Daejeon", + "german": "Daejeon", + "italian": "Daejeon", + "spanish": "Daejeon", + "chinese_simple": "大田广域市", + "korean": "대전광역시", + "dutch": "Daejeon", + "portuguese": "Daejeon", + "russian": "Тэджон", + "chinese_traditional": "大田廣域市", + "unknown1": "Daejeon-gwangyeoksi", + "unknown2": "Daejeon-gwangyeoksi", + "unknown3": "Daejeon-gwangyeoksi", + "unknown4": "Daejeon-gwangyeoksi" + }, + "coordinates": { + "latitude": 36.348266188000004, + "longitude": 127.43076644199999 + } + }, + { + "id": 2282225664, + "name": "Ulsan-gwangyeoksi", + "translations": { + "japanese": "ウルサン広域市", + "english": "Ulsan-gwangyeoksi", + "french": "Ulsan", + "german": "Ulsan", + "italian": "Ulsan", + "spanish": "Ulsan", + "chinese_simple": "蔚山广域市", + "korean": "울산광역시", + "dutch": "Ulsan", + "portuguese": "Ulsan", + "russian": "Ульсан", + "chinese_traditional": "蔚山廣域市", + "unknown1": "Ulsan-gwangyeoksi", + "unknown2": "Ulsan-gwangyeoksi", + "unknown3": "Ulsan-gwangyeoksi", + "unknown4": "Ulsan-gwangyeoksi" + }, + "coordinates": { + "latitude": 35.51330526, + "longitude": 129.36436545 + } + }, + { + "id": 2282291200, + "name": "Gyeonggi-do", + "translations": { + "japanese": "キョンギ道", + "english": "Gyeonggi-do", + "french": "Gyeonggi", + "german": "Gyeonggi-do", + "italian": "Gyeonggi", + "spanish": "Gyeonggi", + "chinese_simple": "京畿道", + "korean": "경기도", + "dutch": "Gyeonggi-do", + "portuguese": "Gyeonggi", + "russian": "Кёнгидо", + "chinese_traditional": "京畿道", + "unknown1": "Gyeonggi-do", + "unknown2": "Gyeonggi-do", + "unknown3": "Gyeonggi-do", + "unknown4": "Gyeonggi-do" + }, + "coordinates": { + "latitude": 37.496337464, + "longitude": 126.996805301 + } + }, + { + "id": 2282356736, + "name": "Gangwon-do", + "translations": { + "japanese": "カンウォン道", + "english": "Gangwon-do", + "french": "Gangwon", + "german": "Gangwon-do", + "italian": "Gangwon", + "spanish": "Gangwon", + "chinese_simple": "江原道", + "korean": "강원도", + "dutch": "Gangwon-do", + "portuguese": "Gangwon", + "russian": "Канвондо", + "chinese_traditional": "江原道", + "unknown1": "Gangwon-do", + "unknown2": "Gangwon-do", + "unknown3": "Gangwon-do", + "unknown4": "Gangwon-do" + }, + "coordinates": { + "latitude": 37.93029742, + "longitude": 127.765850361 + } + }, + { + "id": 2282422272, + "name": "Chungcheongbuk-do", + "translations": { + "japanese": "チュンチョンブク道", + "english": "Chungcheongbuk-do", + "french": "Chungcheong du Nord", + "german": "Chungcheongbuk-do", + "italian": "Chungcheong Settentrionale", + "spanish": "Chungcheong del Norte", + "chinese_simple": "忠清北道", + "korean": "충청북도", + "dutch": "Noord-Chungcheong", + "portuguese": "Chungcheong do Norte", + "russian": "Чхунчхон-Пукто", + "chinese_traditional": "忠清北道", + "unknown1": "Chungcheongbuk-do", + "unknown2": "Chungcheongbuk-do", + "unknown3": "Chungcheongbuk-do", + "unknown4": "Chungcheongbuk-do" + }, + "coordinates": { + "latitude": 36.963500556, + "longitude": 127.88120712 + } + }, + { + "id": 2282487808, + "name": "Chungcheongnam-do", + "translations": { + "japanese": "チュンチョンナム道", + "english": "Chungcheongnam-do", + "french": "Chungcheong du Sud", + "german": "Chungcheongnam-do", + "italian": "Chungcheong Meridionale", + "spanish": "Chungcheong del Sur", + "chinese_simple": "忠清南道", + "korean": "충청남도", + "dutch": "Zuid-Chungcheong", + "portuguese": "Chungcheong do Sul", + "russian": "Чхунчхон-Намдо", + "chinese_traditional": "忠清南道", + "unknown1": "Chungcheongnam-do", + "unknown2": "Chungcheongnam-do", + "unknown3": "Chungcheongnam-do", + "unknown4": "Chungcheongnam-do" + }, + "coordinates": { + "latitude": 36.348266188000004, + "longitude": 127.43076644199999 + } + }, + { + "id": 2282553344, + "name": "Jeollabuk-do", + "translations": { + "japanese": "チョルラブク道", + "english": "Jeollabuk-do", + "french": "Jeolla du Nord", + "german": "Jeollabuk-do", + "italian": "Jeolla Settentrionale", + "spanish": "Jeolla del Norte", + "chinese_simple": "全罗北道", + "korean": "전라북도", + "dutch": "Noord-Jeolla", + "portuguese": "Jeolla do Norte", + "russian": "Чолла-Пукто", + "chinese_traditional": "全羅北道", + "unknown1": "Jeollabuk-do", + "unknown2": "Jeollabuk-do", + "unknown3": "Jeollabuk-do", + "unknown4": "Jeollabuk-do" + }, + "coordinates": { + "latitude": 35.848388264, + "longitude": 127.079202986 + } + }, + { + "id": 2282618880, + "name": "Jeollanam-do", + "translations": { + "japanese": "チョルラナム道", + "english": "Jeollanam-do", + "french": "Jeolla du Sud", + "german": "Jeollanam-do", + "italian": "Jeolla Meridionale", + "spanish": "Jeolla del Sur", + "chinese_simple": "全罗南道", + "korean": "전라남도", + "dutch": "Zuid-Jeolla", + "portuguese": "Jeolla do Sul", + "russian": "Чолла-Намдо", + "chinese_traditional": "全羅南道", + "unknown1": "Jeollanam-do", + "unknown2": "Jeollanam-do", + "unknown3": "Jeollanam-do", + "unknown4": "Jeollanam-do" + }, + "coordinates": { + "latitude": 35.112304288, + "longitude": 126.86496900499999 + } + }, + { + "id": 2282684416, + "name": "Gyeongsangbuk-do", + "translations": { + "japanese": "キョンサンブク道", + "english": "Gyeongsangbuk-do", + "french": "Gyeongsang du Nord", + "german": "Gyeongsangbuk-do", + "italian": "Gyeongsang Settentrionale", + "spanish": "Gyeongsang del Norte", + "chinese_simple": "庆尚北道", + "korean": "경상북도", + "dutch": "Noord-Gyeongsang", + "portuguese": "Gyeongsang do Norte", + "russian": "Кёнсан-Пукто", + "chinese_traditional": "慶尚北道", + "unknown1": "Gyeongsangbuk-do", + "unknown2": "Gyeongsangbuk-do", + "unknown3": "Gyeongsangbuk-do", + "unknown4": "Gyeongsangbuk-do" + }, + "coordinates": { + "latitude": 35.848388264, + "longitude": 128.578840853 + } + }, + { + "id": 2282749952, + "name": "Gyeongsangnam-do", + "translations": { + "japanese": "キョンサンナム道", + "english": "Gyeongsangnam-do", + "french": "Gyeongsang du Sud", + "german": "Gyeongsangnam-do", + "italian": "Gyeongsang Meridionale", + "spanish": "Gyeongsang del Sur", + "chinese_simple": "庆尚南道", + "korean": "경상남도", + "dutch": "Zuid-Gyeongsang", + "portuguese": "Gyeongsang do Sul", + "russian": "Кёнсан-Намдо", + "chinese_traditional": "慶尚南道", + "unknown1": "Gyeongsangnam-do", + "unknown2": "Gyeongsangnam-do", + "unknown3": "Gyeongsangnam-do", + "unknown4": "Gyeongsangnam-do" + }, + "coordinates": { + "latitude": 35.299071864, + "longitude": 128.65025218 + } + }, + { + "id": 2282815488, + "name": "Jeju-teukbyeoljachido", + "translations": { + "japanese": "チェジュ特別自治道", + "english": "Jeju-teukbyeoljachido", + "french": "Jeju", + "german": "Jeju-do", + "italian": "Jeju", + "spanish": "Jeju", + "chinese_simple": "济州特别自治道", + "korean": "제주특별자치도", + "dutch": "Jeju-do", + "portuguese": "Jeju", + "russian": "Чеджудо", + "chinese_traditional": "濟州特別自治道", + "unknown1": "Jeju-teukbyeoljachido", + "unknown2": "Jeju-teukbyeoljachido", + "unknown3": "Jeju-teukbyeoljachido", + "unknown4": "Jeju-teukbyeoljachido" + }, + "coordinates": { + "latitude": 33.513793564, + "longitude": 126.529885086 + } + } + ] + }, + { + "id": 144, + "iso_code": "HK", + "name": "Hong Kong", + "translations": { + "japanese": "ホンコン", + "english": "Hong Kong", + "french": "Hong Kong", + "german": "Hongkong", + "italian": "Hong Kong", + "spanish": "Hong Kong", + "chinese_simple": "中国 香港", + "korean": "홍콩", + "dutch": "Hongkong", + "portuguese": "Hong Kong", + "russian": "Гонконг", + "chinese_traditional": "香港", + "unknown1": "Hong Kong", + "unknown2": "Hong Kong", + "unknown3": "Hong Kong", + "unknown4": "Hong Kong" + }, + "regions": [ + { + "id": 2415919104, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 22.461547596, + "longitude": 114.296575453 + } + }, + { + "id": 2415984640, + "name": "Hong Kong", + "translations": { + "japanese": "ホンコン", + "english": "Hong Kong", + "french": "Hong Kong", + "german": "Hongkong", + "italian": "Hong Kong", + "spanish": "Hong Kong", + "chinese_simple": "中国 香港", + "korean": "홍콩", + "dutch": "Hongkong", + "portuguese": "Hong Kong", + "russian": "Гонконг", + "chinese_traditional": "香港", + "unknown1": "Hong Kong", + "unknown2": "Hong Kong", + "unknown3": "Hong Kong", + "unknown4": "Hong Kong" + }, + "coordinates": { + "latitude": 22.461547596, + "longitude": 114.296575453 + } + } + ] + }, + { + "id": 145, + "iso_code": "MO", + "name": "Macao", + "translations": { + "japanese": "マカオ", + "english": "Macao", + "french": "Macao", + "german": "Macau", + "italian": "Macao", + "spanish": "Macao", + "chinese_simple": "中国 澳门", + "korean": "마카오", + "dutch": "Macau", + "portuguese": "Macau", + "russian": "Макао", + "chinese_traditional": "澳門", + "unknown1": "Macao", + "unknown2": "Macao", + "unknown3": "Macao", + "unknown4": "Macao" + }, + "regions": [ + { + "id": 2432696320, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 22.214355216, + "longitude": 113.59894172 + } + }, + { + "id": 2432761856, + "name": "Macao", + "translations": { + "japanese": "マカオ", + "english": "Macao", + "french": "Macao", + "german": "Macau", + "italian": "Macao", + "spanish": "Macao", + "chinese_simple": "中国 澳门", + "korean": "마카오", + "dutch": "Macau", + "portuguese": "Macau", + "russian": "Макао", + "chinese_traditional": "澳門", + "unknown1": "Macao", + "unknown2": "Macao", + "unknown3": "Macao", + "unknown4": "Macao" + }, + "coordinates": { + "latitude": 22.214355216, + "longitude": 113.59894172 + } + } + ] + }, + { + "id": 153, + "iso_code": "SG", + "name": "Singapore", + "translations": { + "japanese": "シンガポール", + "english": "Singapore", + "french": "Singapour", + "german": "Singapur", + "italian": "Singapore", + "spanish": "Singapur", + "chinese_simple": "新加坡", + "korean": "싱가포르", + "dutch": "Singapore", + "portuguese": "Singapura", + "russian": "Сингапур", + "chinese_traditional": "Singapore", + "unknown1": "Singapore", + "unknown2": "Singapore", + "unknown3": "Singapore", + "unknown4": "Singapore" + }, + "regions": [ + { + "id": 2566914048, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 1.2908935400000001, + "longitude": 103.854042174 + } + }, + { + "id": 2566979584, + "name": "Singapore", + "translations": { + "japanese": "シンガポール", + "english": "Singapore", + "french": "Singapour", + "german": "Singapur", + "italian": "Singapore", + "spanish": "Singapur", + "chinese_simple": "新加坡", + "korean": "싱가포르", + "dutch": "Singapore", + "portuguese": "Singapura", + "russian": "Сингапур", + "chinese_traditional": "Singapore", + "unknown1": "Singapore", + "unknown2": "Singapore", + "unknown3": "Singapore", + "unknown4": "Singapore" + }, + "coordinates": { + "latitude": 1.2908935400000001, + "longitude": 103.854042174 + } + } + ] + }, + { + "id": 156, + "iso_code": "MY", + "name": "Malaysia", + "translations": { + "japanese": "マレーシア", + "english": "Malaysia", + "french": "Malaisie", + "german": "Malaysia", + "italian": "Malesia", + "spanish": "Malasia", + "chinese_simple": "马来西亚", + "korean": "말레이시아", + "dutch": "Maleisië", + "portuguese": "Malásia", + "russian": "Малайзия", + "chinese_traditional": "Malaysia", + "unknown1": "Malaysia", + "unknown2": "Malaysia", + "unknown3": "Malaysia", + "unknown4": "Malaysia" + }, + "regions": [ + { + "id": 2617245696, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 3.164062464, + "longitude": 101.695222827 + } + }, + { + "id": 2617376768, + "name": "Kuala Lumpur", + "translations": { + "japanese": "クアラ・ルンプール", + "english": "Kuala Lumpur", + "french": "Kuala Lumpur", + "german": "Kuala Lumpur", + "italian": "Kuala Lumpur", + "spanish": "Kuala Lumpur", + "chinese_simple": "吉隆坡联邦直辖区", + "korean": "쿠알라룸푸르", + "dutch": "Kuala Lumpur", + "portuguese": "Kuala Lumpur", + "russian": "Куала-Лумпур", + "chinese_traditional": "Kuala Lumpur", + "unknown1": "Kuala Lumpur", + "unknown2": "Kuala Lumpur", + "unknown3": "Kuala Lumpur", + "unknown4": "Kuala Lumpur" + }, + "coordinates": { + "latitude": 3.164062464, + "longitude": 101.695222827 + } + }, + { + "id": 2617442304, + "name": "Johor", + "translations": { + "japanese": "ジョホール州", + "english": "Johor", + "french": "Johor", + "german": "Johor", + "italian": "Johor", + "spanish": "Johor", + "chinese_simple": "柔佛州", + "korean": "조호르 주", + "dutch": "Johor", + "portuguese": "Johor", + "russian": "Джохор", + "chinese_traditional": "Johor", + "unknown1": "Johor", + "unknown2": "Johor", + "unknown3": "Johor", + "unknown4": "Johor" + }, + "coordinates": { + "latitude": 1.461181624, + "longitude": 103.749671773 + } + }, + { + "id": 2617507840, + "name": "Kedah", + "translations": { + "japanese": "ケダ州", + "english": "Kedah", + "french": "Kedah", + "german": "Kedah", + "italian": "Kedah", + "spanish": "Kedah", + "chinese_simple": "吉打州", + "korean": "케다 주", + "dutch": "Kedah", + "portuguese": "Kedah", + "russian": "Кедах", + "chinese_traditional": "Kedah", + "unknown1": "Kedah", + "unknown2": "Kedah", + "unknown3": "Kedah", + "unknown4": "Kedah" + }, + "coordinates": { + "latitude": 6.113891532, + "longitude": 100.365873509 + } + }, + { + "id": 2617573376, + "name": "Kelantan", + "translations": { + "japanese": "ケランタン州", + "english": "Kelantan", + "french": "Kelantan", + "german": "Kelantan", + "italian": "Kelantan", + "spanish": "Kelantan", + "chinese_simple": "吉兰丹州", + "korean": "켈란탄 주", + "dutch": "Kelantan", + "portuguese": "Kelantan", + "russian": "Келантан", + "chinese_traditional": "Kelantan", + "unknown1": "Kelantan", + "unknown2": "Kelantan", + "unknown3": "Kelantan", + "unknown4": "Kelantan" + }, + "coordinates": { + "latitude": 6.1303710240000004, + "longitude": 102.250033906 + } + }, + { + "id": 2617638912, + "name": "Melaka", + "translations": { + "japanese": "マラッカ州", + "english": "Melaka", + "french": "Malacca", + "german": "Malakka", + "italian": "Malacca", + "spanish": "Melaka", + "chinese_simple": "马六甲州", + "korean": "믈라카 주", + "dutch": "Malakka", + "portuguese": "Malacca", + "russian": "Малакка", + "chinese_traditional": "Melaka", + "unknown1": "Melaka", + "unknown2": "Melaka", + "unknown3": "Melaka", + "unknown4": "Melaka" + }, + "coordinates": { + "latitude": 2.191772436, + "longitude": 102.244540727 + } + }, + { + "id": 2617704448, + "name": "Negeri Sembilan", + "translations": { + "japanese": "ヌグリ・センビラン州", + "english": "Negeri Sembilan", + "french": "Negeri Sembilan", + "german": "Negeri Sembilan", + "italian": "Negeri Sembilan", + "spanish": "Negeri Sembilan", + "chinese_simple": "森美兰州", + "korean": "느그리슴빌란 주", + "dutch": "Negeri Sembilan", + "portuguese": "Negeri Sembilan", + "russian": "Негери-Сембелан", + "chinese_traditional": "Negeri Sembilan", + "unknown1": "Negeri Sembilan", + "unknown2": "Negeri Sembilan", + "unknown3": "Negeri Sembilan", + "unknown4": "Negeri Sembilan" + }, + "coordinates": { + "latitude": 2.713623016, + "longitude": 101.931429524 + } + }, + { + "id": 2617769984, + "name": "Pahang", + "translations": { + "japanese": "パハン州", + "english": "Pahang", + "french": "Pahang", + "german": "Pahang", + "italian": "Pahang", + "spanish": "Pahang", + "chinese_simple": "彭亨州", + "korean": "파항 주", + "dutch": "Pahang", + "portuguese": "Pahang", + "russian": "Паханг", + "chinese_traditional": "Pahang", + "unknown1": "Pahang", + "unknown2": "Pahang", + "unknown3": "Pahang", + "unknown4": "Pahang" + }, + "coordinates": { + "latitude": 3.795776324, + "longitude": 103.332190169 + } + }, + { + "id": 2617835520, + "name": "Perak", + "translations": { + "japanese": "ペラ州", + "english": "Perak", + "french": "Perak", + "german": "Perak", + "italian": "Perak", + "spanish": "Perak", + "chinese_simple": "霹雳州", + "korean": "페라크 주", + "dutch": "Perak", + "portuguese": "Perak", + "russian": "Перак", + "chinese_traditional": "Perak", + "unknown1": "Perak", + "unknown2": "Perak", + "unknown3": "Perak", + "unknown4": "Perak" + }, + "coordinates": { + "latitude": 4.581298776, + "longitude": 101.079986779 + } + }, + { + "id": 2617901056, + "name": "Perlis", + "translations": { + "japanese": "ペルリス州", + "english": "Perlis", + "french": "Perlis", + "german": "Perlis", + "italian": "Perlis", + "spanish": "Perlis", + "chinese_simple": "玻璃市州", + "korean": "페를리스 주", + "dutch": "Perlis", + "portuguese": "Perlis", + "russian": "Перлис", + "chinese_traditional": "Perlis", + "unknown1": "Perlis", + "unknown2": "Perlis", + "unknown3": "Perlis", + "unknown4": "Perlis" + }, + "coordinates": { + "latitude": 6.432495044, + "longitude": 100.19558496 + } + }, + { + "id": 2617966592, + "name": "Penang", + "translations": { + "japanese": "ピナン州", + "english": "Penang", + "french": "Penang", + "german": "Penang", + "italian": "Penang", + "spanish": "Penang", + "chinese_simple": "槟榔屿州", + "korean": "피낭 주", + "dutch": "Penang", + "portuguese": "Penang", + "russian": "Пулау-Пинанг", + "chinese_traditional": "Penang", + "unknown1": "Penang", + "unknown2": "Penang", + "unknown3": "Penang", + "unknown4": "Penang" + }, + "coordinates": { + "latitude": 5.416259704, + "longitude": 100.33291443499999 + } + }, + { + "id": 2618032128, + "name": "Sarawak", + "translations": { + "japanese": "サラワク州", + "english": "Sarawak", + "french": "Sarawak", + "german": "Sarawak", + "italian": "Sarawak", + "spanish": "Sarawak", + "chinese_simple": "沙捞越州", + "korean": "사라왁 주", + "dutch": "Sarawak", + "portuguese": "Sarawak", + "russian": "Саравак", + "chinese_traditional": "Sarawak", + "unknown1": "Sarawak", + "unknown2": "Sarawak", + "unknown3": "Sarawak", + "unknown4": "Sarawak" + }, + "coordinates": { + "latitude": 1.549072248, + "longitude": 110.330500215 + } + }, + { + "id": 2618097664, + "name": "Selangor", + "translations": { + "japanese": "セランゴール州", + "english": "Selangor", + "french": "Selangor", + "german": "Selangor", + "italian": "Selangor", + "spanish": "Selangor", + "chinese_simple": "雪兰莪州", + "korean": "셀랑고르 주", + "dutch": "Selangor", + "portuguese": "Selangor", + "russian": "Селангор", + "chinese_traditional": "Selangor", + "unknown1": "Selangor", + "unknown2": "Selangor", + "unknown3": "Selangor", + "unknown4": "Selangor" + }, + "coordinates": { + "latitude": 3.081665004, + "longitude": 101.530427457 + } + }, + { + "id": 2618163200, + "name": "Terengganu", + "translations": { + "japanese": "トレンガヌ州", + "english": "Terengganu", + "french": "Terengganu", + "german": "Terengganu", + "italian": "Terengganu", + "spanish": "Terengganu", + "chinese_simple": "丁加奴州", + "korean": "트렝가누 주", + "dutch": "Terengganu", + "portuguese": "Terengganu", + "russian": "Тренгану", + "chinese_traditional": "Terengganu", + "unknown1": "Terengganu", + "unknown2": "Terengganu", + "unknown3": "Terengganu", + "unknown4": "Terengganu" + }, + "coordinates": { + "latitude": 5.32836908, + "longitude": 103.128942546 + } + }, + { + "id": 2618228736, + "name": "Labuan", + "translations": { + "japanese": "ラブアン", + "english": "Labuan", + "french": "Labuan", + "german": "Labuan", + "italian": "Labuan", + "spanish": "Labuan", + "chinese_simple": "纳闽联邦直辖区", + "korean": "라부안", + "dutch": "Labuan", + "portuguese": "Labuan", + "russian": "Лабуан", + "chinese_traditional": "Labuan", + "unknown1": "Labuan", + "unknown2": "Labuan", + "unknown3": "Labuan", + "unknown4": "Labuan" + }, + "coordinates": { + "latitude": 5.27343744, + "longitude": 115.241402241 + } + }, + { + "id": 2618294272, + "name": "Sabah", + "translations": { + "japanese": "サバ州", + "english": "Sabah", + "french": "Sabah", + "german": "Sabah", + "italian": "Sabah", + "spanish": "Sabah", + "chinese_simple": "沙巴州", + "korean": "사바 주", + "dutch": "Sabah", + "portuguese": "Sabah", + "russian": "Сабах", + "chinese_traditional": "Sabah", + "unknown1": "Sabah", + "unknown2": "Sabah", + "unknown3": "Sabah", + "unknown4": "Sabah" + }, + "coordinates": { + "latitude": 5.982055596, + "longitude": 116.065379091 + } + }, + { + "id": 2618359808, + "name": "Putrajaya", + "translations": { + "japanese": "プトラジャヤ", + "english": "Putrajaya", + "french": "Putrajaya", + "german": "Putrajaya", + "italian": "Putrajaya", + "spanish": "Putrajaya", + "chinese_simple": "布城联邦直辖区", + "korean": "푸트라자야", + "dutch": "Putrajaya", + "portuguese": "Putrajaya", + "russian": "Путраджая", + "chinese_traditional": "Putrajaya", + "unknown1": "Putrajaya", + "unknown2": "Putrajaya", + "unknown3": "Putrajaya", + "unknown4": "Putrajaya" + }, + "coordinates": { + "latitude": 2.91137692, + "longitude": 101.662263753 + } + } + ] + }, + { + "id": 160, + "iso_code": "CN", + "name": "China", + "translations": { + "japanese": "中国", + "english": "China", + "french": "Chine", + "german": "China", + "italian": "Cina", + "spanish": "China", + "chinese_simple": "中国", + "korean": "중국", + "dutch": "China", + "portuguese": "China", + "russian": "Китай", + "chinese_traditional": "中國", + "unknown1": "China", + "unknown2": "China", + "unknown3": "China", + "unknown4": "China" + }, + "regions": [ + { + "id": 2684354560, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 39.913329624, + "longitude": 116.433422084 + } + }, + { + "id": 2684485632, + "name": "Beijing", + "translations": { + "japanese": "北京市", + "english": "Beijing", + "french": "Pékin", + "german": "Peking", + "italian": "Pechino", + "spanish": "Pekín", + "chinese_simple": "北京市", + "korean": "베이징", + "dutch": "Beijing", + "portuguese": "Pequim", + "russian": "Пекин", + "chinese_traditional": "北京市", + "unknown1": "Beijing", + "unknown2": "Beijing", + "unknown3": "Beijing", + "unknown4": "Beijing" + }, + "coordinates": { + "latitude": 39.913329624, + "longitude": 116.433422084 + } + }, + { + "id": 2684551168, + "name": "Chongqing", + "translations": { + "japanese": "重慶市", + "english": "Chongqing", + "french": "Chongqing", + "german": "Chongqing", + "italian": "Chongqing", + "spanish": "Chongqing", + "chinese_simple": "重庆市", + "korean": "충칭", + "dutch": "Tsjoengking", + "portuguese": "Chongqing", + "russian": "Чунцин", + "chinese_traditional": "重慶市", + "unknown1": "Chongqing", + "unknown2": "Chongqing", + "unknown3": "Chongqing", + "unknown4": "Chongqing" + }, + "coordinates": { + "latitude": 29.597167632, + "longitude": 106.364424977 + } + }, + { + "id": 2684616704, + "name": "Shanghai", + "translations": { + "japanese": "上海市", + "english": "Shanghai", + "french": "Shanghai", + "german": "Shanghai", + "italian": "Shanghai", + "spanish": "Shanghái", + "chinese_simple": "上海市", + "korean": "상하이", + "dutch": "Sjanghai", + "portuguese": "Xangai", + "russian": "Шанхай", + "chinese_traditional": "上海市", + "unknown1": "Shanghai", + "unknown2": "Shanghai", + "unknown3": "Shanghai", + "unknown4": "Shanghai" + }, + "coordinates": { + "latitude": 31.245116832, + "longitude": 121.47066722699999 + } + }, + { + "id": 2684682240, + "name": "Tianjin", + "translations": { + "japanese": "天津市", + "english": "Tianjin", + "french": "Tianjin", + "german": "Tianjin", + "italian": "Tientsin", + "spanish": "Tianjin", + "chinese_simple": "天津市", + "korean": "톈진", + "dutch": "Tianjin", + "portuguese": "Tianjin", + "russian": "Тяньцзинь", + "chinese_traditional": "天津市", + "unknown1": "Tianjin", + "unknown2": "Tianjin", + "unknown3": "Tianjin", + "unknown4": "Tianjin" + }, + "coordinates": { + "latitude": 39.149779828, + "longitude": 117.180494428 + } + }, + { + "id": 2684747776, + "name": "Anhui", + "translations": { + "japanese": "安徽省", + "english": "Anhui", + "french": "Anhui", + "german": "Anhui", + "italian": "Anhui", + "spanish": "Anhui", + "chinese_simple": "安徽省", + "korean": "안후이 성", + "dutch": "Anhui", + "portuguese": "Anhui", + "russian": "Аньхой", + "chinese_traditional": "安徽省", + "unknown1": "Anhui", + "unknown2": "Anhui", + "unknown3": "Anhui", + "unknown4": "Anhui" + }, + "coordinates": { + "latitude": 31.931762332, + "longitude": 117.31233072399999 + } + }, + { + "id": 2684813312, + "name": "Fujian", + "translations": { + "japanese": "福建省", + "english": "Fujian", + "french": "Fujian", + "german": "Fujian", + "italian": "Fujian", + "spanish": "Fujian", + "chinese_simple": "福建省", + "korean": "푸젠 성", + "dutch": "Fujian", + "portuguese": "Fujian", + "russian": "Фуцзянь", + "chinese_traditional": "福建省", + "unknown1": "Fujian", + "unknown2": "Fujian", + "unknown3": "Fujian", + "unknown4": "Fujian" + }, + "coordinates": { + "latitude": 26.081542672, + "longitude": 119.29536834299999 + } + }, + { + "id": 2684878848, + "name": "Gansu", + "translations": { + "japanese": "甘粛省", + "english": "Gansu", + "french": "Gansu", + "german": "Gansu", + "italian": "Gansu", + "spanish": "Gansu", + "chinese_simple": "甘肃省", + "korean": "간쑤 성", + "dutch": "Gansu", + "portuguese": "Gansu", + "russian": "Ганьсу", + "chinese_traditional": "甘肅省", + "unknown1": "Gansu", + "unknown2": "Gansu", + "unknown3": "Gansu", + "unknown4": "Gansu" + }, + "coordinates": { + "latitude": 36.029662676, + "longitude": 103.749671773 + } + }, + { + "id": 2684944384, + "name": "Guangdong", + "translations": { + "japanese": "広東省", + "english": "Guangdong", + "french": "Guangdong", + "german": "Guangdong", + "italian": "Guangdong", + "spanish": "Cantón", + "chinese_simple": "广东省", + "korean": "광둥 성", + "dutch": "Guangdong", + "portuguese": "Guangdong", + "russian": "Гуандун", + "chinese_traditional": "廣東省", + "unknown1": "Guangdong", + "unknown2": "Guangdong", + "unknown3": "Guangdong", + "unknown4": "Guangdong" + }, + "coordinates": { + "latitude": 23.09875462, + "longitude": 113.099062431 + } + }, + { + "id": 2685009920, + "name": "Guizhou", + "translations": { + "japanese": "貴州省", + "english": "Guizhou", + "french": "Guizhou", + "german": "Guizhou", + "italian": "Guizhou", + "spanish": "Guizhou", + "chinese_simple": "贵州省", + "korean": "구이저우 성", + "dutch": "Guizhou", + "portuguese": "Guizhou", + "russian": "Гуйчжоу", + "chinese_traditional": "貴州省", + "unknown1": "Guizhou", + "unknown2": "Guizhou", + "unknown3": "Guizhou", + "unknown4": "Guizhou" + }, + "coordinates": { + "latitude": 26.564941104, + "longitude": 106.683029359 + } + }, + { + "id": 2685075456, + "name": "Hainan", + "translations": { + "japanese": "海南省", + "english": "Hainan", + "french": "Hainan", + "german": "Hainan", + "italian": "Hainan", + "spanish": "Hainan", + "chinese_simple": "海南省", + "korean": "하이난 성", + "dutch": "Hainan", + "portuguese": "Hainan", + "russian": "Хайнань", + "chinese_traditional": "海南省", + "unknown1": "Hainan", + "unknown2": "Hainan", + "unknown3": "Hainan", + "unknown4": "Hainan" + }, + "coordinates": { + "latitude": 20.083007584, + "longitude": 110.330500215 + } + }, + { + "id": 2685140992, + "name": "Hebei", + "translations": { + "japanese": "河北省", + "english": "Hebei", + "french": "Hebei", + "german": "Hebei", + "italian": "Hebei", + "spanish": "Hebei", + "chinese_simple": "河北省", + "korean": "허베이 성", + "dutch": "Hebei", + "portuguese": "Hebei", + "russian": "Хэбэй", + "chinese_traditional": "河北省", + "unknown1": "Hebei", + "unknown2": "Hebei", + "unknown3": "Hebei", + "unknown4": "Hebei" + }, + "coordinates": { + "latitude": 38.045653864, + "longitude": 114.466864002 + } + }, + { + "id": 2685206528, + "name": "Heilongjiang", + "translations": { + "japanese": "黒龍江省", + "english": "Heilongjiang", + "french": "Heilongjiang", + "german": "Heilongjiang", + "italian": "Heilongjiang", + "spanish": "Heilongjiang", + "chinese_simple": "黑龙江省", + "korean": "헤이룽장 성", + "dutch": "Heilongjiang", + "portuguese": "Heilongjang", + "russian": "Хэйлунцзян", + "chinese_traditional": "黑龍江省", + "unknown1": "Heilongjiang", + "unknown2": "Heilongjiang", + "unknown3": "Heilongjiang", + "unknown4": "Heilongjiang" + }, + "coordinates": { + "latitude": 45.763549284, + "longitude": 126.700173635 + } + }, + { + "id": 2685272064, + "name": "Henan", + "translations": { + "japanese": "河南省", + "english": "Henan", + "french": "Henan", + "german": "Henan", + "italian": "Henan", + "spanish": "Henan", + "chinese_simple": "河南省", + "korean": "허난 성", + "dutch": "Henan", + "portuguese": "Henan", + "russian": "Хэнань", + "chinese_traditional": "河南省", + "unknown1": "Henan", + "unknown2": "Henan", + "unknown3": "Henan", + "unknown4": "Henan" + }, + "coordinates": { + "latitude": 34.595946872, + "longitude": 113.631900794 + } + }, + { + "id": 2685337600, + "name": "Hubei", + "translations": { + "japanese": "湖北省", + "english": "Hubei", + "french": "Hubei", + "german": "Hubei", + "italian": "Hubei", + "spanish": "Hubei", + "chinese_simple": "湖北省", + "korean": "후베이 성", + "dutch": "Hubei", + "portuguese": "Hubei", + "russian": "Хубэй", + "chinese_traditional": "湖北省", + "unknown1": "Hubei", + "unknown2": "Hubei", + "unknown3": "Hubei", + "unknown4": "Hubei" + }, + "coordinates": { + "latitude": 30.580443988, + "longitude": 114.31305499 + } + }, + { + "id": 2685403136, + "name": "Húnán", + "translations": { + "japanese": "湖南省", + "english": "Húnán", + "french": "Hunan", + "german": "Hunan", + "italian": "Hunan", + "spanish": "Hunan", + "chinese_simple": "湖南省", + "korean": "후난 성", + "dutch": "Hunan", + "portuguese": "Hunan", + "russian": "Хунань", + "chinese_traditional": "湖南省", + "unknown1": "Húnán", + "unknown2": "Húnán", + "unknown3": "Húnán", + "unknown4": "Húnán" + }, + "coordinates": { + "latitude": 28.17993132, + "longitude": 112.978212493 + } + }, + { + "id": 2685468672, + "name": "Jiangsu", + "translations": { + "japanese": "江蘇省", + "english": "Jiangsu", + "french": "Jiangsu", + "german": "Jiangsu", + "italian": "Jiangsu", + "spanish": "Jiangsu", + "chinese_simple": "江苏省", + "korean": "장쑤 성", + "dutch": "Jiangsu", + "portuguese": "Jiangsu", + "russian": "Цзянсу", + "chinese_traditional": "江蘇省", + "unknown1": "Jiangsu", + "unknown2": "Jiangsu", + "unknown3": "Jiangsu", + "unknown4": "Jiangsu" + }, + "coordinates": { + "latitude": 32.030639284, + "longitude": 118.828448128 + } + }, + { + "id": 2685534208, + "name": "Jiangxi", + "translations": { + "japanese": "江西省", + "english": "Jiangxi", + "french": "Jiangxi", + "german": "Jiangxi", + "italian": "Jiangxi", + "spanish": "Jiangxi", + "chinese_simple": "江西省", + "korean": "장시 성", + "dutch": "Jiangxi", + "portuguese": "Jiangxi", + "russian": "Цзянси", + "chinese_traditional": "江西省", + "unknown1": "Jiangxi", + "unknown2": "Jiangxi", + "unknown3": "Jiangxi", + "unknown4": "Jiangxi" + }, + "coordinates": { + "latitude": 28.630370768, + "longitude": 115.933542795 + } + }, + { + "id": 2685599744, + "name": "Jilin", + "translations": { + "japanese": "吉林省", + "english": "Jilin", + "french": "Jilin", + "german": "Jilin", + "italian": "Jilin", + "spanish": "Jilin", + "chinese_simple": "吉林省", + "korean": "지린 성", + "dutch": "Jilin", + "portuguese": "Jilin", + "russian": "Гирин", + "chinese_traditional": "吉林省", + "unknown1": "Jilin", + "unknown2": "Jilin", + "unknown3": "Jilin", + "unknown4": "Jilin" + }, + "coordinates": { + "latitude": 43.895873524, + "longitude": 125.282933453 + } + }, + { + "id": 2685665280, + "name": "Liaoning", + "translations": { + "japanese": "遼寧省", + "english": "Liaoning", + "french": "Liaoning", + "german": "Liaoning", + "italian": "Liaoning", + "spanish": "Liaoning", + "chinese_simple": "辽宁省", + "korean": "랴오닝 성", + "dutch": "Liaoning", + "portuguese": "Liaoning", + "russian": "Ляонин", + "chinese_traditional": "遼寧省", + "unknown1": "Liaoning", + "unknown2": "Liaoning", + "unknown3": "Liaoning", + "unknown4": "Liaoning" + }, + "coordinates": { + "latitude": 41.797484876, + "longitude": 123.382293519 + } + }, + { + "id": 2685730816, + "name": "Qinghai", + "translations": { + "japanese": "青海省", + "english": "Qinghai", + "french": "Qinghai", + "german": "Qinghai", + "italian": "Qinghai", + "spanish": "Qinghai", + "chinese_simple": "青海省", + "korean": "칭하이 성", + "dutch": "Qinghai", + "portuguese": "Qinghai", + "russian": "Цинхай", + "chinese_traditional": "青海省", + "unknown1": "Qinghai", + "unknown2": "Qinghai", + "unknown3": "Qinghai", + "unknown4": "Qinghai" + }, + "coordinates": { + "latitude": 36.595458568, + "longitude": 101.914949987 + } + }, + { + "id": 2685796352, + "name": "Shanxi", + "translations": { + "japanese": "陝西省", + "english": "Shanxi", + "french": "Shaanxi", + "german": "Shaanxi", + "italian": "Shaanxi", + "spanish": "Shaanxi", + "chinese_simple": "陕西省", + "korean": "산시 성", + "dutch": "Shaanxi", + "portuguese": "Shaanxi", + "russian": "Шэньси", + "chinese_traditional": "陝西省", + "unknown1": "Shanxi", + "unknown2": "Shanxi", + "unknown3": "Shanxi", + "unknown4": "Shanxi" + }, + "coordinates": { + "latitude": 34.266357032, + "longitude": 108.896780496 + } + }, + { + "id": 2685861888, + "name": "Shandong", + "translations": { + "japanese": "山東省", + "english": "Shandong", + "french": "Shandong", + "german": "Shandong", + "italian": "Shandong", + "spanish": "Shandong", + "chinese_simple": "山东省", + "korean": "산둥 성", + "dutch": "Shandong", + "portuguese": "Shandong", + "russian": "Шаньдун", + "chinese_traditional": "山東省", + "unknown1": "Shandong", + "unknown2": "Shandong", + "unknown3": "Shandong", + "unknown4": "Shandong" + }, + "coordinates": { + "latitude": 36.716308176, + "longitude": 117.015699058 + } + }, + { + "id": 2685927424, + "name": "Shanxi", + "translations": { + "japanese": "山西省", + "english": "Shanxi", + "french": "Shanxi", + "german": "Shanxi", + "italian": "Shanxi", + "spanish": "Shanxi", + "chinese_simple": "山西省", + "korean": "산시 성", + "dutch": "Shanxi", + "portuguese": "Shanxi", + "russian": "Шаньси", + "chinese_traditional": "山西省", + "unknown1": "Shanxi", + "unknown2": "Shanxi", + "unknown3": "Shanxi", + "unknown4": "Shanxi" + }, + "coordinates": { + "latitude": 37.831420468, + "longitude": 112.50030592 + } + }, + { + "id": 2685992960, + "name": "Sichuan", + "translations": { + "japanese": "四川省", + "english": "Sichuan", + "french": "Sichuan", + "german": "Sichuan", + "italian": "Sichuan", + "spanish": "Sichuan", + "chinese_simple": "四川省", + "korean": "쓰촨 성", + "dutch": "Sichuan", + "portuguese": "Sichuan", + "russian": "Сычуань", + "chinese_traditional": "四川省", + "unknown1": "Sichuan", + "unknown2": "Sichuan", + "unknown3": "Sichuan", + "unknown4": "Sichuan" + }, + "coordinates": { + "latitude": 30.629882464, + "longitude": 104.112221587 + } + }, + { + "id": 2686058496, + "name": "Yunnan", + "translations": { + "japanese": "雲南省", + "english": "Yunnan", + "french": "Yunnan", + "german": "Yunnan", + "italian": "Yunnan", + "spanish": "Yunnan", + "chinese_simple": "云南省", + "korean": "윈난 성", + "dutch": "Yunnan", + "portuguese": "Yunnan", + "russian": "Юньнань", + "chinese_traditional": "雲南省", + "unknown1": "Yunnan", + "unknown2": "Yunnan", + "unknown3": "Yunnan", + "unknown4": "Yunnan" + }, + "coordinates": { + "latitude": 25.065307332, + "longitude": 102.678501868 + } + }, + { + "id": 2686124032, + "name": "Zhejiang", + "translations": { + "japanese": "浙江省", + "english": "Zhejiang", + "french": "Zhejiang", + "german": "Zhejiang", + "italian": "Zhejiang", + "spanish": "Zhejiang", + "chinese_simple": "浙江省", + "korean": "저장 성", + "dutch": "Zhejiang", + "portuguese": "Zhejiang", + "russian": "Чжэцзян", + "chinese_traditional": "浙江省", + "unknown1": "Zhejiang", + "unknown2": "Zhejiang", + "unknown3": "Zhejiang", + "unknown4": "Zhejiang" + }, + "coordinates": { + "latitude": 30.29479946, + "longitude": 120.113852014 + } + }, + { + "id": 2686189568, + "name": "Taiwan", + "translations": { + "japanese": "台湾省", + "english": "Taiwan", + "french": "Taiwan", + "german": "Taiwan", + "italian": "Taiwan", + "spanish": "Taiwán", + "chinese_simple": "台湾省", + "korean": "타이완 성", + "dutch": "Taiwan", + "portuguese": "Taiwan", + "russian": "Тайвань", + "chinese_traditional": "台灣省", + "unknown1": "Taiwan", + "unknown2": "Taiwan", + "unknown3": "Taiwan", + "unknown4": "Taiwan" + }, + "coordinates": { + "latitude": 25.032348348, + "longitude": 121.503626301 + } + }, + { + "id": 2686255104, + "name": "Guangxi-Zhuangzu", + "translations": { + "japanese": "広西チワン族自治区", + "english": "Guangxi-Zhuangzu", + "french": "Guangxi", + "german": "Guangxi", + "italian": "Guangxi Zhuang", + "spanish": "Guangxi", + "chinese_simple": "广西壮族自治区", + "korean": "광시좡 족 자치구", + "dutch": "Guangxi", + "portuguese": "Guangxi", + "russian": "Гуанси-Чжуанский автономный район", + "chinese_traditional": "廣西壯族自治區", + "unknown1": "Guangxi-Zhuangzu", + "unknown2": "Guangxi-Zhuangzu", + "unknown3": "Guangxi-Zhuangzu", + "unknown4": "Guangxi-Zhuangzu" + }, + "coordinates": { + "latitude": 22.829589584, + "longitude": 108.314503522 + } + }, + { + "id": 2686320640, + "name": "Nei-Menggu", + "translations": { + "japanese": "内モンゴル自治区", + "english": "Nei-Menggu", + "french": "Mongolie Intérieure", + "german": "Innere Mongolei", + "italian": "Mongolia Interna", + "spanish": "Mongolia Interior", + "chinese_simple": "内蒙古自治区", + "korean": "네이멍구 자치구", + "dutch": "Binnen-Mongolië", + "portuguese": "Mongólia interior", + "russian": "Автономный район Внутренняя Монголия", + "chinese_traditional": "內蒙古自治區", + "unknown1": "Nei-Menggu", + "unknown2": "Nei-Menggu", + "unknown3": "Nei-Menggu", + "unknown4": "Nei-Menggu" + }, + "coordinates": { + "latitude": 40.81420852, + "longitude": 111.615904101 + } + }, + { + "id": 2686386176, + "name": "Ningxia-huizu", + "translations": { + "japanese": "寧夏回族自治区", + "english": "Ningxia-huizu", + "french": "Ningxia", + "german": "Ningxia", + "italian": "Ningxia Hui", + "spanish": "Ningxia", + "chinese_simple": "宁夏回族自治区", + "korean": "닝샤후이 족 자치구", + "dutch": "Ningxia", + "portuguese": "Ningxia", + "russian": "Нинся-Хуэйский автономный район", + "chinese_traditional": "寧夏回族自治區", + "unknown1": "Ningxia-huizu", + "unknown2": "Ningxia-huizu", + "unknown3": "Ningxia-huizu", + "unknown4": "Ningxia-huizu" + }, + "coordinates": { + "latitude": 38.496093312, + "longitude": 106.314986366 + } + }, + { + "id": 2686451712, + "name": "Xinjiang-Weiwu'er-zu", + "translations": { + "japanese": "新疆ウイグル自治区", + "english": "Xinjiang-Weiwu'er-zu", + "french": "Xinjiang", + "german": "Xinjiang", + "italian": "Xinjiang Uygur", + "spanish": "Xinjiang", + "chinese_simple": "新疆维吾尔自治区", + "korean": "신장웨이우얼 자치구", + "dutch": "Xinjiang", + "portuguese": "Xinjiang", + "russian": "Синьцзян-Уйгурский автономный район", + "chinese_traditional": "新疆維吾爾自治區", + "unknown1": "Xinjiang-Weiwu'er-zu", + "unknown2": "Xinjiang-Weiwu'er-zu", + "unknown3": "Xinjiang-Weiwu'er-zu", + "unknown4": "Xinjiang-Weiwu'er-zu" + }, + "coordinates": { + "latitude": 43.78051708, + "longitude": 87.583245976 + } + }, + { + "id": 2686517248, + "name": "Xizang", + "translations": { + "japanese": "チベット自治区", + "english": "Xizang", + "french": "Tibet", + "german": "Tibet", + "italian": "Tibet", + "spanish": "Tíbet", + "chinese_simple": "西藏自治区", + "korean": "티베트 자치구", + "dutch": "Tibet", + "portuguese": "Tibete", + "russian": "Тибетский автономный район", + "chinese_traditional": "西藏自治區", + "unknown1": "Xizang", + "unknown2": "Xizang", + "unknown3": "Xizang", + "unknown4": "Xizang" + }, + "coordinates": { + "latitude": 29.6630856, + "longitude": 91.164798684 + } + }, + { + "id": 2686582784, + "name": "Macao", + "translations": { + "japanese": "マカオ", + "english": "Macao", + "french": "Macao", + "german": "Macau", + "italian": "Macao", + "spanish": "Macao", + "chinese_simple": "澳门特别行政区", + "korean": "마카오", + "dutch": "Macau", + "portuguese": "Macau", + "russian": "Макао", + "chinese_traditional": "澳門特別行政區", + "unknown1": "Macao", + "unknown2": "Macao", + "unknown3": "Macao", + "unknown4": "Macao" + }, + "coordinates": { + "latitude": 22.214355216, + "longitude": 113.59894172 + } + }, + { + "id": 2686648320, + "name": "Hong Kong", + "translations": { + "japanese": "ホンコン", + "english": "Hong Kong", + "french": "Hong Kong", + "german": "Hongkong", + "italian": "Hong Kong", + "spanish": "Hong Kong", + "chinese_simple": "香港特别行政区", + "korean": "홍콩", + "dutch": "Hongkong", + "portuguese": "Hong Kong", + "russian": "Гонконг", + "chinese_traditional": "香港特別行政區", + "unknown1": "Hong Kong", + "unknown2": "Hong Kong", + "unknown3": "Hong Kong", + "unknown4": "Hong Kong" + }, + "coordinates": { + "latitude": 22.461547596, + "longitude": 114.296575453 + } + } + ] + }, + { + "id": 168, + "iso_code": "AE", + "name": "U.A.E.", + "translations": { + "japanese": "アラブ首長国連邦", + "english": "U.A.E.", + "french": "Émirats arabes unis", + "german": "Vereinigte Arabische Emirate", + "italian": "Emirati Arabi Uniti", + "spanish": "Emiratos Árabes Unidos", + "chinese_simple": "阿拉伯联合酋长国", + "korean": "아랍에미리트", + "dutch": "Verenigde Arabische Emiraten", + "portuguese": "Emirados Árabes Unidos", + "russian": "Объединённые Арабские Эмираты", + "chinese_traditional": "U.A.E.", + "unknown1": "U.A.E.", + "unknown2": "U.A.E.", + "unknown3": "U.A.E.", + "unknown4": "U.A.E." + }, + "regions": [ + { + "id": 2818572288, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 24.466552456, + "longitude": 54.365992563 + } + }, + { + "id": 2818703360, + "name": "Abu Dhabi", + "translations": { + "japanese": "アブダビ", + "english": "Abu Dhabi", + "french": "Abu Dhabi", + "german": "Abu Dhabi", + "italian": "Abu Dhabi", + "spanish": "Abu Dabi", + "chinese_simple": "阿布扎比", + "korean": "아부다비", + "dutch": "Abu Dhabi", + "portuguese": "Abu Dabi", + "russian": "Абу-Даби", + "chinese_traditional": "Abu Dhabi", + "unknown1": "Abu Dhabi", + "unknown2": "Abu Dhabi", + "unknown3": "Abu Dhabi", + "unknown4": "Abu Dhabi" + }, + "coordinates": { + "latitude": 24.466552456, + "longitude": 54.365992563 + } + }, + { + "id": 2818768896, + "name": "Ajman", + "translations": { + "japanese": "アジュマン", + "english": "Ajman", + "french": "Ajman", + "german": "Adschman", + "italian": "Ajman", + "spanish": "Ajmán", + "chinese_simple": "阿治曼", + "korean": "아지만", + "dutch": "Ajman", + "portuguese": "Ajman", + "russian": "Аджман", + "chinese_traditional": "Ajman", + "unknown1": "Ajman", + "unknown2": "Ajman", + "unknown3": "Ajman", + "unknown4": "Ajman" + }, + "coordinates": { + "latitude": 25.4058835, + "longitude": 55.442655647 + } + }, + { + "id": 2818834432, + "name": "Ash Shariqah", + "translations": { + "japanese": "シャルジャ", + "english": "Ash Shariqah", + "french": "Sharjah", + "german": "Schardscha", + "italian": "Sharjah", + "spanish": "Sarja", + "chinese_simple": "沙迦", + "korean": "샤르자", + "dutch": "Sharjah", + "portuguese": "Sarja", + "russian": "Шарджа", + "chinese_traditional": "Ash Shariqah", + "unknown1": "Ash Shariqah", + "unknown2": "Ash Shariqah", + "unknown3": "Ash Shariqah", + "unknown4": "Ash Shariqah" + }, + "coordinates": { + "latitude": 24.999389364, + "longitude": 55.744780492 + } + }, + { + "id": 2818899968, + "name": "Ras al-Khaimah", + "translations": { + "japanese": "ラアス・アル・カイマー", + "english": "Ras al-Khaimah", + "french": "Ras al-Khaïmah", + "german": "Ras al-Chaima", + "italian": "Ras al-Khaimah", + "spanish": "Ras el Jaima", + "chinese_simple": "哈伊马角", + "korean": "라스알카이마", + "dutch": "Ras al-Khaimah", + "portuguese": "Ras el Jaima", + "russian": "Рас эль-Хайма", + "chinese_traditional": "Ras al-Khaimah", + "unknown1": "Ras al-Khaimah", + "unknown2": "Ras al-Khaimah", + "unknown3": "Ras al-Khaimah", + "unknown4": "Ras al-Khaimah" + }, + "coordinates": { + "latitude": 25.664062208, + "longitude": 55.997466726 + } + }, + { + "id": 2818965504, + "name": "Dubai", + "translations": { + "japanese": "ドゥバイ", + "english": "Dubai", + "french": "Dubaï", + "german": "Dubai", + "italian": "Dubai", + "spanish": "Dubái", + "chinese_simple": "迪拜", + "korean": "두바이", + "dutch": "Dubai", + "portuguese": "Dubai", + "russian": "Дубай", + "chinese_traditional": "Dubai", + "unknown1": "Dubai", + "unknown2": "Dubai", + "unknown3": "Dubai", + "unknown4": "Dubai" + }, + "coordinates": { + "latitude": 25.252074908, + "longitude": 55.277860277 + } + }, + { + "id": 2819031040, + "name": "Al Fujayrah", + "translations": { + "japanese": "フジャイラー", + "english": "Al Fujayrah", + "french": "Fujaïrah", + "german": "Fudschaira", + "italian": "Fujayrah", + "spanish": "Fujaira", + "chinese_simple": "富查伊拉", + "korean": "알푸자이라", + "dutch": "Fujairah", + "portuguese": "Fujaira", + "russian": "Фуджейра", + "chinese_traditional": "Al Fujayrah", + "unknown1": "Al Fujayrah", + "unknown2": "Al Fujayrah", + "unknown3": "Al Fujayrah", + "unknown4": "Al Fujayrah" + }, + "coordinates": { + "latitude": 25.120238972, + "longitude": 56.332550645 + } + }, + { + "id": 2819096576, + "name": "Umm al Qaywayn", + "translations": { + "japanese": "ウム・アル・カイワイン", + "english": "Umm al Qaywayn", + "french": "Umm al-Qaiwain", + "german": "Umm al-Qaiwain", + "italian": "Umm al-Qaiwain", + "spanish": "Um el Kaiwain", + "chinese_simple": "乌姆盖万", + "korean": "움알카이와인", + "dutch": "Umm al-Qaiwain", + "portuguese": "Um el Kaiwain", + "russian": "Умм эль-Кайвайн", + "chinese_traditional": "Umm al Qaywayn", + "unknown1": "Umm al Qaywayn", + "unknown2": "Umm al Qaywayn", + "unknown3": "Umm al Qaywayn", + "unknown4": "Umm al Qaywayn" + }, + "coordinates": { + "latitude": 25.499267288, + "longitude": 55.744780492 + } + } + ] + }, + { + "id": 174, + "iso_code": "SA", + "name": "Saudi Arabia", + "translations": { + "japanese": "サウジアラビア", + "english": "Saudi Arabia", + "french": "Arabie saoudite", + "german": "Saudi-Arabien", + "italian": "Arabia Saudita", + "spanish": "Arabia Saudí", + "chinese_simple": "沙特阿拉伯", + "korean": "사우디아라비아", + "dutch": "Saoedi-Arabië", + "portuguese": "Arábia Saudita", + "russian": "Саудовская Аравия", + "chinese_traditional": "Saudi Arabia", + "unknown1": "Saudi Arabia", + "unknown2": "Saudi Arabia", + "unknown3": "Saudi Arabia", + "unknown4": "Saudi Arabia" + }, + "regions": [ + { + "id": 2919235584, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 24.63684054, + "longitude": 46.768926006 + } + }, + { + "id": 2919366656, + "name": "Ar Riyad", + "translations": { + "japanese": "リヤド州", + "english": "Ar Riyad", + "french": "Riyad", + "german": "Riad", + "italian": "Al-Riyad", + "spanish": "Riad", + "chinese_simple": "利雅得地区", + "korean": "리야드 주", + "dutch": "Ar Riyad", + "portuguese": "Riad", + "russian": "Эр-Рияд", + "chinese_traditional": "Ar Riyad", + "unknown1": "Ar Riyad", + "unknown2": "Ar Riyad", + "unknown3": "Ar Riyad", + "unknown4": "Ar Riyad" + }, + "coordinates": { + "latitude": 24.63684054, + "longitude": 46.768926006 + } + }, + { + "id": 2919432192, + "name": "Al Bahah", + "translations": { + "japanese": "バーハ州", + "english": "Al Bahah", + "french": "Al Bâhah", + "german": "Baha", + "italian": "Al-Bahah", + "spanish": "Al Bahah", + "chinese_simple": "巴哈地区", + "korean": "알바하 주", + "dutch": "Al Bahah", + "portuguese": "Baha", + "russian": "Эль-Баха", + "chinese_traditional": "Al Bahah", + "unknown1": "Al Bahah", + "unknown2": "Al Bahah", + "unknown3": "Al Bahah", + "unknown4": "Al Bahah" + }, + "coordinates": { + "latitude": 20.011596452, + "longitude": 41.462515092 + } + }, + { + "id": 2919497728, + "name": "Al Madinah", + "translations": { + "japanese": "メディナ州", + "english": "Al Madinah", + "french": "Médine", + "german": "Medina", + "italian": "Medina", + "spanish": "Medina", + "chinese_simple": "麦地那地区", + "korean": "메디나 주", + "dutch": "Medina", + "portuguese": "Medina", + "russian": "Эль-Мадина", + "chinese_traditional": "Al Madinah", + "unknown1": "Al Madinah", + "unknown2": "Al Madinah", + "unknown3": "Al Madinah", + "unknown4": "Al Madinah" + }, + "coordinates": { + "latitude": 24.082030976, + "longitude": 38.045757754 + } + }, + { + "id": 2919563264, + "name": "Ash Sharqiyah", + "translations": { + "japanese": "東部州", + "english": "Ash Sharqiyah", + "french": "Province Est", + "german": "Asch-Scharqiyya", + "italian": "Ash-Sharqiyah", + "spanish": "Región Oriental", + "chinese_simple": "东部地区", + "korean": "샤르키야 주", + "dutch": "Ash Sharqiyah", + "portuguese": "Ash Sharqiyah", + "russian": "Эш-Шаркийя", + "chinese_traditional": "Ash Sharqiyah", + "unknown1": "Ash Sharqiyah", + "unknown2": "Ash Sharqiyah", + "unknown3": "Ash Sharqiyah", + "unknown4": "Ash Sharqiyah" + }, + "coordinates": { + "latitude": 26.42211884, + "longitude": 50.114272017 + } + }, + { + "id": 2919628800, + "name": "Al Qasim", + "translations": { + "japanese": "カスィーム州", + "english": "Al Qasim", + "french": "Al Qasim", + "german": "Qasim", + "italian": "Al-Qasim", + "spanish": "Al Qasim", + "chinese_simple": "卡西姆地区", + "korean": "카심 주", + "dutch": "Al Qasim", + "portuguese": "Qasim", + "russian": "Эль-Касим", + "chinese_traditional": "Al Qasim", + "unknown1": "Al Qasim", + "unknown2": "Al Qasim", + "unknown3": "Al Qasim", + "unknown4": "Al Qasim" + }, + "coordinates": { + "latitude": 26.328735052, + "longitude": 43.967404716 + } + }, + { + "id": 2919694336, + "name": "'Asir", + "translations": { + "japanese": "アシール州", + "english": "'Asir", + "french": "Assir", + "german": "Asir", + "italian": "'Asir", + "spanish": "Asir", + "chinese_simple": "阿西尔地区", + "korean": "아시르 주", + "dutch": "Asir", + "portuguese": "Assir", + "russian": "Асир", + "chinese_traditional": "'Asir", + "unknown1": "'Asir", + "unknown2": "'Asir", + "unknown3": "'Asir", + "unknown4": "'Asir" + }, + "coordinates": { + "latitude": 18.215331824, + "longitude": 42.500725923 + } + }, + { + "id": 2919759872, + "name": "Ha'il", + "translations": { + "japanese": "ハーイル州", + "english": "Ha'il", + "french": "Haïl", + "german": "Hail", + "italian": "Ha'il", + "spanish": "Hail", + "chinese_simple": "哈伊勒地区", + "korean": "하일 주", + "dutch": "Ha'il", + "portuguese": "Hail", + "russian": "Ха’иль", + "chinese_traditional": "Ha'il", + "unknown1": "Ha'il", + "unknown2": "Ha'il", + "unknown3": "Ha'il", + "unknown4": "Ha'il" + }, + "coordinates": { + "latitude": 27.3284909, + "longitude": 41.599844567 + } + }, + { + "id": 2919825408, + "name": "Makkah", + "translations": { + "japanese": "メッカ州", + "english": "Makkah", + "french": "La Mecque", + "german": "Mekka", + "italian": "Mecca", + "spanish": "La Meca", + "chinese_simple": "麦加地区", + "korean": "메카 주", + "dutch": "Mekka", + "portuguese": "Mecca", + "russian": "Мекка", + "chinese_traditional": "Makkah", + "unknown1": "Makkah", + "unknown2": "Makkah", + "unknown3": "Makkah", + "unknown4": "Makkah" + }, + "coordinates": { + "latitude": 21.4233396, + "longitude": 39.82554775 + } + }, + { + "id": 2919890944, + "name": "Al Hudud ash Shamaliyah", + "translations": { + "japanese": "北部国境州", + "english": "Al Hudud ash Shamaliyah", + "french": "Frontière Nord", + "german": "Al-Hudud asch-schamaliyya", + "italian": "Al-Hudud ash-Shamaliyah", + "spanish": "Frontera Norte", + "chinese_simple": "北部边疆地区", + "korean": "북부 국경 주", + "dutch": "Al Hudud ash Shamaliyah", + "portuguese": "Fronteira Norte", + "russian": "Эль-Худуд эш-Шамалийя", + "chinese_traditional": "Al Hudud ash Shamaliyah", + "unknown1": "Al Hudud ash Shamaliyah", + "unknown2": "Al Hudud ash Shamaliyah", + "unknown3": "Al Hudud ash Shamaliyah", + "unknown4": "Al Hudud ash Shamaliyah" + }, + "coordinates": { + "latitude": 30.98144496, + "longitude": 41.017567593 + } + }, + { + "id": 2919956480, + "name": "Najran", + "translations": { + "japanese": "ナジュラーン州", + "english": "Najran", + "french": "Najran", + "german": "Nadschran", + "italian": "Najran", + "spanish": "Najran", + "chinese_simple": "纳季兰地区", + "korean": "나지란 주", + "dutch": "Najran", + "portuguese": "Najran", + "russian": "Наджран", + "chinese_traditional": "Najran", + "unknown1": "Najran", + "unknown2": "Najran", + "unknown3": "Najran", + "unknown4": "Najran" + }, + "coordinates": { + "latitude": 17.501220504, + "longitude": 44.181638697 + } + }, + { + "id": 2920022016, + "name": "Jizan", + "translations": { + "japanese": "ジーザーン州", + "english": "Jizan", + "french": "Jizan", + "german": "Dschaizan", + "italian": "Jizan", + "spanish": "Jizan", + "chinese_simple": "吉赞地区", + "korean": "지잔 주", + "dutch": "Jizan", + "portuguese": "Jizan", + "russian": "Джизан", + "chinese_traditional": "Jizan", + "unknown1": "Jizan", + "unknown2": "Jizan", + "unknown3": "Jizan", + "unknown4": "Jizan" + }, + "coordinates": { + "latitude": 16.885986136, + "longitude": 42.550164534 + } + }, + { + "id": 2920087552, + "name": "Tabuk", + "translations": { + "japanese": "タブーク州", + "english": "Tabuk", + "french": "Tabouk", + "german": "Tabuk", + "italian": "Tabuk", + "spanish": "Tabuk", + "chinese_simple": "塔布克地区", + "korean": "타부크 주", + "dutch": "Tabuk", + "portuguese": "Tabuk", + "russian": "Табук", + "chinese_traditional": "Tabuk", + "unknown1": "Tabuk", + "unknown2": "Tabuk", + "unknown3": "Tabuk", + "unknown4": "Tabuk" + }, + "coordinates": { + "latitude": 28.383178388, + "longitude": 36.579078961 + } + }, + { + "id": 2920153088, + "name": "Al Jawf", + "translations": { + "japanese": "ジャウフ州", + "english": "Al Jawf", + "french": "Al Djôf", + "german": "Dschauf", + "italian": "Al-Jawf", + "spanish": "Al Jouf", + "chinese_simple": "朱夫地区", + "korean": "자우프 주", + "dutch": "Al Jawf", + "portuguese": "Al Jouf", + "russian": "Эль-Джауф", + "chinese_traditional": "Al Jawf", + "unknown1": "Al Jawf", + "unknown2": "Al Jawf", + "unknown3": "Al Jawf", + "unknown4": "Al Jawf" + }, + "coordinates": { + "latitude": 29.805907864, + "longitude": 39.864000003 + } + } + ] + }, + { + "id": 184, + "iso_code": "SM", + "name": "San Marino", + "translations": { + "japanese": "サンマリノ", + "english": "San Marino", + "french": "Saint-Marin", + "german": "San Marino", + "italian": "San Marino", + "spanish": "San Marino", + "chinese_simple": "圣马力诺", + "korean": "산마리노", + "dutch": "San Marino", + "portuguese": "São Marinho", + "russian": "Сан-Марино", + "chinese_traditional": "San Marino", + "unknown1": "San Marino", + "unknown2": "San Marino", + "unknown3": "San Marino", + "unknown4": "San Marino" + }, + "regions": [ + { + "id": 3087007744, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 43.928832508, + "longitude": 12.431064077 + } + }, + { + "id": 3087073280, + "name": "San Marino", + "translations": { + "japanese": "サンマリノ", + "english": "San Marino", + "french": "Saint-Marin", + "german": "San Marino", + "italian": "San Marino", + "spanish": "San Marino", + "chinese_simple": "圣马力诺", + "korean": "산마리노", + "dutch": "San Marino", + "portuguese": "São Marinho", + "russian": "Сан-Марино", + "chinese_traditional": "San Marino", + "unknown1": "San Marino", + "unknown2": "San Marino", + "unknown3": "San Marino", + "unknown4": "San Marino" + }, + "coordinates": { + "latitude": 43.928832508, + "longitude": 12.431064077 + } + } + ] + }, + { + "id": 185, + "iso_code": "VA", + "name": "Vatican City", + "translations": { + "japanese": "バチカン", + "english": "Vatican City", + "french": "Vatican", + "german": "Vatikanstadt", + "italian": "Vaticano (Città del)", + "spanish": "Vaticano", + "chinese_simple": "梵蒂冈", + "korean": "바티칸", + "dutch": "Vaticaanstad", + "portuguese": "Vaticano (cidade)", + "russian": "Ватикан", + "chinese_traditional": "Vatican City", + "unknown1": "Vatican City", + "unknown2": "Vatican City", + "unknown3": "Vatican City", + "unknown4": "Vatican City" + }, + "regions": [ + { + "id": 3103784960, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 41.896361828, + "longitude": 12.447543614 + } + }, + { + "id": 3103850496, + "name": "Vatican City", + "translations": { + "japanese": "バチカン", + "english": "Vatican City", + "french": "Vatican", + "german": "Vatikanstadt", + "italian": "Vaticano (Città del)", + "spanish": "Vaticano", + "chinese_simple": "梵蒂冈", + "korean": "바티칸", + "dutch": "Vaticaanstad", + "portuguese": "Vaticano (cidade)", + "russian": "Ватикан", + "chinese_traditional": "Vatican City", + "unknown1": "Vatican City", + "unknown2": "Vatican City", + "unknown3": "Vatican City", + "unknown4": "Vatican City" + }, + "coordinates": { + "latitude": 41.896361828, + "longitude": 12.447543614 + } + } + ] + }, + { + "id": 186, + "iso_code": "BM", + "name": "Bermuda", + "translations": { + "japanese": "バーミューダ", + "english": "Bermuda", + "french": "Bermudes", + "german": "Bermuda", + "italian": "Bermude", + "spanish": "Bermudas", + "chinese_simple": "百慕大", + "korean": "버뮤다", + "dutch": "Bermuda", + "portuguese": "Bermudas", + "russian": "Бермуды", + "chinese_traditional": "Bermuda", + "unknown1": "Bermuda", + "unknown2": "Bermuda", + "unknown3": "Bermuda", + "unknown4": "Bermuda" + }, + "regions": [ + { + "id": 3120562176, + "name": "Unspecified", + "translations": { + "japanese": "—", + "english": "—", + "french": "—", + "german": "—", + "italian": "—", + "spanish": "—", + "chinese_simple": "—", + "korean": "—", + "dutch": "—", + "portuguese": "—", + "russian": "—", + "chinese_traditional": "—", + "unknown1": "—", + "unknown2": "—", + "unknown3": "—", + "unknown4": "—" + }, + "coordinates": { + "latitude": 32.332763304, + "longitude": -64.747611401 + } + }, + { + "id": 3120627712, + "name": "Bermuda", + "translations": { + "japanese": "バーミューダ", + "english": "Bermuda", + "french": "Bermudes", + "german": "Bermuda", + "italian": "Bermude", + "spanish": "Bermudas", + "chinese_simple": "百慕大", + "korean": "버뮤다", + "dutch": "Bermuda", + "portuguese": "Bermudas", + "russian": "Бермуды", + "chinese_traditional": "Bermuda", + "unknown1": "Bermuda", + "unknown2": "Bermuda", + "unknown3": "Bermuda", + "unknown4": "Bermuda" + }, + "coordinates": { + "latitude": 32.332763304, + "longitude": -64.747611401 + } + } + ] + } +] \ No newline at end of file diff --git a/src/services/nnas/routes/account-settings.ts b/src/services/nnas/routes/account-settings.ts new file mode 100644 index 0000000..9cd74f1 --- /dev/null +++ b/src/services/nnas/routes/account-settings.ts @@ -0,0 +1,228 @@ +import crypto from 'node:crypto'; +import express from 'express'; +import got from 'got'; +import { z } from 'zod'; +import { getServerByClientID, getPNIDByPID } from '@/database'; +import { LOG_ERROR } from '@/logger'; +import { decryptToken, unpackToken, getValueFromHeaders, sendConfirmationEmail } from '@/util'; +import { config } from '@/config-manager'; +import { HydratedServerDocument } from '@/types/mongoose/server'; +import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; +import { AccountSettings } from '@/types/services/nnas/account-settings'; +import { Token } from '@/types/common/token'; +import { RegionLanguages } from '@/types/services/nnas/region-languages'; +import { RegionTimezone, RegionTimezones } from '@/types/services/nnas/region-timezones'; +import { Country, Region } from '@/types/services/nnas/regions'; +import timezones from '@/services/nnas/timezones.json'; +import regionsList from '@/services/nnas/regions.json'; + +const router = express.Router(); + +const accountSettingsSchema = z.object({ + birthdate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/), + gender: z.enum(['M', 'F']), + tz_name: z.string(), + region: z.coerce.number(), + country: z.string(), + email: z.string().email(), + server_selection: z.enum(['prod', 'test', 'dev']), + marketing_flag: z.enum(['true', 'false']).transform((value) => value === 'true'), + off_device_flag: z.enum(['true', 'false']).transform((value) => value === 'true'), +}); + +/** + * [GET] + * Replacement for: https://account.nintendo.net/v1/account-settings/ui/profile + * Description: Serves the Nintendo Network ID Settings page for the Wii U + */ +router.get('/ui/profile', async function (request: express.Request, response: express.Response): Promise { + const server: HydratedServerDocument | null = await getServerByClientID('3f3928cc6f780638d360f0485cef973f', config.server_environment); + const token = getValueFromHeaders(request.headers, 'x-nintendo-service-token'); + + if (!server || !token) { + response.sendStatus(504); + return; + } + + const aes_key: string = server?.aes_key; + const decryptedToken = decryptToken(Buffer.from(token, 'base64'), aes_key); + + const tokenContents: Token = unpackToken(decryptedToken); + + try { + const PNID: HydratedPNIDDocument | null = await getPNIDByPID(tokenContents.pid); + + if (!PNID) { + response.sendStatus(504); + return; + } + + const countryCode = PNID.country; + const language = PNID.language; + + const regionLanguages: RegionLanguages = timezones[countryCode as keyof typeof timezones]; + const regionTimezones: RegionTimezones = regionLanguages[language] ? regionLanguages[language] : Object.values(regionLanguages)[0]; + + const region: Country | undefined = regionsList.find((region) => region.iso_code === countryCode); + + const miiFaces = ['normal_face', 'smile_open_mouth', 'sorrow', 'surprise_open_mouth', 'wink_left', 'frustrated']; + const face = miiFaces[crypto.randomInt(5)]; + + const notice = request.query.notice ? request.query.notice.toString() : undefined; + + const accountLevel = ['Standard', 'Tester', 'Moderator', 'Developer']; + + response.render('index.ejs', { + PNID, + regionTimezones, + face, + notice, + accountLevel, + regions: region ? region.regions: [], + regionsList + }); + } catch (error: any) { + LOG_ERROR(error); + response.sendStatus(504); + return; + } +}); + +/** + * [GET] + * Description: Fetches the requested mii image from the CDN and send it to the client. + * This is required because of the strict domain whitelist in the account settings app + * on the Wii U. + */ +router.get('/mii/:pid/:face', async function (request: express.Request, response: express.Response): Promise { + if (!config.cdn.base_url) { + response.sendStatus(404); + return; + } + + try { + const url = `${config.cdn.base_url}/mii/${request.params.pid}/${request.params.face}.png`; + console.log(url); + const miiImage = await got(url).buffer(); + + response.set('Content-Type', 'image/png'); + response.send(miiImage); + } catch (error: any) { + LOG_ERROR(error); + response.sendStatus(404); + return; + } +}); + +/** + * [POST] + * Description: Endpoint to update the PNID from the account settings app on the Wii + */ +router.post('/update', async function (request: express.Request, response: express.Response): Promise { + const server: HydratedServerDocument | null = await getServerByClientID('3f3928cc6f780638d360f0485cef973f', config.server_environment); + const token = getValueFromHeaders(request.headers, 'x-nintendo-service-token'); + + if (!server || !token) { + response.sendStatus(504); + return; + } + + const aesKey = server?.aes_key; + const decryptedToken = decryptToken(Buffer.from(token, 'base64'), aesKey); + const tokenContents: Token = unpackToken(decryptedToken); + + try { + const pnid: HydratedPNIDDocument | null = await getPNIDByPID(tokenContents.pid); + const personBody: AccountSettings = request.body; + + if (!pnid) { + response.status(404); + response.redirect('/v1/account-settings/ui/profile'); + return; + } + + const person = accountSettingsSchema.safeParse(personBody); + + if (!person.success) { + response.status(404); + response.redirect('/v1/account-settings/ui/profile'); + return; + } + + const timezoneName = (person.data.tz_name && !!Object.keys(person.data.tz_name).length) ? person.data.tz_name : pnid.timezone.name; + + const regionLanguages: RegionLanguages = timezones[pnid.country as keyof typeof timezones]; + const regionTimezones: RegionTimezones = regionLanguages[pnid.language] ? regionLanguages[pnid.language] : Object.values(regionLanguages)[0]; + const timezone: RegionTimezone | undefined = regionTimezones.find(tz => tz.area === timezoneName); + const country: Country | undefined = regionsList.find((region) => region.iso_code === pnid.country); + let notice = ''; + + if (!country) { + response.status(404); + response.redirect('/v1/account-settings/ui/profile'); + return; + } + + const regionObject: Region | undefined = country.regions.find((region) => region.id === person.data.region); + const region = regionObject ? regionObject.id : pnid.region; + + if (!timezone) { + response.status(404); + response.redirect('/v1/account-settings/ui/profile'); + return; + } + + pnid.birthdate = person.data.birthdate; + pnid.gender = person.data.gender; + pnid.region = region; + pnid.country = person.data.country; + pnid.timezone.name = timezoneName; + pnid.timezone.offset = Number(timezone.utc_offset); + pnid.flags.marketing = person.data.marketing_flag; + pnid.flags.off_device = person.data.off_device_flag; + + if (person.data.server_selection && pnid.access_level > 0 && pnid.access_level < 4) { + const environment = person.data.server_selection; + + if (environment === 'test' && pnid.access_level < 1) { + response.status(400); + notice = 'Do not have permission to enter this environment'; + response.redirect(`/v1/account-settings/ui/profile?notice=${notice}`); + return; + } + + if (environment === 'dev' && pnid.access_level < 3) { + response.status(400); + notice = 'Do not have permission to enter this environment'; + response.redirect(`/v1/account-settings/ui/profile?notice=${notice}`); + return; + } + + pnid.server_access_level = environment; + } + + if (person.data.email.trim().toLowerCase() !== pnid.email.address) { + // TODO - Better email check + pnid.email.address = person.data.email.trim().toLowerCase(); + pnid.email.reachable = false; + pnid.email.validated = false; + pnid.email.validated_date = ''; + pnid.email.id = crypto.randomBytes(4).readUInt32LE(); + + await pnid.generateEmailValidationCode(); + await pnid.generateEmailValidationToken(); + await sendConfirmationEmail(pnid); + + notice = 'A confirmation email has been sent to your inbox.'; + } + + await pnid.save(); + response.redirect(`/v1/account-settings/ui/profile?notice=${notice}`); + } catch (error: any) { + LOG_ERROR(error); + response.sendStatus(504); + return; + } +}); + +export default router; diff --git a/src/services/nnas/routes/admin.ts b/src/services/nnas/routes/admin.ts new file mode 100644 index 0000000..c08c356 --- /dev/null +++ b/src/services/nnas/routes/admin.ts @@ -0,0 +1,121 @@ +import express from 'express'; +import xmlbuilder from 'xmlbuilder'; +import { getValueFromQueryString } from '@/util'; +import { PNID } from '@/models/pnid'; + +const router = express.Router(); + +/** + * [GET] + * Replacement for: https://account.nintendo.net/v1/api/admin/mapped_ids + * Description: Maps between NNID usernames and PIDs + */ +router.get('/mapped_ids', async (request: express.Request, response: express.Response): Promise => { + const inputType = getValueFromQueryString(request.query, 'input_type'); + const outputType = getValueFromQueryString(request.query, 'output_type'); + const input = getValueFromQueryString(request.query, 'input'); + + if (!inputType || !outputType || !input) { + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + cause: 'Bad Request', + code: '1600', + message: 'Unable to process request' + } + } + }).end()); + + return; + } + + let inputList = input.split(','); + let queryInput: string; + let queryOutput: string; + + inputList = inputList.filter(input => input); // * Remove null inputs + + if (inputType === 'user_id') { + queryInput = 'usernameLower'; + inputList = inputList.map(name => name.toLowerCase()); + } else { + queryInput = 'pid'; + } + + if (outputType === 'user_id') { + queryOutput = 'username'; + } else { + queryOutput = 'pid'; + } + + // * This is slower than PNID.where() + // * but it ensures that each input + // * ALWAYS has an output and filters + // * out unwanted input/output types + const results: { + in_id: string; + out_id: string; + }[] = []; + const allowedTypes = ['pid', 'user_id']; + + for (const input of inputList) { + const result: { + in_id: string; + out_id: string; + } = { + in_id: input, + out_id: '' + }; + + if (allowedTypes.includes(inputType) && allowedTypes.includes(outputType)) { + const query: { + usernameLower?: string; + pid?: number; + } = {}; + + if (queryInput === 'usernameLower') { + query.usernameLower = input; + } + + if (queryInput === 'pid') { + query.pid = Number(input); + + if (isNaN(query.pid)) { + // * Bail early + results.push(result); + continue; + } + } + + const searchResult = await PNID.findOne(query); + + if (searchResult) { + result.out_id = searchResult.get(queryOutput); + } + } + + results.push(result); + } + + response.send(xmlbuilder.create({ + mapped_ids: { + mapped_id: results + } + }).end()); +}); + +/** + * [GET] + * Replacement for: https://account.nintendo.net/v1/api/admin/time + * Description: Gets the current server time + */ +router.get('/time', async (request: express.Request, response: express.Response): Promise => { + response.set('X-Nintendo-Date', Date.now().toString()); + response.set('Server', 'Nintendo 3DS (http)'); + response.set('Date', new Date().toUTCString()); + + response.send(''); +}); + + +export default router; \ No newline at end of file diff --git a/src/services/nnid/routes/content.js b/src/services/nnas/routes/content.ts similarity index 81% rename from src/services/nnid/routes/content.js rename to src/services/nnas/routes/content.ts index e8b9d70..a60cc30 100644 --- a/src/services/nnid/routes/content.js +++ b/src/services/nnas/routes/content.ts @@ -1,16 +1,18 @@ -const router = require('express').Router(); -const xmlbuilder = require('xmlbuilder'); -const timezones = require('../timezones.json'); +import express from 'express'; +import xmlbuilder from 'xmlbuilder'; +import timezones from '@/services/nnas/timezones.json'; + +const router = express.Router(); /** * [GET] * Replacement for: https://account.nintendo.net/v1/api/content/agreements/TYPE/REGION/VERSION * Description: Sends the client requested agreement */ -router.get('/agreements/:type/:region/:version', (request, response) => { +router.get('/agreements/:type/:region/:version', (request: express.Request, response: express.Response): void => { response.set('Content-Type', 'text/xml'); response.set('Server', 'Nintendo 3DS (http)'); - response.set('X-Nintendo-Date', new Date().getTime()); + response.set('X-Nintendo-Date', new Date().getTime().toString()); response.send(xmlbuilder.create({ agreements: { @@ -124,14 +126,14 @@ router.get('/agreements/:type/:region/:version', (request, response) => { * Replacement for: https://account.nintendo.net/v1/api/content/time_zones/COUNTRY/LANGUAGE * Description: Sends the client the requested timezones */ -router.get('/time_zones/:countryCode/:language', (request, response) => { +router.get('/time_zones/:countryCode/:language', (request: express.Request, response: express.Response): void => { response.set('Content-Type', 'text/xml'); response.set('Server', 'Nintendo 3DS (http)'); - response.set('X-Nintendo-Date', new Date().getTime()); + response.set('X-Nintendo-Date', new Date().getTime().toString()); /* - // Old method. Crashes WiiU when sending a list with over 32 entries, but otherwise works - // countryTimezones is "countries-and-timezones" module + // * Old method. Crashes WiiU when sending a list with over 32 entries, but otherwise works + // * countryTimezones is "countries-and-timezones" module const country = countryTimezones.getCountry(countryCode); const timezones = country.timezones.map((timezone, index) => { @@ -147,10 +149,11 @@ router.get('/time_zones/:countryCode/:language', (request, response) => { }); */ - const { countryCode, language } = request.params; + const countryCode = request.params.countryCode; + const language = request.params.language; - const regionLanguages = timezones[countryCode]; - const regionTimezones = regionLanguages[language] ? regionLanguages[language] : Object.values(regionLanguages)[0]; + const regionLanguages = timezones[countryCode as keyof typeof timezones]; + const regionTimezones = regionLanguages[language as keyof typeof regionLanguages] ? regionLanguages[language as keyof typeof regionLanguages] : Object.values(regionLanguages)[0]; response.send(xmlbuilder.create({ timezones: { @@ -159,4 +162,4 @@ router.get('/time_zones/:countryCode/:language', (request, response) => { }).end()); }); -module.exports = router; +export default router; \ No newline at end of file diff --git a/src/services/nnas/routes/devices.ts b/src/services/nnas/routes/devices.ts new file mode 100644 index 0000000..f46e6a4 --- /dev/null +++ b/src/services/nnas/routes/devices.ts @@ -0,0 +1,18 @@ +import express from 'express'; +import xmlbuilder from 'xmlbuilder'; + +const router = express.Router(); + +/** + * [GET] + * Replacement for: https://account.nintendo.net/v1/api/devices/@current/status + * Description: Unknown use + */ +router.get('/@current/status', async (request: express.Request, response: express.Response): Promise => { + // TODO - Finish this + response.send(xmlbuilder.create({ + device: '' + }).end()); +}); + +export default router; \ No newline at end of file diff --git a/src/services/nnas/routes/miis.ts b/src/services/nnas/routes/miis.ts new file mode 100644 index 0000000..85487bc --- /dev/null +++ b/src/services/nnas/routes/miis.ts @@ -0,0 +1,130 @@ +import express from 'express'; +import xmlbuilder from 'xmlbuilder'; +import { getValueFromQueryString } from '@/util'; +import { PNID } from '@/models/pnid'; +import { config } from '@/config-manager'; +import { YesNoBoolString } from '@/types/common/yes-no-bool-string'; + +const router = express.Router(); + +/** + * [GET] + * Replacement for: https://account.nintendo.net/v1/api/miis + * Description: Returns a list of NNID miis + */ +router.get('/', async (request: express.Request, response: express.Response): Promise => { + const input = getValueFromQueryString(request.query, 'pids'); + + if (!input) { + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + cause: 'Bad Request', + code: '1600', + message: 'Unable to process request' + } + } + }).end()); + + return; + } + + const pids = input.split(',').map(pid => Number(pid)).filter(pid => !isNaN(pid)); + + const miis: { + data: string; + id: number; + images: { + image: { + cached_url: string; + id: number; + url: string; + type: string; + }[] + }; + name: string; + pid: number; + primary: YesNoBoolString; + user_id: string; + }[] = []; + + for (const pid of pids) { + // TODO - Replace this with a single query again somehow? Maybe aggregation? + const pnid = await PNID.findOne({ pid }); + + if (pnid) { + miis.push({ + data: pnid.mii.data.replace(/(\r\n|\n|\r)/gm, ''), + id: pnid.mii.id, + images: { + image: [ + { + cached_url: `${config.cdn.base_url}/mii/${pnid.pid}/normal_face.png`, + id: pnid.mii.id, + url: `${config.cdn.base_url}/mii/${pnid.pid}/normal_face.png`, + type: 'standard' + }, + { + cached_url: `${config.cdn.base_url}/mii/${pnid.pid}/frustrated.png`, + id: pnid.mii.id, + url: `${config.cdn.base_url}/mii/${pnid.pid}/frustrated.png`, + type: 'frustrated_face' + }, + { + cached_url: `${config.cdn.base_url}/mii/${pnid.pid}/smile_open_mouth.png`, + id: pnid.mii.id, + url: `${config.cdn.base_url}/mii/${pnid.pid}/smile_open_mouth.png`, + type: 'happy_face' + }, + { + cached_url: `${config.cdn.base_url}/mii/${pnid.pid}/wink_left.png`, + id: pnid.mii.id, + url: `${config.cdn.base_url}/mii/${pnid.pid}/wink_left.png`, + type: 'like_face' + }, + { + cached_url: `${config.cdn.base_url}/mii/${pnid.pid}/normal_face.png`, + id: pnid.mii.id, + url: `${config.cdn.base_url}/mii/${pnid.pid}/normal_face.png`, + type: 'normal_face' + }, + { + cached_url: `${config.cdn.base_url}/mii/${pnid.pid}/sorrow.png`, + id: pnid.mii.id, + url: `${config.cdn.base_url}/mii/${pnid.pid}/sorrow.png`, + type: 'puzzled_face' + }, + { + cached_url: `${config.cdn.base_url}/mii/${pnid.pid}/surprised_open_mouth.png`, + id: pnid.mii.id, + url: `${config.cdn.base_url}/mii/${pnid.pid}/surprised_open_mouth.png`, + type: 'surprised_face' + }, + { + cached_url: `${config.cdn.base_url}/mii/${pnid.pid}/body.png`, + id: pnid.mii.id, + url: `${config.cdn.base_url}/mii/${pnid.pid}/body.png`, + type: 'whole_body' + } + ] + }, + name: pnid.mii.name, + pid: pnid.pid, + primary: pnid.mii.primary ? 'Y' : 'N', + user_id: pnid.username + }); + } + } + + if (miis.length === 0) { + response.status(404).end(); + } else { + response.send(xmlbuilder.create({ + miis: { + mii: miis + } + }).end()); + } +}); + +export default router; \ No newline at end of file diff --git a/src/services/nnas/routes/oauth.ts b/src/services/nnas/routes/oauth.ts new file mode 100644 index 0000000..493ed4e --- /dev/null +++ b/src/services/nnas/routes/oauth.ts @@ -0,0 +1,189 @@ +import express from 'express'; +import xmlbuilder from 'xmlbuilder'; +import bcrypt from 'bcrypt'; +import deviceCertificateMiddleware from '@/middleware/device-certificate'; +import consoleStatusVerificationMiddleware from '@/middleware/console-status-verification'; +import { getPNIDByTokenAuth, getPNIDByUsername } from '@/database'; +import { generateToken } from '@/util'; +import { config } from '@/config-manager'; +import { Device } from '@/models/device'; + +const router = express.Router(); + +/** + * [POST] + * Replacement for: https://account.nintendo.net/v1/api/oauth20/access_token/generate + * Description: Generates an access token for a user + */ +router.post('/access_token/generate', deviceCertificateMiddleware, consoleStatusVerificationMiddleware, async (request: express.Request, response: express.Response): Promise => { + const grantType = request.body.grant_type; + const username = request.body.user_id; + const password = request.body.password; + const refreshToken = request.body.refresh_token; + + if (!['password', 'refresh_token'].includes(grantType)) { + response.status(400).send(xmlbuilder.create({ + error: { + cause: 'grant_type', + code: '0004', + message: 'Invalid Grant Type' + } + }).end()); + + return; + } + + let pnid = null; + + if (grantType === 'password') { + if (!username || username.trim() === '') { + response.status(400).send(xmlbuilder.create({ + error: { + cause: 'user_id', + code: '0002', + message: 'user_id format is invalid' + } + }).end()); + + return; + } + + if (!password || password.trim() === '') { + response.status(400).send(xmlbuilder.create({ + error: { + cause: 'password', + code: '0002', + message: 'password format is invalid' + } + }).end()); + + return; + } + + pnid = await getPNIDByUsername(username); + + if (!pnid || !await bcrypt.compare(password, pnid.password)) { + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + code: '0106', + message: 'Invalid account ID or password' + } + } + }).end({ pretty: true })); + + return; + } + } else { + if (!refreshToken || refreshToken.trim() === '') { + response.status(400).send(xmlbuilder.create({ + error: { + cause: 'refresh_token', + code: '0106', + message: 'Invalid Refresh Token' + } + }).end()); + + return; + } + + try { + pnid = await getPNIDByTokenAuth(refreshToken); + + if (!pnid) { + response.status(400).send(xmlbuilder.create({ + error: { + cause: 'refresh_token', + code: '0106', + message: 'Invalid Refresh Token' + } + }).end()); + + return; + } + } catch (error) { + response.status(400).send(xmlbuilder.create({ + error: { + cause: 'refresh_token', + code: '0106', + message: 'Invalid Refresh Token' + } + }).end()); + + return; + } + } + + if (pnid.deleted) { + // * 0112 is the "account deleted" error, but unsure if this unlinks the PNID from the user? + // * 0143 is the "The link to this Nintendo Network ID has been temporarliy removed" error, + // * maybe that is a better error to use here? + response.status(400).send(xmlbuilder.create({ + error: { + code: '0112', + message: pnid.username + } + }).end()); + + return; + } + + // * This are set/validated in consoleStatusVerificationMiddleware + // * It is always set, despite what Express might think + if (request.device?.model === 'wup') { + await Device.updateOne({ + _id: request.device?._id + }, { + $addToSet: { + linked_pids: pnid.pid + } + }); + } + + if (pnid.access_level < 0) { + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + code: '0108', + message: 'Account has been banned' + } + } + }).end()); + + return; + } + + const accessTokenOptions = { + system_type: 0x1, // * WiiU + token_type: 0x1, // * OAuth Access + pid: pnid.pid, + expire_time: BigInt(Date.now() + (3600 * 1000)) + }; + + const refreshTokenOptions = { + system_type: 0x1, // * WiiU + token_type: 0x2, // * OAuth Refresh + pid: pnid.pid, + expire_time: BigInt(Date.now() + (3600 * 1000)) + }; + + const accessTokenBuffer = await generateToken(config.aes_key, accessTokenOptions); + const refreshTokenBuffer = await generateToken(config.aes_key, refreshTokenOptions); + + const accessToken = accessTokenBuffer ? accessTokenBuffer.toString('hex') : ''; + const newRefreshToken = refreshTokenBuffer ? refreshTokenBuffer.toString('hex') : ''; + + // TODO - Handle null tokens + + response.send(xmlbuilder.create({ + OAuth20: { + access_token: { + token: accessToken, + refresh_token: newRefreshToken, + expires_in: 3600 + } + } + }).end()); +}); + +export default router; \ No newline at end of file diff --git a/src/services/nnas/routes/people.ts b/src/services/nnas/routes/people.ts new file mode 100644 index 0000000..2172b53 --- /dev/null +++ b/src/services/nnas/routes/people.ts @@ -0,0 +1,710 @@ +import crypto from 'node:crypto'; +import express from 'express'; +import xmlbuilder from 'xmlbuilder'; +import bcrypt from 'bcrypt'; +import moment from 'moment'; +import deviceCertificateMiddleware from '@/middleware/device-certificate'; +import ratelimit from '@/middleware/ratelimit'; +import { connection as databaseConnection, doesPNIDExist, getPNIDProfileJSONByPID } from '@/database'; +import { getValueFromHeaders, nintendoPasswordHash, sendConfirmationEmail, sendPNIDDeletedEmail } from '@/util'; +import { PNID } from '@/models/pnid'; +import { NEXAccount } from '@/models/nex-account'; +import { LOG_ERROR } from '@/logger'; +import timezones from '@/services/nnas/timezones.json'; + +import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; +import { HydratedNEXAccountDocument } from '@/types/mongoose/nex-account'; +import { Person } from '@/types/services/nnas/person'; + +const router = express.Router(); + +/** + * [GET] + * Replacement for: https://account.nintendo.net/v1/api/people/:USERNAME + * Description: Checks if a username is in use + */ +router.get('/:username', async (request: express.Request, response: express.Response): Promise => { + const username = request.params.username; + + const userExists = await doesPNIDExist(username); + + if (userExists) { + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + code: '0100', + message: 'Account ID already exists' + } + } + }).end()); + + return; + } + + response.send(); +}); + +/** + * [POST] + * Replacement for: https://account.nintendo.net/v1/api/people + * Description: Registers a new NNID + */ +router.post('/', ratelimit, deviceCertificateMiddleware, async (request: express.Request, response: express.Response): Promise => { + if (!request.certificate || !request.certificate.valid) { + // TODO - Change this to a different error + response.status(400).send(xmlbuilder.create({ + error: { + cause: 'Bad Request', + code: '1600', + message: 'Unable to process request' + } + }).end()); + + return; + } + + const person: Person = request.body.person; + + const userExists = await doesPNIDExist(person.user_id); + + if (userExists) { + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + code: '0100', + message: 'Account ID already exists' + } + } + }).end()); + + return; + } + + const creationDate = moment().format('YYYY-MM-DDTHH:MM:SS'); + let pnid: HydratedPNIDDocument; + let nexAccount: HydratedNEXAccountDocument; + + const session = await databaseConnection().startSession(); + await session.startTransaction(); + + try { + nexAccount = new NEXAccount({ + device_type: 'wiiu', + }); + + await nexAccount.generatePID(); + await nexAccount.generatePassword(); + + // * Quick hack to get the PIDs to match + // TODO - Change this maybe? + // * NN with a NNID will always use the NNID PID + // * even if the provided NEX PID is different + // * To fix this we make them the same PID + nexAccount.owning_pid = nexAccount.pid; + + await nexAccount.save({ session }); + + const primaryPasswordHash = nintendoPasswordHash(person.password, nexAccount.pid); + const passwordHash = await bcrypt.hash(primaryPasswordHash, 10); + + const countryCode = person.country; + const language = person.language; + const timezoneName = person.tz_name; + + const regionLanguages = timezones[countryCode as keyof typeof timezones]; + const regionTimezones = regionLanguages[language as keyof typeof regionLanguages] ? regionLanguages[language as keyof typeof regionLanguages] : Object.values(regionLanguages)[0]; + let timezone = regionTimezones.find(tz => tz.area === timezoneName); + + if (!timezone) { + // TODO - Change this, handle the error + timezone = { + area: 'America/New_York', + language: 'en', + name: 'Eastern Time (US & Canada)', + order: '11', + utc_offset: '-14400' + }; + } + + pnid = new PNID({ + pid: nexAccount.pid, + creation_date: creationDate, + updated: creationDate, + username: person.user_id, + usernameLower: person.user_id.toLowerCase(), + password: passwordHash, + birthdate: person.birth_date, + gender: person.gender, + country: countryCode, + language: language, + email: { + address: person.email.address.toLowerCase(), + primary: person.email.primary === 'Y', + parent: person.email.parent === 'Y', + reachable: false, + validated: person.email.validated === 'Y', + id: crypto.randomBytes(4).readUInt32LE() + }, + region: person.region, + timezone: { + name: timezoneName, + offset: Number(timezone.utc_offset) + }, + mii: { + name: person.mii.name, + primary: person.mii.name === 'Y', + data: person.mii.data, + id: crypto.randomBytes(4).readUInt32LE(), + hash: crypto.randomBytes(7).toString('hex'), + image_url: '', // * deprecated, will be removed in the future + image_id: crypto.randomBytes(4).readUInt32LE() + }, + flags: { + active: true, + marketing: person.marketing_flag === 'Y', + off_device: person.off_device_flag === 'Y' + }, + identification: { + email_code: 1, // * will be overwritten before saving + email_token: '' // * will be overwritten before saving + } + }); + + await pnid.generateEmailValidationCode(); + await pnid.generateEmailValidationToken(); + await pnid.generateMiiImages(); + + await pnid.save({ session }); + + await session.commitTransaction(); + } catch (error) { + LOG_ERROR('[POST] /v1/api/people: ' + error); + + await session.abortTransaction(); + + response.status(400).send(xmlbuilder.create({ + error: { + cause: 'Bad Request', + code: '1600', + message: 'Unable to process request' + } + }).end()); + + return; + } finally { + // * This runs regardless of failure + // * Returning on catch will not prevent this from running + await session.endSession(); + } + + await sendConfirmationEmail(pnid); + + response.send(xmlbuilder.create({ + person: { + pid: pnid.pid + } + }).end()); +}); + +/** + * [GET] + * Replacement for: https://account.nintendo.net/v1/api/people/@me/profile + * Description: Gets a users profile + */ +router.get('/@me/profile', async (request: express.Request, response: express.Response): Promise => { + response.set('Content-Type', 'text/xml'); + response.set('Server', 'Nintendo 3DS (http)'); + response.set('X-Nintendo-Date', new Date().getTime().toString()); + + const pnid = request.pnid; + + if (!pnid) { + // TODO - Research this error more + response.status(404).send(xmlbuilder.create({ + errors: { + error: { + cause: '', + code: '0008', + message: 'Not Found' + } + } + }).end()); + + return; + } + + const person = await getPNIDProfileJSONByPID(pnid.pid); + + if (!person) { + // TODO - Research this error more + response.status(404).send(xmlbuilder.create({ + errors: { + error: { + cause: '', + code: '0008', + message: 'Not Found' + } + } + }).end()); + + return; + } + + response.send(xmlbuilder.create({ + person + }, { separateArrayItems: true }).end()); +}); + +/** + * [POST] + * Replacement for: https://account.nintendo.net/v1/api/people/@me/devices + * Description: Gets user profile, seems to be the same as https://account.nintendo.net/v1/api/people/@me/profile + */ +router.post('/@me/devices', async (request: express.Request, response: express.Response): Promise => { + response.set('Content-Type', 'text/xml'); + response.set('Server', 'Nintendo 3DS (http)'); + response.set('X-Nintendo-Date', new Date().getTime().toString()); + + // * We don't care about the device attributes + // * The console ignores them and PNIDs are not tied to consoles anyway + // * So the server also ignores them and does not save the ones posted here + + // TODO - CHANGE THIS. WE NEED TO SAVE CONSOLE DETAILS !!! + + const pnid = request.pnid; + + if (!pnid) { + // TODO - Research this error more + response.status(404).send(xmlbuilder.create({ + errors: { + error: { + cause: '', + code: '0008', + message: 'Not Found' + } + } + }).end()); + + return; + } + + const person = await getPNIDProfileJSONByPID(pnid.pid); + + if (!person) { + // TODO - Research this error more + response.status(404).send(xmlbuilder.create({ + errors: { + error: { + cause: '', + code: '0008', + message: 'Not Found' + } + } + }).end()); + + return; + } + + response.send(xmlbuilder.create({ + person + }).end()); +}); + +/** + * [GET] + * Replacement for: https://account.nintendo.net/v1/api/people/@me/devices + * Description: Returns only user devices + */ +router.get('/@me/devices', async (request: express.Request, response: express.Response): Promise => { + response.set('Content-Type', 'text/xml'); + response.set('Server', 'Nintendo 3DS (http)'); + response.set('X-Nintendo-Date', new Date().getTime().toString()); + + const pnid = request.pnid; + const deviceID = getValueFromHeaders(request.headers, 'x-nintendo-device-id'); + const acceptLanguage = getValueFromHeaders(request.headers, 'accept-language'); + const platformID = getValueFromHeaders(request.headers, 'x-nintendo-platform-id'); + const region = getValueFromHeaders(request.headers, 'x-nintendo-region'); + const serialNumber = getValueFromHeaders(request.headers, 'x-nintendo-serial-number'); + const systemVersion = getValueFromHeaders(request.headers, 'x-nintendo-system-version'); + + if (!deviceID || !acceptLanguage || !platformID || !region || !serialNumber || !systemVersion) { + // TODO - Research these error more + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + cause: 'Bad Request', + code: '1600', + message: 'Unable to process request' + } + } + }).end()); + + return; + } + + if (!pnid) { + // TODO - Research this error more + response.status(404).send(xmlbuilder.create({ + errors: { + error: { + cause: '', + code: '0008', + message: 'Not Found' + } + } + }).end()); + + return; + } + + response.send(xmlbuilder.create({ + devices: [ + { + device: { + device_id: deviceID, + language: acceptLanguage, + updated: moment().format('YYYY-MM-DDTHH:MM:SS'), + pid: pnid.pid, + platform_id: platformID, + region: region, + serial_number: serialNumber, + status: 'ACTIVE', + system_version: systemVersion, + type: 'RETAIL', + updated_by: 'USER' + } + } + ] + }).end()); +}); + +/** + * [GET] + * Replacement for: https://account.nintendo.net/v1/api/people/@me/devices/owner + * Description: Gets user profile, seems to be the same as https://account.nintendo.net/v1/api/people/@me/profile + */ +router.get('/@me/devices/owner', async (request: express.Request, response: express.Response): Promise => { + response.set('Content-Type', 'text/xml'); + response.set('Server', 'Nintendo 3DS (http)'); + response.set('X-Nintendo-Date', moment().add(5, 'h').toString()); + + const pnid = request.pnid; + + if (!pnid) { + // TODO - Research this error more + response.status(404).send(xmlbuilder.create({ + errors: { + error: { + cause: '', + code: '0008', + message: 'Not Found' + } + } + }).end()); + + return; + } + + const person = await getPNIDProfileJSONByPID(pnid.pid); + + if (!person) { + // TODO - Research this error more + response.status(404).send(xmlbuilder.create({ + errors: { + error: { + cause: '', + code: '0008', + message: 'Not Found' + } + } + }).end()); + + return; + } + + response.send(xmlbuilder.create({ + person + }).end()); +}); + +/** + * [GET] + * Replacement for: https://account.nintendo.net/v1/api/people/@me/devices/status + * Description: Unknown use + */ +router.get('/@me/devices/status', async (_request: express.Request, response: express.Response): Promise => { + response.set('Content-Type', 'text/xml'); + response.set('Server', 'Nintendo 3DS (http)'); + response.set('X-Nintendo-Date', moment().add(5, 'h').toString()); + + response.send(xmlbuilder.create({ + device: {} + }).end()); +}); + + +/** + * [PUT] + * Replacement for: https://account.nintendo.net/v1/api/people/@me/miis/@primary + * Description: Updates a users Mii + */ +router.put('/@me/miis/@primary', async (request: express.Request, response: express.Response): Promise => { + const pnid = request.pnid; + + if (!pnid) { + // TODO - Research this error more + response.status(404).send(xmlbuilder.create({ + errors: { + error: { + cause: '', + code: '0008', + message: 'Not Found' + } + } + }).end()); + + return; + } + + const mii: { + name: string; + primary: string; + data: string; + } = request.body.mii; + + // TODO - Better checks + + const name = mii.name; + const primary = mii.primary; + const data = mii.data; + + await pnid.updateMii({ name, primary, data }); + + response.send(''); +}); + +/** + * [PUT] + * Replacement for: https://account.nintendo.net/v1/api/people/@me/devices/@current/inactivate + * Description: Deactivates a user from a console + */ +router.put('/@me/devices/@current/inactivate', async (request: express.Request, response: express.Response): Promise => { + response.set('Server', 'Nintendo 3DS (http)'); + response.set('X-Nintendo-Date', new Date().getTime().toString()); + + const pnid = request.pnid; + + if (!pnid) { + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + cause: 'access_token', + code: '0002', + message: 'Invalid access token' + } + } + }).end()); + + return; + } + + response.send(); +}); + +/** + * [POST] + * Replacement for: https://account.nintendo.net/v1/api/people/@me/deletion + * Description: Deletes a NNID + */ +router.post('/@me/deletion', async (request: express.Request, response: express.Response): Promise => { + const pnid = request.pnid; + + if (!pnid) { + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + cause: 'access_token', + code: '0002', + message: 'Invalid access token' + } + } + }).end()); + + return; + } + + const email = pnid.email.address; + + await pnid.scrub(); + await pnid.save(); + + try { + await sendPNIDDeletedEmail(email, pnid.username); + } catch (error) { + LOG_ERROR(`Error sending deletion email ${error}`); + } + + response.send(''); +}); + +/** + * [PUT] + * Replacement for: https://account.nintendo.net/v1/api/people/@me/ + * Description: Updates a PNIDs account details + */ +router.put('/@me', async (request: express.Request, response: express.Response): Promise => { + const pnid = request.pnid; + const person: Person = request.body.person; + + if (!pnid) { + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + cause: 'access_token', + code: '0002', + message: 'Invalid access token' + } + } + }).end()); + + return; + } + + const gender = person.gender ? person.gender : pnid.gender; + const region = person.region ? person.region : pnid.region; + const countryCode = person.country ? person.country : pnid.country; + const language = person.language ? person.language : pnid.language; + let timezoneName = person.tz_name ? person.tz_name : pnid.timezone.name; + + // * Fix for 3DS sending empty person.tz_name, which is interpreted as an empty object + // TODO - See if there's a cleaner way to do this? + + if (typeof timezoneName === 'object' && Object.keys(timezoneName).length === 0) { + timezoneName = pnid.timezone.name; + } + + const marketingFlag = person.marketing_flag ? person.marketing_flag === 'Y' : pnid.flags.marketing; + const offDeviceFlag = person.off_device_flag ? person.off_device_flag === 'Y' : pnid.flags.off_device; + + const regionLanguages = timezones[countryCode as keyof typeof timezones]; + const regionTimezones = regionLanguages[language as keyof typeof regionLanguages] ? regionLanguages[language as keyof typeof regionLanguages] : Object.values(regionLanguages)[0]; + let timezone = regionTimezones.find(tz => tz.area === timezoneName); + + if (!timezone) { + // TODO - Change this, handle the error + timezone = { + area: 'America/New_York', + language: 'en', + name: 'Eastern Time (US & Canada)', + order: '11', + utc_offset: '-14400' + }; + } + + if (person.password) { + const primaryPasswordHash = nintendoPasswordHash(person.password, pnid.pid); + const passwordHash = await bcrypt.hash(primaryPasswordHash, 10); + + pnid.password = passwordHash; + } + + pnid.gender = gender; + pnid.region = region; + pnid.country = countryCode; + pnid.language = language; + pnid.timezone.name = timezoneName; + pnid.timezone.offset = Number(timezone.utc_offset); + pnid.flags.marketing = marketingFlag; + pnid.flags.off_device = offDeviceFlag; + + await pnid.save(); + + response.send(''); +}); + +/** + * [GET] + * Replacement for: https://account.nintendo.net/v1/api/people/@me/emails/ + * Description: Gets a list (why?) of PNID emails + */ +router.get('/@me/emails', async (request: express.Request, response: express.Response): Promise => { + const pnid = request.pnid; + + if (!pnid) { + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + cause: 'access_token', + code: '0002', + message: 'Invalid access token' + } + } + }).end()); + + return; + } + + response.send(xmlbuilder.create({ + emails: [ + { + email: { + address: pnid.email.address, + id: pnid.email.id, + parent: pnid.email.parent ? 'Y' : 'N', + primary: pnid.email.primary ? 'Y' : 'N', + reachable: pnid.email.reachable ? 'Y' : 'N', + type: 'DEFAULT', // * what is this? + updated_by: 'USER', // * need to actually update this + validated: pnid.email.validated ? 'Y' : 'N', + validated_date: pnid.email.validated_date, + } + } + ] + }).end()); +}); + +/** + * [PUT] + * Replacement for: https://account.nintendo.net/v1/api/people/@me/emails/@primary + * Description: Updates a users email address + */ +router.put('/@me/emails/@primary', async (request: express.Request, response: express.Response): Promise => { + const pnid = request.pnid; + + const email: { + address: string; + } = request.body.email; + + if (!pnid || !email || !email.address) { + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + cause: 'access_token', + code: '0002', + message: 'Invalid access token' + } + } + }).end()); + + return; + } + + // TODO - Better email check + pnid.email.address = email.address.toLowerCase(); + pnid.email.reachable = false; + pnid.email.validated = false; + pnid.email.validated_date = ''; + pnid.email.id = crypto.randomBytes(4).readUInt32LE(); + + await pnid.generateEmailValidationCode(); + await pnid.generateEmailValidationToken(); + + await pnid.save(); + + await sendConfirmationEmail(pnid); + + response.send(''); +}); + +export default router; diff --git a/src/services/nnas/routes/provider.ts b/src/services/nnas/routes/provider.ts new file mode 100644 index 0000000..1f87e8d --- /dev/null +++ b/src/services/nnas/routes/provider.ts @@ -0,0 +1,242 @@ +import express from 'express'; +import xmlbuilder from 'xmlbuilder'; +import { getServerByClientID, getServerByGameServerID } from '@/database'; +import { generateToken, getValueFromHeaders, getValueFromQueryString } from '@/util'; +import { NEXAccount } from '@/models/nex-account'; + +const router = express.Router(); + +/** + * [GET] + * Replacement for: https://account.nintendo.net/v1/api/provider/service_token/@me + * Description: Gets a service token + */ +router.get('/service_token/@me', async (request: express.Request, response: express.Response): Promise => { + const pnid = request.pnid; + + if (!pnid) { + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + cause: 'access_token', + code: '0002', + message: 'Invalid access token' + } + } + }).end()); + + return; + } + + const clientID = getValueFromQueryString(request.query, 'client_id'); + + if (!clientID) { + // TODO - Research this error more + response.send(xmlbuilder.create({ + errors: { + error: { + code: '1021', + message: 'The requested game server was not found' + } + } + }).end()); + + return; + } + + const titleID = getValueFromHeaders(request.headers, 'x-nintendo-title-id'); + + if (!titleID) { + // TODO - Research this error more + response.send(xmlbuilder.create({ + errors: { + error: { + code: '1021', + message: 'The requested game server was not found' + } + } + }).end()); + + return; + } + + const serverAccessLevel = pnid.server_access_level; + const server = await getServerByClientID(clientID, serverAccessLevel); + + if (!server || !server.aes_key) { + response.send(xmlbuilder.create({ + errors: { + error: { + code: '1021', + message: 'The requested game server was not found' + } + } + }).end()); + + return; + } + + if (server.maintenance_mode) { + response.send(xmlbuilder.create({ + errors: { + error: { + code: '2002', + message: 'The requested game server is under maintenance' + } + } + }).end()); + + return; + } + + const tokenOptions = { + system_type: server.device, + token_type: 0x4, // * Service token + pid: pnid.pid, + access_level: pnid.access_level, + title_id: BigInt(parseInt(titleID, 16)), + expire_time: BigInt(Date.now() + (3600 * 1000)) + }; + + const serviceTokenBuffer = await generateToken(server.aes_key, tokenOptions); + let serviceToken = serviceTokenBuffer ? serviceTokenBuffer.toString('base64') : ''; + + if (request.isCemu) { + serviceToken = Buffer.from(serviceToken, 'base64').toString('hex'); + } + + response.send(xmlbuilder.create({ + service_token: { + token: serviceToken + } + }).end()); +}); + +/** + * [GET] + * Replacement for: https://account.nintendo.net/v1/api/provider/nex_token/@me + * Description: Gets a NEX server address and token + */ +router.get('/nex_token/@me', async (request: express.Request, response: express.Response): Promise => { + const pnid = request.pnid; + + if (!pnid) { + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + cause: 'access_token', + code: '0002', + message: 'Invalid access token' + } + } + }).end()); + + return; + } + + const nexAccount = await NEXAccount.findOne({ + owning_pid: pnid.pid + }); + + if (!nexAccount) { + response.status(404).send(xmlbuilder.create({ + errors: { + error: { + cause: '', + code: '0008', + message: 'Not Found' + } + } + }).end()); + + return; + } + + const gameServerID = getValueFromQueryString(request.query, 'game_server_id'); + + if (!gameServerID) { + response.send(xmlbuilder.create({ + errors: { + error: { + code: '0118', + message: 'Unique ID and Game Server ID are not linked' + } + } + }).end()); + + return; + } + + const serverAccessLevel = pnid.server_access_level; + const server = await getServerByGameServerID(gameServerID, serverAccessLevel); + + if (!server || !server.aes_key) { + response.send(xmlbuilder.create({ + errors: { + error: { + code: '1021', + message: 'The requested game server was not found' + } + } + }).end()); + + return; + } + + if (server.maintenance_mode) { + response.send(xmlbuilder.create({ + errors: { + error: { + code: '2002', + message: 'The requested game server is under maintenance' + } + } + }).end()); + + return; + } + + const titleID = getValueFromHeaders(request.headers, 'x-nintendo-title-id'); + + if (!titleID) { + // TODO - Research this error more + response.send(xmlbuilder.create({ + errors: { + error: { + code: '1021', + message: 'The requested game server was not found' + } + } + }).end()); + + return; + } + + const tokenOptions = { + system_type: server.device, + token_type: 0x3, // * nex token, + pid: pnid.pid, + access_level: pnid.access_level, + title_id: BigInt(parseInt(titleID, 16)), + expire_time: BigInt(Date.now() + (3600 * 1000)) + }; + + const nexTokenBuffer = await generateToken(server.aes_key, tokenOptions); + let nexToken = nexTokenBuffer ? nexTokenBuffer.toString('base64') : ''; + + if (request.isCemu) { + nexToken = Buffer.from(nexToken || '', 'base64').toString('hex'); + } + + response.send(xmlbuilder.create({ + nex_token: { + host: server.ip, + nex_password: nexAccount.password, + pid: nexAccount.pid, + port: server.port, + token: nexToken + } + }).end()); +}); + +export default router; \ No newline at end of file diff --git a/src/services/nnas/routes/support.ts b/src/services/nnas/routes/support.ts new file mode 100644 index 0000000..6b4a3cc --- /dev/null +++ b/src/services/nnas/routes/support.ts @@ -0,0 +1,188 @@ +import dns from 'node:dns'; +import express from 'express'; +import xmlbuilder from 'xmlbuilder'; +import moment from 'moment'; +import { getPNIDByEmailAddress, getPNIDByPID } from '@/database'; +import { sendEmailConfirmedEmail, sendConfirmationEmail, sendForgotPasswordEmail, sendEmailConfirmedParentalControlsEmail } from '@/util'; + +const router = express.Router(); + +/** + * [POST] + * Replacement for: https://account.nintendo.net/v1/api/support/validate/email + * Description: Verifies a provided email address is valid + */ +router.post('/validate/email', async (request: express.Request, response: express.Response): Promise => { + const email = request.body.email; + + if (!email) { + response.send(xmlbuilder.create({ + errors: { + error: { + cause: 'email', + code: '0103', + message: 'Email format is invalid' + } + } + }).end()); + + return; + } + + const domain = email.split('@')[1]; + + dns.resolveMx(domain, (error: NodeJS.ErrnoException | null) => { + if (error) { + return response.send(xmlbuilder.create({ + errors: { + error: { + code: '1126', + message: 'The domain "' + domain + '" is not accessible.' + } + } + }).end()); + } + + response.send(); + }); +}); + +/** + * [PUT] + * Replacement for: https://account.nintendo.net/v1/api/support/email_confirmation/:pid/:code + * Description: Verifies a users email via 6 digit code + */ +router.put('/email_confirmation/:pid/:code', async (request: express.Request, response: express.Response): Promise => { + const code = request.params.code; + const pid = Number(request.params.pid); + + const pnid = await getPNIDByPID(pid); + + if (!pnid) { + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + code: '0130', + message: 'PID has not been registered yet' + } + } + }).end()); + + return; + } + + if (pnid.identification.email_code !== code) { + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + code: '0116', + message: 'Missing or invalid verification code' + } + } + }).end()); + return; + } + + const validatedDate = moment().format('YYYY-MM-DDTHH:MM:SS'); + + pnid.email.reachable = true; + pnid.email.validated = true; + pnid.email.validated_date = validatedDate; + + await pnid.save(); + + await sendEmailConfirmedEmail(pnid); + + response.status(200).send(''); +}); + +/** + * [GET] + * Replacement for: https://account.nintendo.net/v1/api/support/resend_confirmation + * Description: Resends a users confirmation email + */ +router.get('/resend_confirmation', async (request: express.Request, response: express.Response): Promise => { + const pid = Number(request.headers['x-nintendo-pid']); + + const pnid = await getPNIDByPID(pid); + + if (!pnid) { + // TODO - Unsure if this is the right error + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + code: '0130', + message: 'PID has not been registered yet' + } + } + }).end()); + + return; + } + + await sendConfirmationEmail(pnid); + + response.status(200).send(''); +}); + +/** + * [GET] + * Replacement for: https://account.nintendo.net/v1/api/support/send_confirmation/pin/:email + * Description: Sends a users confirmation email that their email has been registered for parental controls + */ +router.get('/send_confirmation/pin/:email', async (request: express.Request, response: express.Response): Promise => { + const email = request.params.email; + + const pnid = await getPNIDByEmailAddress(email); + + if (!pnid) { + // TODO - Unsure if this is the right error + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + code: '0130', + message: 'PID has not been registered yet' + } + } + }).end()); + + return; + } + + await sendEmailConfirmedParentalControlsEmail(pnid); + + response.status(200).send(''); +}); + +/** + * [GET] + * Replacement for: https://account.nintendo.net/v1/api/support/forgotten_password/PID + * Description: Sends the user a password reset email + * NOTE: On NN this was a temp password that expired after 24 hours. We do not do that + */ +router.get('/forgotten_password/:pid', async (request: express.Request, response: express.Response): Promise => { + const pid = Number(request.params.pid); + + const pnid = await getPNIDByPID(pid); + + if (!pnid) { + // TODO - Better errors + response.status(400).send(xmlbuilder.create({ + errors: { + error: { + cause: 'device_id', + code: '0113', + message: 'Unauthorized device' + } + } + }).end()); + + return; + } + + await sendForgotPasswordEmail(pnid); + + response.status(200).send(''); +}); + +export default router; diff --git a/src/services/nnid/timezones.json b/src/services/nnas/timezones.json similarity index 100% rename from src/services/nnid/timezones.json rename to src/services/nnas/timezones.json diff --git a/src/services/nnid/index.js b/src/services/nnid/index.js deleted file mode 100644 index 84f1d71..0000000 --- a/src/services/nnid/index.js +++ /dev/null @@ -1,40 +0,0 @@ -// handles "account.nintendo.net" endpoints - -const express = require('express'); -const subdomain = require('express-subdomain'); -const clientHeaderCheck = require('../../middleware/client-header'); -const cemuMiddleware = require('../../middleware/cemu'); -const pnidMiddleware = require('../../middleware/pnid'); -const logger = require('../../../logger'); -const routes = require('./routes'); - -// Router to handle the subdomain restriction -const nnid = express.Router(); - -logger.info('[NNID] Importing middleware'); -nnid.use(clientHeaderCheck); -nnid.use(cemuMiddleware); -nnid.use(pnidMiddleware); - -// Setup routes -logger.info('[NNID] Applying imported routes'); -nnid.use('/v1/api/admin', routes.ADMIN); -nnid.use('/v1/api/content', routes.CONTENT); -nnid.use('/v1/api/devices', routes.DEVICES); -nnid.use('/v1/api/miis', routes.MIIS); -nnid.use('/v1/api/oauth20', routes.OAUTH); -nnid.use('/v1/api/people', routes.PEOPLE); -nnid.use('/v1/api/provider', routes.PROVIDER); -nnid.use('/v1/api/support', routes.SUPPORT); - -// Main router for endpoints -const router = express.Router(); - -// Create subdomains -logger.info('[NNID] Creating \'account\' subdomain'); -router.use(subdomain('account', nnid)); - -logger.info('[NNID] Creating \'c.account\' subdomain'); -router.use(subdomain('c.account', nnid)); - -module.exports = router; \ No newline at end of file diff --git a/src/services/nnid/routes/admin.js b/src/services/nnid/routes/admin.js deleted file mode 100644 index be0b9f1..0000000 --- a/src/services/nnid/routes/admin.js +++ /dev/null @@ -1,59 +0,0 @@ -const router = require('express').Router(); -const xmlbuilder = require('xmlbuilder'); -const { PNID } = require('../../../models/pnid'); - -/** - * [GET] - * Replacement for: https://account.nintendo.net/v1/api/admin/mapped_ids - * Description: Maps between NNID usernames and PIDs - */ -router.get('/mapped_ids', async (request, response) => { - - let { input: inputList, input_type: inputType, output_type: outputType } = request.query; - inputList = inputList.split(','); - inputList = inputList.filter(input => input); // remove nulls - - if (inputType === 'user_id') { - inputType = 'usernameLower'; - inputList = inputList.map(name => name.toLowerCase()); - } - - if (outputType === 'user_id') { - outputType = 'username'; - } - - // This is slower than PNID.where() - // but it ensures that each input - // ALWAYS has an output and filters - // out unwanted input/output types - const results = []; - const allowedTypes = ['pid', 'user_id']; - - for (const input of inputList) { - const result = { - in_id: input, - out_id: '' - }; - - if (allowedTypes.includes(request.query.input_type) && allowedTypes.includes(request.query.output_type)) { - const query = {}; - query[inputType] = input; - - const searchResult = await PNID.findOne(query); - - if (searchResult) { - result.out_id = searchResult.get(outputType); - } - } - - results.push(result); - } - - response.send(xmlbuilder.create({ - mapped_ids: { - mapped_id: results - } - }).end()); -}); - -module.exports = router; \ No newline at end of file diff --git a/src/services/nnid/routes/devices.js b/src/services/nnid/routes/devices.js deleted file mode 100644 index 4dd3e4e..0000000 --- a/src/services/nnid/routes/devices.js +++ /dev/null @@ -1,15 +0,0 @@ -const router = require('express').Router(); -const xmlbuilder = require('xmlbuilder'); - -/** - * [GET] - * Replacement for: https://account.nintendo.net/v1/api/devices/@current/status - * Description: Unknown use - */ -router.get('/@current/status', async (request, response) => { - response.send(xmlbuilder.create({ - device: '' - }).end()); -}); - -module.exports = router; \ No newline at end of file diff --git a/src/services/nnid/routes/index.js b/src/services/nnid/routes/index.js deleted file mode 100644 index b5becf4..0000000 --- a/src/services/nnid/routes/index.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = { - ADMIN: require('./admin'), - CONTENT: require('./content'), - DEVICES: require('./devices'), - MIIS: require('./miis'), - OAUTH: require('./oauth'), - PEOPLE: require('./people'), - PROVIDER: require('./provider'), - SUPPORT: require('./support'), -}; \ No newline at end of file diff --git a/src/services/nnid/routes/miis.js b/src/services/nnid/routes/miis.js deleted file mode 100644 index 3c5603c..0000000 --- a/src/services/nnid/routes/miis.js +++ /dev/null @@ -1,94 +0,0 @@ -const router = require('express').Router(); -const xmlbuilder = require('xmlbuilder'); -const { PNID } = require('../../../models/pnid'); -const { config } = require('../../../config-manager'); - -/** - * [GET] - * Replacement for: https://account.pretendo.cc/v1/api/miis - * Description: Returns a list of NNID miis - */ -router.get('/', async (request, response) => { - - const { pids } = request.query; - - const results = await PNID.where('pid', pids); - const miis = []; - - for (const user of results) { - const { mii } = user; - - const miiImages = [ - { - cached_url: `${config.cdn.base_url}/mii/${user.pid}/normal_face.png`, - id: mii.id, - url: `${config.cdn.base_url}/mii/${user.pid}/normal_face.png`, - type: 'standard' - }, - { - cached_url: `${config.cdn.base_url}/mii/${user.pid}/frustrated.png`, - id: mii.id, - url: `${config.cdn.base_url}/mii/${user.pid}/frustrated.png`, - type: 'frustrated_face' - }, - { - cached_url: `${config.cdn.base_url}/mii/${user.pid}/smile_open_mouth.png`, - id: mii.id, - url: `${config.cdn.base_url}/mii/${user.pid}/smile_open_mouth.png`, - type: 'happy_face' - }, - { - cached_url: `${config.cdn.base_url}/mii/${user.pid}/wink_left.png`, - id: mii.id, - url: `${config.cdn.base_url}/mii/${user.pid}/wink_left.png`, - type: 'like_face' - }, - { - cached_url: `${config.cdn.base_url}/mii/${user.pid}/normal_face.png`, - id: mii.id, - url: `${config.cdn.base_url}/mii/${user.pid}/normal_face.png`, - type: 'normal_face' - }, - { - cached_url: `${config.cdn.base_url}/mii/${user.pid}/sorrow.png`, - id: mii.id, - url: `${config.cdn.base_url}/mii/${user.pid}/sorrow.png`, - type: 'puzzled_face' - }, - { - cached_url: `${config.cdn.base_url}/mii/${user.pid}/surprised_open_mouth.png`, - id: mii.id, - url: `${config.cdn.base_url}/mii/${user.pid}/surprised_open_mouth.png`, - type: 'surprised_face' - }, - { - cached_url: `${config.cdn.base_url}/mii/${user.pid}/body.png`, - id: mii.id, - url: `${config.cdn.base_url}/mii/${user.pid}/body.png`, - type: 'whole_body' - } - ]; - - miis.push({ - data: mii.data.replace(/(\r\n|\n|\r)/gm, ''), - id: mii.id, - images: { - image: miiImages - }, - name: mii.name, - pid: user.pid, - primary: mii.primary ? 'Y' : 'N', - user_id: user.username - }); - } - - //console.log(results[0].mii.data.replace(/(\r\n|\n|\r)/gm, '')); - - response.send(xmlbuilder.create({ - miis: { - mii: miis - } - }).end()); -}); - -module.exports = router; \ No newline at end of file diff --git a/src/services/nnid/routes/oauth.js b/src/services/nnid/routes/oauth.js deleted file mode 100644 index 21516ad..0000000 --- a/src/services/nnid/routes/oauth.js +++ /dev/null @@ -1,120 +0,0 @@ -const router = require('express').Router(); -const xmlbuilder = require('xmlbuilder'); -const bcrypt = require('bcrypt'); -const fs = require('fs-extra'); -const database = require('../../../database'); -const util = require('../../../util'); - -/** - * [POST] - * Replacement for: https://account.nintendo.net/v1/api/oauth20/access_token/generate - * Description: Generates an access token for a user - */ -router.post('/access_token/generate', async (request, response) => { - const { body } = request; - const { grant_type, user_id, password } = body; - - if (!['password', 'refresh_token'].includes(grant_type)) { - response.status(400); - return response.send(xmlbuilder.create({ - error: { - cause: 'grant_type', - code: '0004', - message: 'Invalid Grant Type' - } - }).end()); - } - - if (!user_id || user_id.trim() === '') { - response.status(400); - return response.send(xmlbuilder.create({ - error: { - cause: 'user_id', - code: '0002', - message: 'user_id format is invalid' - } - }).end()); - } - - if (!password || password.trim() === '') { - response.status(400); - return response.send(xmlbuilder.create({ - error: { - cause: 'password', - code: '0002', - message: 'password format is invalid' - } - }).end()); - } - - const pnid = await database.getUserByUsername(user_id); - - if (!pnid || !await bcrypt.compare(password, pnid.password)) { - response.status(400); - return response.send(xmlbuilder.create({ - error: { - code: '0106', - message: 'Invalid account ID or password' - } - }).end({ pretty: true })); - } - - if (pnid.get('access_level') < 0) { - return response.status(400).send(xmlbuilder.create({ - errors: { - error: { - code: '0122', - message: 'Device has been banned by game server' - } - } - }).end()); - } - - const cryptoPath = `${__dirname}/../../../../certs/service/account`; - - if (!await fs.pathExists(cryptoPath)) { - // Need to generate keys - return response.send(xmlbuilder.create({ - errors: { - error: { - code: '0000', - message: 'Could not find account access key crypto path' - } - } - }).end()); - } - - const accessTokenOptions = { - system_type: 0x1, // WiiU - token_type: 0x1, // OAuth Access, - pid: pnid.get('pid'), - expire_time: BigInt(Date.now() + (3600 * 1000)) - }; - - const refreshTokenOptions = { - system_type: 0x1, // WiiU - token_type: 0x2, // OAuth Refresh, - pid: pnid.get('pid'), - expire_time: BigInt(Date.now() + (3600 * 1000)) - }; - - let accessToken = await util.generateToken(null, accessTokenOptions); - let refreshToken = await util.generateToken(null, refreshTokenOptions); - - if (request.isCemu) { - accessToken = Buffer.from(accessToken, 'base64').toString('hex'); - refreshToken = Buffer.from(refreshToken, 'base64').toString('hex'); - } - - response.send(xmlbuilder.create({ - OAuth20: { - access_token: { - token: accessToken, - refresh_token: refreshToken, - expires_in: 3600 - } - } - }).end()); -}); - -module.exports = router; \ No newline at end of file diff --git a/src/services/nnid/routes/people.js b/src/services/nnid/routes/people.js deleted file mode 100644 index 7d1287a..0000000 --- a/src/services/nnid/routes/people.js +++ /dev/null @@ -1,496 +0,0 @@ -const router = require('express').Router(); -const xmlbuilder = require('xmlbuilder'); -const moment = require('moment'); -const crypto = require('crypto'); -const bcrypt = require('bcrypt'); -const { PNID } = require('../../../models/pnid'); -const { NEXAccount } = require('../../../models/nex-account'); -const deviceCertificateMiddleware = require('../../../middleware/device-certificate'); -const ratelimit = require('../../../middleware/ratelimit'); -const database = require('../../../database'); -const util = require('../../../util'); -const logger = require('../../../../logger'); -require('moment-timezone'); - -/** - * [GET] - * Replacement for: https://account.nintendo.net/v1/api/people/:USERNAME - * Description: Checks if a username is in use - */ -router.get('/:username', async (request, response) => { - const { username } = request.params; - - const userExists = await database.doesUserExist(username); - - if (userExists) { - response.status(400); - - return response.end(xmlbuilder.create({ - errors: { - error: { - code: '0100', - message: 'Account ID already exists' - } - } - }).end()); - } - - response.status(200); - response.end(); -}); - -/** - * [POST] - * Replacement for: https://account.nintendo.net/v1/api/people - * Description: Registers a new NNID - */ -router.post('/', ratelimit, deviceCertificateMiddleware, async (request, response) => { - if (!request.certificate.valid) { - // TODO: Change this to a different error - response.status(400); - - return response.send(xmlbuilder.create({ - error: { - cause: 'Bad Request', - code: '1600', - message: 'Unable to process request' - } - }).end()); - } - - const person = request.body.get('person'); - - const userExists = await database.doesUserExist(person.get('user_id')); - - if (userExists) { - response.status(400); - - return response.end(xmlbuilder.create({ - errors: { - error: { - code: '0100', - message: 'Account ID already exists' - } - } - }).end()); - } - - const creationDate = moment().format('YYYY-MM-DDTHH:MM:SS'); - let pnid; - let nexAccount; - - const session = await database.connection.startSession(); - await session.startTransaction(); - - try { - nexAccount = new NEXAccount({ - device_type: 'wiiu', - }); - - await nexAccount.generatePID(); - await nexAccount.generatePassword(); - - // Quick hack to get the PIDs to match - // TODO: Change this maybe? - // NN with a NNID will always use the NNID PID - // even if the provided NEX PID is different - // To fix this we make them the same PID - nexAccount.owning_pid = nexAccount.get('pid'); - - await nexAccount.save({ session }); - - const primaryPasswordHash = util.nintendoPasswordHash(person.get('password'), nexAccount.get('pid')); - const passwordHash = await bcrypt.hash(primaryPasswordHash, 10); - - pnid = new PNID({ - pid: nexAccount.get('pid'), - creation_date: creationDate, - updated: creationDate, - username: person.get('user_id'), - usernameLower: person.get('user_id').toLowerCase(), - password: passwordHash, - birthdate: person.get('birth_date'), - gender: person.get('gender'), - country: person.get('country'), - language: person.get('language'), - email: { - address: person.get('email').get('address').toLowerCase(), - primary: person.get('email').get('primary') === 'Y', - parent: person.get('email').get('parent') === 'Y', - reachable: false, - validated: person.get('email').get('validated') === 'Y', - id: crypto.randomBytes(4).readUInt32LE() - }, - region: person.get('region'), - timezone: { - name: person.get('tz_name'), - offset: (moment.tz(person.get('tz_name')).utcOffset() * 60) - }, - mii: { - name: person.get('mii').get('name'), - primary: person.get('mii').get('name') === 'Y', - data: person.get('mii').get('data'), - id: crypto.randomBytes(4).readUInt32LE(), - hash: crypto.randomBytes(7).toString('hex'), - image_url: '', // deprecated, will be removed in the future - image_id: crypto.randomBytes(4).readUInt32LE() - }, - flags: { - active: true, - marketing: person.get('marketing_flag') === 'Y', - off_device: person.get('off_device_flag') === 'Y' - }, - identification: { - email_code: 1, // will be overwritten before saving - email_token: '' // will be overwritten before saving - } - }); - - await pnid.generateEmailValidationCode(); - await pnid.generateEmailValidationToken(); - await pnid.generateMiiImages(); - - await pnid.save({ session }); - - await session.commitTransaction(); - } catch (error) { - logger.error('[POST] /v1/api/people: ' + error); - - await session.abortTransaction(); - - response.status(400); - - return response.send(xmlbuilder.create({ - error: { - cause: 'Bad Request', - code: '1600', - message: 'Unable to process request' - } - }).end()); - } finally { - // * This runs regardless of failure - // * Returning on catch will not prevent this from running - await session.endSession(); - } - - await util.sendConfirmationEmail(pnid); - - response.send(xmlbuilder.create({ - person: { - pid: pnid.get('pid') - } - }).end()); -}); - -/** - * [GET] - * Replacement for: https://account.nintendo.net/v1/api/people/@me/profile - * Description: Gets a users profile - */ -router.get('/@me/profile', async (request, response) => { - response.set('Content-Type', 'text/xml'); - response.set('Server', 'Nintendo 3DS (http)'); - response.set('X-Nintendo-Date', new Date().getTime()); - - const { pnid } = request; - - const person = await database.getUserProfileJSONByPID(pnid.get('pid')); - - response.send(xmlbuilder.create({ - person - }, { separateArrayItems: true }).end()); -}); - -/** - * [POST] - * Replacement for: https://account.nintendo.net/v1/api/people/@me/devices - * Description: Gets user profile, seems to be the same as https://account.nintendo.net/v1/api/people/@me/profile - */ -router.post('/@me/devices', async (request, response) => { - response.set('Content-Type', 'text/xml'); - response.set('Server', 'Nintendo 3DS (http)'); - response.set('X-Nintendo-Date', new Date().getTime()); - - // We don't care about the device attributes - // The console ignores them and PNIDs are not tied to consoles anyway - // So the server also ignores them and does not save the ones posted here - - const { pnid } = request; - - const person = await database.getUserProfileJSONByPID(pnid.get('pid')); - - response.send(xmlbuilder.create({ - person - }).end()); -}); - -/** - * [GET] - * Replacement for: https://account.nintendo.net/v1/api/people/@me/devices - * Description: Returns only user devices - */ -router.get('/@me/devices', async (request, response) => { - response.set('Content-Type', 'text/xml'); - response.set('Server', 'Nintendo 3DS (http)'); - response.set('X-Nintendo-Date', new Date().getTime()); - - const { pnid, headers } = request; - - response.send(xmlbuilder.create({ - devices: [ - { - device: { - device_id: headers['x-nintendo-device-id'], - language: headers['accept-language'], - updated: moment().format('YYYY-MM-DDTHH:MM:SS'), - pid: pnid.get('pid'), - platform_id: headers['x-nintendo-platform-id'], - region: headers['x-nintendo-region'], - serial_number: headers['x-nintendo-serial-number'], - status: 'ACTIVE', - system_version: headers['x-nintendo-system-version'], - type: 'RETAIL', - updated_by: 'USER' - } - } - ] - }).end()); -}); - -/** - * [GET] - * Replacement for: https://account.nintendo.net/v1/api/people/@me/devices/owner - * Description: Gets user profile, seems to be the same as https://account.nintendo.net/v1/api/people/@me/profile - */ -router.get('/@me/devices/owner', async (request, response) => { - response.set('Content-Type', 'text/xml'); - response.set('Server', 'Nintendo 3DS (http)'); - response.set('X-Nintendo-Date', moment().add(5, 'h')); - - const { pnid } = request; - - const person = await database.getUserProfileJSONByPID(pnid.get('pid')); - - response.send(xmlbuilder.create({ - person - }).end()); -}); - -/** - * [GET] - * Replacement for: https://account.nintendo.net/v1/api/people/@me/devices/status - * Description: Unknown use - */ -router.get('/@me/devices/status', async (request, response) => { - response.set('Content-Type', 'text/xml'); - response.set('Server', 'Nintendo 3DS (http)'); - response.set('X-Nintendo-Date', moment().add(5, 'h')); - - response.send(xmlbuilder.create({ - device: {} - }).end()); -}); - - -/** - * [PUT] - * Replacement for: https://account.nintendo.net/v1/api/people/@me/miis/@primary - * Description: Updates a users Mii - */ -router.put('/@me/miis/@primary', async (request, response) => { - const { pnid } = request; - - const mii = request.body.get('mii'); - - const [name, primary, data] = [mii.get('name'), mii.get('primary'), mii.get('data')]; - - await pnid.updateMii({ name, primary, data }); - - response.send(''); -}); - -/** - * [PUT] - * Replacement for: https://account.nintendo.net/v1/api/people/@me/devices/@current/inactivate - * Description: Deactivates a user from a console - */ -router.put('/@me/devices/@current/inactivate', async (request, response) => { - response.set('Server', 'Nintendo 3DS (http)'); - response.set('X-Nintendo-Date', new Date().getTime()); - - const { pnid } = request; - - if (!pnid) { - response.status(400); - - return response.end(xmlbuilder.create({ - errors: { - error: { - cause: 'access_token', - code: '0002', - message: 'Invalid access token' - } - } - }).end()); - } - - response.status(200); - response.end(); -}); - -/** - * [POST] - * Replacement for: https://account.nintendo.net/v1/api/people/@me/deletion - * Description: Deletes a NNID - */ -router.put('/@me/deletion', async (request, response) => { - const { pnid } = request; - - if (!pnid) { - response.status(400); - - return response.end(xmlbuilder.create({ - errors: { - error: { - cause: 'access_token', - code: '0002', - message: 'Invalid access token' - } - } - }).end()); - } - - await PNID.deleteOne({ pid: pnid.get('pid') }); - - response.send(''); -}); - -/** - * [PUT] - * Replacement for: https://account.nintendo.net/v1/api/people/@me/ - * Description: Updates a PNIDs account details - */ -router.put('/@me', async (request, response) => { - const { pnid } = request; - const person = request.body.get('person'); - - if (!pnid) { - response.status(400); - - return response.end(xmlbuilder.create({ - errors: { - error: { - cause: 'access_token', - code: '0002', - message: 'Invalid access token' - } - } - }).end()); - } - - const gender = person.get('gender') ? person.get('gender') : pnid.get('gender'); - const region = person.get('region') ? person.get('region') : pnid.get('region'); - const timezoneName = person.get('tz_name') ? person.get('tz_name') : pnid.get('timezone.name'); - const marketingFlag = person.get('marketing_flag') ? person.get('marketing_flag') === 'Y' : pnid.get('flags.marketing'); - const offDeviceFlag = person.get('off_device_flag') ? person.get('off_device_flag') === 'Y' : pnid.get('flags.off_device'); - - if (person.get('password')) { - const primaryPasswordHash = util.nintendoPasswordHash(person.get('password'), pnid.get('pid')); - const passwordHash = await bcrypt.hash(primaryPasswordHash, 10); - - pnid.password = passwordHash; - } - - pnid.gender = gender; - pnid.region = region; - pnid.timezone.name = timezoneName; - pnid.timezone.offset = (moment.tz(timezoneName).utcOffset() * 60); - pnid.timezone.marketing = marketingFlag; - pnid.timezone.off_device = offDeviceFlag; - - await pnid.save(); - - response.send(''); -}); - -/** - * [GET] - * Replacement for: https://account.nintendo.net/v1/api/people/@me/emails/ - * Description: Gets a list (why?) of PNID emails - */ -router.get('/@me/emails', async (request, response) => { - const { pnid } = request; - - if (!pnid) { - response.status(400); - - return response.end(xmlbuilder.create({ - errors: { - error: { - cause: 'access_token', - code: '0002', - message: 'Invalid access token' - } - } - }).end()); - } - - response.send(xmlbuilder.create({ - emails: [ - { - email: { - address: pnid.get('email.address'), - id: pnid.get('email.id'), - parent: pnid.get('email.parent') ? 'Y' : 'N', - primary: pnid.get('email.primary') ? 'Y' : 'N', - reachable: pnid.get('email.reachable') ? 'Y' : 'N', - type: 'DEFAULT', // what is this? - updated_by: 'USER', // need to actually update this - validated: pnid.get('email.validated') ? 'Y' : 'N', - validated_date: pnid.get('email.validated_date'), - } - } - ] - }).end()); -}); - -/** - * [PUT] - * Replacement for: https://account.nintendo.net/v1/api/people/@me/emails/@primary - * Description: Updates a users email address - */ -router.put('/@me/emails/@primary', async (request, response) => { - const { pnid } = request; - const email = request.body.get('email'); - - if (!pnid) { - response.status(400); - - return response.end(xmlbuilder.create({ - errors: { - error: { - cause: 'access_token', - code: '0002', - message: 'Invalid access token' - } - } - }).end()); - } - - pnid.set('email.address', email.get('address').toLowerCase()); - pnid.set('email.reachable', false); - pnid.set('email.validated', false); - pnid.set('email.validated_date', ''); - pnid.set('email.id', crypto.randomBytes(4).readUInt32LE()); - - await pnid.generateEmailValidationCode(); - await pnid.generateEmailValidationToken(); - - await pnid.save(); - - await util.sendConfirmationEmail(pnid); - - response.send(''); -}); - -module.exports = router; \ No newline at end of file diff --git a/src/services/nnid/routes/provider.js b/src/services/nnid/routes/provider.js deleted file mode 100644 index 86fd9d1..0000000 --- a/src/services/nnid/routes/provider.js +++ /dev/null @@ -1,172 +0,0 @@ -const router = require('express').Router(); -const xmlbuilder = require('xmlbuilder'); -const fs = require('fs-extra'); -const { NEXAccount } = require('../../../models/nex-account'); -const util = require('../../../util'); -const database = require('../../../database'); -const cache = require('../../../cache'); - -/** - * [GET] - * Replacement for: https://account.nintendo.net/v1/api/provider/service_token/@me - * Description: Gets a service token - */ -router.get('/service_token/@me', async (request, response) => { - const { pnid } = request; - - const titleId = request.headers['x-nintendo-title-id']; - const serverAccessLevel = pnid.get('server_access_level'); - const server = await database.getServerByTitleId(titleId, serverAccessLevel); - - if (!server) { - return response.send(xmlbuilder.create({ - errors: { - error: { - code: '1021', - message: 'The requested game server was not found' - } - } - }).end()); - } - - const { service_name, service_type, device } = server; - - const cryptoPath = `${__dirname}/../../../../certs/${service_type}/${service_name}`; - - if (!await fs.pathExists(cryptoPath)) { - // Need to generate keys - return response.send(xmlbuilder.create({ - errors: { - error: { - code: '1021', - message: 'The requested game server was not found' - } - } - }).end()); - } - - const publicKey = await cache.getServicePublicKey(service_name); - const secretKey = await cache.getServiceSecretKey(service_name); - - const cryptoOptions = { - public_key: publicKey, - hmac_secret: secretKey - }; - - const tokenOptions = { - system_type: device, - token_type: 0x4, // service token, - pid: pnid.get('pid'), - access_level: pnid.get('access_level'), - title_id: BigInt(parseInt(titleId, 16)), - expire_time: BigInt(Date.now() + (3600 * 1000)) - }; - - let serviceToken = await util.generateToken(cryptoOptions, tokenOptions); - - if (request.isCemu) { - serviceToken = Buffer.from(serviceToken, 'base64').toString('hex'); - } - - response.send(xmlbuilder.create({ - service_token: { - token: serviceToken - } - }).end()); -}); - -/** - * [GET] - * Replacement for: https://account.nintendo.net/v1/api/provider/nex_token/@me - * Description: Gets a NEX server address and token - */ -router.get('/nex_token/@me', async (request, response) => { - const { game_server_id: gameServerID } = request.query; - const { pnid } = request; - - if (!gameServerID) { - return response.send(xmlbuilder.create({ - errors: { - error: { - code: '0118', - message: 'Unique ID and Game Server ID are not linked' - } - } - }).end()); - } - - const serverAccessLevel = pnid.get('server_access_level'); - const server = await database.getServer(gameServerID, serverAccessLevel); - - if (!server) { - return response.send(xmlbuilder.create({ - errors: { - error: { - code: '1021', - message: 'The requested game server was not found' - } - } - }).end()); - } - - const { service_name, service_type, ip, port, device } = server; - const titleId = request.headers['x-nintendo-title-id']; - - const cryptoPath = `${__dirname}/../../../../certs/${service_type}/${service_name}`; - - if (!await fs.pathExists(cryptoPath)) { - // Need to generate keys - return response.send(xmlbuilder.create({ - errors: { - error: { - code: '1021', - message: 'The requested game server was not found' - } - } - }).end()); - } - - const publicKey = await cache.getNEXPublicKey(service_name); - const secretKey= await cache.getNEXSecretKey(service_name); - - const cryptoOptions = { - public_key: publicKey, - hmac_secret: secretKey - }; - - const tokenOptions = { - system_type: device, - token_type: 0x3, // nex token, - pid: pnid.get('pid'), - access_level: pnid.get('access_level'), - title_id: BigInt(parseInt(titleId, 16)), - expire_time: BigInt(Date.now() + (3600 * 1000)) - }; - - const nexUser = await NEXAccount.findOne({ - owning_pid: pnid.get('pid') - }); - - if (!nexUser) { - response.status(404); - return response.send('0008Not Found'); - } - - let nexToken = await util.generateToken(cryptoOptions, tokenOptions); - - if (request.isCemu) { - nexToken = Buffer.from(nexToken, 'base64').toString('hex'); - } - - response.send(xmlbuilder.create({ - nex_token: { - host: ip, - nex_password: nexUser.get('password'), - pid: nexUser.get('pid'), - port: port, - token: nexToken - } - }).end()); -}); - -module.exports = router; \ No newline at end of file diff --git a/src/services/nnid/routes/support.js b/src/services/nnid/routes/support.js deleted file mode 100644 index d63fea3..0000000 --- a/src/services/nnid/routes/support.js +++ /dev/null @@ -1,148 +0,0 @@ -const router = require('express').Router(); -const dns = require('dns'); -const xmlbuilder = require('xmlbuilder'); -const moment = require('moment'); -const util = require('../../../util'); -const database = require('../../../database'); - -/** - * [POST] - * Replacement for: https://account.nintendo.net/v1/api/support/validate/email - * Description: Verifies a provided email address is valid - */ -router.post('/validate/email', async (request, response) => { - const { email } = request.body; - - if (!email) { - return response.send(xmlbuilder.create({ - errors: { - error: { - cause: 'email', - code: '0103', - message: 'Email format is invalid' - } - } - }).end()); - } - - const domain = email.split('@')[1]; - - dns.resolveMx(domain, (error) => { - if (error) { - return response.send(xmlbuilder.create({ - errors: { - error: { - code: '1126', - message: 'The domain "' + domain + '" is not accessible.' - } - } - }).end()); - } - - response.status(200); - response.end(); - }); -}); - -/** - * [PUT] - * Replacement for: https://account.nintendo.net/v1/api/support/email_confirmation/:pid/:code - * Description: Verifies a users email via 6 digit code - */ -router.put('/email_confirmation/:pid/:code', async (request, response) => { - const { pid, code } = request.params; - - const pnid = await database.getUserByPID(pid); - - if (!pnid) { - return response.status(400).send(xmlbuilder.create({ - errors: { - error: { - code: '0130', - message: 'PID has not been registered yet' - } - } - }).end()); - } - - if (pnid.get('identification.email_code') !== code) { - return response.status(400).send(xmlbuilder.create({ - errors: { - error: { - code: '0116', - message: 'Missing or invalid verification code' - } - } - }).end()); - } - - const validatedDate = moment().format('YYYY-MM-DDTHH:MM:SS'); - - pnid.set('email.reachable', true); - pnid.set('email.validated', true); - pnid.set('email.validated_date', validatedDate); - - await pnid.save(); - - await util.sendEmailConfirmedEmail(pnid); - - response.status(200).send(''); -}); - -/** - * [GET] - * Replacement for: https://account.nintendo.net/v1/api/support/resend_confirmation - * Description: Resends a users confirmation email - */ -router.get('/resend_confirmation', async (request, response) => { - const pid = request.headers['x-nintendo-pid']; - - const pnid = await database.getUserByPID(pid); - - if (!pnid) { - // TODO - Unsure if this is the right error - return response.status(400).send(xmlbuilder.create({ - errors: { - error: { - code: '0130', - message: 'PID has not been registered yet' - } - } - }).end()); - } - - await util.sendConfirmationEmail(pnid); - - response.status(200).send(''); -}); - -/** - * [GET] - * Replacement for: https://account.nintendo.net/v1/api/support/forgotten_password/PID - * Description: Sends the user a password reset email - * NOTE: On NN this was a temp password that expired after 24 hours. We do not do that - */ -router.get('/forgotten_password/:pid', async (request, response) => { - const { pid } = request.params; - - const pnid = await database.getUserByPID(pid); - - if (!pnid) { - // TODO - Better errors - return response.status(400).send(xmlbuilder.create({ - errors: { - error: { - cause: 'device_id', - code: '0113', - message: 'Unauthorized device' - } - } - }).end()); - } - - await util.sendForgotPasswordEmail(pnid); - - response.status(200).send(''); -}); - -module.exports = router; \ No newline at end of file diff --git a/src/types/common/config.ts b/src/types/common/config.ts new file mode 100644 index 0000000..cc6390f --- /dev/null +++ b/src/types/common/config.ts @@ -0,0 +1,65 @@ +import mongoose from 'mongoose'; + +export const domainServices = ['api', 'assets', 'cbvc', 'conntest', 'datastore', 'nasc', 'nnas', 'local_cdn'] as const; +export type DomainService = typeof domainServices[number]; + +export const optionalDomainServices: DomainService[] = ['local_cdn']; + +export interface Config { + http: { + port: number; + }; + mongoose: { + connection_string: string; + options: mongoose.ConnectOptions; + }; + redis: { + client: { + url: string; + } + }; + email: { + ses: { + region: string; + key: string; + secret: string; + }; + from: string; + }; + s3: { + bucket: string; + endpoint: string; + key: string; + secret: string; + region: string; + forcePathStyle: boolean; + }; + hcaptcha: { + secret: string; + }; + cdn: { + /** + * @deprecated Use `domains.cdn` instead + */ + subdomain?: string; + disk_path: string; + base_url: string; + }; + website_base: string; + aes_key: string; + grpc: { + master_api_keys: { + account: string; + api: string; + }; + port: number; + }; + stripe?: { + secret_key: string; + }; + server_environment: string; + datastore: { + signature_secret: string; + }; + domains: Record; +} diff --git a/src/types/common/gender-types.ts b/src/types/common/gender-types.ts new file mode 100644 index 0000000..9d4ca82 --- /dev/null +++ b/src/types/common/gender-types.ts @@ -0,0 +1 @@ +export type GenderTypes = 'M' | 'F'; \ No newline at end of file diff --git a/src/types/common/mailer-options.ts b/src/types/common/mailer-options.ts new file mode 100644 index 0000000..265b42a --- /dev/null +++ b/src/types/common/mailer-options.ts @@ -0,0 +1,16 @@ +export interface MailerOptions { + to: string; + subject: string; + username: string; + paragraph?: string; + preview?: string; + text: string; + link?: { + href: string; + text: string; + }; + confirmation?: { + href: string; + code: string; + }; +} \ No newline at end of file diff --git a/src/types/common/permission-flags.ts b/src/types/common/permission-flags.ts new file mode 100644 index 0000000..7c22211 --- /dev/null +++ b/src/types/common/permission-flags.ts @@ -0,0 +1,26 @@ +export const PNID_PERMISSION_FLAGS = { + BANNED_ALL_PERMANENTLY: 1n << 0n, + BANNED_ALL_TEMPORARILY: 1n << 1n, + BETA_ACCESS: 1n << 2n, + ACCESS_ADMIN_PANEL: 1n << 3n, + CREATE_SERVER_CONFIGS: 1n << 4n, + MODIFY_SERVER_CONFIGS: 1n << 5n, + DEPLOY_SERVER: 1n << 6n, + MODIFY_PNIDS: 1n << 7n, + MODIFY_NEX_ACCOUNTS: 1n << 8n, + MODIFY_CONSOLES: 1n << 9n, + BAN_PNIDS: 1n << 10n, + BAN_NEX_ACCOUNTS: 1n << 11n, + BAN_CONSOLES: 1n << 12n, + MODERATE_MIIVERSE: 1n << 13n, + CREATE_API_KEYS: 1n << 14n, // * This applies to all services + CREATE_BOSS_TASKS: 1n << 15n, + UPDATE_BOSS_TASKS: 1n << 16n, + DELETE_BOSS_TASKS: 1n << 17n, + UPLOAD_BOSS_FILES: 1n << 18n, + UPDATE_BOSS_FILES: 1n << 18n, + DELETE_BOSS_FILES: 1n << 19n, + UPDATE_PNID_PERMISSIONS: 1n << 20n +} as const; + +export type PNIDPermissionFlag = (typeof PNID_PERMISSION_FLAGS)[keyof typeof PNID_PERMISSION_FLAGS]; \ No newline at end of file diff --git a/src/types/common/safe-qs.ts b/src/types/common/safe-qs.ts new file mode 100644 index 0000000..a17df29 --- /dev/null +++ b/src/types/common/safe-qs.ts @@ -0,0 +1,3 @@ +export interface SafeQs { + [key: string]: string | undefined +} \ No newline at end of file diff --git a/src/types/common/signature-size.ts b/src/types/common/signature-size.ts new file mode 100644 index 0000000..c9f9bbf --- /dev/null +++ b/src/types/common/signature-size.ts @@ -0,0 +1,4 @@ +export interface SignatureSize { + SIZE: number; + PADDING_SIZE: number; +} \ No newline at end of file diff --git a/src/types/common/token-options.ts b/src/types/common/token-options.ts new file mode 100644 index 0000000..6dcc85e --- /dev/null +++ b/src/types/common/token-options.ts @@ -0,0 +1,8 @@ +export interface TokenOptions { + system_type: number; + token_type: number; + pid: number; + access_level?: number; + title_id?: bigint; + expire_time: bigint; +} \ No newline at end of file diff --git a/src/types/common/token.ts b/src/types/common/token.ts new file mode 100644 index 0000000..4c7c558 --- /dev/null +++ b/src/types/common/token.ts @@ -0,0 +1,8 @@ +export interface Token { + system_type: number; + token_type: number; + pid: number; + access_level?: number; + title_id?: bigint; + expire_time: bigint; +} \ No newline at end of file diff --git a/src/types/common/yes-no-bool-string.ts b/src/types/common/yes-no-bool-string.ts new file mode 100644 index 0000000..474aa6e --- /dev/null +++ b/src/types/common/yes-no-bool-string.ts @@ -0,0 +1 @@ +export type YesNoBoolString = 'Y' | 'N'; \ No newline at end of file diff --git a/src/types/express.d.ts b/src/types/express.d.ts new file mode 100644 index 0000000..d6980f3 --- /dev/null +++ b/src/types/express.d.ts @@ -0,0 +1,17 @@ +import NintendoCertificate from '@/nintendo-certificate'; +import { HydratedPNIDDocument } from '@/types/mongoose/pnid'; +import { HydratedNEXAccountDocument } from '@/types/mongoose/nex-account'; +import { HydratedDeviceDocument } from '@/types/mongoose/device'; + +declare global { + namespace Express { + interface Request { + pnid: HydratedPNIDDocument | null; + nexAccount: HydratedNEXAccountDocument | null; + isCemu?: boolean; + files?: Record; + certificate?: NintendoCertificate; + device?: HydratedDeviceDocument; + } + } +} \ No newline at end of file diff --git a/src/types/image-pixels.d.ts b/src/types/image-pixels.d.ts new file mode 100644 index 0000000..a738a3f --- /dev/null +++ b/src/types/image-pixels.d.ts @@ -0,0 +1,32 @@ +declare module 'image-pixels' { + import { NdArray } from 'ndarray'; + + export interface ImagePixelsOptions { + source: ImageSource; + shape: [number, number]; + width: number; + height: number; + type: string; + mime: string; + clip: [number, number, number, number] | { + x?: number; + y?: number; + width?: number; + height?: number; + }; + cache: boolean; + } + + export type ImageSource = string | + HTMLImageElement | SVGImageElement | HTMLVideoElement | + typeof Image | ImageData | ImageBitmap | + File | Blob | + Buffer | ArrayBuffer | Uint8Array | Uint8ClampedArray | + Float32Array | Float64Array | Array | Array> | + NdArray | + ImagePixelsOptions; + + export default function pixels( + src: ImageSource | Promise + ): ImageData; +} \ No newline at end of file diff --git a/src/types/mii-js.d.ts b/src/types/mii-js.d.ts new file mode 100644 index 0000000..55cc57f --- /dev/null +++ b/src/types/mii-js.d.ts @@ -0,0 +1,100 @@ +declare module 'mii-js'; + +// TODO - These have limits, and should be validated + +type MiiStudioURLOptions = { + type?: string; + expression?: string; + width?: number; + bgColor?: string; + clothesColor?: string; + cameraXRotate?: number; + cameraYRotate?: number; + cameraZRotate?: number; + characterXRotate?: number; + characterYRotate?: number; + characterZRotate?: number; + lightXDirection?: number; + lightYDirection?: number; + lightZDirection?: number; + lightDirectionMode?: string; + instanceCount?: number; + instanceRotationMode?: string; +}; + +type Mii = { + version: number; + allowCopying: boolean; + profanityFlag: boolean; + regionLock: number; + characterSet: number; + pageIndex: number; + slotIndex: number; + unknown1: number; + deviceOrigin: number; + systemId: Buffer; + normalMii: boolean; + dsMii: boolean; + nonUserMii: boolean; + isValid: boolean; + creationTime: number; + consoleMAC: Buffer; + gender: number; + birthMonth: number; + birthDay: number; + favoriteColor: number; + favorite: boolean; + miiName: string; + height: number; + build: number; + disableSharing: boolean; + faceType: number; + skinColor: number; + wrinklesType: number; + makeupType: number; + hairType: number; + hairColor: number; + flipHair: boolean; + eyeType: number; + eyeColor: number; + eyeScale: number; + eyeVerticalStretch: number; + eyeRotation: number; + eyeSpacing: number; + eyeYPosition: number; + eyebrowType: number; + eyebrowColor: number; + eyebrowScale: number; + eyebrowVerticalStretch: number; + eyebrowRotation: number; + eyebrowSpacing: number; + eyebrowYPosition: number; + noseType: number; + noseScale: number; + noseYPosition: number; + mouthType: number; + mouthColor: number; + mouthScale: number; + mouthHorizontalStretch: number; + mouthYPosition: number; + mustacheType: number; + unknown2: number; + beardType: number; + facialHairColor: number; + mustacheScale: number; + mustacheYPosition: number; + glassesType: number; + glassesColor: number; + glassesScale: number; + glassesYPosition: number; + moleEnabled: boolean; + moleScale: number; + moleXPosition: number; + moleYPosition: number; + creatorName: string; + checksum: number; + + studioUrl: (options: MiiStudioURLOptions) => string; + encode: () => Buffer; + validate: () => void; +}; \ No newline at end of file diff --git a/src/types/mongoose-unique-validator.d.ts b/src/types/mongoose-unique-validator.d.ts new file mode 100644 index 0000000..0909028 --- /dev/null +++ b/src/types/mongoose-unique-validator.d.ts @@ -0,0 +1 @@ +declare module 'mongoose-unique-validator'; \ No newline at end of file diff --git a/src/types/mongoose/device-attribute.ts b/src/types/mongoose/device-attribute.ts new file mode 100644 index 0000000..e9eb87f --- /dev/null +++ b/src/types/mongoose/device-attribute.ts @@ -0,0 +1,13 @@ +import { Model } from 'mongoose'; + +export interface IDeviceAttribute { + created_date?: string; + name: string; + value: string; +} + +export interface IDeviceAttributeMethods {} + +interface IDeviceAttributeQueryHelpers {} + +export interface DeviceAttributeModel extends Model {} \ No newline at end of file diff --git a/src/types/mongoose/device.ts b/src/types/mongoose/device.ts new file mode 100644 index 0000000..dfc9d89 --- /dev/null +++ b/src/types/mongoose/device.ts @@ -0,0 +1,33 @@ +import { Model, Types, HydratedDocument } from 'mongoose'; +import { IDeviceAttribute } from '@/types/mongoose/device-attribute'; + +type MODEL = 'wup' | 'ctr' | 'spr' | 'ftr' | 'ktr' | 'red' | 'jan'; +type ACCESS_LEVEL = -1 | 0 | 1 | 2 | 3; +type SERVER_ACCESS_LEVEL = 'prod' | 'test' | 'dev'; + +export interface IDevice { + model: MODEL; + device_id: number; + device_type: number; + serial: string; + device_attributes: Types.DocumentArray; + soap: { + token: string; + account_id: number; + }; + environment: string; + mac_hash: string; // * 3DS-specific + fcdcert_hash: string; // * 3DS-specific + linked_pids: number[]; + access_level: ACCESS_LEVEL; + server_access_level: SERVER_ACCESS_LEVEL; + certificate_hash: string; +} + +export interface IDeviceMethods {} + +interface IDeviceQueryHelpers {} + +export interface DeviceModel extends Model {} + +export type HydratedDeviceDocument = HydratedDocument \ No newline at end of file diff --git a/src/types/mongoose/nex-account.ts b/src/types/mongoose/nex-account.ts new file mode 100644 index 0000000..e7fc997 --- /dev/null +++ b/src/types/mongoose/nex-account.ts @@ -0,0 +1,30 @@ +import { Model, HydratedDocument } from 'mongoose'; + +type DEVICE = 'wiiu' | '3ds'; +enum ACCESS_LEVEL { + User = 0, + Admin = 1, + Owner = 2, + Dev = 3 +} + +export interface INEXAccount { + device_type: DEVICE; + pid: number; + password: string; + owning_pid: number; + access_level: ACCESS_LEVEL; + server_access_level: string; + friend_code: string; +} + +export interface INEXAccountMethods { + generatePID(): Promise; + generatePassword(): void; +} + +interface INEXAccountQueryHelpers {} + +export interface NEXAccountModel extends Model {} + +export type HydratedNEXAccountDocument = HydratedDocument \ No newline at end of file diff --git a/src/types/mongoose/pnid.ts b/src/types/mongoose/pnid.ts new file mode 100644 index 0000000..3252c44 --- /dev/null +++ b/src/types/mongoose/pnid.ts @@ -0,0 +1,94 @@ +import { Model, Types, HydratedDocument } from 'mongoose'; +import { IDevice } from '@/types/mongoose/device'; +import { PNIDPermissionFlag } from '@/types/common/permission-flags'; + +export interface IPNID { + deleted: boolean; + permissions: bigint; + access_level: number; + server_access_level: string; + pid: number; + creation_date: string; + updated: string; + username: string; + usernameLower: string; + password: string; + birthdate: string; + gender: string; + country: string; + language: string; + email: { + address: string; + primary: boolean; + parent: boolean; + reachable: boolean; + validated: boolean; + validated_date: string; + id: number; + }; + region: number; + timezone: { + name: string; + offset: number; + marketing: boolean; + off_device: boolean; + }; + mii: { + name: string; + primary: boolean; + data: string; + id: number; + hash: string; + image_url: string; + image_id: number; + }; + flags: { + active: boolean; + marketing: boolean; + off_device: boolean; + }; + devices: Types.DocumentArray; + identification: { // * user identification tokens + email_code: string; + email_token: string; + access_token: { + value: string; + ttl: number; + }; + refresh_token: { + value: string; + ttl: number; + } + }; + connections: { + discord: { + id: string; + }; + stripe: { + customer_id: string; + subscription_id: string; + price_id: string; + tier_level: number; + tier_name: string; + latest_webhook_timestamp: number; + }; + }; +} + +export interface IPNIDMethods { + generatePID(): Promise; + generateEmailValidationCode(): Promise; + generateEmailValidationToken(): Promise; + updateMii(mii: { name: string, primary: string, data: string}): Promise; + generateMiiImages(): Promise; + scrub(): Promise; + hasPermission(flag: PNIDPermissionFlag): boolean; + addPermission(flag: PNIDPermissionFlag): void; + clearPermission(flag: PNIDPermissionFlag): void; +} + +interface IPNIDQueryHelpers {} + +export interface PNIDModel extends Model {} + +export type HydratedPNIDDocument = HydratedDocument \ No newline at end of file diff --git a/src/types/mongoose/server.ts b/src/types/mongoose/server.ts new file mode 100644 index 0000000..a7c8f6e --- /dev/null +++ b/src/types/mongoose/server.ts @@ -0,0 +1,23 @@ +import { Model, HydratedDocument } from 'mongoose'; + +export interface IServer { + client_id: string; + ip: string; + port: number; + service_name: string; + service_type: string; + game_server_id: string; + title_ids: string[]; + access_mode: string; + maintenance_mode: boolean; + device: number; + aes_key: string; +} + +export interface IServerMethods {} + +interface IServerQueryHelpers {} + +export interface ServerModel extends Model {} + +export type HydratedServerDocument = HydratedDocument \ No newline at end of file diff --git a/src/types/services/api/connection-data.ts b/src/types/services/api/connection-data.ts new file mode 100644 index 0000000..54fe992 --- /dev/null +++ b/src/types/services/api/connection-data.ts @@ -0,0 +1,4 @@ +import { DiscordConnectionData } from '@/types/services/api/discord-connection-data'; + +// TODO - This will be a union of all ConnectionData types when more connections are added +export type ConnectionData = DiscordConnectionData; \ No newline at end of file diff --git a/src/types/services/api/connection-response.ts b/src/types/services/api/connection-response.ts new file mode 100644 index 0000000..6baa9b0 --- /dev/null +++ b/src/types/services/api/connection-response.ts @@ -0,0 +1,5 @@ +export interface ConnectionResponse { + app: string; + status: number; + error?: string; +} \ No newline at end of file diff --git a/src/types/services/api/discord-connection-data.ts b/src/types/services/api/discord-connection-data.ts new file mode 100644 index 0000000..0ee459a --- /dev/null +++ b/src/types/services/api/discord-connection-data.ts @@ -0,0 +1,3 @@ +export interface DiscordConnectionData { + id: string; +} \ No newline at end of file diff --git a/src/types/services/api/update-user-request.ts b/src/types/services/api/update-user-request.ts new file mode 100644 index 0000000..a525e98 --- /dev/null +++ b/src/types/services/api/update-user-request.ts @@ -0,0 +1,7 @@ +export interface UpdateUserRequest { + mii?: { + name: string; + primary: string; + data: string; + } +} \ No newline at end of file diff --git a/src/types/services/nasc/request-params.ts b/src/types/services/nasc/request-params.ts new file mode 100644 index 0000000..aafcda6 --- /dev/null +++ b/src/types/services/nasc/request-params.ts @@ -0,0 +1,11 @@ +export interface NASCRequestParams { + action: string; + fcdcert: string; + csnum: string; + macadr: string; + titleid: string; + servertype: string; + userid?: string; + uidhmac?: string; + passwd?: string; +} \ No newline at end of file diff --git a/src/types/services/nnas/account-settings.ts b/src/types/services/nnas/account-settings.ts new file mode 100644 index 0000000..5cef6aa --- /dev/null +++ b/src/types/services/nnas/account-settings.ts @@ -0,0 +1,12 @@ +import { GenderTypes } from '@/types/common/gender-types'; + +export interface AccountSettings { + birthdate: string; + gender: GenderTypes; + tz_name: string; + region: number; + email: string; + server_selection: string; + marketing_flag: boolean; + off_device_flag: boolean; +} \ No newline at end of file diff --git a/src/types/services/nnas/person.ts b/src/types/services/nnas/person.ts new file mode 100644 index 0000000..00958e5 --- /dev/null +++ b/src/types/services/nnas/person.ts @@ -0,0 +1,44 @@ +import { YesNoBoolString } from '@/types/common/yes-no-bool-string'; +import { IDeviceAttribute } from '@/types/mongoose/device-attribute'; + +// TODO - Change this Map type to something more strongly typed +export interface Person { + birth_date: string; + user_id: string; + password: string; + country: string; + language: string; + tz_name: string; + agreement: { + agreement_date: string; + country: string; + location: string; + type: string; + version: string; + }; + email: { + address: string; + owned: YesNoBoolString; + parent: YesNoBoolString; + primary: YesNoBoolString; + validated: YesNoBoolString; + type: string; + }; + mii: { + name: string; + primary: YesNoBoolString; + data: string; + }; + parental_consent: { + scope: string; + consent_date: string; + approval_id: string; + }; + gender: string; + region: number; + marketing_flag: YesNoBoolString; + device_attributes: { + device_attribute: IDeviceAttribute[] + }; + off_device_flag: YesNoBoolString; +} \ No newline at end of file diff --git a/src/types/services/nnas/pnid-profile.ts b/src/types/services/nnas/pnid-profile.ts new file mode 100644 index 0000000..70adea5 --- /dev/null +++ b/src/types/services/nnas/pnid-profile.ts @@ -0,0 +1,53 @@ +import { YesNoBoolString } from '@/types/common/yes-no-bool-string'; + +export interface PNIDProfile { + // *accounts: {}; // * We need to figure this out; no idea what these values mean or what they do + active_flag: YesNoBoolString; + birth_date: string; + country: string; + create_date: string; + device_attributes: { + device_attribute: { + name: string; + value: string; + created_date: string; + }; + }[]; + gender: string; + language: string; + updated: string; + marketing_flag: YesNoBoolString; + off_device_flag: YesNoBoolString; + pid: number; + email: { + address: string; + id: number; + parent: YesNoBoolString; + primary: YesNoBoolString; + reachable: YesNoBoolString; + type: 'DEFAULT'; + updated_by: 'USER'; // * Can also be INTERNAL WS; don't know the difference + validated: YesNoBoolString; + validated_date: string; + }; + mii: { + status: 'COMPLETED'; + data: string; + id: number; + mii_hash: string; + mii_images: { + mii_image: { + cached_url: string; + id: number; + url: string; + type: 'standard'; + } + }; + name: string; + primary: YesNoBoolString; + }; + region: number; + tz_name: string; + user_id: string; + utc_offset: number; +} \ No newline at end of file diff --git a/src/types/services/nnas/region-languages.ts b/src/types/services/nnas/region-languages.ts new file mode 100644 index 0000000..fd4bbf9 --- /dev/null +++ b/src/types/services/nnas/region-languages.ts @@ -0,0 +1,5 @@ +import { RegionTimezones } from '@/types/services/nnas/region-timezones'; + +export interface RegionLanguages { + [myKey: string]: RegionTimezones +} \ No newline at end of file diff --git a/src/types/services/nnas/region-timezones.ts b/src/types/services/nnas/region-timezones.ts new file mode 100644 index 0000000..c904aaa --- /dev/null +++ b/src/types/services/nnas/region-timezones.ts @@ -0,0 +1,9 @@ +export interface RegionTimezone { + area: string; + language: string; + name: string; + utc_offset: string; + order: string; +} + +export type RegionTimezones = RegionTimezone[]; \ No newline at end of file diff --git a/src/types/services/nnas/regions.ts b/src/types/services/nnas/regions.ts new file mode 100644 index 0000000..1d77232 --- /dev/null +++ b/src/types/services/nnas/regions.ts @@ -0,0 +1,36 @@ +export interface Country { + id: number; + iso_code: string; + name: string; + translations: Translations; + regions: Region[]; +} + +export interface Translations { + japanese: string; + english: string; + french: string; + german: string; + italian: string; + spanish: string; + chinese_simple: string; + korean: string; + dutch: string; + portuguese: string; + russian: string; + chinese_traditional: string; + unknown1: string; + unknown2: string; + unknown3: string; + unknown4: string; +} + +export interface Region { + id: number; + name: string; + translations: Translations; + coordinates: { + latitude: number; + longitude: number; + }; +} diff --git a/src/types/tga.d.ts b/src/types/tga.d.ts new file mode 100644 index 0000000..16eb4a2 --- /dev/null +++ b/src/types/tga.d.ts @@ -0,0 +1,58 @@ +declare module 'tga' { + export interface TGAHeader { + idLength: number; + colorMapType: number; + dataType: number; + colorMapOrigin: number; + colorMapLength: number; + colorMapDepth: number; + xOrigin: number; + yOrigin: number; + width: number; + height: number; + bitsPerPixel: number; + flags: number; + id: string; + } + + export default class TGA { + constructor(buf: Buffer, opt?: { dontFixAlpha: boolean }); + + static createTgaBuffer(width: number, height: number, pixels: Uint8Array, dontFlipY: boolean): Buffer; + + parseHeader(): void; + parseFooter(): void; + parseExtension(extensionAreaOffset: number): void; + readColor(offset: number, bytesPerPixel: number): Uint8Array; + readColorWithColorMap(offset: number): Uint8Array; + readColorAuto(offset: number, bytesPerPixel: number, isUsingColorMap: boolean): Uint8Array; + parseColorMap(): void; + setPixel(pixels: Uint8Array, idx: number, color: Uint8Array): void; + parsePixels(): void; + parse(): void; + fixForAlpha(): void; + + public dontFixAlpha: boolean; + public _buff: Buffer; + public data: Uint8Array; + public currentOffset: number; + + public header: TGAHeader; + + public width: number; + public height: number; + + public isUsingColorMap: boolean; + public isUsingRLE: boolean; + public isGray: boolean; + + public hasAlpha: boolean; + + public isFlipX: boolean; + public isFlipY: boolean; + + public colorMap: Uint8Array; + + public pixels: Uint8Array; + } +} \ No newline at end of file diff --git a/src/util.js b/src/util.js deleted file mode 100644 index 0050b38..0000000 --- a/src/util.js +++ /dev/null @@ -1,319 +0,0 @@ -const crypto = require('crypto'); -const path = require('path'); -const NodeRSA = require('node-rsa'); -const aws = require('aws-sdk'); -const fs = require('fs-extra'); -const mailer = require('./mailer'); -const cache = require('./cache'); -const { config, disabledFeatures } = require('./config-manager'); - -let s3; - -if (!disabledFeatures.s3) { - s3 = new aws.S3({ - endpoint: new aws.Endpoint(config.s3.endpoint), - accessKeyId: config.s3.key, - secretAccessKey: config.s3.secret - }); -} - -function nintendoPasswordHash(password, pid) { - const pidBuffer = Buffer.alloc(4); - pidBuffer.writeUInt32LE(pid); - - const unpacked = Buffer.concat([ - pidBuffer, - Buffer.from('\x02\x65\x43\x46'), - Buffer.from(password) - ]); - const hashed = crypto.createHash('sha256').update(unpacked).digest().toString('hex'); - - return hashed; -} - -function nintendoBase64Decode(encoded) { - encoded = encoded.replaceAll('.', '+').replaceAll('-', '/').replaceAll('*', '='); - return Buffer.from(encoded, 'base64'); -} - -function nintendoBase64Encode(decoded) { - const encoded = Buffer.from(decoded).toString('base64'); - return encoded.replaceAll('+', '.').replaceAll('/', '-').replaceAll('=', '*'); -} - -async function generateToken(cryptoOptions, tokenOptions) { - - // Access and refresh tokens use a different format since they must be much smaller - // They take no extra crypto options - if (!cryptoOptions) { - const aesKey = await cache.getServiceAESKey('account', 'hex'); - - const dataBuffer = Buffer.alloc(1 + 1 + 4 + 8); - - dataBuffer.writeUInt8(tokenOptions.system_type, 0x0); - dataBuffer.writeUInt8(tokenOptions.token_type, 0x1); - dataBuffer.writeUInt32LE(tokenOptions.pid, 0x2); - dataBuffer.writeBigUInt64LE(tokenOptions.expire_time, 0x6); - - const iv = Buffer.alloc(16); - const cipher = crypto.createCipheriv('aes-128-cbc', aesKey, iv); - - let encryptedBody = cipher.update(dataBuffer); - encryptedBody = Buffer.concat([encryptedBody, cipher.final()]); - - return encryptedBody.toString('base64'); - } - - const publicKey = new NodeRSA(cryptoOptions.public_key, 'pkcs8-public-pem', { - environment: 'browser', - encryptionScheme: { - 'hash': 'sha256', - } - }); - - // Create the buffer containing the token data - const dataBuffer = Buffer.alloc(1 + 1 + 4 + 1 + 8 + 8); - - dataBuffer.writeUInt8(tokenOptions.system_type, 0x0); - dataBuffer.writeUInt8(tokenOptions.token_type, 0x1); - dataBuffer.writeUInt32LE(tokenOptions.pid, 0x2); - dataBuffer.writeUInt8(tokenOptions.access_level, 0x6); - dataBuffer.writeBigUInt64LE(tokenOptions.title_id, 0x7); - dataBuffer.writeBigUInt64LE(tokenOptions.expire_time, 0xF); - - // Calculate the signature of the token body - const hmac = crypto.createHmac('sha1', cryptoOptions.hmac_secret).update(dataBuffer); - const signature = hmac.digest(); - - // You can thank the 3DS for the shit thats about to happen with the AES IV - // The 3DS only allows for strings up to 255 characters in NEX - // So this is done to reduce the token size as much as possible - // I am sorry, and have already asked every God I could think of for forgiveness - - // Generate random AES key - const key = crypto.randomBytes(16); - - // Encrypt the AES key with RSA public key - const encryptedKey = publicKey.encrypt(key); - - // Take two random points in the RSA encrypted key - const point1 = ~~((encryptedKey.length - 8) * Math.random()); - const point2 = ~~((encryptedKey.length - 8) * Math.random()); - - // Build an IV from each of the two points - const iv = Buffer.concat([ - Buffer.from(encryptedKey.subarray(point1, point1 + 8)), - Buffer.from(encryptedKey.subarray(point2, point2 + 8)) - ]); - - const cipher = crypto.createCipheriv('aes-128-cbc', key, iv); - - // Encrypt the token body with AES - let encryptedBody = cipher.update(dataBuffer); - encryptedBody = Buffer.concat([encryptedBody, cipher.final()]); - - // Create crypto config token section - const cryptoConfig = Buffer.concat([ - encryptedKey, - Buffer.from([point1, point2]) - ]); - - // Build the token - const token = Buffer.concat([ - cryptoConfig, - signature, - encryptedBody - ]); - - return token.toString('base64'); // Encode to base64 for transport -} - -async function decryptToken(token) { - // Access and refresh tokens use a different format since they must be much smaller - // Assume a small length means access or refresh token - if (token.length <= 32) { - const aesKey = await cache.getServiceAESKey('account', 'hex'); - - const iv = Buffer.alloc(16); - - const decipher = crypto.createDecipheriv('aes-128-cbc', aesKey, iv); - - let decryptedBody = decipher.update(token); - decryptedBody = Buffer.concat([decryptedBody, decipher.final()]); - - return decryptedBody; - } - - const privateKeyBytes = await cache.getServicePrivateKey('account'); - const secretKey = await cache.getServiceSecretKey('account'); - - const privateKey = new NodeRSA(privateKeyBytes, 'pkcs1-private-pem', { - environment: 'browser', - encryptionScheme: { - 'hash': 'sha256', - } - }); - - const cryptoConfig = token.subarray(0, 0x82); - const signature = token.subarray(0x82, 0x96); - const encryptedBody = token.subarray(0x96); - - const encryptedAESKey = cryptoConfig.subarray(0, 128); - const point1 = cryptoConfig.readInt8(0x80); - const point2 = cryptoConfig.readInt8(0x81); - - const iv = Buffer.concat([ - Buffer.from(encryptedAESKey.subarray(point1, point1 + 8)), - Buffer.from(encryptedAESKey.subarray(point2, point2 + 8)) - ]); - - const decryptedAESKey = privateKey.decrypt(encryptedAESKey); - - const decipher = crypto.createDecipheriv('aes-128-cbc', decryptedAESKey, iv); - - let decryptedBody = decipher.update(encryptedBody); - decryptedBody = Buffer.concat([decryptedBody, decipher.final()]); - - const hmac = crypto.createHmac('sha1', secretKey).update(decryptedBody); - const calculatedSignature = hmac.digest(); - - if (!signature.equals(calculatedSignature)) { - console.log('Token signature did not match'); - return null; - } - - return decryptedBody; -} - -function unpackToken(token) { - if (token.length <= 14) { - return { - system_type: token.readUInt8(0x0), - token_type: token.readUInt8(0x1), - pid: token.readUInt32LE(0x2), - expire_time: token.readBigUInt64LE(0x6) - }; - } - - return { - system_type: token.readUInt8(0x0), - token_type: token.readUInt8(0x1), - pid: token.readUInt32LE(0x2), - access_level: token.readUInt8(0x6), - title_id: token.readBigUInt64LE(0x7), - expire_time: token.readBigUInt64LE(0xF) - }; -} - -function fullUrl(request) { - const protocol = request.protocol; - const host = request.host; - const opath = request.originalUrl; - - return `${protocol}://${host}${opath}`; -} - -async function uploadCDNAsset(bucket, key, data, acl) { - if (disabledFeatures.s3) { - await writeLocalCDNFile(key, data); - } else { - const awsPutParams = { - Body: data, - Key: key, - Bucket: bucket, - ACL: acl - }; - - await s3.putObject(awsPutParams).promise(); - } -} - -async function writeLocalCDNFile(key, data) { - const filePath = config.cdn.disk_path; - const folder = path.dirname(filePath); - - await fs.ensureDir(folder); - await fs.writeFile(filePath, data); -} - -function nascError(errorCode) { - const params = new URLSearchParams({ - retry: nintendoBase64Encode('1'), - returncd: errorCode == 'null' ? errorCode : nintendoBase64Encode(errorCode), - datetime: nintendoBase64Encode(Date.now().toString()), - }); - - return params; -} - -async function sendConfirmationEmail(pnid) { - await mailer.sendMail({ - to: pnid.get('email.address'), - subject: '[Pretendo Network] Please confirm your email address', - username: pnid.get('username'), - confirmation: { - href: `https://api.pretendo.cc/v1/email/verify?token=${pnid.get('identification.email_token')}`, - code: pnid.get('identification.email_code') - }, - text: `Hello ${pnid.get('username')}! \r\n\r\nYour Pretendo Network ID activation is almost complete. Please click the link to confirm your e-mail address and complete the activation process: \r\nhttps://api.pretendo.cc/v1/email/verify?token=${pnid.get('identification.email_token')} \r\n\r\nYou may also enter the following 6-digit code on your console: ${pnid.get('identification.email_code')}` - }); - -} - -async function sendEmailConfirmedEmail(pnid) { - await mailer.sendMail({ - to: pnid.get('email.address'), - subject: '[Pretendo Network] Email address confirmed', - username: pnid.get('username'), - paragraph: 'your email address has been confirmed. We hope you have fun on Pretendo Network!', - text: `Dear ${pnid.get('username')}, \r\n\r\nYour email address has been confirmed. We hope you have fun on Pretendo Network!` - }); -} - -async function sendForgotPasswordEmail(pnid) { - const publicKey = await cache.getServicePublicKey('account'); - const secretKey = await cache.getServiceSecretKey('account'); - - const cryptoOptions = { - public_key: publicKey, - hmac_secret: secretKey - }; - - const tokenOptions = { - system_type: 0xF, // API - token_type: 0x5, // Password reset - pid: pnid.get('pid'), - access_level: pnid.get('access_level'), - title_id: BigInt(0), - expire_time: BigInt(Date.now() + (24 * 60 * 60 * 1000)) // Only valid for 24 hours - }; - - const passwordResetToken = await generateToken(cryptoOptions, tokenOptions); - - await mailer.sendMail({ - to: pnid.get('email.address'), - subject: '[Pretendo Network] Forgot Password', - username: pnid.get('username'), - paragraph: 'a password reset has been requested from this account. If you did not request the password reset, please ignore this email. If you did request this password reset, please click the link below to reset your password.', - link: { - text: 'Reset password', - href: `${config.website_base}/account/reset-password?token=${encodeURIComponent(passwordResetToken)}` - }, - text: `Dear ${pnid.get('username')}, a password reset has been requested from this account. \r\n\r\nIf you did not request the password reset, please ignore this email. \r\nIf you did request this password reset, please click the link to reset your password: ${config.website_base}/account/reset-password?token=${encodeURIComponent(passwordResetToken)}` - }); -} - -module.exports = { - nintendoPasswordHash, - nintendoBase64Decode, - nintendoBase64Encode, - generateToken, - decryptToken, - unpackToken, - fullUrl, - uploadCDNAsset, - nascError, - sendConfirmationEmail, - sendEmailConfirmedEmail, - sendForgotPasswordEmail -}; \ No newline at end of file diff --git a/src/util.ts b/src/util.ts new file mode 100644 index 0000000..0361952 --- /dev/null +++ b/src/util.ts @@ -0,0 +1,337 @@ +import crypto from 'node:crypto'; +import path from 'node:path'; +import { IncomingHttpHeaders } from 'node:http'; +import { ObjectCannedACL, S3 } from '@aws-sdk/client-s3'; +import fs from 'fs-extra'; +import express from 'express'; +import mongoose from 'mongoose'; +import { ParsedQs } from 'qs'; +import crc32 from 'buffer-crc32'; +import crc from 'crc'; +import { sendMail } from '@/mailer'; +import { config, disabledFeatures } from '@/config-manager'; +import { TokenOptions } from '@/types/common/token-options'; +import { Token } from '@/types/common/token'; +import { IPNID, IPNIDMethods } from '@/types/mongoose/pnid'; +import { SafeQs } from '@/types/common/safe-qs'; + +let s3: S3; + +if (!disabledFeatures.s3) { + s3 = new S3({ + endpoint: config.s3.endpoint, + forcePathStyle: config.s3.forcePathStyle, + region: config.s3.region, + + credentials: { + accessKeyId: config.s3.key, + secretAccessKey: config.s3.secret, + }, + }); +} + +export function nintendoPasswordHash(password: string, pid: number): string { + const pidBuffer = Buffer.alloc(4); + pidBuffer.writeUInt32LE(pid); + + const unpacked = Buffer.concat([ + pidBuffer, + Buffer.from('\x02\x65\x43\x46'), + Buffer.from(password) + ]); + + return crypto.createHash('sha256').update(unpacked).digest().toString('hex'); +} + +export function nintendoBase64Decode(encoded: string): Buffer { + encoded = encoded.replaceAll('.', '+').replaceAll('-', '/').replaceAll('*', '='); + return Buffer.from(encoded, 'base64'); +} + +export function nintendoBase64Encode(decoded: string | Buffer): string { + const encoded = Buffer.from(decoded).toString('base64'); + return encoded.replaceAll('+', '.').replaceAll('/', '-').replaceAll('=', '*'); +} + +export function generateToken(key: string, options: TokenOptions): Buffer | null { + let dataBuffer = Buffer.alloc(1 + 1 + 4 + 8); + + dataBuffer.writeUInt8(options.system_type, 0x0); + dataBuffer.writeUInt8(options.token_type, 0x1); + dataBuffer.writeUInt32LE(options.pid, 0x2); + dataBuffer.writeBigUInt64LE(options.expire_time, 0x6); + + if ((options.token_type !== 0x1 && options.token_type !== 0x2) || options.system_type === 0x3) { + // * Access and refresh tokens have smaller bodies due to size constraints + // * The API does not have this restraint, however + if (options.title_id === undefined || options.access_level === undefined) { + return null; + } + + dataBuffer = Buffer.concat([ + dataBuffer, + Buffer.alloc(8 + 1) + ]); + + dataBuffer.writeBigUInt64LE(options.title_id, 0xE); + dataBuffer.writeInt8(options.access_level, 0x16); + } + + const iv = Buffer.alloc(16); + const cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(key, 'hex'), iv); + + const encrypted = Buffer.concat([ + cipher.update(dataBuffer), + cipher.final() + ]); + + let final = encrypted; + + if ((options.token_type !== 0x1 && options.token_type !== 0x2) || options.system_type === 0x3) { + // * Access and refresh tokens don't get a checksum due to size constraints + const checksum = crc32(dataBuffer); + + final = Buffer.concat([ + checksum, + final + ]); + } + + return final; +} + +export function decryptToken(token: Buffer, key?: string): Buffer { + let encryptedBody: Buffer; + let expectedChecksum = 0; + + if (token.length === 16) { + // * Token is an access/refresh token, no checksum + encryptedBody = token; + } else { + expectedChecksum = token.readUint32BE(); + encryptedBody = token.subarray(4); + } + + if (!key) { + key = config.aes_key; + } + + const iv = Buffer.alloc(16); + const decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(key, 'hex'), iv); + + const decrypted = Buffer.concat([ + decipher.update(encryptedBody), + decipher.final() + ]); + + if (expectedChecksum && (expectedChecksum !== crc.crc32(decrypted))) { + throw new Error('Checksum did not match. Failed decrypt. Are you using the right key?'); + } + + return decrypted; +} + +export function unpackToken(token: Buffer): Token { + const unpacked: Token = { + system_type: token.readUInt8(0x0), + token_type: token.readUInt8(0x1), + pid: token.readUInt32LE(0x2), + expire_time: token.readBigUInt64LE(0x6) + }; + + if (unpacked.token_type !== 0x1 && unpacked.token_type !== 0x2) { + unpacked.title_id = token.readBigUInt64LE(0xE); + unpacked.access_level = token.readInt8(0x16); + } + + return unpacked; +} + +export function fullUrl(request: express.Request): string { + const protocol = request.protocol; + const host = request.host; + const opath = request.originalUrl; + + return `${protocol}://${host}${opath}`; +} + +export async function uploadCDNAsset(bucket: string, key: string, data: Buffer, acl: ObjectCannedACL): Promise { + if (disabledFeatures.s3) { + await writeLocalCDNFile(key, data); + } else { + await s3.putObject({ + Body: data, + Key: key, + Bucket: bucket, + ACL: acl + }); + } +} + +export async function writeLocalCDNFile(key: string, data: Buffer): Promise { + const filePath = config.cdn.disk_path; + const folder = path.dirname(filePath); + + await fs.ensureDir(folder); + await fs.writeFile(filePath, data); +} + +export function nascDateTime(): string { + const now = new Date(); + + const year = now.getFullYear(); + const month = (now.getMonth() + 1).toString().padStart(2, '0'); // * Months are zero-based + const day = now.getDate().toString().padStart(2, '0'); + const hours = now.getHours().toString().padStart(2, '0'); + const minutes = now.getMinutes().toString().padStart(2, '0'); + const seconds = now.getSeconds().toString().padStart(2, '0'); + + return `${year}${month}${day}${hours}${minutes}${seconds}`; +} + +export function nascError(errorCode: string): URLSearchParams { + return new URLSearchParams({ + retry: nintendoBase64Encode('1'), + returncd: errorCode == 'null' ? errorCode : nintendoBase64Encode(errorCode), + datetime: nintendoBase64Encode(nascDateTime()), + }); +} + +export async function sendConfirmationEmail(pnid: mongoose.HydratedDocument): Promise { + const options = { + to: pnid.email.address, + subject: '[Pretendo Network] Please confirm your email address', + username: pnid.username, + confirmation: { + href: `https://api.pretendo.cc/v1/email/verify?token=${pnid.identification.email_token}`, + code: pnid.identification.email_code + }, + text: `Hello ${pnid.username}! \r\n\r\nYour Pretendo Network ID activation is almost complete. Please click the link to confirm your e-mail address and complete the activation process: \r\nhttps://api.pretendo.cc/v1/email/verify?token=${pnid.identification.email_token} \r\n\r\nYou may also enter the following 6-digit code on your console: ${pnid.identification.email_code}` + }; + + await sendMail(options); +} + +export async function sendEmailConfirmedEmail(pnid: mongoose.HydratedDocument): Promise { + const options = { + to: pnid.email.address, + subject: '[Pretendo Network] Email address confirmed', + username: pnid.username, + paragraph: 'your email address has been confirmed. We hope you have fun on Pretendo Network!', + text: `Dear ${pnid.username}, \r\n\r\nYour email address has been confirmed. We hope you have fun on Pretendo Network!` + }; + + await sendMail(options); +} + +export async function sendEmailConfirmedParentalControlsEmail(pnid: mongoose.HydratedDocument): Promise { + const options = { + to: pnid.email.address, + subject: '[Pretendo Network] Email address confirmed for Parental Controls', + username: pnid.username, + paragraph: 'your email address has been confirmed for use with Parental Controls.', + text: `Dear ${pnid.username}, \r\n\r\nYour email address has been confirmed for use with Parental Controls.` + }; + + await sendMail(options); +} + +export async function sendForgotPasswordEmail(pnid: mongoose.HydratedDocument): Promise { + const tokenOptions = { + system_type: 0xF, // * API + token_type: 0x5, // * Password reset + pid: pnid.pid, + access_level: pnid.access_level, + title_id: BigInt(0), + expire_time: BigInt(Date.now() + (24 * 60 * 60 * 1000)) // * Only valid for 24 hours + }; + + const tokenBuffer = await generateToken(config.aes_key, tokenOptions); + const passwordResetToken = tokenBuffer ? tokenBuffer.toString('hex') : ''; + + // TODO - Handle null token + + const mailerOptions = { + to: pnid.email.address, + subject: '[Pretendo Network] Forgot Password', + username: pnid.username, + paragraph: 'a password reset has been requested from this account. If you did not request the password reset, please ignore this email. If you did request this password reset, please click the link below to reset your password.', + link: { + text: 'Reset password', + href: `${config.website_base}/account/reset-password?token=${encodeURIComponent(passwordResetToken)}` + }, + text: `Dear ${pnid.username}, a password reset has been requested from this account. \r\n\r\nIf you did not request the password reset, please ignore this email. \r\nIf you did request this password reset, please click the link to reset your password: ${config.website_base}/account/reset-password?token=${encodeURIComponent(passwordResetToken)}` + }; + + await sendMail(mailerOptions); +} + +export async function sendPNIDDeletedEmail(email: string, username: string): Promise { + const options = { + to: email, + subject: '[Pretendo Network] PNID Deleted', + username: username, + link: { + text: 'Discord Server', + href: 'https://discord.com/invite/pretendo' + }, + text: `Your PNID ${username} has successfully been deleted. If you had a tier subscription, a separate cancellation email will be sent. If you do not receive this cancellation email, or your subscription is still being charged, please contact @jon on our Discord server` + }; + + await sendMail(options); +} + +export function makeSafeQs(query: ParsedQs): SafeQs { + const entries = Object.entries(query); + const output: SafeQs = {}; + + for (const [key, value] of entries) { + if (typeof value !== 'string') { + // * ignore non-strings + continue; + } + + output[key] = value; + } + + return output; +} + +export function getValueFromQueryString(qs: ParsedQs, key: string): string | undefined { + let property = qs[key]; + let value; + + if (property) { + if (Array.isArray(property)) { + property = property[0]; + } + + if (typeof property !== 'string') { + property = makeSafeQs(property); + value = (property)[key]; + } else { + value = property; + } + } + + return value; +} + +export function getValueFromHeaders(headers: IncomingHttpHeaders, key: string): string | undefined { + let header = headers[key]; + let value; + + if (header) { + if (!Array.isArray(header)) { + header = header.split(', '); + } + + value = header[0]; + } + + return value; +} + +export function mapToObject(map: Map): object { + return Object.fromEntries(Array.from(map.entries(), ([ k, v ]) => v instanceof Map ? [ k, mapToObject(v) ] : [ k, v ])); +} \ No newline at end of file diff --git a/src/views/index.ejs b/src/views/index.ejs new file mode 100644 index 0000000..a83781c --- /dev/null +++ b/src/views/index.ejs @@ -0,0 +1,191 @@ + + + + + Account Settings + + + +
+
+

Pretendo Network ID Settings

+ + +
+ +
+

User Settings

+
+

Birth Date

+ +
+
+

Gender

+ +
+
+

Country

+ +
+
+

Region

+ +
+
+

Timezone

+ +
+

Email

+
+ +
+
+ <% if(PNID.email.validated) { %> + Verified + + <% } else { %> + Email Not Verified + + <% } %> +
+

Other Settings

+
+

Server Environment

+
+ checked=""<% } %>> + + <% if(PNID.access_level >= 1) { %> + checked="" <% } %> <% if(PNID.access_level < 1) { %> disabled <% } %> > + + <% } %> + <% if(PNID.access_level === 3) { %> + checked="" <% } %> <% if(PNID.access_level < 3) { %> disabled <% } %> > + + <% } %> +
+
+
+

Email Notifications

+
+ checked=""<% } %>> + + checked=""<% } %>> + +
+
+
+

Non-Nintendo Device Setting

+
+ checked=""<% } %>> + + checked=""<% } %>> + +
+
+
+
+ <% if (notice) { %> + + <% } %> + + + + \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..cdef6fa --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "strict": true, + "resolveJsonModule": true, + "module": "commonjs", + "esModuleInterop": true, + "moduleResolution": "node", + "baseUrl": "src", + "outDir": "dist", + "allowJs": true, + "target": "es2022", + "noEmitOnError": true, + "paths": { + "@/*": ["./*"] + }, + "typeRoots": [ + "node_modules/@types", + "node_modules/@hcaptcha" + ] + }, + "include": ["src"] +} \ No newline at end of file