iT邦幫忙

2

如何解決linebot每則訊息限制之字元數量

(對象)linebot

(語言)node.js

(問題)想請問如何判斷字元後,將line訊息分段發送?

(內容)我將一台檢測機台量測後的數據寫入資料庫,接著用node.js讓linebot可以藉著使用者輸入的關鍵字撈出幅相符的資料(如圖片),但是發現我每次撈出來的數據,字元並不相同,linebot好像超過2000字元就無法傳送給使用者,而我想到的方法是將訊息拆成2則以上,但我該怎麼去撰寫,還是有更好的辦法呢?

'use strict';

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

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

    await query('SELECT * FROM score WHERE date(modified) = $1', [modified])
        .then((rdata) => {
            if(rdata.rows.length > 0){
               result = rdata.rows;
                //工件資料(物件)
            }else{
                result = -1;  //找不到資料
            }    
        }, (error) => {
            result = -9;  //執行錯誤
        });
        return result;
 }
   fixture.fetchfixture(no).then(data => {  
                if (data == -1){
                    event.reply('找不到資料');
                }else if(data == -9){                    
                    event.reply('執行錯誤');
                }else{
                    let msg='';
                    let firstLine = true;

                    data.forEach(item => {
                        if(firstLine){                            
                            firstLine=false;
                        }else{
                            msg = msg + '\n';
                        }
                        msg = msg + item.serno + '\n' + "長度:"+item.length+ '\n' + "寬度:"+item.width+ '\n' + "面積:"+item.area+ '\n' + "大圓:"+item.lcircle+ '\n' + "小圓:"+item.scircle+ '\n' + "圓心距:"+item.cdistance+ '\n'  ;
                       // if(msg.length >)
                    
                    });
                   
                        event.reply({'type':'text', 'text': msg});
              

                    
                }

                       
                  
                })  
            }
   


(備註)我試過用 if...else 去判斷 輸出字元length是否大於1000,如果大於1000就用 .slice 去分段.slice,但似乎不是個好方法,因為撈出的字元數可能介於500-5000

 fixture.fetchfixture(no).then(data => {  
                if (data == -1){
                    event.reply('找不到資料');
                }else if(data == -9){                    
                    event.reply('執行錯誤');
                }else{
                    let msg='';
                    let firstLine = true;

                    data.forEach(item => {
                        if(firstLine){                            
                            firstLine=false;
                        }else{
                            msg = msg + '\n';
                        }
                        msg = msg + item.serno + '\n' + "長度:"+item.length+ '\n' + "寬度:"+item.width+ '\n' + "面積:"+item.area+ '\n' + "大圓:"+item.lcircle+ '\n' + "小圓:"+item.scircle+ '\n' + "圓心距:"+item.cdistance+ '\n'  ;
                       
                    
                    });
                    if(msg.length>2000&&msg.length<4000){
                        event.reply([
                            {'type':'text', 'text': msg.slice(1,1900)},
                            {'type':'text', 'text': msg.slice(1901,3901)}]
                            );

                    }
                    else if{
                        event.reply({'type':'text', 'text': msg});
                }


                    
                }

                        
                })  

https://ithelp.ithome.com.tw/upload/images/20191002/201189671kAVtAuk1f.jpg

RenZhou iT邦新手 5 級 ‧ 2019-10-02 18:03:53 檢舉
有沒有考慮過用flex message的方式去推訊息
40527145 iT邦新手 5 級 ‧ 2019-10-02 18:34:05 檢舉
每次輸入的關鍵字都不同 用flex 會比較好嗎 還沒有去了解flex

2 個回答

3
Han
iT邦新手 5 級 ‧ 2019-10-02 18:11:36
var datas = '............' ;

var maxTimes = 5 ;    //因為Line的多則訊息上限是5
var messages = [] ;
var offset = 0 ;

while(messages.length <= maxTimes)
{
    messages.push({
        type : 'text',
        text : datas.slice(offset, offset + 1000)
    }) ;

    offset += 1000 ;
}

理論解題而已XD 沒有測試過!

補充一下,如果訊息字數超過五則訊息的話,真的就沒解了..
因為每種訊息都有使用限制,即使是FlexMessage也有10kb的json大小限制
用Carousel的FlexMessage則有50KB的限制。

這部份就請斟酌了!或是做成圖片傳送之類!

40527145 iT邦新手 5 級 ‧ 2019-10-02 18:32:45 檢舉

請問可以稍微解釋一下你程式的觀點嗎? 不太懂

Han iT邦新手 5 級 ‧ 2019-10-02 19:16:49 檢舉

將要傳送的訊息放在messages裡面
迴圈裡面處理字串的切割

2
dragonH
iT邦大師 1 級 ‧ 2019-10-02 18:50:18

codepen

const data = 'x'.repeat(2000).concat('y'.repeat(2000)).concat('z'.repeat(1000));
const sliceCount = Math.ceil(data.length / 2000);
let counter = 0;
while(counter < sliceCount) {
  const start = 2000 * counter;
  const messageTosend = data.slice(start, start + 2000);
  console.log(messageTosend);
  counter += 1;
}

不過真的資料真的那麼長

真的會有人看完嗎

不如串個 圖表 或 表格

把資料視覺化

或許會比較好

小魚 iT邦大師 1 級 ‧ 2019-10-02 22:27:54 檢舉

看到就先跳過.

dragonH iT邦大師 1 級 ‧ 2019-10-02 22:34:00 檢舉

/images/emoticon/emoticon37.gif

我要發表回答

立即登入回答