mirror of
https://github.com/yzh503/obsidian-aicommander-plugin.git
synced 2026-07-22 07:40:26 +00:00
Fix a bug in finding file for audio and pdf.
This commit is contained in:
parent
90d15d45a6
commit
47fb63f0f4
3 changed files with 92 additions and 37 deletions
125
main.ts
125
main.ts
|
|
@ -124,12 +124,7 @@ export default class AICommanderPlugin extends Plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
async generateImage(prompt: string) {
|
async generateImage(prompt: string) {
|
||||||
|
if (this.settings.apiKey.length <= 1) throw new Error('OpenAI API Key is not provided.');
|
||||||
if (prompt.length > 1000) return({
|
|
||||||
success: false,
|
|
||||||
prompt: prompt,
|
|
||||||
text: 'Prompt needs to be shorter than 1000 characters.'
|
|
||||||
})
|
|
||||||
|
|
||||||
const configuration = new Configuration({
|
const configuration = new Configuration({
|
||||||
apiKey: this.settings.apiKey,
|
apiKey: this.settings.apiKey,
|
||||||
|
|
@ -158,8 +153,8 @@ export default class AICommanderPlugin extends Plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
async generateTranscript(audioBuffer: ArrayBuffer, filetype: string) {
|
async generateTranscript(audioBuffer: ArrayBuffer, filetype: string) {
|
||||||
|
if (this.settings.apiKey.length <= 1) throw new Error('OpenAI API Key is not provided.');
|
||||||
|
|
||||||
// Workaround for issue https://github.com/openai/openai-node/issues/77
|
|
||||||
const baseUrl = 'https://api.openai.com/v1/audio/transcriptions';
|
const baseUrl = 'https://api.openai.com/v1/audio/transcriptions';
|
||||||
|
|
||||||
const blob = new Blob([audioBuffer]);
|
const blob = new Blob([audioBuffer]);
|
||||||
|
|
@ -192,34 +187,81 @@ export default class AICommanderPlugin extends Plugin {
|
||||||
async getAttachmentDir() {
|
async getAttachmentDir() {
|
||||||
const attachmentFolder = await this.app.vault.adapter.read(`${this.app.vault.configDir}/app.json`).then((content: string) => {
|
const attachmentFolder = await this.app.vault.adapter.read(`${this.app.vault.configDir}/app.json`).then((content: string) => {
|
||||||
const config = JSON.parse(content);
|
const config = JSON.parse(content);
|
||||||
if (config.attachmentFolderPath === '/' || config.attachmentFolderPath === './') {
|
if ('attachmentFolderPath' in config) return config.attachmentFolderPath;
|
||||||
return '';
|
else return '';
|
||||||
}
|
|
||||||
return config.attachmentFolderPath + '/' || '';
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return attachmentFolder as string;
|
return attachmentFolder as string;
|
||||||
}
|
}
|
||||||
|
|
||||||
async findFilePath(text: string, regex: RegExp) {
|
// Test cases:
|
||||||
|
// 1. Attachment Folder: vault, Attachment: /audio.mp3
|
||||||
const path = await this.getAttachmentDir().then((path) => {
|
// 2. Attachment Folder: vault, Attachment: /folder/audio.mp3
|
||||||
|
// 3. Attachment Folder: specified, Attachment: /audio.mp3
|
||||||
|
// 4. Attachment Folder: specified, Attachment: /folder/audio.mp3
|
||||||
|
// 5. Attachment Folder: specified, Attachment: /specified/audio.mp3
|
||||||
|
// 6. Attachment Folder: same, Attachment: /audio.mp3
|
||||||
|
// 7. Attachment Folder: same, Attachment: /folder/audio.mp3
|
||||||
|
// 8. Attachment Folder: same, Attachment: /same/audio.mp3
|
||||||
|
// 9. Attachment Folder: subfolder, Attachment: /audio.mp3
|
||||||
|
// 10. Attachment Folder: subfolder, Attachment: /folder/audio.mp3
|
||||||
|
// 11. Attachment Folder: subfolder, Attachment: /same/subfolder/audio.mp3
|
||||||
|
// 12. Attachment Folder: subfolder, Attachment: /same/audio.mp3
|
||||||
|
async findFilePath(text: string, regex: RegExp[]) {
|
||||||
|
const filepath = await this.getAttachmentDir().then((attachmentPath) => {
|
||||||
let filename = '';
|
let filename = '';
|
||||||
let result: RegExpExecArray | null;
|
let result: RegExpExecArray | null;
|
||||||
while ((result = regex.exec(text)) !== null) {
|
for (const reg of regex) {
|
||||||
filename = decodeURI(result[0]);
|
while ((result = reg.exec(text)) !== null) {
|
||||||
|
filename = normalizePath(decodeURI(result[0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const activeFile = this.app.workspace.getActiveFile();
|
||||||
|
if (!activeFile) throw new Error('No active file');
|
||||||
|
const currentPath = activeFile.path.split('/');
|
||||||
|
currentPath.pop();
|
||||||
|
const currentPathString = currentPath.join('/');
|
||||||
|
|
||||||
|
console.log('currentPathString', currentPathString);
|
||||||
|
console.log('attachmentPath', attachmentPath);
|
||||||
|
console.log('filename', filename);
|
||||||
|
|
||||||
|
const underRootFolder = attachmentPath === '' || attachmentPath === '/';
|
||||||
|
const underCurrentFolder = attachmentPath.startsWith('./');
|
||||||
|
const underSpecificFolder = !underCurrentFolder && !underRootFolder;
|
||||||
|
const fileInSpecificFolder = filename.contains('/');
|
||||||
|
|
||||||
|
console.log(underRootFolder, underCurrentFolder, underSpecificFolder, fileInSpecificFolder);
|
||||||
|
|
||||||
|
let filepath = '';
|
||||||
|
|
||||||
|
if (underRootFolder || fileInSpecificFolder) filepath = filename;
|
||||||
|
if (underSpecificFolder) filepath = attachmentPath + '/' + filename;
|
||||||
|
if (underCurrentFolder) {
|
||||||
|
const attFolder = attachmentPath.substring(2);
|
||||||
|
if (attFolder.length == 0) filepath = currentPathString + '/' + filename;
|
||||||
|
else filepath = currentPathString + '/' + attFolder + '/' + filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filename.contains('/') || filename.contains('\\')) {
|
return this.app.vault.adapter.exists(filepath).then((exists => {
|
||||||
return normalizePath(filename);
|
if (exists) return filepath;
|
||||||
} else {
|
else {
|
||||||
return normalizePath(path + filename);
|
let path = '';
|
||||||
}
|
let found = false;
|
||||||
|
this.app.vault.getFiles().forEach((file) => {
|
||||||
|
if (file.name === filename) {
|
||||||
|
path = file.path;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (found) return path;
|
||||||
|
else throw new Error('File not found');
|
||||||
|
}
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
return path as string;
|
return filepath as string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async generateTextWithPdf(prompt: string, filepath: string) {
|
async generateTextWithPdf(prompt: string, filepath: string) {
|
||||||
const pdfBuffer = await this.app.vault.adapter.readBinary(filepath);
|
const pdfBuffer = await this.app.vault.adapter.readBinary(filepath);
|
||||||
const pdfjs = await loadPdfJs();
|
const pdfjs = await loadPdfJs();
|
||||||
|
|
@ -266,12 +308,16 @@ export default class AICommanderPlugin extends Plugin {
|
||||||
commandGenerateTextWithPdf(editor: Editor, prompt: string, includePrompt: boolean, hasSelected: boolean) {
|
commandGenerateTextWithPdf(editor: Editor, prompt: string, includePrompt: boolean, hasSelected: boolean) {
|
||||||
const position = editor.getCursor();
|
const position = editor.getCursor();
|
||||||
const text = editor.getRange({line: 0, ch: 0}, position);
|
const text = editor.getRange({line: 0, ch: 0}, position);
|
||||||
const regex = /(?<=\[(.*)]\()(([^[\]])+)\.pdf(?=\))/g;
|
const regex = [/(?<=\[(.*)]\()(([^[\]])+)\.pdf(?=\))/g,
|
||||||
|
/(?<=\[\[)(([^[\]])+)\.pdf(?=]])/g];
|
||||||
this.findFilePath(text, regex).then((path) => {
|
this.findFilePath(text, regex).then((path) => {
|
||||||
|
console.log('path', path);
|
||||||
new Notice(`Generating text in context of ${path}...`);
|
new Notice(`Generating text in context of ${path}...`);
|
||||||
this.generateTextWithPdf(prompt, path).then((data) => {
|
this.generateTextWithPdf(prompt, path).then((data) => {
|
||||||
this.processGeneratedText(editor, position.line, data, includePrompt, hasSelected);
|
this.processGeneratedText(editor, position.line, data, includePrompt, hasSelected);
|
||||||
})
|
}).catch(error => {
|
||||||
|
new Notice(error.message);
|
||||||
|
});
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
new Notice(error.message);
|
new Notice(error.message);
|
||||||
});
|
});
|
||||||
|
|
@ -292,20 +338,29 @@ export default class AICommanderPlugin extends Plugin {
|
||||||
const position = editor.getCursor();
|
const position = editor.getCursor();
|
||||||
const line = editor.getLine(position.line)
|
const line = editor.getLine(position.line)
|
||||||
const text = editor.getRange({line: 0, ch: 0}, position);
|
const text = editor.getRange({line: 0, ch: 0}, position);
|
||||||
const regex = /(?<=\[(.*)]\()(([^[\]])+)\.(mp3|mp4|mpeg|mpga|m4a|wav|webm)(?=\))/g;
|
const regex = [/(?<=\[\[)(([^[\]])+)\.(mp3|mp4|mpeg|mpga|m4a|wav|webm)(?=]])/g,
|
||||||
|
/(?<=\[(.*)]\()(([^[\]])+)\.(mp3|mp4|mpeg|mpga|m4a|wav|webm)(?=\))/g];
|
||||||
this.findFilePath(text, regex).then((path) => {
|
this.findFilePath(text, regex).then((path) => {
|
||||||
const fileType = path.split('.').pop();
|
const fileType = path.split('.').pop();
|
||||||
if (fileType == undefined || fileType == null || fileType == '') {
|
if (fileType == undefined || fileType == null || fileType == '') {
|
||||||
new Notice('No audio file found');
|
new Notice('No audio file found');
|
||||||
return;
|
} else {
|
||||||
}
|
this.app.vault.adapter.exists(path).then((exists) => {
|
||||||
this.app.vault.adapter.readBinary(path).then((audioBuffer) => {
|
console.log('Audio filepath', path);
|
||||||
new Notice("Generating transcript...");
|
if (!exists) throw new Error(path + ' does not exist');
|
||||||
this.generateTranscript(audioBuffer, fileType).then((result) => {
|
this.app.vault.adapter.readBinary(path).then((audioBuffer) => {
|
||||||
new Notice('Transcript Generated.');
|
new Notice("Generating transcript...");
|
||||||
editor.setLine(position.line, `${line}${result}\n`);
|
this.generateTranscript(audioBuffer, fileType).then((result) => {
|
||||||
|
new Notice('Transcript Generated.');
|
||||||
|
editor.setLine(position.line, `${line}${result}\n`);
|
||||||
|
});
|
||||||
|
}).catch(error => {
|
||||||
|
new Notice(error.message);
|
||||||
|
});
|
||||||
|
}).catch(error => {
|
||||||
|
new Notice(error.message);
|
||||||
});
|
});
|
||||||
})
|
}
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
new Notice(error.message);
|
new Notice(error.message);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "ai-commander",
|
"id": "ai-commander",
|
||||||
"name": "AI Commander",
|
"name": "AI Commander",
|
||||||
"version": "1.1.1",
|
"version": "1.1.2",
|
||||||
"minAppVersion": "1.0.0",
|
"minAppVersion": "1.0.0",
|
||||||
"description": "Generate audio transcripts, images, and text in context of PDF attachments or web search results using OpenAI and Bing API.",
|
"description": "Generate audio transcripts, images, and text in context of PDF attachments or web search results using OpenAI and Bing API.",
|
||||||
"author": "Simon Yang",
|
"author": "Simon Yang",
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
{
|
{
|
||||||
"1.1.1": "1.0.0"
|
"1.1.2": "1.0.0"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue