-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactoring/NR-65 Refactoring game identifier #207
Changes from all commits
f31dfa2
098f3ea
2b85362
8b05b8d
3fe45fd
1569b81
7adf85e
5fe657b
378231d
8078f29
7a79a0d
cce9f5f
bfe588d
8f37ea9
d33d876
7f2fe0c
71bd5d8
ccbc45a
730c290
58c83d2
a4cdb19
15dbc1d
c8ce0a3
8d6fade
fe8e42d
d1fa78e
5f3f56d
f695ee2
7ddcf9e
6d321e2
0e51d5e
acae142
25e94ce
2a47075
6d5f5a2
984ed3c
b679495
302a05c
3d888e5
07423a8
f0481f5
70a75de
c238382
497d8d4
b4e3ffe
4a074dc
527e239
4c5c27c
6da85db
1176ec4
c326ab7
0c41540
dec36a9
3a334b9
b1a45e0
3647273
973dc07
c928d55
ecddf68
348a34f
7f29a48
62a60d5
1b1d2d2
2011408
a867e63
722700e
e7bd160
1ff3e59
e2d1af1
15d0999
900e877
c855f4a
87f4166
d316d19
fd2017d
b4256b0
4b2ef79
024ae51
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,21 @@ | ||
import { parseHTML } from "linkedom"; | ||
|
||
export function createHtmlDetailsPage(page) { | ||
return { page, id: 1 }; | ||
} | ||
|
||
export function createHtmlDetailsPages(pages) { | ||
return pages.map((page, index) => { | ||
return { page, id: index + 1 }; | ||
}); | ||
} | ||
|
||
export function getParsedHtmlPage(page) { | ||
return parseHTML(page).document; | ||
} | ||
|
||
export function getParsedHtmlPages(pages) { | ||
return pages.map((page, index) => { | ||
return { page: parseHTML(page).document, id: index + 1 }; | ||
}); | ||
} |
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,6 @@ | ||
import { | ||
discoverGamesFromSteamWeb, | ||
updateTypeSideEffectFree, | ||
identifyGames, | ||
assignType, | ||
updateMissingDetails, | ||
updateMissingReleaseDates, | ||
recordAttemptsViaSteamDb, | ||
} from "../../services/game.service.js"; | ||
import { delay } from "../../../common/time.utils.js"; | ||
import { HistoryCheck } from "../../models/history.check.js"; | ||
import { ValidDataSources } from "../../models/valid.data.sources.js"; | ||
|
||
export class GameIdentifier { | ||
#steamClient; | ||
|
@@ -17,6 +9,7 @@ export class GameIdentifier { | |
#historyChecksRepository; | ||
#logger; | ||
#options; | ||
#htmlParser; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Very good! 👍 You are using dependency injection. Now you are inverting dependencies which means the game identifier is independent from the htmlParser and whoever is instantiating the GameIdentifier is dependent on it because it has to provide it to the GameIdentifier on creation. |
||
constructor( | ||
steamClient, | ||
|
@@ -25,203 +18,155 @@ export class GameIdentifier { | |
historyChecksRepository, | ||
logger, | ||
options, | ||
htmlParser, | ||
) { | ||
this.#steamClient = steamClient; | ||
this.#steamAppsRepository = steamAppsRepository; | ||
this.#gamesRepository = gamesRepository; | ||
this.#historyChecksRepository = historyChecksRepository; | ||
this.#logger = logger; | ||
this.#options = options; | ||
this.#htmlParser = htmlParser; | ||
} | ||
|
||
tryViaSteamWeb = async () => { | ||
this.#logger.debugc("identifying games via steam web"); | ||
checkIfGameViaSource = async (source) => { | ||
this.#logger.debugc(`identifying games via ${source}`); | ||
|
||
const steamApps = await this.#steamAppsRepository.getSteamWebUntriedFilteredSteamApps( | ||
const steamApps = await this.#steamAppsRepository.getSourceUntriedFilteredSteamApps( | ||
this.#options.batchSize, | ||
source, | ||
); | ||
if (steamApps.length === 0) { | ||
|
||
if (steamApps.isEmpty) { | ||
this.#logger.debugc( | ||
`no steam apps in db, retry in: ${this.#options.globalIterationDelay} ms`, | ||
); | ||
|
||
return; | ||
} | ||
|
||
const [games, updatedSteamApps] = await this.#identifyViaSteamWeb(steamApps); | ||
|
||
this.#persist(games, updatedSteamApps); | ||
}; | ||
const htmlDetailsPages = await this.#getSteamAppsHtmlDetailsPages( | ||
steamApps.content, | ||
source, | ||
); | ||
|
||
async #identifyViaSteamWeb(steamApps) { | ||
const htmlDetailsPages = await this.#getSteamAppsHtmlDetailsPages(steamApps); | ||
steamApps.identifyTypes(htmlDetailsPages, source); | ||
|
||
const games = discoverGamesFromSteamWeb(steamApps, htmlDetailsPages); | ||
const games = steamApps.extractGames(htmlDetailsPages, source); | ||
|
||
const updatedSteamApps = updateTypeSideEffectFree(steamApps, htmlDetailsPages); | ||
await this.#persistGameCheckUpdates(games, steamApps.content); | ||
}; | ||
|
||
return [games, updatedSteamApps]; | ||
} | ||
async #getSteamAppsHtmlDetailsPages(steamApps, source) { | ||
const htmlDetailsPages = []; | ||
|
||
async #getSteamAppsHtmlDetailsPages(steamApps) { | ||
const detailsPages = []; | ||
for (let steamApp of steamApps) { | ||
detailsPages.push( | ||
// TODO https://github.com/lukatarman/steam-game-stats/issues/192 | ||
await this.#steamClient.getSteamAppHtmlDetailsPage(steamApp.appid), | ||
// TODO https://github.com/lukatarman/steam-game-stats/issues/192 | ||
const htmlPage = await this.#steamClient.getSourceHtmlDetailsPage( | ||
steamApp.appid, | ||
source, | ||
); | ||
|
||
htmlDetailsPages.push({ | ||
page: this.#htmlParser(htmlPage).document, | ||
id: steamApp.appid, | ||
}); | ||
|
||
await delay(this.#options.unitDelay); | ||
} | ||
return detailsPages; | ||
|
||
return htmlDetailsPages; | ||
} | ||
|
||
async #persist(games, updatedSteamApps) { | ||
async #persistGameCheckUpdates(games, steamApps) { | ||
if (games.length !== 0) { | ||
this.#logger.debugc(`persiting ${games.length} identified games`); | ||
|
||
await this.#gamesRepository.insertManyGames(games); | ||
await this.#historyChecksRepository.insertManyHistoryChecks( | ||
HistoryCheck.manyFromGames(games), | ||
); | ||
} | ||
await this.#steamAppsRepository.updateSteamAppsById(updatedSteamApps); | ||
} | ||
|
||
tryViaSteamchartsWeb = async () => { | ||
this.#logger.debugc("identifying games via steamcharts web"); | ||
|
||
const steamApps = | ||
await this.#steamAppsRepository.getSteamchartsUntriedFilteredSteamApps( | ||
this.#options.batchSize, | ||
); | ||
if (steamApps.length === 0) { | ||
this.#logger.debugc( | ||
`no steam apps in db, retry in: ${this.#options.globalIterationDelay} ms`, | ||
); | ||
return; | ||
} | ||
|
||
const updatedSteamApps = await this.#updateStatusViaSteamchartsWeb(steamApps); | ||
const games = identifyGames(updatedSteamApps); | ||
|
||
this.#persist(games, updatedSteamApps); | ||
}; | ||
|
||
// this method is a mess right now, including the tests. Will be fixed in issue: #198 | ||
async #updateStatusViaSteamchartsWeb(steamApps) { | ||
const updatedSteamApps = []; | ||
|
||
for (let steamApp of steamApps) { | ||
const steamAppCopy = steamApp.copy(); | ||
steamAppCopy.triedViaSteamchartsWeb(); | ||
|
||
// TODO https://github.com/lukatarman/steam-game-stats/issues/192 | ||
const result = await this.#steamClient.getSteamchartsGameHtmlDetailsPage( | ||
steamApp.appid, | ||
); | ||
|
||
if (result === "") { | ||
steamAppCopy.failedViaSteamchartsWeb(); | ||
this.#logger.debugc(`no entry on steamcharts web for appid: ${steamApp.appid}`); | ||
} | ||
|
||
assignType(result, steamAppCopy); | ||
|
||
await delay(this.#options.unitDelay); | ||
updatedSteamApps.push(steamAppCopy); | ||
} | ||
|
||
return updatedSteamApps; | ||
await this.#steamAppsRepository.updateSteamAppsById(steamApps); | ||
} | ||
|
||
updateGamesWithoutDetails = async () => { | ||
const source = ValidDataSources.validDataSources.steamDb; | ||
this.#logger.debugc("updating games without details"); | ||
|
||
const games = await this.#gamesRepository.getGamesWithoutDetails( | ||
this.#options.batchSize, | ||
); | ||
|
||
if (games.length === 0) { | ||
if (games.isEmpty) { | ||
this.#logger.debugc( | ||
`no games without details in db, retrying in ${ | ||
`no games without details in db, retry in: ${ | ||
this.#options.globalIterationDelay | ||
} ms`, | ||
); | ||
return; | ||
} | ||
|
||
const steamApps = await this.#steamAppsRepository.getSteamAppsById( | ||
games.map((game) => game.id), | ||
); | ||
const steamApps = await this.#steamAppsRepository.getSteamAppsById(games.ids); | ||
|
||
const htmlDetailsPages = await this.#getSteamDbHtmlDetailsPages(games); | ||
const htmlDetailsPages = await this.#getSteamAppsHtmlDetailsPages( | ||
steamApps.content, | ||
source, | ||
); | ||
|
||
const updatedApps = recordAttemptsViaSteamDb(steamApps, htmlDetailsPages); | ||
steamApps.recordAttemptsViaSource(htmlDetailsPages, source); | ||
|
||
updateMissingDetails(games, htmlDetailsPages); | ||
games.updateGameDetailsFrom(htmlDetailsPages); | ||
|
||
this.#persistMissingProperties(games, updatedApps); | ||
this.#persistUpdatedDetails(games.content, steamApps.content); | ||
}; | ||
|
||
async #getSteamDbHtmlDetailsPages(games) { | ||
const htmlDetailsPages = []; | ||
|
||
for (let game of games) { | ||
// TODO https://github.com/lukatarman/steam-game-stats/issues/192 | ||
const htmlPage = await this.#steamClient.getSteamDbHtmlDetailsPage(game.id); | ||
htmlDetailsPages.push({ page: htmlPage, id: game.id }); | ||
|
||
await delay(this.#options.unitDelay); | ||
} | ||
|
||
return htmlDetailsPages; | ||
} | ||
|
||
async #persistMissingProperties(games, appsWithoutPages) { | ||
if (appsWithoutPages.length !== 0) { | ||
this.#logger.debugc(`persisting ${appsWithoutPages.length} apps without pages`); | ||
this.#steamAppsRepository.updateSteamAppsById(appsWithoutPages); | ||
} | ||
|
||
async #persistUpdatedDetails(games, steamApps) { | ||
this.#logger.debugc(`persisting ${steamApps.length} apps with updated html attempts`); | ||
this.#logger.debugc(`persisting ${games.length} games with updated details`); | ||
await this.#gamesRepository.updateGameDetails(games); | ||
|
||
await this.#steamAppsRepository.updateSteamAppsById(steamApps); | ||
await this.#gamesRepository.updateGameDetailsFrom(games); | ||
} | ||
|
||
updateGamesWithoutReleaseDates = async () => { | ||
this.#logger.debugc("updating games without details"); | ||
const source = ValidDataSources.validDataSources.steamDb; | ||
this.#logger.debugc(`updating games without release dates via ${source}`); | ||
|
||
const games = await this.#gamesRepository.getGamesWithoutReleaseDates( | ||
this.#options.batchSize, | ||
); | ||
|
||
if (games.length === 0) { | ||
if (games.isEmpty) { | ||
this.#logger.debugc( | ||
`no games without release dates in db, retrying in ${ | ||
this.#options.iterationDelay | ||
`no games without release dates in db, retry in: ${ | ||
this.#options.globalIterationDelay | ||
} ms`, | ||
); | ||
|
||
return; | ||
} | ||
|
||
const steamApps = await this.#steamAppsRepository.getSteamAppsById( | ||
games.map((game) => game.id), | ||
); | ||
const steamApps = await this.#steamAppsRepository.getSteamAppsById(games.ids); | ||
|
||
const htmlDetailsPages = await this.#getSteamDbHtmlDetailsPages(games); | ||
const htmlDetailsPages = await this.#getSteamAppsHtmlDetailsPages( | ||
steamApps.content, | ||
source, | ||
); | ||
|
||
const updatedApps = recordAttemptsViaSteamDb(steamApps, htmlDetailsPages); | ||
steamApps.recordAttemptsViaSource(htmlDetailsPages, source); | ||
|
||
updateMissingReleaseDates(games, htmlDetailsPages); | ||
games.extractReleaseDatesFrom(htmlDetailsPages); | ||
|
||
this.#persistReleaseDates(games, updatedApps); | ||
this.#persistReleaseDates(games.content, steamApps.content); | ||
}; | ||
|
||
#persistReleaseDates = async (games, appsWithoutPages) => { | ||
if (appsWithoutPages.length !== 0) { | ||
this.#logger.debugc(`persisting ${appsWithoutPages.length} apps without pages`); | ||
this.#steamAppsRepository.updateSteamAppsById(appsWithoutPages); | ||
} | ||
|
||
async #persistReleaseDates(games, steamApps) { | ||
this.#logger.debugc(`persisting ${steamApps.length} apps with updated html attempts`); | ||
this.#logger.debugc(`persisting ${games.length} games with updated release dates`); | ||
|
||
await this.#steamAppsRepository.updateSteamAppsById(steamApps); | ||
await this.#gamesRepository.updateReleaseDates(games); | ||
}; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use private methods (encapsulation) if no client needs access