Files
generative.fm/node_scripts/update-stats.js
2019-10-27 17:22:09 -05:00

126 lines
3.0 KiB
JavaScript

'use strict';
const { DynamoDB } = require('aws-sdk');
const { production } = require('./secrets');
const { dynamoStatsTableName, dynamoStatesTableName } = production;
const dynamodb = new DynamoDB({
apiVersion: '2012-08-10',
region: 'us-west-2',
});
const scanPromise = ExclusiveStartKey =>
new Promise((resolve, reject) => {
dynamodb.scan(
Object.assign(
{ TableName: dynamoStatesTableName },
ExclusiveStartKey ? { ExclusiveStartKey } : {}
),
(err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
}
);
});
const appendItemsAndQueueNext = data => {
const items = [];
const { Items, LastEvaluatedKey } = data;
items.push(...Items);
if (LastEvaluatedKey) {
return scanPromise(LastEvaluatedKey)
.catch(err => console.error(err))
.then(result => appendItemsAndQueueNext(result))
.then(nextItems => items.concat(nextItems));
}
return Promise.resolve(items);
};
const getTotalPlaytime = items =>
items.reduce((totalPlayTime, item) => {
if (item.playTime) {
Reflect.ownKeys(item.playTime.M)
.filter(pieceId => pieceId.includes('alex-bainter-'))
.forEach(pieceId => {
if (totalPlayTime.has(pieceId)) {
totalPlayTime.set(
pieceId,
totalPlayTime.get(pieceId) +
Number.parseInt(item.playTime.M[pieceId].N, 10)
);
} else {
totalPlayTime.set(
pieceId,
Number.parseInt(item.playTime.M[pieceId].N, 10)
);
}
});
}
return totalPlayTime;
}, new Map());
const getFavorites = items =>
items.reduce((favoriteCounts, item) => {
if (item.favorites) {
item.favorites.SS.forEach(pieceId => {
if (favoriteCounts.has(pieceId)) {
favoriteCounts.set(pieceId, favoriteCounts.get(pieceId) + 1);
} else {
favoriteCounts.set(pieceId, 1);
}
});
}
return favoriteCounts;
}, new Map());
const mapToObj = map =>
Array.from(map).reduce((obj, [key, value]) => {
obj[key] = value;
return obj;
}, {});
const putAs = name => obj =>
new Promise((resolve, reject) => {
const params = {
Item: {
name: {
S: name,
},
json: {
S: JSON.stringify(obj),
},
},
TableName: dynamoStatsTableName,
};
dynamodb.putItem(params, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
const pipe = (...fns) => x => fns.reduce((lastVal, fn) => fn(lastVal), x);
const playTime = pipe(
getTotalPlaytime,
mapToObj,
putAs('playTime')
);
const favoriteCounts = pipe(
getFavorites,
mapToObj,
putAs('favorites')
);
scanPromise()
.catch(err => console.error(err))
.then(data => appendItemsAndQueueNext(data))
.then(items => Promise.all([playTime(items), favoriteCounts(items)]))
.then(results => results.forEach(result => console.log(result)))
.catch(err => console.error(err));