Skip to content

Commit

Permalink
#74 creating event speakers during crawl
Browse files Browse the repository at this point in the history
  • Loading branch information
fcamblor committed Nov 8, 2024
1 parent 6a37752 commit 7cb859c
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 28 deletions.
40 changes: 22 additions & 18 deletions cloud/functions/src/crawlers/crawl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { marked } from 'marked'
import {
resolvedEventFirestorePath,
} from "../../../../shared/utilities/event-utils";
import {createAllSpeakers} from "../functions/firestore/services/event-utils";

export type CrawlerKind<ZOD_TYPE extends z.ZodType> = {
crawlerImpl: (eventId: string, crawlerDescriptor: z.infer<ZOD_TYPE>, criteria: { dayIds?: string[]|undefined }) => Promise<FullEvent>,
Expand Down Expand Up @@ -301,27 +302,27 @@ const saveEvent = async function (event: FullEvent, crawlerDescriptor: z.infer<t
websiteUrl,
} as const

const [spaceToken, spaceContext, listableEvent]: [string|undefined, string, ListableEvent] =
const [maybeSpaceToken, spaceContext, listableEvent]: [string|undefined, string, ListableEvent] =
crawlerDescriptor.visibility === 'public'
? [undefined, 'public space', { ...baseListableEvent, visibility: 'public' }]
: [crawlerDescriptor.spaceToken, `private space: ${crawlerDescriptor.spaceToken}`, {...baseListableEvent, visibility: 'private', spaceToken: crawlerDescriptor.spaceToken}]

if(spaceToken) {
const space = await db.doc(`/spaces/${spaceToken}`).get()
if(maybeSpaceToken) {
const space = await db.doc(`/spaces/${maybeSpaceToken}`).get()
// Creating (dummy) space entry so that we can list spaces serverside (we can't list ids from empty docs)
if(!space.exists) {
space.ref.set({ spaceToken });
space.ref.set({ spaceToken: maybeSpaceToken });
}
}

await db.doc(resolvedEventFirestorePath(event.id, spaceToken)).set(listableEvent)
await db.doc(resolvedEventFirestorePath(event.id, maybeSpaceToken)).set(listableEvent)

const talksStatsAllInOneDoc = await db.doc(`${resolvedEventFirestorePath(event.id, spaceToken)}/talksStats-allInOne/self`).get()
const talksStatsAllInOneDoc = await db.doc(`${resolvedEventFirestorePath(event.id, maybeSpaceToken)}/talksStats-allInOne/self`).get()
if(!talksStatsAllInOneDoc.exists) {
await db.doc(`${resolvedEventFirestorePath(event.id, spaceToken)}/talksStats-allInOne/self`).set({})
await db.doc(`${resolvedEventFirestorePath(event.id, maybeSpaceToken)}/talksStats-allInOne/self`).set({})
}

const firestoreEvent = db.doc(`${resolvedEventFirestorePath(event.id, spaceToken)}`);
const firestoreEvent = db.doc(`${resolvedEventFirestorePath(event.id, maybeSpaceToken)}`);
const organizerSpaceEntries = await firestoreEvent
.collection('organizer-space')
.listDocuments();
Expand All @@ -337,9 +338,9 @@ const saveEvent = async function (event: FullEvent, crawlerDescriptor: z.infer<t
await firestoreEvent.collection('organizer-space').doc(organizerSecretToken).set(organizerSpaceContent)

await Promise.all(event.daySchedules.map(async daySchedule => {
const dailyRating = await db.doc(`${resolvedEventFirestorePath(event.id, spaceToken)}/organizer-space/${organizerSecretToken}/daily-ratings/${daySchedule.day}`).get()
const dailyRating = await db.doc(`${resolvedEventFirestorePath(event.id, maybeSpaceToken)}/organizer-space/${organizerSecretToken}/daily-ratings/${daySchedule.day}`).get()
if(!dailyRating.exists) {
await db.doc(`${resolvedEventFirestorePath(event.id, spaceToken)}/organizer-space/${organizerSecretToken}/daily-ratings/${daySchedule.day}`).set({});
await db.doc(`${resolvedEventFirestorePath(event.id, maybeSpaceToken)}/organizer-space/${organizerSecretToken}/daily-ratings/${daySchedule.day}`).set({});
}
}))

Expand All @@ -352,11 +353,11 @@ const saveEvent = async function (event: FullEvent, crawlerDescriptor: z.infer<t
throw new Error(`More than 1 organizer-space entries detected (${organizerSpaceEntries.length}) for event ${event.id} (${spaceContext})`);
})

const talkFeedbacksDoc = await db.collection(`${resolvedEventFirestorePath(event.id, spaceToken)}/organizer-space/${organizerSecretToken}/ratings`).listDocuments()
const talkFeedbacksDoc = await db.collection(`${resolvedEventFirestorePath(event.id, maybeSpaceToken)}/organizer-space/${organizerSecretToken}/ratings`).listDocuments()
const ratingsTalkIds = talkFeedbacksDoc.map(doc => doc.id);
await Promise.all([
...event.daySchedules.map(async daySchedule => {
const dailyRatings = (await db.doc(`${resolvedEventFirestorePath(event.id, spaceToken)}/organizer-space/${organizerSecretToken}/daily-ratings/${daySchedule.day}`).get()).data() as Record<string, object>;
const dailyRatings = (await db.doc(`${resolvedEventFirestorePath(event.id, maybeSpaceToken)}/organizer-space/${organizerSecretToken}/daily-ratings/${daySchedule.day}`).get()).data() as Record<string, object>;
const talkIds = daySchedule.timeSlots.flatMap(ts => ts.type === 'talks' ? ts.talks.map(t => t.id) : [])
const dailyRatingsToUpdate = talkIds.reduce((dailyRatingsToUpdate, talkId) => {
if(!dailyRatings[talkId]) {
Expand All @@ -366,12 +367,12 @@ const saveEvent = async function (event: FullEvent, crawlerDescriptor: z.infer<t
}, {} as Record<string, object>)

if(Object.keys(dailyRatingsToUpdate).length) {
await db.doc(`${resolvedEventFirestorePath(event.id, spaceToken)}/organizer-space/${organizerSecretToken}/daily-ratings/${daySchedule.day}`).update(dailyRatingsToUpdate);
await db.doc(`${resolvedEventFirestorePath(event.id, maybeSpaceToken)}/organizer-space/${organizerSecretToken}/daily-ratings/${daySchedule.day}`).update(dailyRatingsToUpdate);
}
}),
...event.talks.map(async talk => {
if(!ratingsTalkIds.includes(talk.id)) {
await db.doc(`${resolvedEventFirestorePath(event.id, spaceToken)}/organizer-space/${organizerSecretToken}/ratings/${talk.id}`).create({})
await db.doc(`${resolvedEventFirestorePath(event.id, maybeSpaceToken)}/organizer-space/${organizerSecretToken}/ratings/${talk.id}`).create({})
}
})
])
Expand All @@ -386,7 +387,7 @@ const saveEvent = async function (event: FullEvent, crawlerDescriptor: z.infer<t
}
}))

const talksCollectionRefBeforeUpdate = (await db.collection(`/${resolvedEventFirestorePath(event.id, spaceToken)}/talks`).listDocuments()) || []
const talksCollectionRefBeforeUpdate = (await db.collection(`/${resolvedEventFirestorePath(event.id, maybeSpaceToken)}/talks`).listDocuments()) || []
const talkIdsHashBeforeUpdate = talksCollectionRefBeforeUpdate.map(talk => talk.id).sort().join(",")

await Promise.all(event.talks.map(async talk => {
Expand Down Expand Up @@ -427,13 +428,16 @@ const saveEvent = async function (event: FullEvent, crawlerDescriptor: z.infer<t
}
}));

const talksCollectionRefAfterUpdate = (await db.collection(`/${resolvedEventFirestorePath(event.id, spaceToken)}/talks`).listDocuments()) || []
const talksCollectionRefAfterUpdate = (await db.collection(`/${resolvedEventFirestorePath(event.id, maybeSpaceToken)}/talks`).listDocuments()) || []
const talkIdsHashAfterUpdate = talksCollectionRefAfterUpdate.map(talk => talk.id).sort().join(",")

if(talkIdsHashBeforeUpdate !== talkIdsHashAfterUpdate) {
await eventLastUpdateRefreshed(spaceToken, event.id, ['talkListUpdated']);
await eventLastUpdateRefreshed(maybeSpaceToken, event.id, ['talkListUpdated']);
}

const { createdSpeakers } = await createAllSpeakers(event.talks, maybeSpaceToken, event.id);
console.log(`Created ${createdSpeakers.length} speakers !`)

try {
// TODO: Remove me once watch later will be properly implemented !
event.conferenceDescriptor.features.remindMeOnceVideosAreAvailableEnabled = false;
Expand All @@ -457,7 +461,7 @@ const saveEvent = async function (event: FullEvent, crawlerDescriptor: z.infer<t
error(`Error while storing event's organizer-space content`)
}

await ensureRoomsStatsFilledFor(spaceToken, event.id)
await ensureRoomsStatsFilledFor(maybeSpaceToken, event.id)
}

type ContentTransformation = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {getAllEventsDocs} from "../services/event-utils";
import {createAllSpeakers, getAllEventsDocs} from "../services/event-utils";
import {db} from "../../../firebase";
import {getEventTalks} from "../services/talk-utils";
import {detailedTalksToSpeakersLineup} from "../../../models/Event";
Expand All @@ -24,15 +24,9 @@ export async function introduceEventSpeakersAndFixTalkUndefinedTags(): Promise<"
}
}))

