🐙

Google Apps Scriptで繰り返し作業を自動化した話2 -BIM360との連携

2021/12/11に公開

こちらのスクリプト部分を説明していきます。
https://www.autodesk.com/autodesk-university/forge-content/au_class-urn%3Aadsk.content%3Acontent%3Aa0a4d218-9266-4ec4-a61c-e359fe945a06

Google Apps Scriptでは簡単に外部のWebAPIにアクセスすることができるUrlFetchAppを提供しています。
https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app

こちらを用いてForgeのAPIへアクセスしていきます。共通の設定として以下のものを使用しています。

const base_url = 'https://developer.api.autodesk.com/';

1 Authenticate

1.1 TwoLeggedAccessTokenの取得

今回作成したコードでは別途configにてアプリの設定を行なっている。そのため、必要なものはそちらから取得している。
APIのドキュメントはこちら

https://forge.autodesk.com/en/docs/oauth/v2/reference/http/authenticate-POST/

Responseのstatus codeを取得することで、適切に処理が行われているのかを確認します。
ただ、設定をしないとcodeを取得することができません。必ずoptionmuteHttpExceptions: trueを追加してください。
それによりcodeを取得することが出来る様になります。

function getTwoLeggedToken() {
  var scriptProperties = PropertiesService.getScriptProperties();
  var client_id = scriptProperties.getProperty('clientId'); 
  var client_secret = scriptProperties.getProperty('clientSecret'); 
  var scope = scriptProperties.getProperty('scope'); 
  var body = { 
      'client_id' : client_id, 
      'client_secret' : client_secret, 
      'grant_type' : 'client_credentials', 
      'scope' : scope 
  } 

  var options = { 
    'method': 'post', 
    'contentType': 'application/x-www-form-urlencoded', 
    'payload' : body, 
    muteHttpExceptions: true 
  } 

  var res = UrlFetchApp.fetch(base_url + 'authentication/v1/authenticate', options); 
  if (res.getResponseCode() == 200) return res; 
  else throw("Failed to get Two Legged Access Token.");
} 

1.2 Tokenの取得

Two-Leggedのレスポンスにはaccess_tokenexpires_inが含まれます。一定時間が過ぎるとTokenを再取得する必要があります。
また、時間内であれば再度取得しなくて良いように保存しておくよう設定をしています。

function getToken() {
  config();
  var scriptProperties = PropertiesService.getScriptProperties();
  var expiredDate = new Date(scriptProperties.getProperty('twoLeggedExpiresIn'));
  if ( expiredDate == undefined || expiredDate.getTime() < new Date().getTime())
  {
    var res = getTwoLeggedToken();
    if (res != undefined)
    {
      var token = JSON.parse(getTwoLeggedToken());
      var auth = token.token_type + ' ' + token.access_token; 
      scriptProperties.setProperty('twoLeggedToken', auth);
      expiresIn(token.expires_in);
    }
  }
  return scriptProperties.getProperty('twoLeggedToken'); 
}

function expiresIn(time) {
  var scriptProperties = PropertiesService.getScriptProperties(); 
  var date = new Date(); 
  var expiredDate = new Date(); 
  expiredDate.setSeconds(expiredDate.getSeconds() + time) 
  if (expiredDate > date){ 
    scriptProperties.setProperty('twoLeggedExpiresIn', expiredDate);
  } 
}

2 Projectの取得

Projectの取得にはData Management APIを用いる方法とBIM360 APIを用いる方法がありますが、今回は2Leggedで取得可能なBIM360 APIを使用していきます。

https://forge.autodesk.com/en/docs/bim360/v1/reference/http/projects-GET/

こちらには取得できるプロジェクト数に制限があり、100個までとなっています。そのため、どこから100個取得するのかをoffsetで指定しています。
また、offsetを設定しない場合にはdefault値である0になるようになっています。

function getProjects(offset) {
    config();
    var token = getToken();
    var scriptProperties = PropertiesService.getScriptProperties();
    var accountId = ScriptProperties.getProperty('accountId');
    var headers = {
        Authorization:token
    }
    var url = base_url + 'hq/v1/accounts/' + accountId + '/projects?limit=100';
    var options = {
        'method' : 'get',
        'headers' : headers,
        muteHttpExceptions: true
    }
    if (offset != undefined) {
        url +=  '&offset=' + offset;
    }
    var res = UrlFetchApp.fetch(url, options);
    if (res.getResponseCode() == 200) {
        return res;
    } else {
	throw("Failed to get Projects.");
    }
}

