diff --git a/src/lib/gcloud.ts b/src/lib/gcloud.ts index 7ad995d2..e4020f53 100644 --- a/src/lib/gcloud.ts +++ b/src/lib/gcloud.ts @@ -30,6 +30,22 @@ export async function getGoogleAuth( }); } +export async function trashResource({ + id, + service, +}: { + id: string; + service: google.drive_v3.Drive; +}): Promise { + await service.files.update({ + fileId: id, + requestBody: { + trashed: true, + }, + supportsAllDrives: true, + }); +} + // Returns the id of the resource async function findOrCreateResource({ mimeType, @@ -88,7 +104,7 @@ async function findOrCreateResource({ return id; } -async function getOrCreateFolder({ +export async function getOrCreateFolder({ dir, service, parentFolderId, @@ -196,29 +212,41 @@ async function getOrCreateSheets({ }); } -// Returns the URL of the Drive Folder -export async function getOrCreateDriveFolder({ - userAuthId, - dir, - rootFolderId, +export async function listResourceChildren({ + folderId, + mimeType, + mimeTypeOp = "=", + service, }: { - userAuthId: string; - dir: string; - rootFolderId: string; -}): Promise { - const auth = await getGoogleAuth(userAuthId); - const service = new google.drive_v3.Drive({ - auth, + folderId: string; + mimeType: string; + mimeTypeOp?: string; + service: google.drive_v3.Drive; +}): Promise { + const { data } = await service.files.list({ + q: `trashed=false and '${folderId}' in parents and mimeType ${mimeTypeOp} '${mimeType}'`, + includeItemsFromAllDrives: true, + supportsAllDrives: true, }); - const id = await getOrCreateFolder({ - dir, + return data.files || []; +} + +export async function listFolderChildren({ + folderId, + service, +}: { + folderId: string; + service: google.drive_v3.Drive; +}): Promise { + return await listResourceChildren({ + folderId, + mimeType: FOLDER_MIME_TYPE, service, - parentFolderId: rootFolderId, }); - return `https://drive.google.com/drive/folders/${id}`; } -async function listFolderChildren({ +// Returns the URL of the Drive Folder +export async function getOrCreateDriveFolder({ userAuthId, dir, rootFolderId, @@ -226,7 +254,7 @@ async function listFolderChildren({ userAuthId: string; dir: string; rootFolderId: string; -}): Promise { +}): Promise { const auth = await getGoogleAuth(userAuthId); const service = new google.drive_v3.Drive({ auth, @@ -236,12 +264,7 @@ async function listFolderChildren({ service, parentFolderId: rootFolderId, }); - const { data } = await service.files.list({ - q: `trashed=false and '${id}' in parents and mimeType = '${FOLDER_MIME_TYPE}'`, - includeItemsFromAllDrives: true, - supportsAllDrives: true, - }); - return data.files || []; + return `https://drive.google.com/drive/folders/${id}`; } export async function exportParticipants({ @@ -284,10 +307,15 @@ export async function exportParticipants({ // Retrieve data const participants = await findParticipants(ofmi); - const driveFolders = await listFolderChildren({ + const participantsFolderId = await getOrCreateFolder({ dir: path.join(friendlyOfmiName(ofmi.edition), "Assets", "Participants"), - userAuthId, - rootFolderId: config.GDRIVE_OFMI_ROOT_FOLDER, + service, + parentFolderId: config.GDRIVE_OFMI_ROOT_FOLDER, + }); + + const driveFolders = await listFolderChildren({ + folderId: participantsFolderId, + service, }); const createData = (role: ParticipationRole): string => { diff --git a/src/lib/oauth.ts b/src/lib/oauth.ts index 09639504..8f6c498e 100644 --- a/src/lib/oauth.ts +++ b/src/lib/oauth.ts @@ -37,7 +37,7 @@ export class GCloud { redirect_uri: GCloud.REDIRECT_URI, response_type: "code", scope: - "https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/drive.metadata.readonly", + "https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/drive.metadata.readonly", access_type: "offline", }, ).toString()}`; diff --git a/src/scripts/removeMedia.ts b/src/scripts/removeMedia.ts new file mode 100644 index 00000000..d2086261 --- /dev/null +++ b/src/scripts/removeMedia.ts @@ -0,0 +1,96 @@ +import path from "path"; +import * as google from "googleapis"; +import config from "@/config/default"; +import { findMostRecentOfmi, friendlyOfmiName } from "@/lib/ofmi"; +import { + listFolderChildren, + getGoogleAuth, + listResourceChildren, + getOrCreateFolder, + FOLDER_MIME_TYPE, + // trashResource, +} from "@/lib/gcloud"; +import { ofmiUserAuthId } from "@/lib/ofmiUserImpersonator"; + +async function removeMediaRec({ + folderId, + rootFolderId, + service, +}: { + folderId: string; + rootFolderId: string; + service: google.drive_v3.Drive; +}): Promise { + const videoFiles = await listResourceChildren({ + folderId, + service, + mimeType: "video/", + mimeTypeOp: "contains", + }); + for (const file of videoFiles) { + if (typeof file.id === "string" && typeof file.name === "string") { + console.log(`Deleting file: ${file.name} (${file.id}): ${file.mimeType}`); + // Uncomment the following line to actually trash the file + // await trashResource({ id: file.id, service }); + } + } + + const driveFolders = await listFolderChildren({ + folderId, + service, + }); + for (const folder of driveFolders) { + if (typeof folder.id === "string") { + await removeMediaRec({ + folderId: folder.id, + rootFolderId, + service, + }); + } + } +} + +export async function removeMedia(): Promise { + const ofmi = await findMostRecentOfmi(); + const userAuthId = await ofmiUserAuthId(); + const service = new google.drive_v3.Drive({ + auth: await getGoogleAuth(userAuthId), + }); + const participantsFolderId = await getOrCreateFolder({ + dir: path.join(friendlyOfmiName(ofmi.edition), "Assets", "Participants"), + service, + parentFolderId: config.GDRIVE_OFMI_ROOT_FOLDER, + }); + + // Extrañamente no sirve hacer directo `removeMediaRec` desde aquí. + // Tiene cara de ser un bug al hacer la query de Google API + // Buscamos los folders de participantes a mano. + const { data } = await service.files.list({ + q: `trashed=false and mimeType = '${FOLDER_MIME_TYPE}'`, + fields: "files(id, name, parents)", + includeItemsFromAllDrives: true, + supportsAllDrives: true, + }); + await data.files + ?.filter((file) => file.parents?.includes(participantsFolderId)) + .forEach(async (file) => { + if (typeof file.id === "string") { + console.log( + `Iterating folder: ${file.name} (${file.id}): ${file.mimeType}`, + ); + await removeMediaRec({ + folderId: file.id, + rootFolderId: config.GDRIVE_OFMI_ROOT_FOLDER, + service, + }); + } + }); +} + +removeMedia() + .then(() => { + console.log("Media removed successfully."); + }) + .catch((e) => { + console.error("Error removing media:", e); + });