From b5a9244bcdddcece66258c123ebf51021a13d068 Mon Sep 17 00:00:00 2001 From: Nicolas Bonamy Date: Sun, 22 Dec 2024 23:16:55 -0600 Subject: [PATCH] cleanup --- .gitignore | 3 - defaults/settings.json | 6 - forge.config.ts | 1 - src/main.ts | 17 -- src/main/dropbox.ts | 256 --------------------------- src/main/gdrive.ts | 292 ------------------------------- src/main/history.ts | 6 - src/main/online.ts | 121 ------------- src/preload.ts | 4 - src/settings/SettingsDropbox.vue | 77 -------- src/types/config.d.ts | 11 -- src/types/index.d.ts | 14 -- vitest.config.mjs | 3 - 13 files changed, 811 deletions(-) delete mode 100644 src/main/dropbox.ts delete mode 100644 src/main/gdrive.ts delete mode 100644 src/main/online.ts delete mode 100644 src/settings/SettingsDropbox.vue diff --git a/.gitignore b/.gitignore index 11e5da8d..a43d18a5 100644 --- a/.gitignore +++ b/.gitignore @@ -100,6 +100,3 @@ dist/ # office parser officeParserTemp - -# google drive settings -gdrive.json diff --git a/defaults/settings.json b/defaults/settings.json index d997e0dd..1579d6aa 100644 --- a/defaults/settings.json +++ b/defaults/settings.json @@ -241,11 +241,5 @@ "enabled": true }, "nestor": {} - }, - "dropbox": { - }, - "gdrive": { - "tokens": null, - "fileIds": {} } } diff --git a/forge.config.ts b/forge.config.ts index bff682cd..24ab82fa 100644 --- a/forge.config.ts +++ b/forge.config.ts @@ -88,7 +88,6 @@ const config: ForgeConfig = { 'assets/bulbWhite@2x.png', 'assets/bulbUpdateWhite.png', 'assets/bulbUpdateWhite@2x.png', - //...(fs.existsSync('./gdrive.json') ? ['gdrive.json'] : []), ], ...osxPackagerConfig, afterCopy: [ diff --git a/src/main.ts b/src/main.ts index 648b2472..90f773dc 100644 --- a/src/main.ts +++ b/src/main.ts @@ -21,7 +21,6 @@ import DocumentRepository from './rag/docrepo'; import Embedder from './rag/embedder'; import Nestor from './main/nestor'; import Computer from './main/computer'; -//import OnlineStorage from './main/online'; import TrayIconManager from './main/tray'; import * as config from './main/config'; @@ -38,7 +37,6 @@ import Automator, { AutomationAction } from 'automations/automator'; let commander: Commander = null let docRepo: DocumentRepository = null -//let onlineStorage: OnlineStorage = null let nestor: Nestor = null // first-thing: single instance @@ -78,10 +76,6 @@ if (!process.mas) { nestor = new Nestor(); } -// start online storage -// onlineStorage = new OnlineStorage(app); -// onlineStorage.initialize(); - // this is going to be called later const registerShortcuts = () => { shortcuts.registerShortcuts(app, { @@ -622,14 +616,3 @@ ipcMain.on('computer-get-screenshot', async (event) => { ipcMain.on('computer-execute-action', async (event, payload) => { event.returnValue = await Computer.executeAction(payload); }); - -// ipcMain.on('dropbox-get-authentication-url', async (event, payload) => { -// const dropbox = new Dropbox(app, '', '') -// event.returnValue = await dropbox.getOAuthUrl() -// }) - -// ipcMain.on('dropbox-authenticate-with-code', async (event, payload) => { -// const dropbox = new Dropbox(app, '', '') -// const accessToken = await dropbox.getAccessTokenFromCode(payload) -// event.returnValue = (accessToken != null) -// }) diff --git a/src/main/dropbox.ts b/src/main/dropbox.ts deleted file mode 100644 index c06c2324..00000000 --- a/src/main/dropbox.ts +++ /dev/null @@ -1,256 +0,0 @@ -// import { App } from 'electron' -// import { Dropbox, DropboxAuth } from 'dropbox' -// import * as config from './config' -// import fs from 'fs' - -// const DROPBOX_CLIENT_ID = '' -// const DROPBOX_CLIENT_SECRET = '' - -// export default class { - -// app: App -// localPath: string -// remotePath: string -// timer: NodeJS.Timeout - -// constructor(app: App, localPath: string, remotePath: string) { -// this.app = app -// this.localPath = localPath -// this.remotePath = remotePath -// this.timer = null -// } - -// async getOAuthUrl(): Promise { - -// try { - -// const dbxAuth = new DropboxAuth({ -// clientId: DROPBOX_CLIENT_ID, -// clientSecret: DROPBOX_CLIENT_SECRET -// }) - -// return await dbxAuth.getAuthenticationUrl('', 'state', 'code', 'legacy', [ -// 'files.metadata.read', -// 'files.content.read', 'files.content.write' -// ], 'user', false) as string - -// } catch (error) { -// console.error('Error getting authentication URL:', error) -// throw error -// } - -// } - -// async saveAccessToken(dbxAuth: DropboxAuth): Promise { - -// const settings = config.loadSettings(this.app) -// settings.dropbox.accessToken = dbxAuth.getAccessToken() -// //settings.dropbox.accessTokenExpiresAt = dbxAuth.getAccessTokenExpiresAt() -// //settings.dropbox.refreshToken = dbxAuth.getRefreshToken() -// config.saveSettings(this.app, settings) - -// } - -// async getAccessTokenFromCode(code: string): Promise { - -// try { - -// const dbxAuth = new DropboxAuth({ -// clientId: DROPBOX_CLIENT_ID, -// clientSecret: DROPBOX_CLIENT_SECRET -// }) - -// // log -// console.log('Getting access token from code', code) - -// // do it -// const response = await dbxAuth.getAccessTokenFromCode('', code) -// //console.log(response) -// const result = response.result as { access_token: string }//; expires_in: number; refresh_token: string } -// const accessToken = result.access_token -// // const expiresIn = result.expires_in -// // const expiresAt = new Date().getTime() + expiresIn * 1000 -// // const refreshToken = result.refresh_token -// dbxAuth.setAccessToken(accessToken) -// // dbxAuth.setAccessTokenExpiresAt(new Date(expiresAt)) -// // dbxAuth.setRefreshToken(refreshToken) -// this.saveAccessToken(dbxAuth) - -// return accessToken - -// } catch (error) { -// console.error('Error getting access token:', error) -// } - -// // too bad -// return null -// } - -// async getAccessToken(): Promise { - -// const settings = config.loadSettings(this.app) -// const accessToken = settings.dropbox.accessToken -// // const accessTokenExpiresAt = settings.dropbox.accessTokenExpiresAt -// // const refreshToken = settings.dropbox.refreshToken - -// // if we already have an access token, check it and return it -// if (accessToken) {// && accessTokenExpiresAt && accessTokenExpiresAt) { - -// try { - -// const dbxAuth = new DropboxAuth({ -// clientId: DROPBOX_CLIENT_ID, -// clientSecret: DROPBOX_CLIENT_SECRET, -// accessToken: accessToken, -// // accessTokenExpiresAt: accessTokenExpiresAt, -// // refreshToken: refreshToken -// }) - -// // log -// //console.log('Checking Dropbox access token') - -// // do it -// // await dbxAuth.checkAndRefreshAccessToken() -// // this.saveAccessToken(dbxAuth) -// return dbxAuth.getAccessToken() - -// } catch (error) { -// console.error('Error checking Dropbox access token:', error) -// } - -// } - -// // too bad -// return null - -// } - -// async getMetadata(): Promise { - -// try { - -// const accessToken = await this.getAccessToken() -// if (!accessToken) return - -// const dbx = new Dropbox({ accessToken: accessToken }) - -// const response = await dbx.filesGetMetadata({ path: this.remotePath }) -// return response.result - -// } catch (error) { -// console.error(`Error getting Dropbox metadata for ${this.remotePath}:`, error) -// } - -// return null - -// } - -// async monitor(): Promise { -// if (this.timer) return -// this.timer = setInterval(() => { -// this.downloadIfNeeded() -// }, 1000*60*5) -// } - -// async downloadIfNeeded(): Promise { - -// try { - -// // first check if dropbox has the file -// const dropboxMetadata = await this.getMetadata() -// if (!dropboxMetadata) { -// //console.log('Dropbox metadata not found') -// return false -// } - -// // needed -// const remoteSize = dropboxMetadata.size -// const remoteModifiedTime = new Date(dropboxMetadata.client_modified) - -// // check if we need to download the file -// let needDownload = false - -// // if file does not exist, we need to download it -// if (!fs.existsSync(this.localPath)) { -// needDownload = true -// } else { -// // we need to compare -// const localStats = fs.statSync(this.localPath) -// const localSize = localStats.size -// const localModifiedTime = localStats.mtime - -// // console.log('localSize = ', localSize) -// // console.log('remoteSize = ', remoteSize) -// // console.log('localModifiedTime = ', localModifiedTime) -// // console.log('remoteModifiedTime = ', remoteModifiedTime) - -// needDownload = localSize !== remoteSize || localModifiedTime.getTime() !== remoteModifiedTime.getTime() -// //console.log('Dropbox metadata comparison implies download = ', needDownload) -// } - -// // exit if no need to download -// if (!needDownload) { -// return false -// } - -// // do it -// await this.download(remoteModifiedTime) -// return true - -// } catch (error) { -// console.error(`Error downloading ${this.remotePath} from Dropbox:`, error) -// return false -// } - -// } - -// async download(modifiedTime: fs.TimeLike|null): Promise { - -// const accessToken = await this.getAccessToken() -// if (!accessToken) return - -// const dbx = new Dropbox({ accessToken: accessToken }) - -// // download -// const response = await dbx.filesDownload({ path: this.remotePath }) -// const fileContent = (response.result as any).fileBinary - -// // write and set time -// fs.writeFileSync(this.localPath, fileContent) -// if (modifiedTime) { -// fs.utimesSync(this.localPath, modifiedTime, modifiedTime) -// } - -// // done -// console.log(`Downloaded ${this.remotePath} from Dropbox`) - -// } - -// async upload(): Promise { - -// const accessToken = await this.getAccessToken() -// if (!accessToken) return - -// const dbx = new Dropbox({ accessToken: accessToken }) - -// // read -// const fileContent = fs.readFileSync(this.localPath, 'utf8') - -// // upload -// await dbx.filesUpload({ -// path: this.remotePath, -// contents: fileContent, -// mode: { '.tag': 'overwrite' }, -// }) - -// // sync modified time -// const dropboxMetadata = await this.getMetadata() -// const modifiedTime = new Date(dropboxMetadata.client_modified) -// fs.utimesSync(this.localPath, modifiedTime, modifiedTime) - -// // done -// console.log(`Uploaded ${this.remotePath} to Dropbox`) - -// } - -// } diff --git a/src/main/gdrive.ts b/src/main/gdrive.ts deleted file mode 100644 index e1e7e9d4..00000000 --- a/src/main/gdrive.ts +++ /dev/null @@ -1,292 +0,0 @@ - -import { OnlineFileMetadata, OnlineStorageProvider, anyDict } from 'types/index.d' -import { App } from 'electron' -import { google } from 'googleapis' -import portfinder from 'portfinder' -import * as config from './config' -import path from 'path' -import http from 'http' -import url from 'url' -import fs from 'fs' - -export default class implements OnlineStorageProvider { - - app: App - credentials: any - oauth2Client: any - gdrive: any - - timers: { [key: string]: NodeJS.Timeout } - - constructor(app: App) { - this.app = app - this.credentials = null - this.timers = null - } - - isSetup(): boolean { - - // load credentials - const assetsFolder = process.env.DEBUG ? path.resolve('./') : process.resourcesPath - const credentialsFile = path.join(assetsFolder, 'gdrive.json') - if (fs.existsSync(credentialsFile)) { - console.log('Gdrive credentials found') - this.credentials = JSON.parse(fs.readFileSync(credentialsFile, 'utf8')) - } - - // all we need - return this.credentials !== null && !!this.getTokens() - } - - async initialize(): Promise { - - // we may need a server and a port - let port = 8000 - - // check if we already have tokens - const tokens = await this.getTokens() - if (!tokens) { - - // find a port and listen - port = await portfinder.getPortPromise() - http.createServer(async (req, res) => { - - const queryObject = url.parse(req.url, true).query - const code = queryObject.code as string - const { tokens } = await this.oauth2Client.getToken(code) - this.oauth2Client.setCredentials(tokens) - this.saveTokens(tokens) - res.end('Authentication successful! You can close this tab now.') - - }).listen(port) - - } - - // now create the OAuth2 client - this.oauth2Client = new google.auth.OAuth2( - this.credentials.installed.client_id, - this.credentials.installed.client_secret, - `http://localhost:${port}` - ) - - // callback when tokens are refreshed - this.oauth2Client.on('tokens', (tokens: anyDict) => { - this.saveTokens(tokens) - }); - - // set the tokens - if (tokens) { - this.oauth2Client.setCredentials(tokens) - } - - // init service - this.gdrive = google.drive({ version: 'v3', auth: this.oauth2Client }) - - } - - getOAuthUrl(): string { - - try { - - const scopes = [ - 'https://www.googleapis.com/auth/drive.appdata', - ] - - return this.oauth2Client.generateAuthUrl({ - access_type: 'offline', - scope: scopes - }) - - } catch (error) { - console.error('Error getting authentication URL:', error) - throw error - } - - } - - async metadata(filepath: string): Promise { - - try { - - // needed - const filename = path.basename(filepath) - const settings = config.loadSettings(this.app) - - // get the file - const res = await this.gdrive.files.list({ - spaces: 'appDataFolder', - q: `name = '${filename}'`, - fields: 'files(id, name, mimeType, size, createdTime, modifiedTime)', - pageSize: 1, - }); - - // get the file - const file = res.data.files[0] - if (!file) { - return null - } - - // save the fileId if needed - if (settings.gdrive.fileIds[filename] !== file.id) { - settings.gdrive.fileIds[filename] = file.id - config.saveSettings(this.app, settings) - } - - // done - return { - id: file.id, - size: parseInt(file.size), - createdTime: new Date(file.createdTime), - modifiedTime: new Date(file.modifiedTime), - } - - } catch (error) { - console.error('Error getting file metadata from Gdrive:', error) - return null - } - - } - - async download(filePath: string): Promise { - - // needed - const filename = path.basename(filePath) - const settings = config.loadSettings(this.app) - - // we need a fileId - const fileId = settings.gdrive.fileIds[filename] - if (!fileId) { - console.error('File does not exist in Gdrive:', filename) - return null - } - - // get it - const file = await this.gdrive.files.get({ - fileId: fileId, - alt: 'media', - }); - - // it needs to be ok - if (file.status != 200) { - console.error('Error downloading file from Gdrive:', file) - return null - } - - // get what we need - return file.data - - } - - async upload(filePath: string, modifiedTime: Date): Promise { - - // needed - const filename = path.basename(filePath) - const settings = config.loadSettings(this.app) - - // check if we have already uploaded this file - const fileId = settings.gdrive.fileIds[filename] - if (fileId) { - return await this.update(fileId, filePath, modifiedTime) - } else { - return await this.create(filePath, modifiedTime) - } - - } - - private async create(filePath: string, modifiedTime: Date): Promise { - - try { - - // needed - const filename = path.basename(filePath) - const settings = config.loadSettings(this.app) - - // metadata - const fileMetadata = { - name: filename, - modifiedTime: modifiedTime.toISOString(), - parents: ['appDataFolder'], - } - - // content - const media = { - mimeType: 'application/json', - body: fs.createReadStream(filePath), - } - - // create - const file = await this.gdrive.files.create({ - requestBody: fileMetadata, - media: media, - fields: 'id', - }); - - // record - const fileId = file.data.id - settings.gdrive.fileIds[filename] = fileId - config.saveSettings(this.app, settings) - - // done - return true - - } catch (err) { - console.error('Error creating file in Gdrive:', err); - return false - } - - } - - private async update(fileId: string, filePath: string, modifiedTime: Date): Promise { - - try { - - // metadata - const fileMetadata = { - modifiedTime: modifiedTime.toISOString(), - } - - // content - const media = { - mimeType: 'application/json', - body: fs.createReadStream(filePath), - } - - // update - await this.gdrive.files.update({ - requestBody: fileMetadata, - fileId: fileId, - media: media, - }); - - // done - return true - - } catch (err: unknown) { - - // our file id may be obsolete - if (err instanceof Error && err.message.includes('File not found')) { - console.warn('File not found in Gdrive, creating it instead:', err.message) - return await this.create(filePath, modifiedTime) - } - - // error - console.error('Error creating file in Gdrive:', err); - return false - } - - } - - private saveTokens(tokens: any): void { - const settings = config.loadSettings(this.app) - tokens = {...settings.gdrive.tokens ?? {}, ...tokens} - settings.gdrive.tokens = tokens - config.saveSettings(this.app, settings) - } - - private getTokens(): anyDict { - const settings = config.loadSettings(this.app) - const tokens = settings.gdrive.tokens - return tokens - } - -} diff --git a/src/main/history.ts b/src/main/history.ts index b97e76ec..e6322b0b 100644 --- a/src/main/history.ts +++ b/src/main/history.ts @@ -19,12 +19,6 @@ export const loadHistory = async (app: App): Promise => { // needed const filepath = historyFilePath(app) - // // dropbox - // if (!dropbox) { - // dropbox = new Dropbox(app, filepath, DROPBOX_PATH) - // } - // await dropbox.downloadIfNeeded() - // check existence if (!fs.existsSync(filepath)) { return { folders: [], chats: [] } diff --git a/src/main/online.ts b/src/main/online.ts deleted file mode 100644 index 067444f9..00000000 --- a/src/main/online.ts +++ /dev/null @@ -1,121 +0,0 @@ - -import { OnlineStorageProvider } from 'types/index.d' -import { App } from 'electron' -import { settingsFilePath } from './config' -import { historyFilePath } from './history' -import GoogleDrive from './gdrive' -import Monitor from './monitor' -import fs from 'fs' - -export default class OnlineConfig { - - app: App - monitors: { [key: string]: Monitor } - timers: { [key: string]: NodeJS.Timeout } - provider: OnlineStorageProvider - - constructor(app: App) { - this.app = app - this.provider = null - this.monitors = {} - this.timers = {} - } - - async initialize() : Promise { - this.provider = this.checkGoogle() - if (this.provider) { - await this.provider.initialize() - this.initializeWatchers() - } - } - - private checkGoogle(): OnlineStorageProvider { - const gdrive = new GoogleDrive(this.app) - return gdrive.isSetup() ? gdrive : null - } - - private initializeWatchers() { - this.initializeWatcher(settingsFilePath(this.app)) - this.initializeWatcher(historyFilePath(this.app)) - } - - private initializeWatcher(filepath: string) { - - // we need only one local monitor - if (this.monitors[filepath]) { - return - } - - // create local and remote - this.monitors[filepath] = new Monitor(() => this.checkSync(filepath)) - this.timers[filepath] = setInterval(() => this.checkSync(filepath), 1000*60*5) - - // and check now - this.checkSync(filepath) - - } - - private async checkSync(filepath: string): Promise { - - try { - - // check if it exists - const existsLocal = fs.existsSync(filepath) - const metadata = await this.provider.metadata(filepath) - - // if it exists nowhere then... - if (!existsLocal && !metadata) { - return - } - - // if it does not exist locally then... - if (!existsLocal) { - return this.download(filepath, metadata.modifiedTime) - } - - // get the local stats - const local = await fs.promises.stat(filepath) - - // if it does not exist remotely then... - if (!metadata) { - return this.upload(filepath, local.mtime) - } - - // needed - const remoteModifiedTime = metadata.modifiedTime - const localModifiedTime = local.mtime - - // compare - if (localModifiedTime.getTime() > remoteModifiedTime.getTime()) { - return this.upload(filepath, localModifiedTime) - } else if (localModifiedTime.getTime() < remoteModifiedTime.getTime()) { - return this.download(filepath, remoteModifiedTime) - } - - } catch (error) { - console.error(`Error checking sync status for ${filepath}`, error) - } - - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - private async download(filepath: string, modifiedTime: Date): Promise { - try { - console.log(`Remote version for ${filepath} is newer. Downloading`) - //const contents = await this.provider.download(filepath) - //fs.writeFileSync(filepath, contents) - } catch (err) { - console.error(`Error downloading ${filepath}`, err) - } - } - - private async upload(filepath: string, modifiedTime: Date): Promise { - try { - console.log(`Local version for ${filepath} is newer. Uploading`) - await this.provider.upload(filepath, modifiedTime) - } catch (err) { - console.error(`Error uploading ${filepath}`, err) - } - } - -} diff --git a/src/preload.ts b/src/preload.ts index 3e66d9a4..9f853035 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -129,10 +129,6 @@ contextBridge.exposeInMainWorld( scratchpad: { open: (textId?: string): void => { return ipcRenderer.send('scratchpad-open', textId) }, }, - dropbox: { - getAuthenticationUrl: (): string => { return ipcRenderer.sendSync('dropbox-get-authentication-url') }, - authenticateWithCode: (code: string): boolean => { return ipcRenderer.sendSync('dropbox-authenticate-with-code', code) }, - }, computer: { isAvailable: (): boolean => { return ipcRenderer.sendSync('computer-is-available') }, getScaledScreenSize: (): Size => { return ipcRenderer.sendSync('computer-get-scaled-screen-size') }, diff --git a/src/settings/SettingsDropbox.vue b/src/settings/SettingsDropbox.vue deleted file mode 100644 index e2639c72..00000000 --- a/src/settings/SettingsDropbox.vue +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/types/config.d.ts b/src/types/config.d.ts index 68037744..9f6adc19 100644 --- a/src/types/config.d.ts +++ b/src/types/config.d.ts @@ -15,8 +15,6 @@ export type Configuration = { plugins: {[key: string]: PluginConfig} stt: STTConfig rag: RagConfig - dropbox: DropboxConfig - gdrive: GDriveConfig } export type EngineConfig = EngineCreateOpts & { @@ -146,12 +144,3 @@ export type RagConfig = { searchResultCount?: number relevanceCutOff?: number } - -export type DropboxConfig = { - accessToken: string -} - -export type GDriveConfig = { - tokens: anyDict - fileIds: strDict -} diff --git a/src/types/index.d.ts b/src/types/index.d.ts index 9c0040bc..c08e4d00 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -130,20 +130,6 @@ export type FileContents = { contents: string } -export type OnlineFileMetadata = { - id: string - size: number - createdTime: Date - modifiedTime: Date -} - -export interface OnlineStorageProvider { - initialize: () => Promise - metadata: (filepath: string) => Promise - download: (filepath: string) => Promise - upload: (filepath: string, modifiedTime: Date) => Promise -} - export type ComputerAction = { action: 'key' | 'type' | 'mouse_move' | 'left_click' | 'left_click_drag' | 'right_click' | 'middle_click' | 'double_click' | 'screenshot' | 'cursor_position' coordinate?: number[] diff --git a/vitest.config.mjs b/vitest.config.mjs index c916f20e..a1458902 100644 --- a/vitest.config.mjs +++ b/vitest.config.mjs @@ -27,9 +27,6 @@ export default defineConfig({ '*.config.ts', 'build/*', 'src/*.ts', - 'src/main/online.ts', - 'src/main/dropbox.ts', - 'src/main/gdrive.ts', 'src/automations/macos*.ts', 'src/automations/robot.ts', 'src/automations/windows.ts',