実現したいこと
macアプリのdraftsのアクションを利用して、入力された文字列の1行目をタスク名としてtoggle trackのタスクを開始したいと考えています。
発生している問題・分からないこと
api tokenによる認証周りはクリアしているようなのですが、jsonの形式が不適切であるというエラーが出てうまくタスクを登録することができません。
エラーメッセージ
error
1Test 2Input title:Test 3Final Title:Test 4Start Time:2024-09-15T22:36:22.158Z 5description:Test 6start:2024-09-15T22:36:22.158Z 7duration:-1 8created_with:Drafts App 9Request Data Object (before stringify):[object Object] 10URLhttps://api.track.toggl.com/api/v9/workspaces/<workspacesID>/time_entries 11Request Data String (after stringify):{"workspace_id":"<workspacesID>,"description":"Test","start":"2024-09-15T22:36:22.158Z","duration":-1,"created_with":"Drafts App"} 12HTTP.request Failed: 400, Unknown error 13Full Response: 14Response Status Code:400 15Response Headers:[object Object] 16Response Text:"JSON is not valid" 17Togglへのタスク追加エラー: 400 18Response Text:"JSON is not valid" 19Script step completed.
該当のソースコード
javascript
1// スクリプトで使用する関数の定義 2const togglApiToken = ''APIToken"; 3const workspaceID = '"workspaceID'; // 手動で取得したワークスペースIDをここに設定 4 5 6// Base64エンコードの関数 7function encodeBase64(input) { 8 const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; 9 let str = input; 10 let output = ''; 11 12 for (let block = 0, charCode, i = 0, map = chars; 13 str.charAt(i | 0) || (map = '=', i % 1); 14 output += map.charAt(63 & (block >> (8 - (i % 1) * 8))) 15 ) { 16 charCode = str.charCodeAt(i += 3/4); 17 if (charCode > 0xFF) { 18 throw new Error("The string to be encoded contains characters outside of the Latin1 range."); 19 } 20 block = (block << 8) | charCode; 21 } 22 23 return output; 24} 25 26// Togglへのタスク追加関数 27function addTaskToToggl(title) { 28 const http = HTTP.create(); 29 const now = new Date(); 30 const startTime = now.toISOString(); // ISO 8601形式で日付をフォーマット 31 //const startTime = now.toISOString().replace('Z', '+00:00'); // "Z"を"+00:00"に置き換える 32 33 console.log("Input title:"+title); 34 35 // タイトルが空または未定義の場合、デフォルト値を設定 36 if (!title || title.trim() === "") { 37 title = "Untitled Task"; 38 console.log("Warning: Empty title. Using default:", title); 39 } 40 41 // 現在時刻をUNIXエポック秒で取得 42 const currentUnixTime = Math.floor(now.getTime() / 1000); 43 44 console.log("Final Title:"+title); 45 console.log("Start Time:"+startTime); 46 47 // Unixエポックからの経過時間を秒単位で計算 48 const duration = -1 * Math.floor(now.getTime() / 1000); 49 50 // リクエストデータを正しく設定 51 let requestData = { 52 "workspace_id": parseInt(workspaceID, 10), // workspace_idを整数として指定 53 "description": title, 54 "start": startTime, 55 "duration": -1, 56 "created_with": "Drafts App" 57 }; 58 59 console.log("description:"+requestData.description); 60 console.log("start:"+requestData.start); 61 console.log("duration:"+requestData.duration); 62 console.log("created_with:"+requestData.created_with); 63 64 console.log("Request Data Object (before stringify):"+requestData); 65 console.log("URL"+`https://api.track.toggl.com/api/v9/workspaces/${workspaceID}/time_entries`) 66 67 let requestDataString; 68 try { 69 requestDataString = JSON.stringify(requestData); 70 console.log("Request Data String (after stringify):"+requestDataString); 71 } catch (e) { 72 console.log("JSON.stringify Error:"+e.message); 73 return false; 74 } 75 76 try { 77 const response = http.request({ 78 "url": `https://api.track.toggl.com/api/v9/workspaces/${workspaceID}/time_entries`, 79 "method": "POST", 80 "data": requestDataString, 81 "headers": { 82 "Authorization": "Basic " + encodeBase64(togglApiToken + ":api_token"), 83 "Content-Type": "application/json" 84 } 85 }); 86 87 console.log("Full Response:", JSON.stringify(response, null, 2)); // 2つのスペースで整形して表示 88 console.log("Response Status Code:"+response.statusCode); 89 console.log("Response Headers:"+response.headers); 90 console.log("Response Text:"+response.responseText); 91 92 if (response.statusCode === 200 || response.statusCode === 201) { 93 console.log("Togglタスクが正常に作成されました。"); 94 return true; 95 } else { 96 console.log("Togglへのタスク追加エラー: " + response.statusCode); 97 console.log("Response Text:"+response.responseText); 98 return false; 99 } 100 } catch (error) { 101 console.log("リクエスト送信中にエラーが発生しました:", error.message); 102 return false; 103 } 104} 105 106 107 108 109// ユーザーに登録先を選ばせる 110function showPrompt() { 111 let p = Prompt.create(); 112 p.title = "ノート登録先の選択"; 113 p.addButton("Notion"); 114 p.addButton("DayOne"); 115 p.show(); 116 return p.buttonPressed; 117} 118 119// 選択されたテキストをブロックとして処理する関数 120function processSelectedTextAsBlock(selectedText) { 121 let lines = selectedText.split("\n").map(line => line.trim()).filter(line => line.length > 0); 122 123 if (lines.length > 0) { 124 let title = lines[0]; // 選択された部分の最初の行をタイトルとする 125 let body = lines.slice(1).join("\n"); // 2行目以降をコンテンツとする 126 127 return {"title":title,"body":body}; 128 } else { 129 app.displayErrorMessage("選択されたテキストが無効です。"); 130 return {"title":"","body":""}; 131 } 132} 133 134//テキスト取得関数 135function getTitleContentsDic() { 136 if (editor.getSelectedText().length > 0) { 137 // 選択されている部分がある場合、その部分を自動的にブロックとして登録 138 let selectedText = editor.getSelectedText(); 139 //1行めをtitle,2行目以降をコンテンツとして取得 140 return(processSelectedTextAsBlock(selectedText)); 141 } else { 142 // Draft全体を1つのNotionページとして登録 143 let title = draft.title; // 1行目をタイトルとして使用 144 let d = draft.lines; 145 d.shift(); // 最初の行を削除して残りをコンテンツとして使用 146 let body = d.join("\n"); 147 return {"title":title, "body":body}; 148 } 149} 150 151 152//メインの実行ロジック 153(function() { 154 // Togglへのタスク追加 155 dic_titleContents=getTitleContentsDic() 156 console.log(dic_titleContents["title"]); 157 158 let taskAdded = addTaskToToggl(dic_titleContents["title"]); 159 if (!taskAdded) { 160 alert("Togglへのタスク登録に失敗しました。詳細はコンソールログを確認してください。"); 161 return; 162 } 163 164 // ユーザーに登録先を選ばせる 165 let choice = showPrompt(); 166 if (choice === "Notion") { 167 alert("Notionへのノート登録を開始します。"); 168 } else if (choice === "DayOne") { 169 alert("DayOneへのノート登録を開始します。"); 170 } else { 171 alert("キャンセルされました。"); 172 return; 173 } 174})();
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
8時間程度あれこれ試しましたが、durationやdescriptionの値をどのように変更してもエラーが解消されません。
補足
分かる方がいらっしゃいましたらよろしくお願いいたします。

バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2024/09/17 21:40