2-in-1 ดูราคาหุ้น Stock Token ผ่าน Google Sheet และส่งไปไลน์บอท

Programming Jul 2, 2021

เราสามารถดูราคาหุ้นที่ขายอยู่ใน Stock Token ผ่าน Google Sheet ด้วย Google Finance ได้นะ แบบง่ายๆเลยหล่ะ สำหรับ developer เราจะมาเรียนรู้ในการดึงข้อมูลจาก Google Sheet เข้าไลน์บอทของเราอีกรอบนึง

แรงบันดาลใจมาจากคลิป พี่ต้า แห่ง Skooldio ที่ไปออก Mao-Investor แล้วเขาใช้ Google Finance บน Google Sheet ก็เลยนึกถึง Stock Token ใน Binance เลยลองทำดูดีกว่า

.

เนื้อหาเอาใจหลายกลุ่มมาก ทั้งอ่ะคนลงทุนในหุ้นก็ได้ ลงทุนในคริปโตก็ได้ develop ก็ได้ ชาวบ้านอ่านแล้วก็ได้ประโยชน์ แต่บางอย่างอาจจะแบบต้องมีความรู้หน่อย พยายามอธิบายให้เข้าใจง่ายที่สุดเนอะ

Stock Token คืออะไร?

Stock Token เป็นหนึ่งในบริการของเว็บไซต์เทรด cryptocurrency ชื่อดัง นามว่า Binance ใน feature นี้จะเป็นการซื้อขายหุ้นในสหรัฐอเมริกา โดยที่เราไม่ต้องไปมีบัญชีหุ้นที่โน้น และสามารถเข้าไปเทรดหุ้นได้เลย ผ่านเหรียญ BUSD (เหรียญ stable coin ของ Binance มีมูลค่าคํ้าประกันด้วยดอลลาร์สหรัฐในอัตราส่วน 1:1)

หุ้นตัวแรกที่ให้เราซื้อกันในนี้คือ TSLA (Tesla) นั่นเอง ตัวถัดมาก็คือ COIN (Coinbase) จากนั้นก็มี Microstrategy (MSTR), Apple (AAPL) และ Microsoft (MSFT) ตามลำดับ

ทั้ง 5 ตัวที่กล่าวมานี้ จะอยู่ใน NASDAQ (National Association of Securities Dealers Automated Quotations) หรือ ตลาดหุ้นแนสแด็ก เป็นตลาดหุ้นที่ใหญ่เป็นอันดับที่ 2 ในสหรัฐอเมริกา และบริษัทเทคโนโลยีชั้นนำต่างๆของโลก มักจะจดทะเบียนตลาดหลักทรัพย์ที่นี่

และหน่วยตํ่าสุดที่เราซื้อได้ก็คือ 0.01 นั่นเอง โดยระบบจะเอาเงิน BUSD ที่เราซื้อผ่านทางนี้ไปลงทุนให้ และได้ผลปันผลออกมาจ้า ในที่นี้เราไม่ได้เป็นผู้ถือหุ้นโดยตรงนะ

Stock Token | ซื้อขายหุ้นด้วยคริปโต | Binance.com
ตอนนี้ผู้ใช้ Binance สามารถซื้อหุ้นของบริษัทที่ซื้อขายในตลาดหลักทรัพย์ได้ด้วยบริการซื้อขาย Tokenized Stock แบบใหม่ โดยไม่มีค่าธรรมเนียมสำหรับธุรกรรม Stock Token
https://www.binance.com/th/stock-token

ความเสี่ยง เราให้เท่ากับตลาดหุ้น เนื่องจาก feature นี้กดซื้อได้ที่ราคา market เท่านั้น บวกกับเวลาคนละซีกโลกกัน ทำให้เราดอยไปแล้วทั้งสองตัวจ้า น่าจะรีบขายตัวที่ได้กำไรเนอะ ฮือออออออ แบบตลาดเปิดตอนเราจะนอนงี้

ส่วนตัวเหรียญ BUSD ไม่ได้เสี่ยงมากเท่าไหร่ เนื่องจากเป็น stable coin

การซื้อเหรียญนี้ ถ้าง่ายสุดคือซื้อผ่านระบบ P2P ใน Binance เอง หรือต้องซื้อจาก exchange ในไทยที่มีเหรียญนี้แล้วโอนเข้ามาก็ได้ โดยมีค่าธรรมเนียมการโอนอยู่ หรือซื้อเหรียญอื่นแล้วโอนเข้า Binance เพื่อเอาไปซื้อ BUSD ต่อก็ย่อมได้ แต่มันจะยากไปไหมนะนั่นสำหรับมือใหม่อ่ะ ... เอาเป็นว่ามันจะประมาณนี้แล้วกันเนอะ

แน่นอนว่าการซื้อหุ้นแบบ Stock Token นี้ จะต้องมีบัญชี Binance เสียก่อนนะ

