Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion components/moderation/ScrapeHearing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ const scrapeSingleHearing = httpsCallable<
ScrapeHearingResponse
>(functions, "scrapeSingleHearing")

const scrapeSingleHearingv2 = httpsCallable<
ScrapeHearingRequest,
ScrapeHearingResponse
>(functions, "scrapeSingleHearingv2")

export const ScrapeHearingForm = () => {
const [eventId, setEventId] = useState("")
const [loading, setLoading] = useState(false)
Expand All @@ -39,7 +44,7 @@ export const ScrapeHearingForm = () => {

setLoading(true)
try {
const response = await scrapeSingleHearing({ eventId: parsedEventId })
const response = await scrapeSingleHearingv2({ eventId: parsedEventId })
setResult({
type: "success",
message: `${response.data.message} (ID: ${response.data.hearingId})`
Expand Down
5 changes: 3 additions & 2 deletions functions/src/common.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { FieldValue } from "@google-cloud/firestore"
import axios from "axios"
import { https, logger } from "firebase-functions"
import { CallableRequest } from "firebase-functions/v2/https"
import {
Null,
Nullish,
Expand Down Expand Up @@ -38,7 +39,7 @@ export function checkRequestZod<T extends ZodTypeAny>(

/** Return the authenticated user's id or fail if they are not authenticated. */
export function checkAuth(
context: https.CallableContext,
context: https.CallableContext | CallableRequest,
checkEmailVerification = false
) {
const uid = context.auth?.uid
Expand All @@ -61,7 +62,7 @@ export function checkAuth(
/**
* Checks that the caller is an admin.
*/
export function checkAdmin(context: https.CallableContext) {
export function checkAdmin(context: https.CallableContext | CallableRequest) {
const callerRole = context.auth?.token.role
if (callerRole !== "admin") {
throw fail("permission-denied", "You must be an admin")
Expand Down
1 change: 1 addition & 0 deletions functions/src/events/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from "./scrapeEvents"
export { scrapeSingleHearing } from "./scrapeEvents"
export { scrapeSingleHearingv2 } from "./scrapeEvents"
51 changes: 49 additions & 2 deletions functions/src/events/scrapeEvents.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as functions from "firebase-functions"
import { RuntimeOptions, runWith } from "firebase-functions"
import * as functions from "firebase-functions/v1"
import { RuntimeOptions, runWith } from "firebase-functions/v1"
import { onCall, CallableRequest } from "firebase-functions/v2/https"
import { DateTime } from "luxon"
import { JSDOM } from "jsdom"
import { AssemblyAI } from "assemblyai"
Expand Down Expand Up @@ -476,6 +477,52 @@ export const scrapeSingleHearing = functions
}
})

export const scrapeSingleHearingv2 = onCall(
{ timeoutSeconds: 480, memory: "4GiB", secrets: ["ASSEMBLY_API_KEY"] },
async (request: CallableRequest) => {
// Require admin authentication
// Check how to integrate the new object with these helper functions
checkAuth(request, false)
checkAdmin(request)

const { eventId } = request.data

if (!eventId || typeof eventId !== "number") {
throw new functions.https.HttpsError(
"invalid-argument",
"The function must be called with a valid eventId (number)."
)
}

try {
// Create a temporary scraper instance to reuse the existing logic
const scraper = new HearingScraper()
const hearing = await scraper.getEvent(
{ EventId: eventId },
{ ignoreCutoff: true }
)

// Save the hearing to Firestore
await db.doc(`/events/${hearing.id}`).set(hearing, { merge: true })

console.log(`Successfully scraped hearing ${eventId}`, hearing)

return {
status: "success",
message: `Successfully scraped hearing ${eventId}`,
hearingId: hearing.id
}
} catch (error: any) {
console.error(`Failed to scrape hearing ${eventId}:`, error)
throw new functions.https.HttpsError(
"internal",
`Failed to scrape hearing ${eventId}`,
{ details: error.message }
)
}
}
)

export const scrapeSpecialEvents = new SpecialEventsScraper().function
export const scrapeSessions = new SessionScraper().function
export const scrapeHearings = new HearingScraper().function
3 changes: 2 additions & 1 deletion functions/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ export {
scrapeHearings,
scrapeSessions,
scrapeSpecialEvents,
scrapeSingleHearing
scrapeSingleHearing,
scrapeSingleHearingv2
} from "./events"
export {
syncHearingToSearchIndex,
Expand Down