EPGStationの録画ログをGoogle Calendarに保存する

EPGStation to Google Calendar

というのをGoogle Apps Scriptでやってみた。 これを定期的に実行すればGoogle Calendarで録画済番組が見れて便利かもしれないという試み。予約のカレンダーもあると便利かもしれない。

function updateEpgstation() {
  var baseUrl = "https://epgstation.example.com";
  var calId = "YOUR_CALENDAR_ID";
  // BASIC 認証の場合
  var account = "dankogai:kogaidan";
  var calendar = CalendarApp.getCalendarById(calId);
  var apiUrl = baseUrl + '/api/recorded?isHalfWidth=true';
  var res = UrlFetchApp.fetch(apiUrl, {
    'method': 'get',
    'headers': {
      'Authorization': Utilities.base64Encode(account),
    }}
  );
  var reserves = JSON.parse(res.getContentText());
  var events = [];
  reserves.records.forEach(function(record) {
    var event = {};
    event.title = record.name;
    event.start = new Date(record.startAt);
    event.end = new Date(record.endAt);
    event.description = record.description + "\n" + record.extended + 
      "\n" + baseUrl + "/#/recorded/detail/" + record.id;
    events.push(event);
  });
  mergeAndUpdate(calendar, events);
}

// カレンダーの既存の予定にマージ
function mergeAndUpdate(calendar, newSchedules) {
  var range = getScheduleRange(newSchedules)
  Logger.log("range: "+ range[0] + "~" + range[1])
  var currentEvents = calendar.getEvents(range[0], range[1])
  var dontAdd = []
  var done = []
  currentEvents.forEach(function(event){
    var line = event.getStartTime().getTime() + event.getTitle()
    if (done.indexOf(line) > -1)
    {
      Logger.log("delete duplicate event" + event.getTitle())
      event.deleteEvent()
      return
    }
    done.push(line)

    var exists = false
    newSchedules.forEach(function(schedule){
      if (
        schedule.start.getTime() < new Date(2010, 1, 1).getTime() ||
        schedule.title == event.getTitle() &&
        schedule.start.getTime() == event.getStartTime().getTime() &&
        schedule.end.getTime() == event.getEndTime().getTime() &&
        schedule.description.length == event.getDescription().length/* &&
        schedule.location == event.getLocation()*/)
      {
        if (dontAdd.indexOf(schedule) > -1)
        {
          Logger.log("duplicate " + schedule.title)
          event.deleteEvent()
        }
        else
        {
          dontAdd.push(schedule)
          Logger.log("already created " + schedule.title)
        }
        exists = true
        return
      }
    })
    if (!exists && event.getStartTime().getTime() > range[0].getTime())
    {
      Logger.log("delete " + event.getTitle())
      event.deleteEvent()
    }
  });
  // 新しいスケジュールを追加
  newSchedules.forEach(function(schedule){
    if (schedule != null && dontAdd.indexOf(schedule) < 0)
    {
      Logger.log("create " + schedule.title)
      if ("allDay" in schedule && schedule.allDay)
      {
        var createAllDay = calendar.createAllDayEvent(schedule.title, schedule.start,
          { description: schedule.description, location: schedule.location})
      }
      else
      {
        var created = calendar.createEvent(schedule.title,
          schedule.start, schedule.end, { description: schedule.description, location: schedule.location})
      }
      Utilities.sleep(100)
    }
  });
}

// どの期間のカレンダー予定を取得すればいいかを判定
function getScheduleRange(schedules) {
  var start
  var end
  schedules.forEach(function(schedule){
    if (start == null || schedule.start < start)
    {
      start = schedule.start
    }
    if (end == null || end < schedule.end)
    {
      end = schedule.end
    }
  })
  return [start, end]
}
published at