สร้างบัญชีฟรี | Binance
ลงทะเบียนบัญชีกับ Binance วันนี้
https://www.binance.cc/th/register?ref=XRWJ0QZL

ซึ่งมันจะต่างจากตลาดหลักทรัพย์ปกติตรงที่ เราสามารถซื้อเป็นหน่วยย่อยได้โดยไม่จำเป็นต้องซื้อหน่วยเต็มงี้ ในโลกคริปโตมันทำได้ เพื่อให้เราเข้าถึงการถือหุ้นได้ง่ายขึ้นนั่นเอง

ใช้ Google Finance บน Google Sheet กันเถอะ

จากเมื่อกี้ เราจะสรุปได้ว่า หุ้นทั้ง 5 ตัว อยู่ในตลาด NASDAQ เนอะ

เราสามารถเข้าไปส่องใน Google Finance เพื่อดูก่อนได้เลยจ้า

เข้าไปดูได้ที่ https://www.google.com/finance/ โดยเราทำเป็น list แยกไว้อีกชั้นนึงเพื่อดูจ้า

เข้าไปดูสักหนึ่งตัว เช่น Tesla เราก็จะเห็น detail ของหุ้นนั้นๆ ไม่ว่าจะเป็นราคา ข่าว และ stat ต่างๆ

https://www.google.com/finance/quote/TSLA:NASDAQ

จากนั้นเปิด Google Sheet เราจะอ้างอิงตามคลิปพี่ต้าข้างบนบางส่วนเลยว่ามีอะไรบ้าง

syntax ของตัว GOOGLEFINANCE จะเป็นดังนี้

GOOGLEFINANCE(ticker, [attribute], [start_date], [end_date|num_days], [interval])

มาดูกันทีละตัวกันนะ

ตัวอย่างระหว่างพิมพ์จะประมาณนี้เนอะ
  • ticker : ชื่อหุ้น อันนี้จะบังคับใส่ทุกตัวเนอะ ซึ่งแน่นอนว่าจะต้องมีชื่อหุ้นเนอะ โดยจะ syntax ก็คือ {ตลาดหลักทรัพย์}:{ชื่อย่อหลักทรัพย์} นั่นเอง ลอกจากช่องที่เราค้นหาใน Google Finance ได้เลยยย
  • attribute : ค่าต่างๆที่เราอยากรู้เกี่ยวกับหุ้นนั้นๆ เช่น ราคาจะใช้ price ค่าอัตราส่วนราคาต่อกำไร จะใช้ pe ค่าการเปลี่ยนแปลงราคาตั้งแต่ปิดตลาดก่อนหน้าใช้ change ถ้าอยากได้เป็นเปอร์เซ็นต์คือ changepct นั่นเอง
  • start_date : วันเริ่มต้น
  • end_date : วันสิ้นสุด
  • interval : ความถี่ในการแสดงข้อมูล ถ้าใช้รายวันให้ระบุเป็น 1 ถ้าใช้รายสัปดาห์ให้ระบุเป็น 7 โดยใส่ได้แค่ 2 ค่านี้เท่านั้น

ตัวอย่างในแต่ละช่องใน Google Sheet ชุดนี้กันเถอะ

  • ราคาหุ้น : =GOOGLEFINANCE({ticker},"price")
  • ค่า PE หรือ ค่าอัตราส่วนราคาต่อกำไร : =GOOGLEFINANCE({ticker},"pe") ค่าสามารถเป็น N/A ได้ ถ้ามันติดลบงี้
  • ค่าการเปลี่ยนแปลงราคาตั้งแต่ปิดตลาดก่อนหน้า: =GOOGLEFINANCE({ticker},"change")
  • เปอร์เซ็นต์ของค่าการเปลี่ยนแปลงราคาตั้งแต่ปิดตลาดก่อนหน้า: =GOOGLEFINANCE({ticker},"changepct")

สามารถดูตัว document ของ GOOGLEFINANCE ได้ที่นี่เลยจ้า ซึ่งก็แล้วแต่เราว่าจะใช้สูตรสำนักไหนในการดูเนอะ

GOOGLEFINANCE - เครื่องมือแก้ไขเอกสาร ความช่วยเหลือ
เรียกข้อมูลหลักทรัพย์ในปัจจุบันหรือในอดีตจาก Google Financeตัวอย่างการใช้งาน
https://support.google.com/docs/answer/3093281/googlefinance?hl=th

Disclammer : คือเขาบอกว่า

ข้อมูลราคาไม่ได้มาจากทุกตลาด และอาจล่าช้าได้ถึง 20 นาที ข้อมูลนี้มีให้ "ตามสภาพ" และมีวัตถุประสงค์เพื่อแจ้งให้ทราบเท่านั้น ไม่ใช่เพื่อการซื้อขายหรือเสนอแนะ ข้อจำกัดความรับผิด

