From 17fc0ac6a955c22a007aa530acb44999ebd4571d Mon Sep 17 00:00:00 2001 From: TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com> Date: Tue, 26 Apr 2022 20:04:32 -0400 Subject: [PATCH 1/8] Docker Env Var Support - Add support for a variety of basic docker/docker-compose support --- docker-compose.example.yml | 14 +++++++++ server/src/services/config.js | 55 +++++++++++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/docker-compose.example.yml b/docker-compose.example.yml index 0193028dd..0cd6ab726 100644 --- a/docker-compose.example.yml +++ b/docker-compose.example.yml @@ -5,6 +5,20 @@ services: container_name: reactmap command: sh -c "yarn start" restart: unless-stopped + environment: + SCANNER_DB_HOST: 127.0.0.1 + SCANNER_DB_PORT: 3306 + SCANNER_DB_USER: scanner_username + SCANNER_DB_PASSWORD: scanner_user_pw + SCANNER_DB_NAME: realdevicemap + MANUAL_DB_HOST: 127.0.0.1 + MANUAL_DB_PORT: 3306 + MANUAL_DB_USER: manual_username + MANUAL_DB_PASSWORD: manual_user_pw + MANUAL_DB_NAME: manual_db + TITLE: ReactMap + START_LAT: 0 + START_LON: 0 volumes: - ./server/src/configs/areas.json:/home/node/server/src/configs/areas.json - ./server/src/configs/local.json:/home/node/server/src/configs/local.json diff --git a/server/src/services/config.js b/server/src/services/config.js index c95a6d9e0..d851acbbf 100644 --- a/server/src/services/config.js +++ b/server/src/services/config.js @@ -9,9 +9,60 @@ const config = require('config') // Check if new config exists if (!fs.existsSync(path.resolve(`${__dirname}/../configs/local.json`))) { - console.log('[CONFIG] Config v2 (local.json) not found, you need to run the migration with "yarn config-migrate"') - process.exit(1) + // Only process env variables if local.json doesn't exist + // Generally for quick docker setups + const { + SCANNER_DB_HOST, SCANNER_DB_PORT, SCANNER_DB_NAME, SCANNER_DB_USERNAME, SCANNER_DB_PASSWORD, + MANUAL_DB_HOST, MANUAL_DB_PORT, MANUAL_DB_NAME, MANUAL_DB_USERNAME, MANUAL_DB_PASSWORD, + TITLE, START_LAT, START_LON, + } = process.env + + if (SCANNER_DB_HOST && SCANNER_DB_PORT && SCANNER_DB_NAME && SCANNER_DB_USERNAME && SCANNER_DB_PASSWORD) { + config.database.schemas.push({ + host: SCANNER_DB_HOST, + port: +SCANNER_DB_PORT, + database: SCANNER_DB_NAME, + username: SCANNER_DB_USERNAME, + password: SCANNER_DB_PASSWORD, + useFor: [ + 'device', + 'gym', + 'pokemon', + 'pokestop', + 'scanCell', + 'spawnpoint', + 'weather', + ], + }) + } else { + throw new Error('Missing scanner database config! \nCheck to make sure you have SCANNER_DB_HOST,SCANNER_DB_PORT, SCANNER_DB_NAME, SCANNER_DB_USERNAME, and SCANNER_DB_PASSWORD') + } + if (MANUAL_DB_HOST && MANUAL_DB_PORT && MANUAL_DB_NAME && MANUAL_DB_USERNAME && MANUAL_DB_PASSWORD) { + config.database.schemas.push({ + host: MANUAL_DB_HOST, + port: +MANUAL_DB_PORT, + database: MANUAL_DB_NAME, + username: MANUAL_DB_USERNAME, + password: MANUAL_DB_PASSWORD, + useFor: [ + 'session', + 'user', + 'nest', + 'portal', + ], + }) + } else { + throw new Error('Missing manual database config! \nCheck to make sure you have MANUAL_DB_HOST,MANUAL_DB_PORT, MANUAL_DB_NAME, MANUAL_DB_USERNAME, and MANUAL_DB_PASSWORD') + } + if (!TITLE || !START_LAT || !START_LON) { + console.warn('Missing, TITLE, START_LAT, OR START_LON\nYou will be able to process but but these are recommended to add to your docker-compose file') + } + config.map.general.title = TITLE + config.map.general.headerTitle = TITLE + config.map.general.startLat = +START_LAT + config.map.general.startLon = +START_LON } + if (fs.existsSync(path.resolve(`${__dirname}/../configs/config.json`))) { console.log('[CONFIG] Config v1 (config.json) found, it is fine to leave it but make sure you are using and updating local.json instead.') } From 72d90939cd7a6fd1cabcaab58f57d28154e9a738 Mon Sep 17 00:00:00 2001 From: TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com> Date: Thu, 28 Apr 2022 21:47:08 -0400 Subject: [PATCH 2/8] Custom Env Vars - Add support for full set of config variables in docker-compose - Script to auto generate them + their types for proper parsing - Cleanup default.json --- .gitignore | 2 + docker-compose.example.yml | 7 +- package.json | 3 +- server/scripts/genEnvConfig.js | 46 + .../configs/custom-environment-variables.json | 1335 +++++++++++++++++ server/src/configs/default.json | 41 +- server/src/services/config.js | 19 +- 7 files changed, 1406 insertions(+), 47 deletions(-) create mode 100644 server/scripts/genEnvConfig.js create mode 100644 server/src/configs/custom-environment-variables.json diff --git a/.gitignore b/.gitignore index 6bc38b91e..141d33c2f 100644 --- a/.gitignore +++ b/.gitignore @@ -6,8 +6,10 @@ server/src/configs/* !server/src/configs/default.json !server/src/configs/areas.example.json !server/src/configs/local.example.json +!server/src/configs/custom-environment-variables.json .env + # Masterfile server/src/data/masterfile.json diff --git a/docker-compose.example.yml b/docker-compose.example.yml index 0cd6ab726..d84b214b2 100644 --- a/docker-compose.example.yml +++ b/docker-compose.example.yml @@ -16,9 +16,10 @@ services: MANUAL_DB_USER: manual_username MANUAL_DB_PASSWORD: manual_user_pw MANUAL_DB_NAME: manual_db - TITLE: ReactMap - START_LAT: 0 - START_LON: 0 + MAP_GENERAL_TITLE: ReactMap + MAP_GENERAL_START_LAT: 0 + MAP_GENERAL_START_LON: 0 + ARRAY_VALUE_EXAMPLE: "[3, 4, 5]" volumes: - ./server/src/configs/areas.json:/home/node/server/src/configs/areas.json - ./server/src/configs/local.json:/home/node/server/src/configs/local.json diff --git a/package.json b/package.json index 634d46006..83fca40ff 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "watch": "node esbuild.config.mjs --dev", "dev": "nodemon server/src/index.js --watch server", "generate": "node server/scripts/generateMasterfile.js", + "genEnvConfig": "node server/scripts/genEnvConfig.js", "create-locales": "node server/scripts/createLocales.js", "missing-locales": "node server/scripts/createLocales.js --missing", "create-area": "node server/scripts/poracleToGeoJSON.js", @@ -30,7 +31,6 @@ "devDependencies": { "@craftamap/esbuild-plugin-html": "^0.3.1", "@sentry/cli": "^1.73.0", - "dotenv": "^10.0.0", "esbuild": "^0.14.22", "esbuild-plugin-eslinter": "^0.1.2", "esbuild-plugin-mxn-copy": "^1.0.1", @@ -63,6 +63,7 @@ "compression": "^1.7.4", "config": "^3.3.6", "discord.js": "^12.5.3", + "dotenv": "^10.0.0", "express": "^4.17.1", "express-mysql-session": "^2.1.6", "express-rate-limit": "^5.2.6", diff --git a/server/scripts/genEnvConfig.js b/server/scripts/genEnvConfig.js new file mode 100644 index 000000000..96fd782b6 --- /dev/null +++ b/server/scripts/genEnvConfig.js @@ -0,0 +1,46 @@ +/* eslint-disable no-nested-ternary */ +/* eslint-disable no-console */ +const fs = require('fs') +const sourceConfig = require('../src/configs/default.json') + +const camelToSnake = str => str.replace(/([a-z](?=[A-Z]))/g, '$1_').toUpperCase() + +const recursiveObjCheck = (key, obj, parentKey = '') => { + const snakeKey = `${parentKey}${camelToSnake(key)}` + if (Array.isArray(obj)) { + return { __name: snakeKey, __format: 'json' } + } + if (typeof obj === 'object') { + return Object.fromEntries( + Object.entries(obj).map(([k, v]) => ( + [k, recursiveObjCheck(k, v, `${snakeKey}_`)] + )), + ) + } + return typeof obj === 'string' + ? snakeKey + : { __name: snakeKey, __format: typeof obj } +} + +const generateEnvConfig = async () => { + const envConfig = {} + + Object.entries(sourceConfig).forEach(([key, value]) => { + envConfig[key] = typeof value === 'object' + ? recursiveObjCheck(key, value) + : typeof value === 'string' + ? camelToSnake(key) + : { __name: camelToSnake(key), __format: typeof value } + }) + + fs.writeFileSync( + `${__dirname}/../src/configs/custom-environment-variables.json`, + JSON.stringify(envConfig, null, 2), + ) +} + +module.exports.generateEnvConfig = generateEnvConfig + +if (require.main === module) { + generateEnvConfig().then(() => console.log('Env Config Generated')) +} diff --git a/server/src/configs/custom-environment-variables.json b/server/src/configs/custom-environment-variables.json new file mode 100644 index 000000000..216bc8f84 --- /dev/null +++ b/server/src/configs/custom-environment-variables.json @@ -0,0 +1,1335 @@ +{ + "interface": "INTERFACE", + "port": { + "__name": "PORT", + "__format": "number" + }, + "packageSource": "PACKAGE_SOURCE", + "devOptions": { + "enabled": { + "__name": "DEV_OPTIONS_ENABLED", + "__format": "boolean" + }, + "graphiql": { + "__name": "DEV_OPTIONS_GRAPHIQL", + "__format": "boolean" + }, + "queryDebug": { + "__name": "DEV_OPTIONS_QUERY_DEBUG", + "__format": "boolean" + }, + "clientPath": "DEV_OPTIONS_CLIENT_PATH" + }, + "api": { + "sessionSecret": "API_SESSION_SECRET", + "reactMapSecret": "API_REACT_MAP_SECRET", + "maxSessions": { + "__name": "API_MAX_SESSIONS", + "__format": "number" + }, + "cookieAgeDays": { + "__name": "API_COOKIE_AGE_DAYS", + "__format": "number" + }, + "rateLimit": { + "time": { + "__name": "API_RATE_LIMIT_TIME", + "__format": "number" + }, + "requests": { + "__name": "API_RATE_LIMIT_REQUESTS", + "__format": "number" + } + }, + "queryUpdateHours": { + "pokemon": { + "__name": "API_QUERY_UPDATE_HOURS_POKEMON", + "__format": "number" + }, + "quests": { + "__name": "API_QUERY_UPDATE_HOURS_QUESTS", + "__format": "number" + }, + "raids": { + "__name": "API_QUERY_UPDATE_HOURS_RAIDS", + "__format": "number" + }, + "nests": { + "__name": "API_QUERY_UPDATE_HOURS_NESTS", + "__format": "number" + } + }, + "queryOnSessionInit": { + "pokemon": { + "__name": "API_QUERY_ON_SESSION_INIT_POKEMON", + "__format": "boolean" + }, + "quests": { + "__name": "API_QUERY_ON_SESSION_INIT_QUESTS", + "__format": "boolean" + }, + "raids": { + "__name": "API_QUERY_ON_SESSION_INIT_RAIDS", + "__format": "boolean" + }, + "nests": { + "__name": "API_QUERY_ON_SESSION_INIT_NESTS", + "__format": "boolean" + } + }, + "queryLimits": { + "pokemon": { + "__name": "API_QUERY_LIMITS_POKEMON", + "__format": "number" + }, + "pokemonPvp": { + "__name": "API_QUERY_LIMITS_POKEMON_PVP", + "__format": "number" + }, + "pokestops": { + "__name": "API_QUERY_LIMITS_POKESTOPS", + "__format": "number" + }, + "gyms": { + "__name": "API_QUERY_LIMITS_GYMS", + "__format": "number" + }, + "portals": { + "__name": "API_QUERY_LIMITS_PORTALS", + "__format": "number" + }, + "spawnpoints": { + "__name": "API_QUERY_LIMITS_SPAWNPOINTS", + "__format": "number" + }, + "nests": { + "__name": "API_QUERY_LIMITS_NESTS", + "__format": "number" + }, + "scanCells": { + "__name": "API_QUERY_LIMITS_SCAN_CELLS", + "__format": "number" + } + }, + "pvp": { + "leagues": { + "__name": "API_PVP_LEAGUES", + "__format": "json" + }, + "levels": { + "__name": "API_PVP_LEVELS", + "__format": "json" + }, + "reactMapHandlesPvp": { + "__name": "API_PVP_REACT_MAP_HANDLES_PVP", + "__format": "boolean" + }, + "minCp": { + "great": { + "__name": "API_PVP_MIN_CP_GREAT", + "__format": "number" + }, + "ultra": { + "__name": "API_PVP_MIN_CP_ULTRA", + "__format": "number" + } + } + }, + "portalUpdateLimit": { + "__name": "API_PORTAL_UPDATE_LIMIT", + "__format": "number" + }, + "weatherCellLimit": { + "__name": "API_WEATHER_CELL_LIMIT", + "__format": "number" + }, + "searchResultsLimit": { + "__name": "API_SEARCH_RESULTS_LIMIT", + "__format": "number" + }, + "nestHemisphere": "API_NEST_HEMISPHERE", + "gymValidDataLimit": { + "__name": "API_GYM_VALID_DATA_LIMIT", + "__format": "number" + }, + "hideOldGyms": { + "__name": "API_HIDE_OLD_GYMS", + "__format": "boolean" + }, + "stopValidDataLimit": { + "__name": "API_STOP_VALID_DATA_LIMIT", + "__format": "number" + }, + "hideOldPokestops": { + "__name": "API_HIDE_OLD_POKESTOPS", + "__format": "boolean" + } + }, + "multiDomains": { + "__name": "MULTI_DOMAINS", + "__format": "json" + }, + "map": { + "general": { + "title": "MAP_GENERAL_TITLE", + "headerTitle": "MAP_GENERAL_HEADER_TITLE", + "startLat": { + "__name": "MAP_GENERAL_START_LAT", + "__format": "number" + }, + "startLon": { + "__name": "MAP_GENERAL_START_LON", + "__format": "number" + }, + "startZoom": { + "__name": "MAP_GENERAL_START_ZOOM", + "__format": "number" + }, + "minZoom": { + "__name": "MAP_GENERAL_MIN_ZOOM", + "__format": "number" + }, + "maxZoom": { + "__name": "MAP_GENERAL_MAX_ZOOM", + "__format": "number" + }, + "interactionRangeZoom": { + "__name": "MAP_GENERAL_INTERACTION_RANGE_ZOOM", + "__format": "number" + }, + "scanAreasZoom": { + "__name": "MAP_GENERAL_SCAN_AREAS_ZOOM", + "__format": "number" + }, + "scanCellsZoom": { + "__name": "MAP_GENERAL_SCAN_CELLS_ZOOM", + "__format": "number" + }, + "submissionZoom": { + "__name": "MAP_GENERAL_SUBMISSION_ZOOM", + "__format": "number" + }, + "activeWeatherZoom": { + "__name": "MAP_GENERAL_ACTIVE_WEATHER_ZOOM", + "__format": "number" + }, + "geoJsonFileName": "MAP_GENERAL_GEO_JSON_FILE_NAME", + "attributionPrefix": "MAP_GENERAL_ATTRIBUTION_PREFIX" + }, + "localeSelection": { + "__name": "MAP_LOCALE_SELECTION", + "__format": "json" + }, + "customRoutes": { + "discordAuthUrl": "MAP_CUSTOM_ROUTES_DISCORD_AUTH_URL", + "telegramAuthUrl": "MAP_CUSTOM_ROUTES_TELEGRAM_AUTH_URL", + "telegramBotEnvRef": "MAP_CUSTOM_ROUTES_TELEGRAM_BOT_ENV_REF", + "localAuthUrl": "MAP_CUSTOM_ROUTES_LOCAL_AUTH_URL" + }, + "links": { + "discordInvite": "MAP_LINKS_DISCORD_INVITE", + "feedbackLink": "MAP_LINKS_FEEDBACK_LINK", + "statsLink": "MAP_LINKS_STATS_LINK", + "rolesLinkName": "MAP_LINKS_ROLES_LINK_NAME", + "rolesLink": "MAP_LINKS_ROLES_LINK" + }, + "holidayEffects": { + "christmasSnow": { + "__name": "MAP_HOLIDAY_EFFECTS_CHRISTMAS_SNOW", + "__format": "boolean" + }, + "newYearsFireworks": { + "__name": "MAP_HOLIDAY_EFFECTS_NEW_YEARS_FIREWORKS", + "__format": "boolean" + }, + "valentinesDay": { + "__name": "MAP_HOLIDAY_EFFECTS_VALENTINES_DAY", + "__format": "boolean" + }, + "internationalWomensDay": { + "__name": "MAP_HOLIDAY_EFFECTS_INTERNATIONAL_WOMENS_DAY", + "__format": "boolean" + } + }, + "misc": { + "enableMapJsFilter": { + "__name": "MAP_MISC_ENABLE_MAP_JS_FILTER", + "__format": "boolean" + }, + "questRewardTypeFilters": { + "__name": "MAP_MISC_QUEST_REWARD_TYPE_FILTERS", + "__format": "boolean" + }, + "fetchLatestInvasions": { + "__name": "MAP_MISC_FETCH_LATEST_INVASIONS", + "__format": "boolean" + }, + "invasionCacheHrs": { + "__name": "MAP_MISC_INVASION_CACHE_HRS", + "__format": "number" + }, + "masterfileCacheHrs": { + "__name": "MAP_MISC_MASTERFILE_CACHE_HRS", + "__format": "number" + }, + "webhookCacheHrs": { + "__name": "MAP_MISC_WEBHOOK_CACHE_HRS", + "__format": "number" + }, + "questMessage": "MAP_MISC_QUEST_MESSAGE", + "navigationControls": "MAP_MISC_NAVIGATION_CONTROLS", + "enableFloatingProfileButton": { + "__name": "MAP_MISC_ENABLE_FLOATING_PROFILE_BUTTON", + "__format": "boolean" + }, + "forceTutorial": { + "__name": "MAP_MISC_FORCE_TUTORIAL", + "__format": "boolean" + }, + "enableTutorial": { + "__name": "MAP_MISC_ENABLE_TUTORIAL", + "__format": "boolean" + }, + "enableUserProfile": { + "__name": "MAP_MISC_ENABLE_USER_PROFILE", + "__format": "boolean" + }, + "enableQuestSetSelector": { + "__name": "MAP_MISC_ENABLE_QUEST_SET_SELECTOR", + "__format": "boolean" + }, + "noScanAreaOverlay": { + "__name": "MAP_MISC_NO_SCAN_AREA_OVERLAY", + "__format": "boolean" + }, + "permImageDir": "MAP_MISC_PERM_IMAGE_DIR", + "permArrayImages": { + "__name": "MAP_MISC_PERM_ARRAY_IMAGES", + "__format": "boolean" + }, + "clientTimeoutMinutes": { + "__name": "MAP_MISC_CLIENT_TIMEOUT_MINUTES", + "__format": "number" + } + }, + "theme": { + "style": "MAP_THEME_STYLE", + "primary": "MAP_THEME_PRIMARY", + "secondary": "MAP_THEME_SECONDARY", + "drawer": "MAP_THEME_DRAWER" + }, + "clustering": { + "gyms": { + "zoomLevel": { + "__name": "MAP_CLUSTERING_GYMS_ZOOM_LEVEL", + "__format": "number" + }, + "forcedLimit": { + "__name": "MAP_CLUSTERING_GYMS_FORCED_LIMIT", + "__format": "number" + } + }, + "pokestops": { + "zoomLevel": { + "__name": "MAP_CLUSTERING_POKESTOPS_ZOOM_LEVEL", + "__format": "number" + }, + "forcedLimit": { + "__name": "MAP_CLUSTERING_POKESTOPS_FORCED_LIMIT", + "__format": "number" + } + }, + "pokemon": { + "zoomLevel": { + "__name": "MAP_CLUSTERING_POKEMON_ZOOM_LEVEL", + "__format": "number" + }, + "forcedLimit": { + "__name": "MAP_CLUSTERING_POKEMON_FORCED_LIMIT", + "__format": "number" + } + }, + "portals": { + "zoomLevel": { + "__name": "MAP_CLUSTERING_PORTALS_ZOOM_LEVEL", + "__format": "number" + }, + "forcedLimit": { + "__name": "MAP_CLUSTERING_PORTALS_FORCED_LIMIT", + "__format": "number" + } + }, + "spawnpoints": { + "zoomLevel": { + "__name": "MAP_CLUSTERING_SPAWNPOINTS_ZOOM_LEVEL", + "__format": "number" + }, + "forcedLimit": { + "__name": "MAP_CLUSTERING_SPAWNPOINTS_FORCED_LIMIT", + "__format": "number" + } + } + }, + "messageOfTheDay": { + "index": { + "__name": "MAP_MESSAGE_OF_THE_DAY_INDEX", + "__format": "number" + }, + "settings": { + "parentSpacing": { + "__name": "MAP_MESSAGE_OF_THE_DAY_SETTINGS_PARENT_SPACING", + "__format": "number" + }, + "parentAlignItems": "MAP_MESSAGE_OF_THE_DAY_SETTINGS_PARENT_ALIGN_ITEMS", + "parentJustifyContent": "MAP_MESSAGE_OF_THE_DAY_SETTINGS_PARENT_JUSTIFY_CONTENT", + "parentStyle": {}, + "permanent": { + "__name": "MAP_MESSAGE_OF_THE_DAY_SETTINGS_PERMANENT", + "__format": "boolean" + }, + "freeloaderOnly": { + "__name": "MAP_MESSAGE_OF_THE_DAY_SETTINGS_FREELOADER_ONLY", + "__format": "boolean" + }, + "donorOnly": { + "__name": "MAP_MESSAGE_OF_THE_DAY_SETTINGS_DONOR_ONLY", + "__format": "boolean" + } + }, + "titles": { + "__name": "MAP_MESSAGE_OF_THE_DAY_TITLES", + "__format": "json" + }, + "components": { + "__name": "MAP_MESSAGE_OF_THE_DAY_COMPONENTS", + "__format": "json" + }, + "footerButtons": { + "__name": "MAP_MESSAGE_OF_THE_DAY_FOOTER_BUTTONS", + "__format": "json" + } + }, + "donationPage": { + "showOnMap": { + "__name": "MAP_DONATION_PAGE_SHOW_ON_MAP", + "__format": "boolean" + }, + "showToDonors": { + "__name": "MAP_DONATION_PAGE_SHOW_TO_DONORS", + "__format": "boolean" + }, + "fabIcon": "MAP_DONATION_PAGE_FAB_ICON", + "settings": { + "parentSpacing": { + "__name": "MAP_DONATION_PAGE_SETTINGS_PARENT_SPACING", + "__format": "number" + }, + "parentAlignItems": "MAP_DONATION_PAGE_SETTINGS_PARENT_ALIGN_ITEMS", + "parentJustifyContent": "MAP_DONATION_PAGE_SETTINGS_PARENT_JUSTIFY_CONTENT", + "parentStyle": {} + }, + "titles": { + "__name": "MAP_DONATION_PAGE_TITLES", + "__format": "json" + }, + "components": { + "__name": "MAP_DONATION_PAGE_COMPONENTS", + "__format": "json" + }, + "footerButtons": { + "__name": "MAP_DONATION_PAGE_FOOTER_BUTTONS", + "__format": "json" + } + }, + "loginPage": { + "settings": { + "parentSpacing": { + "__name": "MAP_LOGIN_PAGE_SETTINGS_PARENT_SPACING", + "__format": "number" + }, + "parentAlignItems": "MAP_LOGIN_PAGE_SETTINGS_PARENT_ALIGN_ITEMS", + "parentJustifyContent": "MAP_LOGIN_PAGE_SETTINGS_PARENT_JUSTIFY_CONTENT", + "parentStyle": {} + }, + "components": { + "__name": "MAP_LOGIN_PAGE_COMPONENTS", + "__format": "json" + } + } + }, + "clientSideOptions": { + "admin": { + "devicePathColor": "CLIENT_SIDE_OPTIONS_ADMIN_DEVICE_PATH_COLOR" + }, + "gyms": { + "clustering": { + "__name": "CLIENT_SIDE_OPTIONS_GYMS_CLUSTERING", + "__format": "boolean" + }, + "raidTimers": { + "__name": "CLIENT_SIDE_OPTIONS_GYMS_RAID_TIMERS", + "__format": "boolean" + }, + "interactionRanges": { + "__name": "CLIENT_SIDE_OPTIONS_GYMS_INTERACTION_RANGES", + "__format": "boolean" + }, + "showExBadge": { + "__name": "CLIENT_SIDE_OPTIONS_GYMS_SHOW_EX_BADGE", + "__format": "boolean" + }, + "showArBadge": { + "__name": "CLIENT_SIDE_OPTIONS_GYMS_SHOW_AR_BADGE", + "__format": "boolean" + }, + "raidLevelBadges": { + "__name": "CLIENT_SIDE_OPTIONS_GYMS_RAID_LEVEL_BADGES", + "__format": "boolean" + }, + "gymBadgeDiamonds": { + "__name": "CLIENT_SIDE_OPTIONS_GYMS_GYM_BADGE_DIAMONDS", + "__format": "boolean" + } + }, + "pokestops": { + "clustering": { + "__name": "CLIENT_SIDE_OPTIONS_POKESTOPS_CLUSTERING", + "__format": "boolean" + }, + "invasionTimers": { + "__name": "CLIENT_SIDE_OPTIONS_POKESTOPS_INVASION_TIMERS", + "__format": "boolean" + }, + "lureTimers": { + "__name": "CLIENT_SIDE_OPTIONS_POKESTOPS_LURE_TIMERS", + "__format": "boolean" + }, + "interactionRanges": { + "__name": "CLIENT_SIDE_OPTIONS_POKESTOPS_INTERACTION_RANGES", + "__format": "boolean" + }, + "madQuestText": { + "__name": "CLIENT_SIDE_OPTIONS_POKESTOPS_MAD_QUEST_TEXT", + "__format": "boolean" + }, + "hasQuestIndicator": { + "__name": "CLIENT_SIDE_OPTIONS_POKESTOPS_HAS_QUEST_INDICATOR", + "__format": "boolean" + }, + "showArBadge": { + "__name": "CLIENT_SIDE_OPTIONS_POKESTOPS_SHOW_AR_BADGE", + "__format": "boolean" + } + }, + "pokemon": { + "clustering": { + "__name": "CLIENT_SIDE_OPTIONS_POKEMON_CLUSTERING", + "__format": "boolean" + }, + "pokemonTimers": { + "__name": "CLIENT_SIDE_OPTIONS_POKEMON_POKEMON_TIMERS", + "__format": "boolean" + }, + "legacyFilter": { + "__name": "CLIENT_SIDE_OPTIONS_POKEMON_LEGACY_FILTER", + "__format": "boolean" + }, + "ivCircles": { + "__name": "CLIENT_SIDE_OPTIONS_POKEMON_IV_CIRCLES", + "__format": "boolean" + }, + "minIvCircle": { + "__name": "CLIENT_SIDE_OPTIONS_POKEMON_MIN_IV_CIRCLE", + "__format": "number" + }, + "weatherIndicator": { + "__name": "CLIENT_SIDE_OPTIONS_POKEMON_WEATHER_INDICATOR", + "__format": "boolean" + }, + "interactionRanges": { + "__name": "CLIENT_SIDE_OPTIONS_POKEMON_INTERACTION_RANGES", + "__format": "boolean" + }, + "showDexNumInPopup": { + "__name": "CLIENT_SIDE_OPTIONS_POKEMON_SHOW_DEX_NUM_IN_POPUP", + "__format": "boolean" + }, + "pvpMega": { + "__name": "CLIENT_SIDE_OPTIONS_POKEMON_PVP_MEGA", + "__format": "boolean" + }, + "linkGlobalAndAdvanced": { + "__name": "CLIENT_SIDE_OPTIONS_POKEMON_LINK_GLOBAL_AND_ADVANCED", + "__format": "boolean" + }, + "glow": { + "__name": "CLIENT_SIDE_OPTIONS_POKEMON_GLOW", + "__format": "json" + } + }, + "wayfarer": { + "clustering": { + "__name": "CLIENT_SIDE_OPTIONS_WAYFARER_CLUSTERING", + "__format": "boolean" + }, + "oldPortals": "CLIENT_SIDE_OPTIONS_WAYFARER_OLD_PORTALS", + "newPortals": "CLIENT_SIDE_OPTIONS_WAYFARER_NEW_PORTALS" + }, + "weather": { + "clickableIcon": { + "__name": "CLIENT_SIDE_OPTIONS_WEATHER_CLICKABLE_ICON", + "__format": "boolean" + } + } + }, + "defaultFilters": { + "devices": { + "enabled": { + "__name": "DEFAULT_FILTERS_DEVICES_ENABLED", + "__format": "boolean" + } + }, + "gyms": { + "enabled": { + "__name": "DEFAULT_FILTERS_GYMS_ENABLED", + "__format": "boolean" + }, + "allGyms": { + "__name": "DEFAULT_FILTERS_GYMS_ALL_GYMS", + "__format": "boolean" + }, + "exEligible": { + "__name": "DEFAULT_FILTERS_GYMS_EX_ELIGIBLE", + "__format": "boolean" + }, + "inBattle": { + "__name": "DEFAULT_FILTERS_GYMS_IN_BATTLE", + "__format": "boolean" + }, + "raids": { + "__name": "DEFAULT_FILTERS_GYMS_RAIDS", + "__format": "boolean" + }, + "eggs": { + "__name": "DEFAULT_FILTERS_GYMS_EGGS", + "__format": "boolean" + }, + "pokemon": { + "__name": "DEFAULT_FILTERS_GYMS_POKEMON", + "__format": "boolean" + }, + "gymBadges": { + "__name": "DEFAULT_FILTERS_GYMS_GYM_BADGES", + "__format": "boolean" + } + }, + "nests": { + "enabled": { + "__name": "DEFAULT_FILTERS_NESTS_ENABLED", + "__format": "boolean" + }, + "polygons": { + "__name": "DEFAULT_FILTERS_NESTS_POLYGONS", + "__format": "boolean" + }, + "pokemon": { + "__name": "DEFAULT_FILTERS_NESTS_POKEMON", + "__format": "boolean" + }, + "allPokemon": { + "__name": "DEFAULT_FILTERS_NESTS_ALL_POKEMON", + "__format": "boolean" + }, + "avgFilter": { + "__name": "DEFAULT_FILTERS_NESTS_AVG_FILTER", + "__format": "json" + }, + "avgSliderStep": { + "__name": "DEFAULT_FILTERS_NESTS_AVG_SLIDER_STEP", + "__format": "number" + } + }, + "pokestops": { + "enabled": { + "__name": "DEFAULT_FILTERS_POKESTOPS_ENABLED", + "__format": "boolean" + }, + "lures": { + "__name": "DEFAULT_FILTERS_POKESTOPS_LURES", + "__format": "boolean" + }, + "quests": { + "__name": "DEFAULT_FILTERS_POKESTOPS_QUESTS", + "__format": "boolean" + }, + "questSet": "DEFAULT_FILTERS_POKESTOPS_QUEST_SET", + "items": { + "__name": "DEFAULT_FILTERS_POKESTOPS_ITEMS", + "__format": "boolean" + }, + "megaEnergy": { + "__name": "DEFAULT_FILTERS_POKESTOPS_MEGA_ENERGY", + "__format": "boolean" + }, + "candy": { + "__name": "DEFAULT_FILTERS_POKESTOPS_CANDY", + "__format": "boolean" + }, + "pokemon": { + "__name": "DEFAULT_FILTERS_POKESTOPS_POKEMON", + "__format": "boolean" + }, + "invasions": { + "__name": "DEFAULT_FILTERS_POKESTOPS_INVASIONS", + "__format": "boolean" + }, + "allInvasions": { + "__name": "DEFAULT_FILTERS_POKESTOPS_ALL_INVASIONS", + "__format": "boolean" + } + }, + "pokemon": { + "enabled": { + "__name": "DEFAULT_FILTERS_POKEMON_ENABLED", + "__format": "boolean" + }, + "legacyFilter": { + "__name": "DEFAULT_FILTERS_POKEMON_LEGACY_FILTER", + "__format": "boolean" + }, + "allPokemon": { + "__name": "DEFAULT_FILTERS_POKEMON_ALL_POKEMON", + "__format": "boolean" + }, + "globalValues": { + "iv": { + "__name": "DEFAULT_FILTERS_POKEMON_GLOBAL_VALUES_IV", + "__format": "json" + }, + "level": { + "__name": "DEFAULT_FILTERS_POKEMON_GLOBAL_VALUES_LEVEL", + "__format": "json" + }, + "atk_iv": { + "__name": "DEFAULT_FILTERS_POKEMON_GLOBAL_VALUES_ATK_IV", + "__format": "json" + }, + "def_iv": { + "__name": "DEFAULT_FILTERS_POKEMON_GLOBAL_VALUES_DEF_IV", + "__format": "json" + }, + "sta_iv": { + "__name": "DEFAULT_FILTERS_POKEMON_GLOBAL_VALUES_STA_IV", + "__format": "json" + }, + "pvp": { + "__name": "DEFAULT_FILTERS_POKEMON_GLOBAL_VALUES_PVP", + "__format": "json" + } + } + }, + "portals": { + "enabled": { + "__name": "DEFAULT_FILTERS_PORTALS_ENABLED", + "__format": "boolean" + } + }, + "scanAreas": { + "enabled": { + "__name": "DEFAULT_FILTERS_SCAN_AREAS_ENABLED", + "__format": "boolean" + } + }, + "scanCells": { + "enabled": { + "__name": "DEFAULT_FILTERS_SCAN_CELLS_ENABLED", + "__format": "boolean" + } + }, + "spawnpoints": { + "enabled": { + "__name": "DEFAULT_FILTERS_SPAWNPOINTS_ENABLED", + "__format": "boolean" + } + }, + "submissionCells": { + "enabled": { + "__name": "DEFAULT_FILTERS_SUBMISSION_CELLS_ENABLED", + "__format": "boolean" + } + }, + "weather": { + "enabled": { + "__name": "DEFAULT_FILTERS_WEATHER_ENABLED", + "__format": "boolean" + } + } + }, + "database": { + "settings": { + "userTableName": "DATABASE_SETTINGS_USER_TABLE_NAME", + "gymBadgeTableName": "DATABASE_SETTINGS_GYM_BADGE_TABLE_NAME", + "sessionTableName": "DATABASE_SETTINGS_SESSION_TABLE_NAME", + "migrationTableName": "DATABASE_SETTINGS_MIGRATION_TABLE_NAME", + "joinGymBadgeTable": { + "__name": "DATABASE_SETTINGS_JOIN_GYM_BADGE_TABLE", + "__format": "boolean" + }, + "hideOldQuests": { + "__name": "DATABASE_SETTINGS_HIDE_OLD_QUESTS", + "__format": "boolean" + }, + "maxConnections": { + "__name": "DATABASE_SETTINGS_MAX_CONNECTIONS", + "__format": "number" + }, + "startupDelayMs": { + "__name": "DATABASE_SETTINGS_STARTUP_DELAY_MS", + "__format": "number" + }, + "availableRetryCount": { + "__name": "DATABASE_SETTINGS_AVAILABLE_RETRY_COUNT", + "__format": "number" + } + }, + "schemas": { + "__name": "DATABASE_SCHEMAS", + "__format": "json" + } + }, + "scanner": { + "backendConfig": { + "platform": "SCANNER_BACKEND_CONFIG_PLATFORM", + "apiEndpoint": "SCANNER_BACKEND_CONFIG_API_ENDPOINT", + "apiUsername": "SCANNER_BACKEND_CONFIG_API_USERNAME", + "apiPassword": "SCANNER_BACKEND_CONFIG_API_PASSWORD", + "queueRefreshInterval": { + "__name": "SCANNER_BACKEND_CONFIG_QUEUE_REFRESH_INTERVAL", + "__format": "number" + } + }, + "scanNext": { + "enabled": { + "__name": "SCANNER_SCAN_NEXT_ENABLED", + "__format": "boolean" + }, + "showScanCount": { + "__name": "SCANNER_SCAN_NEXT_SHOW_SCAN_COUNT", + "__format": "boolean" + }, + "showScanQueue": { + "__name": "SCANNER_SCAN_NEXT_SHOW_SCAN_QUEUE", + "__format": "boolean" + }, + "scanNextInstance": "SCANNER_SCAN_NEXT_SCAN_NEXT_INSTANCE", + "scanNextDevice": "SCANNER_SCAN_NEXT_SCAN_NEXT_DEVICE", + "scanNextSleeptime": { + "__name": "SCANNER_SCAN_NEXT_SCAN_NEXT_SLEEPTIME", + "__format": "number" + }, + "scanNextAreaRestriction": { + "__name": "SCANNER_SCAN_NEXT_SCAN_NEXT_AREA_RESTRICTION", + "__format": "json" + }, + "discordRoles": { + "__name": "SCANNER_SCAN_NEXT_DISCORD_ROLES", + "__format": "json" + }, + "telegramGroups": { + "__name": "SCANNER_SCAN_NEXT_TELEGRAM_GROUPS", + "__format": "json" + } + }, + "scanZone": { + "enabled": { + "__name": "SCANNER_SCAN_ZONE_ENABLED", + "__format": "boolean" + }, + "showScanCount": { + "__name": "SCANNER_SCAN_ZONE_SHOW_SCAN_COUNT", + "__format": "boolean" + }, + "showScanQueue": { + "__name": "SCANNER_SCAN_ZONE_SHOW_SCAN_QUEUE", + "__format": "boolean" + }, + "scanZoneMaxSize": { + "__name": "SCANNER_SCAN_ZONE_SCAN_ZONE_MAX_SIZE", + "__format": "number" + }, + "advancedScanZoneOptions": { + "__name": "SCANNER_SCAN_ZONE_ADVANCED_SCAN_ZONE_OPTIONS", + "__format": "boolean" + }, + "scanZoneRadius": { + "pokemon": { + "__name": "SCANNER_SCAN_ZONE_SCAN_ZONE_RADIUS_POKEMON", + "__format": "number" + }, + "gym": { + "__name": "SCANNER_SCAN_ZONE_SCAN_ZONE_RADIUS_GYM", + "__format": "number" + } + }, + "scanZoneSpacing": { + "__name": "SCANNER_SCAN_ZONE_SCAN_ZONE_SPACING", + "__format": "number" + }, + "scanZoneInstance": "SCANNER_SCAN_ZONE_SCAN_ZONE_INSTANCE", + "scanZoneAreaRestriction": { + "__name": "SCANNER_SCAN_ZONE_SCAN_ZONE_AREA_RESTRICTION", + "__format": "json" + }, + "discordRoles": { + "__name": "SCANNER_SCAN_ZONE_DISCORD_ROLES", + "__format": "json" + }, + "telegramGroups": { + "__name": "SCANNER_SCAN_ZONE_TELEGRAM_GROUPS", + "__format": "json" + } + } + }, + "webhooks": { + "__name": "WEBHOOKS", + "__format": "json" + }, + "authentication": { + "strategies": { + "__name": "AUTHENTICATION_STRATEGIES", + "__format": "json" + }, + "areaRestrictions": { + "__name": "AUTHENTICATION_AREA_RESTRICTIONS", + "__format": "json" + }, + "excludeFromTutorial": { + "__name": "AUTHENTICATION_EXCLUDE_FROM_TUTORIAL", + "__format": "json" + }, + "alwaysEnabledPerms": { + "__name": "AUTHENTICATION_ALWAYS_ENABLED_PERMS", + "__format": "json" + }, + "perms": { + "map": { + "enabled": { + "__name": "AUTHENTICATION_PERMS_MAP_ENABLED", + "__format": "boolean" + }, + "roles": { + "__name": "AUTHENTICATION_PERMS_MAP_ROLES", + "__format": "json" + } + }, + "pokemon": { + "enabled": { + "__name": "AUTHENTICATION_PERMS_POKEMON_ENABLED", + "__format": "boolean" + }, + "roles": { + "__name": "AUTHENTICATION_PERMS_POKEMON_ROLES", + "__format": "json" + } + }, + "iv": { + "enabled": { + "__name": "AUTHENTICATION_PERMS_IV_ENABLED", + "__format": "boolean" + }, + "roles": { + "__name": "AUTHENTICATION_PERMS_IV_ROLES", + "__format": "json" + } + }, + "pvp": { + "enabled": { + "__name": "AUTHENTICATION_PERMS_PVP_ENABLED", + "__format": "boolean" + }, + "roles": { + "__name": "AUTHENTICATION_PERMS_PVP_ROLES", + "__format": "json" + } + }, + "gyms": { + "enabled": { + "__name": "AUTHENTICATION_PERMS_GYMS_ENABLED", + "__format": "boolean" + }, + "roles": { + "__name": "AUTHENTICATION_PERMS_GYMS_ROLES", + "__format": "json" + } + }, + "raids": { + "enabled": { + "__name": "AUTHENTICATION_PERMS_RAIDS_ENABLED", + "__format": "boolean" + }, + "roles": { + "__name": "AUTHENTICATION_PERMS_RAIDS_ROLES", + "__format": "json" + } + }, + "pokestops": { + "enabled": { + "__name": "AUTHENTICATION_PERMS_POKESTOPS_ENABLED", + "__format": "boolean" + }, + "roles": { + "__name": "AUTHENTICATION_PERMS_POKESTOPS_ROLES", + "__format": "json" + } + }, + "quests": { + "enabled": { + "__name": "AUTHENTICATION_PERMS_QUESTS_ENABLED", + "__format": "boolean" + }, + "roles": { + "__name": "AUTHENTICATION_PERMS_QUESTS_ROLES", + "__format": "json" + } + }, + "lures": { + "enabled": { + "__name": "AUTHENTICATION_PERMS_LURES_ENABLED", + "__format": "boolean" + }, + "roles": { + "__name": "AUTHENTICATION_PERMS_LURES_ROLES", + "__format": "json" + } + }, + "portals": { + "enabled": { + "__name": "AUTHENTICATION_PERMS_PORTALS_ENABLED", + "__format": "boolean" + }, + "roles": { + "__name": "AUTHENTICATION_PERMS_PORTALS_ROLES", + "__format": "json" + } + }, + "submissionCells": { + "enabled": { + "__name": "AUTHENTICATION_PERMS_SUBMISSION_CELLS_ENABLED", + "__format": "boolean" + }, + "roles": { + "__name": "AUTHENTICATION_PERMS_SUBMISSION_CELLS_ROLES", + "__format": "json" + } + }, + "invasions": { + "enabled": { + "__name": "AUTHENTICATION_PERMS_INVASIONS_ENABLED", + "__format": "boolean" + }, + "roles": { + "__name": "AUTHENTICATION_PERMS_INVASIONS_ROLES", + "__format": "json" + } + }, + "nests": { + "enabled": { + "__name": "AUTHENTICATION_PERMS_NESTS_ENABLED", + "__format": "boolean" + }, + "roles": { + "__name": "AUTHENTICATION_PERMS_NESTS_ROLES", + "__format": "json" + } + }, + "scanAreas": { + "enabled": { + "__name": "AUTHENTICATION_PERMS_SCAN_AREAS_ENABLED", + "__format": "boolean" + }, + "roles": { + "__name": "AUTHENTICATION_PERMS_SCAN_AREAS_ROLES", + "__format": "json" + } + }, + "weather": { + "enabled": { + "__name": "AUTHENTICATION_PERMS_WEATHER_ENABLED", + "__format": "boolean" + }, + "roles": { + "__name": "AUTHENTICATION_PERMS_WEATHER_ROLES", + "__format": "json" + } + }, + "spawnpoints": { + "enabled": { + "__name": "AUTHENTICATION_PERMS_SPAWNPOINTS_ENABLED", + "__format": "boolean" + }, + "roles": { + "__name": "AUTHENTICATION_PERMS_SPAWNPOINTS_ROLES", + "__format": "json" + } + }, + "scanCells": { + "enabled": { + "__name": "AUTHENTICATION_PERMS_SCAN_CELLS_ENABLED", + "__format": "boolean" + }, + "roles": { + "__name": "AUTHENTICATION_PERMS_SCAN_CELLS_ROLES", + "__format": "json" + } + }, + "devices": { + "enabled": { + "__name": "AUTHENTICATION_PERMS_DEVICES_ENABLED", + "__format": "boolean" + }, + "roles": { + "__name": "AUTHENTICATION_PERMS_DEVICES_ROLES", + "__format": "json" + } + }, + "donor": { + "enabled": { + "__name": "AUTHENTICATION_PERMS_DONOR_ENABLED", + "__format": "boolean" + }, + "roles": { + "__name": "AUTHENTICATION_PERMS_DONOR_ROLES", + "__format": "json" + } + }, + "gymBadges": { + "enabled": { + "__name": "AUTHENTICATION_PERMS_GYM_BADGES_ENABLED", + "__format": "boolean" + }, + "roles": { + "__name": "AUTHENTICATION_PERMS_GYM_BADGES_ROLES", + "__format": "json" + } + } + } + }, + "tileServers": { + "__name": "TILE_SERVERS", + "__format": "json" + }, + "navigation": { + "__name": "NAVIGATION", + "__format": "json" + }, + "icons": { + "Read_More_Here": "ICONS_READ_MORE_HERE", + "customizable": { + "__name": "ICONS_CUSTOMIZABLE", + "__format": "json" + }, + "styles": { + "__name": "ICONS_STYLES", + "__format": "json" + }, + "defaultIcons": {}, + "cacheHrs": { + "__name": "ICONS_CACHE_HRS", + "__format": "number" + }, + "sizes": { + "device": { + "sm": { + "__name": "ICONS_SIZES_DEVICE_SM", + "__format": "number" + }, + "md": { + "__name": "ICONS_SIZES_DEVICE_MD", + "__format": "number" + }, + "lg": { + "__name": "ICONS_SIZES_DEVICE_LG", + "__format": "number" + }, + "xl": { + "__name": "ICONS_SIZES_DEVICE_XL", + "__format": "number" + } + }, + "nest": { + "sm": { + "__name": "ICONS_SIZES_NEST_SM", + "__format": "number" + }, + "md": { + "__name": "ICONS_SIZES_NEST_MD", + "__format": "number" + }, + "lg": { + "__name": "ICONS_SIZES_NEST_LG", + "__format": "number" + }, + "xl": { + "__name": "ICONS_SIZES_NEST_XL", + "__format": "number" + } + }, + "gym": { + "sm": { + "__name": "ICONS_SIZES_GYM_SM", + "__format": "number" + }, + "md": { + "__name": "ICONS_SIZES_GYM_MD", + "__format": "number" + }, + "lg": { + "__name": "ICONS_SIZES_GYM_LG", + "__format": "number" + }, + "xl": { + "__name": "ICONS_SIZES_GYM_XL", + "__format": "number" + } + }, + "raid": { + "sm": { + "__name": "ICONS_SIZES_RAID_SM", + "__format": "number" + }, + "md": { + "__name": "ICONS_SIZES_RAID_MD", + "__format": "number" + }, + "lg": { + "__name": "ICONS_SIZES_RAID_LG", + "__format": "number" + }, + "xl": { + "__name": "ICONS_SIZES_RAID_XL", + "__format": "number" + } + }, + "pokestop": { + "sm": { + "__name": "ICONS_SIZES_POKESTOP_SM", + "__format": "number" + }, + "md": { + "__name": "ICONS_SIZES_POKESTOP_MD", + "__format": "number" + }, + "lg": { + "__name": "ICONS_SIZES_POKESTOP_LG", + "__format": "number" + }, + "xl": { + "__name": "ICONS_SIZES_POKESTOP_XL", + "__format": "number" + } + }, + "invasion": { + "sm": { + "__name": "ICONS_SIZES_INVASION_SM", + "__format": "number" + }, + "md": { + "__name": "ICONS_SIZES_INVASION_MD", + "__format": "number" + }, + "lg": { + "__name": "ICONS_SIZES_INVASION_LG", + "__format": "number" + }, + "xl": { + "__name": "ICONS_SIZES_INVASION_XL", + "__format": "number" + } + }, + "reward": { + "sm": { + "__name": "ICONS_SIZES_REWARD_SM", + "__format": "number" + }, + "md": { + "__name": "ICONS_SIZES_REWARD_MD", + "__format": "number" + }, + "lg": { + "__name": "ICONS_SIZES_REWARD_LG", + "__format": "number" + }, + "xl": { + "__name": "ICONS_SIZES_REWARD_XL", + "__format": "number" + } + }, + "pokemon": { + "sm": { + "__name": "ICONS_SIZES_POKEMON_SM", + "__format": "number" + }, + "md": { + "__name": "ICONS_SIZES_POKEMON_MD", + "__format": "number" + }, + "lg": { + "__name": "ICONS_SIZES_POKEMON_LG", + "__format": "number" + }, + "xl": { + "__name": "ICONS_SIZES_POKEMON_XL", + "__format": "number" + } + }, + "spawnpoint": { + "sm": { + "__name": "ICONS_SIZES_SPAWNPOINT_SM", + "__format": "number" + }, + "md": { + "__name": "ICONS_SIZES_SPAWNPOINT_MD", + "__format": "number" + }, + "lg": { + "__name": "ICONS_SIZES_SPAWNPOINT_LG", + "__format": "number" + }, + "xl": { + "__name": "ICONS_SIZES_SPAWNPOINT_XL", + "__format": "number" + } + } + } + }, + "rarity": { + "common": { + "__name": "RARITY_COMMON", + "__format": "json" + }, + "uncommon": { + "__name": "RARITY_UNCOMMON", + "__format": "json" + }, + "rare": { + "__name": "RARITY_RARE", + "__format": "json" + }, + "ultraRare": { + "__name": "RARITY_ULTRA_RARE", + "__format": "json" + }, + "regional": { + "__name": "RARITY_REGIONAL", + "__format": "json" + }, + "event": { + "__name": "RARITY_EVENT", + "__format": "json" + } + }, + "manualAreas": { + "__name": "MANUAL_AREAS", + "__format": "json" + } +} \ No newline at end of file diff --git a/server/src/configs/default.json b/server/src/configs/default.json index eeb09204a..f0d2b1e06 100644 --- a/server/src/configs/default.json +++ b/server/src/configs/default.json @@ -283,7 +283,10 @@ "polygons": false, "pokemon": false, "allPokemon": true, - "avgFilter": [0, 100], + "avgFilter": [ + 0, + 100 + ], "avgSliderStep": 1 }, "pokestops": { @@ -360,24 +363,7 @@ "startupDelayMs": 1000, "availableRetryCount": 5 }, - "schemas": [ - { - "host": "127.0.0.1", - "port": 3306, - "username": "user", - "password": "pass123!", - "database": "rdmdb", - "useFor": [] - }, - { - "host": "127.0.0.1", - "port": 3306, - "username": "user", - "password": "pass123!", - "database": "manualdb", - "useFor": [] - } - ] + "schemas": [] }, "scanner": { "backendConfig": { @@ -404,7 +390,10 @@ "showScanQueue": false, "scanZoneMaxSize": 10, "advancedScanZoneOptions": false, - "scanZoneRadius": { "pokemon": 70, "gym": 750 }, + "scanZoneRadius": { + "pokemon": 70, + "gym": 750 + }, "scanZoneSpacing": 1, "scanZoneInstance": "scanZone", "scanZoneAreaRestriction": [], @@ -556,18 +545,6 @@ "attribution": "© Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community", "url": "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}", "style": "dark" - }, - { - "name": "AlidadeSmoothDark", - "attribution": "© Stadia Maps, © OpenMapTiles © OpenStreetMap contributors", - "url": "https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.png", - "style": "dark" - }, - { - "name": "ThunderForest", - "attribution": "© Thunderforest, © OpenStreetMap contributors", - "url": "https://{s}.tile.thunderforest.com/transport-dark/{z}/{x}/{y}.png", - "style": "dark" } ], "navigation": [ diff --git a/server/src/services/config.js b/server/src/services/config.js index d851acbbf..f66e6309b 100644 --- a/server/src/services/config.js +++ b/server/src/services/config.js @@ -5,16 +5,18 @@ process.env.NODE_CONFIG_DIR = `${__dirname}/../configs` const fs = require('fs') const path = require('path') +const dotenv = require('dotenv') + +dotenv.config() + const config = require('config') -// Check if new config exists if (!fs.existsSync(path.resolve(`${__dirname}/../configs/local.json`))) { - // Only process env variables if local.json doesn't exist - // Generally for quick docker setups + // add database env variables from .env or docker-compose const { SCANNER_DB_HOST, SCANNER_DB_PORT, SCANNER_DB_NAME, SCANNER_DB_USERNAME, SCANNER_DB_PASSWORD, MANUAL_DB_HOST, MANUAL_DB_PORT, MANUAL_DB_NAME, MANUAL_DB_USERNAME, MANUAL_DB_PASSWORD, - TITLE, START_LAT, START_LON, + MAP_GENERAL_START_LAT, MAP_GENERAL_START_LON, } = process.env if (SCANNER_DB_HOST && SCANNER_DB_PORT && SCANNER_DB_NAME && SCANNER_DB_USERNAME && SCANNER_DB_PASSWORD) { @@ -54,15 +56,10 @@ if (!fs.existsSync(path.resolve(`${__dirname}/../configs/local.json`))) { } else { throw new Error('Missing manual database config! \nCheck to make sure you have MANUAL_DB_HOST,MANUAL_DB_PORT, MANUAL_DB_NAME, MANUAL_DB_USERNAME, and MANUAL_DB_PASSWORD') } - if (!TITLE || !START_LAT || !START_LON) { - console.warn('Missing, TITLE, START_LAT, OR START_LON\nYou will be able to process but but these are recommended to add to your docker-compose file') + if (!MAP_GENERAL_START_LAT || !MAP_GENERAL_START_LON) { + console.warn('Missing, MAP_GENERAL_START_LAT OR MAP_GENERAL_START_LON\nYou will be able to proceed but you should add these values to your docker-compose file') } - config.map.general.title = TITLE - config.map.general.headerTitle = TITLE - config.map.general.startLat = +START_LAT - config.map.general.startLon = +START_LON } - if (fs.existsSync(path.resolve(`${__dirname}/../configs/config.json`))) { console.log('[CONFIG] Config v1 (config.json) found, it is fine to leave it but make sure you are using and updating local.json instead.') } From 3dfce4110fa1953ac9119a0501fc4188b2868595 Mon Sep 17 00:00:00 2001 From: TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com> Date: Thu, 28 Apr 2022 21:57:45 -0400 Subject: [PATCH 3/8] fn cleanup --- server/scripts/genEnvConfig.js | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/server/scripts/genEnvConfig.js b/server/scripts/genEnvConfig.js index 96fd782b6..c2dbcd494 100644 --- a/server/scripts/genEnvConfig.js +++ b/server/scripts/genEnvConfig.js @@ -1,11 +1,10 @@ -/* eslint-disable no-nested-ternary */ /* eslint-disable no-console */ const fs = require('fs') const sourceConfig = require('../src/configs/default.json') const camelToSnake = str => str.replace(/([a-z](?=[A-Z]))/g, '$1_').toUpperCase() -const recursiveObjCheck = (key, obj, parentKey = '') => { +const recursiveObjCheck = (obj, key = '', parentKey = '') => { const snakeKey = `${parentKey}${camelToSnake(key)}` if (Array.isArray(obj)) { return { __name: snakeKey, __format: 'json' } @@ -13,7 +12,7 @@ const recursiveObjCheck = (key, obj, parentKey = '') => { if (typeof obj === 'object') { return Object.fromEntries( Object.entries(obj).map(([k, v]) => ( - [k, recursiveObjCheck(k, v, `${snakeKey}_`)] + [k, recursiveObjCheck(v, k, key ? `${snakeKey}_` : snakeKey)] )), ) } @@ -23,19 +22,9 @@ const recursiveObjCheck = (key, obj, parentKey = '') => { } const generateEnvConfig = async () => { - const envConfig = {} - - Object.entries(sourceConfig).forEach(([key, value]) => { - envConfig[key] = typeof value === 'object' - ? recursiveObjCheck(key, value) - : typeof value === 'string' - ? camelToSnake(key) - : { __name: camelToSnake(key), __format: typeof value } - }) - fs.writeFileSync( `${__dirname}/../src/configs/custom-environment-variables.json`, - JSON.stringify(envConfig, null, 2), + JSON.stringify(recursiveObjCheck(sourceConfig), null, 2), ) } From 1b896dae845ce296ba0707594928b65dc64487bf Mon Sep 17 00:00:00 2001 From: TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com> Date: Fri, 29 Apr 2022 10:19:58 -0400 Subject: [PATCH 4/8] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 97ee3e6a8..3ab844d9f 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "serve": "node esbuild.config.mjs --dev --serve", "dev": "nodemon server/src/index.js --watch server", "generate": "node server/scripts/generateMasterfile.js", - "genEnvConfig": "node server/scripts/genEnvConfig.js", + "gen-env-config": "node server/scripts/genEnvConfig.js", "create-locales": "node server/scripts/createLocales.js", "missing-locales": "node server/scripts/createLocales.js --missing", "create-area": "node server/scripts/poracleToGeoJSON.js", From 5970f1c07298eeecc4202178bdf3b40e6f03a2da Mon Sep 17 00:00:00 2001 From: TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com> Date: Sat, 30 Apr 2022 12:15:01 -0400 Subject: [PATCH 5/8] Move telegram bot name from .env to config - Adds a warning if you haven't done so - Auto moves it for you so it doesn't break...but you should move it on your own - Fix inject imports for client --- esbuild.config.mjs | 6 ++- example.env | 1 - package.json | 2 +- server/scripts/configMigration.js | 2 +- .../configs/custom-environment-variables.json | 2 +- server/src/configs/default.json | 2 +- server/src/services/config.js | 44 +++++++++++++------ src/components/layout/auth/Login.jsx | 2 +- src/components/layout/custom/Generator.jsx | 2 +- src/components/layout/dialogs/UserProfile.jsx | 4 +- 10 files changed, 43 insertions(+), 24 deletions(-) diff --git a/esbuild.config.mjs b/esbuild.config.mjs index d0da2bc35..d0a1eec87 100644 --- a/esbuild.config.mjs +++ b/esbuild.config.mjs @@ -141,7 +141,11 @@ const esbuild = { sourcemap: isRelease || isDevelopment, define: { inject: JSON.stringify({ - ...env.parsed, + GOOGLE_ANALYTICS_ID: env.parsed.GOOGLE_ANALYTICS_ID || '', + ANALYTICS_DEBUG_MODE: env.parsed.ANALYTICS_DEBUG_MODE || false, + TITLE: env.parsed.TITLE || env.parsed.MAP_GENERAL_TITLE || '', + SENTRY_DSN: env.parsed.SENTRY_DSN || '', + SENTRY_TRACES_SAMPLE_RATE: env.parsed.SENTRY_TRACES_SAMPLE_RATE || 0.1, VERSION: version, DEVELOPMENT: isDevelopment, CUSTOM: hasCustom, diff --git a/example.env b/example.env index 4b5d0437f..60b6163a9 100644 --- a/example.env +++ b/example.env @@ -1,6 +1,5 @@ GOOGLE_ANALYTICS_ID= TITLE="Map" -TELEGRAM_BOT_NAME="" SENTRY_DSN="" SENTRY_AUTH_TOKEN="" SENTRY_ORG="" diff --git a/package.json b/package.json index 3ab844d9f..ac93b36e5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "reactmap", - "version": "1.2.2", + "version": "1.2.3", "description": "React based frontend map.", "main": "ReactMap.mjs", "author": "TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com>", diff --git a/server/scripts/configMigration.js b/server/scripts/configMigration.js index 027b66ca8..d2280d718 100644 --- a/server/scripts/configMigration.js +++ b/server/scripts/configMigration.js @@ -22,7 +22,7 @@ const convertMapObject = (obj) => obj ? ({ customRoutes: { discordAuthUrl: obj?.discordAuthUrl, telegramAuthUrl: obj?.telegramAuthUrl, - telegramBotEnvRef: obj?.telegramBotEnvRef, + telegramBotName: obj?.telegramBotEnvRef, localAuthUrl: obj?.localAuthUrl, }, links: { diff --git a/server/src/configs/custom-environment-variables.json b/server/src/configs/custom-environment-variables.json index 216bc8f84..50aa92351 100644 --- a/server/src/configs/custom-environment-variables.json +++ b/server/src/configs/custom-environment-variables.json @@ -223,7 +223,7 @@ "customRoutes": { "discordAuthUrl": "MAP_CUSTOM_ROUTES_DISCORD_AUTH_URL", "telegramAuthUrl": "MAP_CUSTOM_ROUTES_TELEGRAM_AUTH_URL", - "telegramBotEnvRef": "MAP_CUSTOM_ROUTES_TELEGRAM_BOT_ENV_REF", + "telegramBotName": "MAP_CUSTOM_ROUTES_TELEGRAM_BOT_NAME", "localAuthUrl": "MAP_CUSTOM_ROUTES_LOCAL_AUTH_URL" }, "links": { diff --git a/server/src/configs/default.json b/server/src/configs/default.json index f0d2b1e06..e530f5768 100644 --- a/server/src/configs/default.json +++ b/server/src/configs/default.json @@ -98,7 +98,7 @@ "customRoutes": { "discordAuthUrl": "/auth/discord/callback", "telegramAuthUrl": "/auth/telegram/callback", - "telegramBotEnvRef": "TELEGRAM_BOT_NAME", + "telegramBotName": "", "localAuthUrl": "/auth/local/callback" }, "links": { diff --git a/server/src/services/config.js b/server/src/services/config.js index f66e6309b..636730033 100644 --- a/server/src/services/config.js +++ b/server/src/services/config.js @@ -64,20 +64,36 @@ if (fs.existsSync(path.resolve(`${__dirname}/../configs/config.json`))) { console.log('[CONFIG] Config v1 (config.json) found, it is fine to leave it but make sure you are using and updating local.json instead.') } -const mergeMapConfig = (obj) => ({ - localeSelection: obj.localeSelection, - ...obj, - ...obj.general, - ...obj.customRoutes, - ...obj.links, - ...obj.holidayEffects, - ...obj.misc, - general: undefined, - customRoutes: undefined, - links: undefined, - holidayEffects: undefined, - misc: undefined, -}) +const mergeMapConfig = (obj) => { + if (obj?.customRoutes?.telegramBotEnvRef) { + console.warn('[CONFIG] customRoutes.telegramBotEnvRef is deprecated, please use customRoutes.telegramBotName instead\n(Move them from your .env file to your config file)') + obj.customRoutes.telegramBotName = process.env[obj.customRoutes.telegramBotEnvRef] + } + ['messageOfTheDay', 'donationPage', 'loginPage'].forEach(category => { + if (obj?.[category]?.components) { + obj[category].components.forEach(component => { + if (component.type === 'telegram') { + component.telegramBotName = process.env[component.telegramBotEnvRef] + console.warn('[CONFIG] telegramBotEnvRef is deprecated, please use telegramBotName instead\n', category, component) + } + }) + } + }) + return { + localeSelection: obj.localeSelection, + ...obj, + ...obj.general, + ...obj.customRoutes, + ...obj.links, + ...obj.holidayEffects, + ...obj.misc, + general: undefined, + customRoutes: undefined, + links: undefined, + holidayEffects: undefined, + misc: undefined, + } +} // Merge sub-objects for the map object config.map = mergeMapConfig(config.map) diff --git a/src/components/layout/auth/Login.jsx b/src/components/layout/auth/Login.jsx index 0eb94dc40..bd14f17f0 100644 --- a/src/components/layout/auth/Login.jsx +++ b/src/components/layout/auth/Login.jsx @@ -68,7 +68,7 @@ const Login = ({ clickedTwice, location, serverSettings, getServerSettings }) => {serverSettings?.authMethods?.includes('telegram') && ( diff --git a/src/components/layout/custom/Generator.jsx b/src/components/layout/custom/Generator.jsx index 45caf3bd2..ee0265c40 100644 --- a/src/components/layout/custom/Generator.jsx +++ b/src/components/layout/custom/Generator.jsx @@ -21,7 +21,7 @@ export default function Generator({ case 'button': return case 'text': return case 'divider': return - case 'telegram': return + case 'telegram': return case 'discord': return case 'localLogin': return ( { const setAuth = useStatic(state => state.setAuth) - const { map: { discordAuthUrl, telegramAuthUrl, telegramBotEnvRef } } = useStatic(state => state.config) + const { map: { discordAuthUrl, telegramAuthUrl, telegramBotName } } = useStatic(state => state.config) const [refreshing, setRefreshing] = useState(false) @@ -117,7 +117,7 @@ const LinkProfiles = ({ auth, t }) => { {['discord', 'telegram'].map((method, i) => { if (!auth.methods.includes(method)) return null const Component = i - ? + ? : return ( From fb144b832baecc5a7cc96e72d7a3f29176854c1c Mon Sep 17 00:00:00 2001 From: TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com> Date: Sat, 30 Apr 2022 12:28:31 -0400 Subject: [PATCH 6/8] Update Telegram.jsx --- src/components/layout/auth/Telegram.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/layout/auth/Telegram.jsx b/src/components/layout/auth/Telegram.jsx index 065062bdc..0ee4c75de 100644 --- a/src/components/layout/auth/Telegram.jsx +++ b/src/components/layout/auth/Telegram.jsx @@ -8,7 +8,7 @@ export default function Telegram({ botName, authUrl }) { const script = document.createElement('script') script.src = 'https://telegram.org/js/telegram-widget.js?4' - script.setAttribute('data-telegram-login', inject?.[botName]) + script.setAttribute('data-telegram-login', botName) script.setAttribute('data-auth-url', authUrl) script.setAttribute('data-lang', (localStorage?.getItem('i18nextLng') || 'en')) script.setAttribute('data-userpic', 'false') From ba66438031b7e3e15c030addcce0787b687fffe7 Mon Sep 17 00:00:00 2001 From: TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com> Date: Sat, 30 Apr 2022 15:47:03 -0400 Subject: [PATCH 7/8] Update config.js --- server/src/services/config.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/src/services/config.js b/server/src/services/config.js index 636730033..ad6a0e648 100644 --- a/server/src/services/config.js +++ b/server/src/services/config.js @@ -65,6 +65,9 @@ if (fs.existsSync(path.resolve(`${__dirname}/../configs/config.json`))) { } const mergeMapConfig = (obj) => { + if (process.env.TELEGRAM_BOT_NAME && !obj?.customRoutes?.telegramBotName) { + obj.telegramBotName = process.env.TELEGRAM_BOT_NAME + } if (obj?.customRoutes?.telegramBotEnvRef) { console.warn('[CONFIG] customRoutes.telegramBotEnvRef is deprecated, please use customRoutes.telegramBotName instead\n(Move them from your .env file to your config file)') obj.customRoutes.telegramBotName = process.env[obj.customRoutes.telegramBotEnvRef] From 9b17203ff9e763dd8b8f62412333effc08d124e1 Mon Sep 17 00:00:00 2001 From: TurtIeSocks <58572875+TurtIeSocks@users.noreply.github.com> Date: Sat, 30 Apr 2022 16:08:47 -0400 Subject: [PATCH 8/8] Update config.js --- server/src/services/config.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/server/src/services/config.js b/server/src/services/config.js index ad6a0e648..173d585ce 100644 --- a/server/src/services/config.js +++ b/server/src/services/config.js @@ -66,18 +66,22 @@ if (fs.existsSync(path.resolve(`${__dirname}/../configs/config.json`))) { const mergeMapConfig = (obj) => { if (process.env.TELEGRAM_BOT_NAME && !obj?.customRoutes?.telegramBotName) { - obj.telegramBotName = process.env.TELEGRAM_BOT_NAME + if (obj.customRoutes) obj.customRoutes.telegramBotName = process.env.TELEGRAM_BOT_NAME + console.warn('[CONFIG] TELEGRAM_BOT_NAME has been moved from the .env file to your config, telegramBotEnvRef is now deprecated.\nplease use customRoutes.telegramBotName instead\n(Move them from your .env file to your config file)') } if (obj?.customRoutes?.telegramBotEnvRef) { - console.warn('[CONFIG] customRoutes.telegramBotEnvRef is deprecated, please use customRoutes.telegramBotName instead\n(Move them from your .env file to your config file)') + console.warn('[CONFIG] TELEGRAM_BOT_NAME has been moved from the .env file to your config, telegramBotEnvRef is now deprecated.\nplease use customRoutes.telegramBotName instead\n(Move them from your .env file to your config file)') obj.customRoutes.telegramBotName = process.env[obj.customRoutes.telegramBotEnvRef] } ['messageOfTheDay', 'donationPage', 'loginPage'].forEach(category => { if (obj?.[category]?.components) { obj[category].components.forEach(component => { if (component.type === 'telegram') { + console.warn('[CONFIG] telegramBotEnvRef is deprecated, please use telegramBotName instead\n', category) + console.warn('OLD:\n', component) component.telegramBotName = process.env[component.telegramBotEnvRef] - console.warn('[CONFIG] telegramBotEnvRef is deprecated, please use telegramBotName instead\n', category, component) + delete component.telegramBotEnvRef + console.warn('NEW:\n', component) } }) }