【GAS】GoogleClassroomでコースを削除する方法（Courses.delete）

こんにちは！GoogleAppsScriptを使った業務効率化に夢中の初心者プログラマー、太郎です。

今日は**GoogleAppsScript(GAS)を用いてClassroomでコースを削除する方法**について書いていきたいと思います。

初心者向けですが、javascriptの基本的なルールは押さえておいた方が理解はしやすいと思いますので、まだの方は[Progate](https://prog-8.com/dashboard)でサクッとjavascriptの文法を学習してみてください。

また、初心者が手当たり次第にコードを書いてみて詰まったところやその時の心の声などもつらつらと書いています。やり方のみさっと知りたい方は、最後の[まとめ](#まとめ-googleclassroomでコースを削除する方法)を参照ください。

また、`ReferenceError: Classroom is not defined`とエラーが出てしまった方は、[こちらの記事](https://qiita.com/coticoticotty/items/fd73cf477140349b2809)を参考にしてみてください。
では、早速トライしていきましょう！
##削除したいコースのIDを取得したい
現在は4つのコースに所属しています※すべて自分がオーナーです
![スクリーンショット (57).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108046/3e4aae11-4f32-36ab-567e-4f99bca6b022.png)
一番左の『削除するクラス』というものを削除できるかトライしてみましょう。

まずは[公式ドキュメント](https://developers.google.com/classroom/reference/rest/v1/courses/delete)にdeleteメソッドがあるようです。deleteにはコースのid情報が必要みたいですね。なのでまずは、コースのid情報を取得していきたいと思います。
コース名からid取得できないかなと思ってとりあえず以下のコード書いてみましたが、、、

```javascript
function deleteCourse() {
  //所属しているクラスを取得
  var course = Classroom.Courses.get('name'='GASテスト用クラス');
}
```
全力でエラー出ました。
`GoogleJsonResponseException: API call to classroom.courses.get failed with error: Requested entity was not found.`

全然だめですね。。。公式ドキュメントのgetの部分を読むと、引数にはidしか取得できないみたい。。。そりゃあかんわね。。。

##所属しているコース一覧を取得
特定のコースだけ指定したかったのですが、難しそうなので一旦自分が所属しているコース一覧を取得したいと思います。

```javascript
function deleteCourse() {
  //所属しているクラスを取得
  var myCourses = Classroom.Courses.list().courses;
}
```
こちらで所属しているコースの一覧が取得できました。取得するコース数を絞りたい場合は、list(5)など、数を指定することもできます。
myCoursesは、自分が所属しているコースの**いろんな情報がまとまったオブジェクト**をまとめた配列となっています。
いろんな情報とは、以下のものですね（[公式ドキュメント](https://developers.google.com/classroom/reference/rest/v1/courses)より）

```javascript
{
  "id": string,
  "name": string,
  "section": string,
  "descriptionHeading": string,
  "description": string,
  "room": string,
  "ownerId": string,
  "creationTime": string,
  "updateTime": string,
  "enrollmentCode": string,
  "courseState": enum (CourseState),
  "alternateLink": string,
  "teacherGroupEmail": string,
  "courseGroupEmail": string,
  "teacherFolder": {
    object (DriveFolder)
  },
  "courseMaterialSets": [
    {
      object (CourseMaterialSet)
    }
  ],
  "guardiansEnabled": boolean,
  "calendarId": st
```
上記のidからcalendarIdまでの情報は、１コースごとに一つ必要。そのため、自分が所属しているコースの数だけ、このまとまった情報が得られます。

```javascript
Logger.log(myCourses.length);//myCoursesの配列の数が出力される
```
これを実行すると、今の自分の場合、4が出力されます(画面上には表示されていなくても、招待を断ったクラスやアーカイブして削除したクラスなどもカウントされるみたいです。ちなみに、一番新しいクラスが1番目となります)。
つまり、myCoursesにはid～calendarIdまでの情報セットが3つ格納されているわけですね（配列として）
##所属しているコースの名前とコースidを取得
さて、今回取得したいのは、nameとidなので、上記の結果を利用して、それぞれ取り出してみます。

myCoursesは2次元の配列(配列の中にオブジェクトがある)ため、取り出し方がちょっと注意です。

```javascript
function deleteCourse() {
  //所属しているクラスを取得
  var myCourses = Classroom.Courses.list().courses;

  //myCoursesの1番目のオブジェクトからnameとidを取り出す
  Logger.log(myCourses[0]['name']);
  Logger.log(myCourses[0]['id']);
}
```
私の場合は、最初のコースが消したいものだったので、これで目当てのクラスのIDは得られました。
ちなみに、後日、クラス名からクラスIDを取得するプログラムも書けたので、スマートにやりたい方は、[こちらの記事](https://qiita.com/coticoticotty/items/6d424482182a557a8600)を参考にしてください。
##いざdelete
取得したIDを引数に、deleteメソッドを使えば、きっとうまく削除できるはず。ということでやってみます。

```javascript
  //所属しているクラスを取得
  var myCourses = Classroom.Courses.list().courses;

  var deleteCourseId = myCourses[0]['id'];
  Classroom.Courses.delete(deleteCourseId);
```
残念ながらエラーが出ました。
`TypeError: Classroom.Courses.delete is not a function`
まあ、GoogleAppsScript上で、「delete」が予測で出なかった時点で分かっていたけど、、、
delete関数が使えない。。。公式ドキュメントをしっかり理解出来たら、もっと簡単にできるんだろうけど、、、
検索しても何も出てこない。removeメソッドであれば予測で出てきたので行けるかも！と思ってトライしてみる。

```javascript

  //所属しているクラスを取得
  var myCourses = Classroom.Courses.list().courses;

  var deleteClassId = myCourses[0]['id'];
  Classroom.Courses.remove(deleteClassId);
```
これもエラー。。。
`GoogleJsonResponseException: API call to classroom.courses.delete failed with error: Precondition check failed.`
Preconditon checkとは何なのかが分からない。
removeメソッドで検索しても、deleteメソッドが表示されるだけだからわけ分からないし。。。
この時点で次の1手が思い浮かばず詰み。。。
必死にいろいろと検索かけるも全くヒットしない。。。ただ削除したいだけなのに、、、何だこのハードルは？？？
##使用可能なメソッド一覧から考えてみる
Classroomのあとに「.(ドット)」を打つと、この後に使用可能なメソッド一覧が表示されます。
![スクリーンショット (38).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108046/335f4666-111e-a89f-599f-fdf78888c3dc.png)
やっぱりCoursesくらいしかないですね。
同様にClassroom.Coursesのあとに「.(ドット)」を打つと、この後に使用可能なメソッド一覧が表示されます。
![スクリーンショット (37).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108046/fcc0926f-fee0-444a-8ee1-e3aa8cc18d0e.png)
やっぱりremoveくらいしかそれっぽいメソッドないですね。というかdeleteなんてないじゃん。。。
何なんだ？公式ドキュメントは？？？（この辺で初心者のイライラはマックスです、笑）

`Precondition Check faild.`というエラーがカギを握っていそうなので調べてみると、、、

>Precondition Failed/前提条件が失敗 — ブラウザのリクエストヘッダーに特定の条件が含まれており、サーバーがその仕様を満たしていないことを意味します。

んっ？そもそもdelete（remove）リクエストできないのかな？？？

そういえば、クラスルームのコースを削除するときって、一度アーカイブしてから削除するんですよね。
![スクリーンショット (40).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108046/bd884403-0a5a-aac6-dfe5-e261106b1410.png)
そんなわけで、試しにこのコースをアーカイブしてから、実行してみると、、、
**なんと削除できました！！！**
一度アーカイブさせないとコースは削除できないようです！！！
では、アーカイブをさせればいいわけですが、、、そんなメソッドあったか？？？

実際にアーカイブさせてみた前と後で、コースの情報のどこが変わるかを確認してみました。すると、**アーカイブする前後では、courseStateがACTIVE→ARCHIVEDに変わるのみ**ということがわかりました。

そんなわけで、courseStateをARCHIVEDに書き換えてからやってみたのですが、、、それでも上手くいかない。。。

そして、アーカイブしたコースでも、上手く削除できない時がある。。。
なんだ？何が起きているんだ！？

その後、いろいろ試していみたところ、クラスルーム上から作成したクラスは削除できず、GASから作成したクラスのみ削除できる、ということが分かりました。
##諦めかけたその時・・・
完全に手詰まりして1回諦めたのですが、同じ会社のエンジニア職の友人に助けてもらうことができました！いや～もう本当にプロってすごいのね。。。このエラーで私5時間以上悩んだんだよ。それをすっ！と。。。早くそんなレベルになりたいですね。

コースの情報を更新するには、**オブジェクトを書き換えるだけでなく、patchメソッドを使う必要がある**とのこと。

そんなわけで、1回patchメソッドを使って、一度クラスをアーカイブしてみたいと思います。

```javascript
var myCourses = Classroom.Courses.list().courses;
var deleteClassId = myCourses[0]['id'];

var course = {"courseState": "ARCHIVED"};
Classroom.Courses.patch(course, deleteClassId, {'updateMask':'courseState'}); 
```
patchメソッドは、更新するクラスを指定するパスとしてID、更新するfieldをオブジェクトで渡した上で、更新したfieldはこの情報だよ～というのを、updateMaskで指定してあげる必要があるみたいです。
いざ、実行してみると・・・
![スクリーンショット (59).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108046/92886dc4-0901-9ebd-e5c1-5331641fcfa2.png)
うお～～、アーカイブされておる！！！

最後、これをdeleteしたいので、以下のコードを書き加えて実行したいと思います。

```javascript
Classroom.Courses.remove(deleteClassId);
```
はい、こちらで無事deleteが出来ました！！！
作業としてはすごく単純なのですが、、、詰まって詰まってすごく時間かかっちゃいましたね。。。
解決してくれた友人には本当に感謝です。

では、以上まとめます！
##まとめ-GoogleClassroomでコースを削除する方法
コースの削除を行うコマンドは以下です。

```javascript
function deleteCourse() {
  var deleteCourseId = "○○○○";//取得したいコースのIDを入力
  var course = {"courseState": "ARCHIVED"};//patchメソッドに渡す因数、アーカイブしたい

  // patchメソッドでコースの情報を更新、アーカイブする
  Classroom.Courses.patch(course, deleteCourseId, {'updateMask':'courseState'}); 
  Classroom.Courses.remove(deleteCourseId);
}
```
コース名からIDを取得する関数と組み合わせるとこんな感じです。

```javascript
function deleteCourse() {
  //所属しているクラスの一覧を配列で取得
  var myCourses = Classroom.Courses.list().courses;

  ////取得したいクラスのIDを、クラス名から取得
  var targetCourseName = '○○○○';//取得したいコース名を入力
  for (i = 0; i < myCourses.length; i++) {
    if (myCourses[i]['name'] === targetCourseName) {//targetClassNameに一致するときのみ以下の処理を実施
      var targetCourseId = myCourses[i]['id'];
    } else {
      continue;
    }
  }
  var course = {"courseState": "ARCHIVED"};//patchメソッドに渡す因数、アーカイブしたい

  // patchメソッドでコースの情報を更新、アーカイブする
  Classroom.Courses.patch(course, targetCourseId, {'updateMask':'courseState'}); 
  // アーカイブしたら、remove(delete)メソッドが使えるようになります
  Classroom.Courses.remove(targetCourseId);
}
```
以上、参考になれば嬉しいです。Google Classroom APIは日本語の情報が少ないため、今後も様々トライしてみた結果を記事に書いていきたいと思います！