会議に遅刻するのはよくないので事前に通知がほしい

こんにちは。エンジニアの井上です。
好きな食べ物は冷凍餃子です。家の近くのスーパーが日曜日になると冷凍食品がやすいのでうどんと冷凍餃子は絶対に買って帰ります。

さて、社会人になってからもうすぐ10ヶ月が経とうとしているわけですが、未だに「作業に集中していてミーティングの時間忘れてた」という現象が起きることがあります。本当によくありません。

誰か教えてくれればいいのに…なんて思ってましたが教えてくれるヤツを作ればいいことに気づいたので作りました。

通知プログラムを作ろう

ChatworkのAPIを叩こう

Chatworkで通知がくれば必ず気づきます。
ミーティングのセット、設備予約などは社内ツールのスケジューラで行っているのですが、これは自分でみなきゃいけないのがめんどくさいです。それに時間がきても教えてくれません。

ということでChatworkで通知を送ってくれる物にします。

今回使う言語はC#、フレームワークは.NET Core 2.2です。
家のPCに入ってたVisual Studioが2017なのですが、.NET Core 3.XはSDKの方が対応してないみたいです。しょんぼり。

まず、ChatworkのAPIキーを取得する必要があります。OAuthはやりません…

自分のアカウントから通知来てたら意味わからなくなるので、新しくアカウントを作りました。今回の用途であれば無料プランで十分です。

右上のメニューからAPI設定の画面に入り、パスワードを入力するとAPIをキーがもらえます。簡単ですね。

もう少しです。C#での実装に移ります。

APIキーをHTTPヘッダの「X-ChatWorkToken」にセットし、Chatwork APIドキュメントに従ってGETなりPOSTなりするとChatworkでメッセージを送ったり、取得したり、タスク追加したりできます。
(このあたりの実装ちょっと怪しいので載せるのはやめておきます?)

私はChatwork APIのエンドポイントURLに近い書き方になるように実装してみました。インデクサやら何やらを駆使しています。

たとえば、メッセージ送信のAPIだと下記のエンドポイントにPOSTメソッドでメッセージ送信ができますが…

https://api.chatwork.com/v2/rooms/{room_id}/messages

C#の方はこうなってます。

var token = Token.Create("api_key");
token.Rooms["room_id"].Messages.Post("こんにちは");

指定時間に通知しよう

だいたい10分おきくらいにスケジュールを取得しながら時間になったらChatworkでメッセージをPOSTしてあげます。

プログラム内に「やることリスト」を一つ持っておいて、ループで監視する方式にしました。「やること」には「何時何分にやるか、繰り返し行うのか、繰り返すなら何分おきなのか」も含まれます。

もっといい方法ある気もしますが…

internal class ScheduledTaskManager
{
	/// <summary>
	/// 実行
	/// </summary>
	public void Run()
	{
		while (true)
		{
			var tasks = this.Tasks.Where(t => t.StartsAt <= DateTime.Now).ToArray();

			foreach (var task in tasks)
			{
				if (DateTime.Now < task.StartsAt.AddMinutes(1))
				{
					task.Action();
				}

				if (task.IsRepeatTask)
				{
					this.Tasks.Add(
						new Task
						{
							Action = task.Action,
							IsRepeatTask = task.IsRepeatTask,
							RepaatInterval = task.RepaatInterval,
							StartsAt = task.StartsAt + task.RepaatInterval,
						});
				}

				this.Tasks.Remove(task);
			}

			Thread.Sleep(1000);
		}
	}

	/// <summary>タスク</summary>
	public List<Task> Tasks { get; set; } = new List<Task>();
}

プログラムの開始時にスケジューラからデータを取得し、指定時刻にタスクとしてセットしておくとあとはその時間にプログラムが実行されます。

スケジュールはその日に変更されることもあるので、開始時のスケジュール取得の処理は15分毎に行います。

それにしても、C#はAction<>やFunc<>がすごく便利です。Javaでやるとすごくめんどくさかった気がします。話が逸れますが検査例外が生理的に無理です。Thread.sleepだけでcatchを要求されるのがゆるせません。(個人の見解です)

動かしてみよう

.NET Coreは.NET Frameworkと違い、Releaseビルドしただけでは.exeファイルは吐いてくれません。マルチプラットフォームのフレームワークなので突然Windowsのexeファイルが出てくるほうがおかしいのですが。

ということでdotnetコマンドでexeファイルを作ります。

Windows機で動かすので「win-x64」としてますが、「osx-x64」、「linux-x64」などにすることでそれぞれのOS用にビルドできます。すげー!

C:\WINDOWS\system32>cd "C:\vsproj\W2ScheduleNotifier"
C:\vsproj\W2ScheduleNotifier>dotnet publish -c Release -r win-x64

とりあえずタスクスケジューラに登録してシステム起動時に裏で動いているようにしました。会社のPCはつけっぱなしなので一旦これで…

ちなみにアカウント名はとある同期にとある同期がつけたあだ名をそのまま使いました。かわいいでしょ。よちお。

これで会議に遅刻することはなくなりそうですね。自己管理の一環です。

改善点

ひとまず動くものが作れたのですが、いくつか課題があります。

まず、リリースがめんどくさいです。家のPCで開発しても動いてるのは会社のPCなので反映は翌日出社してからです。

また、プログラムはタスクスケジューラによって24時間実行中のためdotnetコマンド叩いても多分エラーになります。なので、タスクスケジューラから一回止めてからビルド作ってdotnetコマンド叩いています。正直だるいです。

時代はCIです。こいつはGitHubでソース管理してるのでなんとかなるはずです。

ということで、つぎはこのツールをAWSに乗せてJenkinsで自動デプロイができるところまでやってみたいと思います!

関連記事

プロジェクトストーリー

技術

コメント

この記事へのコメントはありません。

カテゴリー

TOP
TOP