ポモドーロに Session – Pomodoro focus timer with analytics をつかっているのだけど、セッション終了時にそのセッション内容を Obsidian の Daily Note に書き込むようにした記録です。
投稿される内容
- [hh:mm] #session #[カテゴリー]/[目標] [note] `([開始時間] - [終了時間])`
▼こんな感じで Obsidian の Daily Note に追記される

必要なもの
- Obsidian & Advanced URI Plugin
- Mac の『ショートカット』アプリ
1. 準備
Session.app を開いて 設定 > ショートカット で 「Session end」を有効にします。
※ これで、セッション終了時に、ショートカットに登録した 「session_end」というショートカットが実行されるようになります。
ref. Session – Setup session automation on iOS and MacOS with Apple Shortcuts
2. ショートカットの登録
「session_end」という名称でショートカットを作成します。
input
「指定なし」で入力を受け取ります。Session終了後にアプリから引き渡されるデータは以下にまとまっています。
JavaScript for Automation を実行
受け取った値を整形して、Obsidian に Advanced URI をつかって引き渡します。
obsidian://advanced-uri?daily=true&mode=append&openmode=silent&data=[整形した投稿内容]
JavaScript for Automation のコード内容
/**
* Session から受け取ったデータを整形して Obsidian に送信する
* - function run(input, parameters): ショートカットはこの run 関数を実行する。(JXA ではこの関数を定義する必要がある)
* - input : 前のアクションからの入力データ。配列 (Array) になっている。 ほとんどの場合、前のステップから渡されたテキスト(やファイルパスなど)はこの配列の最初の要素にはいっており。 input[0] でアクセスできる。
* - return: この JXA アクションの結果を、さらに次のショートカットアクションに渡したい場合は、run 関数の最後に return で値を返す。
*/
function run(input) {
// アプリケーションと標準機能の準備
var app = Application.currentApplication();
app.includeStandardAdditions = true;
// 入力データを取得
var inputData = getInputParsedJson(input);
if (!inputData) {
return "run : 入力がありません";
}
// 入力データをフォーマット
var { categoryTitle, title, startDate, endDate, notes } = formatInputData(inputData);
// 現在の時間を取得し投稿日時を生成
var prefix = `- ${getNow()}`;
// 投稿データを生成
var tag = `#session #${categoryTitle}`
if ( title ) {
tag += `/${title}`;
}
// - 日付の前後をバッククオートで囲うのはその日付が投稿時間と認識されないように。
var dataToSend = `${prefix} ${tag} ${notes} \`(${startDate} - ${endDate})\``;
// 投稿データを送信するURLを生成
// - advanced-uri : プラグインを使って、Obsidian にデータを送信する
// - daily=true : daily note に送信する
// - mode=append : 追記する
// - openmode=silent : Obsidian を開かずに実行する
// - data= : 送信するデータ
var baseUrl = "obsidian://advanced-uri?daily=true&mode=append&openmode=silent&data=";
// 最終的なURLを組み立て
var finalUrl = baseUrl + encodeURIComponent(dataToSend);
try {
// Obsidian を開く
app.openLocation(finalUrl);
} catch (e) {
app.displayDialog("URLを開けませんでした: " + e);
}
// 次アクションでも input データを利用できるように
return input;
}
/**
* # ショートカットからの input を JSON としてパースする
* - input は配列なので、通常は最初の要素 input[0] に目的のテキストが入っています
* - パース成功したらオブジェクトを、失敗したら null を返します
*/
function getInputParsedJson(input) {
// input 配列自体が空か、要素がない場合は null を返す
if (!input || input.length === 0) {
return null;
}
var receivedInputString = input[0]; // 配列の最初の要素を取得 (JSON文字列のはず)
var receivedData = JSON.parse(receivedInputString);
return receivedData;
}
/**
* # 入力データをフォーマットする
* - sessions.app から渡される json : https://www.stayinsession.com/learn/session-automation-on-ios-and-macos-with-apple-shortcuts
*/
function formatInputData(inputData) {
var category = inputData.category || {};
return {
categoryTitle: category.title || "",
title: inputData.title || "",
startDate: formatDateFromDateString(inputData.start_date || ""),
endDate: formatDateFromDateString(inputData.end_date || ""),
notes: inputData.notes || ""
}
}
/**
* # 日付文字列をフォーマットする
* - 日付文字列を受け取り、HH:MM 形式に変換します。
* @param {string} dateString - ISO 8601 形式の日付文字列
* @returns {string} - フォーマットされた時間 (HH:MM)
*/
function formatDateFromDateString(dateString) {
return formatTime(new Date(dateString));
}
/**
* # 現在の時間を取得する
* @returns {string} - フォーマットされた時間 (HH:MM)
*/
function getNow() {
var now = new Date();
return formatTime(now);
}
/**
* # 時間をフォーマットする
* param {Date} dateObject - 日付オブジェクト
* @returns {string} - フォーマットされた時間 (HH:MM)
*/
function formatTime(dateObject) {
var hour = String(dateObject.getHours()).padStart(2, '0');
var min = String(dateObject.getMinutes()).padStart(2, '0');
return `${hour}:${min}`;
}