diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index a0feda057..eda2cf86a 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -9,6 +9,7 @@ import { goto } from '$app/navigation'; import { page } from '$app/stores'; + import { loadGoogleAuthApi, loadGoogleDriveApi, createPicker } from '$lib/utils/google-drive-picker'; import { get, type Unsubscriber, type Writable } from 'svelte/store'; import type { i18n as i18nType } from 'i18next'; @@ -300,6 +301,12 @@ }; onMount(async () => { + // Initialize Google APIs + await Promise.all([ + loadGoogleAuthApi(), + loadGoogleDriveApi() + ]); + window.addEventListener('message', onMessageHandler); $socket?.on('chat-events', chatEventHandler); @@ -349,6 +356,47 @@ // File upload functions + const uploadGoogleDriveFile = async (fileData) => { + const fileItem = { + type: 'doc', + name: fileData.name, + collection_name: '', + status: 'uploading', + url: fileData.url, + error: '' + }; + + try { + files = [...files, fileItem]; + const res = await processWeb(localStorage.token, '', fileData.url); + + if (res) { + fileItem.status = 'uploaded'; + fileItem.collection_name = res.collection_name; + fileItem.file = { + ...res.file, + ...fileItem.file + }; + + files = files; + } + } catch (e) { + files = files.filter((f) => f.name !== fileData.name); + toast.error(JSON.stringify(e)); + } + }; + + const handleGoogleDrivePicker = async () => { + try { + const fileData = await createPicker(); + if (fileData) { + await uploadGoogleDriveFile(fileData); + } + } catch (error) { + toast.error('Error accessing Google Drive: ' + error.message); + } + }; + const uploadWeb = async (url) => { console.log(url); diff --git a/src/lib/utils/google-drive-picker.ts b/src/lib/utils/google-drive-picker.ts new file mode 100644 index 000000000..855f88592 --- /dev/null +++ b/src/lib/utils/google-drive-picker.ts @@ -0,0 +1,80 @@ +// Google Drive Picker API configuration +const API_KEY = 'YOUR_API_KEY'; +const CLIENT_ID = 'YOUR_CLIENT_ID'; +const SCOPE = ['https://www.googleapis.com/auth/drive.readonly']; + +let pickerApiLoaded = false; +let oauthToken: string | null = null; + +export const loadGoogleDriveApi = () => { + return new Promise((resolve, reject) => { + const script = document.createElement('script'); + script.src = 'https://apis.google.com/js/api.js'; + script.onload = () => { + gapi.load('picker', () => { + pickerApiLoaded = true; + resolve(true); + }); + }; + script.onerror = reject; + document.body.appendChild(script); + }); +}; + +export const loadGoogleAuthApi = () => { + return new Promise((resolve, reject) => { + const script = document.createElement('script'); + script.src = 'https://accounts.google.com/gsi/client'; + script.onload = resolve; + script.onerror = reject; + document.body.appendChild(script); + }); +}; + +export const getAuthToken = async () => { + if (!oauthToken) { + const tokenClient = google.accounts.oauth2.initTokenClient({ + client_id: CLIENT_ID, + scope: SCOPE.join(' '), + callback: (response: any) => { + if (response.access_token) { + oauthToken = response.access_token; + } + }, + }); + await tokenClient.requestAccessToken(); + } + return oauthToken; +}; + +export const createPicker = async () => { + if (!pickerApiLoaded) { + await loadGoogleDriveApi(); + } + + const token = await getAuthToken(); + if (!token) { + throw new Error('Unable to get OAuth token'); + } + + const picker = new google.picker.PickerBuilder() + .addView(google.picker.ViewId.DOCS) + .setOAuthToken(token) + .setDeveloperKey(API_KEY) + .setCallback((data: any) => { + if (data[google.picker.Response.ACTION] === google.picker.Action.PICKED) { + const doc = data[google.picker.Response.DOCUMENTS][0]; + const fileId = doc[google.picker.Document.ID]; + const fileName = doc[google.picker.Document.NAME]; + const fileUrl = doc[google.picker.Document.URL]; + + return { + id: fileId, + name: fileName, + url: fileUrl + }; + } + }) + .build(); + picker.setVisible(true); +};