iT邦幫忙

2

node.js開發 linebot上訊息呈現格式

  • 分享至 

  • xImage

小弟初學linebot開發
應用linebot查詢postgresql資料庫裡的資料
但在linebot呈現上有所落差
想請問該怎麼更改我的程式(程式於文章最後)

  • 問題一:合併訊息
    當我輸入關鍵字後查詢到的結果是這樣:
    https://ithelp.ithome.com.tw/upload/images/20190912/20118967sRxgfG3jLV.jpg
    而我想得到的是這樣:
    https://ithelp.ithome.com.tw/upload/images/20190912/20118967CTPEaEEbKx.jpg
  • 問題二:linebot只回應第一筆資料
    我利用資料存入的時間為linebot上的關鍵字去查詢數據
    總共有12筆符合的資料卻都只呈現第一筆
    資料表如下:
    https://ithelp.ithome.com.tw/upload/images/20190912/20118967QLPbyheffA.jpg
    linebot呈現:
    https://ithelp.ithome.com.tw/upload/images/20190912/20118967MVnFck371w.jpg
    我的程式:
 5 line連接DB-由日期取出工件數據

|__
|__ index.js
|__ package.json
|
|__
|__ asyncDB.js
|__ fixture.js


## 1. asyncDB.js 

填入自己的pgConn

#### 程式
``` js
'use strict';

//-----------------------
// 引用資料庫模組
//-----------------------
const {Client} = require('pg');

//-----------------------
// 自己的資料庫連結位址
//-----------------------
var pgConn = 'postgres://mmopgvcydqshfc:****************************71e5509028d66e81b07f44e055ad22877d9acb89e@ec2-174-129-231-116.compute-1.amazonaws.com:5432/****************';


//產生可同步執行query物件的函式
function query(sql, value=null) {
    return new Promise((resolve, reject) => {
        //設定資料庫連線物件
        var client = new Client({
            connectionString: pgConn,
            ssl: true
        })     

        //連結資料庫
        client.connect();

        //回覆查詢結果  
        client.query(sql, value, (err, results) => {                   
            if (err){
                reject(err);
            }else{
                resolve(results);
            }

            //關閉連線
            client.end();
        });
    });
}

//匯出
module.exports = query;

2. fixture.js

這個程式提供以下API讓前端呼叫:

1. 由日期查詢工件數據
   (1)fetchFixture(modified) 
   (2)傳入值: 日期, string
   (3)回傳值:
        |__ {編號, 長度 , 寬度.....}
        |__ -1(找不到)
        |__ -9(執行錯誤)

程式

'use strict';

//引用操作資料庫的物件
const query = require('./asyncDB');

//------------------------------------------
// 由日期查詢工件數據
//------------------------------------------
var fetchfixture = async function(modified){
    //存放結果
    let result;  

    //讀取資料庫
    await query('SELECT * FROM score WHERE date(modified) = $1', [modified])
        .then((data) => {
            if(data.rows.length > 0){
                result = data.rows[0];  //工件資料(物件)
            }else{
                result = -1;  //找不到資料
            }    
        }, (error) => {
            result = -9;  //執行錯誤
        });

    //回傳執行結果
    return result;  
}
//------------------------------------------

//匯出
module.exports = {fetchfixture};

3. index.js

填入自己的channelId, channelSecret及channelAccessToken值

程式

//----------------------------------------
// 載入必要的模組
//----------------------------------------
var linebot = require('linebot');
var express = require('express');

//增加引用函式
const fixture = require('./utility/fixture');

//----------------------------------------
// 填入自己在Line Developers的channel值
//----------------------------------------
var bot = linebot({
    channelId: '**********',
    channelSecret: '***************************',
    channelAccessToken: '****************************************v************1UcDjw0S+NKtn9jElqixWA8QXwhHMpRWfPFIvzOAt3GzKbr/vk1aULZ6LIrWsqfKvoi6Oc0wIPCsE3QeU1AdB04t89/1O/w1cDnyilFU='
});

//--------------------------------
// 機器人接受訊息的處理
//--------------------------------
bot.on('message', function(event) {    
    event.source.profile().then(
        function (profile) {
            //取得使用者資料
            const userName = profile.displayName;
            const userId = profile.userId;
        
            //使用者傳來的日期
            const no = event.message.text;
          
            //呼叫API取得工件資料
            fixture.fetchfixture(no).then(data => {  
                if (data == -1){
                    event.reply('找不到資料');
                }else if(data == -9){                    
                    event.reply('執行錯誤');
                }else{
                    event.reply([  
                     {type:'text', text:data.serno},
                     {type:'text', text:'長度:'+data.length},
                     {type:'text', text:'寬度:'+data.width},
                     {type:'text', text:'面積:'+data.area},
                     {type:'text', text:'大圓:'+data.lcircle}
                     ]);
                    
                        
                }  
            })  
        }
    );
});

//----------------------------------------
// 建立一個網站應用程式app
// 如果連接根目錄, 交給機器人處理
//----------------------------------------
const app = express();
const linebotParser = bot.parser();
app.post('/', linebotParser);

//----------------------------------------
// 可直接取用檔案的資料夾
//----------------------------------------
app.use(express.static('public'));

//----------------------------------------
// 監聽3000埠號, 
// 或是監聽Heroku設定的埠號
//----------------------------------------
var server = app.listen(process.env.PORT || 3000, function() {
    const port = server.address().port;
    console.log("正在監聽埠號:", port);
});

4. package.json

{
    "name": "myApp",
    "version": "1.0.0",
    "description": "my Linebot application",
    "main": "index.js",
    "scripts": {
        "start": "node ."
    },
    "author": "ian",
    "license": "ISC",
    "dependencies": {
        "express": "^4.16.3",
        "linebot": "^1.4.1",
        "pg": "^7.4.3"
    }
}
 
dragonH iT邦超人 5 級 ‧ 2019-09-12 14:44:19 檢舉
別的先不提

先把 token 遮好

還有 database ...
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

3
dragonH
iT邦超人 5 級 ‧ 2019-09-12 14:49:49
最佳解答

鍵盤解題

1 .

改成

const { serno, length, width, area, lcircle } = data;
event.reply([{ type: 'text', text: `${serno}\n長度: ${length}\n寬度: ${width}\n面積: ${area}\n大圓: ${lcircle}\n`}

應該就好了

2 .

阿你不就只回傳第一筆嗎

if(data.rows.length > 0){
    → → → → result = data.rows[0]; ← ← ← ← //工件資料(物件)
}else{
    result = -1;  //找不到資料
}  

不遮 token 就會像這樣

https://ithelp.ithome.com.tw/upload/images/20190912/20117259nGhErKt95C.png

這樣是有 post 成功吧

太久沒摸忘了 /images/emoticon/emoticon11.gif

40527145 iT邦新手 5 級 ‧ 2019-09-16 14:34:25 檢舉

不好意思 小弟剛學javascript 問題二的部分 該用什麼關鍵字去學習 那一段我是參考別人的

dragonH iT邦超人 5 級 ‧ 2019-09-16 14:44:23 檢舉

40527145

關鍵字搜尋

Array 陣列

data.rows

裡面裝的是所有符合查詢條件的資料

是一個陣列

然後你的寫法

result = data.rows[0]

就是將符合查詢條件的資料的第一筆 (data.rows[0])

賦值給 result

所以你最後只看到一筆資料

我要發表回答

立即登入回答