Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions server/src/configs/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -356,9 +356,7 @@
"migrationTableName": "knex_migrations",
"joinGymBadgeTable": false,
"hideOldQuests": false,
"maxConnections": 10,
"startupDelayMs": 1000,
"availableRetryCount": 5
"maxConnections": 10
},
"schemas": [
{
Expand Down
4 changes: 2 additions & 2 deletions server/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ const Backend = require('i18next-fs-backend')
const { ValidationError } = require('apollo-server-core')
const { ApolloServer } = require('apollo-server-express')

const { Db } = require('./services/initialization')
const config = require('./services/config')
const { Db, Event } = require('./services/initialization')
const { sessionStore } = require('./services/sessionStore')
const rootRouter = require('./routes/rootRouter')
const typeDefs = require('./graphql/typeDefs')
Expand All @@ -37,7 +37,7 @@ const server = new ApolloServer({
debug: config.devOptions.queryDebug,
context: ({ req, res }) => {
const perms = req.user ? req.user.perms : req.session.perms
return { req, res, Db, perms, version }
return { req, res, Db, Event, perms, version }
},
formatError: (e) => {
if (config.devOptions.enabled) {
Expand Down
13 changes: 7 additions & 6 deletions server/src/models/Pokestop.js
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@ module.exports = class Pokestop extends Model {
const finalList = new Set()
const quests = {}
const stops = {}

quests.items = await this.query()
.select('quest_item_id')
.from(isMad ? 'trs_quest' : 'pokestop')
Expand Down Expand Up @@ -602,10 +603,6 @@ module.exports = class Pokestop extends Model {
}
})

if (finalList.size === 0) {
return fetchQuests()
}

if (hasMultiInvasions) {
stops.invasions = await this.query()
.leftJoin('incident', 'pokestop.id', 'incident.pokestop_id')
Expand All @@ -620,12 +617,16 @@ module.exports = class Pokestop extends Model {
])
.where(multiInvasionMs ? 'expiration_ms' : 'incident.expiration', '>=', ts * (multiInvasionMs ? 1000 : 1))
.orderBy('grunt_type')
} else {
} else if (hasMultiInvasions === false) {
stops.invasions = await this.query()
.select(isMad ? 'incident_grunt_type AS grunt_type' : 'grunt_type')
.where(isMad ? 'incident_expiration' : 'incident_expire_timestamp', '>=', isMad ? this.knex().fn.now() : ts)
.groupBy('grunt_type')
.orderBy('grunt_type')
} else {
stops.invasions = Object.keys(Event.masterfile.invasions)
.filter(grunt => +grunt < 100)
.map(i => ({ grunt_type: i }))
}
stops.lures = await this.query()
.select(isMad ? 'active_fort_modifier AS lure_id' : 'lure_id')
Expand All @@ -640,7 +641,7 @@ module.exports = class Pokestop extends Model {
default: rewards.forEach(reward => finalList.add(`i${reward.grunt_type}`)); break
}
})
return [...finalList]
return finalList.size === 0 ? fetchQuests() : [...finalList]
}

static parseRdmRewards = (quest) => {
Expand Down
122 changes: 33 additions & 89 deletions server/src/services/DbCheck.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable no-await-in-loop */
/* eslint-disable no-console */
const knex = require('knex')
const { raw } = require('objection')
Expand All @@ -17,7 +16,7 @@ module.exports = class DbCheck {
if (!this.models[capital]) {
this.models[capital] = []
}
this.models[capital].push({ connection: i, isMad: false })
this.models[capital].push({ connection: i })
})
return knex({
client: 'mysql2',
Expand All @@ -36,42 +35,44 @@ module.exports = class DbCheck {
},
},
})
});
(async () => {
await this.determineType()
await this.pvp()
await this.pokestopChecks()
})()
}

static async isMadDb(connection) {
try {
await connection('trs_quest').limit(1).first()
return true
} catch (e) {
return false
}
})
}

static getDistance(args, isMad) {
return raw(`ROUND(( 3959 * acos( cos( radians(${args.lat}) ) * cos( radians( ${isMad ? 'latitude' : 'lat'} ) ) * cos( radians( ${isMad ? 'longitude' : 'lon'} ) - radians(${args.lon}) ) + sin( radians(${args.lat}) ) * sin( radians( ${isMad ? 'latitude' : 'lat'} ) ) ) ),2)`).as('distance')
}