ก็คือมันไม่ได้มา realtime ทันทีนะ สามารถดูว่าแต่ละตลาด delay ไปเท่าไหร่ใน document นี้นะ

Disclaimer – Google Finance
https://www.google.com/googlefinance/disclaimer/

ถ้าเราอยากรู้ว่าตอนนี้มีการ delay ไปเท่าไหร่ : =GOOGLEFINANCE({ticker},"datadelay")

แล้วใช้กับราคาหุ้นไทยได้ไหมนะ?

ไม่ได้อ่ะ ลองแล้ว

ทั้งๆที่ใส่ตามนี้นะ

ถ้าเจอวิธีที่ทำได้บอกด้วยเน้อ (แต่ของตลาดหลักทรัพย์แห่งประเทศไทยเขาก็มี API แหละ ใช้อันนั้นน่าจะดีกว่า)

แล้วพวกราคาของ Cryptocurrency หล่ะ?

ใช้ได้ โดยมัน reference จาก coinbase มานั่นเอง แต่ในแต่ละกระดานของ exchange นั้นมีราคาซื้อขายไม่เท่ากัน ตามแต่คนซื้อขายในกระดานนั้นๆ และตัว syntax จะสั้นมากๆเลย คือ GOOGLEFINANCE({ชื่อเหรียญ}{สกุลเงิน})

เส้นกราฟหล่ะ?

เราจะใช้สิ่งที่เรียกว่า SPARKLINE ในการเพราะกราฟ โดย default จะเป็นกราฟเส้น ซึ่งก็เหมาะกับหุ้นเลยหล่ะ

syntax จะเป็นแบบนี้

SPARKLINE(ข้อมูล, [options])

syntax ของเขาจะประกอบด้วย 2 ส่วน คือ

  • ข้อมูล : เราจะเอาอะไรมาเพาะกราฟ อันนี้ต้องใส่เนอะ โดยเราจะเอาข้อมูล
  • options : การแสดงผลของกราฟ สามารถกราฟในรูปแบบต่างๆที่เราต้องการได้

สามารถอ่าน document ได้ที่นี่

