質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.30%
Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Q&A

解決済

1回答

1118閲覧

GASでLINEのリッチメニュー(3つのタブ切り替え)を作成したい。

EI12210217

総合スコア2

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

0グッド

3クリップ

投稿2023/11/18 16:26

実現したいこと

GASでLINEのリッチメニュー(3つのタブ)を作成したい。

前提

全くの初心者です。
GASで3つのタブを有したリッチメニューを作成しています。
エイリアス(createRichMenuArias)を実行するとエラーが発生します。
その他はエラーは出ていません。

↓参考にしている動画
https://www.youtube.com/watch?v=gb5O2p1hckw

※ライブラリのスクリプトID(バージョン34)
1KsjhQa6oymhUiACWsAlFTG_XoN8Pnz4px2ekABPjO4tSMX6xRSQMBicy

発生している問題・エラーメッセージ

0:58:38 お知らせ 実行開始
0:58:37 情報 Error:
0:58:37 情報 https://api.line.me/v2/bot/richmenu/alias
0:58:37 情報 Exception: Request failed for https://api.line.me returned code 400. Truncated server response: {"message":"richmenu not found","details":[]} (use muteHttpExceptions option to examine full response)
0:58:38 情報 Error:
0:58:38 情報 https://api.line.me/v2/bot/richmenu/alias
0:58:38 情報 Exception: Request failed for https://api.line.me returned code 400. Truncated server response: {"message":"richmenu not found","details":[]} (use muteHttpExceptions option to examine full response)
0:58:38 情報 Error:
0:58:38 情報 https://api.line.me/v2/bot/richmenu/alias
0:58:38 情報 Exception: Request failed for https://api.line.me returned code 400. Truncated server response: {"message":"richmenu not found","details":[]} (use muteHttpExceptions option to examine full response)
0:58:39 お知らせ 実行完了

該当のソースコード

const bot = new LineBotSdk.client("QPm9+13tS2dh07JVP8Be1lKS6jHW8GKkEmKXshUKcR4Cr1mVo9qgZVuq4F8BLAYd260Tl8T76nkcfhLOwWCIlSCxl5d6FAyATRvY6sUqVEP+cC9tUt223jzJfwdfsFqTNFIG8gLK4GrwIrm8gRhI/wdB04t89/1O/w1cDnyilFU=");
function createRichMenua() {
let richmenu = bot.richmenu({
"name": "リッチメニュー",
"barText": "メニュー",
"size": { "width": 2500, "height": 1686 },
"selected": true,
"areas": [
bot.area({ "x": 0, "y": 0, "width": 833, "height": 350,
"action": bot.aSwitch({"aliasId": "switch-to-a", "data": "change to A"}) }),
bot.area({ "x": 833, "y": 0, "width": 833, "height": 350,
"action": bot.aSwitch({"aliasId": "switch-to-b", "data": "change to B"}) }),
bot.area({ "x": 1666, "y": 0, "width": 833, "height": 350,
"action": bot.aSwitch({"aliasId": "switch-to-c", "data": "change to C"}) }),
]
})
let res = bot.createRichMenu(richmenu);
console.log(res.toString());
}
function createRichMenub() {
let richmenu = bot.richmenu({
"name": "リッチメニュー",
"barText": "メニュー",
"size": { "width": 2500, "height": 1686 },
"selected": true,
"areas": [
bot.area({ "x": 0, "y": 0, "width": 833, "height": 350,
"action": bot.aSwitch({"aliasId": "switch-to-a", "data": "change to A"}) }),
bot.area({ "x": 833, "y": 0, "width": 833, "height": 350,
"action": bot.aSwitch({"aliasId": "switch-to-b", "data": "change to B"}) }),
bot.area({ "x": 1666, "y": 0, "width": 833, "height": 350,
"action": bot.aSwitch({"aliasId": "switch-to-c", "data": "change to C"}) }),
]
})
let res = bot.createRichMenu(richmenu);
console.log(res.toString());
}
function createRichMenuc() {
let richmenu = bot.richmenu({
"name": "リッチメニュー",
"barText": "メニュー",
"size": { "width": 2500, "height": 1686 },
"selected": true,
"areas": [
bot.area({ "x": 0, "y": 0, "width": 833, "height": 350,
"action": bot.aSwitch({"aliasId": "switch-to-a", "data": "change to A"}) }),
bot.area({ "x": 833, "y": 0, "width": 833, "height": 350,
"action": bot.aSwitch({"aliasId": "switch-to-b", "data": "change to B"}) }),
bot.area({ "x": 1666, "y": 0, "width": 833, "height": 350,
"action": bot.aSwitch({"aliasId": "switch-to-c", "data": "change to C"}) }),
]
})
let res = bot.createRichMenu(richmenu);
console.log(res.toString());
}

