Hook To New > Obsidian

@LucB, is there an update on update on progress for Hook To New for Obsidian? Apologies if I missed a prior announcement. Thank you!

— Robert

Sorry for the delay, @rdr. And thanks for raising it again. We tried with their new interface for this last month, but couldn’t get it to work. At the time someone on the forum said they expected Obsidian to improve the API, putting information in the database (rather than the current support for inter-app communication which was file-based). We will look again.

Our community/ CogSci Apps would benefit from having an additional liaison to Obsidian (i.e., an avid Hook customer who is also an avid Obisidian user and who can spare the time to communicate on both sides), to keep track of that rapidly developing app.

I’d be willing to step in here. I’m using Obsidian and Hook intensively.

2 Likes

Thanks, @eMaX , That is much appreciated. I’d love to know where they are at with an API that can support Hook to New, and when they intend to update their API for the other Hook functions.

1 Like

I did find their URL scheme documented here:

https://help.obsidian.md/Advanced+topics/Using+obsidian+URI

An example URL for creating a note did seem to work for me:

obsidian://new?vault=Home&name=my%20note

but it does require the vault name to be set. There also seems to be no way to provide any content for the note.

2 Likes

Hi, the new function works with parameter content

obsidian://new?name=my%20name&vault=my%20vault&content=my%20content

will create a new note in your my vault vault, with the name my name and the first line my content.

However, I’ve been fiddling around with scripting for Hook and I can’t get it to work:

set myVault to "myVault"
set myName to $title
set myContent to "[" & $title & "](" & $user_link & ")"
set myNewNote to "obsidian://new?" & "name=" & myName & "&vault=" & myVault & "&content=" & myContent
open location myNewNote
set myURL to "obsidian://open?" & "name=" & myName & "&vault=" & myVault
return myURL

works when I run it in Script Debugger (setting the $title and $user_link variables, obviously) but won’t do anything in Hook.
Any ideas?

1 Like

Does it get as far as trying to fire Obsidian? I’m wondering if the name and vault parameters not being URL encoded might be an issue?

1 Like

==== Update BELOW ====
I’ve tried it with hard coded, very simple names and it doesn’t work. Doesn’t fire obsidian.
In script debugger it works perfectly, so I suspect it may be an issue the way I call “open location” - in the draft script there’s a weird construct that I’ll try to use here…

=== Update ====
Ok, so this sort of works:

set myVault to "BrainForest"
set myName to "$encoded_title"
set myUserLink to "$encoded_link"

set myContent to "[" & myName & "](" & myUserLink & ")"
set myNewNote to "obsidian://new?name=" & myName & "&vault=" & myVault & "&content=" & myContent
set myScript to "open '" & myNewNote & "'"
do shell script myScript
delay 0.4

get "obsidian://hook-get-address"

If I fire it on a web page, I get a new obsidian note with the markdown link that I want. The trick was using the “do shell script” construct, and also using $encoded_title and $encoded_link (swiped from the Ulysses “New Item” script).

BUT -
the web page is hooked to the obsidian note (if I call hook on the web page, it points me to the obs. note), yet the reverse is NOT TRUE: if I call hook on the obsidian note, I get … nothing.

1 Like

If I understand correctly there’s a couple of things missing. I just wrote to the good folks at Obsidian about that:

Congrats and thank you for delivering an API for creating new notes! (Which we heard from our joint users on our forum recently here.)

There seem to be a couple of issues:

  1. Your API does not seem to give us the URL and title of the item in return. That makes the workflow unreliable. Any chance you can return them both in your x-callback-url API? (Drafts and Craft do that, which makes the process seamless).

  2. Your API requires the vault name; but we don’t know what vaults are available.

later email I rephrased point 2:

basically the issue is that: we from the outside do not have visibility vault names; but you do. So if your “new note” x-callback-url would either:
2.a ) provide an option to ask the user which vault they want it in; and/or
2.b) simply create the note in [b.1] the currently open / foreground vault; or [b.2] a default vault

If anyone’s on the Obsidian slack or forum, perhaps they could point to this to help keep the ball rolling.

@bchend here, or Obsidian users, may correct me if I’m missing something.

updated 2021-05-07 12:12. I updated this post after hearing back from @bchend .

