120 lines
3.9 KiB
JavaScript
120 lines
3.9 KiB
JavaScript
const admin = require('firebase-admin')
|
|
const { FieldValue } = require('firebase-admin/firestore')
|
|
const { onDocumentWritten } = require('firebase-functions/firestore')
|
|
const _ = require('lodash')
|
|
const { refList, db } = require('../index')
|
|
const { SUNO_API_KEY } = require('../config/secrets')
|
|
const { getSunoTimestamps } = require('./lyrics')
|
|
const { deleteFolder } = require('../helpers/firebase')
|
|
const { buildMonthKey } = require('../helpers/stats')
|
|
|
|
const PROJECT_FUNCTION_OPTIONS = {
|
|
document: 'projects/{projectId}',
|
|
secrets: [SUNO_API_KEY],
|
|
}
|
|
|
|
exports.onProjectWritten = onDocumentWritten(PROJECT_FUNCTION_OPTIONS, async (projectSnap) => {
|
|
try {
|
|
const { projectId } = projectSnap.params
|
|
const beforeData = projectSnap?.data?.before?.data() || null
|
|
const afterData = projectSnap?.data?.after?.data() || null
|
|
|
|
if (!afterData) {
|
|
const { userId } = beforeData || {}
|
|
|
|
if (userId) {
|
|
await deleteFolder(`users/${userId}/projects/${projectId}/`)
|
|
}
|
|
|
|
const snapshot = await refList.tasks.where('projectId', '==', projectId).get()
|
|
if (!snapshot.empty) {
|
|
const batch = db.batch()
|
|
snapshot.forEach((doc) => {
|
|
batch.delete(doc.ref)
|
|
})
|
|
await batch.commit()
|
|
}
|
|
|
|
return null
|
|
} else if (!beforeData) {
|
|
//song create
|
|
} else {
|
|
const selectedSongChanged =
|
|
!!afterData?.songUrl &&
|
|
(beforeData?.songUrl !== afterData.songUrl ||
|
|
beforeData?.sunoAudioId !== afterData?.sunoAudioId)
|
|
|
|
if (selectedSongChanged) {
|
|
await getSunoTimestamps(projectId)
|
|
await refList.projects.doc(projectId).update({ hasSong: true })
|
|
}
|
|
|
|
if (!beforeData?.playbackUrl && afterData?.playbackUrl) {
|
|
await refList.projects.doc(projectId).update({ hasPlayback: true })
|
|
}
|
|
}
|
|
|
|
const beforeViews = _.toFinite(_.get(beforeData, 'views', 0))
|
|
const afterViews = _.toFinite(_.get(afterData, 'views', 0))
|
|
const delta = afterViews - beforeViews
|
|
|
|
if (delta > 0) {
|
|
const userIdRaw = _.get(afterData, 'userId', null)
|
|
const userId = _.isString(userIdRaw) && _.trim(userIdRaw).length ? _.trim(userIdRaw) : null
|
|
const now = admin.firestore.Timestamp.now()
|
|
const monthKey = buildMonthKey(now)
|
|
|
|
const statsDocRef = refList.projectStreamStats
|
|
.doc(projectId)
|
|
.collection('monthlyListens')
|
|
.doc(monthKey)
|
|
const projectsRef = refList.projects.doc(projectId)
|
|
|
|
|
|
const totalsDocRef = refList.projectStreamStatsMonthlyTotals.doc(monthKey)
|
|
|
|
await db.runTransaction(async (transaction) => {
|
|
const statsSnapshot = await transaction.get(statsDocRef)
|
|
const totalsSnapshot = await transaction.get(totalsDocRef)
|
|
const updatePayload = {
|
|
projectId,
|
|
userId,
|
|
monthKey,
|
|
updatedAt: now,
|
|
lastStreamAt: now,
|
|
lastDelta: delta,
|
|
streams: FieldValue.increment(delta),
|
|
}
|
|
|
|
const hasFirstStream = statsSnapshot.exists && statsSnapshot.data()?.firstStreamAt
|
|
if (!hasFirstStream) {
|
|
updatePayload.firstStreamAt = now
|
|
}
|
|
|
|
transaction.set(statsDocRef, updatePayload, { merge: true })
|
|
transaction.set(projectsRef, { monthViews: FieldValue.increment(delta) }, { merge: true })
|
|
|
|
const totalsUpdatePayload = {
|
|
monthKey,
|
|
updatedAt: now,
|
|
lastStreamAt: now,
|
|
lastDelta: delta,
|
|
totalStreams: FieldValue.increment(delta),
|
|
}
|
|
const totalsHasFirstStream = totalsSnapshot.exists && totalsSnapshot.data()?.firstStreamAt
|
|
if (!totalsHasFirstStream) {
|
|
totalsUpdatePayload.firstStreamAt = now
|
|
}
|
|
transaction.set(totalsDocRef, totalsUpdatePayload, { merge: true })
|
|
})
|
|
}
|
|
|
|
return null
|
|
} catch (error) {
|
|
console.log('onProjectViewsIncrement error', {
|
|
message: error?.message || String(error || ''),
|
|
})
|
|
return null
|
|
}
|
|
})
|