function uploadRichmenuImagea() {
const file = DriveApp.getFileById("1QzON-DMVYZ8O9i-y50cx9bTS4ZCfR5zc");
const blob = Utilities.newBlob(
file.getBlob().getBytes(),
file.getMimeType(),
file.getName()
);
bot.setRichMenuImage("richmenu-a6e54ef57d4e586cfb8a9c5c9cb06ac3", blob);
}

function uploadRichmenuImageb() {
const file = DriveApp.getFileById("1ry4NJNrT870XM-V4U6hrERn3cgXC9GoO");
const blob = Utilities.newBlob(
file.getBlob().getBytes(),
file.getMimeType(),
file.getName()
);
bot.setRichMenuImage("richmenu-4ae01bf0181bbd7a3a4f9b45e1abf75b", blob);
}

function uploadRichmenuImagec() {
const file = DriveApp.getFileById("1x4PzYPl6ZVfJ4vxjJFYWp0yQo3FStlfU");
const blob = Utilities.newBlob(
file.getBlob().getBytes(),
file.getMimeType(),
file.getName()
);
bot.setRichMenuImage("richmenu-23c24456bfa50e5be17327d5aa1b9cc6", blob);
}

// エイリアス作成
function createRichMenuArias() {
bot.createRichMenuArias("switch-to-a", "richmenu-a6e54ef57d4e586cfb8a9c5c9cb06ac3");
bot.createRichMenuArias("switch-to-b", "richmenu-4ae01bf0181bbd7a3a4f9b45e1abf75b");
bot.createRichMenuArias("switch-to-c", "richmenu-23c24456bfa50e5be17327d5aa1b9cc6");
}

function setDefaultRichMenu() {
bot.setDefaultRichMenu("richmenu-a6e54ef57d4e586cfb8a9c5c9cb06ac3");
}

試したこと

①リッチメニューIDを何度か生成しなおしました。
②エイリアスの作成の削除⇒作成を繰り返しました。

補足情報(FW/ツールのバージョンなど)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YellowGreen

2023/11/19 01:03 編集

既にお気づきまもしれませんが、 uploadRichmenuImagea uploadRichmenuImageb uploadRichmenuImagec の3つを実行しないうちに createRichMenuAlias を実行していませんか? お示しのエラーは、 画像をアップロードしないで実行したときのものと同じです。 先に画像をアップロードする必要があるのですよね。
YellowGreen

2023/11/19 01:09