SPARKLINE - เครื่องมือแก้ไขเอกสาร ความช่วยเหลือ
สร้างแผนภูมิขนาดเล็กในเซลล์เดี่ยวตัวอย่างการใช้งานSPARKLINE(A1:F1)SPARKLINE(A2:E2,{“charttype”
https://support.google.com/docs/answer/3093289/sparkline?hl=th

ในที่นี้เราจะแสดงกราฟของราคาหุ้น ในรอบ 1 วันแล้วกันเนอะ ก่อนหน้านี้เราอยากรู้ว่าแต่ละวันราคาหุ้นเป็นเท่าไหร่

=GOOGLEFINANCE({ticket}, "price", TODAY(), TODAY()-1)

มาดูข้อมูลข้างในกันก่อน โดยจะเลือกดูหุ้นของ Apple เนื่องจากเพิ่งซื้อใน Stock Token ไป แหะๆ เพราะดูแล้วราคาไม่ได้เปลี่ยนแปลงเยอะมาก (ถ้าอ่านกราฟเป็นจะดีมากๆเลยหล่ะ) และมีให้ดู 30 วันล่าสุด

แล้วถ้าเราเพาะกราฟ เราก็จะใช้คำสั่ง SPARKLINE ครอบข้อมูลชุดนี้นั่นเอง

=SPARKLINE(GOOGLEFINANCE({ticket}, "price", TODAY(), TODAY()-1))

ผลที่ได้จะได้กราฟมาแบบนี้

ถามว่าทำกับราคาคริปโตได้ไหม? ได้สิ ทำเหมือนกันเลย จะได้แบบนี้

แต่ด้วยตลาด cryptocurrency เป็นตลาดที่ไม่มีวันปิด ไม่เหมือนตลาดหุ้นที่มีเวลาเปิดปิด ดังนั้นจะได้ข้อมูลในทุกวัน และปิดที่เวลาจบวันนั่นเอง

ส่งข้อมูลใน Google Sheet ไปออกยัง LINE chatbot

ถามจีงงง ให้จะมาเปิด Google Sheet ตลอดเวลากันหล่ะ ไปจ้องกราฟในตลาดน่าจะดีกว่าไหม แต่เราจะใช้บอทเพื่อความสะดวกของเราเอง แหะๆ จะได้ลองทำบอทเชื่อมข้อมูลจาก Google Sheet ไปยัง LINE Bot ด้วยเนอะ

เราจะข้ามวิธีการสร้างบอทไปใน LINE OA ไปเนอะ

flow การทำงานจะเป็นประมาณนี้

เมื่อ user ถามบอท เราจะทำการนำเสนอข้อมูล 2 แบบ คือ ถ้า user พิมพ์คำว่า #stock_token ให้แสดงข้อมูลหุ้นทุกตัวออกมาเลยในรูปแบบ carousel ของ Flex Message และเมื่อถามเพราะหุ้นตัวนั้นๆ เช่น $TSLA หุ้น Tesla ให้แสดงข้อมูลตัวเดียวพอเป็น Flex Message

โดยเราจะใช้ webhook ที่ได้จากการสร้าง function ที่ exports มาจาก Firebase Cloud Function ไปใส่ใน LINE OA เพื่อเป็นการเชื่อมต่อ

บอทจะทำงานตาม condition ที่เราได้วางไว้ และทำการอ่านข้อมูลจาก Google Sheet ออกมาเพื่อส่งกลับออกไปให้ user

ออกแบบ Flex Message

ก่อนอื่น เราไปทำ UI การแสดงผลที่เป็น Flex Message ที่ LINE Bot Designer ก่อนเนอะ หน้าตาจะประมาณนี้

สำหรับทีมชาวบ้าน อาจจะอ่านจบแค่ตรงนี้ก็ได้แหละ เนื่องจากเนื้อหาต่อไปนี้ เป็นเนื้อหาการเขียนโปรแกรมที่มีพื้นฐานประมาณนึงแล้ว และจะไปแบบไวๆหน่อย แต่ทีมชาวบ้านสามารถออกแบบตัวหน้าตาข้อความตรงนี้ได้นะ แล้วเอาส่วน json ส่งให้ developer แล้ว define กันว่าตรงไหนอยากให้แสดงผลแบบไหน เพื่อความเข้าใจที่ตรงกันเนอะ

จากนั้นทำการดึงข้อมูลที่เราต้องการ จากใน Google Sheet กันเลย โดยเราจะไม่ใช้ inline editor ใน DialogFlow เนื่องจากเราต้องการใช้ Google Sheet API ในการดึงข้อมูลมาแสดงจ้า ตอนอ่าน document ก็เหวอเหมือนกัน แล้วฉันจะเพิ่มมันไปยังง้ายยย

ขั้นตอนการเตรียมของต่างๆ

ก่อนอื่นไปสร้างโปรเจก Firebase ก่อนนะ แล้วทำการ init project ให้เรียบร้อย~~

จากนั้นเพิ่ม Google Sheet API เข้ามาในโปรเจก โดยไปที่นี่เลย

Google Cloud Platform
Google Cloud Platform lets you build, deploy and scale applications, websites and services on the same infrastructure as Google.
https://console.developers.google.com/

เลือกชื่อโปรเจกที่เราสร้างมะกี้

แล้วทำการเพิ่ม Google Sheet API เข้ามาในโปรเจก โดยการเข้าไปค้นหา

เมื่อพบแล้ว กดปุ่ม enable เพื่อใช้งานมัน

พอ enable เสร็จปุ๊ปก็มีมาให้เราใช้เลยอ่ะ เอ้อมันดีย์

ก้อปปี้ชื่อ email ที่เป็น @{project_id}.iam.gserviceaccount.com

แล้วไปที่ Google Sheet ของเขา เอา email นี้เพิ่ม permission ของ Google Sheet ที่เราสร้างขึ้นมามะกี้ เป็น editor

จากนั้นทำการเตรียม sheet id เตรียมไว้ โดยดูจาก url ประมาณนี้

https://docs.google.com/spreadsheets/d/{sheet_id}/edit#gid=0

สามารถดูได้ตามนี้เลยจ้า

Google Sheets API Overview | Google Developers

ไปกันต่อที่ Firebase ไปที่ฟันเฟือง setting และไปที่ Service accounts เพื่อไป download key ที่เป็น json ลงมา ชื่อว่า service-account.json พร้อมเปลี่ยนชื่อไฟล์ เพื่อนำไปใช้ต่อไปจ้า

และสุดท้าย อย่าลืม import library ต่างๆเพิ่มเติมใน folder functions อันเป็นที่อยู่ของ Firebase Cloud Function นะเออ มีดังนี้

  • axios
  • firebase-admin
  • firebase-functions
  • googleapis

ทำการเขียนบอทเบื้องต้น

ในที่นี้จะเป็นการเขียน bot โดยจะเขียนบน Firebase Cloud Function เนอะ เนื่องจากบอทตัวนี้จะมีหลายๆฟังก์ชั่นด้วยกัน และการรวมไว้ใน inline editor อาจจะไม่สะดวกสักเท่าไหร่เนอะ

ก่อนอื่นเรามาเขียน echo bot กันก่อน

 .

  • เราจะต้องดักก่อนว่า message ที่ได้มานั้น มี type เป็น text ถึงจะทำงานต่อ เพราะถ้าเราไม่ได้ดักไว้ อาจจะมีข้อความ type อื่นเช่น sticker จะทำให้โค้ดที่เราเขียนนั้น crash ได้จ้า

โดยตัว request.body.event[0] ที่ได้ จะเป็นประมาณนี้ จากการทดลองรันใน Firebase Emulator นะ

  • เรานำข้อความที่ได้จากการที่ user พิมพ์เข้ามา ซึ่งก็คือ request.body.events[0].message.text ทำการส่งกลับให้เป็น echo bot ซะ
  • ทำการปั้นข้อความ แล้ว reply ส่งไปให้ user โดยจะส่ง replyToken ไปกับตัว json ที่เป็น message

ดึงไฟล์ Google Sheet มาเข้าบอทของเรา

เนื่องจากเราเองทำหลายรอบอยู่ในการจัดโค้ด ด้วยความที่เราจะให้บอทตัวนี้มีหลาย feature เลยจะทำการแยก function ออกมาให้เป็น modular architecture ให้มากที่สุด

ดังนั้นในตอนนี้ สร้างไฟล์ google_sheet.js ซึ่งเราจะให้มันอยู่ใน folder ที่ชื่อว่า service นั่นเอง

ก่อนอื่น ทำการ import Google Sheet เข้ามาในโปรเจกก่อน พร้อมกับ Google Sheet ID ที่ได้มาก่อนหน้านี้

const { google } = require("googleapis");
const sheets = google.sheets("v4");

const GOOGLE_SHEET_ID = "YOUR_GOOGLE_SHEET_ID";

ทำการนำเข้าไฟล์ service-account.json เข้ามา พร้อมทำการ create JWT เพื่อทำการ login เข้าไปอ่านเจ้า Google Sheet ด้านใน (ในส่วนนี้สามารถทำ Firebase Environment ทีหลังได้นะเออ เพราะไม่ควรอัพ key ขึ้น Github โดยตรง)

var serviceAccount = require("../service-account.json");
const jwtClient = new google.auth.JWT({
    email: serviceAccount.client_email,
    key: serviceAccount.private_key,
    scopes: ["https://www.googleapis.com/auth/spreadsheets"]
});

ต่อมาทำการอ่านไฟล์จาก Google Sheet ของเรากันเลยจ้า โดยสร้าง function ใหม่ขึ้นมา

  • ใส่ sheet id ให้เรียบร้อย
  • syntax ของ range คือ {sheet_name}!{start}:{end}
function stockToken() {
    sheets.spreadsheets.values.get({
      auth: jwtClient,
      spreadsheetId: GOOGLE_SHEET_ID,
      range: "stock token!A2:H6"
    }).then((response) => {
      var data = response.data.values;
      var length = data.length
      console.log(data);
      console.log(`${length} rows retrieved.`);
    });
}

ผลที่ได้ตัว data ของตัว sheet ออกมา โดยจะได้เป็นประมาณนี้

[
    [
        'NASDAQ:TSLA', 
        'Tesla Inc.',
        '656.57', 
        '661.65', 
        '32.8', 
        '5.27', 
        '', 
        '0'
    ],
    [
        'NASDAQ:COIN', 
        'Coinbase Global, Inc.', 
        '226.01', 
        '96.69', 
        '3.54', 
        '1.59', 
        '', 
        '0'
    ],
    [
        'NASDAQ:MSTR', 
        'MicroStrategy Incorporated..', 
        '553', 
        '#N/A', 
        '-0.72', 
        '-0.13, 
        '', 
        '0'
    ],
    [
        'NASDAQ:AAPL’, 
        'Apple Inc.', 
        '133.7', 
        '30', 
        '-0.28', 
        -0.21', 
        '', 
        '0'
    ],
    [
        'NASDAQ:MSFT', 
        'Microsoft Corporation', 
        '265.27', 
        '26.1', 
        '-0.24, 
        '-0.09', 
        '', 
        '0'
    ]
]

โดยมี length ทั้งหมดเป็น 5 นั่นเอง

สามารถอ่านเพิ่มเติมใน document ได้ดังนี้

Reading & Writing Cell Values | Sheets API | Google Developers
REST Resource: spreadsheets.values | Sheets API | Google Developers

เนื่องด้วยตัวเส้น sparkline ได้ออกมาเป็น string เปล่า จึงไม่สามารถนำมาแสดงในบอทของเราได้จ้า ;_; แต่มีปุ่มกดไป Google Finance แล้วน่าจะโอเคอยู่แหละ

ปั้นตัว Flex Message ขึ้นมา

ก่อนอื่นต้องทำความเข้าใจรูปแบบการนำ Flex Message ไปใช้ก่อนนะ

โดย format ที่ได้จาก LINE Bot Designer นั้น ถ้านำไปใส่ปั้นเป็น message เพื่อส่งออกทาง LINE จะมีหน้าตาตามนี้

จากนั้นสร้างไฟล์ line_template.js ไว้ใน folder ที่ชื่อว่า template เพราะอนาคาอาจจะมีของ Discord งี้ เพื่อสร้าง Flex Message และ Carousel Flex Message ตาม format ที่ถูกต้อง ดังนี้

.

output ที่เราต้องการ มี 2 แบบ คือ

  • ถ้า user พิมพ์คำว่า #stock_token จะให้แสดงหุ้นทั้งหมดขึ้นมาในรูปแบบของ Carousel Flex Message
  • ถ้า user อยากดูข้อมูลหุ้นตัวเดียว เช่น $AAPL ก็ให้แสดงเป็น Flex Message มาตัวเดียวพอ

เราจะเริ่มจากแบบที่แก้ไขได้ง่ายแล้วกันเนอะ ที่การแสดง Flex Message อันเดียวก่อน

สร้าง function ใหม่ใน stock_token.js ชื่อว่า setStockTokenFlexMessageJson เป็น function เอาไว้ปั้น Flex Message ออกมานั่นเอง

ก่อนอื่น เรามากำหนดสีกันก่อน ว่าจะให้แสดงสีเขียวแบบไหน สีแดงแบบไหน ซึ่งทางเราจิ้มจาก Color Tool ของทาง Material Design นั่นเอง โดยเราให้สีของ title จะมีความเข้มกว่าสีที่เป็น body เนอะ

function setStockTokenFlexMessageJson(stock) {
  //color code
  const greenTextTitle = "#00701a";
  const greenTextBody = "#43a047";
    
  const redTextTitle = "#ab000d";
  const redTextBody = "#e53935";
}

โดย stock คือข้อมูลในแต่ละแถว ของหุ้นนั้นๆ เอามาปั้นเป็น Flex Message นั่นเอง

ตัดกลับไปที่ Google Sheet หวังว่าเราจะจำได้อยู่เนอะ ว่าแต่ละช่อง คือค่าอะไรบ้างนะ ซึ่ง stock เป็น array เนอะ ดังนั้นสร้างตัวแปรให้สอดคล้องกันกับแถวของ Google Sheet

function setStockTokenFlexMessageJson(stock) {
  //color code
  
  //stock data
  const stockId = stock[0];
  const stockName = stock[1];
  const stockPrice = stock[2];
  const stockPe = stock[3];
  const stockChange = stock[4];
  const stockChangepct = stock[5];
  const stockButtonUrl = `https://www.google.com/finance/quote/${stockId.split(":")[1]}:${stockId.split(":")[0]}`;
}

ในส่วนของ stockButtonUrl นั้น คือ url ของ Google Finance นั่นเอง เพื่อสามารถดูกราฟหรืออะไรต่างๆเกี่ยวกับหุ้นตัวนั้นต่อไปได้นั่นเอง

ขั้นตอนต่อมาคือการแสดงสีของราคาในปัจจุบัน และการเปลี่ยนแปลงของราคา โดยราคาบวกเป็นสีเขียว ราคาลบเป็นสีแดง ตามปกติทั่วไปเลย

function setStockTokenFlexMessageJson(stock) {
  //color code
  
  //stock data
  
  //condition for text color in Flex Message
  if (stockChange > 0) {
    stockTextTitleColor = greenTextTitle;
  } else {
    stockTextTitleColor = redTextTitle;
  }
    
  if (stockChange > 0) {
    stockTextBodyColor = greenTextBody;
  } else {
    stockTextBodyColor = redTextBody;
  }
}

จากนั้นทำการ return Flex Message ออกมาเป็น json ซึ่งโค้ดมันยาวตรงนี้แหละ ค่อยๆส่องกันแล้วกันเนอะ

.

สร้าง function ใหม่ที่ชื่อว่า setFlexMessageForStockToken เพื่อทำการนำมาเข้า format ของ Flex Message ในการส่งออกให้ถูกต้องนั่นเอง

โดยเราจะใช้ flexMessageTemplate จากใน line_template.js มาช่วยประกอบร่าง ซึ่ง parameter ตัวแรกก็คือ altText และตัวต่อมาก็คือ json ของ Flex Message ที่เราโยน data ของหุ้นแต่ละตัว ที่ได้จาก Google Sheet จาก function setStockTokenFlexMessageJson

function setFlexMessageForStockToken(stock) {
  return lineTemplate.flexMessageTemplate(
    `Stock Token : ${stock[0].split(":")[1]}`, 
    setStockTokenFlexMessageJson(stock)
  );
}

สุดท้าย อย่าลืม module.exports ออกไปด้วยนะ เพื่อนำไปใช้ใน module อื่นๆต่อไป

module.exports = { 
  setStockTokenFlexMessageJson,
  setFlexMessageForStockToken 
};

ทำการประกอบร่างกับ Flex Message

เมื่อเราทำการผลิต Flex Message มาแล้ว เราจะต้องนำมาเชื่อมกับข้อมูลที่ได้จาก Google Sheet เพื่อนำไปแสดงผลในบอทของเรานั่นเอง

กลับมาที่ google_sheet.js ทำการ import module กันก่อน

// Firebase Cloud Function
const functions = require("firebase-functions");

// import module
const utils = require("./utils");
const lineTemplate = require("../templates/line_template");
const stockToken = require("./stock_token");

ต่อมา เปลี่ยนชื่อ function ที่สร้างตอนแรกไว้นามว่า stockToken ให้เป็น stockTokenFlexMessage โดยรับ replyToken เพื่อส่งข้อความออกไป และ name ชื่อหุ้น เข้ามาค้นหาใน Google Sheet นั่นเอง

จากนั้นนำเอา data มาวน loop เพื่อหาว่าชื่อหุ้นนี้ตรงกับแถวนี้ไหม ถ้าตรงให้ปั้น Flex Message แล้วทำการส่งข้อความออกไปนะ

function stockTokenFlexMessage(replyToken, name) {
  return sheets.spreadsheets.values.get({
    auth: jwtClient,
    spreadsheetId: googleSheetId,
    range: "stock token!A2:H6"
  }).then((response) => {
    const data = response.data.values;

    return data.forEach(stock => {
      const stockIdName = stock[0].split(":")[1].toLowerCase();
      if (stockIdName === name) {
        utils.reply(
          replyToken,
          stockToken.setFlexMessageForStockToken(stock)
        )
      }
    });
  });
}

และสร้าง function ใหม่ที่ชื่อว่า stockTokenCarousel เพื่อแสดงข้อมูลหุ้นทั้งหมดออกมา โดยเอาข้อมูลในแต่ละแถวที่ได้มาวนลูป เพื่อสร้าง Flex Message ที่เป็น json ออกมา แล้วนำมาใส่ใน array ตัวนึง เมื่อวนลูปครบแล้วให้ทำการส่งข้อความออกไป เป็นแบบ carousel นั่นเอง

function stockTokenCarousel(replyToken) {
  return sheets.spreadsheets.values.get({
    auth: jwtClient,
    spreadsheetId: googleSheetId,
    range: "stock token!A2:H6"
  }).then((response) => {
    var data = response.data.values;

    var allStockTokenFlexMessage = [];
      data.forEach(stock => {
        const flexMessageResult = stockToken.setStockTokenFlexMessageJson(stock);
        allStockTokenFlexMessage.push(flexMessageResult);
      }
    );

    return utils.reply(
      replyToken,
      lineTemplate.carouselTemplate("Stock Token price", allStockTokenFlexMessage)
      );
  });
}

และสุดท้าย อย่าลืม export ออกมาด้วย เราจะใช้ใน index.js ในตอนสุดท้าย

module.exports = { stockTokenCarousel, stockTokenFlexMessage };

การนำไปใช้จริงในบอทของเรา

กลับมาที่ index.js ทำการ import module กันก่อน

// import module
const googleSheet = require("./services/google_sheet");
const utils = require("./services/utils");

อันนี้อาจจะไม่ใช่วิธีที่ดีที่สุดเนอะ แต่คิดว่าพอดัก condition ได้อยู่ ที่แปลว่าได้นะ 555

มาดูโค้ดทั้งหมด เดี๋ยวจะค่อยๆอธิบายให้ฟัง

.

ก็คือก่อนหน้านี้เราดัก message type เป็น text ไป แล้วเราดัก text ที่ได้ว่า user เขาพิมพ์ว่าอะไร ถ้าเป็น #stock_token ให้แสดงหุ้นทุกตัวออกมาเนอะ โดยให้เข้าไปทำ googleSheet.stockTokenCarousel(request.body.events[0].replyToken);

แต่ถ้าพิมพ์ $ แล้วตามด้วยชื่อหุ้น เราก็จะให้พิมพ์ $ แล้วตามด้วยชื่อเหรียญด้วยเช่นกัน (อันนี้เราอิงตามใน Twitter แหละ)

ดังนั้นเราจะต้องทำการแยกว่ามันคือหุ้นหรือเหรียญกันแน่นะ ถ้าเป็นหุ้น ให้เอาชื่อหุ้นไปหาแล้วแสดง Flex Message ออกมา ถ้าเป็นชื่อเหรียญบอกว่าไม่มีข้อมูลไปก่อน เพราะยังไม่ได้ทำ แฮร่~~

แล้วเราจะแยกชื่อหุ้นออกยังไง? อันนี้อาจจะมีวิธีที่ดีกว่านี้แหละเนอะ คือสร้าง array ชื่อหุ้นขึ้นมา

const stockTokenList = ['tsla', 'coin', 'mstr', 'aapl', 'msft'];

แล้วมา check ก่อนว่ามีตรงตามนี้ไหม?

const foundStockToken = stockTokenList.find(stockToken => stockToken === name);

ถ้าตรงกัน มันจะได้เป็น type String ออกมา โดย typeof foundStockToken === "string" จะเป็น true จากนั้นไปทำ Flex Message ต่อได้เลย

googleSheet.stockTokenFlexMessage(request.body.events[0].replyToken, name);

ถ้าไม่มีจะเป็น type ที่เป็น undefined เนอะ ดังนั้นในตอนนี้ให้ส่ง text message ว่ายังไม่มีข้อมูลไปก่อน เพราะในส่วนนี้เราจะมาทำการแสดงราคาเหรียญคริปโตต่างๆใน content ถัดไปนั่นเอง

utils.reply(
    request.body.events[0].replyToken,
    { type: "text", text: `not have data for ${textMessage}` }
)

ตอน deploy จริง ให้เลือกที่ใกล้ที่สุดตามใน tier1 นี้นะ เนื่องจากลอง tier 2 แล้วไม่ได้แหะ อันนี้ยังไม่ได้ตามต่อว่าทำไม

https://firebase.google.com/docs/functions/locations

ก็เลยเลือก asia-east2 เพราะฮ่องกงน่าจะใกล้ไทยสุดหล่ะ

เสร็จแล้วอย่าลืมใช้ Firebase Environment

ทำไมต้องทำ? เพราะเราต้องการ secure key ต่างๆที่ใช้ในโปรเจกเรา ดังนั้นเราจะต้อง set key ต่างๆเป็น environment variable นั่นเอง

วิธีการทำก็ตามนี้เลย แต่ไม่มีแบบให้แก้เป็น UI อ่ะ สมมุติว่าใส่ผิดงี้ เราต้องพิมพ์ key นั้นใหม่เลย

Environment configuration | Firebase

โค้ดเต็มสามารถเข้าไปดูใน branch นี้ได้เลยจ้า

mikkipastel/coinboi
Contribute to mikkipastel/coinboi development by creating an account on GitHub.
https://github.com/mikkipastel/coinboi/tree/feature/stock_token

demo ให้ดูนิดนึงว่าการใช้งานเป็นยังไง ถ้าดึงข้อมูลทุกตัวมันก็จะช้าๆหน่อยหน่ะ และในตอนนี้ยังไม่มี Rich Menu ดังนั้นขอทำ feature อื่นๆก่อน แล้วจะค่อยปล่อยมาให้เล่นกันน้า

https://www.youtube.com/watch?v=Z_Wc09EfcFM

Reference

ในส่วนการดึง Google Sheet API มาใช้พร้อมเชื่อมต่อ

Sync ข้อมูลระหว่าง Firebase Realtime Database กับ Google Sheets ง่ายนิดเดียว
ถ้าคุณเป็นนักพัฒนาที่เห็นโอกาสในเทคโนโลยีของ Cloud และกำลังคุยกับทางองค์กรเพื่อให้หันมาใช้มัน โดยเฉพาะองค์กรที่เป็น Traditional…

การทดสอบใน localhost

เผยวิธีพัฒนา LINE Chatbot ด้วย Cloud Functions for Firebase แบบไม่ต้อง Deploy
Pain point หนึ่งในการพัฒนา LINE Chatbot ด้วย Cloud Functions for Firebase ก็คือการ Deploy เพราะแต่ละครั้งจะต้องใช้เวลาประมาณ 40–60 วินาที

อันนี้อ่านขั้นตอนแรกพอ

Node.js quickstart | Sheets API | Google Developers

โค้ดพี่ตี๋ช่วยหนูได้เยอะเลย

linedevth/LINE-Bot-101-Cloud-Functions-for-Firebase
Code sample for creating LINE Bot by Messaging API and Cloud Functions for Firebase - linedevth/LINE-Bot-101-Cloud-Functions-for-Firebase

carousel ของ Flex message ที่ถูกต้อง งมหานานมาก กว่าจะเจอ format ที่ถูกต้อง

https://www.ninenik.com/forum_view_3105_1.html

เป็นบล็อกที่ทำยาวนานมากเป็นเดือนๆ และตอนนี้บล็อกจบแล้ว เย้ๆ

download แอพอ่านบล็อกใหม่ของเราได้ที่นี่

MikkiPastel - Apps on Google Play
First application from “MikkiPastel” on play store beta feature- read blog from https://www.mikkipastel.com by this application- read blog content by chrome custom tab- update or refresh new content by pull to refresh- share content to social network
https://play.google.com/store/apps/details?id=com.mikkipastel.blog

ติดตามข่าวสารและบทความใหม่ๆได้ที่

อย่าลืมกด like กด share บทความกันด้วยนะคะ :)

Posted by MikkiPastel on Sunday, 10 December 2017

ช่องทางใหม่ใน Twiter จ้า

และ YouTube ช่องใหม่จ้า

mikkicoding
Android Developer & Content Creator
https://www.youtube.com/channel/UCtGbMSe4i7NJiKQ271Fezcg

Tags

Minseo Chayabanjonglerd

I am a full-time Android Developer and part-time contributor with developer community and web3 world, who believe people have hard skills and soft skills to up-skill to da moon.