async determineType() {
console.log('[DB] Determining database types..')
console.log(`[DB] Determining database types for ${this.connections.length} connection${this.connections.length > 1 ? 's' : ''}`)
await Promise.all(this.connections.map(async (schema, i) => {
const isMad = await DbCheck.isMadDb(schema)
Object.entries(this.models).forEach(([category, sources]) => {
try {
try {
const isMad = await schema('trs_quest').columnInfo().then(col => Object.keys(col).length > 0)
const pvpV2 = await schema('pokemon').columnInfo().then(col => 'pvp' in col)
const [hasRewardAmount, hasAltQuests] = await schema('pokestop').columnInfo()
.then(columns => ([
['quest_reward_amount', 'item_reward_amount'].some(c => c in columns),
'alternative_quest_type' in columns,
]))
const [hasMultiInvasions, multiInvasionMs] = await schema('incident').columnInfo()
.then(columns => ([
'character' in columns,
'expiration_ms' in columns,
]))
Object.entries(this.models).forEach(([category, sources]) => {
sources.forEach((source, j) => {
if (source.connection === i) {
this.models[category][j].isMad = isMad
this.models[category][j].pvpV2 = pvpV2
this.models[category][j].hasRewardAmount = hasRewardAmount
this.models[category][j].hasAltQuests = hasAltQuests
this.models[category][j].hasMultiInvasions = hasMultiInvasions
this.models[category][j].multiInvasionMs = multiInvasionMs
}
})
} catch (e) {
console.error('[DB]', e.message)
}
})
})
} catch (e) {
console.error('[DB]', e.message)
}
}))
}

