-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
127 lines (100 loc) · 5.6 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// Author: NikkelM
// Description: Notion integration that updates a database with information from the Steam API.
// Suppresses the warning about the fetch API being unstable
process.removeAllListeners('warning');
import { getSteamAppInfoDirect, getSteamAppInfoSteamUser, getSteamReviewScoreDirect } from './js/steamAPI.js';
import { CONFIG, localDatabase, addGameToLocalDatabase, storeAPIRequired, steamUserAPIRequired, reviewAPIRequired } from './js/utils.js';
import { getGamesFromNotionDatabase, updateNotionPage, checkNotionPropertiesExistence, setUserIdInDatabaseIfNotSet } from './js/notion.js';
import { getGameProperties } from './js/gameProperties.js';
// ---------- Setup ----------
// We need to do this here because of circular imports
await checkNotionPropertiesExistence();
await setUserIdInDatabaseIfNotSet();
const updateInterval = CONFIG.updateInterval;
// ---------- Main Loop ----------
function main() {
updateNotionDatabase().catch(console.error);
}
main();
async function updateNotionDatabase() {
console.log("Looking for changes in Notion database...");
// Update the last updated timestamp
// Do this before fetching to make sure we don't miss changes made between now and fetching new properties below
// Subtract 60 more seconds to make sure we have some buffer in case things get changed in between executions
const newLastUpdatedAt = new Date(Date.now() - 60000).toISOString();
// If we encounter an error or would hit the Steam API request limit, we don't want to update the timestamp to find the games we missed again
let hadError = false;
let hitSteamAPILimit = false;
// Get the games currently in the Notion database
let [updatedPagesSteamAppIds, updatedPagesEditedBy] = await getGamesFromNotionDatabase();
console.log(`Found ${Object.keys(updatedPagesSteamAppIds).length} new/updated pages with the "${CONFIG.steamAppIdProperty}" property set.\n`);
if (CONFIG.alwaysUpdate) {
console.log("Every page will be updated, as long as someone other than the integration has last edited it and it does not exist in the local database yet.\n");
const integrationUserId = await localDatabase.get('userId');
const pagesInDatabase = await localDatabase.getMany(Object.keys(updatedPagesSteamAppIds));
for (const [pageId, lastEditedBy] of Object.entries(updatedPagesEditedBy)) {
// Only delete pages that were edited by the integration and are already in the local database
if (lastEditedBy === integrationUserId && pagesInDatabase.includes(updatedPagesSteamAppIds[pageId])) {
delete updatedPagesEditedBy[pageId];
delete updatedPagesSteamAppIds[pageId];
}
}
} else {
console.log("Removing pages that are already present in the local database from the list of pages to update...\n");
// Remove all pages from updatedPagesSteamAppIds that are already in the local database
const pagesInDatabase = await localDatabase.getMany(Object.keys(updatedPagesSteamAppIds));
for (const [pageId, steamAppId] of Object.entries(updatedPagesSteamAppIds)) {
if (pagesInDatabase.includes(steamAppId)) {
delete updatedPagesSteamAppIds[pageId];
delete updatedPagesEditedBy[pageId];
}
}
}
console.log(`Found ${Object.keys(updatedPagesSteamAppIds).length} new/updated pages with a "Steam App ID" in the Notion database that will be updated by the integration.`);
// Limit the number of games to avoid hitting the Steam API rate limit, if required
if (Object.keys(updatedPagesSteamAppIds).length > 50 && storeAPIRequired) {
console.log("The Steam store API limits the allowed amount of requests in quick succession. Some games will be updated later.");
hitSteamAPILimit = true;
updatedPagesSteamAppIds = Object.fromEntries(Object.entries(updatedPagesSteamAppIds).slice(0, 50));
}
if (Object.keys(updatedPagesSteamAppIds).length > 0) {
// Get info about the new games from the SteamUser API, if required
const appInfoSteamUser = steamUserAPIRequired
? await getSteamAppInfoSteamUser(Object.values(updatedPagesSteamAppIds)).then((appInfoSteamUser) => { return appInfoSteamUser; })
: null;
// Update the Notion database with the new properties
for (const [pageId, steamAppId] of Object.entries(updatedPagesSteamAppIds)) {
try {
console.log(`Setting properties for game with Steam App ID ${steamAppId}`);
// Get info about this game from the Steam API, if required
const appInfoDirect = storeAPIRequired
? await getSteamAppInfoDirect(steamAppId)
: null;
// Get info about the game's review score from the reviews API, if required
const appInfoReviews = reviewAPIRequired
? await getSteamReviewScoreDirect(steamAppId)
: null;
let notionProperties = await getGameProperties(appInfoDirect, appInfoSteamUser[steamAppId], appInfoReviews, steamAppId);
updateNotionPage(pageId, notionProperties);
addGameToLocalDatabase(pageId, steamAppId);
} catch (error) {
console.error(error);
hadError = true;
}
}
}
// Only update the last updated time if there were no errors during execution and we didn't hit the Steam API request limit
// This makes sure that we can find the games that had errors or that we had to omit again the next time
if (!hadError && !hitSteamAPILimit) {
localDatabase.put('lastUpdatedAt', newLastUpdatedAt);
}
if (hitSteamAPILimit) {
console.log(`Done updating Notion database. Waiting 1 minute until we can ping the Steam store API again....\n`);
// Run this method again in 1 minute
setTimeout(main, 60000);
} else {
console.log(`Done updating Notion database. Looking again in ${updateInterval / 60000} minute(s).\n`);
// Run this method again in `updateInterval` milliseconds
setTimeout(main, updateInterval);
}
}