プライベートで使っている Todo アプリを、Todoist から Microsoft Todo に移行しようかと検討中。もし移行するとなると、リストやタスクを入力し直すのは面倒だ。移行用にプログラム書きたいところ。
Microsoft Todo なら、Microsoft Graph という RESTful API を使えば CRUD できそうだった。SDK もあるところは流石。
Python ではあるけど、Microsoft Graph を使って Microsoft Azure の情報を取得する記事はあった。
自分の場合は C# だし、Microsoft Azure には既にサインアップ済なので、Azure Active Directoy にアプリを登録するところからスタート。
注意点として、一般に公開するアプリの場合は、「サポートされているアカウントの種類」を「任意の組織ディレクトリ内のアカウント(任意の Azure AD ディレクトリ - マルチテナント)と個人の Microsoft アカウント(Skype、Xboxなど)」にしておく必要がありそうだった。
.NET 用の SDK は NuGet からインストール。
OAuth で使うパッケージも併せてインストール。
Microsoft Todo のリストとタスクを CRUD するサンプルを書いてみた。
using Azure.Identity; using Microsoft.Graph; // Microsoft Todo のタスクとリストを CRUD するには // Tasks.ReadWrite の許可が必要。 var scopes = new[] { "Tasks.ReadWrite", }; // 一般ユーザーの Microsoft Todo にアクセスするときは // common を指定すれば良いみたい。 var tenantId = "common"; // Azure AD で登録したアプリケーションの ID (Client ID) var clientId = "YOUR_CLIENT_ID"; // Web ブラウザを表示して、 // ユーザーに Microsoft アカウントにログインしてもらえるよう、 // GraphServiceClient を構成する。 // 最初に API を呼び出すタイミングでブラウザが起動する。 var options = new InteractiveBrowserCredentialOptions { TenantId = tenantId, ClientId = clientId, AuthorityHost = AzureAuthorityHosts.AzurePublicCloud, RedirectUri = new Uri("http://localhost"), }; var interactiveCredential = new InteractiveBrowserCredential(options); var graphClient = new GraphServiceClient(interactiveCredential, scopes); // リスト一覧表示 var todoLists = await graphClient.Me .Todo .Lists .Request() .GetAsync(); foreach (var todoList in todoLists) { Console.WriteLine($"既存のリスト:{todoList.DisplayName}"); } // リスト登録 var createdList = await graphClient.Me .Todo .Lists .Request() .AddAsync(new TodoTaskList { DisplayName = "Test List", }); Console.WriteLine($"登録したリスト:{createdList.DisplayName}"); // タスク登録 var createdTask = await graphClient.Me .Todo .Lists[createdList.Id] .Tasks .Request() .AddAsync(new TodoTask { Title = "Test Task", }); Console.WriteLine($"登録したタスク:{createdTask.Title}"); // リスト内のタスク一覧表示 var tasks = await graphClient.Me .Todo .Lists[createdList.Id] .Tasks.Request() .GetAsync(); foreach (var task in tasks) { Console.WriteLine($"{createdList.DisplayName}:{task.Title}"); } // タスク更新 createdTask.CompletedDateTime = DateTimeTimeZone.FromDateTimeOffset(DateTimeOffset.Now); var updatedTask = await graphClient.Me .Todo .Lists[createdList.Id] .Tasks[createdTask.Id] .Request() .UpdateAsync(createdTask); Console.WriteLine($"更新したタスク:{updatedTask.Title}"); // タスク削除 await graphClient.Me .Todo .Lists[createdList.Id] .Tasks[updatedTask.Id] .Request() .DeleteAsync(); Console.WriteLine($"削除したタスク:{updatedTask.Title}"); // リスト更新 createdList.DisplayName = "Test Updated List"; var updatedList = await graphClient.Me .Todo .Lists[createdList.Id] .Request() .UpdateAsync(createdList); Console.WriteLine($"更新したリスト:{updatedList.DisplayName}"); // リスト削除 await graphClient.Me .Todo .Lists[updatedList.Id] .Request() .DeleteAsync(); Console.WriteLine($"削除したリスト:{updatedList.DisplayName}"); Console.ReadLine();
.NET 6 で実行。自分個人の Microsoft アカウントで試してみた。
まだたいしたリストは登録してなかったけど、一応自分のリスト一覧が表示できていた。CRUD も成功。ただ、SDK の API にクセがあったな。