Commit eb28d472dfdd78993b47618c9e5bd8ab0920d8ac

Authored by Surasit Yerpui
1 parent a8dde2dd
Exists in master

update Service

index copy.js 0 → 100644
@@ -0,0 +1,317 @@ @@ -0,0 +1,317 @@
  1 +"use strict";
  2 +
  3 +const line = require("@line/bot-sdk");
  4 +const express = require("express");
  5 +const config = require("./config.json");
  6 +const bodyParser = require("body-parser");
  7 +const axios = require("axios");
  8 +const fs = require("fs");
  9 +const request = require("request");
  10 +const moment = require("moment");
  11 +const flexMsg = require("./flexMsg");
  12 +
  13 +// create LINE SDK client
  14 +const client = new line.Client(config);
  15 +
  16 +const app = express();
  17 +
  18 +// webhook callback
  19 +app.use("/webhook", line.middleware(config));
  20 +app.post("/webhook", (req, res) => {
  21 + // req.body.events should be an array of events
  22 + if (!Array.isArray(req.body.events)) {
  23 + return res.status(500).end();
  24 + }
  25 + // handle events separately
  26 + Promise.all(
  27 + req.body.events.map((event) => {
  28 + console.log("event", event);
  29 + // check verify webhook event
  30 + if (
  31 + event.replyToken === "00000000000000000000000000000000" ||
  32 + event.replyToken === "ffffffffffffffffffffffffffffffff"
  33 + ) {
  34 + return;
  35 + }
  36 + return handleEvent(event);
  37 + })
  38 + )
  39 + .then(() => res.end())
  40 + .catch((err) => {
  41 + console.error(err);
  42 + res.status(500).end();
  43 + });
  44 +});
  45 +
  46 +// simple reply function
  47 +const replyText = (token, texts) => {
  48 + texts = Array.isArray(texts) ? texts : [texts];
  49 + return client.replyMessage(
  50 + token,
  51 + texts.map((text) => ({ type: "text", text }))
  52 + );
  53 +};
  54 +
  55 +const tolow = (str) => {
  56 + return str.toLowerCase();
  57 +};
  58 +const handleEvent = (event) => {
  59 + let payload = {
  60 + type: "text",
  61 + text: "Hello From PUI",
  62 + };
  63 +
  64 + if (event.message.type == "text") {
  65 + let selecttext = tolow(event.message.text);
  66 + let get_text = mockText()[selecttext];
  67 + if (get_text) {
  68 + payload = get_text;
  69 + }
  70 + } else {
  71 + payload.text = "Other Message =>>>" + JSON.stringify(event);
  72 + }
  73 +
  74 + return client.replyMessage(event.replyToken, payload);
  75 +};
  76 +app.use(bodyParser.json());
  77 +
  78 +app.get("/", (req, res) => {
  79 + res.json({ line: "ok" });
  80 +});
  81 +
  82 +app.get("/push", bodyParser.json(), (req, res) => {
  83 + let message = {
  84 + type: "text",
  85 + text: `use Push Message! to `,
  86 + };
  87 + client.pushMessage("Uaac2ca5a02feab67a18d5521b572b5aa", message);
  88 + res.json(message);
  89 +});
  90 +
  91 +app.post("/save", bodyParser.json(), async (req, res) => {
  92 + console.log("saveFile!");
  93 + try {
  94 + const downloadFile = function (uri, filename, callback) {
  95 + request.head(uri, function (err, res, body) {
  96 + console.log("content-type:", res.headers["content-type"]);
  97 + console.log("content-length:", res.headers["content-length"]);
  98 + console.log("Content-Type:", res.headers["Content-Type"]);
  99 + console.log("res.headers ::", res.headers);
  100 +
  101 + request(uri, {
  102 + headers: {
  103 + Authorization:
  104 + "Bearer be/XHjQ+gMoypZE78Us7hk0h6PA04TyfpQciMOq+B/OVPmumozdhGzYUwopDgsOMCM7RymTK8m++q20GSj3c6B7gZkgEmuGYEYPvc6j+4as6X5bu7tEg+KAZKMfBVDnk+ekpAorC7FMwVPyt2frGRQdB04t89/1O/w1cDnyilFU=",
  105 + },
  106 + })
  107 + .pipe(fs.createWriteStream(filename))
  108 + .on("close", callback);
  109 + });
  110 + };
  111 +
  112 + let unquie_file = moment().format("YYYY-MM-DD_HHmmssss");
  113 + let file_name = `filesave_${unquie_file}`;
  114 + let message_id = req.body.message_id;
  115 + let URI = `https://api-data.line.me/v2/bot/message/${message_id}/content`;
  116 + console.log("message_id ::", message_id);
  117 + console.log("file_name ::", file_name);
  118 +
  119 + axios
  120 + .get(URI, {
  121 + headers: {
  122 + Authorization:
  123 + "Bearer be/XHjQ+gMoypZE78Us7hk0h6PA04TyfpQciMOq+B/OVPmumozdhGzYUwopDgsOMCM7RymTK8m++q20GSj3c6B7gZkgEmuGYEYPvc6j+4as6X5bu7tEg+KAZKMfBVDnk+ekpAorC7FMwVPyt2frGRQdB04t89/1O/w1cDnyilFU=",
  124 + },
  125 + })
  126 + .then(function (response) {
  127 + // handle success
  128 + console.log("axios =>>", response.headers["content-type"]);
  129 + let sp = response.headers["content-type"].split("/");
  130 + let type = sp[sp.length - 1];
  131 + let full_file_name = file_name + "." + type;
  132 + console.log("full_file_name =", full_file_name);
  133 + downloadFile(URI, full_file_name, function () {
  134 + console.log("done!");
  135 + res.json({ LoadFlieName: "Success" });
  136 + });
  137 + })
  138 + .catch(function (error) {
  139 + // handle error
  140 + console.log(error);
  141 + console.error("errorxx ::", error);
  142 + res.json({ error: "error" });
  143 + });
  144 + } catch (error) {
  145 + console.error("errorxx ::", error);
  146 + }
  147 +});
  148 +
  149 +app.post("/saveNew", bodyParser.json(), async (req, res) => {
  150 + console.log("saveFile!");
  151 + try {
  152 + let stream = await client.getMessageContent("14955535936627");
  153 + console.log("stream!", stream);
  154 + } catch (error) {
  155 + console.error(error);
  156 + }
  157 + res.json({ OK: "OK" });
  158 +});
  159 +
  160 +app.post("/push", (req, res) => {
  161 + let body = req.body;
  162 + let { user_id } = body;
  163 + console.log("body ::", body);
  164 + let message = {
  165 + type: "text",
  166 + text: `use Push Message! to ${user_id}`,
  167 + };
  168 + client.pushMessage(user_id, message);
  169 + res.json(message);
  170 +});
  171 +
  172 +app.post("/multicast", (req, res) => {
  173 + let body = req.body;
  174 + let { user_ids } = body;
  175 + console.log("body ::", body);
  176 + let message = [
  177 + {
  178 + type: "text",
  179 + text: `use multicast Message1! to ${JSON.stringify(user_ids)}`,
  180 + },
  181 + {
  182 + type: "text",
  183 + text: `use multicast Message2! to ${JSON.stringify(user_ids)}`,
  184 + },
  185 + ];
  186 + client.multicast(user_ids, message);
  187 + res.json(message);
  188 +});
  189 +
  190 +const port = config.port;
  191 +app.listen(port, () => {
  192 + console.log(`listening on ${port}`);
  193 +});
  194 +
  195 +const GenContentFlex = (content) => {
  196 + return {
  197 + flex1: {
  198 + type: "flex",
  199 + altText: "GenContentFlex!",
  200 + contents: content,
  201 + },
  202 + };
  203 +};
  204 +
  205 +const genMsgContent = flexMsg.GenContentFlex;
  206 +const flexs = flexMsg.flexs;
  207 +// console.log(genMsgContent());
  208 +
  209 +const mockText = () => {
  210 + return {
  211 + flex0: flexs.flex0,
  212 + flex1: flexs.flex1,
  213 +
  214 + bub1: flexs.bub1,
  215 + bub2: flexs.bub2,
  216 + bub3: flexs.bub3,
  217 + bub4: flexs.bub4,
  218 + bub5: flexs.bub5,
  219 + bub6: flexs.bub6,
  220 +
  221 + confirm:{
  222 + "type": "template",
  223 + "altText": "this is a confirm template",
  224 + "template": {
  225 + "type": "confirm",
  226 + "text": "Are you sure?",
  227 + "actions": [
  228 + {
  229 + "type": "message",
  230 + "label": "Yes",
  231 + "text": "yes"
  232 + },
  233 + {
  234 + "type": "message",
  235 + "label": "No",
  236 + "text": "no"
  237 + }
  238 + ]
  239 + }
  240 + },
  241 +
  242 +
  243 + location: {
  244 + type: "text", // ①
  245 + text: "Select your favorite food category or send me your location!",
  246 + quickReply: {
  247 + // ②
  248 + items: [
  249 + {
  250 + type: "action", // ③
  251 + imageUrl: "https://example.com/sushi.png",
  252 + action: {
  253 + type: "message",
  254 + label: "Sushi",
  255 + text: "Sushi",
  256 + },
  257 + },
  258 + {
  259 + type: "action",
  260 + imageUrl: "https://example.com/tempura.png",
  261 + action: {
  262 + type: "message",
  263 + label: "Tempura",
  264 + text: "Tempura",
  265 + },
  266 + },
  267 + {
  268 + type: "action", // ④
  269 + action: {
  270 + type: "location",
  271 + label: "Send location",
  272 + },
  273 + },
  274 + ],
  275 + },
  276 + },
  277 +
  278 +
  279 +
  280 +
  281 + //
  282 + image_carousel: {
  283 + "type": "template",
  284 + "altText": "this is a image carousel template",
  285 + "template": {
  286 + "type": "image_carousel",
  287 + "columns": [
  288 + {
  289 + "imageUrl": "https://example.com/bot/images/item1.jpg",
  290 + "action": {
  291 + "type": "postback",
  292 + "label": "Buy",
  293 + "data": "action=buy&itemid=111"
  294 + }
  295 + },
  296 + {
  297 + "imageUrl": "https://example.com/bot/images/item2.jpg",
  298 + "action": {
  299 + "type": "message",
  300 + "label": "Yes",
  301 + "text": "yes"
  302 + }
  303 + },
  304 + {
  305 + "imageUrl": "https://example.com/bot/images/item3.jpg",
  306 + "action": {
  307 + "type": "uri",
  308 + "label": "View detail",
  309 + "uri": "http://example.com/page/222"
  310 + }
  311 + }
  312 + ]
  313 + }
  314 + }
  315 +
  316 + };
  317 +};
