From cff1eaac49071a23f5b12cf4ea1faf15f9297429 Mon Sep 17 00:00:00 2001 From: JianMiau Date: Tue, 10 Jan 2023 12:01:05 +0800 Subject: [PATCH] [add] first --- .gitignore | 6 ++ JoinClass.js | 27 ++++++++ LineNotifyClass.js | 35 ++++++++++ MemberJoinedClass.js | 38 +++++++++++ MessageClass.js | 152 +++++++++++++++++++++++++++++++++++++++++++ README.md | 1 + ToolsClass.js | 10 +++ app.js | 87 +++++++++++++++++++++++++ package.json | 23 +++++++ 9 files changed, 379 insertions(+) create mode 100644 .gitignore create mode 100644 JoinClass.js create mode 100644 LineNotifyClass.js create mode 100644 MemberJoinedClass.js create mode 100644 MessageClass.js create mode 100644 README.md create mode 100644 ToolsClass.js create mode 100644 app.js create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84a9f86 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +node_modules +.env +package-lock.json +*.pem +.foreverignore +.vscode \ No newline at end of file diff --git a/JoinClass.js b/JoinClass.js new file mode 100644 index 0000000..f168536 --- /dev/null +++ b/JoinClass.js @@ -0,0 +1,27 @@ +/** Join */ +class JoinClass { + constructor(bot, LineNotify) { + this.bot = bot; + this.LineNotify = LineNotify; + } + + Join(event) { + // switch (event.message.type) { + // case 'text': { + // this.Text(event); + // break; + // } + + // case 'sticker': { + // this.Sticker(event); + // break; + // } + + // default: + // break; + // } + console.log(`[Join] ${JSON.stringify(event)}`); + } +} + +module.exports = JoinClass \ No newline at end of file diff --git a/LineNotifyClass.js b/LineNotifyClass.js new file mode 100644 index 0000000..1c56cae --- /dev/null +++ b/LineNotifyClass.js @@ -0,0 +1,35 @@ +const XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest; + +/** LineNotify */ +class LineNotifyClass { + Send(message) { + const data = `message=\n${message}`; + + const xhr = new XMLHttpRequest(); + + xhr.addEventListener("readystatechange", function () { + if (this.readyState === 4) { + // console.log(this.responseText); + } + }); + + xhr.open("POST", "https://notify-api.line.me/api/notify"); + xhr.setRequestHeader("Authorization", "Bearer Dkv8Yh1Li3XsKFqZkmFMNP5o0JDSvan7qfcDmSv9GJr"); + xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + + xhr.send(data); + } + + SendBadmintonNotify() { + const xhr = new XMLHttpRequest(); + xhr.addEventListener("readystatechange", function () { + if (this.readyState === 4) { + // console.log(this.responseText); + } + }); + xhr.open("POST", "http://jianmiau.tk:1880/BadmintonNotify"); + xhr.send(); + } +} + +module.exports = LineNotifyClass \ No newline at end of file diff --git a/MemberJoinedClass.js b/MemberJoinedClass.js new file mode 100644 index 0000000..18f214d --- /dev/null +++ b/MemberJoinedClass.js @@ -0,0 +1,38 @@ +/** MemberJoined */ +class MemberJoinedClass { + constructor(bot, LineNotify) { + this.bot = bot; + this.LineNotify = LineNotify; + } + + MemberJoined(event) { + switch (event.source.groupId) { + case process.env.toBadminton: { + this.Badminton_MemberJoin(event) + break; + } + + default: + break; + } + } + + async Badminton_MemberJoin(event) { + const members = event.joined.members; + for (let i = 0; i < members.length; i++) { + const userId = members[i].userId; + this.SendBadminton_Welcome(event, event.source.groupId, userId) + } + } + + async SendBadminton_Welcome(event, groupId, userId) { + const userdata = await this.bot.getGroupMemberProfile(groupId, userId); + if (userdata && userdata.displayName) { + const message = `歡迎尊貴的 ${userdata.displayName} 降臨羽球團`; + event.reply(message); + this.LineNotify.SendBadmintonNotify(); + } + } +} + +module.exports = MemberJoinedClass \ No newline at end of file diff --git a/MessageClass.js b/MessageClass.js new file mode 100644 index 0000000..007503a --- /dev/null +++ b/MessageClass.js @@ -0,0 +1,152 @@ +/** Message */ +class MessageClass { + constructor(bot, ZhuHanbot, LineNotify) { + this.bot = bot; + this.ZhuHanbot = ZhuHanbot; + this.LineNotify = LineNotify; + } + + Message(event) { + switch (event.message.type) { + case 'text': { + this.Text(event); + break; + } + + case 'sticker': { + this.Sticker(event); + break; + } + + default: + break; + } + } + + Text(event) { + switch (event.source.type) { + case "user": { + this.User(event); + break; + } + + case "group": { + this.Group(event); + break; + } + + default: + break; + } + } + + async Sticker(event) { + switch (event.source.type) { + case "user": { + let userId = event.source.userId; + let displayName = ""; + let profile = await this.bot.getUserProfile(userId); + if (profile) { + displayName = profile.displayName; + } + let replyMsg = `https://liff.line.me/1657715144-m4W6lyjL?type=sticker&stk=noanim&sid=${event.message.stickerId}&pkg=${event.message.packageId}`; + let res_reply = event.reply(replyMsg).then(function (data) { + // 當訊息成功回傳後的處理 + }).catch(function (error) { + // 當訊息回傳失敗後的處理 + }); + break; + } + + case "group": { + break; + } + + default: + break; + } + } + + async User(event) { + let userId = event.source.userId; + let replyMsg = event.message.text; + let displayName = ""; + let profile = await this.bot.getUserProfile(userId); + if (profile) { + displayName = profile.displayName; + } + // JianMiau特別功能 + if (userId === process.env.toJianMiau || userId === process.env.toZhuHan) { + /** 訊息 */ + let Msg = event.message.text.split(" "); + + /** 指令 */ + let Instruction = Msg[0]; + switch (Instruction) { + case "msg": + case "Msg": + case "MSG": { + if (userId == process.env.toJianMiau) { + replyMsg = ""; + if (Msg[1] === "豬涵") { + if (Msg[2] === "豬涵") { + Msg[2] = process.env.toZhuHantoZhuHan; + } else if (Msg[2] === "建喵") { + Msg[2] = process.env.toZhuHantoJianMiau; + } + for (let i = 3; i < Msg.length; i++) { + replyMsg += Msg[i] + (i === Msg.length - 1 ? "" : " "); + } + let res_Msg = this.ZhuHanbot.push(Msg[2], replyMsg); + } else { + for (let i = 3; i < Msg.length; i++) { + replyMsg += Msg[i] + (i === Msg.length - 1 ? "" : " "); + } + let res_Msg = this.bot.push(Msg[2], replyMsg); + } + + let ToJM_message = "已發送訊息:"; + ToJM_message += `\nMyId: ${Msg[1]}`; + ToJM_message += `\nuserId: ${Msg[2]}`; + ToJM_message += `\nmessage: ${replyMsg}`; + let res_reply = event.reply(ToJM_message).then(function (data) { + // 當訊息成功回傳後的處理 + }).catch(function (error) { + // 當訊息回傳失敗後的處理 + }); + } + break; + } + + default: { + // 使用event.reply(要回傳的訊息)方法可將訊息回傳給使用者 + event.reply(replyMsg).then(function (data) { + // 當訊息成功回傳後的處理 + }).catch(function (error) { + // 當訊息回傳失敗後的處理 + }); + break; + } + } + } + } + + Group(event) { + switch (event.source.groupId) { + case process.env.toYoutube: { + let messagereplace = event.message.text; + messagereplace.replace("【IFTTT】 \n", ""); + let replyMsg = messagereplace; + // let res_toOusen = this.bot.push(process.env.toOusen, replyMsg); + let res_toUniversity = this.bot.push(process.env.toUniversity, replyMsg); + let res_toApex = this.bot.push(process.env.toApex, replyMsg); + break; + } + + default: + break; + } + } +} + +module.exports = MessageClass \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..efa7b4a --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# line-bot-js \ No newline at end of file diff --git a/ToolsClass.js b/ToolsClass.js new file mode 100644 index 0000000..248d1c3 --- /dev/null +++ b/ToolsClass.js @@ -0,0 +1,10 @@ +const XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest; + +/** Tools */ +class ToolsClass { + static Sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); + } +} + +module.exports = ToolsClass \ No newline at end of file diff --git a/app.js b/app.js new file mode 100644 index 0000000..46734f0 --- /dev/null +++ b/app.js @@ -0,0 +1,87 @@ +// 背景執行 forever start -a -l line-bot-js.log app.js +// 重新背景執行 forever restart -a -l line-bot-js.log app.js +// 監聽檔案變化 nodemon "npm start" +// Debug nodemon --inspect=192.168.1.15:9229 app.js + +require('dotenv').config() +const dateFormat = require('dateformat'); +// 引用linebot SDK +var linebot = require('linebot'); +const fs = require('fs'); +const express = require('express'); +const app = express(); + +//讀取憑證及金鑰 +const prikey = fs.readFileSync('../certificate/RSA-privkey.pem', 'utf8'); +const cert = fs.readFileSync('../certificate/RSA-cert.pem', 'utf8'); +const cafile = fs.readFileSync('../certificate/RSA-chain.pem', 'utf-8'); + +//建立憑證及金鑰 +const credentials = { + key: prikey, + cert: cert, + ca: cafile +}; + +// 用於辨識Line Channel的資訊 +var bot = linebot({ + channelId: process.env.toJianMiau, + channelSecret: process.env.channelSecret, + channelAccessToken: process.env.channelAccessToken +}); +var ZhuHanbot = linebot({ + channelId: process.env.toZhuHantoJianMiau, + channelSecret: process.env.ZhuHanchannelSecret, + channelAccessToken: process.env.ZhuHanchannelAccessToken +}); + +const LineNotifyClass = require('./LineNotifyClass') +const MessageClass = require('./MessageClass') +const JoinClass = require('./JoinClass') +const MemberJoinedClass = require('./MemberJoinedClass') +const LineNotify = new LineNotifyClass(); +const Message = new MessageClass(bot, ZhuHanbot, LineNotify); +const Join = new JoinClass(bot, LineNotify); +const MemberJoined = new MemberJoinedClass(bot, LineNotify); + +// 當有人傳送訊息給Bot時 +bot.on('event', function (event) { + try { + switch (event.type) { + case 'message': { + Message.Message(event); + break; + } + + case 'join': { + Join.Join(event); + break; + } + + case 'leave': + case 'follow': + case 'unfollow': + case 'memberJoined': { + MemberJoined.MemberJoined(event); + break; + } + + case 'memberLeave': + case 'postback': + case 'accountLink': + case 'fallback': + default: + break; + } + } catch (error) { + console.error(error); + } +}); + +// Bot所監聽的webhook路徑與port +const port = process.env.PORT || 3000; +bot.listen('/linewebhook', port, credentials, function () { + let datetime = dateFormat(new Date(), "yyyy-mm-dd HH:MM:ss"); + console.log(`${datetime} listening on ${port}`); + console.log(`${datetime} [BOT已準備就緒]`); +}); \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..a81ecb5 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "line-bot-js", + "version": "1.0.0", + "description": "", + "main": "app.js", + "dependencies": { + "dateformat": "^4.5.1", + "dotenv": "^8.2.0", + "express": "^4.17.1", + "linebot": "^1.6.1", + "xmlhttprequest": "^1.8.0" + }, + "devDependencies": { + "nodemon": "^2.0.7" + }, + "scripts": { + "start": "forever start -a -l line-bot-js.log app.js", + "dev": "nodemon --inspect=192.168.1.15:9229 app.js" + }, + "keywords": [], + "author": "", + "license": "ISC" +}