ちなみに、 次のようにすると、一箇所を書き換えるだけで済むようになります。 const bot = new LineBotSdk.client("xxxxxxxxxxxxxxxxxxxxxxxx"); const image_a_Id = "xxxxxxxxxxxxxx"; const image_b_Id = "xxxxxxxxxxxxxx"; const image_c_Id = "xxxxxxxxxxxxxx"; const richmenu_a_Id = "xxxxxxxxxxxxx"; const richmenu_b_Id = "xxxxxxxxxxxxx"; const richmenu_c_Id = "xxxxxxxxxxxxx"; const aliasId_a = "switch-to-a"; const aliasId_b = "switch-to-b"; const aliasId_c = "switch-to-c"; const area_width = 833; const area_height = 350; // (1) 手動実行して richmenu-Id をログから取得して上に貼り付ける(3回実施する。) function createRichMenu() { let richmenu = bot.richmenu({ "name": "リッチメニュー", "barText": "メニュー", "size": { "width": 2500, "height": 1686 }, "selected": true, "areas": [ bot.area({ "x": 0, "y": 0, "width": area_width, "height": area_height, "action": bot.aSwitch({ "aliasId": aliasId_a, "data": "change to A" }) }), bot.area({ "x": area_width, "y": 0, "width": area_width, "height": area_height, "action": bot.aSwitch({ "aliasId": aliasId_b, "data": "change to B" }) }), bot.area({ "x": area_width * 2, "y": 0, "width": area_width, "height": area_height, "action": bot.aSwitch({ "aliasId": aliasId_c, "data": "change to C" }) }), ] }) let res = bot.createRichMenu(richmenu); console.log(res.toString()); } // (2) 手動実行して画像 A をアップロードする function uploadRichmenuImagea() { const file = DriveApp.getFileById(image_a_Id); const blob = Utilities.newBlob( file.getBlob().getBytes(), file.getMimeType(), file.getName() ); bot.setRichMenuImage(richmenu_a_Id, blob); } // (3) 手動実行して画像 B をアップロードする function uploadRichmenuImageb() { const file = DriveApp.getFileById(image_b_Id); const blob = Utilities.newBlob( file.getBlob().getBytes(), file.getMimeType(), file.getName() ); bot.setRichMenuImage(richmenu_b_Id, blob); } // (4) 手動実行して画像 C をアップロードする function uploadRichmenuImagec() { const file = DriveApp.getFileById(image_c_Id); const blob = Utilities.newBlob( file.getBlob().getBytes(), file.getMimeType(), file.getName() ); bot.setRichMenuImage(richmenu_c_Id, blob); } // (5) 手動実行でエイリアスを一括作成する function createRichMenuArias() { bot.createRichMenuArias(aliasId_a, richmenu_a_Id); bot.createRichMenuArias(aliasId_b, richmenu_b_Id); bot.createRichMenuArias(aliasId_c, richmenu_c_Id); } // (6) 手動実行でデフォルトのエイリアスを指定する function setDefaultRichMenu() { bot.setDefaultRichMenu(richmenu_a_Id); } // 手動実行でエイリアスを変更する function updateRichMenuArias() { bot.updateRichMenuArias(aliasId_a, richmenu_a_Id); bot.updateRichMenuArias(aliasId_b, richmenu_b_Id); bot.updateRichMenuArias(aliasId_c, richmenu_c_Id); } // 手動実行でエイリアスを削除する function deleteRichMenuArias() { bot.deleteRichMenuArias(aliasId_a); bot.deleteRichMenuArias(aliasId_b); bot.deleteRichMenuArias(aliasId_c); } // 手動実行でリッチメニューを削除する function deleteRichMenu() { bot.deleteRichMenu(richmenu_a_Id); bot.deleteRichMenu(richmenu_b_Id); bot.deleteRichMenu(richmenu_c_Id); }
YellowGreen

2023/11/19 05:42 編集

// 手動実行でリッチメニューIDのリストを配列で取得する function getRichMenuIds() { const response = JSON.parse(bot.getRichMenuList().getContentText()); if (response.richmenus) { const richMenus = response.richmenus; const richMenuIds = richMenus.map(v => v.richMenuId); console.log(richMenuIds); return richMenuIds; } else { return response; } } // 手動実行でリッチメニューエイリアスIDのリストを配列で取得する function getRichMenuAliasIds() { const response = JSON.parse(bot.getRichMenuAriasList().getContentText()); if (response.aliases) { const richMenuAliases = response.aliases; const richMenuAliasIds = richMenuAliases.map(v => v.richMenuAliasId); console.log(richMenuAliasIds); return richMenuAliasIds; } else { return response; } }
EI12210217

2023/11/19 08:19

早速のご回答有難うございます! 試してみて、ご報告致します!
guest

回答1

1

ベストアンサー

①リッチメニューIDを何度か生成しなおしました。
②エイリアスの作成の削除⇒作成を繰り返しました。

とのことなので、「すでに削除済み、もしくは間違ったメニューIDに対して、createRichMenuAriasを実行してしまっている」というのが本当のところだと思います。

質問者さんのコードを見るに、複数のリッチメニューに対して、個別に手動でリッチメニューIDを発行、画像の紐付けとエイリアスの紐付けを行うようです。

LINE Messaging APIの仕様として、重複してリッチメニューIDを設定しようとしてもエラーになるので、、IDを生成し直したりしてうまくいかなかったりしたら、また個別に削除して・・・みたいなことを繰り返したのでしょう。

これ、気を抜いたり疲れていたりすると、絶対に下記のことが起こります。

  • IDのコピペを間違う
  • 一部のメニューIDの修正を忘れる
  • 関数の実行手順の順番を間違う
  • 一部の関数の実行を忘れる

なので、面倒で間違いの起こしやすい、手動書き換えや個別実行は極力排除するべきです。

で、そのような面倒なことをしないで済むようにしたのが下記のコードです。

(サイズやエイリアスの個数は固定なので、その意味での汎用性はありません。切り替える画像を3枚以外の枚数にしたい、別のサイズの画像を使いたい、等の場合は、修正する必要があります)

使い方

「メニューA~Cの画像ファイルID」となっている部分を適宜変えてから、「createRichMenus」 を実行してください。
(関数名の末尾にアンダーバーをつけると、GASのエディタでは実行対象として表示されません。これにより誤って個別実行すべきでない関数を実行してしまうことを防いでいます)

