mirror of
https://github.com/Nezumi-2711/next-gdrive-index.git
synced 2026-09-22 13:38:38 +00:00
Merge pull request #4 from loadingthedev/support-shared-drive
Add support for Shared drive
This commit is contained in:
@@ -37,10 +37,12 @@ export async function GET(
|
||||
const _fileMeta = gdrive.files.get({
|
||||
fileId: decryptData(data.id),
|
||||
fields: "id, name, size, mimeType, webContentLink",
|
||||
supportsAllDrives: gIndexConfig.apiConfig.isTeamDrive,
|
||||
});
|
||||
const _fileContent = gdrive.files.get(
|
||||
{
|
||||
fileId: decryptData(data.id),
|
||||
supportsAllDrives: gIndexConfig.apiConfig.isTeamDrive,
|
||||
alt: "media",
|
||||
},
|
||||
{ responseType: "stream" },
|
||||
|
||||
@@ -3,90 +3,58 @@ import { drive_v3 } from "googleapis";
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
import getSearchParams from "utils/apiHelper/getSearchParams";
|
||||
import {
|
||||
decryptData,
|
||||
encryptData,
|
||||
} from "utils/encryptionHelper/hash";
|
||||
import { decryptData, encryptData } from "utils/encryptionHelper/hash";
|
||||
import ExtendedError from "utils/extendedError";
|
||||
import { gdriveFilesList } from "utils/gdrive";
|
||||
import gdrive from "utils/gdriveInstance";
|
||||
|
||||
import { IGDriveFiles } from "types/api/files";
|
||||
import {
|
||||
APIGetFileResponse,
|
||||
ErrorResponse,
|
||||
} from "types/api/response";
|
||||
import { APIGetFileResponse, ErrorResponse } from "types/api/response";
|
||||
|
||||
function isHiddenFile(name: string) {
|
||||
return gIndexConfig.apiConfig.hiddenFiles.find((item) =>
|
||||
name.startsWith(item),
|
||||
)
|
||||
? true
|
||||
: false;
|
||||
return gIndexConfig.apiConfig.hiddenFiles.find((item) => name.startsWith(item)) ? true : false;
|
||||
}
|
||||
function generateFileObject(
|
||||
data: drive_v3.Schema$File,
|
||||
): IGDriveFiles {
|
||||
function generateFileObject(data: drive_v3.Schema$File): IGDriveFiles {
|
||||
return {
|
||||
mimeType: data.mimeType as string,
|
||||
fileExtension: (data.fileExtension as string) ?? null,
|
||||
encryptedId: encryptData(data.id as string),
|
||||
name: data.name as string,
|
||||
trashed: (data.trashed as boolean) ?? false,
|
||||
modifiedTime: new Date(
|
||||
data.modifiedTime as string,
|
||||
).toLocaleDateString(),
|
||||
encryptedWebContentLink: encryptData(
|
||||
data.webContentLink as string,
|
||||
),
|
||||
modifiedTime: new Date(data.modifiedTime as string).toLocaleDateString(),
|
||||
encryptedWebContentLink: encryptData(data.webContentLink as string),
|
||||
size: Number(data.size ?? 0),
|
||||
thumbnailLink: (data.thumbnailLink as string) ?? null,
|
||||
imageMediaMetadata: data.imageMediaMetadata
|
||||
? {
|
||||
width: Number(data.imageMediaMetadata.width ?? 0),
|
||||
height: Number(
|
||||
data.imageMediaMetadata.height ?? 0,
|
||||
),
|
||||
rotation: Number(
|
||||
data.imageMediaMetadata.rotation ?? 0,
|
||||
),
|
||||
height: Number(data.imageMediaMetadata.height ?? 0),
|
||||
rotation: Number(data.imageMediaMetadata.rotation ?? 0),
|
||||
}
|
||||
: null,
|
||||
videoMediaMetadata: data.videoMediaMetadata
|
||||
? {
|
||||
width: Number(data.videoMediaMetadata.width ?? 0),
|
||||
height: Number(
|
||||
data.videoMediaMetadata.height ?? 0,
|
||||
),
|
||||
durationMillis: Number(
|
||||
data.videoMediaMetadata.durationMillis ?? 0,
|
||||
),
|
||||
height: Number(data.videoMediaMetadata.height ?? 0),
|
||||
durationMillis: Number(data.videoMediaMetadata.durationMillis ?? 0),
|
||||
}
|
||||
: null,
|
||||
};
|
||||
}
|
||||
function generateFolderObject(
|
||||
data: drive_v3.Schema$File,
|
||||
): IGDriveFiles {
|
||||
function generateFolderObject(data: drive_v3.Schema$File): IGDriveFiles {
|
||||
return {
|
||||
mimeType: data.mimeType as string,
|
||||
encryptedId: encryptData(data.id as string),
|
||||
name: data.name as string,
|
||||
trashed: (data.trashed as boolean) ?? false,
|
||||
modifiedTime: new Date(
|
||||
data.modifiedTime as string,
|
||||
).toLocaleDateString(),
|
||||
modifiedTime: new Date(data.modifiedTime as string).toLocaleDateString(),
|
||||
};
|
||||
}
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
const reqStart = Date.now();
|
||||
try {
|
||||
const { encryptedId, isFile, pageToken } =
|
||||
getSearchParams(request.url, [
|
||||
"encryptedId",
|
||||
"isFile",
|
||||
"pageToken",
|
||||
]);
|
||||
const { encryptedId, isFile, pageToken } = getSearchParams(request.url, ["encryptedId", "isFile", "pageToken"]);
|
||||
|
||||
let data: {
|
||||
file: IGDriveFiles | null;
|
||||
@@ -103,54 +71,37 @@ export async function GET(request: NextRequest) {
|
||||
const fileContent = await gdrive.files.get({
|
||||
fileId: decryptData(encryptedId),
|
||||
fields: gIndexConfig.apiConfig.defaultField,
|
||||
supportsAllDrives: gIndexConfig.apiConfig.isTeamDrive,
|
||||
});
|
||||
if (isHiddenFile(fileContent.data.name as string))
|
||||
throw new ExtendedError(
|
||||
"File not found",
|
||||
404,
|
||||
"File you are looking for is not found",
|
||||
);
|
||||
throw new ExtendedError("File not found", 404, "File you are looking for is not found");
|
||||
|
||||
const payload: IGDriveFiles = generateFileObject(
|
||||
fileContent.data,
|
||||
);
|
||||
const payload: IGDriveFiles = generateFileObject(fileContent.data);
|
||||
data.file = payload;
|
||||
} else {
|
||||
const filterName = gIndexConfig.apiConfig.hiddenFiles
|
||||
.map((item) => `name != '${item}'`)
|
||||
.join(" and ");
|
||||
const filterName = gIndexConfig.apiConfig.hiddenFiles.map((item) => `name != '${item}'`).join(" and ");
|
||||
const query: string[] = [
|
||||
...gIndexConfig.apiConfig.defaultQuery,
|
||||
`'${
|
||||
encryptedId
|
||||
? decryptData(encryptedId)
|
||||
: gIndexConfig.apiConfig.rootFolder
|
||||
}' in parents`,
|
||||
`'${encryptedId ? decryptData(encryptedId) : gIndexConfig.apiConfig.rootFolder}' in parents`,
|
||||
`${filterName}`,
|
||||
];
|
||||
const folderContent = await gdrive.files.list({
|
||||
const folderContent = await gdriveFilesList({
|
||||
q: query.join(" and "),
|
||||
fields: `files(${gIndexConfig.apiConfig.defaultField}), nextPageToken`,
|
||||
orderBy: gIndexConfig.apiConfig.defaultOrder,
|
||||
pageSize: gIndexConfig.apiConfig.itemsPerPage,
|
||||
pageToken: pageToken ?? undefined,
|
||||
supportsAllDrives: gIndexConfig.apiConfig.isTeamDrive,
|
||||
includeItemsFromAllDrives: gIndexConfig.apiConfig.isTeamDrive,
|
||||
});
|
||||
|
||||
const listFolders: IGDriveFiles[] =
|
||||
folderContent.data.files
|
||||
?.filter(
|
||||
(item) =>
|
||||
item.mimeType ===
|
||||
"application/vnd.google-apps.folder",
|
||||
)
|
||||
?.filter((item) => item.mimeType === "application/vnd.google-apps.folder")
|
||||
.map((item) => generateFolderObject(item)) ?? [];
|
||||
const listFiles: IGDriveFiles[] =
|
||||
folderContent.data.files
|
||||
?.filter(
|
||||
(item) =>
|
||||
item.mimeType !==
|
||||
"application/vnd.google-apps.folder",
|
||||
)
|
||||
?.filter((item) => item.mimeType !== "application/vnd.google-apps.folder")
|
||||
.map((item) => generateFileObject(item)) ?? [];
|
||||
|
||||
data = {
|
||||
|
||||
@@ -2,52 +2,32 @@ import gIndexConfig from "config";
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
import getSearchParams from "utils/apiHelper/getSearchParams";
|
||||
import {
|
||||
decryptData,
|
||||
encryptData,
|
||||
} from "utils/encryptionHelper/hash";
|
||||
import { decryptData, encryptData } from "utils/encryptionHelper/hash";
|
||||
import ExtendedError from "utils/extendedError";
|
||||
import { gdriveFilesList } from "utils/gdrive";
|
||||
import gdrive from "utils/gdriveInstance";
|
||||
|
||||
import {
|
||||
APIGetPasswordResponse,
|
||||
ErrorResponse,
|
||||
} from "types/api/response";
|
||||
import { APIGetPasswordResponse, ErrorResponse } from "types/api/response";
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
const reqStart = Date.now();
|
||||
|
||||
try {
|
||||
const { path } = getSearchParams(request.url, ["path"]);
|
||||
if (!path)
|
||||
throw new ExtendedError(
|
||||
"Path is required",
|
||||
400,
|
||||
"Can't find path in query, please check your query",
|
||||
);
|
||||
const mappedPath: Record<
|
||||
"name" | "id" | "mimeType",
|
||||
string
|
||||
>[] = JSON.parse(decryptData(path));
|
||||
const passwordParents = mappedPath.map(
|
||||
(path) => `'${decryptData(path.id)}' in parents`,
|
||||
);
|
||||
if (!path) throw new ExtendedError("Path is required", 400, "Can't find path in query, please check your query");
|
||||
const mappedPath: Record<"name" | "id" | "mimeType", string>[] = JSON.parse(decryptData(path));
|
||||
const passwordParents = mappedPath.map((path) => `'${decryptData(path.id)}' in parents`);
|
||||
const query: string[] = [
|
||||
"trashed = false",
|
||||
`name = '${
|
||||
gIndexConfig.apiConfig.specialFile.password
|
||||
}' and (${passwordParents.join(" or ")})`,
|
||||
`name = '${gIndexConfig.apiConfig.specialFile.password}' and (${passwordParents.join(" or ")})`,
|
||||
];
|
||||
const passwordData = await gdrive.files.list({
|
||||
const passwordData = await gdriveFilesList({
|
||||
q: query.join(" and "),
|
||||
fields: "files(id, name, parents)",
|
||||
});
|
||||
|
||||
const protectedPaths = mappedPath.map((path) => {
|
||||
const isPasswordExist = passwordData.data.files?.find(
|
||||
(file) =>
|
||||
file.parents?.[0] === decryptData(path.id),
|
||||
);
|
||||
const isPasswordExist = passwordData.data.files?.find((file) => file.parents?.[0] === decryptData(path.id));
|
||||
if (isPasswordExist)
|
||||
return {
|
||||
name: path.name,
|
||||
@@ -67,6 +47,7 @@ export async function GET(request: NextRequest) {
|
||||
{
|
||||
fileId: path.passwordId as string,
|
||||
alt: "media",
|
||||
supportsAllDrives: gIndexConfig.apiConfig.isTeamDrive,
|
||||
},
|
||||
{ responseType: "text" },
|
||||
)
|
||||
@@ -77,21 +58,14 @@ export async function GET(request: NextRequest) {
|
||||
);
|
||||
});
|
||||
|
||||
const passwordContent = await Promise.all(
|
||||
_passwordContent,
|
||||
);
|
||||
const passwordContent = await Promise.all(_passwordContent);
|
||||
|
||||
let prevPath = [""];
|
||||
let password: Record<
|
||||
"relativePath" | "password",
|
||||
string
|
||||
>[] = [];
|
||||
let password: Record<"relativePath" | "password", string>[] = [];
|
||||
|
||||
mappedPath.forEach((path) => {
|
||||
prevPath.push(path.name);
|
||||
const isPasswordExist = passwordContent.find(
|
||||
(password) => password.path === path.name,
|
||||
);
|
||||
const isPasswordExist = passwordContent.find((password) => password.path === path.name);
|
||||
if (isPasswordExist) {
|
||||
password.push({
|
||||
relativePath: prevPath.join("/"),
|
||||
|
||||
@@ -3,29 +3,21 @@ import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
import getSearchParams from "utils/apiHelper/getSearchParams";
|
||||
import { decryptData } from "utils/encryptionHelper/hash";
|
||||
import { gdriveFilesList } from "utils/gdrive";
|
||||
import gdrive from "utils/gdriveInstance";
|
||||
|
||||
import {
|
||||
APIGetReadmeResponse,
|
||||
ErrorResponse,
|
||||
} from "types/api/response";
|
||||
import { APIGetReadmeResponse, ErrorResponse } from "types/api/response";
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
const reqStart = Date.now();
|
||||
try {
|
||||
const { encryptedId } = getSearchParams(request.url, [
|
||||
"encryptedId",
|
||||
]);
|
||||
const { encryptedId } = getSearchParams(request.url, ["encryptedId"]);
|
||||
|
||||
const query: string[] = [
|
||||
...gIndexConfig.apiConfig.defaultQuery,
|
||||
`'${
|
||||
encryptedId
|
||||
? decryptData(encryptedId)
|
||||
: gIndexConfig.apiConfig.rootFolder
|
||||
}' in parents`,
|
||||
`'${encryptedId ? decryptData(encryptedId) : gIndexConfig.apiConfig.rootFolder}' in parents`,
|
||||
];
|
||||
const folderContent = await gdrive.files.list({
|
||||
const folderContent = await gdriveFilesList({
|
||||
q: query.join(" and "),
|
||||
fields: `files(${gIndexConfig.apiConfig.defaultField}), nextPageToken`,
|
||||
orderBy: gIndexConfig.apiConfig.defaultOrder,
|
||||
@@ -33,9 +25,7 @@ export async function GET(request: NextRequest) {
|
||||
pageToken: undefined,
|
||||
});
|
||||
const isReadmeExist = folderContent.data.files?.find(
|
||||
(file) =>
|
||||
file.name ===
|
||||
gIndexConfig.apiConfig.specialFile.readme,
|
||||
(file) => file.name === gIndexConfig.apiConfig.specialFile.readme,
|
||||
);
|
||||
let data: string | null = null;
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ export async function GET(request: NextRequest, { params }: { params: { encrypte
|
||||
const fileContent = await gdrive.files.get({
|
||||
fileId: lastId,
|
||||
fields: "id, name, mimeType, parents",
|
||||
supportsAllDrives: gIndexConfig.apiConfig.isTeamDrive,
|
||||
});
|
||||
if (fileContent) {
|
||||
path.push(fileContent.data.name as string);
|
||||
@@ -29,6 +30,7 @@ export async function GET(request: NextRequest, { params }: { params: { encrypte
|
||||
const folderContent = await gdrive.files.get({
|
||||
fileId: lastId,
|
||||
fields: "id, name, mimeType, parents",
|
||||
supportsAllDrives: gIndexConfig.apiConfig.isTeamDrive,
|
||||
});
|
||||
if (folderContent.data.id === gIndexConfig.apiConfig.rootFolder) {
|
||||
lastId = "";
|
||||
|
||||
@@ -4,7 +4,7 @@ import { NextRequest, NextResponse } from "next/server";
|
||||
import getSearchParams from "utils/apiHelper/getSearchParams";
|
||||
import { encryptData } from "utils/encryptionHelper/hash";
|
||||
import ExtendedError from "utils/extendedError";
|
||||
import gdrive from "utils/gdriveInstance";
|
||||
import { gdriveFilesList } from "utils/gdrive";
|
||||
|
||||
import { IGDriveFiles } from "types/api/files";
|
||||
import { APISearchResponse, ErrorResponse } from "types/api/response";
|
||||
@@ -15,7 +15,7 @@ export async function GET(request: NextRequest) {
|
||||
const { query } = getSearchParams(request.url, ["query"]);
|
||||
if (!query) throw new ExtendedError("Missing query", 400, "Search query is required");
|
||||
|
||||
const searchFiles = await gdrive.files.list({
|
||||
const searchFiles = await gdriveFilesList({
|
||||
q: [...gIndexConfig.apiConfig.defaultQuery, `name contains '${query}'`].join(" and "),
|
||||
fields: `files(${gIndexConfig.apiConfig.defaultField}), nextPageToken`,
|
||||
orderBy: "name_natural desc",
|
||||
|
||||
@@ -40,7 +40,7 @@ const config: gIndexConfig = {
|
||||
* Then, copy the folder id and paste it here
|
||||
*/
|
||||
rootFolder: "1KgPV6QB1GYT8fmn2uTfbtr9rDXqcRR0j",
|
||||
|
||||
isTeamDrive: false, // Set this to true if you're using Team Drive
|
||||
defaultQuery: ["trashed = false", "(not mimeType contains 'google-apps' or mimeType contains 'folder')"],
|
||||
defaultField:
|
||||
"id, name, mimeType, thumbnailLink, fileExtension, modifiedTime, size, imageMediaMetadata, videoMediaMetadata, webContentLink, trashed",
|
||||
@@ -165,6 +165,7 @@ interface gIndexConfig {
|
||||
|
||||
apiConfig: {
|
||||
rootFolder: string;
|
||||
isTeamDrive: boolean;
|
||||
defaultQuery: string[];
|
||||
defaultField: string;
|
||||
defaultOrder: string;
|
||||
|
||||
@@ -10,6 +10,7 @@ import PasswordLayout from "components/Layout/Password";
|
||||
import PreviewLayout from "components/Layout/Preview";
|
||||
|
||||
import { decryptData, encryptData } from "utils/encryptionHelper/hash";
|
||||
import { gdriveFilesList } from "utils/gdrive";
|
||||
import gdrive from "utils/gdriveInstance";
|
||||
import { addNewPassword, checkPathPassword } from "utils/passwordHelper";
|
||||
|
||||
@@ -196,10 +197,11 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
const fetchRootId = gdrive.files.get({
|
||||
fileId: gIndexConfig.apiConfig.rootFolder,
|
||||
fields: "id",
|
||||
supportsAllDrives: gIndexConfig.apiConfig.isTeamDrive,
|
||||
});
|
||||
const fetchPathId = path.map(async (path) => {
|
||||
const query = ["trashed = false", `name = '${path}'`];
|
||||
const fetchFolderContents = await gdrive.files.list({
|
||||
const fetchFolderContents = await gdriveFilesList({
|
||||
q: `${query.join(" and ")}`,
|
||||
fields: "files(id, name, mimeType, parents)",
|
||||
});
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import gIndexConfig from "config";
|
||||
import { GaxiosResponse } from "gaxios";
|
||||
import type { drive_v3 } from "googleapis";
|
||||
|
||||
import gdrive from "utils/gdriveInstance";
|
||||
|
||||
interface ListFiles extends drive_v3.Params$Resource$Files$List {}
|
||||
|
||||
export async function gdriveFilesList({
|
||||
q,
|
||||
fields,
|
||||
orderBy,
|
||||
pageSize,
|
||||
pageToken,
|
||||
}: ListFiles): Promise<GaxiosResponse<drive_v3.Schema$FileList>> {
|
||||
const result = await gdrive.files.list({
|
||||
q,
|
||||
fields,
|
||||
orderBy,
|
||||
pageSize,
|
||||
pageToken,
|
||||
...(gIndexConfig.apiConfig.isTeamDrive && {
|
||||
supportsAllDrives: true,
|
||||
includeItemsFromAllDrives: true,
|
||||
driveId: gIndexConfig.apiConfig.rootFolder,
|
||||
corpora: "drive",
|
||||
}),
|
||||
});
|
||||
return result;
|
||||
}
|
||||
Reference in New Issue
Block a user