Skip to content
Open
Show file tree
Hide file tree
Changes from 6 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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ keys.json
.tsbuildinfo

# Windows Zone.Identifier files
*:Zone.Identifier
*:Zone.Identifier
package-lock.json
Binary file added assets/drive.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 11 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"plasmo": "0.89.4",
"react": "18.2.0",
"react-dom": "18.2.0",
"tailwindcss": "3.4.1"
"tailwindcss": "3.4.1",
"uuid": "^11.1.0"
},
"devDependencies": {
"@babel/preset-env": "^7.26.9",
Expand Down Expand Up @@ -52,12 +53,19 @@
"manifest": {
"permissions": [
"storage",
"cookies"
"cookies",
"identity"
],
"host_permissions": [
"https://*/*",
"http://*/*"
]
],
"oauth2": {
"client_id": "643972847997-jvqlsaierktjotv6df3fuva98degkiui.apps.googleusercontent.com",
"scopes": [
"https://www.googleapis.com/auth/drive.readonly"
]
}
},
"type": "module"
}
15 changes: 11 additions & 4 deletions plasmo.config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
export default {
import { defineConfig } from "@plasmohq/config";
export default defineConfig({
name: "Mantis connection",
version: "0.0.1",
manifest: {
permissions: [
"storage",
"cookies",
"webRequest"
]
"identity"
],
oauth2: {
"client_id": "643972847997-jvqlsaierktjotv6df3fuva98degkiui.apps.googleusercontent.com",
"scopes": ["https://www.googleapis.com/auth/drive.readonly"]
},
}
}
});
84 changes: 84 additions & 0 deletions src/background.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { request } from "http";

// This is used to register cookies in the browser
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === "setCookie") {
Expand Down Expand Up @@ -41,6 +43,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
}
});


const communications = {};

// This is used to register communication channels between the background script and the injected Mantis
Expand Down Expand Up @@ -78,4 +81,85 @@ chrome.runtime.onMessage.addListener((request, _sender, sendResponse) => {
return true;
}
}
});

// Retrieve access tokens
async function initiateSignIn(): Promise<string | undefined> {
try {
const result = await chrome.identity.getAuthToken({
interactive: true
});
if (result && result.token) {
console.log("Access retrieved");
return result.token; // Return the token string from the result object
} else {
console.log("Interactive sign-in failed or was cancelled.");
return undefined; // Return undefined if no token in the result
}
} catch (error: unknown) {
console.error("Error during interactive sign-in:", error);
console.error("Error details:", JSON.stringify(error, null, 2));
return undefined; // Return undefined if an error occurred
}
}

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === "initiateOAuth") {
(async () => {
try {
const token = await initiateSignIn();
if (!token) {
sendResponse({ success: false, error: "Failed to retrieve access token." });
return;
}

const allFiles: any[] = [];
let nextPageToken: string | undefined = undefined;

do {
const url = new URL("https://www.googleapis.com/drive/v3/files");
url.searchParams.set("pageSize", "1000"); // max per API page
url.searchParams.set("fields", "nextPageToken, files(id, name)");
if (nextPageToken) {
url.searchParams.set("pageToken", nextPageToken);
}

const res = await fetch(url.toString(), {
headers: {
Authorization: `Bearer ${token}`,
},
});

if (!res.ok) {
const errorData = await res.json();
sendResponse({
success: false,
error: `Drive API error: ${errorData.error?.message || res.statusText}`,
});
return;
}

const data = await res.json();
allFiles.push(...data.files);

// Stop at 2000 files
if (allFiles.length >= 2000) {
allFiles.length = 2000; // truncate if over
break;
}

nextPageToken = data.nextPageToken;
} while (nextPageToken);

console.log("✅ Fetched Drive Files (max 2000):", allFiles);
sendResponse({ success: true, token, driveFiles: allFiles });
} catch (err) {
sendResponse({
success: false,
error: (err as Error).message || "Failed to fetch Google Drive metadata",
});
}
})();
return true;
}
});
6 changes: 2 additions & 4 deletions src/connection_manager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@ import { PubmedConnection } from "./connections/pubmed/connection";
import { GoogleDocsConnection } from "./connections/googleDocs/connection";
import { GoogleScholarConnection } from "./connections/googleScholar/connection";
import { WikipediaSegmentConnection } from "./connections/wikipediaSegment/connection";
import { GoogleDriveConnection } from "./connections/googleDrive/connection"
import { LinkedInConnection } from "./connections/Linkedin/connection";


export const CONNECTIONS = [WikipediaSegmentConnection, WikipediaReferencesConnection, GoogleConnection, PubmedConnection, GoogleDocsConnection, GoogleScholarConnection,LinkedInConnection];
export const CONNECTIONS = [WikipediaSegmentConnection, WikipediaReferencesConnection, GoogleConnection, PubmedConnection, GoogleDocsConnection, GoogleScholarConnection, LinkedInConnection, GoogleDriveConnection];

export const searchConnections = (url: string, ) => {
const connections = CONNECTIONS.filter(connection => connection.trigger(url));

return connections;
};
77 changes: 77 additions & 0 deletions src/connections/googleDrive/connection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import type { MantisConnection, injectUIType, onMessageType, registerListenersType, setProgressType, establishLogSocketType } from "../types";
import { GenerationProgress } from "../types";

import driveIcon from "data-base64:../../../assets/drive.png";
import { getSpacePortal, reqSpaceCreation} from "../../driver";

const trigger = (url: string) => {
return url.includes("drive.google.com");
}

const getDriveFiles = async () => {
try {
const response = await new Promise<{
success: boolean;
token?: string;
driveFiles?: any[];
error?: string;
}>((resolve, reject) => {
chrome.runtime.sendMessage({ action: "initiateOAuth" }, (response) => {
if (chrome.runtime.lastError) {
return reject(new Error("Runtime error: " + chrome.runtime.lastError.message));
}
resolve(response);
});
});

if (response.success && response.driveFiles) {
console.log("Token:", response.token);
console.log("Drive files:", response.driveFiles);
return response.driveFiles;
} else {
console.error("OAuth failed:", response.error);
}
} catch (err) {
console.error("Error during Drive file fetch:", err);
}
};

const createSpace = async (injectUI: injectUIType, setProgress: setProgressType, onMessage: onMessageType, registerListeners: registerListenersType, establishLogSocket: establishLogSocketType) => {
setProgress(GenerationProgress.GATHERING_DATA);
const fileMetadata = await getDriveFiles();

setProgress(GenerationProgress.CREATING_SPACE);

const spaceData = await reqSpaceCreation(fileMetadata, {
"name": "semantic",
}, establishLogSocket);

setProgress(GenerationProgress.INJECTING_UI);

const spaceId = spaceData.space_id;
const createdWidget = await injectUI(spaceId, onMessage, registerListeners);

setProgress(GenerationProgress.COMPLETED);

return { spaceId, createdWidget };
};

const injectUI = async (space_id: string, onMessage: onMessageType, registerListeners: registerListenersType) => {

const iframeScalerParent = await getSpacePortal (space_id, onMessage, registerListeners);

document.body.prepend (iframeScalerParent);

return iframeScalerParent;
}



export const GoogleDriveConnection: MantisConnection = {
name: "Google Drive",
description: "Builds spaces based on the content of an entire Google Drive",
icon: driveIcon,
trigger: trigger,
createSpace: createSpace,
injectUI: injectUI,
}
Loading