js

1const bot = new LineBotSdk.client("*********************"); 2 3 4function createRichMenus() { 5 // 現在のリッチメニュー設定をいったん削除する。 6 deleteAllRichMenu_(); 7 8 // リッチメニューAを作成し、画像をアップロードする 9 const richmenu_id_a = createRichMenu_() 10 uploadRichmenuImage_("メニューAの画像ファイルID", richmenu_id_a) 11 12 // リッチメニューBを作成し、画像をアップロードする 13 const richmenu_id_b = createRichMenu_() 14 uploadRichmenuImage_("メニューBの画像ファイルID", richmenu_id_b) 15 16 // リッチメニューCを作成し、画像をアップロードする 17 const richmenu_id_c = createRichMenu_() 18 uploadRichmenuImage_("メニューCの画像ファイルID", richmenu_id_c) 19 20 // デフォルトメニューをAに指定する。 21 bot.setDefaultRichMenu(richmenu_id_a) 22 23 // 各メニューのエイリアスを紐づける 24 bot.createRichMenuArias("switch-to-a", richmenu_id_a); 25 bot.createRichMenuArias("switch-to-b", richmenu_id_b); 26 bot.createRichMenuArias("switch-to-c", richmenu_id_c); 27} 28 29 30// 現在設定されているリッチメニューを全部削除する。 31function deleteAllRichMenu_() { 32 const richMenuAliasList = JSON.parse(bot.getRichMenuAriasList().toString()); 33 try { 34 for (const alias of richMenuAliasList.aliases) { 35 console.log(`メニュー設定を削除しています...:${JSON.stringify(alias)}`); 36 bot.deleteRichMenuArias(alias.richMenuAliasId); 37 bot.deleteRichMenu(alias.richMenuId); 38 } 39 } catch (e) { 40 console.log(e); 41 return; 42 } 43 console.log("メニュー設定の初期化が完了しました。"); 44} 45 46 47// リッチメニューのタップ領域やエイリアスの初期設定を行う。 48function createRichMenu_() { 49 let richmenu = bot.richmenu({ 50 "name": "リッチメニュー", 51 "barText": "メニュー", 52 "size": { "width": 2500, "height": 1686 }, 53 "selected": true, 54 "areas": [ 55 bot.area({ 56 "x": 0, "y": 0, "width": 833, "height": 350, 57 "action": bot.aSwitch({ "aliasId": "switch-to-a", "data": "change to A" }) 58 }), 59 bot.area({ 60 "x": 833, "y": 0, "width": 833, "height": 350, 61 "action": bot.aSwitch({ "aliasId": "switch-to-b", "data": "change to B" }) 62 }), 63 bot.area({ 64 "x": 1666, "y": 0, "width": 833, "height": 350, 65 "action": bot.aSwitch({ "aliasId": "switch-to-c", "data": "change to C" }) 66 }), 67 ] 68 }) 69 70 let res = bot.createRichMenu(richmenu); 71 console.log(`リッチメニューの初期設定が完了しました:${res.toString()}`); 72 return JSON.parse(res).richMenuId; 73} 74 75 76// 指定した画像ファイルIDの画像をアップロードし、同時に指定したリッチメニューIDと紐づける。 77function uploadRichmenuImage_(imageFileId, richmenuId) { 78 const file = DriveApp.getFileById(imageFileId); 79 const blob = Utilities.newBlob( 80 file.getBlob().getBytes(), 81 file.getMimeType(), 82 file.getName() 83 ); 84 console.log(`画像 ${imageFileId} をアップロード中...`); 85 try { 86 bot.setRichMenuImage(richmenuId, blob); 87 console.log(`画像 ${imageFileId} のアップロード完了\nリッチメニューID 「${richmenuId}」との紐付け完了`); 88 } catch (e) { 89 console.log(e.toString()); 90 } 91}

なお、ライブラリでなぜかエイリアスが「Arias」という綴りになってますが、正しくは「Alias」だと思います。

投稿2023/11/19 04:48

退会済みユーザー

退会済みユーザー

総合スコア0

EI12210217👍を押しています

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

EI12210217

2023/11/19 08:20

早速のご回答有難うございます! アドバイスの方もありがとうございます。 納得です。 試してみて、ご報告致します!
EI12210217

2023/11/28 11:52

ご連絡遅くなり、申し訳ございません。 できました! 見事に面倒なコピペや手順などが省かれ、手間なくうまくいきました! 本当にありがとうございます。 コチラのコードをベースに色々試してみます! 感謝いたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問