Expand All @@ -92,7 +93,7 @@ module.exports = class DbCheck {
this.models[model][i].SubModel = models[model].bindKnex(this.connections[source.connection])
})
}
console.log(`[DB] Bound ${model} to ${sources.length} connections`)
console.log(`[DB] Bound ${model} to ${sources.length} connection${sources.length > 1 ? 's' : ''}`)
})
} catch (e) {
console.error(`
Expand All @@ -118,59 +119,6 @@ module.exports = class DbCheck {
return []
}

async pvp() {
await Promise.all(this.models.Pokemon.map(async (source) => {
try {
await source.SubModel.query()
.whereNotNull('pvp')
.limit(1)
source.pvpV2 = true
} catch (_) {
source.pvpV2 = false
}
}))
}

async pokestopChecks() {
await Promise.all(this.models.Pokestop.map(async (source) => {
try {
if (!source.isMad) {
await source.SubModel.query()
.whereNotNull('quest_reward_amount')
.limit(1)
}
source.hasRewardAmount = true
} catch (_) {
source.hasRewardAmount = false
}
try {
await source.SubModel.query()
.whereNotNull('alternative_quest_type')
.limit(1)
source.hasAltQuests = true
} catch (_) {
source.hasAltQuests = false
}
try {
await source.SubModel.query()
.leftJoin('incident', 'pokestop.id', 'incident.pokestop_id')
.limit(1)
source.hasMultiInvasions = true
} catch (_) {
source.hasMultiInvasions = false
}
try {
await source.SubModel.query()
.leftJoin('incident', 'pokestop.id', 'incident.pokestop_id')
.select('expiration_ms')
.limit(1)
source.multiInvasionMs = true
} catch (_) {
source.multiInvasionMs = false
}
}))
}

async getAll(model, perms, args, userId, method = 'getAll') {
const data = await Promise.all(this.models[model].map(async (source) => (
source.SubModel[method](perms, args, source, userId)
Expand All @@ -179,15 +127,11 @@ module.exports = class DbCheck {
}

async getOne(model, id, method = 'getOne') {
const sources = this.models[model]
let foundObj
let source = 0
while (!foundObj && source < sources.length) {
const found = await sources[source].SubModel[method](id, sources[source])
foundObj = found
source += 1
}
return foundObj || {}
const data = await Promise.all(this.models[model].map(async (source) => (
source.SubModel[method](id, source)
)))
const cleaned = DbCheck.deDupeResults(data.filter(Boolean))
return (Array.isArray(cleaned) ? cleaned[0] : cleaned) || {}
}

async search(model, perms, args, method = 'search') {
Expand Down Expand Up @@ -218,7 +162,7 @@ module.exports = class DbCheck {
const results = await Promise.all(this.models[model].map(async (source) => (
source.SubModel.getAvailable(source)
)))
console.log(`[DB] Updating available for ${model}`)
console.log(`[DB] Setting available for ${model}`)
if (results.length === 1) return results[0]
if (results.length > 1) {
const returnSet = new Set()
Expand Down
26 changes: 4 additions & 22 deletions server/src/services/EventManager.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* eslint-disable no-promise-executor-return */
/* eslint-disable no-await-in-loop */
/* eslint-disable no-console */
const { promises: fs } = require('fs')
const path = require('path')
Expand All @@ -10,33 +8,17 @@ const fetchJson = require('./api/fetchJson')
const initWebhooks = require('./initWebhooks')

module.exports = class EventManager {
constructor(config, masterfile, Db, Pvp) {
constructor(masterfile) {
this.masterfile = masterfile
this.invasions = masterfile.invasions
this.available = { gyms: [], pokestops: [], pokemon: [], nests: [] }
this.uicons = []
this.baseUrl = 'https://raw.githubusercontent.com/WatWowMap/wwm-uicons/main/'
this.webhookObj = {}
this.pokestopTry = 1
}

setTimeout(async () => {
// Set initials, comes with a timeout just to make sure all databases get configured first
await this.getUicons(config.icons.styles)
this.available.gyms = await Db.getAvailable('Gym')
this.available.nests = await Db.getAvailable('Nest')
this.available.pokemon = await Db.getAvailable('Pokemon')
this.available.pokestops = await Db.getAvailable('Pokestop')
while (!this.available.pokestops.length && this.pokestopTry <= config.database.settings.availableRetryCount) {
console.log(`[EVENT] No pokestops found, trying again in 1 second (attempt ${this.pokestopTry} / ${config.database.settings.availableRetryCount})`)
await new Promise(resolve => setTimeout(resolve, 1000))
this.available.pokestops = await Db.getAvailable('Pokestop')
this.pokestopTry += 1
}
await this.getMasterfile()
await this.getInvasions()
await this.getWebhooks(config)
}, config.database.settings.startupDelayMs)
this.setTimers(config, Db, Pvp)
async setAvailable(category, model, Db) {
this.available[category] = await Db.getAvailable(model)
}

setTimers(config, Db, Pvp) {
Expand Down
3 changes: 3 additions & 0 deletions server/src/services/api/fetchQuests.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ module.exports = async function fetchQuests() {
questsInfo.push(`i${grunt}`)
}
})
for (let i = 1; i <= 5; i += 1) {
questsInfo.push(`l50${i}`)
}
return questsInfo
} catch (e) {
console.warn(e, '\nUnable to fetch available quests and invasions from GitHub')
Expand Down
20 changes: 19 additions & 1 deletion server/src/services/initialization.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-console */
const {
database: { schemas: exampleSchemas },
} = require('../configs/local.example.json')
Expand All @@ -10,9 +11,26 @@ const PvpWrapper = require('./PvpWrapper')

const Db = new DbCheck(exampleSchemas, config.database, config.devOptions.queryDebug, config.api)
const Pvp = config.api.pvp.reactMapHandlesPvp ? new PvpWrapper(config.api.pvp) : null
const Event = new EventManager(staticMf)

Event.setTimers(config, Db, Pvp)

Db.determineType()
.then(async () => {
await Promise.all([
Event.getUicons(config.icons.styles),
Event.getMasterfile(),
Event.getInvasions(),
Event.getWebhooks(config),
Event.setAvailable('gyms', 'Gym', Db),
Event.setAvailable('pokestops', 'Pokestop', Db),
Event.setAvailable('pokemon', 'Pokemon', Db),
Event.setAvailable('nests', 'Nest', Db),
])
})

module.exports = {
Db,
Pvp,
Event: new EventManager(config, staticMf, Db, Pvp),
Event,
}