You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			95 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			TypeScript
		
	
			
		
		
	
	
			95 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			TypeScript
		
	
import path from 'path';
 | 
						|
import { ipcMain } from 'electron';
 | 
						|
import { isString, map } from 'lodash';
 | 
						|
import rimraf from 'rimraf';
 | 
						|
import fse from 'fs-extra';
 | 
						|
import pify from 'pify';
 | 
						|
// eslint-disable-next-line import/no-named-default
 | 
						|
import { default as glob } from 'glob';
 | 
						|
 | 
						|
import { sqlNode } from './sql'; // checked - only node
 | 
						|
import { createDeleter, getAttachmentsPath } from '../shared/attachments/shared_attachments';
 | 
						|
 | 
						|
let initialized = false;
 | 
						|
 | 
						|
const ERASE_ATTACHMENTS_KEY = 'erase-attachments';
 | 
						|
const CLEANUP_ORPHANED_ATTACHMENTS_KEY = 'cleanup-orphaned-attachments';
 | 
						|
 | 
						|
//      ensureDirectory :: AbsolutePath -> IO Unit
 | 
						|
const ensureDirectory = async (userDataPath: string) => {
 | 
						|
  if (!isString(userDataPath)) {
 | 
						|
    throw new TypeError("'userDataPath' must be a string");
 | 
						|
  }
 | 
						|
  await fse.ensureDir(getAttachmentsPath(userDataPath));
 | 
						|
};
 | 
						|
 | 
						|
const deleteAll = async ({
 | 
						|
  userDataPath,
 | 
						|
  attachments,
 | 
						|
}: {
 | 
						|
  userDataPath: string;
 | 
						|
  attachments: any;
 | 
						|
}) => {
 | 
						|
  const deleteFromDisk = createDeleter(getAttachmentsPath(userDataPath));
 | 
						|
 | 
						|
  for (let index = 0, max = attachments.length; index < max; index += 1) {
 | 
						|
    const file = attachments[index];
 | 
						|
    // eslint-disable-next-line no-await-in-loop
 | 
						|
    await deleteFromDisk(file);
 | 
						|
  }
 | 
						|
 | 
						|
  console.log(`deleteAll: deleted ${attachments.length} files`);
 | 
						|
};
 | 
						|
 | 
						|
const getAllAttachments = async (userDataPath: string) => {
 | 
						|
  const dir = getAttachmentsPath(userDataPath);
 | 
						|
  const pattern = path.join(dir, '**', '*');
 | 
						|
 | 
						|
  const files = await pify(glob)(pattern, { nodir: true });
 | 
						|
  return map(files, file => path.relative(dir, file));
 | 
						|
};
 | 
						|
 | 
						|
async function cleanupOrphanedAttachments(userDataPath: string) {
 | 
						|
  const allAttachments = await getAllAttachments(userDataPath);
 | 
						|
  const orphanedAttachments = sqlNode.removeKnownAttachments(allAttachments);
 | 
						|
  await deleteAll({
 | 
						|
    userDataPath,
 | 
						|
    attachments: orphanedAttachments,
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
export async function initAttachmentsChannel({ userDataPath }: { userDataPath: string }) {
 | 
						|
  if (initialized) {
 | 
						|
    throw new Error('initialze: Already initialized!');
 | 
						|
  }
 | 
						|
  initialized = true;
 | 
						|
 | 
						|
  console.log('Ensure attachments directory exists');
 | 
						|
  await ensureDirectory(userDataPath);
 | 
						|
 | 
						|
  const attachmentsDir = getAttachmentsPath(userDataPath);
 | 
						|
 | 
						|
  ipcMain.on(ERASE_ATTACHMENTS_KEY, event => {
 | 
						|
    try {
 | 
						|
      rimraf.sync(attachmentsDir);
 | 
						|
      event.sender.send(`${ERASE_ATTACHMENTS_KEY}-done`);
 | 
						|
    } catch (error) {
 | 
						|
      const errorForDisplay = error && error.stack ? error.stack : error;
 | 
						|
      console.log(`erase attachments error: ${errorForDisplay}`);
 | 
						|
      event.sender.send(`${ERASE_ATTACHMENTS_KEY}-done`, error);
 | 
						|
    }
 | 
						|
  });
 | 
						|
 | 
						|
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
 | 
						|
  ipcMain.on(CLEANUP_ORPHANED_ATTACHMENTS_KEY, async event => {
 | 
						|
    try {
 | 
						|
      await cleanupOrphanedAttachments(userDataPath);
 | 
						|
      event.sender.send(`${CLEANUP_ORPHANED_ATTACHMENTS_KEY}-done`);
 | 
						|
    } catch (error) {
 | 
						|
      const errorForDisplay = error && error.stack ? error.stack : error;
 | 
						|
      console.log(`cleanup orphaned attachments error: ${errorForDisplay}`);
 | 
						|
      event.sender.send(`${CLEANUP_ORPHANED_ATTACHMENTS_KEY}-done`, error);
 | 
						|
    }
 | 
						|
  });
 | 
						|
}
 |