@@ -9,6 +9,8 @@ const fs = require("fs"); @@ -9,6 +9,8 @@ const fs = require("fs");
9 const request = require("request"); 9 const request = require("request");
10 const moment = require("moment"); 10 const moment = require("moment");
11 const flexMsg = require("./flexMsg"); 11 const flexMsg = require("./flexMsg");
  12 +const ContentService = require("./services/ContentService");
  13 +const LineService = require("./services/LineService");
12 14
13 // create LINE SDK client 15 // create LINE SDK client
14 const client = new line.Client(config); 16 const client = new line.Client(config);
@@ -43,18 +45,6 @@ app.post("/webhook", (req, res) => { @@ -43,18 +45,6 @@ app.post("/webhook", (req, res) => {
43 }); 45 });
44 }); 46 });
45 47
46 -// simple reply function  
47 -const replyText = (token, texts) => {  
48 - texts = Array.isArray(texts) ? texts : [texts];  
49 - return client.replyMessage(  
50 - token,  
51 - texts.map((text) => ({ type: "text", text }))  
52 - );  
53 -};  
54 -  
55 -const tolow = (str) => {  
56 - return str.toLowerCase();  
57 -};  
58 const handleEvent = (event) => { 48 const handleEvent = (event) => {
59 let payload = { 49 let payload = {
60 type: "text", 50 type: "text",
@@ -62,8 +52,8 @@ const handleEvent = (event) => { @@ -62,8 +52,8 @@ const handleEvent = (event) => {
62 }; 52 };
63 53
64 if (event.message.type == "text") { 54 if (event.message.type == "text") {
65 - let selecttext = tolow(event.message.text);  
66 - let get_text = mockText()[selecttext]; 55 + let selecttext = String(event.message.text).toLowerCase();
  56 + let get_text = ContentService.mockText()[selecttext];
67 if (get_text) { 57 if (get_text) {
68 payload = get_text; 58 payload = get_text;
69 } 59 }
@@ -73,21 +63,73 @@ const handleEvent = (event) => { @@ -73,21 +63,73 @@ const handleEvent = (event) => {
73 63
74 return client.replyMessage(event.replyToken, payload); 64 return client.replyMessage(event.replyToken, payload);
75 }; 65 };
76 -app.use(bodyParser.json());  
77 66
  67 +app.use(bodyParser.json());
78 app.get("/", (req, res) => { 68 app.get("/", (req, res) => {
79 res.json({ line: "ok" }); 69 res.json({ line: "ok" });
80 }); 70 });
81 71
82 -app.get("/push", bodyParser.json(), (req, res) => { 72 +app.post("/push", (req, res) => {
  73 + let body = req.body;
  74 + let { user_id } = body;
  75 + console.log("push =>> body ::", body);
83 let message = { 76 let message = {
84 type: "text", 77 type: "text",
85 - text: `use Push Message! to `, 78 + text: `Push Message! to ${user_id}`,
86 }; 79 };
87 - client.pushMessage("Uaac2ca5a02feab67a18d5521b572b5aa", message); 80 + client.pushMessage(user_id, message);
  81 + res.json(message);
  82 +});
  83 +
  84 +app.post("/multicast", (req, res) => {
  85 + let body = req.body;
  86 + let { user_ids } = body;
  87 + console.log("body ::", body);
  88 + let message = [
  89 + {
  90 + type: "text",
  91 + text: `use multicast Message1! to ${JSON.stringify(user_ids)}`,
  92 + },
  93 + {
  94 + type: "text",
  95 + text: `use multicast Message2! to ${JSON.stringify(user_ids)}`,
  96 + },
  97 + ];
  98 +
  99 + client.multicast(user_ids, message);
88 res.json(message); 100 res.json(message);
89 }); 101 });
90 102
  103 +app.post("/multicast", (req, res) => {
  104 + let body = req.body;
  105 + let { user_ids } = body;
  106 + console.log("body ::", body);
  107 + let message = [
  108 + {
  109 + type: "text",
  110 + text: `use multicast Message1! to ${JSON.stringify(user_ids)}`,
  111 + },
  112 + {
  113 + type: "text",
  114 + text: `use multicast Message2! to ${JSON.stringify(user_ids)}`,
  115 + },
  116 + ];
  117 +
  118 + client.multicast(user_ids, message);
  119 + res.json(message);
  120 +});
  121 +
  122 +app.post("/broadcast", async (req, res) => {
  123 + let body = req.body;
  124 + let { messages } = body;
  125 + console.log("body ::", body);
  126 +
  127 + let resx = await LineService.Broadcast(messages);
  128 + console.log("resx", resx);
  129 +
  130 + res.json({ message: "OK" });
  131 +});
  132 +
91 app.post("/save", bodyParser.json(), async (req, res) => { 133 app.post("/save", bodyParser.json(), async (req, res) => {
92 console.log("saveFile!"); 134 console.log("saveFile!");
93 try { 135 try {
@@ -146,172 +188,7 @@ app.post("/save", bodyParser.json(), async (req, res) => { @@ -146,172 +188,7 @@ app.post("/save", bodyParser.json(), async (req, res) => {
146 } 188 }
147 }); 189 });
148 190
149 -app.post("/saveNew", bodyParser.json(), async (req, res) => {  
150 - console.log("saveFile!");  
151 - try {  
152 - let stream = await client.getMessageContent("14955535936627");  
153 - console.log("stream!", stream);  
154 - } catch (error) {  
155 - console.error(error);  
156 - }  
157 - res.json({ OK: "OK" });  
158 -});  
159 -  
160 -app.post("/push", (req, res) => {  
161 - let body = req.body;  
162 - let { user_id } = body;  
163 - console.log("body ::", body);  
164 - let message = {  
165 - type: "text",  
166 - text: `use Push Message! to ${user_id}`,  
167 - };  
168 - client.pushMessage(user_id, message);  
169 - res.json(message);  
170 -});  
171 -  
172 -app.post("/multicast", (req, res) => {  
173 - let body = req.body;  
174 - let { user_ids } = body;  
175 - console.log("body ::", body);  
176 - let message = [  
177 - {  
178 - type: "text",  
179 - text: `use multicast Message1! to ${JSON.stringify(user_ids)}`,  
180 - },  
181 - {  
182 - type: "text",  
183 - text: `use multicast Message2! to ${JSON.stringify(user_ids)}`,  
184 - },  
185 - ];  
186 - client.multicast(user_ids, message);  
187 - res.json(message);  
188 -});  
189 -  
190 const port = config.port; 191 const port = config.port;
191 app.listen(port, () => { 192 app.listen(port, () => {
192 console.log(`listening on ${port}`); 193 console.log(`listening on ${port}`);
193 }); 194 });
194 -  
195 -const GenContentFlex = (content) => {  
196 - return {  
197 - flex1: {  
198 - type: "flex",  
199 - altText: "GenContentFlex!",  
200 - contents: content,  
201 - },  
202 - };  
203 -};  
204 -  
205 -const genMsgContent = flexMsg.GenContentFlex;  
206 -const flexs = flexMsg.flexs;  
207 -// console.log(genMsgContent());  
208 -  
209 -const mockText = () => {  
210 - return {  
211 - flex0: flexs.flex0,  
212 - flex1: flexs.flex1,  
213 -  
214 - bub1: flexs.bub1,  
215 - bub2: flexs.bub2,  
216 - bub3: flexs.bub3,  
217 - bub4: flexs.bub4,  
218 - bub5: flexs.bub5,  
219 - bub6: flexs.bub6,  
220 -  
221 - confirm:{  
222 - "type": "template",  
223 - "altText": "this is a confirm template",  
224 - "template": {  
225 - "type": "confirm",  
226 - "text": "Are you sure?",  
227 - "actions": [  
228 - {  
229 - "type": "message",  
230 - "label": "Yes",  
231 - "text": "yes"  
232 - },  
233 - {  
234 - "type": "message",  
235 - "label": "No",  
236 - "text": "no"  
237 - }  
238 - ]  
239 - }  
240 - },  
241 -  
242 -  
243 - location: {  
244 - type: "text", // ①  
245 - text: "Select your favorite food category or send me your location!",  
246 - quickReply: {  
247 - // ②  
248 - items: [  
249 - {  
250 - type: "action", // ③  
251 - imageUrl: "https://example.com/sushi.png",  
252 - action: {  
253 - type: "message",  
254 - label: "Sushi",  
255 - text: "Sushi",  
256 - },  
257 - },  
258 - {  
259 - type: "action",  
260 - imageUrl: "https://example.com/tempura.png",  
261 - action: {  
262 - type: "message",  
263 - label: "Tempura",  
264 - text: "Tempura",  
265 - },  
266 - },  
267 - {  
268 - type: "action", // ④  
269 - action: {  
270 - type: "location",  
271 - label: "Send location",  
272 - },  
273 - },  
274 - ],  
275 - },  
276 - },  
277 -  
278 -  
279 -  
280 -  
281 - //  
282 - image_carousel: {  
283 - "type": "template",  
284 - "altText": "this is a image carousel template",  
285 - "template": {  
286 - "type": "image_carousel",  
287 - "columns": [  
288 - {  
289 - "imageUrl": "https://example.com/bot/images/item1.jpg",  
290 - "action": {  
291 - "type": "postback",  
292 - "label": "Buy",  
293 - "data": "action=buy&itemid=111"  
294 - }  
295 - },  
296 - {  
297 - "imageUrl": "https://example.com/bot/images/item2.jpg",  
298 - "action": {  
299 - "type": "message",  
300 - "label": "Yes",  
301 - "text": "yes"  
302 - }  
303 - },  
304 - {  
305 - "imageUrl": "https://example.com/bot/images/item3.jpg",  
306 - "action": {  
307 - "type": "uri",  
308 - "label": "View detail",  
309 - "uri": "http://example.com/page/222"  
310 - }  
311 - }  
312 - ]  
313 - }  
314 - }  
315 -  
316 - };  
317 -};  
indexbk.js
@@ -1,166 +0,0 @@ @@ -1,166 +0,0 @@
1 -"use strict";  
2 -  
3 -const line = require("@line/bot-sdk");  
4 -const express = require("express");  
5 -const config = require("./config.json");  
6 -  
7 -// create LINE SDK client  
8 -const client = new line.Client(config);  
9 -  
10 -const app = express();  
11 -  
12 -// webhook callback  
13 -app.post("/webhook", line.middleware(config), (req, res) => {  
14 - // req.body.events should be an array of events  
15 - if (!Array.isArray(req.body.events)) {  
16 - return res.status(500).end();  
17 - }  
18 - // handle events separately  
19 - Promise.all(  
20 - req.body.events.map((event) => {  
21 - console.log("event", event);  
22 - // check verify webhook event  
23 - if (  
24 - event.replyToken === "00000000000000000000000000000000" ||  
25 - event.replyToken === "ffffffffffffffffffffffffffffffff"  
26 - ) {  
27 - return;  
28 - }  
29 - return handleEvent2(event);  
30 - })  
31 - )  
32 - .then(() => res.end())  
33 - .catch((err) => {  
34 - console.error(err);  
35 - res.status(500).end();  
36 - });  
37 -});  
38 -  
39 -// simple reply function  
40 -const replyText = (token, texts) => {  
41 - texts = Array.isArray(texts) ? texts : [texts];  
42 - return client.replyMessage(  
43 - token,  
44 - texts.map((text) => ({ type: "text", text }))  
45 - );  
46 -};  
47 -  
48 -const handleEvent = (event) => {  
49 - // const payload = {  
50 - // type: "text",  
51 - // text: "Hello From PUI",  
52 - // };  
53 -  
54 -  
55 - const payload = {  
56 - "type": "text", // ①  
57 - "text": "Select your favorite food category or send me your location!",  
58 - "quickReply": { // ②  
59 - "items": [  
60 - {  
61 - "type": "action", // ③  
62 - "imageUrl": "https://example.com/sushi.png",  
63 - "action": {  
64 - "type": "message",  
65 - "label": "Sushi",  
66 - "text": "Sushi"  
67 - }  
68 - },  
69 - {  
70 - "type": "action",  
71 - "imageUrl": "https://example.com/tempura.png",  
72 - "action": {  
73 - "type": "message",  
74 - "label": "Tempura",  
75 - "text": "Tempura"  
76 - }  
77 - },  
78 - {  
79 - "type": "action", // ④  
80 - "action": {  
81 - "type": "location",  
82 - "label": "Send location"  
83 - }  
84 - }  
85 - ]  
86 - }  
87 - }  
88 -  
89 - return client.replyMessage(event.replyToken, payload);  
90 -};  
91 -  
92 -// callback function to handle a single event  
93 -function handleEvent2(event) {  
94 - switch (event.type) {  
95 - case 'message':  
96 - const message = event.message;  
97 - switch (message.type) {  
98 - case 'text':  
99 - return handleText(message, event.replyToken);  
100 - case 'image':  
101 - return handleImage(message, event.replyToken);  
102 - case 'video':  
103 - return handleVideo(message, event.replyToken);  
104 - case 'audio':  
105 - return handleAudio(message, event.replyToken);  
106 - case 'location':  
107 - return handleLocation(message, event.replyToken);  
108 - case 'sticker':  
109 - return handleSticker(message, event.replyToken);  
110 - default:  
111 - throw new Error(`Unknown message: ${JSON.stringify(message)}`);  
112 - }  
113 -  
114 - case 'follow':  
115 - return replyText(event.replyToken, 'Got followed event');  
116 -  
117 - case 'unfollow':  
118 - return console.log(`Unfollowed this bot: ${JSON.stringify(event)}`);  
119 -  
120 - case 'join':  
121 - return replyText(event.replyToken, `Joined ${event.source.type}`);  
122 -  
123 - case 'leave':  
124 - return console.log(`Left: ${JSON.stringify(event)}`);  
125 -  
126 - case 'postback':  
127 - let data = event.postback.data;  
128 - return replyText(event.replyToken, `Got postback: ${data}`);  
129 -  
130 - case 'beacon':  
131 - const dm = `${Buffer.from(event.beacon.dm || '', 'hex').toString('utf8')}`;  
132 - return replyText(event.replyToken, `${event.beacon.type} beacon hwid : ${event.beacon.hwid} with device message = ${dm}`);  
133 -  
134 - default:  
135 - throw new Error(`Unknown event: ${JSON.stringify(event)}`);  
136 - }  
137 -}  
138 -  
139 -function handleText(message, replyToken) {  
140 - return replyText(replyToken, message.text);  
141 -}  
142 -  
143 -function handleImage(message, replyToken) {  
144 - return replyText(replyToken, "Got Image");  
145 -}  
146 -  
147 -function handleVideo(message, replyToken) {  
148 - return replyText(replyToken, "Got Video");  
149 -}  
150 -  
151 -function handleAudio(message, replyToken) {  
152 - return replyText(replyToken, "Got Audio");  
153 -}  
154 -  
155 -function handleLocation(message, replyToken) {  
156 - return replyText(replyToken, "Got Location");  
157 -}  
158 -  
159 -function handleSticker(message, replyToken) {  
160 - return replyText(replyToken, "Got Sticker");  
161 -}  
162 -  
163 -const port = config.port;  
164 -app.listen(port, () => {  
165 - console.log(`listening on ${port}`);  
166 -});  
indexv1.js
@@ -1,553 +0,0 @@ @@ -1,553 +0,0 @@
1 -"use strict";  
2 -  
3 -const line = require("@line/bot-sdk");  
4 -const express = require("express");  
5 -const config = require("./config.json");  
6 -const bodyParser = require("body-parser");  
7 -const axios = require("axios");  
8 -const fs = require("fs");  
9 -const request = require("request");  
10 -const moment = require("moment");  
11 -const { type } = require("os");  
12 -  
13 -// create LINE SDK client  
14 -const client = new line.Client(config);  
15 -  
16 -const app = express();  
17 -  
18 -// webhook callback  
19 -app.use("/webhook", line.middleware(config));  
20 -app.post("/webhook", (req, res) => {  
21 - // req.body.events should be an array of events  
22 - if (!Array.isArray(req.body.events)) {  
23 - return res.status(500).end();  
24 - }  
25 - // handle events separately  
26 - Promise.all(  
27 - req.body.events.map((event) => {  
28 - console.log("event", event);  
29 - // check verify webhook event  
30 - if (  
31 - event.replyToken === "00000000000000000000000000000000" ||  
32 - event.replyToken === "ffffffffffffffffffffffffffffffff"  
33 - ) {  
34 - return;  
35 - }  
36 - return handleEvent(event);  
37 - })  
38 - )  
39 - .then(() => res.end())  
40 - .catch((err) => {  
41 - console.error(err);  
42 - res.status(500).end();  
43 - });  
44 -});  
45 -  
46 -// simple reply function  
47 -const replyText = (token, texts) => {  
48 - texts = Array.isArray(texts) ? texts : [texts];  
49 - return client.replyMessage(  
50 - token,  
51 - texts.map((text) => ({ type: "text", text }))  
52 - );  
53 -};  
54 -  
55 -const tolow = (str) => {  
56 - return str.toLowerCase();  
57 -};  
58 -const handleEvent = (event) => {  
59 - let payload = {  
60 - type: "text",  
61 - text: "Hello From PUI",  
62 - };  
63 -  
64 - if (event.message.type == "text") {  
65 - let selecttext = tolow(event.message.text);  
66 - let get_text = mockText()[selecttext];  
67 - if (get_text) {  
68 - payload = get_text;  
69 - }  
70 - } else {  
71 - payload.text = "Other Message =>>>" + JSON.stringify(event);  
72 - }  
73 -  
74 - return client.replyMessage(event.replyToken, payload);  
75 -};  
76 -app.use(bodyParser.json());  
77 -  
78 -app.get("/", (req, res) => {  
79 - res.json({ line: "ok" });  
80 -});  
81 -  
82 -app.get("/push", bodyParser.json(), (req, res) => {  
83 - let message = {  
84 - type: "text",  
85 - text: `use Push Message! to `,  
86 - };  
87 - client.pushMessage("Uaac2ca5a02feab67a18d5521b572b5aa", message);  
88 - res.json(message);  
89 -});  
90 -  
91 -app.post("/save", bodyParser.json(), async (req, res) => {  
92 - console.log("saveFile!");  
93 - try {  
94 - const downloadFile = function (uri, filename, callback) {  
95 - request.head(uri, function (err, res, body) {  
96 - console.log("content-type:", res.headers["content-type"]);  
97 - console.log("content-length:", res.headers["content-length"]);  
98 - console.log("Content-Type:", res.headers["Content-Type"]);  
99 - console.log("res.headers ::", res.headers);  
100 -  
101 - request(uri, {  
102 - headers: {  
103 - Authorization:  
104 - "Bearer be/XHjQ+gMoypZE78Us7hk0h6PA04TyfpQciMOq+B/OVPmumozdhGzYUwopDgsOMCM7RymTK8m++q20GSj3c6B7gZkgEmuGYEYPvc6j+4as6X5bu7tEg+KAZKMfBVDnk+ekpAorC7FMwVPyt2frGRQdB04t89/1O/w1cDnyilFU=",  
105 - },  
106 - })  
107 - .pipe(fs.createWriteStream(filename))  
108 - .on("close", callback);  
109 - });  
110 - };  
111 -  
112 - let unquie_file = moment().format("YYYY-MM-DD_HHmmssss");  
113 - let file_name = `filesave_${unquie_file}`;  
114 - let message_id = req.body.message_id;  
115 - let URI = `https://api-data.line.me/v2/bot/message/${message_id}/content`;  
116 - console.log("message_id ::", message_id);  
117 - console.log("file_name ::", file_name);  
118 -  
119 - axios  
120 - .get(URI, {  
121 - headers: {  
122 - Authorization:  
123 - "Bearer be/XHjQ+gMoypZE78Us7hk0h6PA04TyfpQciMOq+B/OVPmumozdhGzYUwopDgsOMCM7RymTK8m++q20GSj3c6B7gZkgEmuGYEYPvc6j+4as6X5bu7tEg+KAZKMfBVDnk+ekpAorC7FMwVPyt2frGRQdB04t89/1O/w1cDnyilFU=",  
124 - },  
125 - })  
126 - .then(function (response) {  
127 - // handle success  
128 - console.log("axios =>>", response.headers["content-type"]);  
129 - let sp = response.headers["content-type"].split("/");  
130 - let type = sp[sp.length - 1];  
131 - let full_file_name = file_name + "." + type;  
132 - console.log("full_file_name =", full_file_name);  
133 - downloadFile(URI, full_file_name, function () {  
134 - console.log("done!");  
135 - res.json({ LoadFlieName: "Success" });  
136 - });  
137 - })  
138 - .catch(function (error) {  
139 - // handle error  
140 - console.log(error);  
141 - console.error("errorxx ::", error);  
142 - res.json({ error: "error" });  
143 - });  
144 - } catch (error) {  
145 - console.error("errorxx ::", error);  
146 - }  
147 -});  
148 -  
149 -app.post("/saveNew", bodyParser.json(), async (req, res) => {  
150 - console.log("saveFile!");  
151 - try {  
152 - let stream = await client.getMessageContent("14955535936627");  
153 - console.log("stream!", stream);  
154 - } catch (error) {  
155 - console.error(error);  
156 - }  
157 - res.json({ OK: "OK" });  
158 -});  
159 -  
160 -app.post("/push", (req, res) => {  
161 - let body = req.body;  
162 - let { user_id } = body;  
163 - console.log("body ::", body);  
164 - let message = {  
165 - type: "text",  
166 - text: `use Push Message! to ${user_id}`,  
167 - };  
168 - client.pushMessage(user_id, message);  
169 - res.json(message);  
170 -});  
171 -  
172 -app.post("/multicast", (req, res) => {  
173 - let body = req.body;  
174 - let { user_ids } = body;  
175 - console.log("body ::", body);  
176 - let message = [  
177 - {  
178 - type: "text",  
179 - text: `use multicast Message1! to ${JSON.stringify(user_ids)}`,  
180 - },  
181 - {  
182 - type: "text",  
183 - text: `use multicast Message2! to ${JSON.stringify(user_ids)}`,  
184 - },  
185 - ];  
186 - client.multicast(user_ids, message);  
187 - res.json(message);  
188 -});  
189 -  
190 -const port = config.port;  
191 -app.listen(port, () => {  
192 - console.log(`listening on ${port}`);  
193 -});  
194 -  
195 -const GenContentFlex = (content) => {  
196 - return {  
197 - flex1: {  
198 - type: "flex",  
199 - altText: "GenContentFlex!",  
200 - contents: content,  
201 - },  
202 - };  
203 -};  
204 -  
205 -const mockText = () => {  
206 - return {  
207 - flex1: {  
208 - type: "flex",  
209 - altText: "this is a flex message",  
210 - contents: {  
211 - type: "bubble",  
212 - body: {  
213 - type: "box",  
214 - layout: "vertical",  
215 - contents: [  
216 - {  
217 - type: "text",  
218 - text: "hello",  
219 - },  
220 - {  
221 - type: "text",  
222 - text: "world",  
223 - },  
224 - ],  
225 - },  
226 - },  
227 - },  
228 -  
229 - flex2: {  
230 - type: "flex",  
231 - altText: "this is a flex message",  
232 - contents: {  
233 - type: "bubble",  
234 - direction: "ltr",  
235 - header: {  
236 - type: "box",  
237 - layout: "vertical",  
238 - contents: [  
239 - {  
240 - type: "text",  
241 - text: "แมว",  
242 - align: "center",  
243 - contents: [],  
244 - },  
245 - ],  
246 - },  
247 - hero: {  
248 - type: "image",  
249 - url: "https://static.trueplookpanya.com/tppy/member/m_545000_547500/545994/cms/images/2019-Q3/แมว9ชีวิต.jpg",  
250 - size: "full",  
251 - aspectRatio: "1.51:1",  
252 - aspectMode: "fit",  
253 - },  
254 - body: {  
255 - type: "box",  
256 - layout: "vertical",  
257 - contents: [  
258 - {  
259 - type: "text",  
260 - text: "คำอธิบาย",  
261 - align: "center",  
262 - contents: [],  
263 - },  
264 - ],  
265 - },  
266 - footer: {  
267 - type: "box",  
268 - layout: "horizontal",  
269 - contents: [  
270 - {  
271 - type: "button",  
272 - action: {  
273 - type: "uri",  
274 - label: "ดูรูปแมวชัดๆ",  
275 - uri: "https://static.trueplookpanya.com/tppy/member/m_545000_547500/545994/cms/images/2019-Q3/แมว9ชีวิต.jpg",  
276 - },  
277 - },  
278 - ],  
279 - },  
280 - },  
281 - },  
282 -  
283 - flex3: {  
284 - type: "flex",  
285 - altText: "this is a flex message",  
286 - contents: {  
287 - type: "bubble",  
288 - direction: "ltr",  
289 - hero: {  
290 - type: "image",  
291 - url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/01_3_movie.png",  
292 - size: "full",  
293 - aspectRatio: "20:13",  
294 - aspectMode: "cover",  
295 - action: {  
296 - type: "uri",  
297 - label: "Action",  
298 - uri: "https://linecorp.com/",  
299 - },  
300 - },  
301 - body: {  
302 - type: "box",  
303 - layout: "vertical",  
304 - spacing: "md",  
305 - contents: [  
306 - {  
307 - type: "text",  
308 - text: "BROWN'S ADVENTURE\nIN MOVIE",  
309 - weight: "bold",  
310 - size: "xl",  
311 - gravity: "center",  
312 - wrap: true,  
313 - contents: [],  
314 - },  
315 - {  
316 - type: "box",  
317 - layout: "baseline",  
318 - margin: "md",  
319 - contents: [  
320 - {  
321 - type: "icon",  
322 - url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gold_star_28.png",  
323 - size: "sm",  
324 - },  
325 - {  
326 - type: "icon",  
327 - url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gold_star_28.png",  
328 - size: "sm",  
329 - },  
330 - {  
331 - type: "icon",  
332 - url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gold_star_28.png",  
333 - size: "sm",  
334 - },  
335 - {  
336 - type: "icon",  
337 - url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gold_star_28.png",  
338 - size: "sm",  
339 - },  
340 - {  
341 - type: "icon",  
342 - url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gray_star_28.png",  
343 - size: "sm",  
344 - },  
345 - {  
346 - type: "text",  
347 - text: "4.0",  
348 - size: "sm",  
349 - color: "#999999",  
350 - flex: 0,  
351 - margin: "md",  
352 - contents: [],  
353 - },  
354 - ],  
355 - },  
356 - {  
357 - type: "box",  
358 - layout: "vertical",  
359 - spacing: "sm",  
360 - margin: "lg",  
361 - contents: [  
362 - {  
363 - type: "box",  
364 - layout: "baseline",  
365 - spacing: "sm",  
366 - contents: [  
367 - {  
368 - type: "text",  
369 - text: "Date",  
370 - size: "sm",  
371 - color: "#AAAAAA",  
372 - flex: 1,  
373 - contents: [],  
374 - },  
375 - {  
376 - type: "text",  
377 - text: "Monday 25, 9:00PM",  
378 - size: "sm",  
379 - color: "#666666",  
380 - flex: 4,  
381 - wrap: true,  
382 - contents: [],  
383 - },  
384 - ],  
385 - },  
386 - {  
387 - type: "box",  
388 - layout: "baseline",  
389 - spacing: "sm",  
390 - contents: [  
391 - {  
392 - type: "text",  
393 - text: "Place",  
394 - size: "sm",  
395 - color: "#AAAAAA",  
396 - flex: 1,  
397 - contents: [],  
398 - },  
399 - {  
400 - type: "text",  
401 - text: "7 Floor, No.3",  
402 - size: "sm",  
403 - color: "#666666",  
404 - flex: 4,  
405 - wrap: true,  
406 - contents: [],  
407 - },  
408 - ],  
409 - },  
410 - {  
411 - type: "box",  
412 - layout: "baseline",  
413 - spacing: "sm",  
414 - contents: [  
415 - {  
416 - type: "text",  
417 - text: "Seats",  
418 - size: "sm",  
419 - color: "#AAAAAA",  
420 - flex: 1,  
421 - contents: [],  
422 - },  
423 - {  
424 - type: "text",  
425 - text: "C Row, 18 Seat",  
426 - size: "sm",  
427 - color: "#666666",  
428 - flex: 4,  
429 - wrap: true,  
430 - contents: [],  
431 - },  
432 - ],  
433 - },  
434 - ],  
435 - },  
436 - {  
437 - type: "box",  
438 - layout: "vertical",  
439 - margin: "xxl",  
440 - contents: [  
441 - {  
442 - type: "spacer",  
443 - },  
444 - {  
445 - type: "image",  
446 - url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/linecorp_code_withborder.png",  
447 - size: "xl",  
448 - aspectMode: "cover",  
449 - },  
450 - {  
451 - type: "text",  
452 - text: "You can enter the theater by using this code instead of a ticket",  
453 - size: "xs",  
454 - color: "#AAAAAA",  
455 - margin: "xxl",  
456 - wrap: true,  
457 - contents: [],  
458 - },  
459 - ],  
460 - },  
461 - ],  
462 - },  
463 - },  
464 - },  
465 -  
466 -  
467 -  
468 - cat: {  
469 - type: "bubble",  
470 - direction: "ltr",  
471 - header: {  
472 - type: "box",  
473 - layout: "vertical",  
474 - contents: [  
475 - {  
476 - type: "text",  
477 - text: "แมว",  
478 - align: "center",  
479 - contents: [],  
480 - },  
481 - ],  
482 - },  
483 - hero: {  
484 - type: "image",  
485 - url: "https://static.trueplookpanya.com/tppy/member/m_545000_547500/545994/cms/images/2019-Q3/แมว9ชีวิต.jpg",  
486 - size: "full",  
487 - aspectRatio: "1.51:1",  
488 - aspectMode: "fit",  
489 - },  
490 - body: {  
491 - type: "box",  
492 - layout: "vertical",  
493 - contents: [  
494 - {  
495 - type: "text",  
496 - text: "คำอธิบาย",  
497 - align: "center",  
498 - contents: [],  
499 - },  
500 - ],  
501 - },  
502 - footer: {  
503 - type: "box",  
504 - layout: "horizontal",  
505 - contents: [  
506 - {  
507 - type: "button",  
508 - action: {  
509 - type: "uri",  
510 - label: "ดูรูปแมวชัดๆ",  
511 - uri: "https://static.trueplookpanya.com/tppy/member/m_545000_547500/545994/cms/images/2019-Q3/แมว9ชีวิต.jpg",  
512 - },  
513 - },  
514 - ],  
515 - },  
516 - },  
517 -  
518 - location: {  
519 - type: "text", // ①  
520 - text: "Select your favorite food category or send me your location!",  
521 - quickReply: {  
522 - // ②  
523 - items: [  
524 - {  
525 - type: "action", // ③  
526 - imageUrl: "https://example.com/sushi.png",  
527 - action: {  
528 - type: "message",  
529 - label: "Sushi",  
530 - text: "Sushi",  
531 - },  
532 - },  
533 - {  
534 - type: "action",  
535 - imageUrl: "https://example.com/tempura.png",  
536 - action: {  
537 - type: "message",  
538 - label: "Tempura",  
539 - text: "Tempura",  
540 - },  
541 - },  
542 - {  
543 - type: "action", // ④  
544 - action: {  
545 - type: "location",  
546 - label: "Send location",  
547 - },  
548 - },  
549 - ],  
550 - },  
551 - },  
552 - };  
553 -};  
services/ContentService.js 0 → 100644
@@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
  1 +
  2 +const flexMsg = require("./flexMsg");
  3 +const genMsgContent = flexMsg.GenContentFlex;
  4 +const flexs = flexMsg.flexs;
  5 +
  6 +
  7 +const ContentService = {
  8 + mockText: () => {
  9 + return {
  10 + flex0: flexs.flex0,
  11 + flex1: flexs.flex1,
  12 +
  13 + bub1: flexs.bub1,
  14 + bub2: flexs.bub2,
  15 + bub3: flexs.bub3,
  16 + bub4: flexs.bub4,
  17 + bub5: flexs.bub5,
  18 + bub6: flexs.bub6,
  19 + };
  20 + },
  21 +};
  22 +
  23 +module.exports = ContentService;
services/LineService.js 0 → 100644
@@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
  1 +const axios = require("axios").default;
  2 +const headers = {
  3 + Authorization:
  4 + "Bearer be/XHjQ+gMoypZE78Us7hk0h6PA04TyfpQciMOq+B/OVPmumozdhGzYUwopDgsOMCM7RymTK8m++q20GSj3c6B7gZkgEmuGYEYPvc6j+4as6X5bu7tEg+KAZKMfBVDnk+ekpAorC7FMwVPyt2frGRQdB04t89/1O/w1cDnyilFU=",
  5 + "Content-Type": "application/json",
  6 +};
  7 +
  8 +const LineService = {
  9 + Broadcast: async (messages) => {
  10 + console.log("");
  11 + return new Promise(async (resolve, reject) => {
  12 + let URL = "https://api.line.me/v2/bot/message/broadcast";
  13 + let payload = { messages: messages };
  14 + try {
  15 + let res = await axios.post(URL, payload, {
  16 + headers: headers,
  17 + });
  18 + // console.log("res ::", res);
  19 + resolve(res);
  20 + } catch (e) {
  21 + console.log("bbb!");
  22 + console.log("Error ::", e);
  23 + reject(null);
  24 + }
  25 + });
  26 + },
  27 +};
  28 +
  29 +module.exports = LineService;
services/flexMsg.js 0 → 100644
@@ -0,0 +1,749 @@ @@ -0,0 +1,749 @@
  1 +const GenContentFlex = (content, text = "0") => {
  2 + return {
  3 + type: "flex",
  4 + altText: "GenContentFlex!" + text,
  5 + contents: content,
  6 + };
  7 +};
  8 +
  9 +const flexs = {
  10 + flex0: {
  11 + type: "flex",
  12 + altText: "this is a flex message",
  13 + contents: {
  14 + type: "bubble",
  15 + body: {
  16 + type: "box",
  17 + layout: "vertical",
  18 + contents: [
  19 + {
  20 + type: "text",
  21 + text: "hello",
  22 + },
  23 + {
  24 + type: "text",
  25 + text: "world",
  26 + },
  27 + ],
  28 + },
  29 + },
  30 + },
  31 + flex1: GenContentFlex({
  32 + type: "bubble",
  33 + body: {
  34 + type: "box",
  35 + layout: "vertical",
  36 + contents: [
  37 + {
  38 + type: "text",
  39 + text: "hello",
  40 + },
  41 + {
  42 + type: "text",
  43 + text: "world",
  44 + },
  45 + ],
  46 + },
  47 + }),
  48 +
  49 + bub1: GenContentFlex({
  50 + type: "bubble",
  51 + direction: "ltr",
  52 + header: {
  53 + type: "box",
  54 + layout: "vertical",
  55 + contents: [
  56 + {
  57 + type: "text",
  58 + text: "Header",
  59 + align: "center",
  60 + contents: [],
  61 + },
  62 + ],
  63 + },
  64 + hero: {
  65 + type: "image",
  66 + url: "https://vos.line-scdn.net/bot-designer-template-images/bot-designer-icon.png",
  67 + size: "full",
  68 + aspectRatio: "1.51:1",
  69 + aspectMode: "fit",
  70 + },
  71 + body: {
  72 + type: "box",
  73 + layout: "vertical",
  74 + contents: [
  75 + {
  76 + type: "text",
  77 + text: "Body",
  78 + align: "center",
  79 + contents: [],
  80 + },
  81 + ],
  82 + },
  83 + footer: {
  84 + type: "box",
  85 + layout: "horizontal",
  86 + contents: [
  87 + {
  88 + type: "button",
  89 + action: {
  90 + type: "uri",
  91 + label: "Button",
  92 + uri: "https://linecorp.com",
  93 + },
  94 + },
  95 + ],
  96 + },
  97 + }),
  98 +
  99 + bub2: GenContentFlex({
  100 + type: "bubble",
  101 + hero: {
  102 + type: "image",
  103 + url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/01_1_cafe.png",
  104 + size: "full",
  105 + aspectRatio: "20:13",
  106 + aspectMode: "cover",
  107 + action: {
  108 + type: "uri",
  109 + label: "Line",
  110 + uri: "https://linecorp.com/",
  111 + },
  112 + },
  113 + body: {
  114 + type: "box",
  115 + layout: "vertical",
  116 + contents: [
  117 + {
  118 + type: "text",
  119 + text: "Brown Cafe",
  120 + weight: "bold",
  121 + size: "xl",
  122 + contents: [],
  123 + },
  124 + {
  125 + type: "box",
  126 + layout: "baseline",
  127 + margin: "md",
  128 + contents: [
  129 + {
  130 + type: "icon",
  131 + url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gold_star_28.png",
  132 + size: "sm",
  133 + },
  134 + {
  135 + type: "icon",
  136 + url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gold_star_28.png",
  137 + size: "sm",
  138 + },
  139 + {
  140 + type: "icon",
  141 + url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gold_star_28.png",
  142 + size: "sm",
  143 + },
  144 + {
  145 + type: "icon",
  146 + url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gold_star_28.png",
  147 + size: "sm",
  148 + },
  149 + {
  150 + type: "icon",
  151 + url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gray_star_28.png",
  152 + size: "sm",
  153 + },
  154 + {
  155 + type: "text",
  156 + text: "4.0",
  157 + size: "sm",
  158 + color: "#999999",
  159 + flex: 0,
  160 + margin: "md",
  161 + contents: [],
  162 + },
  163 + ],
  164 + },
  165 + {
  166 + type: "box",
  167 + layout: "vertical",
  168 + spacing: "sm",
  169 + margin: "lg",
  170 + contents: [
  171 + {
  172 + type: "box",
  173 + layout: "baseline",
  174 + spacing: "sm",
  175 + contents: [
  176 + {
  177 + type: "text",
  178 + text: "Place",
  179 + size: "sm",
  180 + color: "#AAAAAA",
  181 + flex: 1,
  182 + contents: [],
  183 + },
  184 + {
  185 + type: "text",
  186 + text: "Miraina Tower, 4-1-6 Shinjuku, Tokyo",
  187 + size: "sm",
  188 + color: "#666666",
  189 + flex: 5,
  190 + wrap: true,
  191 + contents: [],
  192 + },
  193 + ],
  194 + },
  195 + {
  196 + type: "box",
  197 + layout: "baseline",
  198 + spacing: "sm",
  199 + contents: [
  200 + {
  201 + type: "text",
  202 + text: "Time",
  203 + size: "sm",
  204 + color: "#AAAAAA",
  205 + flex: 1,
  206 + contents: [],
  207 + },
  208 + {
  209 + type: "text",
  210 + text: "10:00 - 23:00",
  211 + size: "sm",
  212 + color: "#666666",
  213 + flex: 5,
  214 + wrap: true,
  215 + contents: [],
  216 + },
  217 + ],
  218 + },
  219 + ],
  220 + },
  221 + ],
  222 + },
  223 + footer: {
  224 + type: "box",
  225 + layout: "vertical",
  226 + flex: 0,
  227 + spacing: "sm",
  228 + contents: [
  229 + {
  230 + type: "button",
  231 + action: {
  232 + type: "uri",
  233 + label: "CALL",
  234 + uri: "https://linecorp.com",
  235 + },
  236 + height: "sm",
  237 + style: "link",
  238 + },
  239 + {
  240 + type: "button",
  241 + action: {
  242 + type: "uri",
  243 + label: "WEBSITE",
  244 + uri: "https://linecorp.com",
  245 + },
  246 + height: "sm",
  247 + style: "link",
  248 + },
  249 + {
  250 + type: "spacer",
  251 + size: "sm",
  252 + },
  253 + ],
  254 + },
  255 + }),
  256 + bub3: GenContentFlex({
  257 + type: "bubble",
  258 + header: {
  259 + type: "box",
  260 + layout: "horizontal",
  261 + contents: [
  262 + {
  263 + type: "text",
  264 + text: "NEWS DIGEST",
  265 + weight: "bold",
  266 + size: "sm",
  267 + color: "#AAAAAA",
  268 + contents: [],
  269 + },
  270 + ],
  271 + },
  272 + hero: {
  273 + type: "image",
  274 + url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/01_4_news.png",
  275 + size: "full",
  276 + aspectRatio: "20:13",
  277 + aspectMode: "cover",
  278 + action: {
  279 + type: "uri",
  280 + label: "Action",
  281 + uri: "https://linecorp.com/",
  282 + },
  283 + },
  284 + body: {
  285 + type: "box",
  286 + layout: "horizontal",
  287 + spacing: "md",
  288 + contents: [
  289 + {
  290 + type: "box",
  291 + layout: "vertical",
  292 + flex: 1,
  293 + contents: [
  294 + {
  295 + type: "image",
  296 + url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/02_1_news_thumbnail_1.png",
  297 + gravity: "bottom",
  298 + size: "sm",
  299 + aspectRatio: "4:3",
  300 + aspectMode: "cover",
  301 + },
  302 + {
  303 + type: "image",
  304 + url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/02_1_news_thumbnail_2.png",
  305 + margin: "md",
  306 + size: "sm",
  307 + aspectRatio: "4:3",
  308 + aspectMode: "cover",
  309 + },
  310 + ],
  311 + },
  312 + {
  313 + type: "box",
  314 + layout: "vertical",
  315 + flex: 2,
  316 + contents: [
  317 + {
  318 + type: "text",
  319 + text: "7 Things to Know for Today",
  320 + size: "xs",
  321 + flex: 1,
  322 + gravity: "top",
  323 + contents: [],
  324 + },
  325 + {
  326 + type: "separator",
  327 + },
  328 + {
  329 + type: "text",
  330 + text: "Hay fever goes wild",
  331 + size: "xs",
  332 + flex: 2,
  333 + gravity: "center",
  334 + contents: [],
  335 + },
  336 + {
  337 + type: "separator",
  338 + },
  339 + {
  340 + type: "text",
  341 + text: "LINE Pay Begins Barcode Payment Service",
  342 + size: "xs",
  343 + flex: 2,
  344 + gravity: "center",
  345 + contents: [],
  346 + },
  347 + {
  348 + type: "separator",
  349 + },
  350 + {
  351 + type: "text",
  352 + text: "LINE Adds LINE Wallet",
  353 + size: "xs",
  354 + flex: 1,
  355 + gravity: "bottom",
  356 + contents: [],
  357 + },
  358 + ],
  359 + },
  360 + ],
  361 + },
  362 + footer: {
  363 + type: "box",
  364 + layout: "horizontal",
  365 + contents: [
  366 + {
  367 + type: "button",
  368 + action: {
  369 + type: "uri",
  370 + label: "More",
  371 + uri: "https://linecorp.com",
  372 + },
  373 + },
  374 + ],
  375 + },
  376 + }),
  377 + bub4: GenContentFlex({
  378 + type: "bubble",
  379 + hero: {
  380 + type: "image",
  381 + url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/01_2_restaurant.png",
  382 + size: "full",
  383 + aspectRatio: "20:13",
  384 + aspectMode: "cover",
  385 + action: {
  386 + type: "uri",
  387 + label: "Action",
  388 + uri: "https://linecorp.com",
  389 + },
  390 + },
  391 + body: {
  392 + type: "box",
  393 + layout: "vertical",
  394 + spacing: "md",
  395 + action: {
  396 + type: "uri",
  397 + label: "Action",
  398 + uri: "https://linecorp.com",
  399 + },
  400 + contents: [
  401 + {
  402 + type: "text",
  403 + text: "Brown's Burger",
  404 + weight: "bold",
  405 + size: "xl",
  406 + contents: [],
  407 + },
  408 + {
  409 + type: "box",
  410 + layout: "vertical",
  411 + spacing: "sm",
  412 + contents: [
  413 + {
  414 + type: "box",
  415 + layout: "baseline",
  416 + contents: [
  417 + {
  418 + type: "icon",
  419 + url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/restaurant_regular_32.png",
  420 + },
  421 + {
  422 + type: "text",
  423 + text: "$10.5",
  424 + weight: "bold",
  425 + margin: "sm",
  426 + contents: [],
  427 + },
  428 + {
  429 + type: "text",
  430 + text: "400kcl",
  431 + size: "sm",
  432 + color: "#AAAAAA",
  433 + align: "end",
  434 + contents: [],
  435 + },
  436 + ],
  437 + },
  438 + {
  439 + type: "box",
  440 + layout: "baseline",
  441 + contents: [
  442 + {
  443 + type: "icon",
  444 + url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/restaurant_large_32.png",
  445 + },
  446 + {
  447 + type: "text",
  448 + text: "$15.5",
  449 + weight: "bold",
  450 + flex: 0,
  451 + margin: "sm",
  452 + contents: [],
  453 + },
  454 + {
  455 + type: "text",
  456 + text: "550kcl",
  457 + size: "sm",
  458 + color: "#AAAAAA",
  459 + align: "end",
  460 + contents: [],
  461 + },
  462 + ],
  463 + },
  464 + ],
  465 + },
  466 + {
  467 + type: "text",
  468 + text: "Sauce, Onions, Pickles, Lettuce & Cheese",
  469 + size: "xxs",
  470 + color: "#AAAAAA",
  471 + wrap: true,
  472 + contents: [],
  473 + },
  474 + ],
  475 + },
  476 + footer: {
  477 + type: "box",
  478 + layout: "vertical",
  479 + contents: [
  480 + {
  481 + type: "spacer",
  482 + size: "xxl",
  483 + },
  484 + {
  485 + type: "button",
  486 + action: {
  487 + type: "uri",
  488 + label: "Add to Cart",
  489 + uri: "https://linecorp.com",
  490 + },
  491 + color: "#905C44",
  492 + style: "primary",
  493 + },
  494 + ],
  495 + },
  496 + }),
  497 + bub5: GenContentFlex({
  498 + type: "bubble",
  499 + hero: {
  500 + type: "image",
  501 + url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/01_3_movie.png",
  502 + size: "full",
  503 + aspectRatio: "20:13",
  504 + aspectMode: "cover",
  505 + action: {
  506 + type: "uri",
  507 + label: "Action",
  508 + uri: "https://linecorp.com/",
  509 + },
  510 + },
  511 + body: {
  512 + type: "box",
  513 + layout: "vertical",
  514 + spacing: "md",
  515 + contents: [
  516 + {
  517 + type: "text",
  518 + text: "BROWN'S ADVENTURE\nIN MOVIE",
  519 + weight: "bold",
  520 + size: "xl",
  521 + gravity: "center",
  522 + wrap: true,
  523 + contents: [],
  524 + },
  525 + {
  526 + type: "box",
  527 + layout: "baseline",
  528 + margin: "md",
  529 + contents: [
  530 + {
  531 + type: "icon",
  532 + url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gold_star_28.png",
  533 + size: "sm",
  534 + },
  535 + {
  536 + type: "icon",
  537 + url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gold_star_28.png",
  538 + size: "sm",
  539 + },
  540 + {
  541 + type: "icon",
  542 + url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gold_star_28.png",
  543 + size: "sm",
  544 + },
  545 + {
  546 + type: "icon",
  547 + url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gold_star_28.png",
  548 + size: "sm",
  549 + },
  550 + {
  551 + type: "icon",
  552 + url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/review_gray_star_28.png",
  553 + size: "sm",
  554 + },
  555 + {
  556 + type: "text",
  557 + text: "4.0",
  558 + size: "sm",
  559 + color: "#999999",
  560 + flex: 0,
  561 + margin: "md",
  562 + contents: [],
  563 + },
  564 + ],
  565 + },
  566 + {
  567 + type: "box",
  568 + layout: "vertical",
  569 + spacing: "sm",
  570 + margin: "lg",
  571 + contents: [
  572 + {
  573 + type: "box",
  574 + layout: "baseline",
  575 + spacing: "sm",
  576 + contents: [
  577 + {
  578 + type: "text",
  579 + text: "Date",
  580 + size: "sm",
  581 + color: "#AAAAAA",
  582 + flex: 1,
  583 + contents: [],
  584 + },
  585 + {
  586 + type: "text",
  587 + text: "Monday 25, 9:00PM",
  588 + size: "sm",
  589 + color: "#666666",
  590 + flex: 4,
  591 + wrap: true,
  592 + contents: [],
  593 + },
  594 + ],
  595 + },
  596 + {
  597 + type: "box",
  598 + layout: "baseline",
  599 + spacing: "sm",
  600 + contents: [
  601 + {
  602 + type: "text",
  603 + text: "Place",
  604 + size: "sm",
  605 + color: "#AAAAAA",
  606 + flex: 1,
  607 + contents: [],
  608 + },
  609 + {
  610 + type: "text",
  611 + text: "7 Floor, No.3",
  612 + size: "sm",
  613 + color: "#666666",
  614 + flex: 4,
  615 + wrap: true,
  616 + contents: [],
  617 + },
  618 + ],
  619 + },
  620 + {
  621 + type: "box",
  622 + layout: "baseline",
  623 + spacing: "sm",
  624 + contents: [
  625 + {
  626 + type: "text",
  627 + text: "Seats",
  628 + size: "sm",
  629 + color: "#AAAAAA",
  630 + flex: 1,
  631 + contents: [],
  632 + },
  633 + {
  634 + type: "text",
  635 + text: "C Row, 18 Seat",
  636 + size: "sm",
  637 + color: "#666666",
  638 + flex: 4,
  639 + wrap: true,
  640 + contents: [],
  641 + },
  642 + ],
  643 + },
  644 + ],
  645 + },
  646 + {
  647 + type: "box",
  648 + layout: "vertical",
  649 + margin: "xxl",
  650 + contents: [
  651 + {
  652 + type: "spacer",
  653 + },
  654 + {
  655 + type: "image",
  656 + url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/linecorp_code_withborder.png",
  657 + size: "xl",
  658 + aspectMode: "cover",
  659 + },
  660 + {
  661 + type: "text",
  662 + text: "You can enter the theater by using this code instead of a ticket",
  663 + size: "xs",
  664 + color: "#AAAAAA",
  665 + margin: "xxl",
  666 + wrap: true,
  667 + contents: [],
  668 + },
  669 + ],
  670 + },
  671 + ],
  672 + },
  673 + }),
  674 + bub6: GenContentFlex({
  675 + type: "bubble",
  676 + hero: {
  677 + type: "image",
  678 + url: "https://scdn.line-apps.com/n/channel_devcenter/img/fx/01_5_carousel.png",
  679 + size: "full",
  680 + aspectRatio: "20:13",
  681 + aspectMode: "cover",
  682 + },
  683 + body: {
  684 + type: "box",
  685 + layout: "vertical",
  686 + spacing: "sm",
  687 + contents: [
  688 + {
  689 + type: "text",
  690 + text: "Arm Chair, White",
  691 + weight: "bold",
  692 + size: "xl",
  693 + wrap: true,
  694 + contents: [],
  695 + },
  696 + {
  697 + type: "box",
  698 + layout: "baseline",
  699 + contents: [
  700 + {
  701 + type: "text",
  702 + text: "$49",
  703 + weight: "bold",
  704 + size: "xl",
  705 + flex: 0,
  706 + wrap: true,
  707 + contents: [],
  708 + },
  709 + {
  710 + type: "text",
  711 + text: ".99",
  712 + weight: "bold",
  713 + size: "sm",
  714 + flex: 0,
  715 + wrap: true,
  716 + contents: [],
  717 + },
  718 + ],
  719 + },
  720 + ],
  721 + },
  722 + footer: {
  723 + type: "box",
  724 + layout: "vertical",
  725 + spacing: "sm",
  726 + contents: [
  727 + {
  728 + type: "button",
  729 + action: {
  730 + type: "uri",
  731 + label: "Add to Cart",
  732 + uri: "https://linecorp.com",
  733 + },
  734 + style: "primary",
  735 + },
  736 + {
  737 + type: "button",
  738 + action: {
  739 + type: "uri",
  740 + label: "Add to wishlist",
  741 + uri: "https://linecorp.com",
  742 + },
  743 + },
  744 + ],
  745 + },
  746 + }),
  747 +};
  748 +
  749 +module.exports = { GenContentFlex, flexs };