Google Calendarでスケジュール登録するときの問題
GoogleCalendarAPIでは、イベントを登録すると各イベントごとにユニークなidが自動生成されます。(以下イベントidと呼びます)ただし、これだと登録したあとに一度取得しないと登録したイベントidがわからなかったり、複数人で同じイベントを共有する場合に、それぞれでイベントidが違うので、イベント情報が更新された場合など、一括で更新するのが非常にめんどうです。
これらの問題を解決するために、イベント登録時に独自に生成したidを使う手法を取りたいと思います。
rubyでのコードがほぼなかったので、以下に紹介しておきます。
Google Calendarのイベントidのルール
Google CalendarのAPIドキュメントによると、イベントidは以下のルールに従う必要があります。
Opaque identifier of the event. When creating new single or recurring events, you can specify their IDs. Provided IDs must follow these rules:
characters allowed in the ID are those used in base32hex encoding, i.e. lowercase letters a-v and digits 0-9, see section 3.1.2 in RFC2938
the length of the ID must be between 5 and 1024 characters
the ID must be unique per calendar
Due to the globally distributed nature of the system, we cannot guarantee that ID collisions will be detected at event creation time. To minimize the risk of collisions we recommend using an established UUID algorithm such as one described in RFC4122.
If you do not specify an ID, it will be automatically generated by the server.
Note that the icalUID and the id are not identical and only one of them should be supplied at event creation time. One difference in their semantics is that in recurring events, all occurrences of one event have different ids while they all share the same icalUIDs.
イベントidはRFC2938で定義されているフォーマットに従う必要があります。
ここだとBase32encodeで用いられるa-vおよび0-9で構成された5文字以上1024文字以下の文字列
です。
Rubyでidを生成する
RubyにはBase32encode
できる関数があるのでそちらを使いましょう。
生成するべき文字列は他のイベントidと衝突する可能性を避けるために出来る限りユニークにする必要があります。(自分たちがコントロールできるカレンダーなら問題ないかもしれませんが本人のprimaryのカレンダーなどだといろんなところからイベントが登録されるため)
ref: http://dnsruby.rubyforge.org/classes/Base32.html
module Base32
module_function
HEX = '[0-9a-v]'
def encode32hex(str)
str.gsub(/\G(.{5})|(.{1,4}\z)/mn) do
full = $1; flag = $2
n, c = (full || flag.ljust(5, "\0")).unpack("NC")
full = ((n << 8) | c).to_s(32).rjust(8, "0")
if flag
full[0, (flag.length*8+4).div(5)].ljust(8, "=")
else
full
end
end
end
def decode32hex(str)
str.gsub(/\G\s*(#{HEX}{8}|#{HEX}{7}=|#{HEX}{5}={3}|#{HEX}{4}={4}|#{HEX}{2}={6}|(\S))/imno) do
raise "invalid base32" if $2
s = $1
s.tr("=", "0").to_i(32).divmod(256).pack("NC")[0,(s.count("^=")*5).div(8)]
end
end
end
require 'google/apis/calendar_v3'
# .....省略...
def get_event_uid(event_id)
unique_id = "event#{event_id}" #seedになるべき文字列
#末尾の=は不要なので取り除く
Base32.encode32hex(unique_id).gsub("=","")
end
def add(event)
value = {}
#....カレンダーの情報などを設定...
value[:id] = get_event_uid(event["id"])
value[:i_cal_uid] = "#{id}@google.com"
Google::Apis::CalendarV3::Event.new(value)
end
まとめ
Googleカレンダーのイベントidを独自で生成することができると、わざわざイベントidを保持しておく必要がなく、イベント情報の更新等がある場合に一括で更新が出来るため非常に扱いが楽になります。