node-red-contrib-line-messaging-api 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,7 +12,8 @@
12
12
  outputs:1,
13
13
  icon: "comment.png",
14
14
  align: "right",
15
- label: () => this.name || 'Notify_New',
15
+ paletteLabel: 'Notify',
16
+ label: () => this.name || 'Notify',
16
17
  });
17
18
  </script>
18
19
 
@@ -29,6 +30,8 @@
29
30
  </label>
30
31
  <input type="password" id="node-input-AccessToken" placeholder="LINE Notify AccessToken">
31
32
  </div>
33
+
34
+ <p> ※LINE Notifyは2025/3/31でサービス終了となります。利用をやめてPushメッセージなどに移行してください。 https://developers.line.biz/ja/news/2024/10/07/line-notify-will-be-discontinued/ </p>
32
35
  </script>
33
36
 
34
37
  <script type="text/x-red" data-help-name="Notify_New">
@@ -30,7 +30,7 @@ module.exports = (RED) => {
30
30
  const REQUEST_OPTIONS = {
31
31
  method: 'POST',
32
32
  headers: {
33
- 'Content-Type': 'application/x-www-form-urlencoded',
33
+ 'Content-Type': 'application/json',
34
34
  'Authorization': `Bearer ${LINE_NOTIFY_TOKEN}`
35
35
  },
36
36
  body: new URLSearchParams(params).toString()
@@ -14,7 +14,7 @@
14
14
  outputs: 1,
15
15
  icon: "comment.png",
16
16
  align: "right",
17
- paletteLabel: 'Push_New',
17
+ paletteLabel: 'Push',
18
18
  label: () => this.name || 'PushMessage_New'
19
19
  });
20
20
  </script>
@@ -39,6 +39,13 @@
39
39
  <label for="node-input-targetId"><i class="icon-tag"></i> User Id or Group ID</label>
40
40
  <input type="text" id="node-input-targetId" placeholder="User Id or Group ID">
41
41
  </div>
42
+
43
+ <!-- <div class="form-row">
44
+ <label for="story">Tell us your story:</label>
45
+ <textarea id="story" name="story" rows="5" cols="33">
46
+ It was a dark and stormy night...
47
+ </textarea>
48
+ </div> -->
42
49
  </script>
43
50
 
44
51
  <script type="text/x-red" data-help-name="PushMessage_New">
@@ -20,29 +20,57 @@ module.exports = (RED) => {
20
20
  console.error('token not found1');
21
21
  return;
22
22
  }
23
-
23
+ // const client = new line.messagingApi.MessagingApiClient(lineconfig);
24
24
  const client = new line.Client(lineconfig);
25
25
 
