VRChatのフレンドがいるワールドをGASを使ってカレンダーに記録する
最近、VRChatのAPIを叩き始め、何か面白いことできないかと思って作ってみた。
GAS(Google Apps Script)には指定したURLにリクエストを出す機能(UrlFetchApp.fetch())がある。
これを用いればVRCのAPIが叩ける。
今回作ったのは、あるフレンドの現在いるワールドをGoogleのスプレッドシートとカレンダーに記録して行くスクリプト。
(本当は自分のいるワールドの記録をとりたかったのだけど、自分のフレンドしか現在いるワールドを取得できないため、自分のワールドを取得できない。)
使う場合は、フレンドの了承が得られてから。
VRChatのAPI
VRChatのAPIで取得できる情報はいろいろある。結構使えなくなってるのも多いけど。
ドキュメントはここ
今回はフレンドの名前から情報を得る、"Get By Name"を使う。
エンドポイントは以下のURL
https://api.vrchat.cloud/api/1/users/[USERNAME]/name
また、ワールドの名前をIDから得るために、"Get World"を用いる
エンドポイントは以下のURL
https://api.vrchat.cloud/api/1/worlds/[ID]
非公式のものなので急に使えなくなる可能性がある。
また、負荷をかけないためにもリクエストは1分間に1度まで。
GAS
Google Apps ScriptはGoogleの各種サービスをスクリプトで制御するもの。
JavaScriptベースなのでWeb業界の人なら新しく覚えることも少ない。
GASは時間ベースのトリガーを使って*分ごとに自動実行というのが行える。
準備
必要なもの
- Googleアカウント
以上
ドライブ上でGASとスプレッドシートを1個ずつ作る。
右クリックすれば作れる。
(GASは最初ないので、"その他->アプリを追加"から追加しておく)
適当にGASとスプレッドシートは名前を付けておく。
スプレッドシートからIDを記録しておく。
(スプレッドシートの編集画面でURLの/d/と/editに囲まれた文字列がID)
スプレッドシートの一行目に以下の画像のように適当にヘッダーを書いておく
Googleカレンダーでワールド記録用にカレンダーを一個作っておく。
そのカレンダーのIDを記録しておく。
実装
以下のスクリプトをGASに書き込む。
自分の環境に合わせてVRChatのID、パスワード、フレンド名、スプレッドシートとカレンダーのIDを埋めておく。
function GetWorldID() {
// アクセス先の情報
var url = "https://api.vrchat.cloud/api/1/users/";
var friendName = "";//追跡するフレンドの名前
url = url + friendName + "/name"
var userid = "";//VRCのユーザ名
var password = ""; //VRCのパスワード
var queryString = "?apiKey=JlE5Jldo5Jibnk5O5hTx6XVqsJu4WJ26";
//スプレッドシートを得るための情報
var SheetId = "";//スプレッドシートのID
var SheetName = "シート1";
var ss = SpreadsheetApp.openById(SheetId);
var Sheet = ss.getSheetByName(SheetName);
var dat = Sheet.getDataRange().getValues(); //シートデータを取得
url = url + queryString;
Logger.log(url);
// GETメソッドのオプション
var options = {
"contentType": "application/json",
"headers" : {"Authorization" : "Basic " + Utilities.base64Encode(userid + ':' + password, Utilities.Charset.UTF_8)},
"muteHttpExceptions" : true
}
try{
var response = UrlFetchApp.fetch(url, options);
var content = response.getContentText("UTF-8");
Logger.log(content);
var json=JSON.parse(response);
Logger.log("WorldIDは" + json["worldId"]);
var WorldID = json["worldId"];
//VRCHATをやっていないときは記録しない
if(WorldID == "offline"){
Logger.log("User id offline");
return 0;
}
var now = new Date();
Sheet.getRange(dat.length+1,2).setValue(WorldID);
Sheet.getRange(dat.length+1,1).setValue(now);
//set Trigger 2分後に起動
var triggerDay = new Date();
triggerDay.setMinutes(triggerDay.getMinutes() +2);
ScriptApp.newTrigger("GetWorldName").timeBased().at(triggerDay).create();
}catch(e){
Logger.log(e.message);
}
}
function GetWorldName() {
deleteTrigger();
var url = "https://api.vrchat.cloud/api/1/worlds/";
var userid = "";//VRCのユーザ名
var password = "";//VRCのパスワード
var queryString = "?apiKey=JlE5Jldo5Jibnk5O5hTx6XVqsJu4WJ26";
var SheetId = "";//スプレッドシートのID
var SheetName = "シート1";
var ss = SpreadsheetApp.openById(SheetId);
var Sheet = ss.getSheetByName(SheetName);
var dat = Sheet.getDataRange().getValues();
var WorldID = Sheet.getRange(dat.length, 2).getValue();
var TheTime = Sheet.getRange(dat.length, 1).getValue();
var TheTime10 = Sheet.getRange(dat.length, 1).getValue();
var options = {
"contentType": "application/json",
"headers" : {"Authorization" : "Basic " + Utilities.base64Encode(userid + ':' + password, Utilities.Charset.UTF_8)},
"muteHttpExceptions" : true
}
try{
url = url + WorldID + queryString;
var response = UrlFetchApp.fetch(url, options);
var content = response.getContentText("UTF-8");
Logger.log(content);
var json=JSON.parse(response);
Logger.log("WorldNameは" + json["name"]);
var WorldName = json["name"];
Sheet.getRange(dat.length,3).setValue(WorldName);
RecordCalender(WorldName, TheTime, TheTime10);
}catch(e){
Logger.log(e.message);
}
}
function RecordCalender(WorldName, TheTime, TheTime10){
var calID = "";//カレンダーのID
var cal = CalendarApp.getCalendarById(calID);
var now = TheTime;
var now10 = TheTime10;
now10.setMinutes(now10.getMinutes() + 10);
cal.createEvent(WorldName, now, now10);
}
function deleteTrigger() {
var triggers = ScriptApp.getProjectTriggers();
for(var i=0; i < triggers.length; i++) {
if (triggers[i].getHandlerFunction() == "GetWorldName") {
ScriptApp.deleteTrigger(triggers[i]);
}
}
}
スクリプトの処理の流れとしては、
- VRCAPIを使ってフレンドの現在いるワールドのIDを取得しスプレッドシートに追加。2分後に2.を起動するトリガーを設定。
2.1 この処理を起動したトリガーを削除。ワールドIDからワールドの名前をVRCのAPIを使って取得し、スプレッドシートに追加。
2.2. カレンダーに記録する。
トリガー設定
トリガー設定前に、必ずGASエディタ画面で1回は実行しておくこと(エディタ画面でctrl + r)。
ワールドIDを取得する関数を10分ごとに呼び出すようにトリガーを追加設定しておく。
トリガーはGASエディタ画面の編集->現在のプロジェクトのトリガーから行える。
結果
記録されたデータは、ワールド名をタイトルにイベントとしてGoogleカレンダーに記録される。(見づらい…)。
Googleカレンダーなので全世界に公開も可能。
はまったとこ
ユーザ名に日本語名が入っていると、リクエストの際にBASIC認証で、UTF-8を指定しておかないといけない。
自分は自分のフレンドにはなれない。
VRCAPIが1分間に1回の制限、GASの実行時間が1日に1時間までの制限があるのであつかいづらい。
今後やりたいこと
今回のスクリプトの改善
カレンダーで見やすいイベント(ワールド名)追加。
- 同じワールドなら表示をまとめる。
10分感覚で情報を取得ているが、もっと狭い感覚で情報を取得する。
WorldIDから名前を取得するときにVRCのAPIを叩かずにスプレッドシートから取得するキャッシュ機能 - どのワールドに長くいたとかの分析機能
APIを用いた別のこと
フレンド登録日をカレンダーに記録するGASの作成。