Merge branch 'master' into nymkappa/bugfix/update-log-indexer
This commit is contained in:
		
						commit
						475bb11991
					
				| @ -63,6 +63,11 @@ | |||||||
|     "ENABLED": true, |     "ENABLED": true, | ||||||
|     "TX_PER_SECOND_SAMPLE_PERIOD": 150 |     "TX_PER_SECOND_SAMPLE_PERIOD": 150 | ||||||
|   }, |   }, | ||||||
|  |   "MAXMIND": { | ||||||
|  |     "ENABLED": false, | ||||||
|  |     "GEOLITE2_CITY": "/usr/local/share/GeoIP/GeoLite2-City.mmdb", | ||||||
|  |     "GEOLITE2_ASN": "/usr/local/share/GeoIP/GeoLite2-ASN.mmdb" | ||||||
|  |   }, | ||||||
|   "BISQ": { |   "BISQ": { | ||||||
|     "ENABLED": false, |     "ENABLED": false, | ||||||
|     "DATA_PATH": "/bisq/statsnode-data/btc_mainnet/db" |     "DATA_PATH": "/bisq/statsnode-data/btc_mainnet/db" | ||||||
|  | |||||||
							
								
								
									
										50
									
								
								backend/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										50
									
								
								backend/package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -17,6 +17,7 @@ | |||||||
|         "crypto-js": "^4.0.0", |         "crypto-js": "^4.0.0", | ||||||
|         "express": "^4.18.0", |         "express": "^4.18.0", | ||||||
|         "lightning": "^5.16.3", |         "lightning": "^5.16.3", | ||||||
|  |         "maxmind": "^4.3.6", | ||||||
|         "mysql2": "2.3.3", |         "mysql2": "2.3.3", | ||||||
|         "node-worker-threads-pool": "^1.5.1", |         "node-worker-threads-pool": "^1.5.1", | ||||||
|         "socks-proxy-agent": "~7.0.0", |         "socks-proxy-agent": "~7.0.0", | ||||||
| @ -2222,6 +2223,19 @@ | |||||||
|         "node": ">=10" |         "node": ">=10" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |     "node_modules/maxmind": { | ||||||
|  |       "version": "4.3.6", | ||||||
|  |       "resolved": "https://registry.npmjs.org/maxmind/-/maxmind-4.3.6.tgz", | ||||||
|  |       "integrity": "sha512-CwnEZqJX0T6b2rWrc0/V3n9hL/hWAMEn7fY09077YJUHiHx7cn/esA2ZIz8BpYLSJUf7cGVel0oUJa9jMwyQpg==", | ||||||
|  |       "dependencies": { | ||||||
|  |         "mmdb-lib": "2.0.2", | ||||||
|  |         "tiny-lru": "8.0.2" | ||||||
|  |       }, | ||||||
|  |       "engines": { | ||||||
|  |         "node": ">=10", | ||||||
|  |         "npm": ">=6" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     "node_modules/md5.js": { |     "node_modules/md5.js": { | ||||||
|       "version": "1.3.5", |       "version": "1.3.5", | ||||||
|       "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", |       "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", | ||||||
| @ -2317,6 +2331,15 @@ | |||||||
|         "node": "*" |         "node": "*" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |     "node_modules/mmdb-lib": { | ||||||
|  |       "version": "2.0.2", | ||||||
|  |       "resolved": "https://registry.npmjs.org/mmdb-lib/-/mmdb-lib-2.0.2.tgz", | ||||||
|  |       "integrity": "sha512-shi1I+fCPQonhTi7qyb6hr7hi87R7YS69FlfJiMFuJ12+grx0JyL56gLNzGTYXPU7EhAPkMLliGeyHer0K+AVA==", | ||||||
|  |       "engines": { | ||||||
|  |         "node": ">=10", | ||||||
|  |         "npm": ">=6" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     "node_modules/ms": { |     "node_modules/ms": { | ||||||
|       "version": "2.0.0", |       "version": "2.0.0", | ||||||
|       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", |       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", | ||||||
| @ -3027,6 +3050,14 @@ | |||||||
|       "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", |       "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", | ||||||
|       "dev": true |       "dev": true | ||||||
|     }, |     }, | ||||||
|  |     "node_modules/tiny-lru": { | ||||||
|  |       "version": "8.0.2", | ||||||
|  |       "resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-8.0.2.tgz", | ||||||
|  |       "integrity": "sha512-ApGvZ6vVvTNdsmt676grvCkUCGwzG9IqXma5Z07xJgiC5L7akUMof5U8G2JTI9Rz/ovtVhJBlY6mNhEvtjzOIg==", | ||||||
|  |       "engines": { | ||||||
|  |         "node": ">=6" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     "node_modules/tiny-secp256k1": { |     "node_modules/tiny-secp256k1": { | ||||||
|       "version": "2.2.1", |       "version": "2.2.1", | ||||||
|       "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.2.1.tgz", |       "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.2.1.tgz", | ||||||
| @ -4971,6 +5002,15 @@ | |||||||
|         "yallist": "^4.0.0" |         "yallist": "^4.0.0" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |     "maxmind": { | ||||||
|  |       "version": "4.3.6", | ||||||
|  |       "resolved": "https://registry.npmjs.org/maxmind/-/maxmind-4.3.6.tgz", | ||||||
|  |       "integrity": "sha512-CwnEZqJX0T6b2rWrc0/V3n9hL/hWAMEn7fY09077YJUHiHx7cn/esA2ZIz8BpYLSJUf7cGVel0oUJa9jMwyQpg==", | ||||||
|  |       "requires": { | ||||||
|  |         "mmdb-lib": "2.0.2", | ||||||
|  |         "tiny-lru": "8.0.2" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     "md5.js": { |     "md5.js": { | ||||||
|       "version": "1.3.5", |       "version": "1.3.5", | ||||||
|       "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", |       "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", | ||||||
| @ -5039,6 +5079,11 @@ | |||||||
|         "brace-expansion": "^1.1.7" |         "brace-expansion": "^1.1.7" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |     "mmdb-lib": { | ||||||
|  |       "version": "2.0.2", | ||||||
|  |       "resolved": "https://registry.npmjs.org/mmdb-lib/-/mmdb-lib-2.0.2.tgz", | ||||||
|  |       "integrity": "sha512-shi1I+fCPQonhTi7qyb6hr7hi87R7YS69FlfJiMFuJ12+grx0JyL56gLNzGTYXPU7EhAPkMLliGeyHer0K+AVA==" | ||||||
|  |     }, | ||||||
|     "ms": { |     "ms": { | ||||||
|       "version": "2.0.0", |       "version": "2.0.0", | ||||||
|       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", |       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", | ||||||
| @ -5549,6 +5594,11 @@ | |||||||
|       "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", |       "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", | ||||||
|       "dev": true |       "dev": true | ||||||
|     }, |     }, | ||||||
|  |     "tiny-lru": { | ||||||
|  |       "version": "8.0.2", | ||||||
|  |       "resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-8.0.2.tgz", | ||||||
|  |       "integrity": "sha512-ApGvZ6vVvTNdsmt676grvCkUCGwzG9IqXma5Z07xJgiC5L7akUMof5U8G2JTI9Rz/ovtVhJBlY6mNhEvtjzOIg==" | ||||||
|  |     }, | ||||||
|     "tiny-secp256k1": { |     "tiny-secp256k1": { | ||||||
|       "version": "2.2.1", |       "version": "2.2.1", | ||||||
|       "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.2.1.tgz", |       "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.2.1.tgz", | ||||||
|  | |||||||
| @ -38,6 +38,7 @@ | |||||||
|     "crypto-js": "^4.0.0", |     "crypto-js": "^4.0.0", | ||||||
|     "express": "^4.18.0", |     "express": "^4.18.0", | ||||||
|     "lightning": "^5.16.3", |     "lightning": "^5.16.3", | ||||||
|  |     "maxmind": "^4.3.6", | ||||||
|     "mysql2": "2.3.3", |     "mysql2": "2.3.3", | ||||||
|     "node-worker-threads-pool": "^1.5.1", |     "node-worker-threads-pool": "^1.5.1", | ||||||
|     "socks-proxy-agent": "~7.0.0", |     "socks-proxy-agent": "~7.0.0", | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ import logger from '../logger'; | |||||||
| import { Common } from './common'; | import { Common } from './common'; | ||||||
| 
 | 
 | ||||||
| class DatabaseMigration { | class DatabaseMigration { | ||||||
|   private static currentVersion = 28; |   private static currentVersion = 29; | ||||||
|   private queryTimeout = 120000; |   private queryTimeout = 120000; | ||||||
|   private statisticsAddedIndexed = false; |   private statisticsAddedIndexed = false; | ||||||
|   private uniqueLogs: string[] = []; |   private uniqueLogs: string[] = []; | ||||||
| @ -280,6 +280,17 @@ class DatabaseMigration { | |||||||
|         await this.$executeQuery(`ALTER TABLE lightning_stats MODIFY added DATE`); |         await this.$executeQuery(`ALTER TABLE lightning_stats MODIFY added DATE`); | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|  |       if (databaseSchemaVersion < 29 && isBitcoin === true) { | ||||||
|  |         await this.$executeQuery(this.getCreateGeoNamesTableQuery(), await this.$checkIfTableExists('geo_names')); | ||||||
|  |         await this.$executeQuery('ALTER TABLE `nodes` ADD as_number int(11) unsigned NULL DEFAULT NULL'); | ||||||
|  |         await this.$executeQuery('ALTER TABLE `nodes` ADD city_id int(11) unsigned NULL DEFAULT NULL'); | ||||||
|  |         await this.$executeQuery('ALTER TABLE `nodes` ADD country_id int(11) unsigned NULL DEFAULT NULL'); | ||||||
|  |         await this.$executeQuery('ALTER TABLE `nodes` ADD accuracy_radius int(11) unsigned NULL DEFAULT NULL'); | ||||||
|  |         await this.$executeQuery('ALTER TABLE `nodes` ADD subdivision_id int(11) unsigned NULL DEFAULT NULL'); | ||||||
|  |         await this.$executeQuery('ALTER TABLE `nodes` ADD longitude double NULL DEFAULT NULL'); | ||||||
|  |         await this.$executeQuery('ALTER TABLE `nodes` ADD latitude double NULL DEFAULT NULL'); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|     } catch (e) { |     } catch (e) { | ||||||
|       throw e; |       throw e; | ||||||
|     } |     } | ||||||
| @ -693,6 +704,16 @@ class DatabaseMigration { | |||||||
|     ) ENGINE=InnoDB DEFAULT CHARSET=utf8;`;
 |     ) ENGINE=InnoDB DEFAULT CHARSET=utf8;`;
 | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   private getCreateGeoNamesTableQuery(): string { | ||||||
|  |     return `CREATE TABLE geo_names (
 | ||||||
|  |       id int(11) unsigned NOT NULL, | ||||||
|  |       type enum('city','country','division','continent') NOT NULL, | ||||||
|  |       names text DEFAULT NULL, | ||||||
|  |       UNIQUE KEY id (id,type), | ||||||
|  |       KEY id_2 (id) | ||||||
|  |     ) ENGINE=InnoDB DEFAULT CHARSET=utf8;` | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   public async $truncateIndexedData(tables: string[]) { |   public async $truncateIndexedData(tables: string[]) { | ||||||
|     const allowedTables = ['blocks', 'hashrates', 'prices']; |     const allowedTables = ['blocks', 'hashrates', 'prices']; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -13,6 +13,17 @@ class NodesApi { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   public async $getAllNodes(): Promise<any> { | ||||||
|  |     try { | ||||||
|  |       const query = `SELECT * FROM nodes`; | ||||||
|  |       const [rows]: any = await DB.query(query); | ||||||
|  |       return rows; | ||||||
|  |     } catch (e) { | ||||||
|  |       logger.err('$getAllNodes error: ' + (e instanceof Error ? e.message : e)); | ||||||
|  |       throw e; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   public async $getNodeStats(public_key: string): Promise<any> { |   public async $getNodeStats(public_key: string): Promise<any> { | ||||||
|     try { |     try { | ||||||
|       const query = `SELECT UNIX_TIMESTAMP(added) AS added, capacity, channels FROM node_stats WHERE public_key = ? ORDER BY added DESC`; |       const query = `SELECT UNIX_TIMESTAMP(added) AS added, capacity, channels FROM node_stats WHERE public_key = ? ORDER BY added DESC`; | ||||||
|  | |||||||
| @ -98,6 +98,11 @@ interface IConfig { | |||||||
|     BISQ_URL: string; |     BISQ_URL: string; | ||||||
|     BISQ_ONION: string; |     BISQ_ONION: string; | ||||||
|   }; |   }; | ||||||
|  |   MAXMIND: { | ||||||
|  |     ENABLED: boolean; | ||||||
|  |     GEOLITE2_CITY: string; | ||||||
|  |     GEOLITE2_ASN: string; | ||||||
|  |   }, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const defaults: IConfig = { | const defaults: IConfig = { | ||||||
| @ -197,7 +202,12 @@ const defaults: IConfig = { | |||||||
|     'LIQUID_ONION': 'http://liquidmom47f6s3m53ebfxn47p76a6tlnxib3wp6deux7wuzotdr6cyd.onion/api/v1', |     'LIQUID_ONION': 'http://liquidmom47f6s3m53ebfxn47p76a6tlnxib3wp6deux7wuzotdr6cyd.onion/api/v1', | ||||||
|     'BISQ_URL': 'https://bisq.markets/api', |     'BISQ_URL': 'https://bisq.markets/api', | ||||||
|     'BISQ_ONION': 'http://bisqmktse2cabavbr2xjq7xw3h6g5ottemo5rolfcwt6aly6tp5fdryd.onion/api' |     'BISQ_ONION': 'http://bisqmktse2cabavbr2xjq7xw3h6g5ottemo5rolfcwt6aly6tp5fdryd.onion/api' | ||||||
|   } |   }, | ||||||
|  |   "MAXMIND": { | ||||||
|  |     'ENABLED': false, | ||||||
|  |     "GEOLITE2_CITY": "/usr/local/share/GeoIP/GeoLite2-City.mmdb", | ||||||
|  |     "GEOLITE2_ASN": "/usr/local/share/GeoIP/GeoLite2-ASN.mmdb" | ||||||
|  |   }, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class Config implements IConfig { | class Config implements IConfig { | ||||||
| @ -215,6 +225,7 @@ class Config implements IConfig { | |||||||
|   SOCKS5PROXY: IConfig['SOCKS5PROXY']; |   SOCKS5PROXY: IConfig['SOCKS5PROXY']; | ||||||
|   PRICE_DATA_SERVER: IConfig['PRICE_DATA_SERVER']; |   PRICE_DATA_SERVER: IConfig['PRICE_DATA_SERVER']; | ||||||
|   EXTERNAL_DATA_SERVER: IConfig['EXTERNAL_DATA_SERVER']; |   EXTERNAL_DATA_SERVER: IConfig['EXTERNAL_DATA_SERVER']; | ||||||
|  |   MAXMIND: IConfig['MAXMIND']; | ||||||
| 
 | 
 | ||||||
|   constructor() { |   constructor() { | ||||||
|     const configs = this.merge(configFile, defaults); |     const configs = this.merge(configFile, defaults); | ||||||
| @ -232,6 +243,7 @@ class Config implements IConfig { | |||||||
|     this.SOCKS5PROXY = configs.SOCKS5PROXY; |     this.SOCKS5PROXY = configs.SOCKS5PROXY; | ||||||
|     this.PRICE_DATA_SERVER = configs.PRICE_DATA_SERVER; |     this.PRICE_DATA_SERVER = configs.PRICE_DATA_SERVER; | ||||||
|     this.EXTERNAL_DATA_SERVER = configs.EXTERNAL_DATA_SERVER; |     this.EXTERNAL_DATA_SERVER = configs.EXTERNAL_DATA_SERVER; | ||||||
|  |     this.MAXMIND = configs.MAXMIND; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   merge = (...objects: object[]): IConfig => { |   merge = (...objects: object[]): IConfig => { | ||||||
|  | |||||||
| @ -73,6 +73,9 @@ class Logger { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   private getNetwork(): string { |   private getNetwork(): string { | ||||||
|  |     if (config.LIGHTNING.ENABLED) { | ||||||
|  |       return 'lightning'; | ||||||
|  |     } | ||||||
|     if (config.BISQ.ENABLED) { |     if (config.BISQ.ENABLED) { | ||||||
|       return 'bisq'; |       return 'bisq'; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -8,6 +8,7 @@ import config from '../../config'; | |||||||
| import { IEsploraApi } from '../../api/bitcoin/esplora-api.interface'; | import { IEsploraApi } from '../../api/bitcoin/esplora-api.interface'; | ||||||
| import lightningApi from '../../api/lightning/lightning-api-factory'; | import lightningApi from '../../api/lightning/lightning-api-factory'; | ||||||
| import { ILightningApi } from '../../api/lightning/lightning-api.interface'; | import { ILightningApi } from '../../api/lightning/lightning-api.interface'; | ||||||
|  | import { $lookupNodeLocation } from './sync-tasks/node-locations'; | ||||||
| 
 | 
 | ||||||
| class NodeSyncService { | class NodeSyncService { | ||||||
|   constructor() {} |   constructor() {} | ||||||
| @ -33,6 +34,10 @@ class NodeSyncService { | |||||||
|       } |       } | ||||||
|       logger.info(`Nodes updated.`); |       logger.info(`Nodes updated.`); | ||||||
| 
 | 
 | ||||||
|  |       if (config.MAXMIND.ENABLED) { | ||||||
|  |         await $lookupNodeLocation(); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|       await this.$setChannelsInactive(); |       await this.$setChannelsInactive(); | ||||||
| 
 | 
 | ||||||
|       for (const channel of networkGraph.channels) { |       for (const channel of networkGraph.channels) { | ||||||
|  | |||||||
| @ -206,7 +206,7 @@ class LightningStatsUpdater { | |||||||
|               torNodes++; |               torNodes++; | ||||||
|               isUnnanounced = false; |               isUnnanounced = false; | ||||||
|             } |             } | ||||||
|             const hasClearnet = [4, 6].includes(net.isIP(socket.split(':')[0])); |             const hasClearnet = [4, 6].includes(net.isIP(socket.substring(0, socket.lastIndexOf(':')))); | ||||||
|             if (hasClearnet) { |             if (hasClearnet) { | ||||||
|               clearnetNodes++; |               clearnetNodes++; | ||||||
|               isUnnanounced = false; |               isUnnanounced = false; | ||||||
|  | |||||||
							
								
								
									
										63
									
								
								backend/src/tasks/lightning/sync-tasks/node-locations.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								backend/src/tasks/lightning/sync-tasks/node-locations.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,63 @@ | |||||||
|  | import * as net from 'net'; | ||||||
|  | import maxmind, { CityResponse, AsnResponse } from 'maxmind'; | ||||||
|  | import nodesApi from '../../../api/explorer/nodes.api'; | ||||||
|  | import config from '../../../config'; | ||||||
|  | import DB from '../../../database'; | ||||||
|  | import logger from '../../../logger'; | ||||||
|  | 
 | ||||||
|  | export async function $lookupNodeLocation(): Promise<void> { | ||||||
|  |   logger.info(`Running node location updater using Maxmind...`); | ||||||
|  |   try { | ||||||
|  |     const nodes = await nodesApi.$getAllNodes(); | ||||||
|  |     const lookupCity = await maxmind.open<CityResponse>(config.MAXMIND.GEOLITE2_CITY); | ||||||
|  |     const lookupAsn = await maxmind.open<AsnResponse>(config.MAXMIND.GEOLITE2_ASN); | ||||||
|  | 
 | ||||||
|  |     for (const node of nodes) { | ||||||
|  |       const sockets: string[] = node.sockets.split(','); | ||||||
|  |       for (const socket of sockets) { | ||||||
|  |         const ip = socket.substring(0, socket.lastIndexOf(':')).replace('[', '').replace(']', ''); | ||||||
|  |         const hasClearnet = [4, 6].includes(net.isIP(ip)); | ||||||
|  |         if (hasClearnet && ip !== '127.0.1.1' && ip !== '127.0.0.1') { | ||||||
|  |           const city = lookupCity.get(ip); | ||||||
|  |           const asn = lookupAsn.get(ip); | ||||||
|  |           if (city && asn) { | ||||||
|  |             const query = `UPDATE nodes SET as_number = ?, city_id = ?, country_id = ?, subdivision_id = ?, longitude = ?, latitude = ?, accuracy_radius = ? WHERE public_key = ?`; | ||||||
|  |             const params = [asn.autonomous_system_number, city.city?.geoname_id, city.country?.geoname_id, city.subdivisions ? city.subdivisions[0].geoname_id : null, city.location?.longitude, city.location?.latitude, city.location?.accuracy_radius, node.public_key]; | ||||||
|  |             await DB.query(query, params); | ||||||
|  | 
 | ||||||
|  |              // Store Continent
 | ||||||
|  |              if (city.continent?.geoname_id) { | ||||||
|  |                await DB.query( | ||||||
|  |                 `INSERT IGNORE INTO geo_names (id, type, names) VALUES (?, 'continent', ?)`, | ||||||
|  |                 [city.continent?.geoname_id, JSON.stringify(city.continent?.names)]); | ||||||
|  |              } | ||||||
|  | 
 | ||||||
|  |              // Store Country
 | ||||||
|  |              if (city.country?.geoname_id) { | ||||||
|  |                await DB.query( | ||||||
|  |                 `INSERT IGNORE INTO geo_names (id, type, names) VALUES (?, 'country', ?)`, | ||||||
|  |                 [city.country?.geoname_id, JSON.stringify(city.country?.names)]); | ||||||
|  |              } | ||||||
|  | 
 | ||||||
|  |             // Store Division
 | ||||||
|  |             if (city.subdivisions && city.subdivisions[0]) { | ||||||
|  |               await DB.query( | ||||||
|  |                 `INSERT IGNORE INTO geo_names (id, type, names) VALUES (?, 'division', ?)`, | ||||||
|  |                 [city.subdivisions[0].geoname_id, JSON.stringify(city.subdivisions[0]?.names)]); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // Store City
 | ||||||
|  |             if (city.city?.geoname_id) { | ||||||
|  |               await DB.query( | ||||||
|  |                 `INSERT IGNORE INTO geo_names (id, type, names) VALUES (?, 'city', ?)`, | ||||||
|  |                 [city.city?.geoname_id, JSON.stringify(city.city?.names)]); | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     logger.info(`Node location data updated.`); | ||||||
|  |   } catch (e) { | ||||||
|  |     logger.err('$lookupNodeLocation() error: ' + (e instanceof Error ? e.message : e)); | ||||||
|  |   } | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user