26
26
  node.on('input', async (msg, send, done) => {
27
27
  try {
28
28
  const userId = msg.targetId || node.credentials.targetId;
29
-
30
- //Flex Messageなどに対応
31
- if(typeof msg.payload === 'object' && msg.payload.type){
32
- msg.payload = await client.pushMessage(userId, msg.payload);
33
- }
34
- //テキストのみの場合
35
- else{
36
- msg.payload = await client.pushMessage(userId, {
37
- type: 'text',
38
- text: msg.payload,
39
- });
29
+ let sendMessages = [];
30
+ console.log(`---オブジェクトメッセージ---`);
31
+ console.log(typeof msg.payload);
32
+
33
+ //複数メッセージかどうか
34
+ if(typeof msg.payload === 'object' && Array.isArray(msg.payload)){
35
+ // console.log(`---複数メッセージ---`);
36
+ // 配列渡してくるときは自分で何かやりたい人なので、そのまま渡す
37
+ sendMessages = msg.payload;
38
+ }else{
39
+ console.log(`---単体メッセージ---`);
40
+ //Flex Messageやその他メッセージに対応(type指定がある場合)
41
+ if(typeof msg.payload === 'object' && msg.payload.type){
42
+ sendMessages = [msg.payload];
43
+ }
44
+ //テキストのみの場合
45
+ else{
46
+ // v2 判定: {変数名} の形式が含まれているか確認
47
+ const variablePattern = /\{[a-zA-Z0-9_]+\}/;
48
+ const isV2Message = typeof msg.payload === 'string' && variablePattern.test(msg.payload) && msg.substitution;
49
+ if (isV2Message) {
50
+ // console.log(`---テキストメッセージv2---`,msg.substitution);
51
+ sendMessages = [{
52
+ type: 'textV2',
53
+ text: msg.payload,
54
+ substitution: msg.substitution,
55
+ }]
56
+ }else{
57
+ // console.log(`---テキストメッセージv1---`);
58
+ sendMessages = [{
59
+ type: 'text',
60
+ text: msg.payload,
61
+ }]
62
+ }
63
+ }
40
64
  }
41
65
 
66
+ msg.payload = await client.pushMessage(userId, sendMessages);
42
67
  send(msg);
43
68
  } catch (error) {
44
- console.log(error);
45
- done(error);
69
+ // console.log(error.originalError.response.data);
70
+ // msg.payload = error.body;
71
+ msg.payload = error.originalError.response.data;
72
+ send(msg);
73
+ node.error("エラー発生", msg.payload);
46
74
  }
47
75
  });
48
76
  }
@@ -1,5 +1,5 @@
1
1
  <script>
