Skip to content

Instantly share code, notes, and snippets.

@tandevmode
Last active June 2, 2021 02:12
Show Gist options
  • Save tandevmode/0ce6e7f274e2468194cd0c58b9a122ba to your computer and use it in GitHub Desktop.
Save tandevmode/0ce6e7f274e2468194cd0c58b9a122ba to your computer and use it in GitHub Desktop.
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