3 Account Userの取得

Userの取得にもProject同様のAPIが用意されています。ただ、問題はProjectに比べてUserは登録人数が膨大になっている可能性があります。そのため、users/serchを使っていく方法を取りました。
Project同様のやり方は以下のとおりです。

https://forge.autodesk.com/en/docs/bim360/v1/reference/http/users-GET/

function getUsers(offset) {
    config();
    var token = getToken();
    var scriptProperties = PropertiesService.getScriptProperties();
    var accountId = ScriptProperties.getProperty('accountId');
    var headers = {
        Authorization:token
    }
    var url = base_url + 'hq/v1/accounts/' + accountId + '/users?limit=100';
    var options = {
        'method' : 'get',
        'headers' : headers,
        muteHttpExceptions: true
    }
    if (offset != undefined) {
        url +=  '&offset=' + offset;
    }
    var res = UrlFetchApp.fetch(url, options);
    if (res.getResponseCode() == 200) {
        return res;
    }
    return;
}

一方で、emailを利用した取得の方法がこちらです。こちらのAPIではname, email, company_nameを単体または複数(AND/OR)の条件で検索することができます。

https://forge.autodesk.com/en/docs/bim360/v1/reference/http/users-search-GET/

function getIserByEmail(email) {
  var emailUrl = email.replace('@', '%40');

  config();
  var token = getToken();
  var scriptProperties = PropertiesService.getScriptProperties();
  var accountId = ScriptProperties.getProperty('accountId');
  var headers = {
      Authorization:token
  }

  var options = {
    'method' : 'get',
    'headers' : headers,
    muteHttpExceptions: true
  }

  var res = UrlFetchApp.fetch(base_url + 'hq/v1/accounts/' + accountId + '/users/search?email=' + emailUrl, option);
  if (res.getResponseCode() == 200) {
      return res;
    } else {
      throw Error("Can't get user by Email");
    }
}

4 Projectへの登録

ここまで来たら登録したいプロジェクトにユーザーを登録するだけです。使用するのはPOST projects/:project_id/users/importとなります。複数名を一括で登録することも可能ですので、コードを少々変更していただければと思います。

https://forge.autodesk.com/en/docs/bim360/v1/reference/http/projects-project_id-users-import-POST/

function posetUserToProject(userId, projectId) {
  var myUserId = 'PUT YOUR USER ID HERE';
  config();
  var token = getToken();
  var scriptProperties = PropertiesService.getScriptProperties();
  var accountId = ScriptProperties.getProperty('accountId');
  var headers = {
      Authorization:token,
      'x-user-id' : myUserId
  }

  var body = [{
    'user_id' : userId,
    'servicies' : {
      'project_administration' : {
        'access_level' : 'admin'
      },
      'document_management' : {
        'access_level' : 'admin'
      }
    }
  }]

  //OR
  /*
  var body = [{
    'user_id' : userId,
    'servicies' : {
      'document_management' : {
        'access_level' : 'user'
      }
    }
  }]
  */
  var options = { 
    'method': 'post', 
    'contentType': 'application/json', 
    'payload' : JSON.stringify(body), 
    muteHttpExceptions: true 
  } 

  var res = UrlFetchApp.fetch(base_url + 'hq/v2/accounts/' + accountId + '/projects/' + projectId + '/users/import',options);
      if (res.getResponseCode() == 200) {
        return res;
    } else {
      throw Error("Can't post user to Project");
    }
}

5 まとめ

Google Sheetと合わせて使うと非常に便利です。
メールアドレスを使って一括登録はBIM360 Teamではできたのですが、BIM360 Docs以降はできなくなってしまいました。少しでもめんどくさい作業がなくなれば良いなと思います。千人単位の登録とかメンドすぎます…

おまけ

config()を勝手に使ってますが、こんな感じにしてあります。
毎度毎度やる必要はないかと思いますが、どのようなプロセスが踏まれるかわからないので、念の為入れてありますが、必要なければ削除することも可能です。

function config() {
  var scriptProperties = PropertiesService.getScriptProperties();
  scriptProperties.setProperties({
  'clientId': 'YOUR CLIENT ID HERE',
  'clientSecret': 'YOUR CLIENT SECRET HERE',
  'scope' : 'account:read account:write',
  'accountId' : 'YOUR ACCOUNT ID HERE'
  })

Discussion