ラジコのAPIから放送局を指定し土日のみの番組表をスプレッドシートにシート別に書きだす

ディレクターの方よりある放送局の土日のみラジコの番組表がほしいと相談があったのでGASの勉強兼ねて実装してみました。
ラジコのAPI(v3)を調べてみると以下のような形でXMLが取得できるとのことでした。

```
http://radiko.jp/v3/program/station/date/日付/放送局名.xml
```

実際にできあがったコードが以下になります。
ちょっと無駄な記述もあるかもですがご容赦くださいませ。
こちらをGASのスクリプトエディタに貼り付け「実行」 -> 「関数を実行」 -> 「generate」を選択します。

```Code.gs
// 開始日
const startDate = new Date('2020-05-01');
// 終了日
const endDate = new Date('2020-06-30');
// 放送局名
const broadcaster = 'FM_OKINAWA';

const week = {
  sunday   : 0,
  monday   : 1,
  tuesday  : 2,
  wednesday: 3,
  thursday : 4,
  friday   : 5,
  saturday : 6
};

const weekend = [week.sunday, week.saturday];

function normalizeSheetName(sheetName) {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getActiveSheet();
  sheet.setName(sheetName);
}

function createSheet(sheetName) {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  ss.insertSheet(sheetName);
}

function deleteSheet(sheetName) {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getSheetByName(sheetName);
  ss.deleteSheet(sheet);
}

function deleteOtherThanActiveSheet() {
　const activeSheet = SpreadsheetApp.getActiveSpreadsheet();
　const len = activeSheet.getNumSheets();

　activeSheet.moveActiveSheet(1);

　for (let i = len; 1 < i; i--) {
　　const sheet = activeSheet.getSheets()[i-1];
　　activeSheet.deleteSheet(sheet);
　}
}

function getWeekendArray(start, end) {
  const arr = [];
  const dt = new Date(start);

  while (dt <= end) {
    if (weekend.includes(dt.getDay())) {
      const year = dt.getFullYear();
      const month = ('0' + (dt.getMonth() + 1)).slice(-2);
      const day = ('0' + dt.getDate()).slice(-2);
      
      arr.push({ year, month, day });
    }
    dt.setDate(dt.getDate() + 1);
  }
  
  return arr;
}

function fetchUrl(url) {
  const res = UrlFetchApp.fetch(url, { muteHttpExceptions: true });

  if (res.getResponseCode() !== 200) {
    return null;
  }
      
  return res;
}

function insert(str, index, value) {
  return str.substr(0, index) + value + str.substr(index);
}
    
function formatTime(start, end) {
  return `${insert(start, 2, ':')} 〜 ${insert(end, 2, ':')}`;
}

function getValues(prog) {
  return prog.map((entry) => {
    return [
      formatTime(entry.getAttribute("ftl").getValue(), entry.getAttribute("tol").getValue()),
      entry.getChildText('title'),
      entry.getChildText('pfm')
    ];
  });
}

function generate() {
  if (SpreadsheetApp.getActiveSpreadsheet().getNumSheets() > 1) {
    deleteOtherThanActiveSheet();
  }
  
  const sheetName = `Sheet_${Date.now ()}`;
  normalizeSheetName(sheetName);
  
  const weekendArr = getWeekendArray(startDate, endDate);
        
  weekendArr.forEach((weekend) => {
    const { year, month, day } = weekend; 
    const response = fetchUrl(`http://radiko.jp/v3/program/station/date/${year}${month}${day}/${broadcaster}.xml`);

    if (response) {
      const xml = XmlService.parse(response.getContentText());
      const root = xml.getRootElement();
      const values = getValues(root.getChildren("stations")[0].getChildren("station")[0].getChildren("progs")[0].getChildren('prog'));
      
      createSheet(`${year}/${month}/${day}`);
    
      const sheet = SpreadsheetApp.getActiveSheet();
      sheet.getRange(1, 1, values.length, 3).setValues(values);
    }
  });
  
  deleteSheet(sheetName);
}
```

添付のようにシート別に番組表が書き出せました。
![Jun-12-2020 18-29-18.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596604/7cb518f1-b1a6-f3b8-ceea-8b83f926fd00.gif)

同じ境遇の方はあまりいないとは思うのですが、この記事が誰かのお役に立てれば幸いです。