2
- RED.nodes.registerType('ReplyMessage',{
2
+ RED.nodes.registerType('ReplyMessage_New',{
3
3
  category: 'LINE',
4
4
  color: '#01B301',
5
5
  defaults: {
@@ -11,17 +11,17 @@
11
11
  channelAccessToken: {type:"password", required:true},
12
12
  },
13
13
  inputs:1,
14
- outputs:0,
14
+ outputs:1,
15
15
  icon: "comment.png",
16
16
  align: "right",
17
17
  paletteLabel: 'Reply',
18
18
  label: function () {
19
- return this.name || 'ReplyMessage';
19
+ return this.name || 'ReplyMessage_New';
20
20
  }
21
21
  });
22
22
  </script>
23
23
 
24
- <script type="text/x-red" data-template-name="ReplyMessage">
24
+ <script type="text/x-red" data-template-name="ReplyMessage_New">
25
25
  <div class="form-row">
26
26
  <label for="node-input-name"><i class="icon-tag"></i> Name</label>
27
27
  <input type="text" id="node-input-name" placeholder="Name">
@@ -43,6 +43,6 @@
43
43
  </div>
44
44
  </script>
45
45
 
46
- <script type="text/x-red" data-help-name="ReplyMessage">
46
+ <script type="text/x-red" data-help-name="ReplyMessage_New">
47
47
  <p>A simple node that converts the message payloads into all ReplyMessage characters</p>
48
48
  </script>
@@ -53,15 +53,20 @@ module.exports = (RED) => {
53
53
  }
54
54
 
55
55
  // 新仕様
56
- const reply = (msg) => {
56
+ const reply = async (msg) => {
57
+ console.log(typeof msg.payload, msg.payload);
57
58
  if (!msg.line || !msg.line.event || !msg.line.event.type) {
58
59
  throw 'no valid LINE event found within msg';
59
60
  } else if (!msg.line.event.replyToken) {
60
61
  throw 'no replyable LINE event received';
61
62
  } else if (!msg.payload) {
62
63
  throw 'reply content (msg.payload) is empty';
63
- } else if (typeof msg.payload === 'object' && msg.payload.type) {
64
- // payloadがオブジェクトの場合はメッセージオブジェクト扱いで送信される
64
+ } else if(typeof msg.payload === 'object' && Array.isArray(msg.payload) && msg.payload.length !== 0 && msg.payload[0].type){
65
+ // payloadが配列かつメッセージオブジェクトが中身の場合
66
+ return client.replyMessage(msg.line.event.replyToken, msg.payload);
67
+ }
68
+ else if (typeof msg.payload === 'object' && msg.payload.type) {
69
+ // payloadがオブジェクトの場合
65
70
  return client.replyMessage(msg.line.event.replyToken, msg.payload);
66
71
  } else {
67
72
  // payloadがそれ以外なら強制的に文字列に変換しテキストメッセージ扱いで送信する
@@ -76,9 +81,8 @@ module.exports = (RED) => {
76
81
  if (msg.line && msg.line.event) {
77
82
  // 新仕様
78
83
  try {
79
- const result = await reply(msg);
80
- console.info(result);
81
- send(msg);
84
+ msg.payload = await reply(msg);
85
+ send(msg); //次のノードへ
82
86
  done();
83
87
  } catch (err) {
84
88
  console.warn(err);
@@ -104,7 +108,7 @@ module.exports = (RED) => {
104
108
  });
105
109
  }
106
110
 
107
- RED.nodes.registerType('ReplyMessage', main, {
111
+ RED.nodes.registerType('ReplyMessage_New', main, {
108
112
  credentials: {
109
113
  channelSecret: { type:'password' },
110
114
  channelAccessToken: { type:'password' },
@@ -27,7 +27,7 @@
27
27
  <div class="form-row">
28
28
  <label for="node-input-AccessToken">
29
29
  <i class="icon-tag"></i>
30
- LINE Limit AccessToken
30
+ Channel Access Token
31
31
  </label>
32
32
  <input type="password" id="node-input-AccessToken" placeholder="LINE Limit AccessToken">
33
33
  </div>
@@ -1,38 +1,51 @@
1
1
  module.exports = (RED) => {
2
2
  'use strict';
3
-
4
- const axiosBase = require('axios');
5
3
 
6
4
  const main = function(config){
7
5
  const node = this;
8
6
  RED.nodes.createNode(node, config);
9
7
  const LINE_TOKEN = node.credentials.AccessToken;
10
- const axios = axiosBase.create({
11
- baseURL: `https://api.line.me/v2/bot/message/quota`,
12
- headers: {
13
- 'Content-Type': 'application/x-www-form-urlencoded',
14
- 'Authorization': `Bearer ${LINE_TOKEN}`
15
- }
16
- });
17
8
 
18
9
  node.on('input', async (msg, send, done) => {
19
10
  const mes = msg.payload;
20
11
  try {
21
- const resLimit = await axios.get(`/`);
22
- const resCurrent = await axios.get(`/consumption`);
12
+ // LINEのクォータ情報を取得するAPIのURL
13
+ const quotaUrl = `https://api.line.me/v2/bot/message/quota`;
14
+ const consumptionUrl = `${quotaUrl}/consumption`;
15
+
16
+ // Fetch APIを使ってクォータ情報を取得
17
+ const resLimit = await fetch(quotaUrl, {
18
+ method: 'GET',
19
+ headers: {
20
+ 'Content-Type': 'application/x-www-form-urlencoded',
21
+ 'Authorization': `Bearer ${LINE_TOKEN}`
22
+ }
23
+ });
24
+
25
+ const resCurrent = await fetch(consumptionUrl, {
26
+ method: 'GET',
27
+ headers: {
28
+ 'Content-Type': 'application/x-www-form-urlencoded',
29
+ 'Authorization': `Bearer ${LINE_TOKEN}`
30
+ }
31
+ });
32
+
33
+ // レスポンスをJSONとして解析
34
+ const dataLimit = await resLimit.json();
35
+ const dataCurrent = await resCurrent.json();
23
36
 
24
37
  const output = {
25
- type: resLimit.data.type,
26
- limit: resLimit.data.value,
27
- totalUsage: resCurrent.data.totalUsage,
28
- usagePercentage: resCurrent.data.totalUsage / resLimit.data.value
29
- }
38
+ type: dataLimit.type,
39
+ limit: dataLimit.value,
40
+ totalUsage: dataCurrent.totalUsage,
41
+ usagePercentage: dataCurrent.totalUsage / dataLimit.value
42
+ };
30
43
 
31
44
  msg.payload = output;
32
45
  send(msg);
33
46
  done();
34
47
  } catch (error) {
35
- console.log(error);
48
+ console.error(error);
36
49
  done(error);
37
50
  }
38
51
 
@@ -12,8 +12,9 @@
12
12
  outputs:0,
13
13
  icon: "comment.png",
14
14
  align: "right",
15
+ paletteLabel: 'Notify_old',
15
16
  label: function() {
16
- return this.name||"Notify";
17
+ return this.name||"Notify_old";
17
18
  }
18
19
  });
19
20
  </script>
@@ -31,7 +32,7 @@
31
32
  </label>
32
33
  <input type="password" id="node-input-AccessToken" placeholder="LINE Notify AccessToken">
33
34
  </div>
34
-
35
+ <p> ※LINE Notifyは2025/3/31でサービス終了となります。利用をやめてPushメッセージなどに移行してください。 https://developers.line.biz/ja/news/2024/10/07/line-notify-will-be-discontinued/ </p>
35
36
  <p>こちらのノードは旧バージョンになります。Newバージョンの利用を検討してください。</p>
36
37
  <p>This node is the old version, please consider using the New version.</p>
37
38
  </script>
@@ -14,7 +14,7 @@
14
14
  outputs: 0,
15
15
  icon: "comment.png",
16
16
  align: "right",
17
- paletteLabel: 'Push',
17
+ paletteLabel: 'Push_old',
18
18
  label: function() {
19
19
  return this.name || 'PushMessage';
20
20
  }
@@ -14,7 +14,7 @@
14
14
  outputs:0,
15
15
  icon: "comment.png",
16
16
  align: "right",
17
- paletteLabel: 'Reply',
17
+ paletteLabel: 'Reply_old',
18
18
  label: function () {
19
19
  return this.name || 'ReplyMessage';
20
20
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-line-messaging-api",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Node-REDでLINE Botが作れます。",
5
5
  "main": "line.js",
6
6
  "repository": {
@@ -14,21 +14,23 @@
14
14
  "node-red": {
15
15
  "nodes": {
16
16
  "Webhook": "./nodes/webhook/webhook.js",
17
- "ReplyMessage": "./nodes/reply/reply.js",
18
- "PushMessage": "./nodes/push/push.js",
17
+ "ReplyMessage_New": "./nodes/_new/reply/reply.js",
18
+ "PushMessage_New": "./nodes/_new/push/push.js",
19
19
  "BloadcastMessage": "./nodes/bloadcast/bloadcast.js",
20
20
  "Limit": "./nodes/limit/limit.js",
21
- "Notify": "./nodes/notify/notify.js",
22
- "Notify_new": "./nodes/_new/notify/notify.js",
23
- "ReplyMessage_new": "./nodes/_new/reply/reply.js",
24
- "PushMessage_new": "./nodes/_new/push/push.js"
21
+ "ReplyMessage": "./nodes/reply/reply.js",
22
+ "PushMessage": "./nodes/push/push.js",
23
+ "Notify_New": "./nodes/_new/notify/notify.js",
24
+ "Notify": "./nodes/notify/notify.js"
25
25
  }
26
26
  },
27
- "keywords": ["node-red"],
27
+ "keywords": [
28
+ "node-red"
29
+ ],
28
30
  "author": "n0bisuke",
29
31
  "license": "Apache 2.0",
30
32
  "dependencies": {
31
- "@line/bot-sdk": "^7.2.0",
33
+ "@line/bot-sdk": "^9.5.0",
32
34
  "body-parser": "^1.19.1",
33
35
  "cors": "^2.8.5",
34
36
  "express": "^4.17.1"