2 Likes

@LucB, thanks for stepping in!
The vault issue is important, especially if you want to implement a scalable solution for Hook / Obsidian integration.

But if one accepts the idea of using a “default vault”, I think we already have the items we need:
obsidian://new?vault=myVault&name=myName&content=myContent
creates a note and focuses obsidian on this note,
then
obsidian://hook-get-address
returns the markdown link of said note.

In Script Debugger, with hardcoded values for myVault, myName and myContent, this works, so the obsidian url-scheme should be ok.
The issue here, if we want a quick and dirty implementation of Hook to New Obsidian while the developers give us something more seamless, iis to make the apple script work - and here I have to say I’m stumped.

1 Like

Ok, after much head scratching I realized that
obsidian://hook-get-address
returns the full markdownified link for the new note, whereas Hook seems to be expecting only a URL.

So here’s a New Item script that works most of the time.

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

set myVault to "{YOUR DEFAULT VAULT NAME HERE}"
set myName to "$encoded_title"
set myUserLink to "$encoded_link"
set myLink to "$link"

set myContent to "[" & myName & "](" & myUserLink & ")"
set myNewNote to "obsidian://new?name=" & myName & "&vault=" & myVault & "&content=" & myContent
set myScript to "open '" & myNewNote & "'"
-- Create a new note in Obsidian
do shell script myScript
delay 0.4

-- Get the MD link for this new note on the clipboard
do shell script "open 'obsidian://hook-get-address'"
delay 0.4

-- Extract the MD link from the clipboard
set theNewMDLink to «class ktxt» of ((the clipboard as text) as record)
-- Get only the second part of the MD link (the url)
set oldDelimiters to AppleScript's text item delimiters
set AppleScript's text item delimiters to "]("
set theArray to every text item of theNewMDLink
set AppleScript's text item delimiters to oldDelimiters
set t to item 2 of theArray
set theNewLink to text 1 thru -2 of t
-- Return the URL
return theNewLink

CAVEAT: this works only with Obsidian open on your machine. If it’s closed, results have been random for me - i usually end up with the content inside a “daily note”, but sometimes the script just hangs…

1 Like

so the new item script needs to open the file and then get the address of the file and return it. Is that all it needs to do?

I updated this a bit to deal with a few issues. If the file already exists for some reason, don’t create another file, use the one we have. And if you move the file, the link should still work. And it works regardless of whether Obsidian is running.

If there is a downside, its that you need a plugin. But it’s a pretty good plugin to have anyway if doing stuff like this is useful. Its called Obsidian Advanced URI (GitHub - Vinzent03/obsidian-advanced-uri: Advanced modes for Obsidian URI).

Here is the code I am using:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

set myVault to "ObsidianVault"


on findAndReplaceInText(theText, theSearchString, theReplacementString)
    set AppleScript's text item delimiters to theSearchString
    set theTextItems to every text item of theText
    set AppleScript's text item delimiters to theReplacementString
    set theText to theTextItems as string
    set AppleScript's text item delimiters to ""
    return theText
end findAndReplaceInText

on removeAfterDollars(theText)
	set AppleScript's text item delimiters to "$$$"
	return text item 1 of theText
end removeAfterDollars

set myName to findAndReplaceInText("$encoded_title", "/", "-")
set myUserLink to findAndReplaceInText(removeAfterDollars("$encoded_link"), "/", "%252F")


set myContent to "[" & myName & "](" & myUserLink & ")"
set myNewUrl to "obsidian://advanced-uri?vault=" & myVault & "&filepath=" & myName
set myNewNote to myNewUrl & "&data=" & myContent & "&mode=prepend"
set myScript to "open '" & myNewNote & "'"

do shell script myScript

return myNewUrl

Now this would be a lot easier if encoded link didn’t have the $$$ and the base64 encoded string and if applescript had a built in way to replace text.

2 Likes

Hi,

I am a new user of Hook, and I have a few questions regarding creating new notes, e.g. based on a web page, in Obsidian.

  1. Is it possible to create new Obsidian notes by using template files defined for Obsidian? For instance, the following template:
---
title: {{title}}

tags: ['']

created at: '{{date:YYYYMMDD}}{{time:HHmm}}'
completed at: 
modified at: 
---

