📥
Toggl APIで日報用の活動記録を収集する
仕事をしていると、日報という形で一日の業務を報告することもあると思う。
Togglを使えば、業務の記録を可視化できるし、APIを使えば日報に役立つ形式でデータを取得できる。
ので、書いた。
環境
今回は以下の環境で実行するものを作成した。
- Deno 1.40.5
- WSL2 Ubuntu 22.04
Toggl の使い方
- 仕事に関することをまとめるため、
Client
に会社名を設定する - 仕事に関する
Project
は、会社のClient
に属するように設定する - 雑多なタスクは
misc.
というプロジェクトにまとめている
Toggl APIを Deno で叩く
API token の取得
ドキュメントに従い、API token を取得する。
Authentication | Track Your Way
記録したTime Entriesを取得する
Toggl で記録された Time Entries は以下のエンドポイントで取得できる。
- クエリに
start_date
とend_date
を指定することで、その範囲の Time Entries を取得できる -
meta
を指定することで、Client
やProject
などの値も取得できる- 余計にAPIを叩く必要がなくなる
実装
下記は実際の実装例で、 要点は以下の通り。
- API tokenはファイル読み込みにした
- 一日の範囲が 6:00 から 翌 6:00 までとなるように取得する
// report.ts
const d = new Date();
d.setTime(d.getTime() - 6 * 60 * 60 * 1000);
const today = d.toISOString().split("T")[0];
const tomorrow = new Date(d.getTime() + 24 * 60 * 60 * 1000).toISOString().split("T")[0];
const start_date = encodeURIComponent(today + "T06:00:00+09:00");
const end_date = encodeURIComponent(tomorrow + "T06:00:00+09:00");
const endpoint = `https://api.track.toggl.com/api/v9/me/time_entries?start_date=${start_date}&end_date=${end_date}&meta=true`;
const api_token = (await Deno.readTextFile("api_token.txt")).trim();
const res = await fetch(endpoint, {
method: "GET",
headers: {
"Content-Type": "application/json",
"Authorization": `Basic ${btoa(`${api_token}:api_token`)}`,
},
});
const data = await res.json();
type Entry = {
"client_name": string;
"project_name": string;
"description": string;
"duration": number;
};
const client = "会社名";
const work_entries = data.filter((entry: Entry) => entry.client_name === client);
// Projectごと、タスクごとに集計する
type Summary = Record<string, Record<string, number>>;
const summary: Summary = {};
for (const entry of work_entries) {
const project = entry.project_name;
const task = entry.description;
const duration = entry.duration;
if (!summary[project]) {
summary[project] = {};
}
if (!summary[project][task]) {
summary[project][task] = 0;
}
if (duration > 0) {
summary[project][task] += duration;
}
}
// 集計結果を markdown 書式で扱いやすい形にする
// Project 「misc.」 だけはあとで表示する
for (const project in summary) {
if (project === "misc.") {
continue;
}
console.log(`### ${project}`);
for (const task in summary[project]) {
const duration = summary[project][task] / 3600;
console.log(`- ${task}: ${duration.toFixed(2)}h`);
}
console.log("");
}
if (summary["misc."]) {
console.log("### misc.");
for (const task in summary["misc."]) {
const duration = summary["misc."][task] / 3600;
console.log(`- ${task}: ${duration.toFixed(2)}h`);
}
}
使い方
deno run --allow-net --allow-read report.ts
WSLの外(クリップボード)に引き渡す
deno run --allow-net --allow-read report.ts | iconv -t utf-16 | clip.exe
Discussion