Skip to content

Commit

Permalink
extract settings into separate source file and add ability to turn of…
Browse files Browse the repository at this point in the history
…f automatic sync and a new command to bind to key or slash command
  • Loading branch information
kinabalu committed Jun 17, 2024
1 parent 7e9ecc3 commit 3858209
Show file tree
Hide file tree
Showing 3 changed files with 282 additions and 247 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
## Voicenotes Sync
Plugin offers the ability to sync down your thoughts an ideas from the voicenotes.com online service. The service
uses an API key which the plugin can grab post login and we do not save anything but the username in the settings file.
uses an API key which the plugin can grab post login (if using email and password or use the Login via Apple, Google, Twitter (X) instructions below) and we do not save anything but the username in the settings file.

Through the plugin settings one can customize the sync directory and frequency, download the audio file used in the
transcript and any AI generated summaries or actions become sections in the note text.

### Features
- Sync data from VoiceNotes.com including any AI generated summaries or actions
- Automatically sync data based on configurable minutes from VoiceNotes.com
- Includes any AI generated summaries or actions
- Includes TODOs which are turned into markdown todos (can append a tag to every TODO as well)
- Customize the sync directory and frequency
- Downloads the audio file (default is off)
- Prepend the date to the title / filename
- Optional mode to delete synced notes from the voicenotes.com server
- Destructive action which requires double opt-in toggles

Expand Down
269 changes: 24 additions & 245 deletions main.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,9 @@
import {
App,
Notice,
Plugin,
PluginSettingTab,
Setting,
PluginManifest,
DataAdapter,
normalizePath, TFile, Editor,
} from 'obsidian';
import {moment} from "obsidian"
import {App, DataAdapter, Editor, moment, normalizePath, Notice, Plugin, PluginManifest, TFile,} from 'obsidian';
import VoiceNotesApi from "./voicenotes-api";
import {capitalizeFirstLetter, isToday} from "./utils";
import {VoiceNoteEmail} from "./types";
import { sanitize } from 'sanitize-filename-ts';
import {sanitize} from 'sanitize-filename-ts';
import {VoiceNotesSettingTab} from "./settings";