# {{title}}

  1. In version 3.2.1 of Hook, one can define Prefix and Suffix when creating new notes. Is it possible to allow for add time stamp also for newly created Obsidian notes, e.g. 202108241456?
  2. If one wants to change the behaviour for Hook To New > Obsidian, should be scripts provided in this forum be included in the Get Address or New Item part of the scripts for Obsidian?

Thanks in advance.

1 Like

After searching on the Hook forum, now I will answer my questions as follows:

1 & 2. It is possible to customize note content and title by using the method in the following post: Obsidian Hook to New - #15 by Wen.
3. The script should be included in the New Item part.

2 Likes

Welcome to the Hook Productivity Forum , @Wen. and thank you for contributing!

Just as an exercise in understanding how hook integrates with JavaScript, I created a javascript version. This has been tested for a full 10 minutes so trust it accordingly :wink:

//JavaScript
(() => {
	// See:
	// https://help.obsidian.md/Advanced+topics/Using+obsidian+URI
	// https://hookproductivity.com/help/integration/creating-integration-scripts/
    'use strict';

    // Constants
    let vault = 'Home'; // <---- Default vault
    let folder = '002 WIP/' // <---- Chosen destination folder (ends with '/') or blank

    let createDateStamp = () => {
        let d = new Date();
        let month = '' + (d.getMonth() + 1);
        let day = '' + d.getDate();
        let year = d.getFullYear();
        if (month.length < 2)
            month = '0' + month;
        if (day.length < 2)
            day = '0' + day;
        return [year, month, day].join('-');
    }

    let prefix = createDateStamp() + ' '; // <---- prefix for the created file, or blank

    // Parameters passed in and substituted by hook itself
    let title = '$title';
    let encodedLink = '$encoded_link';

    // The encoded link has a hook specific suffix ($$$...) we must remove
    let processedEncodedLink = encodedLink.replace(new RegExp('\\$\\$\\$.*', 'g'), '');
    // How many times has this been encoded?!?!?!
    let link = decodeURIComponent(decodeURIComponent(decodeURIComponent(processedEncodedLink)))

    // Can't allow just anything in the title as it messes with sync plugin
    // and links to the document. I'm probably being over cautious here
    let fileName = title
        .replaceAll('$', '-')
        .replaceAll('%', '-')
        .replaceAll('|', '-')
        .replaceAll('?', '-')
        .replaceAll('[', '-')
        .replaceAll(']', '-')
        .replaceAll('(', '-')
        .replaceAll(')', '-')

    let markdownTitle = title
        .replaceAll('[', '-')
        .replaceAll(']', '-')
        .replaceAll('(', '-')
        .replaceAll(')', '-')

    let content =
        '# ' + title + '\n' +
        '\n' +
        '[' + markdownTitle + '](' + link + ')\n';

    // Build the url
    let url = 'obsidian://new' +
        '?vault=' + encodeURIComponent(vault) +
        '&file=' + encodeURIComponent(folder + prefix + fileName) +
        '&content=' + encodeURIComponent(content);

    //console.log(url);
    return url;
})();
1 Like

For the record of this topic, we released a solution using a community plugin (advanced-URI) in Hook Version 3.4.3 (4626, integration v. 201) earlier this month, which we updated on Friday with version 206 of Hook integrations.

See also Using Hook with Obsidian – Hook.

We’ve been communicating with Shida Li, developer of Obsidian. We sent him this late Friday: How to Make Your App Linkable via X-Callback-Url (For App Developers) – Hook, and by this morning he emailed us back this morning saying

Our new hook x-callback-url just went live in the insider build today.

Using obsidian URI - Obsidian Help

We’re having a look.

2 Likes

Here is also some details about this update:

Obsidian URI’s new and hook-get-address actions can now optionally accept x-success as part of the x-callback-url specifications, and will return a name, url, and file (file://) as the returned URL parameters.

https://forum.obsidian.md/t/obsidian-release-v0-14-3-insider-build/34806

2 Likes

Thanks, @Wen , that’s it. There’s an issue remaining with it. We notified Shida Li about it yesterday. It will apparently be in the next Obsidian v0.14.3 Insider build.

2 Likes