公式の intra-mart IM-Notice デスクトップアプリは Windows でしか動作せず、しかも 1 アカウントでしか利用できない制限があるので、Go で作り直してみた。
結局 ZeroMQ で Pub/Sub しているだけっぽかったので簡単に作ることができた。
POST /mq/user で SubscribeID を取得するのがポイント。
通知には Beeep を利用、Mac の場合 OS の通知が利用される。
yaml ファイルにベースURLとアカウントのリストを書いておけば起動時にすべてのURLとアカウントに対して接続/購読処理を行い、以降通知を受け取ることができる。
通知履歴は作ってもいいけどどうせ利用しないので実装しなかった。
もし仮に今作るなら Fyne を使うのが流行なのだろうか。
それにしても Go はマジでイケてる。
本調子ならもっといろいろ作ったり勉強したりしたいのだが・・。
MS には Go の Win32 API を作って欲しい。
実行/コンパイル時には以下が必要
brew install libsodium
brew install pkg-config
brew install czmq
brew install zeromq
main.go
func main() {
ctx := context.Background()
accounts, err := account.ReadFromFile()
if err != nil {
beeep.Alert("im_notice(mac)", fmt.Sprintf("%v", err), "assets/warning.png")
log.Fatal(err)
}
endpoints, err := endpoint.NewEndpoints(ctx, accounts)
if err != nil {
beeep.Alert("im_notice(mac)", fmt.Sprintf("%v", err), "assets/warning.png")
log.Fatal(err)
}
commaSeparatedEndpoints := endpoint.CommaSeparatedEndpoints(endpoints)
commaSeparatedSubscribeIDs := endpoint.CommaSeparatedSubscribeIDs(endpoints)
minTTLSeconds := endpoint.MinTTLSeconds(endpoints)
ttlSeconds := minTTLSeconds
for {
sock, err := goczmq.NewSub(commaSeparatedEndpoints, "ping," + commaSeparatedSubscribeIDs)
if err != nil {
beeep.Alert("im_notice(mac)", fmt.Sprintf("%v", err), "assets/warning.png")
log.Fatal(err)
}
defer sock.Destroy()
for {
time.Sleep(1 * time.Second)
ttlSeconds--
if ttlSeconds < 0 {
ttlSeconds = minTTLSeconds
break
}
recvs, err := sock.RecvMessageNoWait()
if err == goczmq.ErrRecvMessage {
continue
}
if err != nil {
beeep.Alert("im_notice(mac)", fmt.Sprintf("%v", err), "assets/warning.png")
log.Fatal(err)
}
if len(recvs[1]) == 4 && recvs[1][0] == 112 && recvs[1][1] == 105 && recvs[1][2] == 110 && recvs[1][3] == 103 {
ttlSeconds = minTTLSeconds
continue
}
payload, err := payload.UnmarshalPayload(recvs[1])
beeep.Notify(payload.Subject, payload.Body, "assets/information.png")
}
}
}