const lineupSpeakers = detailedTalksToSpeakersLineup(migratedEventTalks);

const eventSpeakersColl = db.collection(`${eventDoc.ref.path}/speakers`)
const existingSpeakerDocs = await eventSpeakersColl.listDocuments()

// delete all then re-create all
await Promise.all(existingSpeakerDocs.map(speakerDoc => speakerDoc.delete()))
await Promise.all(lineupSpeakers.map(lineupSpeaker => db.doc(`${eventDoc.ref.path}/speakers/${lineupSpeaker.id}`).set(lineupSpeaker)))
console.log(`${lineupSpeakers.length} event speakers created for event id ${eventDoc.id}`)
const event = eventDoc.data();
const { createdSpeakers } = await createAllSpeakers(eventTalks, event.visibility === 'private' ? event.spaceToken : undefined, event.id);
console.log(`${createdSpeakers.length} event speakers created for event id ${eventDoc.id}`)
} catch (err) {
console.error(`Error during Event speaker creation for ${eventDoc.id}: ${err}`)
}
Expand Down
17 changes: 17 additions & 0 deletions cloud/functions/src/functions/firestore/services/event-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import DocumentSnapshot = firestore.DocumentSnapshot;
import {getAllSpaceIds} from "./space-utils";
import {resolvedEventFirestorePath, resolvedEventsFirestorePath} from "../../../../../../shared/utilities/event-utils";
import {AllInOneTalkStats} from "../../../../../../shared/event-stats";
import {getEventTalks} from "./talk-utils";
import {detailedTalksToSpeakersLineup} from "../../../models/Event";
import {DetailedTalk} from "../../../../../../shared/daily-schedule.firestore";


export async function getAllEventsDocs(opts: { includePrivateSpaces: boolean } = { includePrivateSpaces: false }) {
Expand Down Expand Up @@ -41,3 +44,17 @@ export async function getAllEventsWithTalks(opts: { includePrivateSpaces: boolea
return { event: eventDoc.data(), allInOneTalkStats: allInOneTalkStats || {} };
}))
}

export async function createAllSpeakers(eventTalks: DetailedTalk[], maybeSpaceToken: string|undefined, eventId: string) {
const lineupSpeakers = detailedTalksToSpeakersLineup(eventTalks);

const eventRootPath = resolvedEventFirestorePath(eventId, maybeSpaceToken);
const eventSpeakersColl = db.collection(`${eventRootPath}/speakers`)
const existingSpeakerDocs = await eventSpeakersColl.listDocuments()

// delete all then re-create all
await Promise.all(existingSpeakerDocs.map(speakerDoc => speakerDoc.delete()))
await Promise.all(lineupSpeakers.map(lineupSpeaker => db.doc(`${eventRootPath}/speakers/${lineupSpeaker.id}`).set(lineupSpeaker)))

return { createdSpeakers: lineupSpeakers }
}

0 comments on commit 7cb859c

Please sign in to comment.