Google Apps ScriptでSlackに毎朝Google Calendarの予定を流す

予定が入っているのを忘れて困ったことになったので、毎朝Slackにその日と次の日の予定を流すようにしてみました。 初めてGoogle Apps Script触ったけど、サーバ無しでもcronっぽいことできるし日常を便利にするのにすごく使えそう。

下のコードを日タイマーで午前6時〜7時に動くように設定して終了! (calendarIdはGoogle Calendarの設定を開いて、"カレンダーのアドレス"を見る。Slackの投稿先URLはIncoming Webhookの設定してURL見る。)

function notifyEvents() {
  var today = new Date();
  var tomorrow = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1);
  _notify(_text(today) + "\n\n" + _text(tomorrow));
}

function _events(date) {
  var calendarId = 'xxxxxxxxxx';
  var events = CalendarApp.getCalendarById(calendarId).getEventsForDay(date);
  var results = [];
  for (var i = 0, l = events.length; i < l; i++) {
    var event = events[i];
    var s = '';
    if (!event.isAllDayEvent()) {
      s = _hhmm(event.getStartTime()) + '-' + _hhmm(event.getEndTime());
    }
    results.push(event.getTitle() + s);
  }
  return results;
}

function _hhmm(date) {
  return Utilities.formatDate(date, 'GMT+0900', 'HH:mm');
}

function _notify(text) {
  var payload = {
    text: text,
    channel: '#general',
    username: '今日と明日の予定',
    icon_emoji: ':calendar:'
  }
  var url = 'https://hooks.slack.com/services/xxxxxxxxxx/xxxxxxxxxx/xxxxxxxxxx';
  UrlFetchApp.fetch(url, { method: 'POST', payload: JSON.stringify(payload) });
}

function _text(date) {
  var events = _events(date);
  var mmdd = Utilities.formatDate(date, 'GMT+0900', 'MM/dd');
  var text;
  if (events.length > 0) {
    text = mmdd + "の予定:\n" + events.join("\n")
  } else {
    text = mmdd + 'の予定はありません'
  }
  return text;
}

Slackに特定ブランチへのpushを通知する

この記事はアクトインディ技師舞台報告書に自分が投稿したものの転載です。

--以下転載--

こんにちは、komatsuです。

日付が変わってしまいましたが、この記事はアクトインディ Advent Calendar 2015の19日目の記事です。ネムイ(´・ωゞ)

翌20日目の記事は、hondaによるAndroidアプリ開発用のCI環境を作ろうです。

さて、弊社ではチケット管理にRedmineを使っていて、 新機能開発などの大きめのチケットには、Slackにそれ専用のチャンネルが立つことがあります。 (メンバーはそのチケットの担当プログラマ、デザイナ、ディレクタ)

ですが、

  • (ディレクタはGitHubのcommit logを見ないので)バグ対応などの細かいタスクの進捗を報告するのが面倒
  • 特に話し合うことが無いと更新が全くなくて若干寂しい

という個人的な問題がありました。 なので、そのチケットに関連するブランチへのpush内容をチャンネルに通知できたら、上記の問題が多少改善するのでは?と考え、このようなコードを書いてhubotに反映してみました。

( on で通知するブランチを登録できて、off で解除できます。)

直近の大きめチケットで実際に運用してみましたが、個人的には上記の問題は改善された気がしています。

できるだけ手間をかけずに情報共有できたらいいですよね。

それではみなさん、より良い開発環境を!

ActiveSupportのString#inquiry便利

例えば、Railsのviewでタブ的なものを書いていて、選択されているタブを表現するのに

/ hoge.html.slim
= render 'tab', current: 'hoge'

/ _tab.html.slim
li class=('active' if current == 'hoge') hoge
li class=('active' if current == 'huga') huga  

と書くより、

/ hoge.html.slim
= render 'tab', current: 'hoge'

/ _tab.html.slim
current = current.inquiry
li class=('active' if current.hoge?) hoge
li class=('active' if current.huga?) huga  

って書くほうがメッセージっぽくて良さそうな気がする。

