wranglebot
Version:
open source media asset management
212 lines (188 loc) • 5.37 kB
text/typescript
import { finder } from "../system/index.js";
import { SearchLite } from "searchlite";
import ReturnObject from "../utility/SendBack.js";
import { Volume } from "./Volume.js";
import LogBot from "logbotjs";
import EventEmitter from "events";
import { FSWatcher } from "fs";
class DriveBot extends EventEmitter {
/**
* @wbType {Volume[]}
*/
drives: any = [];
verbose;
watchers = [];
private watcher: FSWatcher | null = null;
constructor() {
super();
}
/**
* Starts listening to changes to mounted volumes
*
* @example
* driveBot.watch(["mylib1, mylib2"]);
*
* @fires DriveBot#removed
* @fires DriveBot#added
*
*/
watch() {
this.watcher = finder.watch(finder.pathToVolumes, (eventType, volumeName) => {
if (eventType === "rename") {
this.getDrive(volumeName).then((drive) => {
if (drive) {
const oldDrive = drive;
this.drives.splice(this.drives.indexOf(drive), 1);
LogBot.log(200, "Volume removed: " + volumeName);
this.emit("removed", oldDrive);
} else {
this.scan()
.then((allDrives) => {
const search = SearchLite.find(allDrives, "label", volumeName);
if (search.wasSuccess()) {
this.drives.push(search.result);
LogBot.log(200, "Volume added: " + volumeName);
this.emit("added", search.result);
}
})
.catch((e) => {
console.error(e);
});
}
});
}
});
}
hasWatcher() {
return this.watcher !== null;
}
stopWatching() {
if (this.watcher) {
this.watcher.close();
this.watcher = null;
}
}
/**
* scans all mounted drives and returns an Array of Drives
* @return {Promise<Volume[]>}
*/
async scan() {
return new Promise((resolve) => {
let newDrives: any = [];
finder.getDisks().then(async (drives) => {
for (let drive of drives) {
const newDrive = new Volume(drive);
newDrives.push(newDrive);
}
resolve(newDrives);
});
});
}
async updateDrives() {
if (this.drives.length === 0) this.drives = await this.scan();
}
async getDriveById(id) {
await this.updateDrives();
return this.drives.find((drive) => drive.volumeId === id);
}
async eject(id) {
return new Promise((resolve) => {
this.getDriveById(id).then((vol) => {
if (vol) {
finder.eject(vol.mountpoint, (error) => {
if (!error) {
LogBot.log(200, "Ejected " + vol.label);
resolve(true);
} else {
LogBot.log(500, "Error ejecting drive: " + error);
resolve(false);
}
});
}
});
});
}
async ejectDevice(deviceName) {
return new Promise((resolve) => {
let search = SearchLite.find(this.drives, "label", deviceName);
if (search.wasSuccess()) {
if (search.result.status === "offline") {
this.drives.splice(search.count, 1);
resolve(
new ReturnObject({
status: 200,
message: deviceName + " was offline, so I removed it.",
})
);
} else {
finder.eject(search.result.mountpoint, (error) => {
if (!error) {
this.drives.splice(search.count, 1);
resolve(
new ReturnObject({
status: 200,
message: "I have successfully ejected the drive " + deviceName,
})
);
} else {
resolve(
new ReturnObject({
status: 500,
message: "I was unable to eject the drive " + deviceName,
})
);
}
});
}
}
});
}
async getDrive(driveName) {
await this.updateDrives();
let search = SearchLite.find(this.drives, "label", driveName);
if (search.wasSuccess()) {
return search.result;
}
return false;
}
getDriveByMountpoint(mountpoint) {
if (this.drives.length === 0) throw new Error("No drives found");
let search = SearchLite.find(this.drives, "mountpoint", mountpoint);
if (search.wasSuccess()) {
return search.result;
}
return false;
}
async getDriveBySerial(serialNumber) {
await this.updateDrives();
let search = SearchLite.find(this.drives, "serialNumber", serialNumber);
if (search.wasSuccess()) {
return search.result;
}
return false;
}
async getDrives() {
await this.updateDrives();
return this.drives;
}
async getMountPoint(mountpoint) {
await this.updateDrives();
let search = SearchLite.find(this.drives, "mountpoint", mountpoint);
if (search.wasSuccess()) {
return search.result.mountpoint;
}
return "";
}
async getCurrentVolumeName(serialNumber) {
const driveToCheck = await this.getDriveBySerial(serialNumber);
if (driveToCheck) {
return driveToCheck.label;
}
return "";
}
log(message, type) {
LogBot.log(`DriveBot:${type}`, message, this.verbose);
}
}
const driveBot = new DriveBot();
export { driveBot, DriveBot };