GASからCalendarResourceAPIを叩いてみた（+XmlServiceの説明）

2015/12/15
DirectoryAPIにCalenarResourceAPIが追加されました。

http://qiita.com/mistolteen/items/e15e7f80c0bf1d701b95


#こちらの記事は動作しません

**※こちらの記事のコードはスクリプトでサポートが終了した OAuthConfigを使用しているため現在は動作しません。**
詳しくは http://goo.gl/IwCSaV をご覧ください。

#概要

GoogleAppsScriptから認証してAPIを叩くやり方を試してみました。

今回は[CalendarResourceAPI](https://developers.google.com/admin-sdk/calendar-resource/?hl=ja)を使いました。（ついでにxmlの解析も。）
なお、このコードを実行するにはGoogleAppsの管理者である必要があります。

#処理の流れ
1. 認証
+ APIアクセス
+ 取得したxmlからリソースカレンダーの情報を取得

##認証とAPIアクセス
認証部分はGoogleOAuth_の部分です。なかなかズバリこれというサンプルがなかったので…。
scopeとURLを変更すれば他のGoogleのAPIも叩ける（はず）。


```js:GoogleOAuth_
//Google oAuth
function googleOAuth_(name,scope) {
  var oAuthConfig = UrlFetchApp.addOAuthService(name);
  oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
  oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
  oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
  oAuthConfig.setConsumerKey("anonymous");
  oAuthConfig.setConsumerSecret("anonymous");
  return {oAuthServiceName:name, oAuthUseToken:"always"};
}
```

取得自体は認証したあとにCalendarResourceAPIのURLをUrlFetchAppで叩くだけです。


##XMLからデータを取得
APIを叩くと、結果はxmlで返されるので後はこれを解析してデータを取り出すだけです。

取得したXMLの構造は下記のようになっています。
root下のentry1つ１つがリソースカレンダー情報になっています。その中にapps:propertyにresourceIdなどがAttributeとしてnameとvalueのペアで格納されています。
![resource.png](https://qiita-image-store.s3.amazonaws.com/0/7695/047658f1-5ff0-4e00-bfd7-76395167414c.png)


##XMLについて
XmlServiceでparseしたxmlから子要素を取得するには、名前と名前空間が必要です。

例えばrootからentryの子要素のみを抜き出そうとすると、getChildrenの引数に名前（entry）とデフォルト名前空間を指定します。

namespaceはXmlService.getNamespaceを使います。デフォルト名前空間なので、引数がprefixのみの物を使います。（xmlの頭にあるxmlns。ここでは'http://www.w3.org/2005/Atom' ）

```js:getChildren
var xml = XmlService.parse(response.getContentText());
var root = xml.getRootElement();  
var entries = root.getChildren('entry', XmlService.getNamespace('http://www.w3.org/2005/Atom'));
```


また、最終的に取得したい部分はentry以下のapps:propertyとなっています。
appsという名前空間内にあるので、appsという名前空間と'property'という名前で取得することができます。
（これもxmlファイルの頭にxmlns:appsとして記述されています。）

```js:appsns
var appsns = XmlService.getNamespace("apps", "http://schemas.google.com/apps/2006");

for(var i = 0; i < entries.length; i++){
  var entry = entries[i];
  var properties = entry.getChildren('property', appsns);
}
```

取得したい値はapps:propertyタグの中にあるのでGetAttributeを使います。
今回はnameもvalueも中に入っているので、nameのvalueでどのプロパティか判断してvalueのvalueを割り当てるという判断をしています。
※他にうまいやり方がある？

```js:getAttribute

// 取得可能プロパティ
var resourceId = '',
    resourceCommonName = '',
    resourceEmail = '',
    resourceDescription = '',
    resourceType = '';
    
for(var j = 0; j < properties.length; j++){
  var property = properties[j];
     
  var name = property.getAttribute("name").getValue();
  switch(name){
    case 'resourceId':
      resourceId = property.getAttribute("value").getValue();
      break;
    case 'resourceCommonName':
      resourceCommonName = property.getAttribute("value").getValue();
      break;
    case 'resourceEmail':
      resourceEmail = property.getAttribute("value").getValue();
      break;
    case 'resourceDescription':
      resourceDescription = property.getAttribute("value").getValue();
      break;
    case 'resourceType':
      resourceType = property.getAttribute("value").getValue();
      break;
    default:
      break;
   }
 }

```

#全体ソース
Webアプリとして取得したXMLを表示するソースです。
※サンプルの{domain name}を自分のドメイン名に変えてください。

```js:all
function doGet(e){
  var scope = "https://apps-apis.google.com/a/feeds/calendar/resource/";
  //oAuth
  var fetchArgs = googleOAuth_('cal', scope);
  var url = "https://apps-apis.google.com/a/feeds/calendar/resource/2.0/{domain name}";
  var response = UrlFetchApp.fetch(url, fetchArgs);
  
  var xml = XmlService.parse(response.getContentText());
  var root = xml.getRootElement();
  
  var entries = root.getChildren('entry', XmlService.getNamespace('http://www.w3.org/2005/Atom'));
  
  var appsns = XmlService.getNamespace("apps", "http://schemas.google.com/apps/2006");
  
  var calendars = new Array();
  
  for(var i = 0; i < entries.length; i++){
    var entry = entries[i];
    var properties = entry.getChildren('property', appsns);
    
    // 取得可能プロパティ
    var resourceId = '',
        resourceCommonName = '',
        resourceEmail = '',
        resourceDescription = '',
        resourceType = '';
    
    for(var j = 0; j < properties.length; j++){
      var property = properties[j];
      
      var name = property.getAttribute("name").getValue();
      switch(name){
        case 'resourceId':
          resourceId = property.getAttribute("value").getValue();
          break;
        case 'resourceCommonName':
          resourceCommonName = property.getAttribute("value").getValue();
          break;
        case 'resourceEmail':
          resourceEmail = property.getAttribute("value").getValue();
          break;
        case 'resourceDescription':
          resourceDescription = property.getAttribute("value").getValue();
          break;
        case 'resourceType':
          resourceType = property.getAttribute("value").getValue();
          break;
        default:
          break;
      }
    }
    
    calendars.push({
      resourceId: resourceId,
      resourceCommonName: resourceCommonName,
      resourceEmail: resourceEmail,
      resourceDescription: resourceDescription,
      resourceType: resourceType
    });
  }
  
  Logger.log(calendars);
  
  return ContentService.createTextOutput(response.getContentText()).setMimeType(ContentService.MimeType.XML);
}

//Google oAuth
function googleOAuth_(name,scope) {
  var oAuthConfig = UrlFetchApp.addOAuthService(name);
  oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope);
  oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken");
  oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken");
  oAuthConfig.setConsumerKey("anonymous");
  oAuthConfig.setConsumerSecret("anonymous");
  return {oAuthServiceName:name, oAuthUseToken:"always"};
}
```