実装はこんな感じで、method_missingで処理してるので速度気にしてるとアレかもしれない。

def method_missing(method_name, *arguments)
  if method_name[-1] == '?'
    self == method_name[0..-2]
  else
    super
  end
end

https://github.com/rails/rails/blob/master/activesupport/lib/active_support/string_inquirer.rb

出社したらSlackで自動的に挨拶する

これはアクトインディ技師舞台報告書に自分が投稿したものの転載です。

--以下転載--

こんにちは、komatsuです。

この記事はアクトインディ Advent Calendar 2015 の11日目の記事です。 前日の記事がハードコアだったので今日は軽いものを。

さて、弊社では週2日程度のリモート勤務が認められています。 リモートだと居るかいないかが特に分かりづらいためでしょうか、勤務開始時にSlackで挨拶をするのが習慣になっているようです。 が、別に出社しているときでも挨拶はしてよいもののはずです。というかリモートからは社内の様子が分かりにくいので、リモートであろうとなかろうとSlack上で挨拶してくれればいいのになーと思っています。

(※ 勤務開始時間は自由に設定できるため人によってバラバラ)

というわけで出社のときでも挨拶するように個人的に心がけているのですが、出社している安心感からかどうしても忘れがちでした。 忘れないためにリマインドするのも悪くはないのですが、いっそ忘れてもいいように自動化してしまいたいところです。

やってみる

出社時間はまちまちなため、社内の無線LANに入ったときをきっかけにしてSlackに挨拶を投稿すればよさそうです。

SlackのTokenを取得

プログラムからSlackに投稿できるように、Tokenを取得します。 https://api.slack.com/web のAuthenticationでCreate tokenすればokです。

スクリプトを作成

こんな感じ(↓)の雑なスクリプトを書いて ~/hello に置きました。 Wi-Fiの接続先が会社のものだったときに、1日1回まで挨拶をSlackに投稿します。

# 1日1回
require 'date'
path = '/Users/nomnel/hello/last'
return if File.exists?(path) && Date.parse(File.read(path)) == Date.today

x = `networksetup -getairportnetwork en0`.match(/Current Wi-Fi Network: (.+)/)
return unless x
ssid = x[1]
if %w(office).include?(ssid)
  params = {
    token: 'ここにToken',
    channel: '#general',
    text: 'おはようございます',
    as_user: 'true',
  }.map {|k, v| "#{k}=#{v}" }.join('&')

  require 'uri'
  url = "https://slack.com/api/chat.postMessage?#{URI.encode(params)}"
  `curl "#{url}"`

  File.write(path, Date.today.to_s)
end

launchdで自動実行

~/Library/LaunchAgents/hello.plist を作成し、中身を以下のようにします。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>Hello</string>
  <key>ProgramArguments</key>
  <array>
    <string>/Users/nomnel/.rbenv/shims/ruby</string>
    <string>/Users/nomnel/hello/run.rb</string>
  </array>
  <key>StartInterval</key>
  <integer>60</integer>
</dict>
</plist>

あとは launchctl load ~/Library/LaunchAgents/hello.plist して読み込んでおき、 出社してPCを開けば…

えびでんす

できましたね!

最後に

アクトインディではとりあえず自動化したがる横着なエンジニアを募集しています!

Git リモートのマージ済みブランチを削除する

github.com

をインストールして

git checkout master && git fetch origin && git remote prune origin && git-prune-remote-branch

する。

git-prune-remote-branch、以前は自作スクリプトでやってたけど、gemあるならそっち使った方が気楽という気持ち。

コピペした.sshだと警告が出てgit cloneできなかった

経緯

OSをクリーンインストール後、退避しておいた.sshをコピペしてgit cloneしようとしたら下の警告が出て失敗した。

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/Users/nomnel/.ssh/id_rsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "/Users/nomnel/.ssh/id_rsa": bad permissions
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

原因と対策

秘密鍵パーミッションが0644になっていてtoo openだと怒られているので

chmod 0600 ~/.ssh/id_rsa

して解決。