node-red-contrib-line-messaging-api 0.1.16 → 0.2.1
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.
- package/README.md +23 -0
- package/nodes/_new/notify/notify.html +4 -6
- package/nodes/_new/notify/notify.js +23 -13
- package/nodes/_new/push/push.html +46 -0
- package/nodes/_new/push/push.js +57 -0
- package/nodes/_new/reply/reply.html +48 -0
- package/nodes/_new/reply/reply.js +113 -0
- package/nodes/notify/notify.html +3 -0
- package/nodes/push/push.html +3 -0
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -46,6 +46,28 @@ AdminタブからInstall
|
|
|
46
46
|
|
|
47
47
|

|
|
48
48
|
|
|
49
|
+
### LINE Notify_new
|
|
50
|
+
|
|
51
|
+
過去のものとAPIは変わってないですが、オプション指定ができます。
|
|
52
|
+
|
|
53
|
+
> 
|
|
54
|
+
|
|
55
|
+
template nodeにJSONを設定してみてください。
|
|
56
|
+
|
|
57
|
+
> 
|
|
58
|
+
|
|
59
|
+
- 画像とスタンプも送る例
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
{
|
|
63
|
+
"stickerPackageId": "446",
|
|
64
|
+
"stickerId": "1988",
|
|
65
|
+
"message": "{{payload}}",
|
|
66
|
+
"imageThumbnail": "https://i.gyazo.com/a84c585225af440bd0d5fff881152792.png",
|
|
67
|
+
"imageFullsize": "https://i.gyazo.com/a84c585225af440bd0d5fff881152792.png"
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
49
71
|
## LINK
|
|
50
72
|
|
|
51
73
|
* [NodeRED](https://flows.nodered.org/node/node-red-contrib-line-messaging-api)
|
|
@@ -54,6 +76,7 @@ AdminタブからInstall
|
|
|
54
76
|
|
|
55
77
|
## release
|
|
56
78
|
|
|
79
|
+
- 2023/12/11: Notify_newを追加。スタンプや画像も送れるように。
|
|
57
80
|
- 2021/8/1: Reply Messageが画像に対応(thanks [@ukkz](https://github.com/ukkz))
|
|
58
81
|
- 2020/12/17: Bloadcast Messageに対応、Reply MessageがFlex Messageに対応(thanks [@gaomar](https://github.com/gaomar))
|
|
59
82
|
- 2019/2/13: PUSH MessageとLINE Notify対応
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
RED.nodes.registerType('Notify_New',{
|
|
2
|
+
RED.nodes.registerType('Notify_New', {
|
|
3
3
|
category: 'LINE',
|
|
4
4
|
color: '#1ad823',
|
|
5
5
|
defaults: {
|
|
@@ -9,12 +9,10 @@
|
|
|
9
9
|
AccessToken: { type: "password", required: true }
|
|
10
10
|
},
|
|
11
11
|
inputs:1,
|
|
12
|
-
outputs:
|
|
12
|
+
outputs:1,
|
|
13
13
|
icon: "comment.png",
|
|
14
14
|
align: "right",
|
|
15
|
-
label:
|
|
16
|
-
return this.name||"Notify_New";
|
|
17
|
-
}
|
|
15
|
+
label: () => this.name || 'Notify_New',
|
|
18
16
|
});
|
|
19
17
|
</script>
|
|
20
18
|
|
|
@@ -33,6 +31,6 @@
|
|
|
33
31
|
</div>
|
|
34
32
|
</script>
|
|
35
33
|
|
|
36
|
-
<script type="text/x-red" data-help-name="
|
|
34
|
+
<script type="text/x-red" data-help-name="Notify_New">
|
|
37
35
|
<p><a href="https://notify-bot.line.me/my/">LINE Notify</a>でアクセストークンを取得して設定して下さい。</p>
|
|
38
36
|
</script>
|
|
@@ -3,29 +3,39 @@ module.exports = (RED) => {
|
|
|
3
3
|
|
|
4
4
|
const LINE_NOTIFY_BASE_URL = 'https://notify-api.line.me';
|
|
5
5
|
const LINE_NOTIFY_PATH = '/api/notify';
|
|
6
|
-
let REQUEST_OPTIONS = {};
|
|
6
|
+
// let REQUEST_OPTIONS = {};
|
|
7
7
|
|
|
8
8
|
const main = function(config){
|
|
9
9
|
const node = this;
|
|
10
10
|
RED.nodes.createNode(node, config);
|
|
11
|
-
|
|
12
|
-
const LINE_NOTIFY_TOKEN = node.credentials.AccessToken;
|
|
13
|
-
REQUEST_OPTIONS = {
|
|
14
|
-
method: 'POST',
|
|
15
|
-
headers: {
|
|
16
|
-
'Content-Type': 'application/x-www-form-urlencoded',
|
|
17
|
-
'Authorization': `Bearer ${LINE_NOTIFY_TOKEN}`
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
|
|
21
11
|
|
|
22
12
|
/**
|
|
23
13
|
* 実行時の処理
|
|
24
14
|
*/
|
|
25
15
|
node.on('input', async (msg, send, done) => {
|
|
26
|
-
const
|
|
27
|
-
const REQUEST_URL = `${LINE_NOTIFY_BASE_URL}${LINE_NOTIFY_PATH}?message=${encodeURI(mes)}`;
|
|
16
|
+
// const REQUEST_URL = `${LINE_NOTIFY_BASE_URL}${LINE_NOTIFY_PATH}?message=${encodeURI(mes)}&stickerPackageId=1`;
|
|
28
17
|
try {
|
|
18
|
+
const REQUEST_URL = `${LINE_NOTIFY_BASE_URL}${LINE_NOTIFY_PATH}`;
|
|
19
|
+
const mes = msg.payload;
|
|
20
|
+
console.log(mes, typeof mes);
|
|
21
|
+
|
|
22
|
+
let params = {};
|
|
23
|
+
try {
|
|
24
|
+
params = JSON.parse(mes); // JSON形式の場合
|
|
25
|
+
} catch (error) {
|
|
26
|
+
params.message = mes;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const LINE_NOTIFY_TOKEN = node.credentials.AccessToken;
|
|
30
|
+
const REQUEST_OPTIONS = {
|
|
31
|
+
method: 'POST',
|
|
32
|
+
headers: {
|
|
33
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
34
|
+
'Authorization': `Bearer ${LINE_NOTIFY_TOKEN}`
|
|
35
|
+
},
|
|
36
|
+
body: new URLSearchParams(params).toString()
|
|
37
|
+
};
|
|
38
|
+
|
|
29
39
|
const response = await fetch(REQUEST_URL, REQUEST_OPTIONS);
|
|
30
40
|
const data = await response.json();
|
|
31
41
|
msg.payload = data;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
RED.nodes.registerType('PushMessage_New',{
|
|
3
|
+
category: 'LINE',
|
|
4
|
+
color: '#01B301',
|
|
5
|
+
defaults: {
|
|
6
|
+
name: {value:""},
|
|
7
|
+
},
|
|
8
|
+
credentials: {
|
|
9
|
+
// channelSecret: {type:"password", required:true},
|
|
10
|
+
channelAccessToken: {type:"password", required:true},
|
|
11
|
+
targetId:{type:"password", required:true},
|
|
12
|
+
},
|
|
13
|
+
inputs: 1,
|
|
14
|
+
outputs: 1,
|
|
15
|
+
icon: "comment.png",
|
|
16
|
+
align: "right",
|
|
17
|
+
paletteLabel: 'Push_New',
|
|
18
|
+
label: () => this.name || 'PushMessage_New'
|
|
19
|
+
});
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<script type="text/x-red" data-template-name="PushMessage_New">
|
|
23
|
+
<div class="form-row">
|
|
24
|
+
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
|
25
|
+
<input type="text" id="node-input-name" placeholder="Name">
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<!-- <div class="form-row">
|
|
29
|
+
<label for="node-input-channelSecret"><i class="icon-tag"></i> Secret</label>
|
|
30
|
+
<input type="password" id="node-input-channelSecret" placeholder="ChannelSecret">
|
|
31
|
+
</div> -->
|
|
32
|
+
|
|
33
|
+
<div class="form-row">
|
|
34
|
+
<label for="node-input-channelAccessToken"><i class="icon-tag"></i> AccessToken</label>
|
|
35
|
+
<input type="password" id="node-input-channelAccessToken" placeholder="ChannelAccessToken">
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<div class="form-row">
|
|
39
|
+
<label for="node-input-targetId"><i class="icon-tag"></i> User Id or Group ID</label>
|
|
40
|
+
<input type="text" id="node-input-targetId" placeholder="User Id or Group ID">
|
|
41
|
+
</div>
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
<script type="text/x-red" data-help-name="PushMessage_New">
|
|
45
|
+
<p>Send a push message by specifying the user ID or group ID.</p>
|
|
46
|
+
</script>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module.exports = (RED) => {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const line = require('@line/bot-sdk');
|
|
5
|
+
const main = function(config){
|
|
6
|
+
const node = this;
|
|
7
|
+
RED.nodes.createNode(node, config);
|
|
8
|
+
|
|
9
|
+
let lineconfig;
|
|
10
|
+
try {
|
|
11
|
+
lineconfig = require('../../env');
|
|
12
|
+
} catch (error) {
|
|
13
|
+
lineconfig = {
|
|
14
|
+
// channelSecret: node.credentials.channelSecret,
|
|
15
|
+
channelAccessToken: node.credentials.channelAccessToken
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if(lineconfig.channelAccessToken === undefined || lineconfig.channelAccessToken === '') {
|
|
20
|
+
console.error('token not found1');
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const client = new line.Client(lineconfig);
|
|
25
|
+
|
|
26
|
+
node.on('input', async (msg, send, done) => {
|
|
27
|
+
try {
|
|
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
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
send(msg);
|
|
43
|
+
} catch (error) {
|
|
44
|
+
console.log(error);
|
|
45
|
+
done(error);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
RED.nodes.registerType("PushMessage_New", main, {
|
|
51
|
+
credentials: {
|
|
52
|
+
// channelSecret: {type:"password"},
|
|
53
|
+
channelAccessToken: {type:"password"},
|
|
54
|
+
targetId: {type:"password"},
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
RED.nodes.registerType('ReplyMessage',{
|
|
3
|
+
category: 'LINE',
|
|
4
|
+
color: '#01B301',
|
|
5
|
+
defaults: {
|
|
6
|
+
name: {value:""},
|
|
7
|
+
replyMessage:{value:""}
|
|
8
|
+
},
|
|
9
|
+
credentials: {
|
|
10
|
+
channelSecret: {type:"password", required:true},
|
|
11
|
+
channelAccessToken: {type:"password", required:true},
|
|
12
|
+
},
|
|
13
|
+
inputs:1,
|
|
14
|
+
outputs:0,
|
|
15
|
+
icon: "comment.png",
|
|
16
|
+
align: "right",
|
|
17
|
+
paletteLabel: 'Reply',
|
|
18
|
+
label: function () {
|
|
19
|
+
return this.name || 'ReplyMessage';
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<script type="text/x-red" data-template-name="ReplyMessage">
|
|
25
|
+
<div class="form-row">
|
|
26
|
+
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
|
27
|
+
<input type="text" id="node-input-name" placeholder="Name">
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<div class="form-row">
|
|
31
|
+
<label for="node-input-channelSecret"><i class="icon-tag"></i> Secret</label>
|
|
32
|
+
<input type="password" id="node-input-channelSecret" placeholder="ChannelSecret">
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<div class="form-row">
|
|
36
|
+
<label for="node-input-channelAccessToken"><i class="icon-tag"></i> AccessToken</label>
|
|
37
|
+
<input type="password" id="node-input-channelAccessToken" placeholder="ChannelAccessToken">
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
<div class="form-row">
|
|
41
|
+
<label for="node-input-replyMessage"><i class="icon-tag"></i> ReplyMessage</label>
|
|
42
|
+
<input type="text" id="node-input-replyMessage" placeholder="static text message here">
|
|
43
|
+
</div>
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<script type="text/x-red" data-help-name="ReplyMessage">
|
|
47
|
+
<p>A simple node that converts the message payloads into all ReplyMessage characters</p>
|
|
48
|
+
</script>
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
module.exports = (RED) => {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const line = require('@line/bot-sdk');
|
|
5
|
+
const main = function(config){
|
|
6
|
+
const node = this;
|
|
7
|
+
RED.nodes.createNode(node, config);
|
|
8
|
+
|
|
9
|
+
let lineconfig;
|
|
10
|
+
try {
|
|
11
|
+
lineconfig = require('../../env');
|
|
12
|
+
} catch (error) {
|
|
13
|
+
lineconfig = {
|
|
14
|
+
channelSecret: node.credentials.channelSecret,
|
|
15
|
+
channelAccessToken: node.credentials.channelAccessToken
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (lineconfig.channelSecret === '' || lineconfig.channelAccessToken === '') {
|
|
20
|
+
this.error(RED._('token not found'));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const client = new line.Client(lineconfig);
|
|
24
|
+
|
|
25
|
+
// 旧仕様
|
|
26
|
+
const handleEvent = (event) => {
|
|
27
|
+
if (event.type !== 'message') {
|
|
28
|
+
return Promise.resolve(null);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (event.message.type === 'text') {
|
|
32
|
+
return client.replyMessage(event.replyToken, {
|
|
33
|
+
type: 'text',
|
|
34
|
+
text: config.replyMessage || event.message.text // 実際に返信の言葉を入れる箇所
|
|
35
|
+
});
|
|
36
|
+
} else if (event.message.type === 'flex') {
|
|
37
|
+
const message_text = event.message.altText;
|
|
38
|
+
|
|
39
|
+
return client.replyMessage(event.replyToken, {
|
|
40
|
+
type: 'flex',
|
|
41
|
+
altText: message_text,
|
|
42
|
+
contents: event.message.text
|
|
43
|
+
});
|
|
44
|
+
} else if (event.message.type === 'image') {
|
|
45
|
+
return client.replyMessage(event.replyToken, {
|
|
46
|
+
type: 'image',
|
|
47
|
+
originalContentUrl: event.message.originalContentUrl,
|
|
48
|
+
previewImageUrl: event.message.previewImageUrl || event.message.originalContentUrl
|
|
49
|
+
});
|
|
50
|
+
} else {
|
|
51
|
+
return Promise.resolve(null);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// 新仕様
|
|
56
|
+
const reply = (msg) => {
|
|
57
|
+
if (!msg.line || !msg.line.event || !msg.line.event.type) {
|
|
58
|
+
throw 'no valid LINE event found within msg';
|
|
59
|
+
} else if (!msg.line.event.replyToken) {
|
|
60
|
+
throw 'no replyable LINE event received';
|
|
61
|
+
} else if (!msg.payload) {
|
|
62
|
+
throw 'reply content (msg.payload) is empty';
|
|
63
|
+
} else if (typeof msg.payload === 'object' && msg.payload.type) {
|
|
64
|
+
// payloadがオブジェクトの場合はメッセージオブジェクト扱いで送信される
|
|
65
|
+
return client.replyMessage(msg.line.event.replyToken, msg.payload);
|
|
66
|
+
} else {
|
|
67
|
+
// payloadがそれ以外なら強制的に文字列に変換しテキストメッセージ扱いで送信する
|
|
68
|
+
return client.replyMessage(msg.line.event.replyToken, {
|
|
69
|
+
type: 'text',
|
|
70
|
+
text: config.replyMessage || String(msg.payload)
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
node.on('input', async (msg, send, done) => {
|
|
76
|
+
if (msg.line && msg.line.event) {
|
|
77
|
+
// 新仕様
|
|
78
|
+
try {
|
|
79
|
+
const result = await reply(msg);
|
|
80
|
+
console.info(result);
|
|
81
|
+
send(msg);
|
|
82
|
+
done();
|
|
83
|
+
} catch (err) {
|
|
84
|
+
console.warn(err);
|
|
85
|
+
done(err);
|
|
86
|
+
}
|
|
87
|
+
} else if (msg.payload.events) {
|
|
88
|
+
// 旧仕様
|
|
89
|
+
Promise
|
|
90
|
+
.all(msg.payload.events.map(handleEvent))
|
|
91
|
+
.then(result => {
|
|
92
|
+
// [{}]が返ってきてる
|
|
93
|
+
if (result.length === 1 && 0 === Object.keys(result[0]).length) {
|
|
94
|
+
result = { status: 200, message: 'Success' }
|
|
95
|
+
}
|
|
96
|
+
msg.payload = result;
|
|
97
|
+
send(msg);
|
|
98
|
+
done();
|
|
99
|
+
}).catch(err => {
|
|
100
|
+
console.log(err);
|
|
101
|
+
done(err);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
RED.nodes.registerType('ReplyMessage', main, {
|
|
108
|
+
credentials: {
|
|
109
|
+
channelSecret: { type:'password' },
|
|
110
|
+
channelAccessToken: { type:'password' },
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
package/nodes/notify/notify.html
CHANGED
|
@@ -31,6 +31,9 @@
|
|
|
31
31
|
</label>
|
|
32
32
|
<input type="password" id="node-input-AccessToken" placeholder="LINE Notify AccessToken">
|
|
33
33
|
</div>
|
|
34
|
+
|
|
35
|
+
<p>こちらのノードは旧バージョンになります。Newバージョンの利用を検討してください。</p>
|
|
36
|
+
<p>This node is the old version, please consider using the New version.</p>
|
|
34
37
|
</script>
|
|
35
38
|
|
|
36
39
|
<script type="text/x-red" data-help-name="Notify">
|
package/nodes/push/push.html
CHANGED
|
@@ -41,6 +41,9 @@
|
|
|
41
41
|
<label for="node-input-targetId"><i class="icon-tag"></i> User Id or Group ID</label>
|
|
42
42
|
<input type="text" id="node-input-targetId" placeholder="User Id or Group ID">
|
|
43
43
|
</div>
|
|
44
|
+
|
|
45
|
+
<p>こちらのノードは旧バージョンになります。Newバージョンの利用を検討してください。</p>
|
|
46
|
+
<p>This node is the old version, please consider using the New version.</p>
|
|
44
47
|
</script>
|
|
45
48
|
|
|
46
49
|
<script type="text/x-red" data-help-name="PushMessage">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-red-contrib-line-messaging-api",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Node-REDでLINE Botが作れます。",
|
|
5
5
|
"main": "line.js",
|
|
6
6
|
"repository": {
|
|
@@ -19,7 +19,9 @@
|
|
|
19
19
|
"BloadcastMessage": "./nodes/bloadcast/bloadcast.js",
|
|
20
20
|
"Limit": "./nodes/limit/limit.js",
|
|
21
21
|
"Notify": "./nodes/notify/notify.js",
|
|
22
|
-
"Notify_new": "./nodes/_new/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"
|
|
23
25
|
}
|
|
24
26
|
},
|
|
25
27
|
"keywords": ["node-red"],
|