유명현

Merge branch 'feature/line-bot-v3' into 'main'

Feature/line bot v3

다음과 같은 기능이 구현되었습니다.
- DB에 유저-키워드 등록
- node-schedule을 이용해 1시간에 한번, 등록된 매물을 유저에게 carousel message로 알림

See merge request !19
......@@ -10,12 +10,6 @@ sequelize
.sync({ force: false })
.then(() => {
console.log("database connection complete");
database.addKeyword("rtx3060", "junseok");
database.getKeywordsByUserId("junseok");
database.deleteKeyword("phobyjun", "rtx3080");
database.getAllUsers();
database.getUsersByKeyword("rtx3060");
database.getAllKeywords();
})
.catch((err) => {
console.log("database connection failed");
......
const { marketMultiSearch } = require("../search/marketSearch");
const setCarouselMessage = require("../message/setCarouselMessage");
// Database APIs
const db = require("../../apis/database");
// API List
// database.addKeyword = async function(keyword, userId)
// database.deleteKeyword = async function(userId, keyword)
// database.getKeywordsByUserId = async function(userId)
// database.getUsersByKeyword = async function(keyword)
// database.getAllUsers = async function()
// database.getAllKeywords = async function()
const checkMamul = (client) => {
db.getAllKeywords().then((keywords) => {
for (let i = 0, pending = Promise.resolve(); i < keywords.length; i++) {
pending = db.getUsersByKeyword(keywords[i]).then((userIds) => {
marketMultiSearch(keywords[i]).then((res) => {
client.multicast(userIds, [setCarouselMessage(res)]);
});
});
}
});
};
module.exports = { checkMamul };
// Line chatbot + Message generate functions
const line = require("@line/bot-sdk");
const setFlexMessage = require("./message/setFlexMessage");
const setCarouselMessage = require("./message/setCarouselMessage");
const fs = require("fs");
// Market Search
const { daangnSingleSearch } = require("./search/daangnSearch");
const { daangnMultiSearch } = require("./search/daangnSearch");
const { joongnaSingleSearch } = require("./search/joongnaSearch");
......@@ -10,12 +12,36 @@ const { bunjangSingleSearch } = require("./search/bunjangSearch");
const { bunjangMultiSearch } = require("./search/bunjangSearch");
const { marketMultiSearch } = require("./search/marketSearch");
// File search - Will be deleted (Unused)
const fs = require("fs");
// Cron for Mamul Notification
const schedule = require("node-schedule");
const job = schedule.scheduleJob("0 */1 * * *", () => {
checkMamul(client);
});
// Database APIs
const db = require("../apis/database");
// API List
// database.addKeyword = async function(keyword, userId)
// database.deleteKeyword = async function(userId, keyword)
// database.getKeywordsByUserId = async function(userId)
// database.getUsersByKeyword = async function(keyword)
// database.getAllUsers = async function()
// database.getAllKeywords = async function()
// Import credentials for Line chatbot
require("dotenv").config({ path: __dirname + "/../.env" });
const config = {
channelAccessToken: process.env.channelAccessToken,
channelSecret: process.env.channelSecret,
};
// Cron for Mamul Notification
const { checkMamul } = require("./checkMamul/checkMamul");
// Line chat bot client & event
const client = new line.Client(config);
let waitNewMamulList = []; // 매물 키워드 입력 기다리는 목록
......@@ -28,7 +54,7 @@ function handleEvent(event) {
var found = waitNewMamulList.indexOf(event.source.userId);
if (found == -1) {
waitNewMamulList.push(event.source.userId);
console.log(waitNewMamulList);
console.log(`waitNewMamulList Changed : ${waitNewMamulList}`);
return Promise.resolve(
client.replyMessage(event.replyToken, {
type: "text",
......@@ -54,7 +80,7 @@ function handleEvent(event) {
"1000000",
"https://dnvefa72aowie.cloudfront.net/origin/article/202205/94cdd237258671d5806a70f64ab2b3c7dcd790da0384b394ef5809fe10c08ced.webp?q=95&s=1440x1440&t=inside",
"https://www.daangn.com/articles/403755360",
"test설명"
"채굴X, 흡연X, 반려동물X 입니다.\n직거래 희망하며, 쿨거래시 네고 1만원 가능합니다."
),
})
);
......@@ -75,9 +101,13 @@ function handleEvent(event) {
waitNewMamulList.splice(found, 1);
console.log(waitNewMamulList[found]);
return Promise.resolve(
db.addKeyword(event.message.text, event.source.userId),
client.replyMessage(event.replyToken, {
type: "text",
text: "매물이 등록되었습니다!\n등록된 매물: " + event.message.text,
text: `매물이 등록되었습니다!\n등록된 매물: ${event.message.text}`,
}),
marketMultiSearch(event.message.text).then((res) => {
client.pushMessage(event.source.userId, setCarouselMessage(res));
})
);
}
......
......@@ -14,6 +14,7 @@
"dotenv": "^16.0.1",
"express": "^4.18.1",
"mysql2": "^2.3.3",
"node-schedule": "^2.1.0",
"nodemon": "^2.0.16",
"sequelize": "^6.20.0"
}
......@@ -508,6 +509,18 @@
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"node_modules/cron-parser": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-3.5.0.tgz",
"integrity": "sha512-wyVZtbRs6qDfFd8ap457w3XVntdvqcwBGxBoTvJQH9KGVKL/fB+h2k3C8AqiVxvUQKN1Ps/Ns46CNViOpVDhfQ==",
"dependencies": {
"is-nan": "^1.3.2",
"luxon": "^1.26.0"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/crypto-random-string": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
......@@ -548,6 +561,21 @@
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz",
"integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ=="
},
"node_modules/define-properties": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
"integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
"dependencies": {
"has-property-descriptors": "^1.0.0",
"object-keys": "^1.1.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
......@@ -911,6 +939,17 @@
"node": ">=4"
}
},
"node_modules/has-property-descriptors": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
"integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
"dependencies": {
"get-intrinsic": "^1.1.1"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
......@@ -1094,6 +1133,21 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-nan": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz",
"integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==",
"dependencies": {
"call-bind": "^1.0.0",
"define-properties": "^1.1.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-npm": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz",
......@@ -1178,6 +1232,11 @@
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
},
"node_modules/long-timeout": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz",
"integrity": "sha1-lyHXiLR+C8taJMLivuGg2lXatRQ="
},
"node_modules/lowercase-keys": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
......@@ -1197,6 +1256,14 @@
"node": ">=10"
}
},
"node_modules/luxon": {
"version": "1.28.0",
"resolved": "https://registry.npmjs.org/luxon/-/luxon-1.28.0.tgz",
"integrity": "sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ==",
"engines": {
"node": "*"
}
},
"node_modules/make-dir": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
......@@ -1380,6 +1447,19 @@
"node": ">= 0.6"
}
},
"node_modules/node-schedule": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-2.1.0.tgz",
"integrity": "sha512-nl4JTiZ7ZQDc97MmpTq9BQjYhq7gOtoh7SiPH069gBFBj0PzD8HI7zyFs6rzqL8Y5tTiEEYLxgtbx034YPrbyQ==",
"dependencies": {
"cron-parser": "^3.5.0",
"long-timeout": "0.1.1",
"sorted-array-functions": "^1.3.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/nodemon": {
"version": "2.0.16",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.16.tgz",
......@@ -1459,6 +1539,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/on-finished": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
......@@ -1927,6 +2015,11 @@
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
},
"node_modules/sorted-array-functions": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz",
"integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA=="
},
"node_modules/sqlstring": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
......@@ -2655,6 +2748,15 @@
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"cron-parser": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-3.5.0.tgz",
"integrity": "sha512-wyVZtbRs6qDfFd8ap457w3XVntdvqcwBGxBoTvJQH9KGVKL/fB+h2k3C8AqiVxvUQKN1Ps/Ns46CNViOpVDhfQ==",
"requires": {
"is-nan": "^1.3.2",
"luxon": "^1.26.0"
}
},
"crypto-random-string": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
......@@ -2686,6 +2788,15 @@
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz",
"integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ=="
},
"define-properties": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
"integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
"requires": {
"has-property-descriptors": "^1.0.0",
"object-keys": "^1.1.1"
}
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
......@@ -2952,6 +3063,14 @@
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
},
"has-property-descriptors": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
"integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
"requires": {
"get-intrinsic": "^1.1.1"
}
},
"has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
......@@ -3070,6 +3189,15 @@
"is-path-inside": "^3.0.2"
}
},
"is-nan": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz",
"integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==",
"requires": {
"call-bind": "^1.0.0",
"define-properties": "^1.1.3"
}
},
"is-npm": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz",
......@@ -3136,6 +3264,11 @@
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
},
"long-timeout": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz",
"integrity": "sha1-lyHXiLR+C8taJMLivuGg2lXatRQ="
},
"lowercase-keys": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
......@@ -3149,6 +3282,11 @@
"yallist": "^4.0.0"
}
},
"luxon": {
"version": "1.28.0",
"resolved": "https://registry.npmjs.org/luxon/-/luxon-1.28.0.tgz",
"integrity": "sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ=="
},
"make-dir": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
......@@ -3287,6 +3425,16 @@
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="
},
"node-schedule": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-2.1.0.tgz",
"integrity": "sha512-nl4JTiZ7ZQDc97MmpTq9BQjYhq7gOtoh7SiPH069gBFBj0PzD8HI7zyFs6rzqL8Y5tTiEEYLxgtbx034YPrbyQ==",
"requires": {
"cron-parser": "^3.5.0",
"long-timeout": "0.1.1",
"sorted-array-functions": "^1.3.0"
}
},
"nodemon": {
"version": "2.0.16",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.16.tgz",
......@@ -3342,6 +3490,11 @@
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
"integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g=="
},
"object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
},
"on-finished": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
......@@ -3675,6 +3828,11 @@
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
},
"sorted-array-functions": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz",
"integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA=="
},
"sqlstring": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
......
......@@ -20,6 +20,7 @@
"dotenv": "^16.0.1",
"express": "^4.18.1",
"mysql2": "^2.3.3",
"node-schedule": "^2.1.0",
"nodemon": "^2.0.16",
"sequelize": "^6.20.0"
}
......