Last active
June 2, 2021 02:12
-
-
Save tandevmode/0ce6e7f274e2468194cd0c58b9a122ba to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const functions = require('firebase-functions') | |
// สำหรับการเข้าถึง Cloud Storage | |
const admin = require("firebase-admin"); | |
admin.initializeApp(); | |
// สำหรับ network requests | |
const axios = require('axios'); | |
// สำหรับสร้าง public url ใน Cloud Storage | |
const UUID = require("uuid-v4"); | |
// สำหรับจัดการไฟล์ | |
const path = require("path"); | |
const os = require("os"); | |
const fs = require("fs"); | |
const LINE_MESSAGING_API = "https://api.line.me/v2/bot"; | |
const LINE_CONTENT_API = "https://api-data.line.me/v2/bot/message"; | |
const UNSPLASH_API = "https://source.unsplash.com/1600x900/?"; | |
const REMOVE_BG_API = "https://api.remove.bg/v1.0/removebg"; | |
// เมืองท่องเที่ยวชื่อดังที่เราอยากจะไปเที่ยวทิพย์ | |
const CITIES = ["Paris", "London", "Newyork", "Tokyo", "Osaka", "Seoul", "Taipei", "Bangkok"] | |
const LINE_HEADER = { | |
"Content-Type": "application/json", | |
"Authorization": "Bearer xxxxx" | |
}; | |
exports.LineWebhook = functions.region("asia-northeast1").https.onRequest(async (req, res) => { | |
const event = req.body.events[0]; | |
if (event.type === 'message' && event.message.type === 'image') { | |
const city = randomItem(CITIES); | |
const url = await uploadAndProcessImg(event, city); | |
await reply(event.replyToken, city, { | |
type: "image", | |
originalContentUrl: url, | |
previewImageUrl: url | |
}); | |
} | |
return res.end(); | |
}); | |
function randomItem(items) { | |
return items[Math.floor(Math.random() * items.length)]; | |
} | |
const uploadAndProcessImg = async (event, city) => { | |
// ดึงรูปของผู้ใช้ที่ส่งมาจาก LINE | |
const url = `${LINE_CONTENT_API}/${event.message.id}/content`; | |
const originalImage = await axios({ | |
method: "get", | |
headers: LINE_HEADER, | |
url: url, | |
responseType: "arraybuffer" | |
}); | |
// เซฟรูปผู้ใช้ลงเครื่องและทำการอัพโหลดไว้ที่ Cloud Storage | |
const filename = event.timestamp; | |
const originalLocalFile = path.join(os.tmpdir(), filename + ".jpg"); | |
fs.writeFileSync(originalLocalFile, originalImage.data); | |
const originalImageUrl = await uploadImage(event, originalLocalFile, filename + ".jpg"); | |
// ดึงรูปสถานที่เที่ยวจาก Unsplash | |
const backgroundImage = await axios({ | |
method: "get", | |
url: UNSPLASH_API + city + ",landscape", | |
responseType: "arraybuffer" | |
}); | |
// เซฟรูปสถานที่เที่ยวลงเครื่องและทำการอัพโหลดไว้ที่ Cloud Storage | |
const backgroundLocalFile = path.join(os.tmpdir(), filename + "-bg.jpg"); | |
fs.writeFileSync(backgroundLocalFile, backgroundImage.data); | |
const backgroundImageUrl = await uploadImage(event, backgroundLocalFile, filename + "-bg.jpg"); | |
// เรียกใช้ Remove bg API โดยส่งรูปของผู้ใช้กับสถานที่เที่ยว | |
const result = await axios({ | |
method: "post", | |
headers: { | |
"accept": "application/json", | |
"Content-Type": "application/json", | |
"X-API-Key": "your-removebg-api-key" | |
}, | |
url: REMOVE_BG_API, | |
data: JSON.stringify({ | |
size: "preview", | |
image_file: "", | |
semitransparency: "true", | |
position: "original", | |
bg_color: "", | |
scale: "original", | |
image_url: originalImageUrl, | |
roi: "0% 0% 100% 100%", | |
crop: "false", | |
channels: "rgba", | |
bg_image_url: backgroundImageUrl, | |
format: "auto", | |
type: "auto", | |
crop_margin: "0", | |
add_shadow: "false", | |
type_level: 1 | |
}) | |
}); | |
// ได้ผลลัพธ์กลับมาเป็น base64 ต้องสร้าง buffer จาก base64 | |
const bufferResult = Buffer.from(result.data.data.result_b64, "base64"); | |
// เซฟรูปที่ได้จาก Remove bg ลงเครื่องและทำการอัพโหลดไว้ที่ Cloud Storage | |
const resultLocalFile = path.join(os.tmpdir(), filename + "-result.jpg"); | |
fs.writeFileSync(resultLocalFile, bufferResult); | |
const resultImageUrl = await uploadImage(event, resultLocalFile, filename + "-result.jpg"); | |
// ลบไฟล์ temp เมื่ออัพโหลดเรียบร้อย | |
fs.unlinkSync(originalLocalFile); | |
fs.unlinkSync(backgroundLocalFile); | |
fs.unlinkSync(resultLocalFile); | |
return resultImageUrl; | |
}; | |
const uploadImage = async (event, imgLocalFile, filename) => { | |
const uuid = UUID(); | |
const bucket = admin.storage().bucket(); | |
const file = await bucket.upload(imgLocalFile, { | |
// กำหนด path ในการเก็บไฟล์แยกเป็นแต่ละ userId | |
destination: `photos/${event.source.userId}/${filename}`, | |
metadata: { | |
cacheControl: 'no-cache', | |
metadata: { | |
firebaseStorageDownloadTokens: uuid | |
} | |
} | |
}); | |
const prefix = `https://firebasestorage.googleapis.com/v0/b/${bucket.name}/o`; | |
const suffix = `alt=media&token=${uuid}`; | |
// ส่งคืนค่า public url ของรูปออกไป | |
return `${prefix}/${encodeURIComponent(file[0].name)}?${suffix}`; | |
}; | |
const reply = async (replyToken, city, payload) => { | |
axios({ | |
method: "post", | |
url: `${LINE_MESSAGING_API}/message/reply`, | |
headers: LINE_HEADER, | |
data: JSON.stringify({ | |
replyToken: replyToken, | |
messages: [{ | |
type: "text", | |
text: "#เที่ยวทิพย์ Let's go to " + city | |
}, payload] | |
}) | |
}); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment