132 lines
5.5 KiB
JavaScript
132 lines
5.5 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.recalculateTopPlayed = exports.updateTopPlayedOnHistoryChange = void 0;
|
|
const functions = require("firebase-functions");
|
|
const admin = require("firebase-admin");
|
|
// Initialize Firebase Admin
|
|
admin.initializeApp();
|
|
// Database reference
|
|
const db = admin.database();
|
|
/**
|
|
* Cloud Function that triggers when a song is added to history
|
|
* This function aggregates all history items to create/update the topPlayed collection
|
|
* based on unique combinations of artist and title (not path)
|
|
*/
|
|
exports.updateTopPlayedOnHistoryChange = functions.database
|
|
.ref('/controllers/{controllerName}/history/{historyId}')
|
|
.onCreate(async (snapshot, context) => {
|
|
const { controllerName } = context.params;
|
|
console.log(`TopPlayed update triggered for controller: ${controllerName}`);
|
|
try {
|
|
// Get the controller reference
|
|
const controllerRef = db.ref(`/controllers/${controllerName}`);
|
|
// Get all history items for this controller
|
|
const historySnapshot = await controllerRef.child('history').once('value');
|
|
const historyData = historySnapshot.val();
|
|
if (!historyData) {
|
|
console.log('No history data found, skipping TopPlayed update');
|
|
return;
|
|
}
|
|
// Aggregate history items by path
|
|
const aggregation = {};
|
|
Object.values(historyData).forEach((song) => {
|
|
const historySong = song;
|
|
if (historySong && historySong.path) {
|
|
const path = historySong.path;
|
|
if (aggregation[path]) {
|
|
aggregation[path].count += historySong.count || 1;
|
|
}
|
|
else {
|
|
aggregation[path] = {
|
|
artist: historySong.artist,
|
|
title: historySong.title,
|
|
path: historySong.path,
|
|
count: historySong.count || 1
|
|
};
|
|
}
|
|
}
|
|
});
|
|
// Convert aggregation to array, sort by count (descending), and take top 100
|
|
const sortedSongs = Object.entries(aggregation)
|
|
.map(([, songData]) => ({
|
|
artist: songData.artist,
|
|
title: songData.title,
|
|
path: songData.path,
|
|
count: songData.count
|
|
}))
|
|
.sort((a, b) => b.count - a.count)
|
|
.slice(0, 100);
|
|
// Write as an array so Firebase uses numeric keys
|
|
await controllerRef.child('topPlayed').set(sortedSongs);
|
|
console.log(`Successfully updated TopPlayed for controller ${controllerName} with ${sortedSongs.length} unique songs (by path)`);
|
|
}
|
|
catch (error) {
|
|
console.error('Error updating TopPlayed:', error);
|
|
throw error;
|
|
}
|
|
});
|
|
/**
|
|
* Alternative function that can be called manually to recalculate TopPlayed
|
|
* This is useful for initial setup or data migration
|
|
*/
|
|
exports.recalculateTopPlayed = functions.https.onCall(async (data) => {
|
|
const { controllerName } = data;
|
|
if (!controllerName) {
|
|
throw new functions.https.HttpsError('invalid-argument', 'controllerName is required');
|
|
}
|
|
console.log(`Manual TopPlayed recalculation requested for controller: ${controllerName}`);
|
|
try {
|
|
// Get the controller reference
|
|
const controllerRef = db.ref(`/controllers/${controllerName}`);
|
|
// Get all history items for this controller
|
|
const historySnapshot = await controllerRef.child('history').once('value');
|
|
const historyData = historySnapshot.val();
|
|
if (!historyData) {
|
|
console.log('No history data found, returning empty TopPlayed');
|
|
await controllerRef.child('topPlayed').set({});
|
|
return { success: true, message: 'No history data found, TopPlayed cleared' };
|
|
}
|
|
// Aggregate history items by path
|
|
const aggregation = {};
|
|
Object.values(historyData).forEach((song) => {
|
|
const historySong = song;
|
|
if (historySong && historySong.path) {
|
|
const path = historySong.path;
|
|
if (aggregation[path]) {
|
|
aggregation[path].count += historySong.count || 1;
|
|
}
|
|
else {
|
|
aggregation[path] = {
|
|
artist: historySong.artist,
|
|
title: historySong.title,
|
|
path: historySong.path,
|
|
count: historySong.count || 1
|
|
};
|
|
}
|
|
}
|
|
});
|
|
// Convert aggregation to array, sort by count (descending), and take top 100
|
|
const sortedSongs = Object.entries(aggregation)
|
|
.map(([, songData]) => ({
|
|
artist: songData.artist,
|
|
title: songData.title,
|
|
path: songData.path,
|
|
count: songData.count
|
|
}))
|
|
.sort((a, b) => b.count - a.count)
|
|
.slice(0, 100);
|
|
// Write as an array so Firebase uses numeric keys
|
|
await controllerRef.child('topPlayed').set(sortedSongs);
|
|
console.log(`Successfully recalculated TopPlayed for controller ${controllerName} with ${sortedSongs.length} unique songs (by path)`);
|
|
return {
|
|
success: true,
|
|
message: `TopPlayed recalculated successfully`,
|
|
songCount: sortedSongs.length
|
|
};
|
|
}
|
|
catch (error) {
|
|
console.error('Error recalculating TopPlayed:', error);
|
|
throw new functions.https.HttpsError('internal', 'Failed to recalculate TopPlayed');
|
|
}
|
|
});
|
|
//# sourceMappingURL=index.js.map
|