declare global {
interface Window {
Expand All @@ -24,6 +15,7 @@ interface VoiceNotesPluginSettings {
token?: string;
username?: string;
password?: string;
automaticSync: boolean;
syncTimeout?: number;
downloadAudio?: boolean;
syncDirectory: string;
Expand All @@ -35,6 +27,7 @@ interface VoiceNotesPluginSettings {
}

const DEFAULT_SETTINGS: VoiceNotesPluginSettings = {
automaticSync: true,
syncTimeout: 60,
downloadAudio: false,
syncDirectory: "voicenotes",
Expand Down Expand Up @@ -68,6 +61,12 @@ export default class VoiceNotesPlugin extends Plugin {
this.addSettingTab(new VoiceNotesSettingTab(this.app, this));


this.addCommand({
id: 'manual-sync-voicenotes',
name: 'Manual Sync Voicenotes',
callback: async () => await this.sync(false)
})

this.addCommand({
id: 'insert-voicenotes-from-today',
name: 'Insert Today\'s Voicenotes',
Expand Down Expand Up @@ -149,6 +148,8 @@ export default class VoiceNotesPlugin extends Plugin {
}

async sync(fullSync: boolean = false) {
console.debug(`Sync running full? ${fullSync}`)

this.vnApi = new VoiceNotesApi({});
this.vnApi.token = this.settings.token

Expand All @@ -174,6 +175,7 @@ export default class VoiceNotesPlugin extends Plugin {

// console.dir(recordings)
if (recordings) {
new Notice(`Syncing latest Voicenotes`)
for (const recording of recordings.data) {
if (!recording.title) {
new Notice(`Unable to grab voice recording with id: ${recording.id}`)
Expand Down Expand Up @@ -269,242 +271,19 @@ export default class VoiceNotesPlugin extends Plugin {
}

window.clearInterval(this.syncInterval)
this.syncInterval = window.setInterval(() => {
this.timeSinceSync += this.ONE_SECOND

if (this.timeSinceSync >= this.settings.syncTimeout * 60 * 1000) {
this.timeSinceSync = 0
this.sync()
}
}, this.ONE_SECOND)

}
}

class VoiceNotesSettingTab extends PluginSettingTab {
plugin: VoiceNotesPlugin;
vnApi: VoiceNotesApi;
password: string;

constructor(app: App, plugin: VoiceNotesPlugin) {
super(app, plugin);
this.plugin = plugin;
this.vnApi = new VoiceNotesApi({});
}

async display(): Promise<void> {
let { containerEl } = this;

containerEl.empty();

if (!this.plugin.settings.token) {
new Setting(containerEl)
.setName('Username')
.addText(text => text
.setPlaceholder('Email address')
.setValue(this.plugin.settings.username)
.onChange(async (value) => {
this.plugin.settings.username = value;
await this.plugin.saveSettings();
}));
new Setting(containerEl)
.setName('Password')
.addText(text => text
.setPlaceholder('Password')
.setValue(this.plugin.settings.password)
.onChange(async (value) => {
this.password = value;
await this.plugin.saveSettings();
}));

new Setting(containerEl)
.addButton(button => button
.setButtonText("Login")
.onClick(async (evt) => {
this.plugin.settings.token = await this.vnApi.login({
username: this.plugin.settings.username,
password: this.password
})

this.plugin.settings.password = null
if (this.plugin.settings.token) {
new Notice("Login to voicenotes.com was successful")
await this.plugin.saveSettings()
await this.display()
} else {
new Notice("Login to voicenotes.com was unsuccessful")
}
})
)

new Setting(containerEl)
.setName('Auth Token')
.addText(text => text
.setPlaceholder('12345|abcdefghijklmnopqrstuvwxyz')
.setValue(this.plugin.settings.token)
.onChange(async (value) => {
this.plugin.settings.token = value;
await this.plugin.saveSettings();
}));
new Setting(containerEl)
.addButton(button => button
.setButtonText("Login with token")
.onClick(async (evt) => {
this.vnApi.setToken(this.plugin.settings.token)
const response = await this.vnApi.getUserInfo()
this.plugin.settings.password = null

if (response) {
new Notice("Login to voicenotes.com was successful")
await this.plugin.saveSettings()
await this.display()
} else {
new Notice("Login to voicenotes.com was unsuccessful")
}
})
)
}
if (this.plugin.settings.token) {
this.vnApi.setToken(this.plugin.settings.token)

const userInfo = await this.vnApi.getUserInfo()

new Setting(containerEl)
.setName("Name")
.addText(text => text
.setPlaceholder(userInfo.name)
.setDisabled(true)
)
new Setting(containerEl)
.setName("Email")
.addText(text => text
.setPlaceholder(userInfo.email)
.setDisabled(true)
)
new Setting(containerEl)
.addButton(button => button
.setButtonText("Logout")
.onClick(async (evt) => {
new Notice("Logged out of voicenotes.com")
this.plugin.settings.token = null
this.plugin.settings.password = null
this.password = null
await this.plugin.saveSettings()
await this.display()
})
)

new Setting(containerEl)
.setName("Force Sync")
.setDesc("Manual synchronization -- only use the overwrite manual sync if you're ok with overwriting already synced notes")
.addButton(button => button
.setButtonText("Manual sync")
.onClick(async (evt) => {
new Notice("Performing manual synchronization without overwriting existing work.")
await this.plugin.sync();
new Notice("Manual synchronization has completed.")
})
)
.addButton(button => button
.setButtonText("Manual sync (overwrite)")
.onClick(async (evt) => {
// Upon a manual sync we are going to forget about existing data so we can sync all again
new Notice("Performing manual synchronization and overwriting all notes.")
this.plugin.syncedRecordingIds = [];
await this.plugin.sync(true);
new Notice("Manual synchronization with overwrite has completed.")
})
)
if (this.settings.automaticSync) {
console.debug(`timeSinceSync ${this.timeSinceSync} - syncTimeout: ${this.settings.syncTimeout}`)
this.syncInterval = window.setInterval(() => {
this.timeSinceSync += this.ONE_SECOND

if (this.timeSinceSync >= this.settings.syncTimeout * 60 * 1000) {
this.timeSinceSync = 0
this.sync()
}
}, this.ONE_SECOND)
}

new Setting(containerEl)
.setName("Sync every")
.setDesc("Number of minutes between syncing with VoiceNotes.com servers")
.addText(text => text
.setPlaceholder("30")
.setValue(`${this.plugin.settings.syncTimeout}`)
.onChange(async (value) => {
this.plugin.settings.syncTimeout = Number(value);
await this.plugin.saveSettings();
})
)

new Setting(containerEl)
.setName("Sync directory")
.setDesc("Directory to sync voice notes")
.addText(text => text
.setPlaceholder("voicenotes")
.setValue(`${this.plugin.settings.syncDirectory}`)
.onChange(async (value) => {
this.plugin.settings.syncDirectory = value;
await this.plugin.saveSettings();
})
)

new Setting(containerEl)
.setName("Add a tag to todos")
.setDesc("When syncing a note add an optional tag to the todo")
.addText(text => text
.setPlaceholder("TODO")
.setValue(this.plugin.settings.todoTag)
.onChange(async (value) => {
this.plugin.settings.todoTag = value;
await this.plugin.saveSettings();
})
)

new Setting(containerEl)
.setName("Download audio")
.setDesc("Store and download the audio associated with the transcript")
.addToggle(toggle => toggle
.setValue(this.plugin.settings.downloadAudio)
.onChange(async (value) => {
this.plugin.settings.downloadAudio = Boolean(value);
await this.plugin.saveSettings();
})
)


new Setting(containerEl)
.setName("Prepend Date to Note Title")
.setDesc("Adding the dates to the file names of all synced notes")
.addToggle(toggle => toggle
.setValue(this.plugin.settings.prependDateToTitle)
.onChange(async (value) => {
this.plugin.settings.prependDateToTitle = value;
await this.plugin.saveSettings();
})
)

new Setting(containerEl)
.setName("Delete synced recordings")
.setDesc("DESTRUCTIVE action which after syncing the note locally will delete it from the voicenotes.com server.")
.addToggle(toggle => toggle
.setValue(this.plugin.settings.deleteSynced)
.onChange(async (value) => {
this.plugin.settings.deleteSynced = value;

if (!value) {
this.plugin.settings.reallyDeleteSynced = false;
}

await this.plugin.saveSettings();
await this.display()
})
)

if (this.plugin.settings.deleteSynced) {
new Setting(containerEl)
.setName("REALLY delete synced recordings")
.setDesc("We want you to be sufficiently clear that this will delete anything on voicenotes.com")
.addToggle(toggle => toggle
.setValue(this.plugin.settings.reallyDeleteSynced)
.onChange(async (value) => {
this.plugin.settings.reallyDeleteSynced = Boolean(value);
await this.plugin.saveSettings();
})
)
}
}
}

Loading

0 comments on commit 3858209

Please sign in to comment.